| 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 |