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 "media/base/android/media_codec_loop.h" |
| 6 |
5 #include "base/macros.h" | 7 #include "base/macros.h" |
6 #include "base/message_loop/message_loop.h" | 8 #include "base/message_loop/message_loop.h" |
| 9 #include "base/test/test_mock_time_task_runner.h" |
| 10 #include "base/threading/thread_task_runner_handle.h" |
7 #include "media/base/android/media_codec_bridge.h" | 11 #include "media/base/android/media_codec_bridge.h" |
8 #include "media/base/android/media_codec_loop.h" | |
9 #include "media/base/android/mock_media_codec_bridge.h" | 12 #include "media/base/android/mock_media_codec_bridge.h" |
10 #include "media/base/fake_single_thread_task_runner.h" | |
11 #include "testing/gmock/include/gmock/gmock.h" | 13 #include "testing/gmock/include/gmock/gmock.h" |
12 #include "testing/gtest/include/gtest/gtest.h" | 14 #include "testing/gtest/include/gtest/gtest.h" |
13 | 15 |
14 using ::testing::_; | 16 using ::testing::_; |
15 using ::testing::AtLeast; | 17 using ::testing::AtLeast; |
16 using ::testing::Eq; | 18 using ::testing::Eq; |
17 using ::testing::Field; | 19 using ::testing::Field; |
18 using ::testing::InSequence; | 20 using ::testing::InSequence; |
19 using ::testing::Mock; | 21 using ::testing::Mock; |
20 using ::testing::Return; | 22 using ::testing::Return; |
(...skipping 18 matching lines...) Expand all Loading... |
39 MOCK_METHOD1(OnInputDataQueued, void(bool)); | 41 MOCK_METHOD1(OnInputDataQueued, void(bool)); |
40 MOCK_METHOD1(OnDecodedEos, void(const MediaCodecLoop::OutputBuffer&)); | 42 MOCK_METHOD1(OnDecodedEos, void(const MediaCodecLoop::OutputBuffer&)); |
41 MOCK_METHOD1(OnDecodedFrame, bool(const MediaCodecLoop::OutputBuffer&)); | 43 MOCK_METHOD1(OnDecodedFrame, bool(const MediaCodecLoop::OutputBuffer&)); |
42 MOCK_METHOD0(OnOutputFormatChanged, bool()); | 44 MOCK_METHOD0(OnOutputFormatChanged, bool()); |
43 MOCK_METHOD0(OnCodecLoopError, void()); | 45 MOCK_METHOD0(OnCodecLoopError, void()); |
44 }; | 46 }; |
45 | 47 |
46 class MediaCodecLoopTest : public testing::Test { | 48 class MediaCodecLoopTest : public testing::Test { |
47 public: | 49 public: |
48 MediaCodecLoopTest() | 50 MediaCodecLoopTest() |
49 : client_(new StrictMock<MockMediaCodecLoopClient>()), | 51 : task_runner_handle_(mock_task_runner_), |
50 task_runner_(new FakeSingleThreadTaskRunner(&clock_)) {} | 52 client_(new StrictMock<MockMediaCodecLoopClient>()) {} |
51 | 53 |
52 ~MediaCodecLoopTest() override {} | 54 ~MediaCodecLoopTest() override {} |
53 | 55 |
54 protected: | 56 protected: |
55 enum IdleExpectation { | 57 enum IdleExpectation { |
56 ShouldBeIdle, | 58 ShouldBeIdle, |
57 ShouldNotBeIdle, | 59 ShouldNotBeIdle, |
58 }; | 60 }; |
59 | 61 |
60 // Wait until |codec_loop_| is idle. | 62 // Wait until |codec_loop_| is idle. |
(...skipping 16 matching lines...) Expand all Loading... |
77 break; | 79 break; |
78 } | 80 } |
79 | 81 |
80 // Either way, we expect that MCL should not attempt to dequeue input | 82 // 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 | 83 // buffers, either because it's idle or because we said that no input |
82 // is pending. | 84 // is pending. |
83 EXPECT_CALL(Codec(), DequeueInputBuffer(_, _)).Times(0); | 85 EXPECT_CALL(Codec(), DequeueInputBuffer(_, _)).Times(0); |
84 | 86 |
85 // TODO(liberato): assume that MCL doesn't retry for 30 seconds. Note | 87 // TODO(liberato): assume that MCL doesn't retry for 30 seconds. Note |
86 // that this doesn't actually wall-clock wait. | 88 // that this doesn't actually wall-clock wait. |
87 task_runner_->Sleep(base::TimeDelta::FromSeconds(30)); | 89 mock_task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(30)); |
88 } | 90 } |
89 | 91 |
90 void ConstructCodecLoop(int sdk_int = kLollipop) { | 92 void ConstructCodecLoop(int sdk_int = kLollipop) { |
91 std::unique_ptr<MediaCodecBridge> codec(new MockMediaCodecBridge()); | 93 std::unique_ptr<MediaCodecBridge> codec(new MockMediaCodecBridge()); |
92 // Since we're providing a codec, we do not expect an error. | 94 // Since we're providing a codec, we do not expect an error. |
93 EXPECT_CALL(*client_, OnCodecLoopError()).Times(0); | 95 EXPECT_CALL(*client_, OnCodecLoopError()).Times(0); |
94 codec_loop_.reset(new MediaCodecLoop(sdk_int, client_.get(), | 96 codec_loop_.reset(new MediaCodecLoop(sdk_int, client_.get(), |
95 std::move(codec), task_runner_)); | 97 std::move(codec), mock_task_runner_)); |
96 codec_loop_->SetTestTickClock(&clock_); | 98 codec_loop_->SetTestTickClock(clock_.get()); |
97 Mock::VerifyAndClearExpectations(client_.get()); | 99 Mock::VerifyAndClearExpectations(client_.get()); |
98 } | 100 } |
99 | 101 |
100 // Set an expectation that MCL will try to get another input / output buffer, | 102 // Set an expectation that MCL will try to get another input / output buffer, |
101 // and not get one in DoPendingWork. | 103 // and not get one in DoPendingWork. |
102 void ExpectEmptyIOLoop() { | 104 void ExpectEmptyIOLoop() { |
103 ExpectIsAnyInputPending(false); | 105 ExpectIsAnyInputPending(false); |
104 EXPECT_CALL(Codec(), DequeueOutputBuffer(_, _, _, _, _, _, _)) | 106 EXPECT_CALL(Codec(), DequeueOutputBuffer(_, _, _, _, _, _, _)) |
105 .Times(1) | 107 .Times(1) |
106 .WillOnce(Return(MEDIA_CODEC_TRY_AGAIN_LATER)); | 108 .WillOnce(Return(MEDIA_CODEC_TRY_AGAIN_LATER)); |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
175 Field(&MediaCodecLoop::OutputBuffer::index, Eq(buf.index)))) | 177 Field(&MediaCodecLoop::OutputBuffer::index, Eq(buf.index)))) |
176 .Times(1) | 178 .Times(1) |
177 .WillOnce(Return(true)); | 179 .WillOnce(Return(true)); |
178 } | 180 } |
179 | 181 |
180 MockMediaCodecBridge& Codec() { | 182 MockMediaCodecBridge& Codec() { |
181 return *static_cast<MockMediaCodecBridge*>(codec_loop_->GetCodec()); | 183 return *static_cast<MockMediaCodecBridge*>(codec_loop_->GetCodec()); |
182 } | 184 } |
183 | 185 |
184 public: | 186 public: |
| 187 // Mocks the current thread's task runner which will also be used as the |
| 188 // MediaCodecLoop's task runner. |
| 189 scoped_refptr<base::TestMockTimeTaskRunner> mock_task_runner_ = |
| 190 new base::TestMockTimeTaskRunner; |
| 191 base::ThreadTaskRunnerHandle task_runner_handle_; |
| 192 |
| 193 // A reference to |mock_task_runner_|'s TickClock handed to |codec_loop_|. |
| 194 std::unique_ptr<base::TickClock> clock_ = |
| 195 mock_task_runner_->GetMockTickClock(); |
| 196 |
185 std::unique_ptr<MediaCodecLoop> codec_loop_; | 197 std::unique_ptr<MediaCodecLoop> codec_loop_; |
186 std::unique_ptr<MockMediaCodecLoopClient> client_; | 198 std::unique_ptr<MockMediaCodecLoopClient> client_; |
187 // TODO: how is the lifecycle of |clock_| handled? |task_runner_| can outlive | |
188 // us, since it's a refptr. | |
189 base::SimpleTestTickClock clock_; | |
190 scoped_refptr<FakeSingleThreadTaskRunner> task_runner_; | |
191 | 199 |
192 DISALLOW_COPY_AND_ASSIGN(MediaCodecLoopTest); | 200 DISALLOW_COPY_AND_ASSIGN(MediaCodecLoopTest); |
193 }; | 201 }; |
194 | 202 |
195 TEST_F(MediaCodecLoopTest, TestConstructionWithNullCodec) { | 203 TEST_F(MediaCodecLoopTest, TestConstructionWithNullCodec) { |
196 std::unique_ptr<MediaCodecBridge> codec; | 204 std::unique_ptr<MediaCodecBridge> codec; |
197 EXPECT_CALL(*client_, OnCodecLoopError()).Times(1); | 205 EXPECT_CALL(*client_, OnCodecLoopError()).Times(1); |
198 const int sdk_int = kLollipop; | 206 const int sdk_int = kLollipop; |
199 codec_loop_.reset( | 207 codec_loop_.reset( |
200 new MediaCodecLoop(sdk_int, client_.get(), std::move(codec))); | 208 new MediaCodecLoop(sdk_int, client_.get(), std::move(codec), |
| 209 scoped_refptr<base::SingleThreadTaskRunner>())); |
201 // Do not WaitUntilIdle() here, since that assumes that we have a codec. | 210 // Do not WaitUntilIdle() here, since that assumes that we have a codec. |
202 | 211 |
203 ASSERT_FALSE(codec_loop_->GetCodec()); | 212 ASSERT_FALSE(codec_loop_->GetCodec()); |
204 } | 213 } |
205 | 214 |
206 TEST_F(MediaCodecLoopTest, TestConstructionWithCodec) { | 215 TEST_F(MediaCodecLoopTest, TestConstructionWithCodec) { |
207 ConstructCodecLoop(); | 216 ConstructCodecLoop(); |
208 ASSERT_EQ(codec_loop_->GetCodec(), &Codec()); | 217 ASSERT_EQ(codec_loop_->GetCodec(), &Codec()); |
209 WaitUntilIdle(ShouldBeIdle); | 218 WaitUntilIdle(ShouldBeIdle); |
210 } | 219 } |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
457 | 466 |
458 // MCL did work, so it will try again. | 467 // MCL did work, so it will try again. |
459 ExpectEmptyIOLoop(); | 468 ExpectEmptyIOLoop(); |
460 } | 469 } |
461 | 470 |
462 codec_loop_->OnKeyAdded(); | 471 codec_loop_->OnKeyAdded(); |
463 WaitUntilIdle(ShouldNotBeIdle); | 472 WaitUntilIdle(ShouldNotBeIdle); |
464 } | 473 } |
465 | 474 |
466 } // namespace media | 475 } // namespace media |
OLD | NEW |