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