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