blob: 0216ff53df154f2aac45d4ed5f19a99c15f7d122 [file] [log] [blame]
vspasova@webrtc.orgb358bd82012-07-02 07:43:30 +00001/*
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 */
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000010#include <stdio.h>
vspasova@webrtc.orgb358bd82012-07-02 07:43:30 +000011#include <stdlib.h>
12#include <sys/stat.h>
13
14#include <iomanip>
15#include <sstream>
16
kjellanderd2b63cf2017-06-30 03:04:59 -070017#include "webrtc/rtc_tools/converter/converter.h"
vspasova@webrtc.orgb358bd82012-07-02 07:43:30 +000018
19#ifdef WIN32
20#define SEPARATOR '\\'
21#define STAT _stat
22#else
23#define SEPARATOR '/'
24#define STAT stat
25#endif
26
27namespace webrtc {
28namespace test {
29
30Converter::Converter(int width, int height)
31 : width_(width),
32 height_(height) {
33}
34
35bool Converter::ConvertRGBAToI420Video(std::string frames_dir,
vspasova@webrtc.org8e221ee2012-08-15 07:42:00 +000036 std::string output_file_name,
37 bool delete_frames) {
38 FILE* output_file = fopen(output_file_name.c_str(), "wb");
vspasova@webrtc.orgb358bd82012-07-02 07:43:30 +000039
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();
Peter Boström0c4e06b2015-10-07 12:23:21 +020048 uint8_t* rgba_buffer = new uint8_t[input_frame_size];
vspasova@webrtc.orgb358bd82012-07-02 07:43:30 +000049 int y_plane_size = YPlaneSize();
Peter Boström0c4e06b2015-10-07 12:23:21 +020050 uint8_t* dst_y = new uint8_t[y_plane_size];
vspasova@webrtc.orgb358bd82012-07-02 07:43:30 +000051 int u_plane_size = UPlaneSize();
Peter Boström0c4e06b2015-10-07 12:23:21 +020052 uint8_t* dst_u = new uint8_t[u_plane_size];
vspasova@webrtc.orgb358bd82012-07-02 07:43:30 +000053 int v_plane_size = VPlaneSize();
Peter Boström0c4e06b2015-10-07 12:23:21 +020054 uint8_t* dst_v = new uint8_t[v_plane_size];
vspasova@webrtc.orgb358bd82012-07-02 07:43:30 +000055
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
vspasova@webrtc.org8e221ee2012-08-15 07:42:00 +000074 // 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
vspasova@webrtc.orgb358bd82012-07-02 07:43:30 +000081 // 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
Peter Boström0c4e06b2015-10-07 12:23:21 +0200109bool 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,
vspasova@webrtc.orgb358bd82012-07-02 07:43:30 +0000115 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
Peter Boström0c4e06b2015-10-07 12:23:21 +0200122bool Converter::AddYUVPlaneToFile(uint8_t* yuv_plane,
123 int yuv_plane_size,
vspasova@webrtc.orgb358bd82012-07-02 07:43:30 +0000124 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
135bool Converter::ReadRGBAFrame(const char* input_file_name, int input_frame_size,
136 unsigned char* buffer) {
vspasova@webrtc.orgf61dc9b2012-08-22 08:12:00 +0000137 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",
vspasova@webrtc.orgb358bd82012-07-02 07:43:30 +0000140 input_file_name);
141 return false;
142 }
vspasova@webrtc.orgf61dc9b2012-08-22 08:12:00 +0000143
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
vspasova@webrtc.orgb358bd82012-07-02 07:43:30 +0000152 return true;
153}
154
155std::string Converter::FindFullFileName(std::string dir_name,
156 std::string file_name) {
157 return dir_name + SEPARATOR + file_name;
158}
159
160bool 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
166std::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