xref: /aosp_15_r20/external/webrtc/rtc_tools/video_file_writer.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker 
11*d9f75844SAndroid Build Coastguard Worker #include "rtc_tools/video_file_writer.h"
12*d9f75844SAndroid Build Coastguard Worker 
13*d9f75844SAndroid Build Coastguard Worker #include <stdint.h>
14*d9f75844SAndroid Build Coastguard Worker 
15*d9f75844SAndroid Build Coastguard Worker #include <cstdio>
16*d9f75844SAndroid Build Coastguard Worker #include <string>
17*d9f75844SAndroid Build Coastguard Worker 
18*d9f75844SAndroid Build Coastguard Worker #include "absl/strings/match.h"
19*d9f75844SAndroid Build Coastguard Worker #include "api/video/video_frame_buffer.h"
20*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
21*d9f75844SAndroid Build Coastguard Worker 
22*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
23*d9f75844SAndroid Build Coastguard Worker namespace test {
24*d9f75844SAndroid Build Coastguard Worker namespace {
25*d9f75844SAndroid Build Coastguard Worker 
WriteVideoToFile(const rtc::scoped_refptr<Video> & video,const std::string & file_name,int fps,bool isY4m)26*d9f75844SAndroid Build Coastguard Worker void WriteVideoToFile(const rtc::scoped_refptr<Video>& video,
27*d9f75844SAndroid Build Coastguard Worker                       const std::string& file_name,
28*d9f75844SAndroid Build Coastguard Worker                       int fps,
29*d9f75844SAndroid Build Coastguard Worker                       bool isY4m) {
30*d9f75844SAndroid Build Coastguard Worker   RTC_CHECK(video);
31*d9f75844SAndroid Build Coastguard Worker   FILE* output_file = fopen(file_name.c_str(), "wb");
32*d9f75844SAndroid Build Coastguard Worker   if (output_file == nullptr) {
33*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_ERROR) << "Could not open file for writing: " << file_name;
34*d9f75844SAndroid Build Coastguard Worker     return;
35*d9f75844SAndroid Build Coastguard Worker   }
36*d9f75844SAndroid Build Coastguard Worker 
37*d9f75844SAndroid Build Coastguard Worker   if (isY4m) {
38*d9f75844SAndroid Build Coastguard Worker     fprintf(output_file, "YUV4MPEG2 W%d H%d F%d:1 C420\n", video->width(),
39*d9f75844SAndroid Build Coastguard Worker             video->height(), fps);
40*d9f75844SAndroid Build Coastguard Worker   }
41*d9f75844SAndroid Build Coastguard Worker   for (size_t i = 0; i < video->number_of_frames(); ++i) {
42*d9f75844SAndroid Build Coastguard Worker     if (isY4m) {
43*d9f75844SAndroid Build Coastguard Worker       std::string frame = "FRAME\n";
44*d9f75844SAndroid Build Coastguard Worker       fwrite(frame.c_str(), 1, 6, output_file);
45*d9f75844SAndroid Build Coastguard Worker     }
46*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<I420BufferInterface> buffer = video->GetFrame(i);
47*d9f75844SAndroid Build Coastguard Worker     RTC_CHECK(buffer) << "Frame: " << i
48*d9f75844SAndroid Build Coastguard Worker                       << "\nWhile trying to create: " << file_name;
49*d9f75844SAndroid Build Coastguard Worker     const uint8_t* data_y = buffer->DataY();
50*d9f75844SAndroid Build Coastguard Worker     int stride = buffer->StrideY();
51*d9f75844SAndroid Build Coastguard Worker     for (int i = 0; i < video->height(); ++i) {
52*d9f75844SAndroid Build Coastguard Worker       fwrite(data_y + i * stride, /*size=*/1, stride, output_file);
53*d9f75844SAndroid Build Coastguard Worker     }
54*d9f75844SAndroid Build Coastguard Worker     const uint8_t* data_u = buffer->DataU();
55*d9f75844SAndroid Build Coastguard Worker     stride = buffer->StrideU();
56*d9f75844SAndroid Build Coastguard Worker     for (int i = 0; i < buffer->ChromaHeight(); ++i) {
57*d9f75844SAndroid Build Coastguard Worker       fwrite(data_u + i * stride, /*size=*/1, stride, output_file);
58*d9f75844SAndroid Build Coastguard Worker     }
59*d9f75844SAndroid Build Coastguard Worker     const uint8_t* data_v = buffer->DataV();
60*d9f75844SAndroid Build Coastguard Worker     stride = buffer->StrideV();
61*d9f75844SAndroid Build Coastguard Worker     for (int i = 0; i < buffer->ChromaHeight(); ++i) {
62*d9f75844SAndroid Build Coastguard Worker       fwrite(data_v + i * stride, /*size=*/1, stride, output_file);
63*d9f75844SAndroid Build Coastguard Worker     }
64*d9f75844SAndroid Build Coastguard Worker   }
65*d9f75844SAndroid Build Coastguard Worker   if (ferror(output_file) != 0) {
66*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_ERROR) << "Error writing to file " << file_name;
67*d9f75844SAndroid Build Coastguard Worker   }
68*d9f75844SAndroid Build Coastguard Worker   fclose(output_file);
69*d9f75844SAndroid Build Coastguard Worker }
70*d9f75844SAndroid Build Coastguard Worker 
71*d9f75844SAndroid Build Coastguard Worker }  // Anonymous namespace
72*d9f75844SAndroid Build Coastguard Worker 
WriteVideoToFile(const rtc::scoped_refptr<Video> & video,const std::string & file_name,int fps)73*d9f75844SAndroid Build Coastguard Worker void WriteVideoToFile(const rtc::scoped_refptr<Video>& video,
74*d9f75844SAndroid Build Coastguard Worker                       const std::string& file_name,
75*d9f75844SAndroid Build Coastguard Worker                       int fps) {
76*d9f75844SAndroid Build Coastguard Worker   WriteVideoToFile(video, file_name, fps,
77*d9f75844SAndroid Build Coastguard Worker                    /*isY4m=*/absl::EndsWith(file_name, ".y4m"));
78*d9f75844SAndroid Build Coastguard Worker }
79*d9f75844SAndroid Build Coastguard Worker 
WriteY4mVideoToFile(const rtc::scoped_refptr<Video> & video,const std::string & file_name,int fps)80*d9f75844SAndroid Build Coastguard Worker void WriteY4mVideoToFile(const rtc::scoped_refptr<Video>& video,
81*d9f75844SAndroid Build Coastguard Worker                          const std::string& file_name,
82*d9f75844SAndroid Build Coastguard Worker                          int fps) {
83*d9f75844SAndroid Build Coastguard Worker   WriteVideoToFile(video, file_name, fps, /*isY4m=*/true);
84*d9f75844SAndroid Build Coastguard Worker }
85*d9f75844SAndroid Build Coastguard Worker 
WriteYuvVideoToFile(const rtc::scoped_refptr<Video> & video,const std::string & file_name,int fps)86*d9f75844SAndroid Build Coastguard Worker void WriteYuvVideoToFile(const rtc::scoped_refptr<Video>& video,
87*d9f75844SAndroid Build Coastguard Worker                          const std::string& file_name,
88*d9f75844SAndroid Build Coastguard Worker                          int fps) {
89*d9f75844SAndroid Build Coastguard Worker   WriteVideoToFile(video, file_name, fps, /*isY4m=*/false);
90*d9f75844SAndroid Build Coastguard Worker }
91*d9f75844SAndroid Build Coastguard Worker 
92*d9f75844SAndroid Build Coastguard Worker }  // namespace test
93*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
94