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 27 namespace webrtc { 28 namespace test { 29 30 Converter::Converter(int width, int height) 31 : width_(width), 32 height_(height) { 33 } 34 35 bool 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* rgba_buffer = new uint8[input_frame_size]; 49 int y_plane_size = YPlaneSize(); 50 uint8* dst_y = new uint8[y_plane_size]; 51 int u_plane_size = UPlaneSize(); 52 uint8* dst_u = new uint8[u_plane_size]; 53 int v_plane_size = VPlaneSize(); 54 uint8* dst_v = new uint8[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 109 bool Converter::AddYUVToFile(uint8* y_plane, int y_plane_size, 110 uint8* u_plane, int u_plane_size, 111 uint8* v_plane, int v_plane_size, 112 FILE* output_file) { 113 bool success = AddYUVPlaneToFile(y_plane, y_plane_size, output_file) && 114 AddYUVPlaneToFile(u_plane, u_plane_size, output_file) && 115 AddYUVPlaneToFile(v_plane, v_plane_size, output_file); 116 return success; 117 } 118 119 bool Converter::AddYUVPlaneToFile(uint8* yuv_plane, int yuv_plane_size, 120 FILE* file) { 121 size_t bytes_written = fwrite(yuv_plane, 1, yuv_plane_size, file); 122 123 if (bytes_written != static_cast<size_t>(yuv_plane_size)) { 124 fprintf(stderr, "Number of bytes written (%d) doesn't match size of y plane" 125 " (%d)\n", static_cast<int>(bytes_written), yuv_plane_size); 126 return false; 127 } 128 return true; 129 } 130 131 bool Converter::ReadRGBAFrame(const char* input_file_name, int input_frame_size, 132 unsigned char* buffer) { 133 FILE* input_file = fopen(input_file_name, "rb"); 134 if (input_file == NULL) { 135 fprintf(stderr, "Couldn't open input file for reading: %s\n", 136 input_file_name); 137 return false; 138 } 139 140 size_t nbr_read = fread(buffer, 1, input_frame_size, input_file); 141 fclose(input_file); 142 143 if (nbr_read != static_cast<size_t>(input_frame_size)) { 144 fprintf(stderr, "Error reading from input file: %s\n", input_file_name); 145 return false; 146 } 147 148 return true; 149 } 150 151 std::string Converter::FindFullFileName(std::string dir_name, 152 std::string file_name) { 153 return dir_name + SEPARATOR + file_name; 154 } 155 156 bool Converter:: FileExists(std::string file_name_to_check) { 157 struct STAT file_info; 158 int result = STAT(file_name_to_check.c_str(), &file_info); 159 return (result == 0); 160 } 161 162 std::string Converter::FormFrameName(int width, int number) { 163 std::stringstream tmp; 164 165 // Zero-pad number to a string. 166 tmp << std::setfill('0') << std::setw(width) << number; 167 168 return "frame_" + tmp.str(); 169 } 170 171 } // namespace test 172 } // namespace webrtc 173