/* * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include #include #include "api/scoped_refptr.h" #include "api/video/i420_buffer.h" #include "common_video/libyuv/include/webrtc_libyuv.h" #include "rtc_base/logging.h" #include "rtc_base/strings/string_builder.h" #include "test/testsupport/file_utils.h" #include "test/testsupport/frame_reader.h" namespace webrtc { namespace test { namespace { constexpr int kFrameHeaderSize = 6; // "FRAME\n" } // namespace void ParseY4mHeader(std::string filepath, Resolution* resolution, int* header_size) { FILE* file = fopen(filepath.c_str(), "r"); RTC_CHECK(file != NULL) << "Cannot open " << filepath; // Length of Y4M header is technically unlimited due to the comment tag 'X'. char h[1024]; RTC_CHECK(fgets(h, sizeof(h), file) != NULL) << "File " << filepath << " is too small"; fclose(file); RTC_CHECK(sscanf(h, "YUV4MPEG2 W%d H%d", &resolution->width, &resolution->height) == 2) << filepath << " is not a valid Y4M file"; RTC_CHECK_GT(resolution->width, 0) << "Width must be positive"; RTC_CHECK_GT(resolution->height, 0) << "Height must be positive"; *header_size = strcspn(h, "\n") + 1; RTC_CHECK(static_cast(*header_size) < sizeof(h)) << filepath << " has unexpectedly large header"; } Y4mFrameReaderImpl::Y4mFrameReaderImpl(std::string filepath, RepeatMode repeat_mode) : YuvFrameReaderImpl(filepath, Resolution(), repeat_mode) {} void Y4mFrameReaderImpl::Init() { file_ = fopen(filepath_.c_str(), "rb"); RTC_CHECK(file_ != nullptr) << "Cannot open " << filepath_; ParseY4mHeader(filepath_, &resolution_, &header_size_bytes_); frame_size_bytes_ = CalcBufferSize(VideoType::kI420, resolution_.width, resolution_.height); frame_size_bytes_ += kFrameHeaderSize; size_t file_size_bytes = GetFileSize(filepath_); RTC_CHECK_GT(file_size_bytes, 0u) << "File " << filepath_ << " is empty"; RTC_CHECK_GT(file_size_bytes, header_size_bytes_) << "File " << filepath_ << " is too small"; num_frames_ = static_cast((file_size_bytes - header_size_bytes_) / frame_size_bytes_); RTC_CHECK_GT(num_frames_, 0u) << "File " << filepath_ << " is too small"; header_size_bytes_ += kFrameHeaderSize; } std::unique_ptr CreateY4mFrameReader(std::string filepath) { return CreateY4mFrameReader(filepath, YuvFrameReaderImpl::RepeatMode::kSingle); } std::unique_ptr CreateY4mFrameReader( std::string filepath, YuvFrameReaderImpl::RepeatMode repeat_mode) { Y4mFrameReaderImpl* frame_reader = new Y4mFrameReaderImpl(filepath, repeat_mode); frame_reader->Init(); return std::unique_ptr(frame_reader); } } // namespace test } // namespace webrtc