Tool for editing of yuv-files. Specify a path to the clip that should be edited, the height and width of the clip, one set of frames that should be removed from the clip, and a path to where the result should be written. There is a executable created that make use of the library where the functionality is implemented. There is also a unittest added for the library.
BUG= Review URL: https://webrtc-codereview.appspot.com/929021 git-svn-id: http://webrtc.googlecode.com/svn/trunk@3174 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
52ec985d82
commit
4de3dfe613
86
webrtc/tools/frame_cutter/frame_cutter.cc
Normal file
86
webrtc/tools/frame_cutter/frame_cutter.cc
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/tools/frame_cutter/frame_cutter_lib.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "webrtc/tools/simple_command_line_parser.h"
|
||||
|
||||
// A command-line tool to edit a YUV-video (I420 sub-sampled).
|
||||
int main(int argc, char** argv) {
|
||||
std::string program_name = argv[0];
|
||||
std::string usage = "Deletes a series of frames in a yuv file. "
|
||||
"Only I420 is supported!\n"
|
||||
"Example usage:\n" + program_name +
|
||||
" --in_path=input.yuv --width=320 --height=240 --f=60 --l=120 "
|
||||
"--out_path=edited_clip.yuv\n"
|
||||
"Command line flags:\n"
|
||||
" --in_path(string): Path and filename to the input file\n"
|
||||
" -- width(int): Width in pixels of the frames in the input file."
|
||||
" Default: -1\n"
|
||||
" -- height(int): Height in pixels of the frames in the input file."
|
||||
" Default: -1\n"
|
||||
" -- f(int): First frame to cut.\n"
|
||||
" Default: -1\n"
|
||||
" -- l(int): Last frame to cut.\n"
|
||||
" Default: -1\n"
|
||||
" -- out_path(string): The output file to which frames are written."
|
||||
" Default: output.yuv\n";
|
||||
|
||||
webrtc::test::CommandLineParser parser;
|
||||
|
||||
// Init the parser and set the usage message
|
||||
parser.Init(argc, argv);
|
||||
parser.SetUsageMessage(usage);
|
||||
|
||||
parser.SetFlag("in_path", "-1");
|
||||
parser.SetFlag("width", "-1");
|
||||
parser.SetFlag("height", "-1");
|
||||
parser.SetFlag("f", "-1");
|
||||
parser.SetFlag("l", "-1");
|
||||
parser.SetFlag("out_path", "edited_output.yuv");
|
||||
parser.SetFlag("help", "false");
|
||||
|
||||
parser.ProcessFlags();
|
||||
if (parser.GetFlag("help") == "true") {
|
||||
parser.PrintUsageMessage();
|
||||
}
|
||||
parser.PrintEnteredFlags();
|
||||
|
||||
const char* in_path = parser.GetFlag("in_path").c_str();
|
||||
int width = strtol((parser.GetFlag("width")).c_str(), NULL, 10);
|
||||
int height = strtol((parser.GetFlag("height")).c_str(), NULL, 10);
|
||||
int first_frame_to_cut = strtol((parser.GetFlag("f")).c_str(), NULL, 10);
|
||||
int last_frame_to_cut = strtol((parser.GetFlag("l")).c_str(), NULL, 10);
|
||||
|
||||
const char* out_path = parser.GetFlag("out_path").c_str();
|
||||
|
||||
if (!strcmp(in_path, "-1")) {
|
||||
fprintf(stderr, "You must specify a file to edit\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (first_frame_to_cut <= 0 || last_frame_to_cut <= 0) {
|
||||
fprintf(stderr, "Error: You must specify which frames to cut!\n");
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (width <= 0 || height <= 0) {
|
||||
fprintf(stderr, "Error: width or height cannot be <= 0!\n");
|
||||
return -3;
|
||||
}
|
||||
|
||||
return webrtc::FrameCutter(in_path, width, height, first_frame_to_cut,
|
||||
last_frame_to_cut, out_path);
|
||||
}
|
||||
|
74
webrtc/tools/frame_cutter/frame_cutter_lib.cc
Normal file
74
webrtc/tools/frame_cutter/frame_cutter_lib.cc
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
|
||||
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
using std::string;
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
int FrameCutter(const string& in_path, int width, int height,
|
||||
int first_frame_to_cut, int last_frame_to_cut,
|
||||
const string& out_path) {
|
||||
if (last_frame_to_cut < first_frame_to_cut) {
|
||||
fprintf(stderr, "The set of frames to cut is empty! (l < f)\n");
|
||||
return -10;
|
||||
}
|
||||
|
||||
FILE* in_fid = fopen(in_path.c_str() , "r");
|
||||
if (!in_fid) {
|
||||
fprintf(stderr, "Could not read input file: %s.\n", in_path.c_str());
|
||||
return -11;
|
||||
}
|
||||
|
||||
// Frame size of I420.
|
||||
int frame_length = CalcBufferSize(kI420, width, height);
|
||||
|
||||
webrtc::scoped_array<uint8_t> temp_buffer(new uint8_t[frame_length]);
|
||||
|
||||
FILE* out_fid = fopen(out_path.c_str(), "w");
|
||||
|
||||
if (!out_fid) {
|
||||
fprintf(stderr, "Could not open output file: %s.\n", out_path.c_str());
|
||||
return -12;
|
||||
}
|
||||
|
||||
int num_frames_read = 0;
|
||||
int num_bytes_read;
|
||||
|
||||
while ((num_bytes_read = fread(temp_buffer.get(), 1, frame_length, in_fid))
|
||||
== frame_length) {
|
||||
if ((num_frames_read < first_frame_to_cut) ||
|
||||
(last_frame_to_cut < num_frames_read)) {
|
||||
fwrite(temp_buffer.get(), 1, frame_length, out_fid);
|
||||
num_frames_read++;
|
||||
} else {
|
||||
num_frames_read++;
|
||||
}
|
||||
}
|
||||
if (num_bytes_read > 0 && num_bytes_read < frame_length) {
|
||||
printf("Frame to small! Last frame truncated.\n");
|
||||
}
|
||||
|
||||
fclose(in_fid);
|
||||
fclose(out_fid);
|
||||
|
||||
printf("Done editing!\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
28
webrtc/tools/frame_cutter/frame_cutter_lib.h
Normal file
28
webrtc/tools/frame_cutter/frame_cutter_lib.h
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_TOOLS_FRAME_CUTTER_FRAME_CUTTER_H_
|
||||
#define WEBRTC_TOOLS_FRAME_CUTTER_FRAME_CUTTER_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Frame numbering starts at 1. The set of frames to be cut includes the frame
|
||||
// with the number: first_frame_to_cut and last_frame_to_cut. I.e if one clip
|
||||
// has 10 frames (1 to 10), and you specify first_frame_to_cut = 4 and
|
||||
// last_frame_to_cut = 7, then you will get a clip that contains frame 1, 2, 3,
|
||||
// 8, 9 and 10.
|
||||
int FrameCutter(const std::string& in_path, int width, int height,
|
||||
int first_frame_to_cut, int last_frame_to_cut,
|
||||
const std::string& out_path);
|
||||
}
|
||||
|
||||
#endif // WEBRTC_TOOLS_FRAME_CUTTER_FRAME_CUTTER_H_
|
104
webrtc/tools/frame_cutter/frame_cutter_unittest.cc
Normal file
104
webrtc/tools/frame_cutter/frame_cutter_unittest.cc
Normal file
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
|
||||
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
||||
#include "webrtc/test/testsupport/fileutils.h"
|
||||
#include "webrtc/tools/frame_cutter/frame_cutter_lib.h"
|
||||
|
||||
using webrtc::CalcBufferSize;
|
||||
using webrtc::FrameCutter;
|
||||
using webrtc::kI420;
|
||||
using webrtc::scoped_array;
|
||||
using webrtc::test::OutputPath;
|
||||
using webrtc::test::ResourcePath;
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
const int width = 352;
|
||||
const int height = 288;
|
||||
|
||||
const std::string ref_video = ResourcePath("foreman_cif", "yuv");
|
||||
const std::string test_video = OutputPath() + "testvideo.yuv";
|
||||
|
||||
int num_bytes_read;
|
||||
|
||||
TEST(FrameCutterUnittest, ValidInPath) {
|
||||
const int first_frame_to_cut = 160;
|
||||
const int last_frame_to_cut = 240;
|
||||
|
||||
int result = FrameCutter(ref_video, width, height, first_frame_to_cut,
|
||||
last_frame_to_cut, test_video);
|
||||
EXPECT_EQ(0, result);
|
||||
|
||||
FILE* ref_video_fid = fopen(ref_video.c_str(), "r");
|
||||
ASSERT_TRUE(ref_video_fid != NULL);
|
||||
FILE* test_video_fid = fopen(test_video.c_str(), "r");
|
||||
ASSERT_TRUE(test_video_fid != NULL);
|
||||
|
||||
const int frame_size =CalcBufferSize(kI420, width, height);
|
||||
|
||||
scoped_array<int> ref_buffer(new int[frame_size]);
|
||||
scoped_array<int> test_buffer(new int[frame_size]);
|
||||
|
||||
for (int i = 0; i < first_frame_to_cut; ++i) {
|
||||
num_bytes_read = fread(ref_buffer.get(), frame_size, 1, ref_video_fid);
|
||||
EXPECT_EQ(frame_size, num_bytes_read);
|
||||
|
||||
num_bytes_read = fread(test_buffer.get(), frame_size, 1, test_video_fid);
|
||||
EXPECT_EQ(frame_size, num_bytes_read);
|
||||
|
||||
EXPECT_EQ(0, memcmp(ref_buffer.get(), test_buffer.get(), frame_size));
|
||||
}
|
||||
// Do not compare the frames that have been cut.
|
||||
for (int i = first_frame_to_cut; i <= last_frame_to_cut; ++i) {
|
||||
num_bytes_read = fread(&ref_buffer, frame_size, 1, ref_video_fid);
|
||||
EXPECT_EQ(frame_size, num_bytes_read);
|
||||
}
|
||||
|
||||
while (!feof(test_video_fid)) {
|
||||
num_bytes_read = fread(&ref_buffer, frame_size, 1, ref_video_fid);
|
||||
EXPECT_EQ(frame_size, num_bytes_read);
|
||||
num_bytes_read = fread(&test_buffer, frame_size, 1, test_video_fid);
|
||||
EXPECT_EQ(frame_size, num_bytes_read);
|
||||
EXPECT_EQ(0, memcmp(ref_buffer.get(), test_buffer.get(), frame_size));
|
||||
}
|
||||
bool are_both_files_at_the_end =
|
||||
(feof(test_video_fid) && feof(test_video_fid));
|
||||
EXPECT_TRUE(are_both_files_at_the_end);
|
||||
}
|
||||
|
||||
TEST(FrameCutterUnittest, EmptySetToCut) {
|
||||
int first_frame_to_cut = 2;
|
||||
int last_frame_to_cut = 1;
|
||||
|
||||
int result = FrameCutter(ref_video, width, height, first_frame_to_cut,
|
||||
last_frame_to_cut, test_video);
|
||||
EXPECT_EQ(-10, result);
|
||||
}
|
||||
|
||||
TEST(FrameCutterUnittest, InValidInPath) {
|
||||
const std::string ref_video = "PATH/THAT/DOES/NOT/EXIST";
|
||||
|
||||
int first_frame_to_cut = 30;
|
||||
int last_frame_to_cut = 120;
|
||||
|
||||
int result = FrameCutter(ref_video, width, height, first_frame_to_cut,
|
||||
last_frame_to_cut, test_video);
|
||||
EXPECT_EQ(-11, result);
|
||||
}
|
||||
}
|
||||
}
|
@ -84,5 +84,45 @@
|
||||
'converter/rgba_to_i420_converter.cc',
|
||||
],
|
||||
}, # rgba_to_i420_converter
|
||||
{
|
||||
'target_name': 'frame_cutter_lib',
|
||||
'type': '<(library)',
|
||||
'dependencies': [
|
||||
'<(DEPTH)/webrtc/common_video/common_video.gyp:common_video',
|
||||
],
|
||||
'sources': [
|
||||
'frame_cutter/frame_cutter_lib.cc',
|
||||
'frame_cutter/frame_cutter_lib.h',
|
||||
],
|
||||
}, # frame_cutter_lib
|
||||
{
|
||||
'target_name': 'frame_cutter',
|
||||
'type': 'executable',
|
||||
'dependencies': [
|
||||
'command_line_parser',
|
||||
'frame_cutter_lib',
|
||||
],
|
||||
'sources': [
|
||||
'frame_cutter/frame_cutter.cc',
|
||||
],
|
||||
}, # frame_cutter
|
||||
],
|
||||
'conditions': [
|
||||
['include_tests==1', {
|
||||
'targets' : [
|
||||
{
|
||||
'target_name': 'tools_unittests',
|
||||
'type': 'executable',
|
||||
'dependencies': [
|
||||
'frame_cutter_lib',
|
||||
'<(webrtc_root)/test/test.gyp:test_support_main',
|
||||
'<(DEPTH)/testing/gtest.gyp:gtest',
|
||||
],
|
||||
'sources': [
|
||||
'frame_cutter/frame_cutter_unittest.cc',
|
||||
],
|
||||
}, # tools_unittests
|
||||
], # targets
|
||||
}], # include_tests
|
||||
], # conditions
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user