Home | History | Annotate | Download | only in converter
      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