blob: bfa19e5cf15fff3be4d7283fd8e96ad4b98f8d98 [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
Yves Gerey3e707812018-11-28 16:47:49 +010011#include <assert.h>
sprang@webrtc.org25dd1db2015-03-02 11:55:45 +000012#include <stdio.h>
Yves Gerey3e707812018-11-28 16:47:49 +010013#include <string.h>
14#include <cstdint>
kwibergbfefb032016-05-01 14:53:46 -070015#include <memory>
sprang@webrtc.org25dd1db2015-03-02 11:55:45 +000016#include <string>
17
Yves Gerey3e707812018-11-28 16:47:49 +010018#include "api/video/video_frame_buffer.h"
19#include "rtc_base/scoped_ref_ptr.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "test/frame_generator.h"
21#include "test/gtest.h"
22#include "test/testsupport/fileutils.h"
sprang@webrtc.org25dd1db2015-03-02 11:55:45 +000023
24namespace webrtc {
25namespace test {
26
27static const int kFrameWidth = 4;
28static const int kFrameHeight = 4;
29
30class FrameGeneratorTest : public ::testing::Test {
31 public:
32 void SetUp() override {
33 two_frame_filename_ =
34 test::TempFilename(test::OutputPath(), "2_frame_yuv_file");
35 one_frame_filename_ =
36 test::TempFilename(test::OutputPath(), "1_frame_yuv_file");
37
38 FILE* file = fopen(two_frame_filename_.c_str(), "wb");
39 WriteYuvFile(file, 0, 0, 0);
40 WriteYuvFile(file, 127, 127, 127);
41 fclose(file);
42 file = fopen(one_frame_filename_.c_str(), "wb");
43 WriteYuvFile(file, 255, 255, 255);
44 fclose(file);
45 }
46 void TearDown() override {
47 remove(one_frame_filename_.c_str());
48 remove(two_frame_filename_.c_str());
49 }
50
51 protected:
52 void WriteYuvFile(FILE* file, uint8_t y, uint8_t u, uint8_t v) {
53 assert(file);
kwibergbfefb032016-05-01 14:53:46 -070054 std::unique_ptr<uint8_t[]> plane_buffer(new uint8_t[y_size]);
sprang@webrtc.org25dd1db2015-03-02 11:55:45 +000055 memset(plane_buffer.get(), y, y_size);
56 fwrite(plane_buffer.get(), 1, y_size, file);
57 memset(plane_buffer.get(), u, uv_size);
58 fwrite(plane_buffer.get(), 1, uv_size, file);
59 memset(plane_buffer.get(), v, uv_size);
60 fwrite(plane_buffer.get(), 1, uv_size, file);
61 }
62
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -070063 void CheckFrameAndMutate(VideoFrame* frame, uint8_t y, uint8_t u, uint8_t v) {
sprang@webrtc.org25dd1db2015-03-02 11:55:45 +000064 // Check that frame is valid, has the correct color and timestamp are clean.
65 ASSERT_NE(nullptr, frame);
Magnus Jedvert90e31902017-06-07 11:32:50 +020066 rtc::scoped_refptr<I420BufferInterface> i420_buffer =
67 frame->video_frame_buffer()->ToI420();
nissec9c142f2016-05-17 04:05:47 -070068 const uint8_t* buffer;
Magnus Jedvert90e31902017-06-07 11:32:50 +020069 buffer = i420_buffer->DataY();
sprang@webrtc.org25dd1db2015-03-02 11:55:45 +000070 for (int i = 0; i < y_size; ++i)
71 ASSERT_EQ(y, buffer[i]);
Magnus Jedvert90e31902017-06-07 11:32:50 +020072 buffer = i420_buffer->DataU();
sprang@webrtc.org25dd1db2015-03-02 11:55:45 +000073 for (int i = 0; i < uv_size; ++i)
74 ASSERT_EQ(u, buffer[i]);
Magnus Jedvert90e31902017-06-07 11:32:50 +020075 buffer = i420_buffer->DataV();
sprang@webrtc.org25dd1db2015-03-02 11:55:45 +000076 for (int i = 0; i < uv_size; ++i)
77 ASSERT_EQ(v, buffer[i]);
78 EXPECT_EQ(0, frame->ntp_time_ms());
79 EXPECT_EQ(0, frame->render_time_ms());
80 EXPECT_EQ(0u, frame->timestamp());
81
82 // Mutate to something arbitrary non-zero.
83 frame->set_ntp_time_ms(11);
nisse1c0dea82017-01-30 02:43:18 -080084 frame->set_timestamp_us(12);
sprang@webrtc.org25dd1db2015-03-02 11:55:45 +000085 frame->set_timestamp(13);
86 }
87
erikvarga579de6f2017-08-29 09:12:57 -070088 uint64_t Hash(VideoFrame* frame) {
89 // Generate a 64-bit hash from the frame's buffer.
90 uint64_t hash = 19;
91 rtc::scoped_refptr<I420BufferInterface> i420_buffer =
92 frame->video_frame_buffer()->ToI420();
93 const uint8_t* buffer = i420_buffer->DataY();
94 for (int i = 0; i < y_size; ++i) {
95 hash = (37 * hash) + buffer[i];
96 }
97 buffer = i420_buffer->DataU();
98 for (int i = 0; i < uv_size; ++i) {
99 hash = (37 * hash) + buffer[i];
100 }
101 buffer = i420_buffer->DataV();
102 for (int i = 0; i < uv_size; ++i) {
103 hash = (37 * hash) + buffer[i];
104 }
105 return hash;
106 }
107
sprang@webrtc.org25dd1db2015-03-02 11:55:45 +0000108 std::string two_frame_filename_;
109 std::string one_frame_filename_;
110 const int y_size = kFrameWidth * kFrameHeight;
111 const int uv_size = ((kFrameHeight + 1) / 2) * ((kFrameWidth + 1) / 2);
112};
113
114TEST_F(FrameGeneratorTest, SingleFrameFile) {
kwibergbfefb032016-05-01 14:53:46 -0700115 std::unique_ptr<FrameGenerator> generator(FrameGenerator::CreateFromYuvFile(
sprang@webrtc.org25dd1db2015-03-02 11:55:45 +0000116 std::vector<std::string>(1, one_frame_filename_), kFrameWidth,
117 kFrameHeight, 1));
118 CheckFrameAndMutate(generator->NextFrame(), 255, 255, 255);
119 CheckFrameAndMutate(generator->NextFrame(), 255, 255, 255);
120}
121
122TEST_F(FrameGeneratorTest, TwoFrameFile) {
kwibergbfefb032016-05-01 14:53:46 -0700123 std::unique_ptr<FrameGenerator> generator(FrameGenerator::CreateFromYuvFile(
sprang@webrtc.org25dd1db2015-03-02 11:55:45 +0000124 std::vector<std::string>(1, two_frame_filename_), kFrameWidth,
125 kFrameHeight, 1));
126 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
kwibergbfefb032016-05-01 14:53:46 -0700136 std::unique_ptr<FrameGenerator> generator(
sprang@webrtc.org25dd1db2015-03-02 11:55:45 +0000137 FrameGenerator::CreateFromYuvFile(files, kFrameWidth, kFrameHeight, 1));
138 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;
kwibergbfefb032016-05-01 14:53:46 -0700146 std::unique_ptr<FrameGenerator> generator(FrameGenerator::CreateFromYuvFile(
sprang@webrtc.org25dd1db2015-03-02 11:55:45 +0000147 std::vector<std::string>(1, two_frame_filename_), kFrameWidth,
148 kFrameHeight, kRepeatCount));
149 for (int i = 0; i < kRepeatCount; ++i)
150 CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
151 for (int i = 0; i < kRepeatCount; ++i)
152 CheckFrameAndMutate(generator->NextFrame(), 127, 127, 127);
153 CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
154}
155
156TEST_F(FrameGeneratorTest, MultipleFrameFilesWithRepeat) {
157 const int kRepeatCount = 3;
158 std::vector<std::string> files;
159 files.push_back(two_frame_filename_);
160 files.push_back(one_frame_filename_);
kwibergbfefb032016-05-01 14:53:46 -0700161 std::unique_ptr<FrameGenerator> generator(FrameGenerator::CreateFromYuvFile(
sprang@webrtc.org25dd1db2015-03-02 11:55:45 +0000162 files, kFrameWidth, kFrameHeight, kRepeatCount));
163 for (int i = 0; i < kRepeatCount; ++i)
164 CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
165 for (int i = 0; i < kRepeatCount; ++i)
166 CheckFrameAndMutate(generator->NextFrame(), 127, 127, 127);
167 for (int i = 0; i < kRepeatCount; ++i)
168 CheckFrameAndMutate(generator->NextFrame(), 255, 255, 255);
169 CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
170}
171
erikvarga579de6f2017-08-29 09:12:57 -0700172TEST_F(FrameGeneratorTest, SlideGenerator) {
173 const int kGenCount = 9;
174 const int kRepeatCount = 3;
175 std::unique_ptr<FrameGenerator> generator(
Yves Gerey665174f2018-06-19 15:03:05 +0200176 FrameGenerator::CreateSlideGenerator(kFrameWidth, kFrameHeight,
177 kRepeatCount));
erikvarga579de6f2017-08-29 09:12:57 -0700178 uint64_t hashes[kGenCount];
179 for (int i = 0; i < kGenCount; ++i) {
180 hashes[i] = Hash(generator->NextFrame());
181 }
182 // Check that the buffer changes only every |kRepeatCount| frames.
183 for (int i = 1; i < kGenCount; ++i) {
184 if (i % kRepeatCount == 0) {
Yves Gerey665174f2018-06-19 15:03:05 +0200185 EXPECT_NE(hashes[i - 1], hashes[i]);
erikvarga579de6f2017-08-29 09:12:57 -0700186 } else {
Yves Gerey665174f2018-06-19 15:03:05 +0200187 EXPECT_EQ(hashes[i - 1], hashes[i]);
erikvarga579de6f2017-08-29 09:12:57 -0700188 }
189 }
190}
191
sprang@webrtc.org25dd1db2015-03-02 11:55:45 +0000192} // namespace test
193} // namespace webrtc