Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(136)

Side by Side Diff: media/cast/sender/video_encoder_impl_unittest.cc

Issue 892383002: RELAND: [Cast] Software encoder support for varying video frame sizes. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix for 'access to uninitialized memory' error. Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « media/cast/sender/video_encoder_impl.cc ('k') | media/cast/sender/video_sender.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <vector> 5 #include <vector>
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/memory/ref_counted.h" 8 #include "base/memory/ref_counted.h"
9 #include "base/memory/scoped_ptr.h" 9 #include "base/memory/scoped_ptr.h"
10 #include "media/base/video_frame.h" 10 #include "media/base/video_frame.h"
11 #include "media/cast/cast_defines.h" 11 #include "media/cast/cast_defines.h"
12 #include "media/cast/cast_environment.h" 12 #include "media/cast/cast_environment.h"
13 #include "media/cast/sender/video_encoder_impl.h" 13 #include "media/cast/sender/video_encoder_impl.h"
14 #include "media/cast/test/fake_single_thread_task_runner.h" 14 #include "media/cast/test/fake_single_thread_task_runner.h"
15 #include "media/cast/test/utility/default_config.h" 15 #include "media/cast/test/utility/default_config.h"
16 #include "media/cast/test/utility/video_utility.h" 16 #include "media/cast/test/utility/video_utility.h"
17 #include "testing/gmock/include/gmock/gmock.h" 17 #include "testing/gtest/include/gtest/gtest.h"
18 18
19 namespace media { 19 namespace media {
20 namespace cast { 20 namespace cast {
21 21
22 using testing::_; 22 class VideoEncoderImplTest : public ::testing::TestWithParam<Codec> {
23
24 namespace {
25 class TestVideoEncoderCallback
26 : public base::RefCountedThreadSafe<TestVideoEncoderCallback> {
27 public:
28 explicit TestVideoEncoderCallback(bool multiple_buffer_mode)
29 : multiple_buffer_mode_(multiple_buffer_mode),
30 count_frames_delivered_(0) {}
31
32 int count_frames_delivered() const {
33 return count_frames_delivered_;
34 }
35
36 void SetExpectedResult(uint32 expected_frame_id,
37 uint32 expected_last_referenced_frame_id,
38 uint32 expected_rtp_timestamp,
39 const base::TimeTicks& expected_reference_time) {
40 expected_frame_id_ = expected_frame_id;
41 expected_last_referenced_frame_id_ = expected_last_referenced_frame_id;
42 expected_rtp_timestamp_ = expected_rtp_timestamp;
43 expected_reference_time_ = expected_reference_time;
44 }
45
46 void DeliverEncodedVideoFrame(
47 scoped_ptr<EncodedFrame> encoded_frame) {
48 if (expected_frame_id_ != expected_last_referenced_frame_id_) {
49 EXPECT_EQ(EncodedFrame::DEPENDENT, encoded_frame->dependency);
50 } else if (!multiple_buffer_mode_) {
51 EXPECT_EQ(EncodedFrame::KEY, encoded_frame->dependency);
52 }
53 EXPECT_EQ(expected_frame_id_, encoded_frame->frame_id);
54 EXPECT_EQ(expected_last_referenced_frame_id_,
55 encoded_frame->referenced_frame_id)
56 << "frame id: " << expected_frame_id_;
57 EXPECT_EQ(expected_rtp_timestamp_, encoded_frame->rtp_timestamp);
58 EXPECT_EQ(expected_reference_time_, encoded_frame->reference_time);
59 EXPECT_FALSE(encoded_frame->data.empty());
60 ++count_frames_delivered_;
61 }
62
63 private:
64 friend class base::RefCountedThreadSafe<TestVideoEncoderCallback>;
65 virtual ~TestVideoEncoderCallback() {}
66
67 const bool multiple_buffer_mode_;
68 int count_frames_delivered_;
69
70 uint32 expected_frame_id_;
71 uint32 expected_last_referenced_frame_id_;
72 uint32 expected_rtp_timestamp_;
73 base::TimeTicks expected_reference_time_;
74
75 DISALLOW_COPY_AND_ASSIGN(TestVideoEncoderCallback);
76 };
77 } // namespace
78
79 class VideoEncoderImplTest : public ::testing::Test {
80 protected: 23 protected:
81 VideoEncoderImplTest() { 24 VideoEncoderImplTest()
82 video_config_ = GetDefaultVideoSenderConfig(); 25 : testing_clock_(new base::SimpleTestTickClock()),
83 video_config_.codec = CODEC_VIDEO_VP8; 26 task_runner_(new test::FakeSingleThreadTaskRunner(testing_clock_)),
84 gfx::Size size(video_config_.width, video_config_.height); 27 cast_environment_(new CastEnvironment(
85 video_frame_ = media::VideoFrame::CreateFrame( 28 scoped_ptr<base::TickClock>(testing_clock_).Pass(),
86 VideoFrame::I420, size, gfx::Rect(size), size, base::TimeDelta()); 29 task_runner_,
87 PopulateVideoFrame(video_frame_.get(), 123); 30 task_runner_,
31 task_runner_)),
32 video_config_(GetDefaultVideoSenderConfig()),
33 count_frames_delivered_(0) {
34 testing_clock_->Advance(base::TimeTicks::Now() - base::TimeTicks());
35 first_frame_time_ = testing_clock_->NowTicks();
88 } 36 }
89 37
90 ~VideoEncoderImplTest() override {} 38 ~VideoEncoderImplTest() override {}
91 39
92 void SetUp() override { 40 void SetUp() override {
93 testing_clock_ = new base::SimpleTestTickClock(); 41 video_config_.codec = GetParam();
94 testing_clock_->Advance(base::TimeTicks::Now() - base::TimeTicks());
95 task_runner_ = new test::FakeSingleThreadTaskRunner(testing_clock_);
96 cast_environment_ =
97 new CastEnvironment(scoped_ptr<base::TickClock>(testing_clock_).Pass(),
98 task_runner_,
99 task_runner_,
100 task_runner_);
101 } 42 }
102 43
103 void TearDown() override { 44 void TearDown() override {
104 video_encoder_.reset(); 45 video_encoder_.reset();
105 task_runner_->RunTasks(); 46 task_runner_->RunTasks();
106 } 47 }
107 48
108 void CreateEncoder() { 49 void CreateEncoder(bool three_buffer_mode) {
109 test_video_encoder_callback_ = new TestVideoEncoderCallback( 50 video_config_.max_number_of_video_buffers_used =
110 video_config_.max_number_of_video_buffers_used != 1); 51 (three_buffer_mode ? 3 : 1);
111 video_encoder_.reset( 52 video_encoder_.reset(new VideoEncoderImpl(
112 new VideoEncoderImpl(cast_environment_, video_config_)); 53 cast_environment_,
113 } 54 video_config_,
114 55 CastInitializationCallback()));
115 void AdvanceClockAndVideoFrameTimestamp() { 56 task_runner_->RunTasks();
57 }
58
59 VideoEncoder* video_encoder() const {
60 return video_encoder_.get();
61 }
62
63 void AdvanceClock() {
116 testing_clock_->Advance(base::TimeDelta::FromMilliseconds(33)); 64 testing_clock_->Advance(base::TimeDelta::FromMilliseconds(33));
117 video_frame_->set_timestamp( 65 }
118 video_frame_->timestamp() + base::TimeDelta::FromMilliseconds(33)); 66
119 } 67 base::TimeTicks Now() const {
120 68 return testing_clock_->NowTicks();
121 base::SimpleTestTickClock* testing_clock_; // Owned by CastEnvironment. 69 }
122 scoped_refptr<TestVideoEncoderCallback> test_video_encoder_callback_; 70
71 void RunTasks() const {
72 return task_runner_->RunTasks();
73 }
74
75 int count_frames_delivered() const {
76 return count_frames_delivered_;
77 }
78
79 // Return a callback that, when run, expects the EncodedFrame to have the
80 // given properties.
81 VideoEncoder::FrameEncodedCallback CreateFrameDeliverCallback(
82 uint32 expected_frame_id,
83 uint32 expected_last_referenced_frame_id,
84 uint32 expected_rtp_timestamp,
85 const base::TimeTicks& expected_reference_time) {
86 return base::Bind(&VideoEncoderImplTest::DeliverEncodedVideoFrame,
87 base::Unretained(this),
88 expected_frame_id,
89 expected_last_referenced_frame_id,
90 expected_rtp_timestamp,
91 expected_reference_time);
92 }
93
94 // Creates a new VideoFrame of the given |size|, filled with a test pattern.
95 scoped_refptr<media::VideoFrame> CreateTestVideoFrame(
96 const gfx::Size& size) const {
97 const scoped_refptr<media::VideoFrame> frame =
98 media::VideoFrame::CreateFrame(
99 VideoFrame::I420, size, gfx::Rect(size), size,
100 testing_clock_->NowTicks() - first_frame_time_);
101 PopulateVideoFrame(frame.get(), 123);
102 return frame;
103 }
104
105 private:
106 // Checks that |encoded_frame| matches expected values. This is the method
107 // bound in the callback returned from CreateFrameDeliverCallback().
108 void DeliverEncodedVideoFrame(
109 uint32 expected_frame_id,
110 uint32 expected_last_referenced_frame_id,
111 uint32 expected_rtp_timestamp,
112 const base::TimeTicks& expected_reference_time,
113 scoped_ptr<EncodedFrame> encoded_frame) {
114 if (expected_frame_id != expected_last_referenced_frame_id) {
115 EXPECT_EQ(EncodedFrame::DEPENDENT, encoded_frame->dependency);
116 } else if (video_config_.max_number_of_video_buffers_used == 1) {
117 EXPECT_EQ(EncodedFrame::KEY, encoded_frame->dependency);
118 }
119 EXPECT_EQ(expected_frame_id, encoded_frame->frame_id);
120 EXPECT_EQ(expected_last_referenced_frame_id,
121 encoded_frame->referenced_frame_id)
122 << "frame id: " << expected_frame_id;
123 EXPECT_EQ(expected_rtp_timestamp, encoded_frame->rtp_timestamp);
124 EXPECT_EQ(expected_reference_time, encoded_frame->reference_time);
125 EXPECT_FALSE(encoded_frame->data.empty());
126 ++count_frames_delivered_;
127 }
128
129 base::SimpleTestTickClock* const testing_clock_; // Owned by CastEnvironment.
130 const scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_;
131 const scoped_refptr<CastEnvironment> cast_environment_;
123 VideoSenderConfig video_config_; 132 VideoSenderConfig video_config_;
124 scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_; 133 base::TimeTicks first_frame_time_;
125 scoped_ptr<VideoEncoder> video_encoder_; 134 scoped_ptr<VideoEncoder> video_encoder_;
126 scoped_refptr<media::VideoFrame> video_frame_; 135
127 136 int count_frames_delivered_;
128 scoped_refptr<CastEnvironment> cast_environment_;
129 137
130 DISALLOW_COPY_AND_ASSIGN(VideoEncoderImplTest); 138 DISALLOW_COPY_AND_ASSIGN(VideoEncoderImplTest);
131 }; 139 };
132 140
133 TEST_F(VideoEncoderImplTest, GeneratesKeyFrameThenOnlyDeltaFrames) { 141 // A simple test to encode ten frames of video, expecting to see one key frame
134 CreateEncoder(); 142 // followed by nine delta frames.
135 143 TEST_P(VideoEncoderImplTest, GeneratesKeyFrameThenOnlyDeltaFrames) {
136 VideoEncoder::FrameEncodedCallback frame_encoded_callback = 144 CreateEncoder(false);
137 base::Bind(&TestVideoEncoderCallback::DeliverEncodedVideoFrame, 145
138 test_video_encoder_callback_.get()); 146 EXPECT_EQ(0, count_frames_delivered());
139 147
140 EXPECT_EQ(0, test_video_encoder_callback_->count_frames_delivered()); 148 scoped_refptr<media::VideoFrame> video_frame =
141 149 CreateTestVideoFrame(gfx::Size(1280, 720));
142 test_video_encoder_callback_->SetExpectedResult( 150 EXPECT_TRUE(video_encoder()->EncodeVideoFrame(
143 0, 0, TimeDeltaToRtpDelta(video_frame_->timestamp(), kVideoFrequency), 151 video_frame,
144 testing_clock_->NowTicks()); 152 Now(),
145 EXPECT_TRUE(video_encoder_->EncodeVideoFrame( 153 CreateFrameDeliverCallback(
146 video_frame_, testing_clock_->NowTicks(), frame_encoded_callback)); 154 0, 0, TimeDeltaToRtpDelta(video_frame->timestamp(), kVideoFrequency),
147 task_runner_->RunTasks(); 155 Now())));
156 RunTasks();
148 157
149 for (uint32 frame_id = 1; frame_id < 10; ++frame_id) { 158 for (uint32 frame_id = 1; frame_id < 10; ++frame_id) {
150 AdvanceClockAndVideoFrameTimestamp(); 159 AdvanceClock();
151 test_video_encoder_callback_->SetExpectedResult( 160 video_frame = CreateTestVideoFrame(gfx::Size(1280, 720));
152 frame_id, 161 EXPECT_TRUE(video_encoder()->EncodeVideoFrame(
153 frame_id - 1, 162 video_frame,
154 TimeDeltaToRtpDelta(video_frame_->timestamp(), kVideoFrequency), 163 Now(),
155 testing_clock_->NowTicks()); 164 CreateFrameDeliverCallback(
156 EXPECT_TRUE(video_encoder_->EncodeVideoFrame( 165 frame_id, frame_id - 1,
157 video_frame_, testing_clock_->NowTicks(), frame_encoded_callback)); 166 TimeDeltaToRtpDelta(video_frame->timestamp(), kVideoFrequency),
158 task_runner_->RunTasks(); 167 Now())));
159 } 168 RunTasks();
160 169 }
161 EXPECT_EQ(10, test_video_encoder_callback_->count_frames_delivered()); 170
171 EXPECT_EQ(10, count_frames_delivered());
162 } 172 }
163 173
164 TEST_F(VideoEncoderImplTest, 174 // Tests basic frame dependency rules when using the VP8 encoder in multi-buffer
175 // mode.
176 TEST_P(VideoEncoderImplTest,
165 FramesDoNotDependOnUnackedFramesInMultiBufferMode) { 177 FramesDoNotDependOnUnackedFramesInMultiBufferMode) {
166 video_config_.max_number_of_video_buffers_used = 3; 178 if (GetParam() != CODEC_VIDEO_VP8)
167 CreateEncoder(); 179 return; // Only test multibuffer mode for the VP8 encoder.
168 180 CreateEncoder(true);
169 VideoEncoder::FrameEncodedCallback frame_encoded_callback = 181
170 base::Bind(&TestVideoEncoderCallback::DeliverEncodedVideoFrame, 182 EXPECT_EQ(0, count_frames_delivered());
171 test_video_encoder_callback_.get()); 183
172 184 scoped_refptr<media::VideoFrame> video_frame =
173 EXPECT_EQ(0, test_video_encoder_callback_->count_frames_delivered()); 185 CreateTestVideoFrame(gfx::Size(1280, 720));
174 186 EXPECT_TRUE(video_encoder()->EncodeVideoFrame(
175 test_video_encoder_callback_->SetExpectedResult( 187 video_frame,
176 0, 0, TimeDeltaToRtpDelta(video_frame_->timestamp(), kVideoFrequency), 188 Now(),
177 testing_clock_->NowTicks()); 189 CreateFrameDeliverCallback(
178 EXPECT_TRUE(video_encoder_->EncodeVideoFrame( 190 0, 0, TimeDeltaToRtpDelta(video_frame->timestamp(), kVideoFrequency),
179 video_frame_, testing_clock_->NowTicks(), frame_encoded_callback)); 191 Now())));
180 task_runner_->RunTasks(); 192 RunTasks();
181 193
182 AdvanceClockAndVideoFrameTimestamp(); 194 AdvanceClock();
183 video_encoder_->LatestFrameIdToReference(0); 195 video_encoder()->LatestFrameIdToReference(0);
184 test_video_encoder_callback_->SetExpectedResult( 196 video_frame = CreateTestVideoFrame(gfx::Size(1280, 720));
185 1, 0, TimeDeltaToRtpDelta(video_frame_->timestamp(), kVideoFrequency), 197 EXPECT_TRUE(video_encoder()->EncodeVideoFrame(
186 testing_clock_->NowTicks()); 198 video_frame,
187 EXPECT_TRUE(video_encoder_->EncodeVideoFrame( 199 Now(),
188 video_frame_, testing_clock_->NowTicks(), frame_encoded_callback)); 200 CreateFrameDeliverCallback(
189 task_runner_->RunTasks(); 201 1, 0, TimeDeltaToRtpDelta(video_frame->timestamp(), kVideoFrequency),
190 202 Now())));
191 AdvanceClockAndVideoFrameTimestamp(); 203 RunTasks();
192 video_encoder_->LatestFrameIdToReference(1); 204
193 test_video_encoder_callback_->SetExpectedResult( 205 AdvanceClock();
194 2, 1, TimeDeltaToRtpDelta(video_frame_->timestamp(), kVideoFrequency), 206 video_encoder()->LatestFrameIdToReference(1);
195 testing_clock_->NowTicks()); 207 video_frame = CreateTestVideoFrame(gfx::Size(1280, 720));
196 EXPECT_TRUE(video_encoder_->EncodeVideoFrame( 208 EXPECT_TRUE(video_encoder()->EncodeVideoFrame(
197 video_frame_, testing_clock_->NowTicks(), frame_encoded_callback)); 209 video_frame,
198 task_runner_->RunTasks(); 210 Now(),
199 211 CreateFrameDeliverCallback(
200 video_encoder_->LatestFrameIdToReference(2); 212 2, 1, TimeDeltaToRtpDelta(video_frame->timestamp(), kVideoFrequency),
213 Now())));
214 RunTasks();
215
216 video_encoder()->LatestFrameIdToReference(2);
201 217
202 for (uint32 frame_id = 3; frame_id < 10; ++frame_id) { 218 for (uint32 frame_id = 3; frame_id < 10; ++frame_id) {
203 AdvanceClockAndVideoFrameTimestamp(); 219 AdvanceClock();
204 test_video_encoder_callback_->SetExpectedResult( 220 video_frame = CreateTestVideoFrame(gfx::Size(1280, 720));
205 frame_id, 2, 221 EXPECT_TRUE(video_encoder()->EncodeVideoFrame(
206 TimeDeltaToRtpDelta(video_frame_->timestamp(), kVideoFrequency), 222 video_frame,
207 testing_clock_->NowTicks()); 223 Now(),
208 EXPECT_TRUE(video_encoder_->EncodeVideoFrame( 224 CreateFrameDeliverCallback(
209 video_frame_, testing_clock_->NowTicks(), frame_encoded_callback)); 225 frame_id, 2,
210 task_runner_->RunTasks(); 226 TimeDeltaToRtpDelta(video_frame->timestamp(), kVideoFrequency),
211 } 227 Now())));
212 228 RunTasks();
213 EXPECT_EQ(10, test_video_encoder_callback_->count_frames_delivered()); 229 }
230
231 EXPECT_EQ(10, count_frames_delivered());
214 } 232 }
215 233
234 // Tests that the encoder continues to output EncodedFrames as the frame size
235 // changes. See media/cast/receiver/video_decoder_unittest.cc for a complete
236 // encode/decode cycle of varied frame sizes that actually checks the frame
237 // content.
238 TEST_P(VideoEncoderImplTest, EncodesVariedFrameSizes) {
239 CreateEncoder(false);
240 ASSERT_TRUE(video_encoder()->CanEncodeVariedFrameSizes());
241
242 EXPECT_EQ(0, count_frames_delivered());
243
244 std::vector<gfx::Size> frame_sizes;
245 frame_sizes.push_back(gfx::Size(1280, 720));
246 frame_sizes.push_back(gfx::Size(640, 360)); // Shrink both dimensions.
247 frame_sizes.push_back(gfx::Size(300, 200)); // Shrink both dimensions again.
248 frame_sizes.push_back(gfx::Size(200, 300)); // Same area.
249 frame_sizes.push_back(gfx::Size(600, 400)); // Grow both dimensions.
250 frame_sizes.push_back(gfx::Size(638, 400)); // Shrink only one dimension.
251 frame_sizes.push_back(gfx::Size(638, 398)); // Shrink the other dimension.
252 frame_sizes.push_back(gfx::Size(320, 180)); // Shrink both dimensions again.
253 frame_sizes.push_back(gfx::Size(322, 180)); // Grow only one dimension.
254 frame_sizes.push_back(gfx::Size(322, 182)); // Grow the other dimension.
255 frame_sizes.push_back(gfx::Size(1920, 1080)); // Grow both dimensions again.
256
257 uint32 frame_id = 0;
258
259 // Encode one frame at each size. Expect nothing but key frames to come out.
260 for (const auto& frame_size : frame_sizes) {
261 AdvanceClock();
262 const scoped_refptr<media::VideoFrame> video_frame =
263 CreateTestVideoFrame(frame_size);
264 EXPECT_TRUE(video_encoder()->EncodeVideoFrame(
265 video_frame,
266 Now(),
267 CreateFrameDeliverCallback(
268 frame_id,
269 frame_id,
270 TimeDeltaToRtpDelta(video_frame->timestamp(), kVideoFrequency),
271 Now())));
272 RunTasks();
273 ++frame_id;
274 }
275
276 // Encode 10 frames at each size. Expect one key frame followed by nine delta
277 // frames for each frame size.
278 for (const auto& frame_size : frame_sizes) {
279 for (int i = 0; i < 10; ++i) {
280 AdvanceClock();
281 const scoped_refptr<media::VideoFrame> video_frame =
282 CreateTestVideoFrame(frame_size);
283 EXPECT_TRUE(video_encoder()->EncodeVideoFrame(
284 video_frame,
285 Now(),
286 CreateFrameDeliverCallback(
287 frame_id,
288 i == 0 ? frame_id : frame_id - 1,
289 TimeDeltaToRtpDelta(video_frame->timestamp(), kVideoFrequency),
290 Now())));
291 RunTasks();
292 ++frame_id;
293 }
294 }
295
296 EXPECT_EQ(static_cast<int>(frame_id), count_frames_delivered());
297 }
298
299 INSTANTIATE_TEST_CASE_P(,
300 VideoEncoderImplTest,
301 ::testing::Values(CODEC_VIDEO_FAKE, CODEC_VIDEO_VP8));
302
216 } // namespace cast 303 } // namespace cast
217 } // namespace media 304 } // namespace media
OLDNEW
« no previous file with comments | « media/cast/sender/video_encoder_impl.cc ('k') | media/cast/sender/video_sender.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698