blob: b9ea2d0c4678d6b055df78ed49f182fe5eec3e73 [file] [log] [blame]
/*
* Copyright (c) 2017 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 <stdint.h>
#include <stdio.h>
#include <memory>
#include <string>
#include "api/scoped_refptr.h"
#include "api/video/i420_buffer.h"
#include "api/video/video_frame_buffer.h"
#include "test/gtest.h"
#include "test/testsupport/file_utils.h"
#include "test/testsupport/frame_reader.h"
namespace webrtc {
namespace test {
namespace {
using Ratio = FrameReader::Ratio;
using RepeatMode = YuvFrameReaderImpl::RepeatMode;
constexpr Resolution kResolution({.width = 1, .height = 1});
constexpr char kFrameContent[3][3] = {{0, 1, 2}, {1, 2, 3}, {2, 3, 4}};
constexpr int kNumFrames = sizeof(kFrameContent) / sizeof(kFrameContent[0]);
} // namespace
class YuvFrameReaderTest : public ::testing::Test {
protected:
YuvFrameReaderTest() = default;
~YuvFrameReaderTest() override = default;
void SetUp() override {
filepath_ = webrtc::test::TempFilename(webrtc::test::OutputPath(),
"yuv_frame_reader_unittest");
FILE* file = fopen(filepath_.c_str(), "wb");
fwrite(kFrameContent, 1, sizeof(kFrameContent), file);
fclose(file);
reader_ = CreateYuvFrameReader(filepath_, kResolution);
}
void TearDown() override { remove(filepath_.c_str()); }
std::string filepath_;
std::unique_ptr<FrameReader> reader_;
};
TEST_F(YuvFrameReaderTest, num_frames) {
EXPECT_EQ(kNumFrames, reader_->num_frames());
}
TEST_F(YuvFrameReaderTest, PullFrame_frameContent) {
rtc::scoped_refptr<I420BufferInterface> buffer = reader_->PullFrame();
EXPECT_EQ(kFrameContent[0][0], *buffer->DataY());
EXPECT_EQ(kFrameContent[0][1], *buffer->DataU());
EXPECT_EQ(kFrameContent[0][2], *buffer->DataV());
}
TEST_F(YuvFrameReaderTest, ReadFrame_randomOrder) {
std::vector<int> expected_frames = {2, 0, 1};
std::vector<int> actual_frames;
for (int frame_num : expected_frames) {
rtc::scoped_refptr<I420BufferInterface> buffer =
reader_->ReadFrame(frame_num);
actual_frames.push_back(*buffer->DataY());
}
EXPECT_EQ(expected_frames, actual_frames);
}
TEST_F(YuvFrameReaderTest, PullFrame_scale) {
rtc::scoped_refptr<I420BufferInterface> buffer = reader_->PullFrame(
/*pulled_frame_num=*/nullptr, Resolution({.width = 2, .height = 2}),
FrameReader::kNoScale);
EXPECT_EQ(2, buffer->width());
EXPECT_EQ(2, buffer->height());
}
class YuvFrameReaderRepeatModeTest
: public YuvFrameReaderTest,
public ::testing::WithParamInterface<
std::tuple<RepeatMode, std::vector<int>>> {};
TEST_P(YuvFrameReaderRepeatModeTest, PullFrame) {
RepeatMode mode = std::get<0>(GetParam());
std::vector<int> expected_frames = std::get<1>(GetParam());
reader_ = CreateYuvFrameReader(filepath_, kResolution, mode);
std::vector<int> read_frames;
for (size_t i = 0; i < expected_frames.size(); ++i) {
rtc::scoped_refptr<I420BufferInterface> buffer = reader_->PullFrame();
read_frames.push_back(*buffer->DataY());
}
EXPECT_EQ(expected_frames, read_frames);
}
INSTANTIATE_TEST_SUITE_P(
YuvFrameReaderTest,
YuvFrameReaderRepeatModeTest,
::testing::ValuesIn(
{std::make_tuple(RepeatMode::kSingle, std::vector<int>{0, 1, 2}),
std::make_tuple(RepeatMode::kRepeat,
std::vector<int>{0, 1, 2, 0, 1, 2}),
std::make_tuple(RepeatMode::kPingPong,
std::vector<int>{0, 1, 2, 1, 0, 1, 2})}));
class YuvFrameReaderFramerateScaleTest
: public YuvFrameReaderTest,
public ::testing::WithParamInterface<
std::tuple<Ratio, std::vector<int>>> {};
TEST_P(YuvFrameReaderFramerateScaleTest, PullFrame) {
Ratio framerate_scale = std::get<0>(GetParam());
std::vector<int> expected_frames = std::get<1>(GetParam());
std::vector<int> actual_frames;
for (size_t i = 0; i < expected_frames.size(); ++i) {
int pulled_frame;
rtc::scoped_refptr<I420BufferInterface> buffer =
reader_->PullFrame(&pulled_frame, kResolution, framerate_scale);
actual_frames.push_back(pulled_frame);
}
EXPECT_EQ(expected_frames, actual_frames);
}
INSTANTIATE_TEST_SUITE_P(YuvFrameReaderTest,
YuvFrameReaderFramerateScaleTest,
::testing::ValuesIn({
std::make_tuple(Ratio({.num = 1, .den = 2}),
std::vector<int>{0, 2, 4}),
std::make_tuple(Ratio({.num = 2, .den = 3}),
std::vector<int>{0, 1, 3, 4, 6}),
std::make_tuple(Ratio({.num = 2, .den = 1}),
std::vector<int>{0, 0, 1, 1}),
}));
} // namespace test
} // namespace webrtc