blob: 4be304a0d85c9dba57090cfd2a18a7265b20118b [file] [log] [blame]
sprang@webrtc.org25dd1db2015-03-02 11:55:45 +00001/*
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 19:08:33 +020011#include "test/frame_generator.h"
12
Yves Gerey3e707812018-11-28 16:47:49 +010013#include <assert.h>
sprang@webrtc.org25dd1db2015-03-02 11:55:45 +000014#include <stdio.h>
Yves Gerey3e707812018-11-28 16:47:49 +010015#include <string.h>
Jonas Olssona4d87372019-07-05 19:08:33 +020016
Yves Gerey3e707812018-11-28 16:47:49 +010017#include <cstdint>
kwibergbfefb032016-05-01 14:53:46 -070018#include <memory>
sprang@webrtc.org25dd1db2015-03-02 11:55:45 +000019#include <string>
20
Mirko Bonadeid9708072019-01-25 20:26:48 +010021#include "api/scoped_refptr.h"
Yves Gerey3e707812018-11-28 16:47:49 +010022#include "api/video/video_frame_buffer.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020023#include "test/gtest.h"
Steve Anton10542f22019-01-11 09:11:00 -080024#include "test/testsupport/file_utils.h"
sprang@webrtc.org25dd1db2015-03-02 11:55:45 +000025
26namespace webrtc {
27namespace test {
28
29static const int kFrameWidth = 4;
30static const int kFrameHeight = 4;
31
32class FrameGeneratorTest : public ::testing::Test {
33 public:
34 void SetUp() override {
35 two_frame_filename_ =
36 test::TempFilename(test::OutputPath(), "2_frame_yuv_file");
37 one_frame_filename_ =
38 test::TempFilename(test::OutputPath(), "1_frame_yuv_file");
39
40 FILE* file = fopen(two_frame_filename_.c_str(), "wb");
41 WriteYuvFile(file, 0, 0, 0);
42 WriteYuvFile(file, 127, 127, 127);
43 fclose(file);
44 file = fopen(one_frame_filename_.c_str(), "wb");
45 WriteYuvFile(file, 255, 255, 255);
46 fclose(file);
47 }
48 void TearDown() override {
49 remove(one_frame_filename_.c_str());
50 remove(two_frame_filename_.c_str());
51 }
52
53 protected:
54 void WriteYuvFile(FILE* file, uint8_t y, uint8_t u, uint8_t v) {
55 assert(file);
kwibergbfefb032016-05-01 14:53:46 -070056 std::unique_ptr<uint8_t[]> plane_buffer(new uint8_t[y_size]);
sprang@webrtc.org25dd1db2015-03-02 11:55:45 +000057 memset(plane_buffer.get(), y, y_size);
58 fwrite(plane_buffer.get(), 1, y_size, file);
59 memset(plane_buffer.get(), u, uv_size);
60 fwrite(plane_buffer.get(), 1, uv_size, file);
61 memset(plane_buffer.get(), v, uv_size);
62 fwrite(plane_buffer.get(), 1, uv_size, file);
63 }
64
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -070065 void CheckFrameAndMutate(VideoFrame* frame, uint8_t y, uint8_t u, uint8_t v) {
sprang@webrtc.org25dd1db2015-03-02 11:55:45 +000066 // Check that frame is valid, has the correct color and timestamp are clean.
67 ASSERT_NE(nullptr, frame);
Magnus Jedvert90e31902017-06-07 11:32:50 +020068 rtc::scoped_refptr<I420BufferInterface> i420_buffer =
69 frame->video_frame_buffer()->ToI420();
nissec9c142f2016-05-17 04:05:47 -070070 const uint8_t* buffer;
Magnus Jedvert90e31902017-06-07 11:32:50 +020071 buffer = i420_buffer->DataY();
sprang@webrtc.org25dd1db2015-03-02 11:55:45 +000072 for (int i = 0; i < y_size; ++i)
73 ASSERT_EQ(y, buffer[i]);
Magnus Jedvert90e31902017-06-07 11:32:50 +020074 buffer = i420_buffer->DataU();
sprang@webrtc.org25dd1db2015-03-02 11:55:45 +000075 for (int i = 0; i < uv_size; ++i)
76 ASSERT_EQ(u, buffer[i]);
Magnus Jedvert90e31902017-06-07 11:32:50 +020077 buffer = i420_buffer->DataV();
sprang@webrtc.org25dd1db2015-03-02 11:55:45 +000078 for (int i = 0; i < uv_size; ++i)
79 ASSERT_EQ(v, buffer[i]);
80 EXPECT_EQ(0, frame->ntp_time_ms());
81 EXPECT_EQ(0, frame->render_time_ms());
82 EXPECT_EQ(0u, frame->timestamp());
83
84 // Mutate to something arbitrary non-zero.
85 frame->set_ntp_time_ms(11);
nisse1c0dea82017-01-30 02:43:18 -080086 frame->set_timestamp_us(12);
sprang@webrtc.org25dd1db2015-03-02 11:55:45 +000087 frame->set_timestamp(13);
88 }
89
erikvarga579de6f2017-08-29 09:12:57 -070090 uint64_t Hash(VideoFrame* frame) {
91 // Generate a 64-bit hash from the frame's buffer.
92 uint64_t hash = 19;
93 rtc::scoped_refptr<I420BufferInterface> i420_buffer =
94 frame->video_frame_buffer()->ToI420();
95 const uint8_t* buffer = i420_buffer->DataY();
96 for (int i = 0; i < y_size; ++i) {
97 hash = (37 * hash) + buffer[i];
98 }
99 buffer = i420_buffer->DataU();
100 for (int i = 0; i < uv_size; ++i) {
101 hash = (37 * hash) + buffer[i];
102 }
103 buffer = i420_buffer->DataV();
104 for (int i = 0; i < uv_size; ++i) {
105 hash = (37 * hash) + buffer[i];
106 }
107 return hash;
108 }
109
sprang@webrtc.org25dd1db2015-03-02 11:55:45 +0000110 std::string two_frame_filename_;
111 std::string one_frame_filename_;
112 const int y_size = kFrameWidth * kFrameHeight;
113 const int uv_size = ((kFrameHeight + 1) / 2) * ((kFrameWidth + 1) / 2);
114};
115
116TEST_F(FrameGeneratorTest, SingleFrameFile) {
kwibergbfefb032016-05-01 14:53:46 -0700117 std::unique_ptr<FrameGenerator> generator(FrameGenerator::CreateFromYuvFile(
sprang@webrtc.org25dd1db2015-03-02 11:55:45 +0000118 std::vector<std::string>(1, one_frame_filename_), kFrameWidth,
119 kFrameHeight, 1));
120 CheckFrameAndMutate(generator->NextFrame(), 255, 255, 255);
121 CheckFrameAndMutate(generator->NextFrame(), 255, 255, 255);
122}
123
124TEST_F(FrameGeneratorTest, TwoFrameFile) {
kwibergbfefb032016-05-01 14:53:46 -0700125 std::unique_ptr<FrameGenerator> generator(FrameGenerator::CreateFromYuvFile(
sprang@webrtc.org25dd1db2015-03-02 11:55:45 +0000126 std::vector<std::string>(1, two_frame_filename_), kFrameWidth,
127 kFrameHeight, 1));
128 CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
129 CheckFrameAndMutate(generator->NextFrame(), 127, 127, 127);
130 CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
131}
132
133TEST_F(FrameGeneratorTest, MultipleFrameFiles) {
134 std::vector<std::string> files;
135 files.push_back(two_frame_filename_);
136 files.push_back(one_frame_filename_);
137
kwibergbfefb032016-05-01 14:53:46 -0700138 std::unique_ptr<FrameGenerator> generator(
sprang@webrtc.org25dd1db2015-03-02 11:55:45 +0000139 FrameGenerator::CreateFromYuvFile(files, kFrameWidth, kFrameHeight, 1));
140 CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
141 CheckFrameAndMutate(generator->NextFrame(), 127, 127, 127);
142 CheckFrameAndMutate(generator->NextFrame(), 255, 255, 255);
143 CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
144}
145
146TEST_F(FrameGeneratorTest, TwoFrameFileWithRepeat) {
147 const int kRepeatCount = 3;
kwibergbfefb032016-05-01 14:53:46 -0700148 std::unique_ptr<FrameGenerator> generator(FrameGenerator::CreateFromYuvFile(
sprang@webrtc.org25dd1db2015-03-02 11:55:45 +0000149 std::vector<std::string>(1, two_frame_filename_), kFrameWidth,
150 kFrameHeight, kRepeatCount));
151 for (int i = 0; i < kRepeatCount; ++i)
152 CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
153 for (int i = 0; i < kRepeatCount; ++i)
154 CheckFrameAndMutate(generator->NextFrame(), 127, 127, 127);
155 CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
156}
157
158TEST_F(FrameGeneratorTest, MultipleFrameFilesWithRepeat) {
159 const int kRepeatCount = 3;
160 std::vector<std::string> files;
161 files.push_back(two_frame_filename_);
162 files.push_back(one_frame_filename_);
kwibergbfefb032016-05-01 14:53:46 -0700163 std::unique_ptr<FrameGenerator> generator(FrameGenerator::CreateFromYuvFile(
sprang@webrtc.org25dd1db2015-03-02 11:55:45 +0000164 files, kFrameWidth, kFrameHeight, kRepeatCount));
165 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 09:12:57 -0700174TEST_F(FrameGeneratorTest, SlideGenerator) {
175 const int kGenCount = 9;
176 const int kRepeatCount = 3;
177 std::unique_ptr<FrameGenerator> generator(
Yves Gerey665174f2018-06-19 15:03:05 +0200178 FrameGenerator::CreateSlideGenerator(kFrameWidth, kFrameHeight,
179 kRepeatCount));
erikvarga579de6f2017-08-29 09:12:57 -0700180 uint64_t hashes[kGenCount];
181 for (int i = 0; i < kGenCount; ++i) {
182 hashes[i] = Hash(generator->NextFrame());
183 }
184 // Check that the buffer changes only every |kRepeatCount| frames.
185 for (int i = 1; i < kGenCount; ++i) {
186 if (i % kRepeatCount == 0) {
Yves Gerey665174f2018-06-19 15:03:05 +0200187 EXPECT_NE(hashes[i - 1], hashes[i]);
erikvarga579de6f2017-08-29 09:12:57 -0700188 } else {
Yves Gerey665174f2018-06-19 15:03:05 +0200189 EXPECT_EQ(hashes[i - 1], hashes[i]);
erikvarga579de6f2017-08-29 09:12:57 -0700190 }
191 }
192}
193
sprang@webrtc.org25dd1db2015-03-02 11:55:45 +0000194} // namespace test
195} // namespace webrtc