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:
brykt@google.com 2012-11-27 13:44:07 +00:00
parent 52ec985d82
commit 4de3dfe613
5 changed files with 332 additions and 0 deletions

View 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);
}

View 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;
}
}

View 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_

View 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);
}
}
}

View File

@ -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
}