blob: ece37a547f62b9e26e51d028b34e3fd5e50591d0 [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
sprang@webrtc.org25dd1db2015-03-02 11:55:4513#include <stdio.h>
Yves Gerey3e707812018-11-28 15:47:4914#include <string.h>
Jonas Olssona4d87372019-07-05 17:08:3315
Yves Gerey3e707812018-11-28 15:47:4916#include <cstdint>
kwibergbfefb032016-05-01 21:53:4617#include <memory>
sprang@webrtc.org25dd1db2015-03-02 11:55:4518#include <string>
19
Mirko Bonadeid9708072019-01-25 19:26:4820#include "api/scoped_refptr.h"
Artem Titov33f9d2b2019-12-05 14:59:0021#include "api/test/create_frame_generator.h"
22#include "api/test/frame_generator_interface.h"
Yves Gerey3e707812018-11-28 15:47:4923#include "api/video/video_frame_buffer.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3124#include "test/gtest.h"
Steve Anton10542f22019-01-11 17:11:0025#include "test/testsupport/file_utils.h"
sprang@webrtc.org25dd1db2015-03-02 11:55:4526
27namespace webrtc {
28namespace test {
29
Artem Titov9b731592022-10-07 13:01:3230constexpr int kFrameWidth = 4;
31constexpr int kFrameHeight = 4;
32constexpr int y_size = kFrameWidth * kFrameHeight;
33constexpr int uv_size = ((kFrameHeight + 1) / 2) * ((kFrameWidth + 1) / 2);
sprang@webrtc.org25dd1db2015-03-02 11:55:4534
35class FrameGeneratorTest : public ::testing::Test {
36 public:
37 void SetUp() override {
Artem Titov9b731592022-10-07 13:01:3238 two_frame_yuv_filename_ =
sprang@webrtc.org25dd1db2015-03-02 11:55:4539 test::TempFilename(test::OutputPath(), "2_frame_yuv_file");
Artem Titov9b731592022-10-07 13:01:3240 one_frame_yuv_filename_ =
sprang@webrtc.org25dd1db2015-03-02 11:55:4541 test::TempFilename(test::OutputPath(), "1_frame_yuv_file");
Artem Titov9b731592022-10-07 13:01:3242 two_frame_nv12_filename_ =
43 test::TempFilename(test::OutputPath(), "2_frame_nv12_file");
44 one_frame_nv12_filename_ =
45 test::TempFilename(test::OutputPath(), "1_frame_nv12_file");
sprang@webrtc.org25dd1db2015-03-02 11:55:4546
Artem Titov9b731592022-10-07 13:01:3247 FILE* file = fopen(two_frame_yuv_filename_.c_str(), "wb");
sprang@webrtc.org25dd1db2015-03-02 11:55:4548 WriteYuvFile(file, 0, 0, 0);
Artem Titov9b731592022-10-07 13:01:3249 WriteYuvFile(file, 127, 128, 129);
sprang@webrtc.org25dd1db2015-03-02 11:55:4550 fclose(file);
Artem Titov9b731592022-10-07 13:01:3251 file = fopen(one_frame_yuv_filename_.c_str(), "wb");
sprang@webrtc.org25dd1db2015-03-02 11:55:4552 WriteYuvFile(file, 255, 255, 255);
53 fclose(file);
Artem Titov9b731592022-10-07 13:01:3254 file = fopen(two_frame_nv12_filename_.c_str(), "wb");
55 WriteNV12File(file, 0, 0, 0);
56 WriteNV12File(file, 127, 128, 129);
57 fclose(file);
58 file = fopen(one_frame_nv12_filename_.c_str(), "wb");
59 WriteNV12File(file, 255, 255, 255);
60 fclose(file);
sprang@webrtc.org25dd1db2015-03-02 11:55:4561 }
Artem Titov9b731592022-10-07 13:01:3262
sprang@webrtc.org25dd1db2015-03-02 11:55:4563 void TearDown() override {
Artem Titov9b731592022-10-07 13:01:3264 remove(one_frame_yuv_filename_.c_str());
65 remove(two_frame_yuv_filename_.c_str());
66 remove(one_frame_nv12_filename_.c_str());
67 remove(two_frame_nv12_filename_.c_str());
sprang@webrtc.org25dd1db2015-03-02 11:55:4568 }
69
70 protected:
71 void WriteYuvFile(FILE* file, uint8_t y, uint8_t u, uint8_t v) {
Mirko Bonadei25ab3222021-07-08 18:08:2072 RTC_DCHECK(file);
kwibergbfefb032016-05-01 21:53:4673 std::unique_ptr<uint8_t[]> plane_buffer(new uint8_t[y_size]);
sprang@webrtc.org25dd1db2015-03-02 11:55:4574 memset(plane_buffer.get(), y, y_size);
75 fwrite(plane_buffer.get(), 1, y_size, file);
76 memset(plane_buffer.get(), u, uv_size);
77 fwrite(plane_buffer.get(), 1, uv_size, file);
78 memset(plane_buffer.get(), v, uv_size);
79 fwrite(plane_buffer.get(), 1, uv_size, file);
80 }
81
Artem Titov9b731592022-10-07 13:01:3282 void WriteNV12File(FILE* file, uint8_t y, uint8_t u, uint8_t v) {
83 RTC_DCHECK(file);
84 uint8_t plane_buffer[y_size];
85
86 memset(&plane_buffer, y, y_size);
87 fwrite(&plane_buffer, 1, y_size, file);
88 for (size_t i = 0; i < uv_size; ++i) {
89 plane_buffer[2 * i] = u;
90 plane_buffer[2 * i + 1] = v;
91 }
92 fwrite(&plane_buffer, 1, 2 * uv_size, file);
93 }
94
Artem Titov33f9d2b2019-12-05 14:59:0095 void CheckFrameAndMutate(const FrameGeneratorInterface::VideoFrameData& frame,
Artem Titov5256d8b2019-12-02 09:34:1296 uint8_t y,
97 uint8_t u,
98 uint8_t v) {
sprang@webrtc.org25dd1db2015-03-02 11:55:4599 // Check that frame is valid, has the correct color and timestamp are clean.
Magnus Jedvert90e31902017-06-07 09:32:50100 rtc::scoped_refptr<I420BufferInterface> i420_buffer =
Artem Titov5256d8b2019-12-02 09:34:12101 frame.buffer->ToI420();
nissec9c142f2016-05-17 11:05:47102 const uint8_t* buffer;
Magnus Jedvert90e31902017-06-07 09:32:50103 buffer = i420_buffer->DataY();
sprang@webrtc.org25dd1db2015-03-02 11:55:45104 for (int i = 0; i < y_size; ++i)
105 ASSERT_EQ(y, buffer[i]);
Magnus Jedvert90e31902017-06-07 09:32:50106 buffer = i420_buffer->DataU();
sprang@webrtc.org25dd1db2015-03-02 11:55:45107 for (int i = 0; i < uv_size; ++i)
108 ASSERT_EQ(u, buffer[i]);
Magnus Jedvert90e31902017-06-07 09:32:50109 buffer = i420_buffer->DataV();
sprang@webrtc.org25dd1db2015-03-02 11:55:45110 for (int i = 0; i < uv_size; ++i)
111 ASSERT_EQ(v, buffer[i]);
sprang@webrtc.org25dd1db2015-03-02 11:55:45112 }
113
Artem Titov33f9d2b2019-12-05 14:59:00114 uint64_t Hash(const FrameGeneratorInterface::VideoFrameData& frame) {
erikvarga579de6f2017-08-29 16:12:57115 // Generate a 64-bit hash from the frame's buffer.
116 uint64_t hash = 19;
117 rtc::scoped_refptr<I420BufferInterface> i420_buffer =
Artem Titov5256d8b2019-12-02 09:34:12118 frame.buffer->ToI420();
erikvarga579de6f2017-08-29 16:12:57119 const uint8_t* buffer = i420_buffer->DataY();
120 for (int i = 0; i < y_size; ++i) {
121 hash = (37 * hash) + buffer[i];
122 }
123 buffer = i420_buffer->DataU();
124 for (int i = 0; i < uv_size; ++i) {
125 hash = (37 * hash) + buffer[i];
126 }
127 buffer = i420_buffer->DataV();
128 for (int i = 0; i < uv_size; ++i) {
129 hash = (37 * hash) + buffer[i];
130 }
131 return hash;
132 }
133
Artem Titov9b731592022-10-07 13:01:32134 std::string two_frame_yuv_filename_;
135 std::string one_frame_yuv_filename_;
136 std::string two_frame_nv12_filename_;
137 std::string one_frame_nv12_filename_;
sprang@webrtc.org25dd1db2015-03-02 11:55:45138};
139
Artem Titov9b731592022-10-07 13:01:32140TEST_F(FrameGeneratorTest, SingleFrameYuvFile) {
Artem Titov33f9d2b2019-12-05 14:59:00141 std::unique_ptr<FrameGeneratorInterface> generator(
142 CreateFromYuvFileFrameGenerator(
Artem Titov9b731592022-10-07 13:01:32143 std::vector<std::string>(1, one_frame_yuv_filename_), kFrameWidth,
Artem Titov33f9d2b2019-12-05 14:59:00144 kFrameHeight, 1));
sprang@webrtc.org25dd1db2015-03-02 11:55:45145 CheckFrameAndMutate(generator->NextFrame(), 255, 255, 255);
146 CheckFrameAndMutate(generator->NextFrame(), 255, 255, 255);
147}
148
Artem Titov9b731592022-10-07 13:01:32149TEST_F(FrameGeneratorTest, TwoFrameYuvFile) {
Artem Titov33f9d2b2019-12-05 14:59:00150 std::unique_ptr<FrameGeneratorInterface> generator(
151 CreateFromYuvFileFrameGenerator(
Artem Titov9b731592022-10-07 13:01:32152 std::vector<std::string>(1, two_frame_yuv_filename_), kFrameWidth,
Artem Titov33f9d2b2019-12-05 14:59:00153 kFrameHeight, 1));
sprang@webrtc.org25dd1db2015-03-02 11:55:45154 CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
Artem Titov9b731592022-10-07 13:01:32155 CheckFrameAndMutate(generator->NextFrame(), 127, 128, 129);
sprang@webrtc.org25dd1db2015-03-02 11:55:45156 CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
157}
158
Artem Titov9b731592022-10-07 13:01:32159TEST_F(FrameGeneratorTest, MultipleFrameYuvFiles) {
sprang@webrtc.org25dd1db2015-03-02 11:55:45160 std::vector<std::string> files;
Artem Titov9b731592022-10-07 13:01:32161 files.push_back(two_frame_yuv_filename_);
162 files.push_back(one_frame_yuv_filename_);
sprang@webrtc.org25dd1db2015-03-02 11:55:45163
Artem Titov33f9d2b2019-12-05 14:59:00164 std::unique_ptr<FrameGeneratorInterface> generator(
165 CreateFromYuvFileFrameGenerator(files, kFrameWidth, kFrameHeight, 1));
sprang@webrtc.org25dd1db2015-03-02 11:55:45166 CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
Artem Titov9b731592022-10-07 13:01:32167 CheckFrameAndMutate(generator->NextFrame(), 127, 128, 129);
sprang@webrtc.org25dd1db2015-03-02 11:55:45168 CheckFrameAndMutate(generator->NextFrame(), 255, 255, 255);
169 CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
170}
171
Artem Titov9b731592022-10-07 13:01:32172TEST_F(FrameGeneratorTest, TwoFrameYuvFileWithRepeat) {
sprang@webrtc.org25dd1db2015-03-02 11:55:45173 const int kRepeatCount = 3;
Artem Titov33f9d2b2019-12-05 14:59:00174 std::unique_ptr<FrameGeneratorInterface> generator(
175 CreateFromYuvFileFrameGenerator(
Artem Titov9b731592022-10-07 13:01:32176 std::vector<std::string>(1, two_frame_yuv_filename_), kFrameWidth,
Artem Titov33f9d2b2019-12-05 14:59:00177 kFrameHeight, kRepeatCount));
sprang@webrtc.org25dd1db2015-03-02 11:55:45178 for (int i = 0; i < kRepeatCount; ++i)
179 CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
180 for (int i = 0; i < kRepeatCount; ++i)
Artem Titov9b731592022-10-07 13:01:32181 CheckFrameAndMutate(generator->NextFrame(), 127, 128, 129);
sprang@webrtc.org25dd1db2015-03-02 11:55:45182 CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
183}
184
Artem Titov9b731592022-10-07 13:01:32185TEST_F(FrameGeneratorTest, MultipleFrameYuvFilesWithRepeat) {
sprang@webrtc.org25dd1db2015-03-02 11:55:45186 const int kRepeatCount = 3;
187 std::vector<std::string> files;
Artem Titov9b731592022-10-07 13:01:32188 files.push_back(two_frame_yuv_filename_);
189 files.push_back(one_frame_yuv_filename_);
Artem Titov33f9d2b2019-12-05 14:59:00190 std::unique_ptr<FrameGeneratorInterface> generator(
191 CreateFromYuvFileFrameGenerator(files, kFrameWidth, kFrameHeight,
192 kRepeatCount));
sprang@webrtc.org25dd1db2015-03-02 11:55:45193 for (int i = 0; i < kRepeatCount; ++i)
194 CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
195 for (int i = 0; i < kRepeatCount; ++i)
Artem Titov9b731592022-10-07 13:01:32196 CheckFrameAndMutate(generator->NextFrame(), 127, 128, 129);
197 for (int i = 0; i < kRepeatCount; ++i)
198 CheckFrameAndMutate(generator->NextFrame(), 255, 255, 255);
199 CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
200}
201
202TEST_F(FrameGeneratorTest, SingleFrameNV12File) {
203 std::unique_ptr<FrameGeneratorInterface> generator(
204 CreateFromNV12FileFrameGenerator(
205 std::vector<std::string>(1, one_frame_nv12_filename_), kFrameWidth,
206 kFrameHeight, 1));
207 CheckFrameAndMutate(generator->NextFrame(), 255, 255, 255);
208 CheckFrameAndMutate(generator->NextFrame(), 255, 255, 255);
209}
210
211TEST_F(FrameGeneratorTest, TwoFrameNV12File) {
212 std::unique_ptr<FrameGeneratorInterface> generator(
213 CreateFromNV12FileFrameGenerator(
214 std::vector<std::string>(1, two_frame_nv12_filename_), kFrameWidth,
215 kFrameHeight, 1));
216 CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
217 CheckFrameAndMutate(generator->NextFrame(), 127, 128, 129);
218 CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
219}
220
221TEST_F(FrameGeneratorTest, MultipleFrameNV12Files) {
222 std::vector<std::string> files;
223 files.push_back(two_frame_nv12_filename_);
224 files.push_back(one_frame_nv12_filename_);
225
226 std::unique_ptr<FrameGeneratorInterface> generator(
227 CreateFromNV12FileFrameGenerator(files, kFrameWidth, kFrameHeight, 1));
228 CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
229 CheckFrameAndMutate(generator->NextFrame(), 127, 128, 129);
230 CheckFrameAndMutate(generator->NextFrame(), 255, 255, 255);
231 CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
232}
233
234TEST_F(FrameGeneratorTest, TwoFrameNV12FileWithRepeat) {
235 const int kRepeatCount = 3;
236 std::unique_ptr<FrameGeneratorInterface> generator(
237 CreateFromNV12FileFrameGenerator(
238 std::vector<std::string>(1, two_frame_nv12_filename_), kFrameWidth,
239 kFrameHeight, kRepeatCount));
240 for (int i = 0; i < kRepeatCount; ++i)
241 CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
242 for (int i = 0; i < kRepeatCount; ++i)
243 CheckFrameAndMutate(generator->NextFrame(), 127, 128, 129);
244 CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
245}
246
247TEST_F(FrameGeneratorTest, MultipleFrameNV12FilesWithRepeat) {
248 const int kRepeatCount = 3;
249 std::vector<std::string> files;
250 files.push_back(two_frame_nv12_filename_);
251 files.push_back(one_frame_nv12_filename_);
252 std::unique_ptr<FrameGeneratorInterface> generator(
253 CreateFromNV12FileFrameGenerator(files, kFrameWidth, kFrameHeight,
254 kRepeatCount));
255 for (int i = 0; i < kRepeatCount; ++i)
256 CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
257 for (int i = 0; i < kRepeatCount; ++i)
258 CheckFrameAndMutate(generator->NextFrame(), 127, 128, 129);
sprang@webrtc.org25dd1db2015-03-02 11:55:45259 for (int i = 0; i < kRepeatCount; ++i)
260 CheckFrameAndMutate(generator->NextFrame(), 255, 255, 255);
261 CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
262}
263
erikvarga579de6f2017-08-29 16:12:57264TEST_F(FrameGeneratorTest, SlideGenerator) {
265 const int kGenCount = 9;
266 const int kRepeatCount = 3;
Artem Titov33f9d2b2019-12-05 14:59:00267 std::unique_ptr<FrameGeneratorInterface> generator(
268 CreateSlideFrameGenerator(kFrameWidth, kFrameHeight, kRepeatCount));
erikvarga579de6f2017-08-29 16:12:57269 uint64_t hashes[kGenCount];
270 for (int i = 0; i < kGenCount; ++i) {
271 hashes[i] = Hash(generator->NextFrame());
272 }
Artem Titov1ee563d2021-07-27 10:46:29273 // Check that the buffer changes only every `kRepeatCount` frames.
erikvarga579de6f2017-08-29 16:12:57274 for (int i = 1; i < kGenCount; ++i) {
275 if (i % kRepeatCount == 0) {
Yves Gerey665174f2018-06-19 13:03:05276 EXPECT_NE(hashes[i - 1], hashes[i]);
erikvarga579de6f2017-08-29 16:12:57277 } else {
Yves Gerey665174f2018-06-19 13:03:05278 EXPECT_EQ(hashes[i - 1], hashes[i]);
erikvarga579de6f2017-08-29 16:12:57279 }
280 }
281}
282
sprang@webrtc.org25dd1db2015-03-02 11:55:45283} // namespace test
284} // namespace webrtc