A command-line tool based on libyuv to convert a set of RGBA files to a YUV video.
BUG= TEST= tgbra_to_i420_converter --frames_dir=<directory_to_rgba_frames> --output_file=<output_yuv_file> --width=<width_of_input_frames> --height=<height_of_input_frames> <output_yuv_file> should be an empty file because we open it in append mode Review URL: https://webrtc-codereview.appspot.com/673006 git-svn-id: http://webrtc.googlecode.com/svn/trunk@2475 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
2a45209a6d
commit
b358bd8f87
@ -75,5 +75,19 @@
|
||||
'testsupport/packet_reader_unittest.cc',
|
||||
],
|
||||
},
|
||||
{
|
||||
'target_name': 'rgba_to_i420_converter',
|
||||
'type': 'executable',
|
||||
'dependencies': [
|
||||
'test_support',
|
||||
'<(webrtc_root)/../third_party/google-gflags/google-gflags.gyp:google-gflags',
|
||||
'<(webrtc_root)/../third_party/libyuv/libyuv.gyp:libyuv',
|
||||
],
|
||||
'sources': [
|
||||
'testsupport/converter/converter.h',
|
||||
'testsupport/converter/converter.cc',
|
||||
'testsupport/converter/rgba_to_i420_converter.cc',
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
159
src/test/testsupport/converter/converter.cc
Normal file
159
src/test/testsupport/converter/converter.cc
Normal file
@ -0,0 +1,159 @@
|
||||
/*
|
||||
* 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 <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
|
||||
#include "testsupport/converter/converter.h"
|
||||
#include "testsupport/frame_reader.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#define SEPARATOR '\\'
|
||||
#define STAT _stat
|
||||
#else
|
||||
#define SEPARATOR '/'
|
||||
#define STAT stat
|
||||
#endif
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
Converter::Converter(int width, int height)
|
||||
: width_(width),
|
||||
height_(height) {
|
||||
}
|
||||
|
||||
bool Converter::ConvertRGBAToI420Video(std::string frames_dir,
|
||||
std::string output_file_name) {
|
||||
FILE* output_file = fopen(output_file_name.c_str(), "ab");
|
||||
|
||||
// Open output file in append mode.
|
||||
if (output_file == NULL) {
|
||||
fprintf(stderr, "Couldn't open input file for reading: %s\n",
|
||||
output_file_name.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
int input_frame_size = InputFrameSize();
|
||||
uint8* rgba_buffer = new uint8[input_frame_size];
|
||||
int y_plane_size = YPlaneSize();
|
||||
uint8* dst_y = new uint8[y_plane_size];
|
||||
int u_plane_size = UPlaneSize();
|
||||
uint8* dst_u = new uint8[u_plane_size];
|
||||
int v_plane_size = VPlaneSize();
|
||||
uint8* dst_v = new uint8[v_plane_size];
|
||||
|
||||
int counter = 0; // Counter to form frame names.
|
||||
bool success = false; // Is conversion successful.
|
||||
|
||||
while (true) {
|
||||
std::string file_name = FormFrameName(4, counter);
|
||||
// Get full path file name.
|
||||
std::string input_file_name = FindFullFileName(frames_dir, file_name);
|
||||
|
||||
if (FileExists(input_file_name)) {
|
||||
++counter; // Update counter for the next round.
|
||||
} else {
|
||||
fprintf(stdout, "Reached end of frames list\n");
|
||||
break;
|
||||
}
|
||||
|
||||
// Read the RGBA frame into rgba_buffer.
|
||||
ReadRGBAFrame(input_file_name.c_str(), input_frame_size, rgba_buffer);
|
||||
|
||||
// Convert to I420 frame.
|
||||
libyuv::ABGRToI420(rgba_buffer, SrcStrideFrame(),
|
||||
dst_y, DstStrideY(),
|
||||
dst_u, DstStrideU(),
|
||||
dst_v, DstStrideV(),
|
||||
width_, height_);
|
||||
|
||||
// Add the I420 frame to the YUV video file.
|
||||
success = AddYUVToFile(dst_y, y_plane_size, dst_u, u_plane_size,
|
||||
dst_v, v_plane_size, output_file);
|
||||
|
||||
|
||||
if (!success) {
|
||||
fprintf(stderr, "LibYUV error during RGBA to I420 frame conversion\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
delete[] rgba_buffer;
|
||||
delete[] dst_y;
|
||||
delete[] dst_u;
|
||||
delete[] dst_v;
|
||||
|
||||
fclose(output_file);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool Converter::AddYUVToFile(uint8* y_plane, int y_plane_size,
|
||||
uint8* u_plane, int u_plane_size,
|
||||
uint8* v_plane, int v_plane_size,
|
||||
FILE* output_file) {
|
||||
bool success = AddYUVPlaneToFile(y_plane, y_plane_size, output_file) &&
|
||||
AddYUVPlaneToFile(u_plane, u_plane_size, output_file) &&
|
||||
AddYUVPlaneToFile(v_plane, v_plane_size, output_file);
|
||||
return success;
|
||||
}
|
||||
|
||||
bool Converter::AddYUVPlaneToFile(uint8* yuv_plane, int yuv_plane_size,
|
||||
FILE* file) {
|
||||
size_t bytes_written = fwrite(yuv_plane, 1, yuv_plane_size, file);
|
||||
|
||||
if (bytes_written != static_cast<size_t>(yuv_plane_size)) {
|
||||
fprintf(stderr, "Number of bytes written (%d) doesn't match size of y plane"
|
||||
" (%d)\n", static_cast<int>(bytes_written), yuv_plane_size);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Converter::ReadRGBAFrame(const char* input_file_name, int input_frame_size,
|
||||
unsigned char* buffer) {
|
||||
// Use FrameReader.
|
||||
FrameReaderImpl frame_reader(input_file_name, input_frame_size);
|
||||
if (!frame_reader.Init()) {
|
||||
fprintf(stderr, "Couldn't initialize FrameReader for frame %s",
|
||||
input_file_name);
|
||||
return false;
|
||||
}
|
||||
frame_reader.ReadFrame(buffer);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string Converter::FindFullFileName(std::string dir_name,
|
||||
std::string file_name) {
|
||||
return dir_name + SEPARATOR + file_name;
|
||||
}
|
||||
|
||||
bool Converter:: FileExists(std::string file_name_to_check) {
|
||||
struct STAT file_info;
|
||||
int result = STAT(file_name_to_check.c_str(), &file_info);
|
||||
return (result == 0);
|
||||
}
|
||||
|
||||
std::string Converter::FormFrameName(int width, int number) {
|
||||
std::stringstream tmp;
|
||||
|
||||
// Zero-pad number to a string.
|
||||
tmp << std::setfill('0') << std::setw(width) << number;
|
||||
|
||||
return "frame_" + tmp.str();
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
|
||||
|
104
src/test/testsupport/converter/converter.h
Normal file
104
src/test/testsupport/converter/converter.h
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.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SRC_TEST_TESTSUPPORT_CONVERTER_CONVERTER_H_
|
||||
#define WEBRTC_SRC_TEST_TESTSUPPORT_CONVERTER_CONVERTER_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "third_party/libyuv/include/libyuv.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
// Handles a conversion between a set of RGBA frames to a YUV (I420) video.
|
||||
class Converter {
|
||||
public:
|
||||
Converter(int width, int height);
|
||||
|
||||
// Converts RGBA to YUV video.
|
||||
bool ConvertRGBAToI420Video(std::string frames_dir,
|
||||
std::string output_file_name);
|
||||
|
||||
private:
|
||||
int width_; // Width of the video (respectively of the RGBA frames).
|
||||
int height_; // Height of the video (respectively of the RGBA frames).
|
||||
|
||||
// Returns the size of the Y plane in bytes.
|
||||
int YPlaneSize() const {
|
||||
return width_*height_;
|
||||
}
|
||||
|
||||
// Returns the size of the U plane in bytes.
|
||||
int UPlaneSize() const {
|
||||
return ((width_+1)/2)*((height_)/2);
|
||||
}
|
||||
|
||||
// Returns the size of the V plane in bytes.
|
||||
int VPlaneSize() const {
|
||||
return ((width_+1)/2)*((height_)/2);
|
||||
}
|
||||
|
||||
// Returns the number of bytes per row in the RGBA frame.
|
||||
int SrcStrideFrame() const {
|
||||
return width_*4;
|
||||
}
|
||||
|
||||
// Returns the number of bytes in the Y plane.
|
||||
int DstStrideY() const {
|
||||
return width_;
|
||||
}
|
||||
|
||||
// Returns the number of bytes in the U plane.
|
||||
int DstStrideU() const {
|
||||
return (width_+1)/2;
|
||||
}
|
||||
|
||||
// Returns the number of bytes in the V plane.
|
||||
int DstStrideV() const {
|
||||
return (width_+1)/2;
|
||||
}
|
||||
|
||||
// Returns the size in bytes of the input RGBA frames.
|
||||
int InputFrameSize() const {
|
||||
return width_*height_*4;
|
||||
}
|
||||
|
||||
// Writes the Y, U and V (in this order) planes to the file, thus adding a
|
||||
// raw YUV frame to the file.
|
||||
bool AddYUVToFile(uint8* y_plane, int y_plane_size,
|
||||
uint8* u_plane, int u_plane_size,
|
||||
uint8* v_plane, int v_plane_size,
|
||||
FILE* output_file);
|
||||
|
||||
// Adds the Y, U or V plane to the file.
|
||||
bool AddYUVPlaneToFile(uint8* yuv_plane, int yuv_plane_size, FILE* file);
|
||||
|
||||
// Reads a RGBA frame from input_file_name with input_frame_size size in bytes
|
||||
// into the buffer.
|
||||
bool ReadRGBAFrame(const char* input_file_name, int input_frame_size,
|
||||
unsigned char* buffer);
|
||||
|
||||
// Finds the full path name of the file - concatenates the directory and file
|
||||
// names.
|
||||
std::string FindFullFileName(std::string dir_name, std::string file_name);
|
||||
|
||||
// Checks if a file exists.
|
||||
bool FileExists(std::string file_name_to_check);
|
||||
|
||||
// Returns the name of the file in the form frame_<number>, where <number> is
|
||||
// 4 zero padded (i.e. frame_0000, frame_0001, etc.).
|
||||
std::string FormFrameName(int width, int number);
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SRC_TEST_TESTSUPPORT_CONVERTER_CONVERTER_H_
|
58
src/test/testsupport/converter/rgba_to_i420_converter.cc
Normal file
58
src/test/testsupport/converter/rgba_to_i420_converter.cc
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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 <cstdio>
|
||||
|
||||
#include "google/gflags.h"
|
||||
#include "testsupport/converter/converter.h"
|
||||
|
||||
DEFINE_int32(width, -1, "Width in pixels of the frames in the input file.");
|
||||
DEFINE_int32(height, -1, "Height in pixels of the frames in the input file.");
|
||||
DEFINE_string(frames_dir, ".", "The path to the directory where the frames "
|
||||
"reside");
|
||||
DEFINE_string(output_file, "./output.yuv", "The output file to which frames are"
|
||||
" written");
|
||||
|
||||
/*
|
||||
* A command-line tool based on libyuv to convert a set of RGBA files to a YUV
|
||||
* video.
|
||||
* Usage:
|
||||
* rgba_to_i420_converter --frames_dir=<directory_to_rgba_frames>
|
||||
* --output_file=<output_yuv_file> --width=<width_of_input_frames>
|
||||
* --height=<height_of_input_frames>
|
||||
*
|
||||
* <output_yuv_file> should be an empty file because we open it in append mode
|
||||
*/
|
||||
int main(int argc, char** argv) {
|
||||
std::string program_name = argv[0];
|
||||
std::string usage = "Converts RGBA raw image files to I420 frames for YUV.\n"
|
||||
"Run " + program_name + " --helpshort for usage.\n"
|
||||
"Example usage:\n" + program_name +
|
||||
" --frames_dir=. --output_file=output.yuv --width=320 --height=240\n";
|
||||
google::SetUsageMessage(usage);
|
||||
|
||||
google::ParseCommandLineFlags(&argc, &argv, true);
|
||||
|
||||
fprintf(stdout, "You entered the following flags: frames_dir=%s, "
|
||||
"output_file=%s, width=%d, height=%d\n", FLAGS_frames_dir.c_str(),
|
||||
FLAGS_output_file.c_str(), FLAGS_width, FLAGS_height);
|
||||
|
||||
webrtc::test::Converter converter(FLAGS_width, FLAGS_height);
|
||||
bool success = converter.ConvertRGBAToI420Video(FLAGS_frames_dir,
|
||||
FLAGS_output_file);
|
||||
|
||||
if (success) {
|
||||
fprintf(stdout, "Successful conversion of RGBA frames to YUV video!\n");
|
||||
return 0;
|
||||
} else {
|
||||
fprintf(stdout, "Unsuccessful conversion of RGBA frames to YUV video!\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user