Fix ping-pong mode on single frame sequences
Bug: webrtc:14852 Change-Id: Icc1226460dd8d09aa26edd65b89ef5b38debb31f Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/324285 Commit-Queue: Sergey Silkin <ssilkin@webrtc.org> Reviewed-by: Erik Språng <sprang@webrtc.org> Cr-Commit-Position: refs/heads/main@{#40988}
This commit is contained in:
parent
8005d5613e
commit
8c16f1f49d
@ -36,7 +36,7 @@ int WrapFrameNum(int frame_num, int num_frames, RepeatMode mode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
RTC_CHECK_EQ(RepeatMode::kPingPong, mode);
|
RTC_CHECK_EQ(RepeatMode::kPingPong, mode);
|
||||||
int cycle_len = 2 * (num_frames - 1);
|
int cycle_len = std::max(1, 2 * (num_frames - 1));
|
||||||
int wrapped_num = frame_num % cycle_len;
|
int wrapped_num = frame_num % cycle_len;
|
||||||
if (wrapped_num >= num_frames) {
|
if (wrapped_num >= num_frames) {
|
||||||
return cycle_len - wrapped_num;
|
return cycle_len - wrapped_num;
|
||||||
|
|||||||
@ -29,8 +29,7 @@ using Ratio = FrameReader::Ratio;
|
|||||||
using RepeatMode = YuvFrameReaderImpl::RepeatMode;
|
using RepeatMode = YuvFrameReaderImpl::RepeatMode;
|
||||||
|
|
||||||
constexpr Resolution kResolution({.width = 1, .height = 1});
|
constexpr Resolution kResolution({.width = 1, .height = 1});
|
||||||
constexpr char kFrameContent[3][3] = {{0, 1, 2}, {1, 2, 3}, {2, 3, 4}};
|
constexpr int kDefaultNumFrames = 3;
|
||||||
constexpr int kNumFrames = sizeof(kFrameContent) / sizeof(kFrameContent[0]);
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
class YuvFrameReaderTest : public ::testing::Test {
|
class YuvFrameReaderTest : public ::testing::Test {
|
||||||
@ -41,39 +40,48 @@ class YuvFrameReaderTest : public ::testing::Test {
|
|||||||
void SetUp() override {
|
void SetUp() override {
|
||||||
filepath_ = webrtc::test::TempFilename(webrtc::test::OutputPath(),
|
filepath_ = webrtc::test::TempFilename(webrtc::test::OutputPath(),
|
||||||
"yuv_frame_reader_unittest");
|
"yuv_frame_reader_unittest");
|
||||||
FILE* file = fopen(filepath_.c_str(), "wb");
|
CreateYuvFileAndReader(/*num_frames=*/3, RepeatMode::kSingle);
|
||||||
fwrite(kFrameContent, 1, sizeof(kFrameContent), file);
|
|
||||||
fclose(file);
|
|
||||||
|
|
||||||
reader_ = CreateYuvFrameReader(filepath_, kResolution);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TearDown() override { remove(filepath_.c_str()); }
|
void TearDown() override { remove(filepath_.c_str()); }
|
||||||
|
|
||||||
|
void CreateYuvFileAndReader(int num_frames, RepeatMode repeat_mode) {
|
||||||
|
FILE* file = fopen(filepath_.c_str(), "wb");
|
||||||
|
for (int i = 0; i < num_frames; ++i) {
|
||||||
|
uint8_t y = static_cast<uint8_t>(i & 255);
|
||||||
|
uint8_t u = static_cast<uint8_t>((i + 1) & 255);
|
||||||
|
uint8_t v = static_cast<uint8_t>((i + 2) & 255);
|
||||||
|
fwrite(&y, 1, 1, file);
|
||||||
|
fwrite(&u, 1, 1, file);
|
||||||
|
fwrite(&v, 1, 1, file);
|
||||||
|
}
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
reader_ = CreateYuvFrameReader(filepath_, kResolution, repeat_mode);
|
||||||
|
}
|
||||||
|
|
||||||
std::string filepath_;
|
std::string filepath_;
|
||||||
std::unique_ptr<FrameReader> reader_;
|
std::unique_ptr<FrameReader> reader_;
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(YuvFrameReaderTest, num_frames) {
|
TEST_F(YuvFrameReaderTest, num_frames) {
|
||||||
EXPECT_EQ(kNumFrames, reader_->num_frames());
|
EXPECT_EQ(kDefaultNumFrames, reader_->num_frames());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(YuvFrameReaderTest, PullFrame_frameContent) {
|
TEST_F(YuvFrameReaderTest, PullFrame_frameContent) {
|
||||||
rtc::scoped_refptr<I420BufferInterface> buffer = reader_->PullFrame();
|
rtc::scoped_refptr<I420BufferInterface> buffer = reader_->PullFrame();
|
||||||
EXPECT_EQ(kFrameContent[0][0], *buffer->DataY());
|
EXPECT_EQ(0u, *buffer->DataY());
|
||||||
EXPECT_EQ(kFrameContent[0][1], *buffer->DataU());
|
EXPECT_EQ(1u, *buffer->DataU());
|
||||||
EXPECT_EQ(kFrameContent[0][2], *buffer->DataV());
|
EXPECT_EQ(2u, *buffer->DataV());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(YuvFrameReaderTest, ReadFrame_randomOrder) {
|
TEST_F(YuvFrameReaderTest, ReadFrame_randomOrder) {
|
||||||
std::vector<int> expected_frames = {2, 0, 1};
|
rtc::scoped_refptr<I420BufferInterface> buffer = reader_->ReadFrame(2);
|
||||||
std::vector<int> actual_frames;
|
EXPECT_EQ(2u, *buffer->DataY());
|
||||||
for (int frame_num : expected_frames) {
|
buffer = reader_->ReadFrame(0);
|
||||||
rtc::scoped_refptr<I420BufferInterface> buffer =
|
EXPECT_EQ(0u, *buffer->DataY());
|
||||||
reader_->ReadFrame(frame_num);
|
buffer = reader_->ReadFrame(1);
|
||||||
actual_frames.push_back(*buffer->DataY());
|
EXPECT_EQ(1u, *buffer->DataY());
|
||||||
}
|
|
||||||
EXPECT_EQ(expected_frames, actual_frames);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(YuvFrameReaderTest, PullFrame_scale) {
|
TEST_F(YuvFrameReaderTest, PullFrame_scale) {
|
||||||
@ -87,30 +95,31 @@ TEST_F(YuvFrameReaderTest, PullFrame_scale) {
|
|||||||
class YuvFrameReaderRepeatModeTest
|
class YuvFrameReaderRepeatModeTest
|
||||||
: public YuvFrameReaderTest,
|
: public YuvFrameReaderTest,
|
||||||
public ::testing::WithParamInterface<
|
public ::testing::WithParamInterface<
|
||||||
std::tuple<RepeatMode, std::vector<int>>> {};
|
std::tuple<int, RepeatMode, std::vector<uint8_t>>> {};
|
||||||
|
|
||||||
TEST_P(YuvFrameReaderRepeatModeTest, PullFrame) {
|
TEST_P(YuvFrameReaderRepeatModeTest, PullFrame) {
|
||||||
RepeatMode mode = std::get<0>(GetParam());
|
auto [num_frames, repeat_mode, expected_frames] = GetParam();
|
||||||
std::vector<int> expected_frames = std::get<1>(GetParam());
|
CreateYuvFileAndReader(num_frames, repeat_mode);
|
||||||
|
for (auto expected_frame : expected_frames) {
|
||||||
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();
|
rtc::scoped_refptr<I420BufferInterface> buffer = reader_->PullFrame();
|
||||||
read_frames.push_back(*buffer->DataY());
|
EXPECT_EQ(expected_frame, *buffer->DataY());
|
||||||
}
|
}
|
||||||
EXPECT_EQ(expected_frames, read_frames);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
INSTANTIATE_TEST_SUITE_P(
|
INSTANTIATE_TEST_SUITE_P(
|
||||||
YuvFrameReaderTest,
|
YuvFrameReaderTest,
|
||||||
YuvFrameReaderRepeatModeTest,
|
YuvFrameReaderRepeatModeTest,
|
||||||
::testing::ValuesIn(
|
::testing::ValuesIn(
|
||||||
{std::make_tuple(RepeatMode::kSingle, std::vector<int>{0, 1, 2}),
|
{std::make_tuple(3, RepeatMode::kSingle, std::vector<uint8_t>{0, 1, 2}),
|
||||||
std::make_tuple(RepeatMode::kRepeat,
|
std::make_tuple(3,
|
||||||
std::vector<int>{0, 1, 2, 0, 1, 2}),
|
RepeatMode::kRepeat,
|
||||||
std::make_tuple(RepeatMode::kPingPong,
|
std::vector<uint8_t>{0, 1, 2, 0, 1, 2}),
|
||||||
std::vector<int>{0, 1, 2, 1, 0, 1, 2})}));
|
std::make_tuple(3,
|
||||||
|
RepeatMode::kPingPong,
|
||||||
|
std::vector<uint8_t>{0, 1, 2, 1, 0, 1, 2}),
|
||||||
|
std::make_tuple(1,
|
||||||
|
RepeatMode::kPingPong,
|
||||||
|
std::vector<uint8_t>{0, 0})}));
|
||||||
|
|
||||||
class YuvFrameReaderFramerateScaleTest
|
class YuvFrameReaderFramerateScaleTest
|
||||||
: public YuvFrameReaderTest,
|
: public YuvFrameReaderTest,
|
||||||
@ -118,17 +127,13 @@ class YuvFrameReaderFramerateScaleTest
|
|||||||
std::tuple<Ratio, std::vector<int>>> {};
|
std::tuple<Ratio, std::vector<int>>> {};
|
||||||
|
|
||||||
TEST_P(YuvFrameReaderFramerateScaleTest, PullFrame) {
|
TEST_P(YuvFrameReaderFramerateScaleTest, PullFrame) {
|
||||||
Ratio framerate_scale = std::get<0>(GetParam());
|
auto [framerate_scale, expected_frames] = GetParam();
|
||||||
std::vector<int> expected_frames = std::get<1>(GetParam());
|
for (auto expected_frame : expected_frames) {
|
||||||
|
|
||||||
std::vector<int> actual_frames;
|
|
||||||
for (size_t i = 0; i < expected_frames.size(); ++i) {
|
|
||||||
int pulled_frame;
|
int pulled_frame;
|
||||||
rtc::scoped_refptr<I420BufferInterface> buffer =
|
rtc::scoped_refptr<I420BufferInterface> buffer =
|
||||||
reader_->PullFrame(&pulled_frame, kResolution, framerate_scale);
|
reader_->PullFrame(&pulled_frame, kResolution, framerate_scale);
|
||||||
actual_frames.push_back(pulled_frame);
|
EXPECT_EQ(pulled_frame, expected_frame);
|
||||||
}
|
}
|
||||||
EXPECT_EQ(expected_frames, actual_frames);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
INSTANTIATE_TEST_SUITE_P(YuvFrameReaderTest,
|
INSTANTIATE_TEST_SUITE_P(YuvFrameReaderTest,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user