converter.cc revision 0c4e06b4c6107a1b94f764e279e4fb4161e905b0
1/* 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10#include <stdio.h> 11#include <stdlib.h> 12#include <sys/stat.h> 13 14#include <iomanip> 15#include <sstream> 16 17#include "webrtc/tools/converter/converter.h" 18 19#ifdef WIN32 20#define SEPARATOR '\\' 21#define STAT _stat 22#else 23#define SEPARATOR '/' 24#define STAT stat 25#endif 26 27namespace webrtc { 28namespace test { 29 30Converter::Converter(int width, int height) 31 : width_(width), 32 height_(height) { 33} 34 35bool Converter::ConvertRGBAToI420Video(std::string frames_dir, 36 std::string output_file_name, 37 bool delete_frames) { 38 FILE* output_file = fopen(output_file_name.c_str(), "wb"); 39 40 // Open output file in append mode. 41 if (output_file == NULL) { 42 fprintf(stderr, "Couldn't open input file for reading: %s\n", 43 output_file_name.c_str()); 44 return false; 45 } 46 47 int input_frame_size = InputFrameSize(); 48 uint8_t* rgba_buffer = new uint8_t[input_frame_size]; 49 int y_plane_size = YPlaneSize(); 50 uint8_t* dst_y = new uint8_t[y_plane_size]; 51 int u_plane_size = UPlaneSize(); 52 uint8_t* dst_u = new uint8_t[u_plane_size]; 53 int v_plane_size = VPlaneSize(); 54 uint8_t* dst_v = new uint8_t[v_plane_size]; 55 56 int counter = 0; // Counter to form frame names. 57 bool success = false; // Is conversion successful. 58 59 while (true) { 60 std::string file_name = FormFrameName(4, counter); 61 // Get full path file name. 62 std::string input_file_name = FindFullFileName(frames_dir, file_name); 63 64 if (FileExists(input_file_name)) { 65 ++counter; // Update counter for the next round. 66 } else { 67 fprintf(stdout, "Reached end of frames list\n"); 68 break; 69 } 70 71 // Read the RGBA frame into rgba_buffer. 72 ReadRGBAFrame(input_file_name.c_str(), input_frame_size, rgba_buffer); 73 74 // Delete the input frame. 75 if (delete_frames) { 76 if (remove(input_file_name.c_str()) != 0) { 77 fprintf(stderr, "Cannot delete file %s\n", input_file_name.c_str()); 78 } 79 } 80 81 // Convert to I420 frame. 82 libyuv::ABGRToI420(rgba_buffer, SrcStrideFrame(), 83 dst_y, DstStrideY(), 84 dst_u, DstStrideU(), 85 dst_v, DstStrideV(), 86 width_, height_); 87 88 // Add the I420 frame to the YUV video file. 89 success = AddYUVToFile(dst_y, y_plane_size, dst_u, u_plane_size, 90 dst_v, v_plane_size, output_file); 91 92 93 if (!success) { 94 fprintf(stderr, "LibYUV error during RGBA to I420 frame conversion\n"); 95 break; 96 } 97 } 98 99 delete[] rgba_buffer; 100 delete[] dst_y; 101 delete[] dst_u; 102 delete[] dst_v; 103 104 fclose(output_file); 105 106 return success; 107} 108 109bool Converter::AddYUVToFile(uint8_t* y_plane, 110 int y_plane_size, 111 uint8_t* u_plane, 112 int u_plane_size, 113 uint8_t* v_plane, 114 int v_plane_size, 115 FILE* output_file) { 116 bool success = AddYUVPlaneToFile(y_plane, y_plane_size, output_file) && 117 AddYUVPlaneToFile(u_plane, u_plane_size, output_file) && 118 AddYUVPlaneToFile(v_plane, v_plane_size, output_file); 119 return success; 120} 121 122bool Converter::AddYUVPlaneToFile(uint8_t* yuv_plane, 123 int yuv_plane_size, 124 FILE* file) { 125 size_t bytes_written = fwrite(yuv_plane, 1, yuv_plane_size, file); 126 127 if (bytes_written != static_cast<size_t>(yuv_plane_size)) { 128 fprintf(stderr, "Number of bytes written (%d) doesn't match size of y plane" 129 " (%d)\n", static_cast<int>(bytes_written), yuv_plane_size); 130 return false; 131 } 132 return true; 133} 134 135bool Converter::ReadRGBAFrame(const char* input_file_name, int input_frame_size, 136 unsigned char* buffer) { 137 FILE* input_file = fopen(input_file_name, "rb"); 138 if (input_file == NULL) { 139 fprintf(stderr, "Couldn't open input file for reading: %s\n", 140 input_file_name); 141 return false; 142 } 143 144 size_t nbr_read = fread(buffer, 1, input_frame_size, input_file); 145 fclose(input_file); 146 147 if (nbr_read != static_cast<size_t>(input_frame_size)) { 148 fprintf(stderr, "Error reading from input file: %s\n", input_file_name); 149 return false; 150 } 151 152 return true; 153} 154 155std::string Converter::FindFullFileName(std::string dir_name, 156 std::string file_name) { 157 return dir_name + SEPARATOR + file_name; 158} 159 160bool Converter:: FileExists(std::string file_name_to_check) { 161 struct STAT file_info; 162 int result = STAT(file_name_to_check.c_str(), &file_info); 163 return (result == 0); 164} 165 166std::string Converter::FormFrameName(int width, int number) { 167 std::stringstream tmp; 168 169 // Zero-pad number to a string. 170 tmp << std::setfill('0') << std::setw(width) << number; 171 172 return "frame_" + tmp.str(); 173} 174 175} // namespace test 176} // namespace webrtc 177