OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "base/macros.h" | 5 #include "base/macros.h" |
6 #include "base/message_loop/message_loop.h" | 6 #include "base/message_loop/message_loop.h" |
7 #include "media/base/android/media_codec_bridge.h" | 7 #include "media/base/android/media_codec_bridge.h" |
8 #include "media/base/android/media_codec_loop.h" | 8 #include "media/base/android/media_codec_loop.h" |
9 #include "media/base/android/mock_media_codec_bridge.h" | 9 #include "media/base/android/mock_media_codec_bridge.h" |
10 #include "media/base/fake_single_thread_task_runner.h" | 10 #include "media/base/fake_single_thread_task_runner.h" |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
66 EXPECT_CALL(Codec(), DequeueOutputBuffer(_, _, _, _, _, _, _)).Times(0); | 66 EXPECT_CALL(Codec(), DequeueOutputBuffer(_, _, _, _, _, _, _)).Times(0); |
67 break; | 67 break; |
68 case ShouldNotBeIdle: | 68 case ShouldNotBeIdle: |
69 // Expect at least one call to see if more work is ready. We will | 69 // Expect at least one call to see if more work is ready. We will |
70 // return 'no'. | 70 // return 'no'. |
71 EXPECT_CALL(*client_, IsAnyInputPending()) | 71 EXPECT_CALL(*client_, IsAnyInputPending()) |
72 .Times(AtLeast(1)) | 72 .Times(AtLeast(1)) |
73 .WillRepeatedly(Return(false)); | 73 .WillRepeatedly(Return(false)); |
74 EXPECT_CALL(Codec(), DequeueOutputBuffer(_, _, _, _, _, _, _)) | 74 EXPECT_CALL(Codec(), DequeueOutputBuffer(_, _, _, _, _, _, _)) |
75 .Times(AtLeast(1)) | 75 .Times(AtLeast(1)) |
76 .WillRepeatedly(Return(MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER)); | 76 .WillRepeatedly(Return(MEDIA_CODEC_TRY_AGAIN_LATER)); |
77 break; | 77 break; |
78 } | 78 } |
79 | 79 |
80 // Either way, we expect that MCL should not attempt to dequeue input | 80 // Either way, we expect that MCL should not attempt to dequeue input |
81 // buffers, either because it's idle or because we said that no input | 81 // buffers, either because it's idle or because we said that no input |
82 // is pending. | 82 // is pending. |
83 EXPECT_CALL(Codec(), DequeueInputBuffer(_, _)).Times(0); | 83 EXPECT_CALL(Codec(), DequeueInputBuffer(_, _)).Times(0); |
84 | 84 |
85 // TODO(liberato): assume that MCL doesn't retry for 30 seconds. Note | 85 // TODO(liberato): assume that MCL doesn't retry for 30 seconds. Note |
86 // that this doesn't actually wall-clock wait. | 86 // that this doesn't actually wall-clock wait. |
87 task_runner_->Sleep(base::TimeDelta::FromSeconds(30)); | 87 task_runner_->Sleep(base::TimeDelta::FromSeconds(30)); |
88 } | 88 } |
89 | 89 |
90 void ConstructCodecLoop(int sdk_int = kLollipop) { | 90 void ConstructCodecLoop(int sdk_int = kLollipop) { |
91 std::unique_ptr<MediaCodecBridge> codec(new MockMediaCodecBridge()); | 91 std::unique_ptr<MediaCodecBridge> codec(new MockMediaCodecBridge()); |
92 // Since we're providing a codec, we do not expect an error. | 92 // Since we're providing a codec, we do not expect an error. |
93 EXPECT_CALL(*client_, OnCodecLoopError()).Times(0); | 93 EXPECT_CALL(*client_, OnCodecLoopError()).Times(0); |
94 codec_loop_.reset(new MediaCodecLoop(sdk_int, client_.get(), | 94 codec_loop_.reset(new MediaCodecLoop(sdk_int, client_.get(), |
95 std::move(codec), task_runner_)); | 95 std::move(codec), task_runner_)); |
96 codec_loop_->SetTestTickClock(&clock_); | 96 codec_loop_->SetTestTickClock(&clock_); |
97 Mock::VerifyAndClearExpectations(client_.get()); | 97 Mock::VerifyAndClearExpectations(client_.get()); |
98 } | 98 } |
99 | 99 |
100 // Set an expectation that MCL will try to get another input / output buffer, | 100 // Set an expectation that MCL will try to get another input / output buffer, |
101 // and not get one in DoPendingWork. | 101 // and not get one in DoPendingWork. |
102 void ExpectEmptyIOLoop() { | 102 void ExpectEmptyIOLoop() { |
103 ExpectIsAnyInputPending(false); | 103 ExpectIsAnyInputPending(false); |
104 EXPECT_CALL(Codec(), DequeueOutputBuffer(_, _, _, _, _, _, _)) | 104 EXPECT_CALL(Codec(), DequeueOutputBuffer(_, _, _, _, _, _, _)) |
105 .Times(1) | 105 .Times(1) |
106 .WillOnce(Return(MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER)); | 106 .WillOnce(Return(MEDIA_CODEC_TRY_AGAIN_LATER)); |
107 } | 107 } |
108 | 108 |
109 void ExpectIsAnyInputPending(bool pending) { | 109 void ExpectIsAnyInputPending(bool pending) { |
110 EXPECT_CALL(*client_, IsAnyInputPending()).WillOnce(Return(pending)); | 110 EXPECT_CALL(*client_, IsAnyInputPending()).WillOnce(Return(pending)); |
111 } | 111 } |
112 | 112 |
113 void ExpectDequeueInputBuffer(int input_buffer_index, | 113 void ExpectDequeueInputBuffer(int input_buffer_index, |
114 MediaCodecStatus status = MEDIA_CODEC_OK) { | 114 MediaCodecStatus status = MEDIA_CODEC_OK) { |
115 EXPECT_CALL(Codec(), DequeueInputBuffer(_, _)) | 115 EXPECT_CALL(Codec(), DequeueInputBuffer(_, _)) |
116 .WillOnce(DoAll(SetArgPointee<1>(input_buffer_index), Return(status))); | 116 .WillOnce(DoAll(SetArgPointee<1>(input_buffer_index), Return(status))); |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
208 ASSERT_EQ(codec_loop_->GetCodec(), &Codec()); | 208 ASSERT_EQ(codec_loop_->GetCodec(), &Codec()); |
209 WaitUntilIdle(ShouldBeIdle); | 209 WaitUntilIdle(ShouldBeIdle); |
210 } | 210 } |
211 | 211 |
212 TEST_F(MediaCodecLoopTest, TestPendingWorkWithoutInput) { | 212 TEST_F(MediaCodecLoopTest, TestPendingWorkWithoutInput) { |
213 ConstructCodecLoop(); | 213 ConstructCodecLoop(); |
214 // MCL should try ask if there is pending input, and try to dequeue output. | 214 // MCL should try ask if there is pending input, and try to dequeue output. |
215 ExpectIsAnyInputPending(false); | 215 ExpectIsAnyInputPending(false); |
216 EXPECT_CALL(Codec(), DequeueOutputBuffer(_, _, _, _, _, _, _)) | 216 EXPECT_CALL(Codec(), DequeueOutputBuffer(_, _, _, _, _, _, _)) |
217 .Times(1) | 217 .Times(1) |
218 .WillOnce(Return(MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER)); | 218 .WillOnce(Return(MEDIA_CODEC_TRY_AGAIN_LATER)); |
219 codec_loop_->DoPendingWork(); | 219 codec_loop_->DoPendingWork(); |
220 WaitUntilIdle(ShouldNotBeIdle); | 220 WaitUntilIdle(ShouldNotBeIdle); |
221 } | 221 } |
222 | 222 |
223 TEST_F(MediaCodecLoopTest, TestPendingWorkWithInput) { | 223 TEST_F(MediaCodecLoopTest, TestPendingWorkWithInput) { |
224 ConstructCodecLoop(); | 224 ConstructCodecLoop(); |
225 // MCL should try ask if there is pending input, and try to dequeue both an | 225 // MCL should try ask if there is pending input, and try to dequeue both an |
226 // output and input buffer. | 226 // output and input buffer. |
227 ExpectIsAnyInputPending(true); | 227 ExpectIsAnyInputPending(true); |
228 EXPECT_CALL(Codec(), DequeueOutputBuffer(_, _, _, _, _, _, _)).Times(1); | 228 EXPECT_CALL(Codec(), DequeueOutputBuffer(_, _, _, _, _, _, _)).Times(1); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
268 | 268 |
269 // Now send the EOS back on the output queue. | 269 // Now send the EOS back on the output queue. |
270 EosOutputBuffer eos; | 270 EosOutputBuffer eos; |
271 ExpectDequeueOutputBuffer(eos); | 271 ExpectDequeueOutputBuffer(eos); |
272 EXPECT_CALL(Codec(), ReleaseOutputBuffer(eos.index, false)); | 272 EXPECT_CALL(Codec(), ReleaseOutputBuffer(eos.index, false)); |
273 EXPECT_CALL(*client_, OnDecodedEos(_)).Times(1); | 273 EXPECT_CALL(*client_, OnDecodedEos(_)).Times(1); |
274 | 274 |
275 // See TestUnqueuedEos. | 275 // See TestUnqueuedEos. |
276 EXPECT_CALL(Codec(), DequeueOutputBuffer(_, _, _, _, _, _, _)) | 276 EXPECT_CALL(Codec(), DequeueOutputBuffer(_, _, _, _, _, _, _)) |
277 .Times(1) | 277 .Times(1) |
278 .WillOnce(Return(MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER)); | 278 .WillOnce(Return(MEDIA_CODEC_TRY_AGAIN_LATER)); |
279 } | 279 } |
280 codec_loop_->DoPendingWork(); | 280 codec_loop_->DoPendingWork(); |
281 // Don't WaitUntilIdle() here. See TestUnqueuedEos. | 281 // Don't WaitUntilIdle() here. See TestUnqueuedEos. |
282 } | 282 } |
283 | 283 |
284 TEST_F(MediaCodecLoopTest, TestQueueInputData) { | 284 TEST_F(MediaCodecLoopTest, TestQueueInputData) { |
285 // Send a buffer full of data into MCL and make sure that it gets queued with | 285 // Send a buffer full of data into MCL and make sure that it gets queued with |
286 // MediaCodecBridge correctly. | 286 // MediaCodecBridge correctly. |
287 ConstructCodecLoop(); | 287 ConstructCodecLoop(); |
288 { | 288 { |
289 InSequence _s; | 289 InSequence _s; |
290 | 290 |
291 ExpectIsAnyInputPending(true); | 291 ExpectIsAnyInputPending(true); |
292 int input_buffer_index = 123; | 292 int input_buffer_index = 123; |
293 ExpectDequeueInputBuffer(input_buffer_index); | 293 ExpectDequeueInputBuffer(input_buffer_index); |
294 | 294 |
295 MediaCodecLoop::InputData data = BigBuckBunny(); | 295 MediaCodecLoop::InputData data = BigBuckBunny(); |
296 ExpectProvideInputData(data); | 296 ExpectProvideInputData(data); |
297 | 297 |
298 // MCL should send the buffer into MediaCodec and notify the client. | 298 // MCL should send the buffer into MediaCodec and notify the client. |
299 ExpectQueueInputBuffer(input_buffer_index, data); | 299 ExpectQueueInputBuffer(input_buffer_index, data); |
300 ExpectInputDataQueued(true); | 300 ExpectInputDataQueued(true); |
301 | 301 |
302 // MCL will try to dequeue an output buffer too. | 302 // MCL will try to dequeue an output buffer too. |
303 EXPECT_CALL(Codec(), DequeueOutputBuffer(_, _, _, _, _, _, _)) | 303 EXPECT_CALL(Codec(), DequeueOutputBuffer(_, _, _, _, _, _, _)) |
304 .Times(1) | 304 .Times(1) |
305 .WillOnce(Return(MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER)); | 305 .WillOnce(Return(MEDIA_CODEC_TRY_AGAIN_LATER)); |
306 | 306 |
307 // DoPendingWork will try again. | 307 // DoPendingWork will try again. |
308 ExpectEmptyIOLoop(); | 308 ExpectEmptyIOLoop(); |
309 } | 309 } |
310 codec_loop_->DoPendingWork(); | 310 codec_loop_->DoPendingWork(); |
311 WaitUntilIdle(ShouldNotBeIdle); | 311 WaitUntilIdle(ShouldNotBeIdle); |
312 } | 312 } |
313 | 313 |
314 TEST_F(MediaCodecLoopTest, TestQueueInputDataFails) { | 314 TEST_F(MediaCodecLoopTest, TestQueueInputDataFails) { |
315 // Send a buffer full of data into MCL, but MediaCodecBridge fails to queue | 315 // Send a buffer full of data into MCL, but MediaCodecBridge fails to queue |
(...skipping 18 matching lines...) Expand all Loading... |
334 // MCL is now in the error state. | 334 // MCL is now in the error state. |
335 } | 335 } |
336 | 336 |
337 TEST_F(MediaCodecLoopTest, TestQueueInputDataTryAgain) { | 337 TEST_F(MediaCodecLoopTest, TestQueueInputDataTryAgain) { |
338 // Signal that there is input pending, but don't provide an input buffer. | 338 // Signal that there is input pending, but don't provide an input buffer. |
339 ConstructCodecLoop(); | 339 ConstructCodecLoop(); |
340 { | 340 { |
341 InSequence _s; | 341 InSequence _s; |
342 | 342 |
343 ExpectIsAnyInputPending(true); | 343 ExpectIsAnyInputPending(true); |
344 ExpectDequeueInputBuffer(-1, MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER); | 344 ExpectDequeueInputBuffer(-1, MEDIA_CODEC_TRY_AGAIN_LATER); |
345 // MCL will try for output too. | 345 // MCL will try for output too. |
346 ExpectDequeueOutputBuffer(MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER); | 346 ExpectDequeueOutputBuffer(MEDIA_CODEC_TRY_AGAIN_LATER); |
347 } | 347 } |
348 codec_loop_->DoPendingWork(); | 348 codec_loop_->DoPendingWork(); |
349 // Note that the client might not be allowed to change from "input pending" | 349 // Note that the client might not be allowed to change from "input pending" |
350 // to "no input pending" without actually being asked for input. For now, | 350 // to "no input pending" without actually being asked for input. For now, |
351 // MCL doesn't assume this. | 351 // MCL doesn't assume this. |
352 WaitUntilIdle(ShouldNotBeIdle); | 352 WaitUntilIdle(ShouldNotBeIdle); |
353 } | 353 } |
354 | 354 |
355 TEST_F(MediaCodecLoopTest, TestSeveralPendingIOBuffers) { | 355 TEST_F(MediaCodecLoopTest, TestSeveralPendingIOBuffers) { |
356 // Provide several input and output buffers to MCL. | 356 // Provide several input and output buffers to MCL. |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
417 // First DoPendingWork() | 417 // First DoPendingWork() |
418 ExpectIsAnyInputPending(true); | 418 ExpectIsAnyInputPending(true); |
419 ExpectDequeueInputBuffer(input_buffer_index); | 419 ExpectDequeueInputBuffer(input_buffer_index); |
420 | 420 |
421 ExpectProvideInputData(data); | 421 ExpectProvideInputData(data); |
422 | 422 |
423 // Notify MCL that it's missing the key. | 423 // Notify MCL that it's missing the key. |
424 ExpectQueueInputBuffer(input_buffer_index, data, MEDIA_CODEC_NO_KEY); | 424 ExpectQueueInputBuffer(input_buffer_index, data, MEDIA_CODEC_NO_KEY); |
425 | 425 |
426 // MCL should now try for output buffers. | 426 // MCL should now try for output buffers. |
427 ExpectDequeueOutputBuffer(MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER); | 427 ExpectDequeueOutputBuffer(MEDIA_CODEC_TRY_AGAIN_LATER); |
428 | 428 |
429 // MCL will try again, since trying to queue the input buffer is considered | 429 // MCL will try again, since trying to queue the input buffer is considered |
430 // doing work, for some reason. It would be nice to make this optional. | 430 // doing work, for some reason. It would be nice to make this optional. |
431 // Note that it should not ask us for more input, since it has not yet sent | 431 // Note that it should not ask us for more input, since it has not yet sent |
432 // the buffer we just provided. | 432 // the buffer we just provided. |
433 ExpectDequeueOutputBuffer(MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER); | 433 ExpectDequeueOutputBuffer(MEDIA_CODEC_TRY_AGAIN_LATER); |
434 } | 434 } |
435 codec_loop_->DoPendingWork(); | 435 codec_loop_->DoPendingWork(); |
436 | 436 |
437 // Try again, to be sure that MCL doesn't request more input. Note that this | 437 // Try again, to be sure that MCL doesn't request more input. Note that this |
438 // is also done in the above loop, but that one could be made optional. This | 438 // is also done in the above loop, but that one could be made optional. This |
439 // forces MCL to try again as part of an entirely new DoPendingWork cycle. | 439 // forces MCL to try again as part of an entirely new DoPendingWork cycle. |
440 { | 440 { |
441 InSequence _s; | 441 InSequence _s; |
442 // MCL should only try for output buffers, since it's still waiting for a | 442 // MCL should only try for output buffers, since it's still waiting for a |
443 // key to be added. | 443 // key to be added. |
444 ExpectDequeueOutputBuffer(MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER); | 444 ExpectDequeueOutputBuffer(MEDIA_CODEC_TRY_AGAIN_LATER); |
445 } | 445 } |
446 codec_loop_->DoPendingWork(); | 446 codec_loop_->DoPendingWork(); |
447 | 447 |
448 // When we add the key, MCL will DoPending work again. This time, it should | 448 // When we add the key, MCL will DoPending work again. This time, it should |
449 // succeed since the key has been added. | 449 // succeed since the key has been added. |
450 { | 450 { |
451 InSequence _s; | 451 InSequence _s; |
452 // MCL should not retain the original pointer. | 452 // MCL should not retain the original pointer. |
453 data.memory = nullptr; | 453 data.memory = nullptr; |
454 ExpectQueueInputBuffer(input_buffer_index, data); | 454 ExpectQueueInputBuffer(input_buffer_index, data); |
455 ExpectInputDataQueued(true); | 455 ExpectInputDataQueued(true); |
456 ExpectDequeueOutputBuffer(MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER); | 456 ExpectDequeueOutputBuffer(MEDIA_CODEC_TRY_AGAIN_LATER); |
457 | 457 |
458 // MCL did work, so it will try again. | 458 // MCL did work, so it will try again. |
459 ExpectEmptyIOLoop(); | 459 ExpectEmptyIOLoop(); |
460 } | 460 } |
461 | 461 |
462 codec_loop_->OnKeyAdded(); | 462 codec_loop_->OnKeyAdded(); |
463 WaitUntilIdle(ShouldNotBeIdle); | 463 WaitUntilIdle(ShouldNotBeIdle); |
464 } | 464 } |
465 | 465 |
466 } // namespace media | 466 } // namespace media |
OLD | NEW |