blob: 72fb9b5188eccbb35fe6502d4adedc11d709bb75 [file] [log] [blame]
Artem Titov645df9e2019-01-14 13:21:591/*
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 <stdio.h>
Jonas Olssona4d87372019-07-05 17:08:3312
Artem Titov645df9e2019-01-14 13:21:5913#include <string>
14
Mirko Bonadeid9708072019-01-25 19:26:4815#include "api/scoped_refptr.h"
Artem Titov645df9e2019-01-14 13:21:5916#include "api/video/i420_buffer.h"
Sergey Silkin1985b5a2022-12-06 14:36:2117#include "common_video/libyuv/include/webrtc_libyuv.h"
Sergey Silkin18454b72022-02-18 10:54:2818#include "rtc_base/logging.h"
Artem Titovb984c072022-10-10 13:04:3019#include "rtc_base/strings/string_builder.h"
Artem Titov645df9e2019-01-14 13:21:5920#include "test/testsupport/file_utils.h"
21#include "test/testsupport/frame_reader.h"
22
23namespace webrtc {
24namespace test {
25namespace {
Sergey Silkin1985b5a2022-12-06 14:36:2126constexpr int kFrameHeaderSize = 6; // "FRAME\n"
Artem Titov645df9e2019-01-14 13:21:5927} // namespace
28
Sergey Silkin1985b5a2022-12-06 14:36:2129void ParseY4mHeader(std::string filepath,
30 Resolution* resolution,
31 int* header_size) {
32 FILE* file = fopen(filepath.c_str(), "r");
33 RTC_CHECK(file != NULL) << "Cannot open " << filepath;
34
35 // Length of Y4M header is technically unlimited due to the comment tag 'X'.
36 char h[1024];
37 RTC_CHECK(fgets(h, sizeof(h), file) != NULL)
38 << "File " << filepath << " is too small";
39 fclose(file);
40
41 RTC_CHECK(sscanf(h, "YUV4MPEG2 W%d H%d", &resolution->width,
42 &resolution->height) == 2)
43 << filepath << " is not a valid Y4M file";
44
45 RTC_CHECK_GT(resolution->width, 0) << "Width must be positive";
46 RTC_CHECK_GT(resolution->height, 0) << "Height must be positive";
47
48 *header_size = strcspn(h, "\n") + 1;
49 RTC_CHECK(static_cast<unsigned>(*header_size) < sizeof(h))
50 << filepath << " has unexpectedly large header";
Artem Titov645df9e2019-01-14 13:21:5951}
52
Sergey Silkin1985b5a2022-12-06 14:36:2153Y4mFrameReaderImpl::Y4mFrameReaderImpl(std::string filepath,
54 RepeatMode repeat_mode)
55 : YuvFrameReaderImpl(filepath, Resolution(), repeat_mode) {}
Sergey Silkin18454b72022-02-18 10:54:2856
Sergey Silkin1985b5a2022-12-06 14:36:2157void Y4mFrameReaderImpl::Init() {
58 file_ = fopen(filepath_.c_str(), "rb");
59 RTC_CHECK(file_ != nullptr) << "Cannot open " << filepath_;
Sergey Silkin18454b72022-02-18 10:54:2860
Sergey Silkin1985b5a2022-12-06 14:36:2161 ParseY4mHeader(filepath_, &resolution_, &header_size_bytes_);
62 frame_size_bytes_ =
63 CalcBufferSize(VideoType::kI420, resolution_.width, resolution_.height);
64 frame_size_bytes_ += kFrameHeaderSize;
65
66 size_t file_size_bytes = GetFileSize(filepath_);
67 RTC_CHECK_GT(file_size_bytes, 0u) << "File " << filepath_ << " is empty";
68 RTC_CHECK_GT(file_size_bytes, header_size_bytes_)
69 << "File " << filepath_ << " is too small";
70
71 num_frames_ = static_cast<int>((file_size_bytes - header_size_bytes_) /
72 frame_size_bytes_);
73 RTC_CHECK_GT(num_frames_, 0u) << "File " << filepath_ << " is too small";
74 header_size_bytes_ += kFrameHeaderSize;
Artem Titov645df9e2019-01-14 13:21:5975}
76
Sergey Silkin1985b5a2022-12-06 14:36:2177std::unique_ptr<FrameReader> CreateY4mFrameReader(std::string filepath) {
78 return CreateY4mFrameReader(filepath,
79 YuvFrameReaderImpl::RepeatMode::kSingle);
80}
81
82std::unique_ptr<FrameReader> CreateY4mFrameReader(
83 std::string filepath,
84 YuvFrameReaderImpl::RepeatMode repeat_mode) {
85 Y4mFrameReaderImpl* frame_reader =
86 new Y4mFrameReaderImpl(filepath, repeat_mode);
87 frame_reader->Init();
88 return std::unique_ptr<FrameReader>(frame_reader);
Artem Titov645df9e2019-01-14 13:21:5989}
90
91} // namespace test
92} // namespace webrtc