Artem Titov | 645df9e | 2019-01-14 13:21:59 | [diff] [blame] | 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 <stdio.h> |
Jonas Olsson | a4d8737 | 2019-07-05 17:08:33 | [diff] [blame] | 12 | |
Artem Titov | 645df9e | 2019-01-14 13:21:59 | [diff] [blame] | 13 | #include <string> |
| 14 | |
Mirko Bonadei | d970807 | 2019-01-25 19:26:48 | [diff] [blame] | 15 | #include "api/scoped_refptr.h" |
Artem Titov | 645df9e | 2019-01-14 13:21:59 | [diff] [blame] | 16 | #include "api/video/i420_buffer.h" |
Sergey Silkin | 1985b5a | 2022-12-06 14:36:21 | [diff] [blame] | 17 | #include "common_video/libyuv/include/webrtc_libyuv.h" |
Sergey Silkin | 18454b7 | 2022-02-18 10:54:28 | [diff] [blame] | 18 | #include "rtc_base/logging.h" |
Artem Titov | b984c07 | 2022-10-10 13:04:30 | [diff] [blame] | 19 | #include "rtc_base/strings/string_builder.h" |
Artem Titov | 645df9e | 2019-01-14 13:21:59 | [diff] [blame] | 20 | #include "test/testsupport/file_utils.h" |
| 21 | #include "test/testsupport/frame_reader.h" |
| 22 | |
| 23 | namespace webrtc { |
| 24 | namespace test { |
| 25 | namespace { |
Sergey Silkin | 1985b5a | 2022-12-06 14:36:21 | [diff] [blame] | 26 | constexpr int kFrameHeaderSize = 6; // "FRAME\n" |
Artem Titov | 645df9e | 2019-01-14 13:21:59 | [diff] [blame] | 27 | } // namespace |
| 28 | |
Sergey Silkin | 1985b5a | 2022-12-06 14:36:21 | [diff] [blame] | 29 | void 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 Titov | 645df9e | 2019-01-14 13:21:59 | [diff] [blame] | 51 | } |
| 52 | |
Sergey Silkin | 1985b5a | 2022-12-06 14:36:21 | [diff] [blame] | 53 | Y4mFrameReaderImpl::Y4mFrameReaderImpl(std::string filepath, |
| 54 | RepeatMode repeat_mode) |
| 55 | : YuvFrameReaderImpl(filepath, Resolution(), repeat_mode) {} |
Sergey Silkin | 18454b7 | 2022-02-18 10:54:28 | [diff] [blame] | 56 | |
Sergey Silkin | 1985b5a | 2022-12-06 14:36:21 | [diff] [blame] | 57 | void Y4mFrameReaderImpl::Init() { |
| 58 | file_ = fopen(filepath_.c_str(), "rb"); |
| 59 | RTC_CHECK(file_ != nullptr) << "Cannot open " << filepath_; |
Sergey Silkin | 18454b7 | 2022-02-18 10:54:28 | [diff] [blame] | 60 | |
Sergey Silkin | 1985b5a | 2022-12-06 14:36:21 | [diff] [blame] | 61 | 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 Titov | 645df9e | 2019-01-14 13:21:59 | [diff] [blame] | 75 | } |
| 76 | |
Sergey Silkin | 1985b5a | 2022-12-06 14:36:21 | [diff] [blame] | 77 | std::unique_ptr<FrameReader> CreateY4mFrameReader(std::string filepath) { |
| 78 | return CreateY4mFrameReader(filepath, |
| 79 | YuvFrameReaderImpl::RepeatMode::kSingle); |
| 80 | } |
| 81 | |
| 82 | std::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 Titov | 645df9e | 2019-01-14 13:21:59 | [diff] [blame] | 89 | } |
| 90 | |
| 91 | } // namespace test |
| 92 | } // namespace webrtc |