vspasova@webrtc.org | b358bd8 | 2012-07-02 07:43:30 +0000 | [diff] [blame] | 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 | */ |
pbos@webrtc.org | 12dc1a3 | 2013-08-05 16:22:53 +0000 | [diff] [blame] | 10 | #include <stdio.h> |
vspasova@webrtc.org | b358bd8 | 2012-07-02 07:43:30 +0000 | [diff] [blame] | 11 | #include <stdlib.h> |
| 12 | #include <sys/stat.h> |
| 13 | |
| 14 | #include <iomanip> |
| 15 | #include <sstream> |
| 16 | |
kjellander | d2b63cf | 2017-06-30 03:04:59 -0700 | [diff] [blame] | 17 | #include "webrtc/rtc_tools/converter/converter.h" |
vspasova@webrtc.org | b358bd8 | 2012-07-02 07:43:30 +0000 | [diff] [blame] | 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, |
vspasova@webrtc.org | 8e221ee | 2012-08-15 07:42:00 +0000 | [diff] [blame] | 36 | std::string output_file_name, |
| 37 | bool delete_frames) { |
| 38 | FILE* output_file = fopen(output_file_name.c_str(), "wb"); |
vspasova@webrtc.org | b358bd8 | 2012-07-02 07:43:30 +0000 | [diff] [blame] | 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(); |
Peter Boström | 0c4e06b | 2015-10-07 12:23:21 +0200 | [diff] [blame] | 48 | uint8_t* rgba_buffer = new uint8_t[input_frame_size]; |
vspasova@webrtc.org | b358bd8 | 2012-07-02 07:43:30 +0000 | [diff] [blame] | 49 | int y_plane_size = YPlaneSize(); |
Peter Boström | 0c4e06b | 2015-10-07 12:23:21 +0200 | [diff] [blame] | 50 | uint8_t* dst_y = new uint8_t[y_plane_size]; |
vspasova@webrtc.org | b358bd8 | 2012-07-02 07:43:30 +0000 | [diff] [blame] | 51 | int u_plane_size = UPlaneSize(); |
Peter Boström | 0c4e06b | 2015-10-07 12:23:21 +0200 | [diff] [blame] | 52 | uint8_t* dst_u = new uint8_t[u_plane_size]; |
vspasova@webrtc.org | b358bd8 | 2012-07-02 07:43:30 +0000 | [diff] [blame] | 53 | int v_plane_size = VPlaneSize(); |
Peter Boström | 0c4e06b | 2015-10-07 12:23:21 +0200 | [diff] [blame] | 54 | uint8_t* dst_v = new uint8_t[v_plane_size]; |
vspasova@webrtc.org | b358bd8 | 2012-07-02 07:43:30 +0000 | [diff] [blame] | 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 | |
vspasova@webrtc.org | 8e221ee | 2012-08-15 07:42:00 +0000 | [diff] [blame] | 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 | |
vspasova@webrtc.org | b358bd8 | 2012-07-02 07:43:30 +0000 | [diff] [blame] | 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 | |
Peter Boström | 0c4e06b | 2015-10-07 12:23:21 +0200 | [diff] [blame] | 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, |
vspasova@webrtc.org | b358bd8 | 2012-07-02 07:43:30 +0000 | [diff] [blame] | 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 | |
Peter Boström | 0c4e06b | 2015-10-07 12:23:21 +0200 | [diff] [blame] | 122 | bool Converter::AddYUVPlaneToFile(uint8_t* yuv_plane, |
| 123 | int yuv_plane_size, |
vspasova@webrtc.org | b358bd8 | 2012-07-02 07:43:30 +0000 | [diff] [blame] | 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 | |
| 135 | bool Converter::ReadRGBAFrame(const char* input_file_name, int input_frame_size, |
| 136 | unsigned char* buffer) { |
vspasova@webrtc.org | f61dc9b | 2012-08-22 08:12:00 +0000 | [diff] [blame] | 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", |
vspasova@webrtc.org | b358bd8 | 2012-07-02 07:43:30 +0000 | [diff] [blame] | 140 | input_file_name); |
| 141 | return false; |
| 142 | } |
vspasova@webrtc.org | f61dc9b | 2012-08-22 08:12:00 +0000 | [diff] [blame] | 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 | |
vspasova@webrtc.org | b358bd8 | 2012-07-02 07:43:30 +0000 | [diff] [blame] | 152 | return true; |
| 153 | } |
| 154 | |
| 155 | std::string Converter::FindFullFileName(std::string dir_name, |
| 156 | std::string file_name) { |
| 157 | return dir_name + SEPARATOR + file_name; |
| 158 | } |
| 159 | |
| 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 | |
| 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 |