xref: /aosp_15_r20/external/webrtc/rtc_tools/video_file_reader.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_reader.h"
12*d9f75844SAndroid Build Coastguard Worker 
13*d9f75844SAndroid Build Coastguard Worker #include <cstdio>
14*d9f75844SAndroid Build Coastguard Worker #include <string>
15*d9f75844SAndroid Build Coastguard Worker #include <vector>
16*d9f75844SAndroid Build Coastguard Worker 
17*d9f75844SAndroid Build Coastguard Worker #include "absl/strings/match.h"
18*d9f75844SAndroid Build Coastguard Worker #include "absl/types/optional.h"
19*d9f75844SAndroid Build Coastguard Worker #include "api/make_ref_counted.h"
20*d9f75844SAndroid Build Coastguard Worker #include "api/video/i420_buffer.h"
21*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
22*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
23*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/string_encode.h"
24*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/string_to_number.h"
25*d9f75844SAndroid Build Coastguard Worker 
26*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
27*d9f75844SAndroid Build Coastguard Worker namespace test {
28*d9f75844SAndroid Build Coastguard Worker 
29*d9f75844SAndroid Build Coastguard Worker namespace {
30*d9f75844SAndroid Build Coastguard Worker 
ReadBytes(uint8_t * dst,size_t n,FILE * file)31*d9f75844SAndroid Build Coastguard Worker bool ReadBytes(uint8_t* dst, size_t n, FILE* file) {
32*d9f75844SAndroid Build Coastguard Worker   return fread(reinterpret_cast<char*>(dst), /* size= */ 1, n, file) == n;
33*d9f75844SAndroid Build Coastguard Worker }
34*d9f75844SAndroid Build Coastguard Worker 
35*d9f75844SAndroid Build Coastguard Worker // Common base class for .yuv and .y4m files.
36*d9f75844SAndroid Build Coastguard Worker class VideoFile : public Video {
37*d9f75844SAndroid Build Coastguard Worker  public:
VideoFile(int width,int height,const std::vector<fpos_t> & frame_positions,FILE * file)38*d9f75844SAndroid Build Coastguard Worker   VideoFile(int width,
39*d9f75844SAndroid Build Coastguard Worker             int height,
40*d9f75844SAndroid Build Coastguard Worker             const std::vector<fpos_t>& frame_positions,
41*d9f75844SAndroid Build Coastguard Worker             FILE* file)
42*d9f75844SAndroid Build Coastguard Worker       : width_(width),
43*d9f75844SAndroid Build Coastguard Worker         height_(height),
44*d9f75844SAndroid Build Coastguard Worker         frame_positions_(frame_positions),
45*d9f75844SAndroid Build Coastguard Worker         file_(file) {}
46*d9f75844SAndroid Build Coastguard Worker 
~VideoFile()47*d9f75844SAndroid Build Coastguard Worker   ~VideoFile() override { fclose(file_); }
48*d9f75844SAndroid Build Coastguard Worker 
number_of_frames() const49*d9f75844SAndroid Build Coastguard Worker   size_t number_of_frames() const override { return frame_positions_.size(); }
width() const50*d9f75844SAndroid Build Coastguard Worker   int width() const override { return width_; }
height() const51*d9f75844SAndroid Build Coastguard Worker   int height() const override { return height_; }
52*d9f75844SAndroid Build Coastguard Worker 
GetFrame(size_t frame_index) const53*d9f75844SAndroid Build Coastguard Worker   rtc::scoped_refptr<I420BufferInterface> GetFrame(
54*d9f75844SAndroid Build Coastguard Worker       size_t frame_index) const override {
55*d9f75844SAndroid Build Coastguard Worker     RTC_CHECK_LT(frame_index, frame_positions_.size());
56*d9f75844SAndroid Build Coastguard Worker 
57*d9f75844SAndroid Build Coastguard Worker     fsetpos(file_, &frame_positions_[frame_index]);
58*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<I420Buffer> buffer = I420Buffer::Create(width_, height_);
59*d9f75844SAndroid Build Coastguard Worker 
60*d9f75844SAndroid Build Coastguard Worker     if (!ReadBytes(buffer->MutableDataY(), width_ * height_, file_) ||
61*d9f75844SAndroid Build Coastguard Worker         !ReadBytes(buffer->MutableDataU(),
62*d9f75844SAndroid Build Coastguard Worker                    buffer->ChromaWidth() * buffer->ChromaHeight(), file_) ||
63*d9f75844SAndroid Build Coastguard Worker         !ReadBytes(buffer->MutableDataV(),
64*d9f75844SAndroid Build Coastguard Worker                    buffer->ChromaWidth() * buffer->ChromaHeight(), file_)) {
65*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_ERROR) << "Could not read YUV data for frame " << frame_index;
66*d9f75844SAndroid Build Coastguard Worker       return nullptr;
67*d9f75844SAndroid Build Coastguard Worker     }
68*d9f75844SAndroid Build Coastguard Worker 
69*d9f75844SAndroid Build Coastguard Worker     return buffer;
70*d9f75844SAndroid Build Coastguard Worker   }
71*d9f75844SAndroid Build Coastguard Worker 
72*d9f75844SAndroid Build Coastguard Worker  private:
73*d9f75844SAndroid Build Coastguard Worker   const int width_;
74*d9f75844SAndroid Build Coastguard Worker   const int height_;
75*d9f75844SAndroid Build Coastguard Worker   const std::vector<fpos_t> frame_positions_;
76*d9f75844SAndroid Build Coastguard Worker   FILE* const file_;
77*d9f75844SAndroid Build Coastguard Worker };
78*d9f75844SAndroid Build Coastguard Worker 
79*d9f75844SAndroid Build Coastguard Worker }  // namespace
80*d9f75844SAndroid Build Coastguard Worker 
Iterator(const rtc::scoped_refptr<const Video> & video,size_t index)81*d9f75844SAndroid Build Coastguard Worker Video::Iterator::Iterator(const rtc::scoped_refptr<const Video>& video,
82*d9f75844SAndroid Build Coastguard Worker                           size_t index)
83*d9f75844SAndroid Build Coastguard Worker     : video_(video), index_(index) {}
84*d9f75844SAndroid Build Coastguard Worker 
85*d9f75844SAndroid Build Coastguard Worker Video::Iterator::Iterator(const Video::Iterator& other) = default;
86*d9f75844SAndroid Build Coastguard Worker Video::Iterator::Iterator(Video::Iterator&& other) = default;
87*d9f75844SAndroid Build Coastguard Worker Video::Iterator& Video::Iterator::operator=(Video::Iterator&&) = default;
88*d9f75844SAndroid Build Coastguard Worker Video::Iterator& Video::Iterator::operator=(const Video::Iterator&) = default;
89*d9f75844SAndroid Build Coastguard Worker Video::Iterator::~Iterator() = default;
90*d9f75844SAndroid Build Coastguard Worker 
operator *() const91*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<I420BufferInterface> Video::Iterator::operator*() const {
92*d9f75844SAndroid Build Coastguard Worker   return video_->GetFrame(index_);
93*d9f75844SAndroid Build Coastguard Worker }
operator ==(const Video::Iterator & other) const94*d9f75844SAndroid Build Coastguard Worker bool Video::Iterator::operator==(const Video::Iterator& other) const {
95*d9f75844SAndroid Build Coastguard Worker   return index_ == other.index_;
96*d9f75844SAndroid Build Coastguard Worker }
operator !=(const Video::Iterator & other) const97*d9f75844SAndroid Build Coastguard Worker bool Video::Iterator::operator!=(const Video::Iterator& other) const {
98*d9f75844SAndroid Build Coastguard Worker   return !(*this == other);
99*d9f75844SAndroid Build Coastguard Worker }
100*d9f75844SAndroid Build Coastguard Worker 
operator ++(int)101*d9f75844SAndroid Build Coastguard Worker Video::Iterator Video::Iterator::operator++(int) {
102*d9f75844SAndroid Build Coastguard Worker   const Iterator copy = *this;
103*d9f75844SAndroid Build Coastguard Worker   ++*this;
104*d9f75844SAndroid Build Coastguard Worker   return copy;
105*d9f75844SAndroid Build Coastguard Worker }
106*d9f75844SAndroid Build Coastguard Worker 
operator ++()107*d9f75844SAndroid Build Coastguard Worker Video::Iterator& Video::Iterator::operator++() {
108*d9f75844SAndroid Build Coastguard Worker   ++index_;
109*d9f75844SAndroid Build Coastguard Worker   return *this;
110*d9f75844SAndroid Build Coastguard Worker }
111*d9f75844SAndroid Build Coastguard Worker 
begin() const112*d9f75844SAndroid Build Coastguard Worker Video::Iterator Video::begin() const {
113*d9f75844SAndroid Build Coastguard Worker   return Iterator(rtc::scoped_refptr<const Video>(this), 0);
114*d9f75844SAndroid Build Coastguard Worker }
115*d9f75844SAndroid Build Coastguard Worker 
end() const116*d9f75844SAndroid Build Coastguard Worker Video::Iterator Video::end() const {
117*d9f75844SAndroid Build Coastguard Worker   return Iterator(rtc::scoped_refptr<const Video>(this), number_of_frames());
118*d9f75844SAndroid Build Coastguard Worker }
119*d9f75844SAndroid Build Coastguard Worker 
OpenY4mFile(const std::string & file_name)120*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<Video> OpenY4mFile(const std::string& file_name) {
121*d9f75844SAndroid Build Coastguard Worker   FILE* file = fopen(file_name.c_str(), "rb");
122*d9f75844SAndroid Build Coastguard Worker   if (file == nullptr) {
123*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_ERROR) << "Could not open input file for reading: " << file_name;
124*d9f75844SAndroid Build Coastguard Worker     return nullptr;
125*d9f75844SAndroid Build Coastguard Worker   }
126*d9f75844SAndroid Build Coastguard Worker 
127*d9f75844SAndroid Build Coastguard Worker   int parse_file_header_result = -1;
128*d9f75844SAndroid Build Coastguard Worker   if (fscanf(file, "YUV4MPEG2 %n", &parse_file_header_result) != 0 ||
129*d9f75844SAndroid Build Coastguard Worker       parse_file_header_result == -1) {
130*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_ERROR) << "File " << file_name
131*d9f75844SAndroid Build Coastguard Worker                       << " does not start with YUV4MPEG2 header";
132*d9f75844SAndroid Build Coastguard Worker     return nullptr;
133*d9f75844SAndroid Build Coastguard Worker   }
134*d9f75844SAndroid Build Coastguard Worker 
135*d9f75844SAndroid Build Coastguard Worker   std::string header_line;
136*d9f75844SAndroid Build Coastguard Worker   while (true) {
137*d9f75844SAndroid Build Coastguard Worker     const int c = fgetc(file);
138*d9f75844SAndroid Build Coastguard Worker     if (c == EOF) {
139*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_ERROR) << "Could not read header line";
140*d9f75844SAndroid Build Coastguard Worker       return nullptr;
141*d9f75844SAndroid Build Coastguard Worker     }
142*d9f75844SAndroid Build Coastguard Worker     if (c == '\n')
143*d9f75844SAndroid Build Coastguard Worker       break;
144*d9f75844SAndroid Build Coastguard Worker     header_line.push_back(static_cast<char>(c));
145*d9f75844SAndroid Build Coastguard Worker   }
146*d9f75844SAndroid Build Coastguard Worker 
147*d9f75844SAndroid Build Coastguard Worker   absl::optional<int> width;
148*d9f75844SAndroid Build Coastguard Worker   absl::optional<int> height;
149*d9f75844SAndroid Build Coastguard Worker   absl::optional<float> fps;
150*d9f75844SAndroid Build Coastguard Worker 
151*d9f75844SAndroid Build Coastguard Worker   std::vector<std::string> fields;
152*d9f75844SAndroid Build Coastguard Worker   rtc::tokenize(header_line, ' ', &fields);
153*d9f75844SAndroid Build Coastguard Worker   for (const std::string& field : fields) {
154*d9f75844SAndroid Build Coastguard Worker     const char prefix = field.front();
155*d9f75844SAndroid Build Coastguard Worker     const std::string suffix = field.substr(1);
156*d9f75844SAndroid Build Coastguard Worker     switch (prefix) {
157*d9f75844SAndroid Build Coastguard Worker       case 'W':
158*d9f75844SAndroid Build Coastguard Worker         width = rtc::StringToNumber<int>(suffix);
159*d9f75844SAndroid Build Coastguard Worker         break;
160*d9f75844SAndroid Build Coastguard Worker       case 'H':
161*d9f75844SAndroid Build Coastguard Worker         height = rtc::StringToNumber<int>(suffix);
162*d9f75844SAndroid Build Coastguard Worker         break;
163*d9f75844SAndroid Build Coastguard Worker       case 'C':
164*d9f75844SAndroid Build Coastguard Worker         if (suffix != "420" && suffix != "420mpeg2") {
165*d9f75844SAndroid Build Coastguard Worker           RTC_LOG(LS_ERROR)
166*d9f75844SAndroid Build Coastguard Worker               << "Does not support any other color space than I420 or "
167*d9f75844SAndroid Build Coastguard Worker                  "420mpeg2, but was: "
168*d9f75844SAndroid Build Coastguard Worker               << suffix;
169*d9f75844SAndroid Build Coastguard Worker           return nullptr;
170*d9f75844SAndroid Build Coastguard Worker         }
171*d9f75844SAndroid Build Coastguard Worker         break;
172*d9f75844SAndroid Build Coastguard Worker       case 'F': {
173*d9f75844SAndroid Build Coastguard Worker         std::vector<std::string> fraction;
174*d9f75844SAndroid Build Coastguard Worker         rtc::tokenize(suffix, ':', &fraction);
175*d9f75844SAndroid Build Coastguard Worker         if (fraction.size() == 2) {
176*d9f75844SAndroid Build Coastguard Worker           const absl::optional<int> numerator =
177*d9f75844SAndroid Build Coastguard Worker               rtc::StringToNumber<int>(fraction[0]);
178*d9f75844SAndroid Build Coastguard Worker           const absl::optional<int> denominator =
179*d9f75844SAndroid Build Coastguard Worker               rtc::StringToNumber<int>(fraction[1]);
180*d9f75844SAndroid Build Coastguard Worker           if (numerator && denominator && *denominator != 0)
181*d9f75844SAndroid Build Coastguard Worker             fps = *numerator / static_cast<float>(*denominator);
182*d9f75844SAndroid Build Coastguard Worker           break;
183*d9f75844SAndroid Build Coastguard Worker         }
184*d9f75844SAndroid Build Coastguard Worker       }
185*d9f75844SAndroid Build Coastguard Worker     }
186*d9f75844SAndroid Build Coastguard Worker   }
187*d9f75844SAndroid Build Coastguard Worker   if (!width || !height) {
188*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_ERROR) << "Could not find width and height in file header";
189*d9f75844SAndroid Build Coastguard Worker     return nullptr;
190*d9f75844SAndroid Build Coastguard Worker   }
191*d9f75844SAndroid Build Coastguard Worker   if (!fps) {
192*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_ERROR) << "Could not find fps in file header";
193*d9f75844SAndroid Build Coastguard Worker     return nullptr;
194*d9f75844SAndroid Build Coastguard Worker   }
195*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_INFO) << "Video has resolution: " << *width << "x" << *height
196*d9f75844SAndroid Build Coastguard Worker                    << " " << *fps << " fps";
197*d9f75844SAndroid Build Coastguard Worker   if (*width % 2 != 0 || *height % 2 != 0) {
198*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_ERROR)
199*d9f75844SAndroid Build Coastguard Worker         << "Only supports even width/height so that chroma size is a "
200*d9f75844SAndroid Build Coastguard Worker            "whole number.";
201*d9f75844SAndroid Build Coastguard Worker     return nullptr;
202*d9f75844SAndroid Build Coastguard Worker   }
203*d9f75844SAndroid Build Coastguard Worker 
204*d9f75844SAndroid Build Coastguard Worker   const int i420_frame_size = 3 * *width * *height / 2;
205*d9f75844SAndroid Build Coastguard Worker   std::vector<fpos_t> frame_positions;
206*d9f75844SAndroid Build Coastguard Worker   while (true) {
207*d9f75844SAndroid Build Coastguard Worker     std::array<char, 6> read_buffer;
208*d9f75844SAndroid Build Coastguard Worker     if (fread(read_buffer.data(), 1, read_buffer.size(), file) <
209*d9f75844SAndroid Build Coastguard Worker             read_buffer.size() ||
210*d9f75844SAndroid Build Coastguard Worker         memcmp(read_buffer.data(), "FRAME\n", read_buffer.size()) != 0) {
211*d9f75844SAndroid Build Coastguard Worker       if (!feof(file)) {
212*d9f75844SAndroid Build Coastguard Worker         RTC_LOG(LS_ERROR) << "Did not find FRAME header, ignoring rest of file";
213*d9f75844SAndroid Build Coastguard Worker       }
214*d9f75844SAndroid Build Coastguard Worker       break;
215*d9f75844SAndroid Build Coastguard Worker     }
216*d9f75844SAndroid Build Coastguard Worker     fpos_t pos;
217*d9f75844SAndroid Build Coastguard Worker     fgetpos(file, &pos);
218*d9f75844SAndroid Build Coastguard Worker     frame_positions.push_back(pos);
219*d9f75844SAndroid Build Coastguard Worker     // Skip over YUV pixel data.
220*d9f75844SAndroid Build Coastguard Worker     fseek(file, i420_frame_size, SEEK_CUR);
221*d9f75844SAndroid Build Coastguard Worker   }
222*d9f75844SAndroid Build Coastguard Worker   if (frame_positions.empty()) {
223*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_ERROR) << "Could not find any frames in the file";
224*d9f75844SAndroid Build Coastguard Worker     return nullptr;
225*d9f75844SAndroid Build Coastguard Worker   }
226*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_INFO) << "Video has " << frame_positions.size() << " frames";
227*d9f75844SAndroid Build Coastguard Worker 
228*d9f75844SAndroid Build Coastguard Worker   return rtc::make_ref_counted<VideoFile>(*width, *height, frame_positions,
229*d9f75844SAndroid Build Coastguard Worker                                           file);
230*d9f75844SAndroid Build Coastguard Worker }
231*d9f75844SAndroid Build Coastguard Worker 
OpenYuvFile(const std::string & file_name,int width,int height)232*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<Video> OpenYuvFile(const std::string& file_name,
233*d9f75844SAndroid Build Coastguard Worker                                       int width,
234*d9f75844SAndroid Build Coastguard Worker                                       int height) {
235*d9f75844SAndroid Build Coastguard Worker   FILE* file = fopen(file_name.c_str(), "rb");
236*d9f75844SAndroid Build Coastguard Worker   if (file == nullptr) {
237*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_ERROR) << "Could not open input file for reading: " << file_name;
238*d9f75844SAndroid Build Coastguard Worker     return nullptr;
239*d9f75844SAndroid Build Coastguard Worker   }
240*d9f75844SAndroid Build Coastguard Worker 
241*d9f75844SAndroid Build Coastguard Worker   if (width % 2 != 0 || height % 2 != 0) {
242*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_ERROR)
243*d9f75844SAndroid Build Coastguard Worker         << "Only supports even width/height so that chroma size is a "
244*d9f75844SAndroid Build Coastguard Worker            "whole number.";
245*d9f75844SAndroid Build Coastguard Worker     return nullptr;
246*d9f75844SAndroid Build Coastguard Worker   }
247*d9f75844SAndroid Build Coastguard Worker 
248*d9f75844SAndroid Build Coastguard Worker   // Seek to end of file.
249*d9f75844SAndroid Build Coastguard Worker   fseek(file, 0, SEEK_END);
250*d9f75844SAndroid Build Coastguard Worker   const size_t file_size = ftell(file);
251*d9f75844SAndroid Build Coastguard Worker   // Seek back to beginning of file.
252*d9f75844SAndroid Build Coastguard Worker   fseek(file, 0, SEEK_SET);
253*d9f75844SAndroid Build Coastguard Worker 
254*d9f75844SAndroid Build Coastguard Worker   const int i420_frame_size = 3 * width * height / 2;
255*d9f75844SAndroid Build Coastguard Worker   const size_t number_of_frames = file_size / i420_frame_size;
256*d9f75844SAndroid Build Coastguard Worker 
257*d9f75844SAndroid Build Coastguard Worker   std::vector<fpos_t> frame_positions;
258*d9f75844SAndroid Build Coastguard Worker   for (size_t i = 0; i < number_of_frames; ++i) {
259*d9f75844SAndroid Build Coastguard Worker     fpos_t pos;
260*d9f75844SAndroid Build Coastguard Worker     fgetpos(file, &pos);
261*d9f75844SAndroid Build Coastguard Worker     frame_positions.push_back(pos);
262*d9f75844SAndroid Build Coastguard Worker     fseek(file, i420_frame_size, SEEK_CUR);
263*d9f75844SAndroid Build Coastguard Worker   }
264*d9f75844SAndroid Build Coastguard Worker   if (frame_positions.empty()) {
265*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_ERROR) << "Could not find any frames in the file";
266*d9f75844SAndroid Build Coastguard Worker     return nullptr;
267*d9f75844SAndroid Build Coastguard Worker   }
268*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_INFO) << "Video has " << frame_positions.size() << " frames";
269*d9f75844SAndroid Build Coastguard Worker 
270*d9f75844SAndroid Build Coastguard Worker   return rtc::make_ref_counted<VideoFile>(width, height, frame_positions, file);
271*d9f75844SAndroid Build Coastguard Worker }
272*d9f75844SAndroid Build Coastguard Worker 
OpenYuvOrY4mFile(const std::string & file_name,int width,int height)273*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<Video> OpenYuvOrY4mFile(const std::string& file_name,
274*d9f75844SAndroid Build Coastguard Worker                                            int width,
275*d9f75844SAndroid Build Coastguard Worker                                            int height) {
276*d9f75844SAndroid Build Coastguard Worker   if (absl::EndsWith(file_name, ".yuv"))
277*d9f75844SAndroid Build Coastguard Worker     return OpenYuvFile(file_name, width, height);
278*d9f75844SAndroid Build Coastguard Worker   if (absl::EndsWith(file_name, ".y4m"))
279*d9f75844SAndroid Build Coastguard Worker     return OpenY4mFile(file_name);
280*d9f75844SAndroid Build Coastguard Worker 
281*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_ERROR) << "Video file does not end in either .yuv or .y4m: "
282*d9f75844SAndroid Build Coastguard Worker                     << file_name;
283*d9f75844SAndroid Build Coastguard Worker 
284*d9f75844SAndroid Build Coastguard Worker   return nullptr;
285*d9f75844SAndroid Build Coastguard Worker }
286*d9f75844SAndroid Build Coastguard Worker 
287*d9f75844SAndroid Build Coastguard Worker }  // namespace test
288*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
289