blob: 12d5111bff54d25d40898e4a738841ff34d966d5 [file] [log] [blame]
sprang@webrtc.org25dd1db2015-03-02 11:55:451/*
2 * Copyright (c) 2015 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
Jonas Olssona4d87372019-07-05 17:08:3311#include "test/frame_generator.h"
12
Yves Gerey3e707812018-11-28 15:47:4913#include <assert.h>
sprang@webrtc.org25dd1db2015-03-02 11:55:4514#include <stdio.h>
Yves Gerey3e707812018-11-28 15:47:4915#include <string.h>
Jonas Olssona4d87372019-07-05 17:08:3316
Yves Gerey3e707812018-11-28 15:47:4917#include <cstdint>
kwibergbfefb032016-05-01 21:53:4618#include <memory>
sprang@webrtc.org25dd1db2015-03-02 11:55:4519#include <string>
20
Mirko Bonadeid9708072019-01-25 19:26:4821#include "api/scoped_refptr.h"
Artem Titov33f9d2b2019-12-05 14:59:0022#include "api/test/create_frame_generator.h"
23#include "api/test/frame_generator_interface.h"
Yves Gerey3e707812018-11-28 15:47:4924#include "api/video/video_frame_buffer.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3125#include "test/gtest.h"
Steve Anton10542f22019-01-11 17:11:0026#include "test/testsupport/file_utils.h"
sprang@webrtc.org25dd1db2015-03-02 11:55:4527
28namespace webrtc {
29namespace test {
30
31static const int kFrameWidth = 4;
32static const int kFrameHeight = 4;
33
34class FrameGeneratorTest : public ::testing::Test {
35 public:
36 void SetUp() override {
37 two_frame_filename_ =
38 test::TempFilename(test::OutputPath(), "2_frame_yuv_file");
39 one_frame_filename_ =
40 test::TempFilename(test::OutputPath(), "1_frame_yuv_file");
41
42 FILE* file = fopen(two_frame_filename_.c_str(), "wb");
43 WriteYuvFile(file, 0, 0, 0);
44 WriteYuvFile(file, 127, 127, 127);
45 fclose(file);
46 file = fopen(one_frame_filename_.c_str(), "wb");
47 WriteYuvFile(file, 255, 255, 255);
48 fclose(file);
49 }
50 void TearDown() override {
51 remove(one_frame_filename_.c_str());
52 remove(two_frame_filename_.c_str());
53 }
54
55 protected:
56 void WriteYuvFile(FILE* file, uint8_t y, uint8_t u, uint8_t v) {
57 assert(file);
kwibergbfefb032016-05-01 21:53:4658 std::unique_ptr<uint8_t[]> plane_buffer(new uint8_t[y_size]);
sprang@webrtc.org25dd1db2015-03-02 11:55:4559 memset(plane_buffer.get(), y, y_size);
60 fwrite(plane_buffer.get(), 1, y_size, file);
61 memset(plane_buffer.get(), u, uv_size);
62 fwrite(plane_buffer.get(), 1, uv_size, file);
63 memset(plane_buffer.get(), v, uv_size);
64 fwrite(plane_buffer.get(), 1, uv_size, file);
65 }
66
Artem Titov33f9d2b2019-12-05 14:59:0067 void CheckFrameAndMutate(const FrameGeneratorInterface::VideoFrameData& frame,
Artem Titov5256d8b2019-12-02 09:34:1268 uint8_t y,
69 uint8_t u,
70 uint8_t v) {
sprang@webrtc.org25dd1db2015-03-02 11:55:4571 // Check that frame is valid, has the correct color and timestamp are clean.
Magnus Jedvert90e31902017-06-07 09:32:5072 rtc::scoped_refptr<I420BufferInterface> i420_buffer =
Artem Titov5256d8b2019-12-02 09:34:1273 frame.buffer->ToI420();
nissec9c142f2016-05-17 11:05:4774 const uint8_t* buffer;
Magnus Jedvert90e31902017-06-07 09:32:5075 buffer = i420_buffer->DataY();
sprang@webrtc.org25dd1db2015-03-02 11:55:4576 for (int i = 0; i < y_size; ++i)
77 ASSERT_EQ(y, buffer[i]);
Magnus Jedvert90e31902017-06-07 09:32:5078 buffer = i420_buffer->DataU();
sprang@webrtc.org25dd1db2015-03-02 11:55:4579 for (int i = 0; i < uv_size; ++i)
80 ASSERT_EQ(u, buffer[i]);
Magnus Jedvert90e31902017-06-07 09:32:5081 buffer = i420_buffer->DataV();
sprang@webrtc.org25dd1db2015-03-02 11:55:4582 for (int i = 0; i < uv_size; ++i)
83 ASSERT_EQ(v, buffer[i]);
sprang@webrtc.org25dd1db2015-03-02 11:55:4584 }
85
Artem Titov33f9d2b2019-12-05 14:59:0086 uint64_t Hash(const FrameGeneratorInterface::VideoFrameData& frame) {
erikvarga579de6f2017-08-29 16:12:5787 // Generate a 64-bit hash from the frame's buffer.
88 uint64_t hash = 19;
89 rtc::scoped_refptr<I420BufferInterface> i420_buffer =
Artem Titov5256d8b2019-12-02 09:34:1290 frame.buffer->ToI420();
erikvarga579de6f2017-08-29 16:12:5791 const uint8_t* buffer = i420_buffer->DataY();
92 for (int i = 0; i < y_size; ++i) {
93 hash = (37 * hash) + buffer[i];
94 }
95 buffer = i420_buffer->DataU();
96 for (int i = 0; i < uv_size; ++i) {
97 hash = (37 * hash) + buffer[i];
98 }
99 buffer = i420_buffer->DataV();
100 for (int i = 0; i < uv_size; ++i) {
101 hash = (37 * hash) + buffer[i];
102 }
103 return hash;
104 }
105
sprang@webrtc.org25dd1db2015-03-02 11:55:45106 std::string two_frame_filename_;
107 std::string one_frame_filename_;
108 const int y_size = kFrameWidth * kFrameHeight;
109 const int uv_size = ((kFrameHeight + 1) / 2) * ((kFrameWidth + 1) / 2);
110};
111
112TEST_F(FrameGeneratorTest, SingleFrameFile) {
Artem Titov33f9d2b2019-12-05 14:59:00113 std::unique_ptr<FrameGeneratorInterface> generator(
114 CreateFromYuvFileFrameGenerator(
115 std::vector<std::string>(1, one_frame_filename_), kFrameWidth,
116 kFrameHeight, 1));
sprang@webrtc.org25dd1db2015-03-02 11:55:45117 CheckFrameAndMutate(generator->NextFrame(), 255, 255, 255);
118 CheckFrameAndMutate(generator->NextFrame(), 255, 255, 255);
119}
120
121TEST_F(FrameGeneratorTest, TwoFrameFile) {
Artem Titov33f9d2b2019-12-05 14:59:00122 std::unique_ptr<FrameGeneratorInterface> generator(
123 CreateFromYuvFileFrameGenerator(
124 std::vector<std::string>(1, two_frame_filename_), kFrameWidth,
125 kFrameHeight, 1));
sprang@webrtc.org25dd1db2015-03-02 11:55:45126 CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
127 CheckFrameAndMutate(generator->NextFrame(), 127, 127, 127);
128 CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
129}
130
131TEST_F(FrameGeneratorTest, MultipleFrameFiles) {
132 std::vector<std::string> files;
133 files.push_back(two_frame_filename_);
134 files.push_back(one_frame_filename_);
135
Artem Titov33f9d2b2019-12-05 14:59:00136 std::unique_ptr<FrameGeneratorInterface> generator(
137 CreateFromYuvFileFrameGenerator(files, kFrameWidth, kFrameHeight, 1));
sprang@webrtc.org25dd1db2015-03-02 11:55:45138 CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
139 CheckFrameAndMutate(generator->NextFrame(), 127, 127, 127);
140 CheckFrameAndMutate(generator->NextFrame(), 255, 255, 255);
141 CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
142}
143
144TEST_F(FrameGeneratorTest, TwoFrameFileWithRepeat) {
145 const int kRepeatCount = 3;
Artem Titov33f9d2b2019-12-05 14:59:00146 std::unique_ptr<FrameGeneratorInterface> generator(
147 CreateFromYuvFileFrameGenerator(
148 std::vector<std::string>(1, two_frame_filename_), kFrameWidth,
149 kFrameHeight, kRepeatCount));
sprang@webrtc.org25dd1db2015-03-02 11:55:45150 for (int i = 0; i < kRepeatCount; ++i)
151 CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
152 for (int i = 0; i < kRepeatCount; ++i)
153 CheckFrameAndMutate(generator->NextFrame(), 127, 127, 127);
154 CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
155}
156
157TEST_F(FrameGeneratorTest, MultipleFrameFilesWithRepeat) {
158 const int kRepeatCount = 3;
159 std::vector<std::string> files;
160 files.push_back(two_frame_filename_);
161 files.push_back(one_frame_filename_);
Artem Titov33f9d2b2019-12-05 14:59:00162 std::unique_ptr<FrameGeneratorInterface> generator(
163 CreateFromYuvFileFrameGenerator(files, kFrameWidth, kFrameHeight,
164 kRepeatCount));
sprang@webrtc.org25dd1db2015-03-02 11:55:45165 for (int i = 0; i < kRepeatCount; ++i)
166 CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
167 for (int i = 0; i < kRepeatCount; ++i)
168 CheckFrameAndMutate(generator->NextFrame(), 127, 127, 127);
169 for (int i = 0; i < kRepeatCount; ++i)
170 CheckFrameAndMutate(generator->NextFrame(), 255, 255, 255);
171 CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
172}
173
erikvarga579de6f2017-08-29 16:12:57174TEST_F(FrameGeneratorTest, SlideGenerator) {
175 const int kGenCount = 9;
176 const int kRepeatCount = 3;
Artem Titov33f9d2b2019-12-05 14:59:00177 std::unique_ptr<FrameGeneratorInterface> generator(
178 CreateSlideFrameGenerator(kFrameWidth, kFrameHeight, kRepeatCount));
erikvarga579de6f2017-08-29 16:12:57179 uint64_t hashes[kGenCount];
180 for (int i = 0; i < kGenCount; ++i) {
181 hashes[i] = Hash(generator->NextFrame());
182 }
183 // Check that the buffer changes only every |kRepeatCount| frames.
184 for (int i = 1; i < kGenCount; ++i) {
185 if (i % kRepeatCount == 0) {
Yves Gerey665174f2018-06-19 13:03:05186 EXPECT_NE(hashes[i - 1], hashes[i]);
erikvarga579de6f2017-08-29 16:12:57187 } else {
Yves Gerey665174f2018-06-19 13:03:05188 EXPECT_EQ(hashes[i - 1], hashes[i]);
erikvarga579de6f2017-08-29 16:12:57189 }
190 }
191}
192
sprang@webrtc.org25dd1db2015-03-02 11:55:45193} // namespace test
194} // namespace webrtc