diff options
Diffstat (limited to 'third_party/libwebrtc/test/testsupport/y4m_frame_reader.cc')
-rw-r--r-- | third_party/libwebrtc/test/testsupport/y4m_frame_reader.cc | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/third_party/libwebrtc/test/testsupport/y4m_frame_reader.cc b/third_party/libwebrtc/test/testsupport/y4m_frame_reader.cc new file mode 100644 index 0000000000..72fb9b5188 --- /dev/null +++ b/third_party/libwebrtc/test/testsupport/y4m_frame_reader.cc @@ -0,0 +1,92 @@ +/* + * 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 <stdio.h> + +#include <string> + +#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<unsigned>(*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<int>((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<FrameReader> CreateY4mFrameReader(std::string filepath) { + return CreateY4mFrameReader(filepath, + YuvFrameReaderImpl::RepeatMode::kSingle); +} + +std::unique_ptr<FrameReader> CreateY4mFrameReader( + std::string filepath, + YuvFrameReaderImpl::RepeatMode repeat_mode) { + Y4mFrameReaderImpl* frame_reader = + new Y4mFrameReaderImpl(filepath, repeat_mode); + frame_reader->Init(); + return std::unique_ptr<FrameReader>(frame_reader); +} + +} // namespace test +} // namespace webrtc |