• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
Converter(int width,int height)30 Converter::Converter(int width, int height)
31     : width_(width),
32       height_(height) {
33 }
34 
ConvertRGBAToI420Video(std::string frames_dir,std::string output_file_name,bool delete_frames)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_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 
AddYUVToFile(uint8_t * y_plane,int y_plane_size,uint8_t * u_plane,int u_plane_size,uint8_t * v_plane,int v_plane_size,FILE * output_file)109 bool 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 
AddYUVPlaneToFile(uint8_t * yuv_plane,int yuv_plane_size,FILE * file)122 bool 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 
ReadRGBAFrame(const char * input_file_name,int input_frame_size,unsigned char * buffer)135 bool 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 
FindFullFileName(std::string dir_name,std::string file_name)155 std::string Converter::FindFullFileName(std::string dir_name,
156                                         std::string file_name) {
157   return dir_name + SEPARATOR + file_name;
158 }
159 
FileExists(std::string file_name_to_check)160 bool 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 
FormFrameName(int width,int number)166 std::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