| /* |
| * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
| * |
| * Use of this source code is governed by a BSD-style license |
| * that can be found in the LICENSE file in the root of the source |
| * tree. An additional intellectual property rights grant can be found |
| * in the file PATENTS. All contributing project authors may |
| * be found in the AUTHORS file in the root of the source tree. |
| */ |
| #include "rtc_tools/converter/converter.h" |
| |
| #include <stdio.h> |
| #include <sys/stat.h> |
| #include <iomanip> |
| #include <sstream> |
| |
| #include "third_party/libyuv/include/libyuv/compare.h" |
| #include "third_party/libyuv/include/libyuv/convert.h" |
| |
| #ifdef WIN32 |
| #define SEPARATOR '\\' |
| #define STAT _stat |
| #else |
| #define SEPARATOR '/' |
| #define STAT stat |
| #endif |
| |
| namespace webrtc { |
| namespace test { |
| |
| Converter::Converter(int width, int height) : width_(width), height_(height) {} |
| |
| bool Converter::ConvertRGBAToI420Video(std::string frames_dir, |
| std::string output_file_name, |
| bool delete_frames) { |
| FILE* output_file = fopen(output_file_name.c_str(), "wb"); |
| |
| // Open output file in append mode. |
| if (output_file == NULL) { |
| fprintf(stderr, "Couldn't open input file for reading: %s\n", |
| output_file_name.c_str()); |
| return false; |
| } |
| |
| int input_frame_size = InputFrameSize(); |
| uint8_t* rgba_buffer = new uint8_t[input_frame_size]; |
| int y_plane_size = YPlaneSize(); |
| uint8_t* dst_y = new uint8_t[y_plane_size]; |
| int u_plane_size = UPlaneSize(); |
| uint8_t* dst_u = new uint8_t[u_plane_size]; |
| int v_plane_size = VPlaneSize(); |
| uint8_t* dst_v = new uint8_t[v_plane_size]; |
| |
| int counter = 0; // Counter to form frame names. |
| bool success = false; // Is conversion successful. |
| |
| while (true) { |
| std::string file_name = FormFrameName(4, counter); |
| // Get full path file name. |
| std::string input_file_name = FindFullFileName(frames_dir, file_name); |
| |
| if (FileExists(input_file_name)) { |
| ++counter; // Update counter for the next round. |
| } else { |
| fprintf(stdout, "Reached end of frames list\n"); |
| break; |
| } |
| |
| // Read the RGBA frame into rgba_buffer. |
| ReadRGBAFrame(input_file_name.c_str(), input_frame_size, rgba_buffer); |
| |
| // Delete the input frame. |
| if (delete_frames) { |
| if (remove(input_file_name.c_str()) != 0) { |
| fprintf(stderr, "Cannot delete file %s\n", input_file_name.c_str()); |
| } |
| } |
| |
| // Convert to I420 frame. |
| libyuv::ABGRToI420(rgba_buffer, SrcStrideFrame(), dst_y, DstStrideY(), |
| dst_u, DstStrideU(), dst_v, DstStrideV(), width_, |
| height_); |
| |
| // Add the I420 frame to the YUV video file. |
| success = AddYUVToFile(dst_y, y_plane_size, dst_u, u_plane_size, dst_v, |
| v_plane_size, output_file); |
| |
| if (!success) { |
| fprintf(stderr, "LibYUV error during RGBA to I420 frame conversion\n"); |
| break; |
| } |
| } |
| |
| delete[] rgba_buffer; |
| delete[] dst_y; |
| delete[] dst_u; |
| delete[] dst_v; |
| |
| fclose(output_file); |
| |
| return success; |
| } |
| |
| bool Converter::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) { |
| bool success = AddYUVPlaneToFile(y_plane, y_plane_size, output_file) && |
| AddYUVPlaneToFile(u_plane, u_plane_size, output_file) && |
| AddYUVPlaneToFile(v_plane, v_plane_size, output_file); |
| return success; |
| } |
| |
| bool Converter::AddYUVPlaneToFile(uint8_t* yuv_plane, |
| int yuv_plane_size, |
| FILE* file) { |
| size_t bytes_written = fwrite(yuv_plane, 1, yuv_plane_size, file); |
| |
| if (bytes_written != static_cast<size_t>(yuv_plane_size)) { |
| fprintf(stderr, |
| "Number of bytes written (%d) doesn't match size of y plane" |
| " (%d)\n", |
| static_cast<int>(bytes_written), yuv_plane_size); |
| return false; |
| } |
| return true; |
| } |
| |
| bool Converter::ReadRGBAFrame(const char* input_file_name, |
| int input_frame_size, |
| unsigned char* buffer) { |
| FILE* input_file = fopen(input_file_name, "rb"); |
| if (input_file == NULL) { |
| fprintf(stderr, "Couldn't open input file for reading: %s\n", |
| input_file_name); |
| return false; |
| } |
| |
| size_t nbr_read = fread(buffer, 1, input_frame_size, input_file); |
| fclose(input_file); |
| |
| if (nbr_read != static_cast<size_t>(input_frame_size)) { |
| fprintf(stderr, "Error reading from input file: %s\n", input_file_name); |
| return false; |
| } |
| |
| return true; |
| } |
| |
| std::string Converter::FindFullFileName(std::string dir_name, |
| std::string file_name) { |
| return dir_name + SEPARATOR + file_name; |
| } |
| |
| bool Converter::FileExists(std::string file_name_to_check) { |
| struct STAT file_info; |
| int result = STAT(file_name_to_check.c_str(), &file_info); |
| return (result == 0); |
| } |
| |
| std::string Converter::FormFrameName(int width, int number) { |
| std::stringstream tmp; |
| |
| // Zero-pad number to a string. |
| tmp << std::setfill('0') << std::setw(width) << number; |
| |
| return "frame_" + tmp.str(); |
| } |
| |
| } // namespace test |
| } // namespace webrtc |