Added possibility to repeat frames. Also added unittest for that feature.
BUG= Review URL: https://webrtc-codereview.appspot.com/994005 git-svn-id: http://webrtc.googlecode.com/svn/trunk@3321 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
d73527ccab
commit
f556890844
@ -1,32 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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,
|
|
||||||
// last_frame_to_cut = 7 and interval = 1, then you will get a clip that
|
|
||||||
// contains frame 1, 2, 3, 8, 9 and 10.
|
|
||||||
// Interval specifies with what interval frames should be cut. I.e if one clip
|
|
||||||
// has 10 frames (1 to 10), and you specify first_frame_to_cut = 1,
|
|
||||||
// last_frame_to_cut = 10 and interval = 3, then you will get a clip that
|
|
||||||
// contains frame 1, 2, 4, 5, 7, 8, 10.
|
|
||||||
int CutFrames(const std::string& in_path, int width, int height,
|
|
||||||
int first_frame_to_cut, int interval, int last_frame_to_cut,
|
|
||||||
const std::string& out_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // WEBRTC_TOOLS_FRAME_CUTTER_FRAME_CUTTER_H_
|
|
@ -1,153 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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::CutFrames;
|
|
||||||
using webrtc::kI420;
|
|
||||||
using webrtc::scoped_array;
|
|
||||||
using webrtc::test::OutputPath;
|
|
||||||
using webrtc::test::ResourcePath;
|
|
||||||
|
|
||||||
namespace webrtc {
|
|
||||||
namespace test {
|
|
||||||
|
|
||||||
const int kWidth = 352;
|
|
||||||
const int kHeight = 288;
|
|
||||||
|
|
||||||
const std::string kRefVideo = ResourcePath("foreman_cif", "yuv");
|
|
||||||
const std::string kTestVideo = OutputPath() + "testvideo.yuv";
|
|
||||||
|
|
||||||
int num_bytes_read;
|
|
||||||
|
|
||||||
TEST(CutFramesUnittest, ValidInPath) {
|
|
||||||
const int kFirstFrameToCut = 160;
|
|
||||||
const int kInterval = 1;
|
|
||||||
const int kLastFrameToCut = 240;
|
|
||||||
|
|
||||||
int result = CutFrames(kRefVideo, kWidth, kHeight, kFirstFrameToCut,
|
|
||||||
kInterval, kLastFrameToCut, kTestVideo);
|
|
||||||
EXPECT_EQ(0, result);
|
|
||||||
|
|
||||||
FILE* ref_video_fid = fopen(kRefVideo.c_str(), "rb");
|
|
||||||
ASSERT_TRUE(ref_video_fid != NULL);
|
|
||||||
FILE* test_video_fid = fopen(kTestVideo.c_str(), "rb");
|
|
||||||
ASSERT_TRUE(test_video_fid != NULL);
|
|
||||||
|
|
||||||
const int kFrameSize = CalcBufferSize(kI420, kWidth, kHeight);
|
|
||||||
|
|
||||||
scoped_array<int> ref_buffer(new int[kFrameSize]);
|
|
||||||
scoped_array<int> test_buffer(new int[kFrameSize]);
|
|
||||||
|
|
||||||
for (int i = 1; i < kFirstFrameToCut; ++i) {
|
|
||||||
num_bytes_read = fread(ref_buffer.get(), 1, kFrameSize, ref_video_fid);
|
|
||||||
EXPECT_EQ(kFrameSize, num_bytes_read);
|
|
||||||
|
|
||||||
num_bytes_read = fread(test_buffer.get(), 1, kFrameSize, test_video_fid);
|
|
||||||
EXPECT_EQ(kFrameSize, num_bytes_read);
|
|
||||||
|
|
||||||
EXPECT_EQ(0, memcmp(ref_buffer.get(), test_buffer.get(), kFrameSize));
|
|
||||||
}
|
|
||||||
// Do not compare the frames that have been cut.
|
|
||||||
for (int i = kFirstFrameToCut; i <= kLastFrameToCut; ++i) {
|
|
||||||
num_bytes_read = fread(ref_buffer.get(), 1, kFrameSize, ref_video_fid);
|
|
||||||
EXPECT_EQ(kFrameSize, num_bytes_read);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!feof(test_video_fid) && !feof(ref_video_fid)) {
|
|
||||||
num_bytes_read = fread(ref_buffer.get(), 1, kFrameSize, ref_video_fid);
|
|
||||||
if (!feof(ref_video_fid)) {
|
|
||||||
EXPECT_EQ(kFrameSize, num_bytes_read);
|
|
||||||
}
|
|
||||||
num_bytes_read = fread(test_buffer.get(), 1, kFrameSize, test_video_fid);
|
|
||||||
if (!feof(test_video_fid)) {
|
|
||||||
EXPECT_EQ(kFrameSize, num_bytes_read);
|
|
||||||
}
|
|
||||||
if (!feof(test_video_fid) && !feof(test_video_fid)) {
|
|
||||||
EXPECT_EQ(0, memcmp(ref_buffer.get(), test_buffer.get(), kFrameSize));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fclose(ref_video_fid);
|
|
||||||
fclose(test_video_fid);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(CutFramesUnittest, EmptySetToCut) {
|
|
||||||
const int kFirstFrameToCut = 2;
|
|
||||||
const int kInterval = 1;
|
|
||||||
const int kLastFrameToCut = 1;
|
|
||||||
|
|
||||||
int result = CutFrames(kRefVideo, kWidth, kHeight, kFirstFrameToCut,
|
|
||||||
kInterval, kLastFrameToCut, kTestVideo);
|
|
||||||
EXPECT_EQ(-10, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(CutFramesUnittest, InValidInPath) {
|
|
||||||
const std::string kRefVideo = "PATH/THAT/DOES/NOT/EXIST";
|
|
||||||
|
|
||||||
const int kFirstFrameToCut = 30;
|
|
||||||
const int kInterval = 1;
|
|
||||||
const int kLastFrameToCut = 120;
|
|
||||||
|
|
||||||
int result = CutFrames(kRefVideo, kWidth, kHeight, kFirstFrameToCut,
|
|
||||||
kInterval, kLastFrameToCut, kTestVideo);
|
|
||||||
EXPECT_EQ(-11, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(CutFramesUnitTest, DeletingEverySecondFrame) {
|
|
||||||
const int kFirstFrameToCut = 1;
|
|
||||||
const int kInterval = 2;
|
|
||||||
const int kLastFrameToCut = 10000;
|
|
||||||
// Set kLastFrameToCut to a large value so that all frame are processed.
|
|
||||||
int result = CutFrames(kRefVideo, kWidth, kHeight, kFirstFrameToCut,
|
|
||||||
kInterval, kLastFrameToCut, kTestVideo);
|
|
||||||
EXPECT_EQ(0, result);
|
|
||||||
|
|
||||||
FILE* original_fid = fopen(kRefVideo.c_str(), "rb");
|
|
||||||
ASSERT_TRUE(original_fid != NULL);
|
|
||||||
FILE* edited_fid = fopen(kTestVideo.c_str(), "rb");
|
|
||||||
ASSERT_TRUE(edited_fid != NULL);
|
|
||||||
|
|
||||||
const int kFrameSize = CalcBufferSize(kI420, kWidth, kHeight);
|
|
||||||
|
|
||||||
scoped_array<int> original_buffer(new int[kFrameSize]);
|
|
||||||
scoped_array<int> edited_buffer(new int[kFrameSize]);
|
|
||||||
|
|
||||||
int num_frames_read = 0;
|
|
||||||
|
|
||||||
while (!feof(original_fid) && !feof(edited_fid)) {
|
|
||||||
num_bytes_read =
|
|
||||||
fread(original_buffer.get(), 1, kFrameSize, original_fid);
|
|
||||||
if (!feof(original_fid)) {
|
|
||||||
EXPECT_EQ(kFrameSize, num_bytes_read);
|
|
||||||
num_frames_read++;
|
|
||||||
}
|
|
||||||
if (num_frames_read % kInterval != 0) {
|
|
||||||
num_bytes_read = fread(edited_buffer.get(), 1, kFrameSize, edited_fid);
|
|
||||||
if (!feof(edited_fid)) {
|
|
||||||
EXPECT_EQ(kFrameSize, num_bytes_read);
|
|
||||||
}
|
|
||||||
if (!feof(original_fid) && !feof(edited_fid)) {
|
|
||||||
EXPECT_EQ(0, memcmp(original_buffer.get(),
|
|
||||||
edited_buffer.get(), kFrameSize));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -8,7 +8,7 @@
|
|||||||
* be found in the AUTHORS file in the root of the source tree.
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "webrtc/tools/frame_cutter/frame_cutter_lib.h"
|
#include "webrtc/tools/frame_editing/frame_editing_lib.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -30,20 +30,34 @@ int main(int argc, char** argv) {
|
|||||||
" Default: -1\n"
|
" Default: -1\n"
|
||||||
"--height(int): Height in pixels of the frames in the input file."
|
"--height(int): Height in pixels of the frames in the input file."
|
||||||
" Default: -1\n"
|
" Default: -1\n"
|
||||||
"--f(int): First frame to cut.\n"
|
"--f(int): First frame to process. Default: -1\n"
|
||||||
|
"--l(int): Last frame to process. Default: -1\n"
|
||||||
|
"Frame numbering starts at 1. The set of frames to be processed includes "
|
||||||
|
"the frame with the number <f> and <l>.\n"
|
||||||
|
"--interval(int): Interval specifies with what ratio the number of frames "
|
||||||
|
"should be increased or decreased with.\n"
|
||||||
|
"If you set <interval> to a positive number, frames between <f> and <l> "
|
||||||
|
"will be inserted <interval> times."
|
||||||
|
" If you set <interval> to a negative number then the amount of frames "
|
||||||
|
"between <f> and <l> will be decreased with a ratio of abs(interval)."
|
||||||
|
" Set interval=-1 if every frame between <f> and <l> should be "
|
||||||
|
"deleted. Set interval=-2 if every second frame should be deleted, and so "
|
||||||
|
"on. Frame numbering between <f> and <l> starts with 1 and frames with"
|
||||||
|
" number n where (n - 1) % interval == 0 will be kept.\n"
|
||||||
|
"Example 1:\n"
|
||||||
|
"If one clip has 10 frames (1 to 10) and you specify <f>=4, <l>=7 and "
|
||||||
|
"interval=2, then you will get a clip that contains frame "
|
||||||
|
"1, 2, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9 and 10.\n"
|
||||||
|
"Example 2:\n"
|
||||||
|
"If you specify f=4, l=7 and interval=-1, then you will get a clip that"
|
||||||
|
" contains frame 1, 2, 3, 8, 9 and 10.\n"
|
||||||
|
"Example 3:\n"
|
||||||
|
"If one clip has 10 frames (1 to 10), and you specify f=1, l=10 and "
|
||||||
|
" interval=-4, then you will get a clip that contains frame "
|
||||||
|
"1, 5 and 9.\n"
|
||||||
|
"No interpolation is done when up-sampling."
|
||||||
" Default: -1\n"
|
" Default: -1\n"
|
||||||
"--interval(int): Set to 1 if every frame between f and l should be "
|
"--out_path(string): The output file to which frames are written."
|
||||||
"deleted. Set it to 2 if every second frame should be deleted, "
|
|
||||||
"and so on...Frame numbering between the limits start with 1 and frames "
|
|
||||||
"read between and including the limits with number n where "
|
|
||||||
"n % interval != 0 will be kept.\n"
|
|
||||||
"Example: If the clip have frames with the numbers 1 to 10, and you set f=2"
|
|
||||||
" , l=7 and interval=2, then the output clip will contain the frames with "
|
|
||||||
" number 1, 2, 4, 6, 8, 9, 10."
|
|
||||||
" Default: 1\n"
|
|
||||||
"--l(int): Last frame to cut."
|
|
||||||
" Default: -1\n"
|
|
||||||
" --out_path(string): The output file to which frames are written."
|
|
||||||
" Default: output.yuv\n";
|
" Default: output.yuv\n";
|
||||||
|
|
||||||
webrtc::test::CommandLineParser parser;
|
webrtc::test::CommandLineParser parser;
|
||||||
@ -51,12 +65,11 @@ int main(int argc, char** argv) {
|
|||||||
// Init the parser and set the usage message
|
// Init the parser and set the usage message
|
||||||
parser.Init(argc, argv);
|
parser.Init(argc, argv);
|
||||||
parser.SetUsageMessage(usage);
|
parser.SetUsageMessage(usage);
|
||||||
|
|
||||||
parser.SetFlag("in_path", "-1");
|
parser.SetFlag("in_path", "-1");
|
||||||
parser.SetFlag("width", "-1");
|
parser.SetFlag("width", "-1");
|
||||||
parser.SetFlag("height", "-1");
|
parser.SetFlag("height", "-1");
|
||||||
parser.SetFlag("f", "-1");
|
parser.SetFlag("f", "-1");
|
||||||
parser.SetFlag("interval", "1");
|
parser.SetFlag("interval", "-1");
|
||||||
parser.SetFlag("l", "-1");
|
parser.SetFlag("l", "-1");
|
||||||
parser.SetFlag("out_path", "edited_output.yuv");
|
parser.SetFlag("out_path", "edited_output.yuv");
|
||||||
parser.SetFlag("help", "false");
|
parser.SetFlag("help", "false");
|
||||||
@ -90,8 +103,7 @@ int main(int argc, char** argv) {
|
|||||||
fprintf(stderr, "Error: width or height cannot be <= 0!\n");
|
fprintf(stderr, "Error: width or height cannot be <= 0!\n");
|
||||||
return -3;
|
return -3;
|
||||||
}
|
}
|
||||||
|
return webrtc::EditFrames(in_path, width, height, first_frame_to_cut,
|
||||||
return webrtc::CutFrames(in_path, width, height, first_frame_to_cut,
|
interval, last_frame_to_cut, out_path);
|
||||||
interval, last_frame_to_cut, out_path);
|
|
||||||
}
|
}
|
||||||
|
|
@ -21,11 +21,10 @@ using std::string;
|
|||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
int CutFrames(const string& in_path, int width, int height,
|
int EditFrames(const string& in_path, int width, int height,
|
||||||
int first_frame_to_cut, int interval, int last_frame_to_cut,
|
int first_frame_to_process, int interval,
|
||||||
const string& out_path) {
|
int last_frame_to_process, const string& out_path) {
|
||||||
|
if (last_frame_to_process < first_frame_to_process) {
|
||||||
if (last_frame_to_cut < first_frame_to_cut) {
|
|
||||||
fprintf(stderr, "The set of frames to cut is empty! (l < f)\n");
|
fprintf(stderr, "The set of frames to cut is empty! (l < f)\n");
|
||||||
return -10;
|
return -10;
|
||||||
}
|
}
|
||||||
@ -56,25 +55,34 @@ int CutFrames(const string& in_path, int width, int height,
|
|||||||
while ((num_bytes_read = fread(temp_buffer.get(), 1, frame_length, in_fid))
|
while ((num_bytes_read = fread(temp_buffer.get(), 1, frame_length, in_fid))
|
||||||
== frame_length) {
|
== frame_length) {
|
||||||
num_frames_read++;
|
num_frames_read++;
|
||||||
if ((num_frames_read < first_frame_to_cut) ||
|
if ((num_frames_read < first_frame_to_process) ||
|
||||||
(last_frame_to_cut < num_frames_read)) {
|
(last_frame_to_process < num_frames_read)) {
|
||||||
fwrite(temp_buffer.get(), 1, frame_length, out_fid);
|
fwrite(temp_buffer.get(), 1, frame_length, out_fid);
|
||||||
} else {
|
} else {
|
||||||
num_frames_read_between++;
|
num_frames_read_between++;
|
||||||
if (num_frames_read_between % interval != 0) {
|
if (interval <= 0) {
|
||||||
fwrite(temp_buffer.get(), 1, frame_length, out_fid);
|
if (interval == -1) {
|
||||||
|
// Remove all frames.
|
||||||
|
} else {
|
||||||
|
if (((num_frames_read_between - 1) % interval) == 0) {
|
||||||
|
// Keep only every |interval| frame.
|
||||||
|
fwrite(temp_buffer.get(), 1, frame_length, out_fid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (interval > 0) {
|
||||||
|
for (int i = 1; i <= interval; ++i) {
|
||||||
|
fwrite(temp_buffer.get(), 1, frame_length, out_fid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (num_bytes_read > 0 && num_bytes_read < frame_length) {
|
if (num_bytes_read > 0 && num_bytes_read < frame_length) {
|
||||||
printf("Frame to small! Last frame truncated.\n");
|
printf("Frame to small! Last frame truncated.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(in_fid);
|
fclose(in_fid);
|
||||||
fclose(out_fid);
|
fclose(out_fid);
|
||||||
|
|
||||||
printf("Done editing!\n");
|
printf("Done editing!\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
} // namespace webrtc
|
||||||
|
|
39
webrtc/tools/frame_editing/frame_editing_lib.h
Normal file
39
webrtc/tools/frame_editing/frame_editing_lib.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* 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_EDITING_FRAME_EDITING_H_
|
||||||
|
#define WEBRTC_TOOLS_FRAME_EDITING_FRAME_EDITING_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
|
||||||
|
// Frame numbering starts at 1. The set of frames to be processed includes the
|
||||||
|
// frame with the number: first_frame_to_process and last_frame_to_process.
|
||||||
|
// Interval specifies with what interval frames should be cut or kept.
|
||||||
|
// Example 1:
|
||||||
|
// If one clip has 10 frames (1 to 10), and you specify
|
||||||
|
// first_frame_to_process = 4, last_frame_to_process = 7 and interval = -1,
|
||||||
|
// then you will get a clip that contains frame 1, 2, 3, 8, 9 and 10.
|
||||||
|
// Example 2:
|
||||||
|
// I you specify first_frame_to_process = 1, last_frame_to_process = 10 and
|
||||||
|
// interval = -4, then you will get a clip that contains frame 1, 5, 9.
|
||||||
|
// Example 3:
|
||||||
|
// If you specify first_frame_to_process = 4, last_frame_to_process = 7 and
|
||||||
|
// interval = 2, then you will get a clip that contains frame
|
||||||
|
// 1, 2, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9 and 10.
|
||||||
|
// No interpolation is done when up-sampling.
|
||||||
|
|
||||||
|
int EditFrames(const std::string& in_path, int width, int height,
|
||||||
|
int first_frame_to_process, int interval,
|
||||||
|
int last_frame_to_process, const std::string& out_path);
|
||||||
|
} // namespace webrtc
|
||||||
|
|
||||||
|
#endif // WEBRTC_TOOLS_FRAME_EDITING_FRAME_EDITING_H_
|
200
webrtc/tools/frame_editing/frame_editing_unittest.cc
Normal file
200
webrtc/tools/frame_editing/frame_editing_unittest.cc
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
/*
|
||||||
|
* 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_editing/frame_editing_lib.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
namespace test {
|
||||||
|
|
||||||
|
const int kWidth = 352;
|
||||||
|
const int kHeight = 288;
|
||||||
|
const int kFrameSize = CalcBufferSize(kI420, kWidth, kHeight);
|
||||||
|
const std::string kRefVideo = ResourcePath("foreman_cif", "yuv");
|
||||||
|
const std::string kTestVideo = OutputPath() + "testvideo.yuv";
|
||||||
|
|
||||||
|
class FrameEditingTest : public ::testing::Test {
|
||||||
|
protected:
|
||||||
|
virtual void SetUp() {
|
||||||
|
original_fid_ = fopen(kRefVideo.c_str(), "rb");
|
||||||
|
ASSERT_TRUE(original_fid_ != NULL);
|
||||||
|
edited_fid_ = fopen(kTestVideo.c_str(), "rb");
|
||||||
|
ASSERT_TRUE(edited_fid_ != NULL);
|
||||||
|
original_buffer_.reset(new int[kFrameSize]);
|
||||||
|
edited_buffer_.reset(new int[kFrameSize]);
|
||||||
|
num_frames_read_ = 0;
|
||||||
|
}
|
||||||
|
virtual void TearDown() {
|
||||||
|
fclose(original_fid_);
|
||||||
|
fclose(edited_fid_);
|
||||||
|
}
|
||||||
|
// Compares the frames in both streams to the end of one of the streams.
|
||||||
|
void CompareToTheEnd(FILE* test_video_fid, FILE* ref_video_fid,
|
||||||
|
scoped_array<int>* ref_buffer,
|
||||||
|
scoped_array<int>* test_buffer) {
|
||||||
|
while (!feof(test_video_fid) && !feof(ref_video_fid)) {
|
||||||
|
num_bytes_read_ = fread(ref_buffer->get(), 1, kFrameSize, ref_video_fid);
|
||||||
|
if (!feof(ref_video_fid)) {
|
||||||
|
EXPECT_EQ(kFrameSize, num_bytes_read_);
|
||||||
|
}
|
||||||
|
num_bytes_read_ = fread(test_buffer->get(), 1, kFrameSize,
|
||||||
|
test_video_fid);
|
||||||
|
if (!feof(test_video_fid)) {
|
||||||
|
EXPECT_EQ(kFrameSize, num_bytes_read_);
|
||||||
|
}
|
||||||
|
if (!feof(test_video_fid) && !feof(test_video_fid)) {
|
||||||
|
EXPECT_EQ(0, memcmp(ref_buffer->get(), test_buffer->get(),
|
||||||
|
kFrameSize));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// There should not be anything left in either stream.
|
||||||
|
EXPECT_EQ(!feof(test_video_fid), !feof(ref_video_fid));
|
||||||
|
}
|
||||||
|
FILE* original_fid_;
|
||||||
|
FILE* edited_fid_;
|
||||||
|
int kFrameSize_;
|
||||||
|
int num_bytes_read_;
|
||||||
|
scoped_array<int> original_buffer_;
|
||||||
|
scoped_array<int> edited_buffer_;
|
||||||
|
int num_frames_read_;
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(FrameEditingTest, ValidInPath) {
|
||||||
|
const int kFirstFrameToProcess = 160;
|
||||||
|
const int kInterval = -1;
|
||||||
|
const int kLastFrameToProcess = 240;
|
||||||
|
|
||||||
|
int result = EditFrames(kRefVideo, kWidth, kHeight, kFirstFrameToProcess,
|
||||||
|
kInterval, kLastFrameToProcess, kTestVideo);
|
||||||
|
EXPECT_EQ(0, result);
|
||||||
|
|
||||||
|
for (int i = 1; i < kFirstFrameToProcess; ++i) {
|
||||||
|
num_bytes_read_ = fread(original_buffer_.get(), 1, kFrameSize,
|
||||||
|
original_fid_);
|
||||||
|
EXPECT_EQ(kFrameSize, num_bytes_read_);
|
||||||
|
|
||||||
|
num_bytes_read_ = fread(edited_buffer_.get(), 1, kFrameSize, edited_fid_);
|
||||||
|
EXPECT_EQ(kFrameSize, num_bytes_read_);
|
||||||
|
|
||||||
|
EXPECT_EQ(0, memcmp(original_buffer_.get(), edited_buffer_.get(),
|
||||||
|
kFrameSize));
|
||||||
|
}
|
||||||
|
// Do not compare the frames that have been cut.
|
||||||
|
for (int i = kFirstFrameToProcess; i <= kLastFrameToProcess; ++i) {
|
||||||
|
num_bytes_read_ = fread(original_buffer_.get(), 1, kFrameSize,
|
||||||
|
original_fid_);
|
||||||
|
EXPECT_EQ(kFrameSize, num_bytes_read_);
|
||||||
|
}
|
||||||
|
CompareToTheEnd(edited_fid_, original_fid_, &original_buffer_,
|
||||||
|
&edited_buffer_);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(FrameEditingTest, EmptySetToCut) {
|
||||||
|
const int kFirstFrameToProcess = 2;
|
||||||
|
const int kInterval = -1;
|
||||||
|
const int kLastFrameToProcess = 1;
|
||||||
|
|
||||||
|
int result = EditFrames(kRefVideo, kWidth, kHeight, kFirstFrameToProcess,
|
||||||
|
kInterval, kLastFrameToProcess, kTestVideo);
|
||||||
|
EXPECT_EQ(-10, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(FrameEditingTest, InValidInPath) {
|
||||||
|
const std::string kRefVideo = "PATH/THAT/DOES/NOT/EXIST";
|
||||||
|
|
||||||
|
const int kFirstFrameToProcess = 30;
|
||||||
|
const int kInterval = 1;
|
||||||
|
const int kLastFrameToProcess = 120;
|
||||||
|
|
||||||
|
int result = EditFrames(kRefVideo, kWidth, kHeight, kFirstFrameToProcess,
|
||||||
|
kInterval, kLastFrameToProcess, kTestVideo);
|
||||||
|
EXPECT_EQ(-11, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(FrameEditingTest, DeletingEverySecondFrame) {
|
||||||
|
const int kFirstFrameToProcess = 1;
|
||||||
|
const int kInterval = -2;
|
||||||
|
const int kLastFrameToProcess = 10000;
|
||||||
|
// Set kLastFrameToProcess to a large value so that all frame are processed.
|
||||||
|
int result = EditFrames(kRefVideo, kWidth, kHeight, kFirstFrameToProcess,
|
||||||
|
kInterval, kLastFrameToProcess, kTestVideo);
|
||||||
|
EXPECT_EQ(0, result);
|
||||||
|
|
||||||
|
while (!feof(original_fid_) && !feof(edited_fid_)) {
|
||||||
|
num_bytes_read_ =
|
||||||
|
fread(original_buffer_.get(), 1, kFrameSize, original_fid_);
|
||||||
|
if (!feof(original_fid_)) {
|
||||||
|
EXPECT_EQ(kFrameSize, num_bytes_read_);
|
||||||
|
num_frames_read_++;
|
||||||
|
}
|
||||||
|
// We want to compare every second frame of the original to the edited.
|
||||||
|
// kInterval=-2 and (num_frames_read_ - 1) % kInterval will be -1 for
|
||||||
|
// every second frame.
|
||||||
|
// num_frames_read_ - 1 because we have deleted frame number 2, 4 , 6 etc.
|
||||||
|
if ((num_frames_read_ - 1) % kInterval == -1) {
|
||||||
|
num_bytes_read_ = fread(edited_buffer_.get(), 1, kFrameSize,
|
||||||
|
edited_fid_);
|
||||||
|
if (!feof(edited_fid_)) {
|
||||||
|
EXPECT_EQ(kFrameSize, num_bytes_read_);
|
||||||
|
}
|
||||||
|
if (!feof(original_fid_) && !feof(edited_fid_)) {
|
||||||
|
EXPECT_EQ(0, memcmp(original_buffer_.get(),
|
||||||
|
edited_buffer_.get(), kFrameSize));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(FrameEditingTest, RepeatFrames) {
|
||||||
|
const int kFirstFrameToProcess = 160;
|
||||||
|
const int kInterval = 2;
|
||||||
|
const int kLastFrameToProcess = 240;
|
||||||
|
|
||||||
|
int result = EditFrames(kRefVideo, kWidth, kHeight, kFirstFrameToProcess,
|
||||||
|
kInterval, kLastFrameToProcess, kTestVideo);
|
||||||
|
EXPECT_EQ(0, result);
|
||||||
|
|
||||||
|
for (int i = 1; i < kFirstFrameToProcess; ++i) {
|
||||||
|
num_bytes_read_ = fread(original_buffer_.get(), 1, kFrameSize,
|
||||||
|
original_fid_);
|
||||||
|
EXPECT_EQ(kFrameSize, num_bytes_read_);
|
||||||
|
|
||||||
|
num_bytes_read_ = fread(edited_buffer_.get(), 1, kFrameSize, edited_fid_);
|
||||||
|
EXPECT_EQ(kFrameSize, num_bytes_read_);
|
||||||
|
|
||||||
|
EXPECT_EQ(0, memcmp(original_buffer_.get(), edited_buffer_.get(),
|
||||||
|
kFrameSize));
|
||||||
|
}
|
||||||
|
// Do not compare the frames that have been repeated.
|
||||||
|
for (int i = kFirstFrameToProcess; i <= kLastFrameToProcess; ++i) {
|
||||||
|
num_bytes_read_ = fread(original_buffer_.get(), 1, kFrameSize,
|
||||||
|
original_fid_);
|
||||||
|
EXPECT_EQ(kFrameSize, num_bytes_read_);
|
||||||
|
for (int i = 1; i <= kInterval; ++i) {
|
||||||
|
num_bytes_read_ = fread(edited_buffer_.get(), 1, kFrameSize,
|
||||||
|
edited_fid_);
|
||||||
|
EXPECT_EQ(kFrameSize, num_bytes_read_);
|
||||||
|
EXPECT_EQ(0, memcmp(original_buffer_.get(), edited_buffer_.get(),
|
||||||
|
kFrameSize));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CompareToTheEnd(edited_fid_, original_fid_, &original_buffer_,
|
||||||
|
&edited_buffer_);
|
||||||
|
}
|
||||||
|
} // namespace test
|
||||||
|
} // namespace webrtc
|
||||||
|
|
@ -85,27 +85,27 @@
|
|||||||
],
|
],
|
||||||
}, # rgba_to_i420_converter
|
}, # rgba_to_i420_converter
|
||||||
{
|
{
|
||||||
'target_name': 'frame_cutter_lib',
|
'target_name': 'frame_editing_lib',
|
||||||
'type': '<(library)',
|
'type': '<(library)',
|
||||||
'dependencies': [
|
'dependencies': [
|
||||||
'<(webrtc_root)/common_video/common_video.gyp:common_video',
|
'<(webrtc_root)/common_video/common_video.gyp:common_video',
|
||||||
],
|
],
|
||||||
'sources': [
|
'sources': [
|
||||||
'frame_cutter/frame_cutter_lib.cc',
|
'frame_editing/frame_editing_lib.cc',
|
||||||
'frame_cutter/frame_cutter_lib.h',
|
'frame_editing/frame_editing_lib.h',
|
||||||
],
|
],
|
||||||
}, # frame_cutter_lib
|
}, # frame_editing_lib
|
||||||
{
|
{
|
||||||
'target_name': 'frame_cutter',
|
'target_name': 'frame_editor',
|
||||||
'type': 'executable',
|
'type': 'executable',
|
||||||
'dependencies': [
|
'dependencies': [
|
||||||
'command_line_parser',
|
'command_line_parser',
|
||||||
'frame_cutter_lib',
|
'frame_editing_lib',
|
||||||
],
|
],
|
||||||
'sources': [
|
'sources': [
|
||||||
'frame_cutter/frame_cutter.cc',
|
'frame_editing/frame_editing.cc',
|
||||||
],
|
],
|
||||||
}, # frame_cutter
|
}, # frame_editing
|
||||||
],
|
],
|
||||||
'conditions': [
|
'conditions': [
|
||||||
['include_tests==1', {
|
['include_tests==1', {
|
||||||
@ -114,15 +114,15 @@
|
|||||||
'target_name': 'tools_unittests',
|
'target_name': 'tools_unittests',
|
||||||
'type': 'executable',
|
'type': 'executable',
|
||||||
'dependencies': [
|
'dependencies': [
|
||||||
'frame_cutter_lib',
|
'frame_editing_lib',
|
||||||
'<(webrtc_root)/test/test.gyp:test_support_main',
|
'<(webrtc_root)/test/test.gyp:test_support_main',
|
||||||
'<(DEPTH)/testing/gtest.gyp:gtest',
|
'<(DEPTH)/testing/gtest.gyp:gtest',
|
||||||
],
|
],
|
||||||
'sources': [
|
'sources': [
|
||||||
'frame_cutter/frame_cutter_unittest.cc',
|
'frame_editing/frame_editing_unittest.cc',
|
||||||
],
|
],
|
||||||
}, # tools_unittests
|
}, # tools_unittests
|
||||||
], # targets
|
], # targets
|
||||||
}], # include_tests
|
}], # include_tests
|
||||||
], # conditions
|
], # conditions
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user