OLD | NEW |
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 #include <utility> |
6 | 7 |
7 #include "base/bind.h" | 8 #include "base/bind.h" |
8 #include "base/memory/ref_counted.h" | 9 #include "base/memory/ref_counted.h" |
9 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
10 #include "media/base/video_frame.h" | 11 #include "media/base/video_frame.h" |
11 #include "media/cast/cast_defines.h" | 12 #include "media/cast/cast_defines.h" |
12 #include "media/cast/cast_environment.h" | 13 #include "media/cast/cast_environment.h" |
13 #include "media/cast/sender/video_encoder_impl.h" | 14 #include "media/cast/sender/fake_video_encode_accelerator_factory.h" |
| 15 #include "media/cast/sender/video_frame_factory.h" |
| 16 #include "media/cast/sender/video_encoder.h" |
14 #include "media/cast/test/fake_single_thread_task_runner.h" | 17 #include "media/cast/test/fake_single_thread_task_runner.h" |
15 #include "media/cast/test/utility/default_config.h" | 18 #include "media/cast/test/utility/default_config.h" |
16 #include "media/cast/test/utility/video_utility.h" | 19 #include "media/cast/test/utility/video_utility.h" |
17 #include "testing/gtest/include/gtest/gtest.h" | 20 #include "testing/gtest/include/gtest/gtest.h" |
18 | 21 |
| 22 #if defined(OS_MACOSX) |
| 23 #include "media/cast/sender/h264_vt_encoder.h" |
| 24 #endif |
| 25 |
19 namespace media { | 26 namespace media { |
20 namespace cast { | 27 namespace cast { |
21 | 28 |
22 class VideoEncoderImplTest : public ::testing::TestWithParam<Codec> { | 29 class VideoEncoderTest |
| 30 : public ::testing::TestWithParam<std::pair<Codec, bool>> { |
23 protected: | 31 protected: |
24 VideoEncoderImplTest() | 32 VideoEncoderTest() |
25 : testing_clock_(new base::SimpleTestTickClock()), | 33 : testing_clock_(new base::SimpleTestTickClock()), |
26 task_runner_(new test::FakeSingleThreadTaskRunner(testing_clock_)), | 34 task_runner_(new test::FakeSingleThreadTaskRunner(testing_clock_)), |
27 cast_environment_(new CastEnvironment( | 35 cast_environment_(new CastEnvironment( |
28 scoped_ptr<base::TickClock>(testing_clock_).Pass(), | 36 scoped_ptr<base::TickClock>(testing_clock_).Pass(), |
29 task_runner_, | 37 task_runner_, |
30 task_runner_, | 38 task_runner_, |
31 task_runner_)), | 39 task_runner_)), |
32 video_config_(GetDefaultVideoSenderConfig()), | 40 video_config_(GetDefaultVideoSenderConfig()), |
33 operational_status_(STATUS_UNINITIALIZED), | 41 operational_status_(STATUS_UNINITIALIZED), |
34 count_frames_delivered_(0) { | 42 count_frames_delivered_(0) { |
35 testing_clock_->Advance(base::TimeTicks::Now() - base::TimeTicks()); | 43 testing_clock_->Advance(base::TimeTicks::Now() - base::TimeTicks()); |
36 first_frame_time_ = testing_clock_->NowTicks(); | 44 first_frame_time_ = testing_clock_->NowTicks(); |
37 } | 45 } |
38 | 46 |
39 ~VideoEncoderImplTest() override {} | 47 ~VideoEncoderTest() override {} |
40 | 48 |
41 void SetUp() override { | 49 void SetUp() override { |
42 video_config_.codec = GetParam(); | 50 video_config_.codec = GetParam().first; |
| 51 video_config_.use_external_encoder = GetParam().second; |
| 52 |
| 53 if (video_config_.use_external_encoder) |
| 54 vea_factory_.reset(new FakeVideoEncodeAcceleratorFactory(task_runner_)); |
43 } | 55 } |
44 | 56 |
45 void TearDown() override { | 57 void TearDown() override { |
46 video_encoder_.reset(); | 58 video_encoder_.reset(); |
47 task_runner_->RunTasks(); | 59 RunTasksAndAdvanceClock(); |
48 } | 60 } |
49 | 61 |
50 void CreateEncoder(bool three_buffer_mode) { | 62 void CreateEncoder(bool three_buffer_mode) { |
51 ASSERT_EQ(STATUS_UNINITIALIZED, operational_status_); | 63 ASSERT_EQ(STATUS_UNINITIALIZED, operational_status_); |
52 video_config_.max_number_of_video_buffers_used = | 64 video_config_.max_number_of_video_buffers_used = |
53 (three_buffer_mode ? 3 : 1); | 65 (three_buffer_mode ? 3 : 1); |
54 video_encoder_.reset(new VideoEncoderImpl( | 66 video_encoder_ = VideoEncoder::Create( |
55 cast_environment_, | 67 cast_environment_, |
56 video_config_, | 68 video_config_, |
57 base::Bind(&VideoEncoderImplTest::OnOperationalStatusChange, | 69 base::Bind(&VideoEncoderTest::OnOperationalStatusChange, |
58 base::Unretained(this)))); | 70 base::Unretained(this)), |
59 task_runner_->RunTasks(); | 71 base::Bind( |
60 ASSERT_EQ(STATUS_INITIALIZED, operational_status_); | 72 &FakeVideoEncodeAcceleratorFactory::CreateVideoEncodeAccelerator, |
| 73 base::Unretained(vea_factory_.get())), |
| 74 base::Bind(&FakeVideoEncodeAcceleratorFactory::CreateSharedMemory, |
| 75 base::Unretained(vea_factory_.get()))).Pass(); |
| 76 RunTasksAndAdvanceClock(); |
| 77 if (is_encoder_present()) |
| 78 ASSERT_EQ(STATUS_INITIALIZED, operational_status_); |
| 79 } |
| 80 |
| 81 bool is_encoder_present() const { |
| 82 return !!video_encoder_; |
| 83 } |
| 84 |
| 85 bool is_testing_software_vp8_encoder() const { |
| 86 return video_config_.codec == CODEC_VIDEO_VP8 && |
| 87 !video_config_.use_external_encoder; |
| 88 } |
| 89 |
| 90 bool is_testing_video_toolbox_encoder() const { |
| 91 return |
| 92 #if defined(OS_MACOSX) |
| 93 (!video_config_.use_external_encoder && |
| 94 H264VideoToolboxEncoder::IsSupported(video_config_)) || |
| 95 #endif |
| 96 false; |
| 97 } |
| 98 |
| 99 bool is_testing_platform_encoder() const { |
| 100 return video_config_.use_external_encoder || |
| 101 is_testing_video_toolbox_encoder(); |
61 } | 102 } |
62 | 103 |
63 VideoEncoder* video_encoder() const { | 104 VideoEncoder* video_encoder() const { |
64 return video_encoder_.get(); | 105 return video_encoder_.get(); |
65 } | 106 } |
66 | 107 |
67 void AdvanceClock() { | 108 void DestroyEncoder() { |
68 testing_clock_->Advance(base::TimeDelta::FromMilliseconds(33)); | 109 video_encoder_.reset(); |
69 } | 110 } |
70 | 111 |
71 base::TimeTicks Now() const { | 112 base::TimeTicks Now() const { |
72 return testing_clock_->NowTicks(); | 113 return testing_clock_->NowTicks(); |
73 } | 114 } |
74 | 115 |
75 void RunTasks() const { | 116 void RunTasksAndAdvanceClock() const { |
76 return task_runner_->RunTasks(); | 117 const base::TimeDelta frame_duration = base::TimeDelta::FromMicroseconds( |
| 118 1000000.0 / video_config_.max_frame_rate); |
| 119 #if defined(OS_MACOSX) |
| 120 if (is_testing_video_toolbox_encoder()) { |
| 121 // The H264VideoToolboxEncoder (on MAC_OSX and IOS) is not a faked |
| 122 // implementation in these tests, and performs its encoding asynchronously |
| 123 // on an unknown set of threads. Therefore, sleep the current thread for |
| 124 // the real amount of time to avoid excessively spinning the CPU while |
| 125 // waiting for something to happen. |
| 126 base::PlatformThread::Sleep(frame_duration); |
| 127 } |
| 128 #endif |
| 129 task_runner_->RunTasks(); |
| 130 testing_clock_->Advance(frame_duration); |
77 } | 131 } |
78 | 132 |
79 int count_frames_delivered() const { | 133 int count_frames_delivered() const { |
80 return count_frames_delivered_; | 134 return count_frames_delivered_; |
81 } | 135 } |
82 | 136 |
83 // Return a callback that, when run, expects the EncodedFrame to have the | 137 void WaitForAllFramesToBeDelivered(int total_expected) const { |
84 // given properties. | 138 video_encoder_->EmitFrames(); |
85 VideoEncoder::FrameEncodedCallback CreateFrameDeliverCallback( | 139 while (count_frames_delivered_ < total_expected) |
86 uint32 expected_frame_id, | 140 RunTasksAndAdvanceClock(); |
87 uint32 expected_last_referenced_frame_id, | |
88 uint32 expected_rtp_timestamp, | |
89 const base::TimeTicks& expected_reference_time) { | |
90 return base::Bind(&VideoEncoderImplTest::DeliverEncodedVideoFrame, | |
91 base::Unretained(this), | |
92 expected_frame_id, | |
93 expected_last_referenced_frame_id, | |
94 expected_rtp_timestamp, | |
95 expected_reference_time); | |
96 } | 141 } |
97 | 142 |
98 // Creates a new VideoFrame of the given |size|, filled with a test pattern. | 143 // Creates a new VideoFrame of the given |size|, filled with a test pattern. |
99 scoped_refptr<media::VideoFrame> CreateTestVideoFrame( | 144 // When available, it attempts to use the VideoFrameFactory provided by the |
100 const gfx::Size& size) const { | 145 // encoder. |
101 const scoped_refptr<media::VideoFrame> frame = | 146 scoped_refptr<media::VideoFrame> CreateTestVideoFrame(const gfx::Size& size) { |
102 media::VideoFrame::CreateFrame( | 147 const base::TimeDelta timestamp = |
103 VideoFrame::I420, size, gfx::Rect(size), size, | 148 testing_clock_->NowTicks() - first_frame_time_; |
104 testing_clock_->NowTicks() - first_frame_time_); | 149 scoped_refptr<media::VideoFrame> frame; |
| 150 if (video_frame_factory_) |
| 151 frame = video_frame_factory_->MaybeCreateFrame(size, timestamp); |
| 152 if (!frame) { |
| 153 frame = media::VideoFrame::CreateFrame( |
| 154 VideoFrame::I420, size, gfx::Rect(size), size, timestamp); |
| 155 } |
105 PopulateVideoFrame(frame.get(), 123); | 156 PopulateVideoFrame(frame.get(), 123); |
106 return frame; | 157 return frame; |
107 } | 158 } |
108 | 159 |
| 160 // Requests encoding the |video_frame| and has the resulting frame delivered |
| 161 // via a callback that checks for expected results. Returns false if the |
| 162 // encoder rejected the request. |
| 163 bool EncodeAndCheckDelivery( |
| 164 const scoped_refptr<media::VideoFrame>& video_frame, |
| 165 uint32 frame_id, |
| 166 uint32 reference_frame_id) { |
| 167 return video_encoder_->EncodeVideoFrame( |
| 168 video_frame, |
| 169 Now(), |
| 170 base::Bind(&VideoEncoderTest::DeliverEncodedVideoFrame, |
| 171 base::Unretained(this), |
| 172 frame_id, |
| 173 reference_frame_id, |
| 174 TimeDeltaToRtpDelta(video_frame->timestamp(), |
| 175 kVideoFrequency), |
| 176 Now())); |
| 177 } |
| 178 |
| 179 // If the implementation of |video_encoder_| is ExternalVideoEncoder, check |
| 180 // that the VEA factory has responded (by running the callbacks) a specific |
| 181 // number of times. Otherwise, check that the VEA factory is inactive. |
| 182 void ExpectVEAResponsesForExternalVideoEncoder( |
| 183 int vea_response_count, |
| 184 int shm_response_count) const { |
| 185 if (!vea_factory_) |
| 186 return; |
| 187 EXPECT_EQ(vea_response_count, vea_factory_->vea_response_count()); |
| 188 EXPECT_EQ(shm_response_count, vea_factory_->shm_response_count()); |
| 189 } |
| 190 |
| 191 void SetVEAFactoryAutoRespond(bool auto_respond) { |
| 192 if (vea_factory_) |
| 193 vea_factory_->SetAutoRespond(auto_respond); |
| 194 } |
| 195 |
109 private: | 196 private: |
110 void OnOperationalStatusChange(OperationalStatus status) { | 197 void OnOperationalStatusChange(OperationalStatus status) { |
| 198 DVLOG(1) << "OnOperationalStatusChange: from " << operational_status_ |
| 199 << " to " << status; |
111 operational_status_ = status; | 200 operational_status_ = status; |
| 201 |
| 202 EXPECT_TRUE(operational_status_ == STATUS_CODEC_REINIT_PENDING || |
| 203 operational_status_ == STATUS_INITIALIZED); |
| 204 |
| 205 // Create the VideoFrameFactory the first time status changes to |
| 206 // STATUS_INITIALIZED. |
| 207 if (operational_status_ == STATUS_INITIALIZED && !video_frame_factory_) |
| 208 video_frame_factory_ = video_encoder_->CreateVideoFrameFactory().Pass(); |
112 } | 209 } |
113 | 210 |
114 // Checks that |encoded_frame| matches expected values. This is the method | 211 // Checks that |encoded_frame| matches expected values. This is the method |
115 // bound in the callback returned from CreateFrameDeliverCallback(). | 212 // bound in the callback returned from EncodeAndCheckDelivery(). |
116 void DeliverEncodedVideoFrame( | 213 void DeliverEncodedVideoFrame( |
117 uint32 expected_frame_id, | 214 uint32 expected_frame_id, |
118 uint32 expected_last_referenced_frame_id, | 215 uint32 expected_last_referenced_frame_id, |
119 uint32 expected_rtp_timestamp, | 216 uint32 expected_rtp_timestamp, |
120 const base::TimeTicks& expected_reference_time, | 217 const base::TimeTicks& expected_reference_time, |
121 scoped_ptr<EncodedFrame> encoded_frame) { | 218 scoped_ptr<EncodedFrame> encoded_frame) { |
122 if (expected_frame_id != expected_last_referenced_frame_id) { | 219 EXPECT_TRUE(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
123 EXPECT_EQ(EncodedFrame::DEPENDENT, encoded_frame->dependency); | 220 |
124 } else if (video_config_.max_number_of_video_buffers_used == 1) { | |
125 EXPECT_EQ(EncodedFrame::KEY, encoded_frame->dependency); | |
126 } | |
127 EXPECT_EQ(expected_frame_id, encoded_frame->frame_id); | 221 EXPECT_EQ(expected_frame_id, encoded_frame->frame_id); |
128 EXPECT_EQ(expected_last_referenced_frame_id, | |
129 encoded_frame->referenced_frame_id) | |
130 << "frame id: " << expected_frame_id; | |
131 EXPECT_EQ(expected_rtp_timestamp, encoded_frame->rtp_timestamp); | 222 EXPECT_EQ(expected_rtp_timestamp, encoded_frame->rtp_timestamp); |
132 EXPECT_EQ(expected_reference_time, encoded_frame->reference_time); | 223 EXPECT_EQ(expected_reference_time, encoded_frame->reference_time); |
133 EXPECT_FALSE(encoded_frame->data.empty()); | 224 |
| 225 // The platform encoders are "black boxes" and may choose to vend key frames |
| 226 // and/or empty data at any time. The software encoders, however, should |
| 227 // strictly adhere to expected behavior. |
| 228 if (is_testing_platform_encoder()) { |
| 229 const bool expected_key_frame = |
| 230 expected_frame_id == expected_last_referenced_frame_id; |
| 231 const bool have_key_frame = |
| 232 encoded_frame->dependency == EncodedFrame::KEY; |
| 233 EXPECT_EQ(have_key_frame, |
| 234 encoded_frame->frame_id == encoded_frame->referenced_frame_id); |
| 235 LOG_IF(WARNING, expected_key_frame != have_key_frame) |
| 236 << "Platform encoder chose to emit a " |
| 237 << (have_key_frame ? "key" : "delta") |
| 238 << " frame instead of the expected kind @ frame_id=" |
| 239 << encoded_frame->frame_id; |
| 240 LOG_IF(WARNING, encoded_frame->data.empty()) |
| 241 << "Platform encoder returned an empty frame @ frame_id=" |
| 242 << encoded_frame->frame_id; |
| 243 } else { |
| 244 if (expected_frame_id != expected_last_referenced_frame_id) { |
| 245 EXPECT_EQ(EncodedFrame::DEPENDENT, encoded_frame->dependency); |
| 246 } else if (video_config_.max_number_of_video_buffers_used == 1) { |
| 247 EXPECT_EQ(EncodedFrame::KEY, encoded_frame->dependency); |
| 248 } |
| 249 EXPECT_EQ(expected_last_referenced_frame_id, |
| 250 encoded_frame->referenced_frame_id); |
| 251 EXPECT_FALSE(encoded_frame->data.empty()); |
| 252 } |
| 253 |
134 ++count_frames_delivered_; | 254 ++count_frames_delivered_; |
135 } | 255 } |
136 | 256 |
137 base::SimpleTestTickClock* const testing_clock_; // Owned by CastEnvironment. | 257 base::SimpleTestTickClock* const testing_clock_; // Owned by CastEnvironment. |
138 const scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_; | 258 const scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_; |
139 const scoped_refptr<CastEnvironment> cast_environment_; | 259 const scoped_refptr<CastEnvironment> cast_environment_; |
140 VideoSenderConfig video_config_; | 260 VideoSenderConfig video_config_; |
| 261 scoped_ptr<FakeVideoEncodeAcceleratorFactory> vea_factory_; |
141 base::TimeTicks first_frame_time_; | 262 base::TimeTicks first_frame_time_; |
142 OperationalStatus operational_status_; | 263 OperationalStatus operational_status_; |
143 scoped_ptr<VideoEncoder> video_encoder_; | 264 scoped_ptr<VideoEncoder> video_encoder_; |
| 265 scoped_ptr<VideoFrameFactory> video_frame_factory_; |
144 | 266 |
145 int count_frames_delivered_; | 267 int count_frames_delivered_; |
146 | 268 |
147 DISALLOW_COPY_AND_ASSIGN(VideoEncoderImplTest); | 269 DISALLOW_COPY_AND_ASSIGN(VideoEncoderTest); |
148 }; | 270 }; |
149 | 271 |
150 // A simple test to encode ten frames of video, expecting to see one key frame | 272 // A simple test to encode ten frames of video, expecting to see one key frame |
151 // followed by nine delta frames. | 273 // followed by nine delta frames. |
152 TEST_P(VideoEncoderImplTest, GeneratesKeyFrameThenOnlyDeltaFrames) { | 274 TEST_P(VideoEncoderTest, GeneratesKeyFrameThenOnlyDeltaFrames) { |
153 CreateEncoder(false); | 275 CreateEncoder(false); |
| 276 SetVEAFactoryAutoRespond(true); |
154 | 277 |
155 EXPECT_EQ(0, count_frames_delivered()); | 278 EXPECT_EQ(0, count_frames_delivered()); |
| 279 ExpectVEAResponsesForExternalVideoEncoder(0, 0); |
156 | 280 |
157 scoped_refptr<media::VideoFrame> video_frame = | 281 uint32 frame_id = 0; |
158 CreateTestVideoFrame(gfx::Size(1280, 720)); | 282 uint32 reference_frame_id = 0; |
159 EXPECT_TRUE(video_encoder()->EncodeVideoFrame( | 283 const gfx::Size frame_size(1280, 720); |
160 video_frame, | |
161 Now(), | |
162 CreateFrameDeliverCallback( | |
163 0, 0, TimeDeltaToRtpDelta(video_frame->timestamp(), kVideoFrequency), | |
164 Now()))); | |
165 RunTasks(); | |
166 | 284 |
167 for (uint32 frame_id = 1; frame_id < 10; ++frame_id) { | 285 // For the platform encoders, the first one or more frames is dropped while |
168 AdvanceClock(); | 286 // the encoder initializes. Then, for all encoders, expect one key frame is |
169 video_frame = CreateTestVideoFrame(gfx::Size(1280, 720)); | 287 // delivered. |
170 EXPECT_TRUE(video_encoder()->EncodeVideoFrame( | 288 bool accepted_first_frame = false; |
171 video_frame, | 289 do { |
172 Now(), | 290 accepted_first_frame = EncodeAndCheckDelivery( |
173 CreateFrameDeliverCallback( | 291 CreateTestVideoFrame(frame_size), frame_id, reference_frame_id); |
174 frame_id, frame_id - 1, | 292 if (!is_testing_platform_encoder()) |
175 TimeDeltaToRtpDelta(video_frame->timestamp(), kVideoFrequency), | 293 EXPECT_TRUE(accepted_first_frame); |
176 Now()))); | 294 RunTasksAndAdvanceClock(); |
177 RunTasks(); | 295 } while (!accepted_first_frame); |
| 296 ExpectVEAResponsesForExternalVideoEncoder(1, 3); |
| 297 |
| 298 // Expect the remaining frames are encoded as delta frames. |
| 299 for (++frame_id; frame_id < 10; ++frame_id, ++reference_frame_id) { |
| 300 EXPECT_TRUE(EncodeAndCheckDelivery(CreateTestVideoFrame(frame_size), |
| 301 frame_id, |
| 302 reference_frame_id)); |
| 303 RunTasksAndAdvanceClock(); |
178 } | 304 } |
179 | 305 |
180 EXPECT_EQ(10, count_frames_delivered()); | 306 WaitForAllFramesToBeDelivered(10); |
| 307 ExpectVEAResponsesForExternalVideoEncoder(1, 3); |
181 } | 308 } |
182 | 309 |
183 // Tests basic frame dependency rules when using the VP8 encoder in multi-buffer | 310 // Tests basic frame dependency rules when using the VP8 encoder in multi-buffer |
184 // mode. | 311 // mode. |
185 TEST_P(VideoEncoderImplTest, | 312 TEST_P(VideoEncoderTest, FramesDoNotDependOnUnackedFramesInMultiBufferMode) { |
186 FramesDoNotDependOnUnackedFramesInMultiBufferMode) { | 313 if (!is_testing_software_vp8_encoder()) |
187 if (GetParam() != CODEC_VIDEO_VP8) | 314 return; // Only test multibuffer mode for the software VP8 encoder. |
188 return; // Only test multibuffer mode for the VP8 encoder. | |
189 CreateEncoder(true); | 315 CreateEncoder(true); |
190 | 316 |
191 EXPECT_EQ(0, count_frames_delivered()); | 317 EXPECT_EQ(0, count_frames_delivered()); |
192 | 318 |
193 scoped_refptr<media::VideoFrame> video_frame = | 319 const gfx::Size frame_size(1280, 720); |
194 CreateTestVideoFrame(gfx::Size(1280, 720)); | 320 EXPECT_TRUE(EncodeAndCheckDelivery(CreateTestVideoFrame(frame_size), 0, 0)); |
195 EXPECT_TRUE(video_encoder()->EncodeVideoFrame( | 321 RunTasksAndAdvanceClock(); |
196 video_frame, | |
197 Now(), | |
198 CreateFrameDeliverCallback( | |
199 0, 0, TimeDeltaToRtpDelta(video_frame->timestamp(), kVideoFrequency), | |
200 Now()))); | |
201 RunTasks(); | |
202 | 322 |
203 AdvanceClock(); | |
204 video_encoder()->LatestFrameIdToReference(0); | 323 video_encoder()->LatestFrameIdToReference(0); |
205 video_frame = CreateTestVideoFrame(gfx::Size(1280, 720)); | 324 EXPECT_TRUE(EncodeAndCheckDelivery(CreateTestVideoFrame(frame_size), 1, 0)); |
206 EXPECT_TRUE(video_encoder()->EncodeVideoFrame( | 325 RunTasksAndAdvanceClock(); |
207 video_frame, | |
208 Now(), | |
209 CreateFrameDeliverCallback( | |
210 1, 0, TimeDeltaToRtpDelta(video_frame->timestamp(), kVideoFrequency), | |
211 Now()))); | |
212 RunTasks(); | |
213 | 326 |
214 AdvanceClock(); | |
215 video_encoder()->LatestFrameIdToReference(1); | 327 video_encoder()->LatestFrameIdToReference(1); |
216 video_frame = CreateTestVideoFrame(gfx::Size(1280, 720)); | 328 EXPECT_TRUE(EncodeAndCheckDelivery(CreateTestVideoFrame(frame_size), 2, 1)); |
217 EXPECT_TRUE(video_encoder()->EncodeVideoFrame( | 329 RunTasksAndAdvanceClock(); |
218 video_frame, | |
219 Now(), | |
220 CreateFrameDeliverCallback( | |
221 2, 1, TimeDeltaToRtpDelta(video_frame->timestamp(), kVideoFrequency), | |
222 Now()))); | |
223 RunTasks(); | |
224 | 330 |
225 video_encoder()->LatestFrameIdToReference(2); | 331 video_encoder()->LatestFrameIdToReference(2); |
226 | 332 |
227 for (uint32 frame_id = 3; frame_id < 10; ++frame_id) { | 333 for (uint32 frame_id = 3; frame_id < 10; ++frame_id) { |
228 AdvanceClock(); | 334 EXPECT_TRUE(EncodeAndCheckDelivery( |
229 video_frame = CreateTestVideoFrame(gfx::Size(1280, 720)); | 335 CreateTestVideoFrame(frame_size), frame_id, 2)); |
230 EXPECT_TRUE(video_encoder()->EncodeVideoFrame( | 336 RunTasksAndAdvanceClock(); |
231 video_frame, | |
232 Now(), | |
233 CreateFrameDeliverCallback( | |
234 frame_id, 2, | |
235 TimeDeltaToRtpDelta(video_frame->timestamp(), kVideoFrequency), | |
236 Now()))); | |
237 RunTasks(); | |
238 } | 337 } |
239 | 338 |
240 EXPECT_EQ(10, count_frames_delivered()); | 339 EXPECT_EQ(10, count_frames_delivered()); |
241 } | 340 } |
242 | 341 |
243 // Tests that the encoder continues to output EncodedFrames as the frame size | 342 // Tests that the encoder continues to output EncodedFrames as the frame size |
244 // changes. See media/cast/receiver/video_decoder_unittest.cc for a complete | 343 // changes. See media/cast/receiver/video_decoder_unittest.cc for a complete |
245 // encode/decode cycle of varied frame sizes that actually checks the frame | 344 // encode/decode cycle of varied frame sizes that actually checks the frame |
246 // content. | 345 // content. |
247 TEST_P(VideoEncoderImplTest, EncodesVariedFrameSizes) { | 346 TEST_P(VideoEncoderTest, EncodesVariedFrameSizes) { |
248 CreateEncoder(false); | 347 CreateEncoder(false); |
249 ASSERT_TRUE(video_encoder()->CanEncodeVariedFrameSizes()); | 348 SetVEAFactoryAutoRespond(true); |
250 | 349 |
251 EXPECT_EQ(0, count_frames_delivered()); | 350 EXPECT_EQ(0, count_frames_delivered()); |
| 351 ExpectVEAResponsesForExternalVideoEncoder(0, 0); |
252 | 352 |
253 std::vector<gfx::Size> frame_sizes; | 353 std::vector<gfx::Size> frame_sizes; |
254 frame_sizes.push_back(gfx::Size(1280, 720)); | 354 frame_sizes.push_back(gfx::Size(1280, 720)); |
255 frame_sizes.push_back(gfx::Size(640, 360)); // Shrink both dimensions. | 355 frame_sizes.push_back(gfx::Size(640, 360)); // Shrink both dimensions. |
256 frame_sizes.push_back(gfx::Size(300, 200)); // Shrink both dimensions again. | 356 frame_sizes.push_back(gfx::Size(300, 200)); // Shrink both dimensions again. |
257 frame_sizes.push_back(gfx::Size(200, 300)); // Same area. | 357 frame_sizes.push_back(gfx::Size(200, 300)); // Same area. |
258 frame_sizes.push_back(gfx::Size(600, 400)); // Grow both dimensions. | 358 frame_sizes.push_back(gfx::Size(600, 400)); // Grow both dimensions. |
259 frame_sizes.push_back(gfx::Size(638, 400)); // Shrink only one dimension. | 359 frame_sizes.push_back(gfx::Size(638, 400)); // Shrink only one dimension. |
260 frame_sizes.push_back(gfx::Size(638, 398)); // Shrink the other dimension. | 360 frame_sizes.push_back(gfx::Size(638, 398)); // Shrink the other dimension. |
261 frame_sizes.push_back(gfx::Size(320, 180)); // Shrink both dimensions again. | 361 frame_sizes.push_back(gfx::Size(320, 180)); // Shrink both dimensions again. |
262 frame_sizes.push_back(gfx::Size(322, 180)); // Grow only one dimension. | 362 frame_sizes.push_back(gfx::Size(322, 180)); // Grow only one dimension. |
263 frame_sizes.push_back(gfx::Size(322, 182)); // Grow the other dimension. | 363 frame_sizes.push_back(gfx::Size(322, 182)); // Grow the other dimension. |
264 frame_sizes.push_back(gfx::Size(1920, 1080)); // Grow both dimensions again. | 364 frame_sizes.push_back(gfx::Size(1920, 1080)); // Grow both dimensions again. |
265 | 365 |
266 uint32 frame_id = 0; | 366 uint32 frame_id = 0; |
267 | 367 |
268 // Encode one frame at each size. Expect nothing but key frames to come out. | 368 // Encode one frame at each size. For the platform encoders, expect no frames |
| 369 // to be delivered since each frame size change will sprun re-initialization |
| 370 // of the underlying encoder. Otherwise, expect all key frames to come out. |
269 for (const auto& frame_size : frame_sizes) { | 371 for (const auto& frame_size : frame_sizes) { |
270 AdvanceClock(); | 372 EXPECT_EQ(!is_testing_platform_encoder(), |
271 const scoped_refptr<media::VideoFrame> video_frame = | 373 EncodeAndCheckDelivery(CreateTestVideoFrame(frame_size), |
272 CreateTestVideoFrame(frame_size); | 374 frame_id, |
273 EXPECT_TRUE(video_encoder()->EncodeVideoFrame( | 375 frame_id)); |
274 video_frame, | 376 RunTasksAndAdvanceClock(); |
275 Now(), | 377 if (!is_testing_platform_encoder()) |
276 CreateFrameDeliverCallback( | 378 ++frame_id; |
277 frame_id, | |
278 frame_id, | |
279 TimeDeltaToRtpDelta(video_frame->timestamp(), kVideoFrequency), | |
280 Now()))); | |
281 RunTasks(); | |
282 ++frame_id; | |
283 } | 379 } |
284 | 380 |
285 // Encode 10 frames at each size. Expect one key frame followed by nine delta | 381 // Encode 10+ frames at each size. For the platform decoders, expect the |
286 // frames for each frame size. | 382 // first one or more frames are dropped while the encoder re-inits. Then, for |
| 383 // all encoders, expect one key frame followed by all delta frames. |
287 for (const auto& frame_size : frame_sizes) { | 384 for (const auto& frame_size : frame_sizes) { |
288 for (int i = 0; i < 10; ++i) { | 385 bool accepted_first_frame = false; |
289 AdvanceClock(); | 386 do { |
290 const scoped_refptr<media::VideoFrame> video_frame = | 387 accepted_first_frame = EncodeAndCheckDelivery( |
291 CreateTestVideoFrame(frame_size); | 388 CreateTestVideoFrame(frame_size), frame_id, frame_id); |
292 EXPECT_TRUE(video_encoder()->EncodeVideoFrame( | 389 if (!is_testing_platform_encoder()) |
293 video_frame, | 390 EXPECT_TRUE(accepted_first_frame); |
294 Now(), | 391 RunTasksAndAdvanceClock(); |
295 CreateFrameDeliverCallback( | 392 } while (!accepted_first_frame); |
296 frame_id, | 393 ++frame_id; |
297 i == 0 ? frame_id : frame_id - 1, | 394 for (int i = 1; i < 10; ++i, ++frame_id) { |
298 TimeDeltaToRtpDelta(video_frame->timestamp(), kVideoFrequency), | 395 EXPECT_TRUE(EncodeAndCheckDelivery(CreateTestVideoFrame(frame_size), |
299 Now()))); | 396 frame_id, |
300 RunTasks(); | 397 frame_id - 1)); |
301 ++frame_id; | 398 RunTasksAndAdvanceClock(); |
302 } | 399 } |
303 } | 400 } |
304 | 401 |
305 EXPECT_EQ(static_cast<int>(frame_id), count_frames_delivered()); | 402 WaitForAllFramesToBeDelivered(10 * frame_sizes.size()); |
| 403 ExpectVEAResponsesForExternalVideoEncoder( |
| 404 2 * frame_sizes.size(), 6 * frame_sizes.size()); |
306 } | 405 } |
307 | 406 |
308 INSTANTIATE_TEST_CASE_P(, | 407 // Verify that everything goes well even if ExternalVideoEncoder is destroyed |
309 VideoEncoderImplTest, | 408 // before it has a chance to receive the VEA creation callback. For all other |
310 ::testing::Values(CODEC_VIDEO_FAKE, CODEC_VIDEO_VP8)); | 409 // encoders, this tests that the encoder can be safely destroyed before the task |
| 410 // is run that delivers the first EncodedFrame. |
| 411 TEST_P(VideoEncoderTest, CanBeDestroyedBeforeVEAIsCreated) { |
| 412 CreateEncoder(false); |
| 413 |
| 414 // Send a frame to spawn creation of the ExternalVideoEncoder instance. |
| 415 EncodeAndCheckDelivery(CreateTestVideoFrame(gfx::Size(1280, 720)), 0, 0); |
| 416 |
| 417 // Destroy the encoder, and confirm the VEA Factory did not respond yet. |
| 418 DestroyEncoder(); |
| 419 ExpectVEAResponsesForExternalVideoEncoder(0, 0); |
| 420 |
| 421 // Allow the VEA Factory to respond by running the creation callback. When |
| 422 // the task runs, it will be a no-op since the weak pointers to the |
| 423 // ExternalVideoEncoder were invalidated. |
| 424 SetVEAFactoryAutoRespond(true); |
| 425 RunTasksAndAdvanceClock(); |
| 426 ExpectVEAResponsesForExternalVideoEncoder(1, 0); |
| 427 } |
| 428 |
| 429 namespace { |
| 430 std::vector<std::pair<Codec, bool>> DetermineEncodersToTest() { |
| 431 std::vector<std::pair<Codec, bool>> values; |
| 432 // Fake encoder. |
| 433 values.push_back(std::make_pair(CODEC_VIDEO_FAKE, false)); |
| 434 // Software VP8 encoder. |
| 435 values.push_back(std::make_pair(CODEC_VIDEO_VP8, false)); |
| 436 // Hardware-accelerated encoder (faked). |
| 437 values.push_back(std::make_pair(CODEC_VIDEO_VP8, true)); |
| 438 #if defined(OS_MACOSX) |
| 439 // VideoToolbox encoder (when VideoToolbox is present). |
| 440 VideoSenderConfig video_config = GetDefaultVideoSenderConfig(); |
| 441 video_config.use_external_encoder = false; |
| 442 video_config.codec = CODEC_VIDEO_H264; |
| 443 if (H264VideoToolboxEncoder::IsSupported(video_config)) |
| 444 values.push_back(std::make_pair(CODEC_VIDEO_H264, false)); |
| 445 #endif |
| 446 return values; |
| 447 } |
| 448 } // namespace |
| 449 |
| 450 INSTANTIATE_TEST_CASE_P( |
| 451 , VideoEncoderTest, ::testing::ValuesIn(DetermineEncodersToTest())); |
311 | 452 |
312 } // namespace cast | 453 } // namespace cast |
313 } // namespace media | 454 } // namespace media |
OLD | NEW |