1 /*
2  *  Copyright (c) 2018 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 
11 #include "rtc_tools/video_file_writer.h"
12 
13 #include <stdint.h>
14 
15 #include <cstdio>
16 #include <string>
17 
18 #include "absl/strings/match.h"
19 #include "api/video/video_frame_buffer.h"
20 #include "rtc_base/logging.h"
21 
22 namespace webrtc {
23 namespace test {
24 namespace {
25 
WriteVideoToFile(const rtc::scoped_refptr<Video> & video,const std::string & file_name,int fps,bool isY4m)26 void WriteVideoToFile(const rtc::scoped_refptr<Video>& video,
27                       const std::string& file_name,
28                       int fps,
29                       bool isY4m) {
30   RTC_CHECK(video);
31   FILE* output_file = fopen(file_name.c_str(), "wb");
32   if (output_file == nullptr) {
33     RTC_LOG(LS_ERROR) << "Could not open file for writing: " << file_name;
34     return;
35   }
36 
37   if (isY4m) {
38     fprintf(output_file, "YUV4MPEG2 W%d H%d F%d:1 C420\n", video->width(),
39             video->height(), fps);
40   }
41   for (size_t i = 0; i < video->number_of_frames(); ++i) {
42     if (isY4m) {
43       std::string frame = "FRAME\n";
44       fwrite(frame.c_str(), 1, 6, output_file);
45     }
46     rtc::scoped_refptr<I420BufferInterface> buffer = video->GetFrame(i);
47     RTC_CHECK(buffer) << "Frame: " << i
48                       << "\nWhile trying to create: " << file_name;
49     const uint8_t* data_y = buffer->DataY();
50     int stride = buffer->StrideY();
51     for (int i = 0; i < video->height(); ++i) {
52       fwrite(data_y + i * stride, /*size=*/1, stride, output_file);
53     }
54     const uint8_t* data_u = buffer->DataU();
55     stride = buffer->StrideU();
56     for (int i = 0; i < buffer->ChromaHeight(); ++i) {
57       fwrite(data_u + i * stride, /*size=*/1, stride, output_file);
58     }
59     const uint8_t* data_v = buffer->DataV();
60     stride = buffer->StrideV();
61     for (int i = 0; i < buffer->ChromaHeight(); ++i) {
62       fwrite(data_v + i * stride, /*size=*/1, stride, output_file);
63     }
64   }
65   if (ferror(output_file) != 0) {
66     RTC_LOG(LS_ERROR) << "Error writing to file " << file_name;
67   }
68   fclose(output_file);
69 }
70 
71 }  // Anonymous namespace
72 
WriteVideoToFile(const rtc::scoped_refptr<Video> & video,const std::string & file_name,int fps)73 void WriteVideoToFile(const rtc::scoped_refptr<Video>& video,
74                       const std::string& file_name,
75                       int fps) {
76   WriteVideoToFile(video, file_name, fps,
77                    /*isY4m=*/absl::EndsWith(file_name, ".y4m"));
78 }
79 
WriteY4mVideoToFile(const rtc::scoped_refptr<Video> & video,const std::string & file_name,int fps)80 void WriteY4mVideoToFile(const rtc::scoped_refptr<Video>& video,
81                          const std::string& file_name,
82                          int fps) {
83   WriteVideoToFile(video, file_name, fps, /*isY4m=*/true);
84 }
85 
WriteYuvVideoToFile(const rtc::scoped_refptr<Video> & video,const std::string & file_name,int fps)86 void WriteYuvVideoToFile(const rtc::scoped_refptr<Video>& video,
87                          const std::string& file_name,
88                          int fps) {
89   WriteVideoToFile(video, file_name, fps, /*isY4m=*/false);
90 }
91 
92 }  // namespace test
93 }  // namespace webrtc
94