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