| OLD | NEW |
| 1 // Copyright (c) 2013 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/gpu/avda_codec_allocator.h" | 5 #include "media/gpu/avda_codec_allocator.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <memory> | 9 #include <memory> |
| 10 | 10 |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/time/tick_clock.h" | 13 #include "base/time/tick_clock.h" |
| 14 #include "testing/gmock/include/gmock/gmock.h" |
| 14 #include "testing/gtest/include/gtest/gtest.h" | 15 #include "testing/gtest/include/gtest/gtest.h" |
| 15 | 16 |
| 17 using testing::Invoke; |
| 18 using testing::NiceMock; |
| 19 using testing::_; |
| 20 |
| 16 namespace media { | 21 namespace media { |
| 17 namespace { | 22 namespace { |
| 18 template <typename ReturnType> | 23 template <typename ReturnType> |
| 19 void RunAndSignalTask(base::WaitableEvent* event, | 24 void RunAndSignalTask(base::WaitableEvent* event, |
| 20 ReturnType* return_value, | 25 ReturnType* return_value, |
| 21 const base::Callback<ReturnType(void)>& cb) { | 26 const base::Callback<ReturnType(void)>& cb) { |
| 22 *return_value = cb.Run(); | 27 *return_value = cb.Run(); |
| 23 event->Signal(); | 28 event->Signal(); |
| 24 } | 29 } |
| 30 |
| 31 void WaitUntilRestarted(base::WaitableEvent* about_to_wait_event, |
| 32 base::WaitableEvent* wait_event) { |
| 33 // Notify somebody that we've started. |
| 34 if (about_to_wait_event) |
| 35 about_to_wait_event->Signal(); |
| 36 wait_event->Wait(); |
| 37 } |
| 38 |
| 39 void SignalImmediately(base::WaitableEvent* event) { |
| 40 event->Signal(); |
| 41 } |
| 25 } | 42 } |
| 26 | 43 |
| 27 class MockTickClock : public base::TickClock { | 44 class MockTickClock : public base::TickClock { |
| 28 public: | 45 public: |
| 29 MockTickClock() { | 46 MockTickClock() { |
| 30 // Don't start with the null time. | 47 // Don't start with the null time. |
| 31 Advance(1000); | 48 Advance(1000); |
| 32 } | 49 } |
| 33 ~MockTickClock() override{}; | 50 ~MockTickClock() override{}; |
| 34 base::TimeTicks NowTicks() override { | 51 base::TimeTicks NowTicks() override { |
| 35 base::AutoLock auto_lock(lock_); | 52 base::AutoLock auto_lock(lock_); |
| 36 return now_; | 53 return now_; |
| 37 } | 54 } |
| 38 | 55 |
| 39 // Handy utility. | 56 // Handy utility. |
| 40 void Advance(int msec) { | 57 void Advance(int msec) { |
| 41 base::AutoLock auto_lock(lock_); | 58 base::AutoLock auto_lock(lock_); |
| 42 now_ += base::TimeDelta::FromMilliseconds(msec); | 59 now_ += base::TimeDelta::FromMilliseconds(msec); |
| 43 } | 60 } |
| 44 | 61 |
| 45 private: | 62 private: |
| 46 base::Lock lock_; | 63 base::Lock lock_; |
| 47 base::TimeTicks now_; | 64 base::TimeTicks now_; |
| 48 }; | 65 }; |
| 49 | 66 |
| 67 class MockClient : public AVDACodecAllocatorClient { |
| 68 public: |
| 69 MOCK_METHOD1(OnSurfaceAvailable, void(bool success)); |
| 70 MOCK_METHOD0(OnSurfaceDestroyed, void()); |
| 71 |
| 72 // Gmock doesn't let us mock methods taking move-only types. |
| 73 MOCK_METHOD1(OnCodecConfiguredMock, void(VideoCodecBridge* media_codec)); |
| 74 void OnCodecConfigured( |
| 75 std::unique_ptr<VideoCodecBridge> media_codec) override { |
| 76 OnCodecConfiguredMock(media_codec.get()); |
| 77 } |
| 78 }; |
| 79 |
| 50 class AVDACodecAllocatorTest : public testing::Test { | 80 class AVDACodecAllocatorTest : public testing::Test { |
| 51 public: | 81 public: |
| 52 AVDACodecAllocatorTest() : allocator_thread_("AllocatorThread") {} | 82 AVDACodecAllocatorTest() : allocator_thread_("AllocatorThread") {} |
| 53 ~AVDACodecAllocatorTest() override {} | 83 ~AVDACodecAllocatorTest() override {} |
| 54 | 84 |
| 55 protected: | 85 protected: |
| 56 void SetUp() override { | 86 void SetUp() override { |
| 57 // Start the main thread for the allocator. This would normally be the GPU | 87 // Start the main thread for the allocator. This would normally be the GPU |
| 58 // main thread. | 88 // main thread. |
| 59 ASSERT_TRUE(allocator_thread_.Start()); | 89 ASSERT_TRUE(allocator_thread_.Start()); |
| 60 | 90 |
| 61 // AVDACodecAllocator likes to post tasks to the current thread. | 91 // AVDACodecAllocator likes to post tasks to the current thread. |
| 62 | 92 |
| 63 test_information_.reset(new AVDACodecAllocator::TestInformation()); | 93 test_information_.reset(new AVDACodecAllocator::TestInformation()); |
| 64 test_information_->tick_clock_.reset(new MockTickClock()); | 94 test_information_->tick_clock_.reset(new MockTickClock()); |
| 65 test_information_->stop_event_.reset(new base::WaitableEvent( | 95 test_information_->stop_event_.reset(new base::WaitableEvent( |
| 66 base::WaitableEvent::ResetPolicy::AUTOMATIC, | 96 base::WaitableEvent::ResetPolicy::AUTOMATIC, |
| 67 base::WaitableEvent::InitialState::NOT_SIGNALED)); | 97 base::WaitableEvent::InitialState::NOT_SIGNALED)); |
| 68 | 98 |
| 69 // Allocate the allocator on the appropriate thread. | 99 // Allocate the allocator on the appropriate thread. |
| 70 allocator_ = PostAndWait( | 100 allocator_ = PostAndWait( |
| 71 FROM_HERE, base::Bind( | 101 FROM_HERE, base::Bind( |
| 72 [](AVDACodecAllocator::TestInformation* test_info) { | 102 [](AVDACodecAllocator::TestInformation* test_info) { |
| 73 return new AVDACodecAllocator(test_info); | 103 return new AVDACodecAllocator(test_info); |
| 74 }, | 104 }, |
| 75 test_information_.get())); | 105 test_information_.get())); |
| 106 allocator2_ = new AVDACodecAllocator(test_information_.get()); |
| 76 | 107 |
| 77 // All threads should be stopped | 108 // All threads should be stopped |
| 78 ASSERT_FALSE(IsThreadRunning(AVDACodecAllocator::TaskType::AUTO_CODEC)); | 109 ASSERT_FALSE(IsThreadRunning(TaskType::AUTO_CODEC)); |
| 79 ASSERT_FALSE(IsThreadRunning(AVDACodecAllocator::TaskType::SW_CODEC)); | 110 ASSERT_FALSE(IsThreadRunning(TaskType::SW_CODEC)); |
| 80 | 111 |
| 81 // Register an AVDA instance to start the allocator's threads. | 112 // Register an AVDA instance to start the allocator's threads. |
| 82 ASSERT_TRUE(StartThread(avda1_)); | 113 ASSERT_TRUE(StartThread(avda1_)); |
| 83 | 114 |
| 84 // Assert that at least the AUTO_CODEC thread is started. The other might | 115 // Assert that at least the AUTO_CODEC thread is started. The other might |
| 85 // not be. | 116 // not be. |
| 86 ASSERT_TRUE(IsThreadRunning(AVDACodecAllocator::TaskType::AUTO_CODEC)); | 117 ASSERT_TRUE(IsThreadRunning(TaskType::AUTO_CODEC)); |
| 87 ASSERT_EQ(AVDACodecAllocator::TaskType::AUTO_CODEC, | 118 ASSERT_EQ(TaskType::AUTO_CODEC, TaskTypeForAllocation()); |
| 88 TaskTypeForAllocation()); | |
| 89 } | 119 } |
| 90 | 120 |
| 91 void TearDown() override { | 121 void TearDown() override { |
| 92 // Don't leave any threads hung, or this will hang too. | 122 // Don't leave any threads hung, or this will hang too. |
| 93 // It would be nice if we could let a unique ptr handle this, but the | 123 // It would be nice if we could let a unique ptr handle this, but the |
| 94 // destructor is private. We also have to destroy it on the right thread. | 124 // destructor is private. We also have to destroy it on the right thread. |
| 95 PostAndWait(FROM_HERE, base::Bind( | 125 PostAndWait(FROM_HERE, base::Bind( |
| 96 [](AVDACodecAllocator* allocator) { | 126 [](AVDACodecAllocator* allocator) { |
| 97 delete allocator; | 127 delete allocator; |
| 98 return true; | 128 return true; |
| 99 }, | 129 }, |
| 100 allocator_)); | 130 allocator_)); |
| 101 | 131 |
| 102 allocator_thread_.Stop(); | 132 allocator_thread_.Stop(); |
| 133 delete allocator2_; |
| 103 } | 134 } |
| 104 | 135 |
| 105 protected: | 136 protected: |
| 106 static void WaitUntilRestarted(base::WaitableEvent* about_to_wait_event, | |
| 107 base::WaitableEvent* wait_event) { | |
| 108 // Notify somebody that we've started. | |
| 109 about_to_wait_event->Signal(); | |
| 110 wait_event->Wait(); | |
| 111 } | |
| 112 | |
| 113 static void SignalImmediately(base::WaitableEvent* event) { event->Signal(); } | |
| 114 | 137 |
| 115 // Start / stop the threads for |avda| on the right thread. | 138 // Start / stop the threads for |avda| on the right thread. |
| 116 bool StartThread(AndroidVideoDecodeAccelerator* avda) { | 139 bool StartThread(AVDACodecAllocatorClient* avda) { |
| 117 return PostAndWait(FROM_HERE, base::Bind( | 140 return PostAndWait(FROM_HERE, base::Bind( |
| 118 [](AVDACodecAllocator* allocator, | 141 [](AVDACodecAllocator* allocator, |
| 119 AndroidVideoDecodeAccelerator* avda) { | 142 AVDACodecAllocatorClient* avda) { |
| 120 return allocator->StartThread(avda); | 143 return allocator->StartThread(avda); |
| 121 }, | 144 }, |
| 122 allocator_, avda)); | 145 allocator_, avda)); |
| 123 } | 146 } |
| 124 | 147 |
| 125 void StopThread(AndroidVideoDecodeAccelerator* avda) { | 148 void StopThread(AVDACodecAllocatorClient* avda) { |
| 126 // Note that we also wait for the stop event, so that we know that the | 149 // Note that we also wait for the stop event, so that we know that the |
| 127 // stop has completed. It's async with respect to the allocator thread. | 150 // stop has completed. It's async with respect to the allocator thread. |
| 128 PostAndWait(FROM_HERE, base::Bind( | 151 PostAndWait(FROM_HERE, base::Bind( |
| 129 [](AVDACodecAllocator* allocator, | 152 [](AVDACodecAllocator* allocator, |
| 130 AndroidVideoDecodeAccelerator* avda) { | 153 AVDACodecAllocatorClient* avda) { |
| 131 allocator->StopThread(avda); | 154 allocator->StopThread(avda); |
| 132 return true; | 155 return true; |
| 133 }, | 156 }, |
| 134 allocator_, avda)); | 157 allocator_, avda)); |
| 135 // Note that we don't do this on the allocator thread, since that's the | 158 // Note that we don't do this on the allocator thread, since that's the |
| 136 // thread that will signal it. | 159 // thread that will signal it. |
| 137 test_information_->stop_event_->Wait(); | 160 test_information_->stop_event_->Wait(); |
| 138 } | 161 } |
| 139 | 162 |
| 140 // Return the running state of |task_type|, doing the necessary thread hops. | 163 // Return the running state of |task_type|, doing the necessary thread hops. |
| 141 bool IsThreadRunning(AVDACodecAllocator::TaskType task_type) { | 164 bool IsThreadRunning(TaskType task_type) { |
| 142 return PostAndWait( | 165 return PostAndWait( |
| 143 FROM_HERE, | 166 FROM_HERE, |
| 144 base::Bind( | 167 base::Bind( |
| 145 [](AVDACodecAllocator* allocator, | 168 [](AVDACodecAllocator* allocator, TaskType task_type) { |
| 146 AVDACodecAllocator::TaskType task_type) { | |
| 147 return allocator->GetThreadForTesting(task_type).IsRunning(); | 169 return allocator->GetThreadForTesting(task_type).IsRunning(); |
| 148 }, | 170 }, |
| 149 allocator_, task_type)); | 171 allocator_, task_type)); |
| 150 } | 172 } |
| 151 | 173 |
| 152 AVDACodecAllocator::TaskType TaskTypeForAllocation() { | 174 TaskType TaskTypeForAllocation() { |
| 153 return PostAndWait(FROM_HERE, | 175 return PostAndWait(FROM_HERE, |
| 154 base::Bind(&AVDACodecAllocator::TaskTypeForAllocation, | 176 base::Bind(&AVDACodecAllocator::TaskTypeForAllocation, |
| 155 base::Unretained(allocator_))); | 177 base::Unretained(allocator_))); |
| 156 } | 178 } |
| 157 | 179 |
| 158 scoped_refptr<base::SingleThreadTaskRunner> TaskRunnerFor( | 180 scoped_refptr<base::SingleThreadTaskRunner> TaskRunnerFor( |
| 159 AVDACodecAllocator::TaskType task_type) { | 181 TaskType task_type) { |
| 160 return PostAndWait(FROM_HERE, | 182 return PostAndWait(FROM_HERE, |
| 161 base::Bind(&AVDACodecAllocator::TaskRunnerFor, | 183 base::Bind(&AVDACodecAllocator::TaskRunnerFor, |
| 162 base::Unretained(allocator_), task_type)); | 184 base::Unretained(allocator_), task_type)); |
| 163 } | 185 } |
| 164 | 186 |
| 165 // Post |cb| to the allocator thread, and wait for a response. Note that we | 187 // Post |cb| to the allocator thread, and wait for a response. Note that we |
| 166 // don't have a specialization for void, and void won't work as written. So, | 188 // don't have a specialization for void, and void won't work as written. So, |
| 167 // be sure to return something. | 189 // be sure to return something. |
| 168 template <typename ReturnType> | 190 template <typename ReturnType> |
| 169 ReturnType PostAndWait(const tracked_objects::Location& from_here, | 191 ReturnType PostAndWait(const tracked_objects::Location& from_here, |
| 170 const base::Callback<ReturnType(void)>& cb) { | 192 const base::Callback<ReturnType(void)>& cb) { |
| 171 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, | 193 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, |
| 172 base::WaitableEvent::InitialState::NOT_SIGNALED); | 194 base::WaitableEvent::InitialState::NOT_SIGNALED); |
| 173 ReturnType return_value = ReturnType(); | 195 ReturnType return_value = ReturnType(); |
| 174 allocator_thread_.task_runner()->PostTask( | 196 allocator_thread_.task_runner()->PostTask( |
| 175 from_here, | 197 from_here, |
| 176 base::Bind(&RunAndSignalTask<ReturnType>, &event, &return_value, cb)); | 198 base::Bind(&RunAndSignalTask<ReturnType>, &event, &return_value, cb)); |
| 177 event.Wait(); | 199 event.Wait(); |
| 178 return return_value; | 200 return return_value; |
| 179 } | 201 } |
| 180 | 202 |
| 181 base::Thread allocator_thread_; | 203 base::Thread allocator_thread_; |
| 182 | 204 |
| 183 // Test info that we provide to the codec allocator. | 205 // Test info that we provide to the codec allocator. |
| 184 std::unique_ptr<AVDACodecAllocator::TestInformation> test_information_; | 206 std::unique_ptr<AVDACodecAllocator::TestInformation> test_information_; |
| 185 | 207 |
| 186 // Allocator that we own. Would be a unique_ptr, but the destructor is | 208 // Allocators that we own. The first is intialized to be used on the allocator |
| 187 // private. Plus, we need to destruct it from the right thread. | 209 // thread and the second one is initialized on the test thread. Each test |
| 210 // should only be using one of the two. They are not unique_ptrs because the |
| 211 // destructor is private and they need to be destructed on the right thread. |
| 188 AVDACodecAllocator* allocator_ = nullptr; | 212 AVDACodecAllocator* allocator_ = nullptr; |
| 213 AVDACodecAllocator* allocator2_ = nullptr; |
| 189 | 214 |
| 190 AndroidVideoDecodeAccelerator* avda1_ = (AndroidVideoDecodeAccelerator*)0x1; | 215 NiceMock<MockClient> client1_, client2_, client3_; |
| 191 AndroidVideoDecodeAccelerator* avda2_ = (AndroidVideoDecodeAccelerator*)0x2; | 216 NiceMock<MockClient>* avda1_ = &client1_; |
| 217 NiceMock<MockClient>* avda2_ = &client2_; |
| 218 NiceMock<MockClient>* avda3_ = &client3_; |
| 192 }; | 219 }; |
| 193 | 220 |
| 194 TEST_F(AVDACodecAllocatorTest, TestMultiInstance) { | 221 TEST_F(AVDACodecAllocatorTest, TestMultiInstance) { |
| 195 // Add an avda instance. This one must succeed immediately, since the last | 222 // Add an avda instance. This one must succeed immediately, since the last |
| 196 // one is still running. | 223 // one is still running. |
| 197 ASSERT_TRUE(StartThread(avda2_)); | 224 ASSERT_TRUE(StartThread(avda2_)); |
| 198 | 225 |
| 199 // Stop the original avda instance. | 226 // Stop the original avda instance. |
| 200 StopThread(avda1_); | 227 StopThread(avda1_); |
| 201 | 228 |
| 202 // Verify that the AUTO_CODEC thread is still running. | 229 // Verify that the AUTO_CODEC thread is still running. |
| 203 ASSERT_TRUE(IsThreadRunning(AVDACodecAllocator::TaskType::AUTO_CODEC)); | 230 ASSERT_TRUE(IsThreadRunning(TaskType::AUTO_CODEC)); |
| 204 ASSERT_EQ(AVDACodecAllocator::TaskType::AUTO_CODEC, TaskTypeForAllocation()); | 231 ASSERT_EQ(TaskType::AUTO_CODEC, TaskTypeForAllocation()); |
| 205 | 232 |
| 206 // Remove the second instance and wait for it to stop. Remember that it | 233 // Remove the second instance and wait for it to stop. Remember that it |
| 207 // stops after messages have been posted to the thread, so we don't know | 234 // stops after messages have been posted to the thread, so we don't know |
| 208 // how long it will take. | 235 // how long it will take. |
| 209 StopThread(avda2_); | 236 StopThread(avda2_); |
| 210 | 237 |
| 211 // Verify that the threads have stopped. | 238 // Verify that the threads have stopped. |
| 212 ASSERT_FALSE(IsThreadRunning(AVDACodecAllocator::TaskType::AUTO_CODEC)); | 239 ASSERT_FALSE(IsThreadRunning(TaskType::AUTO_CODEC)); |
| 213 ASSERT_FALSE(IsThreadRunning(AVDACodecAllocator::TaskType::SW_CODEC)); | 240 ASSERT_FALSE(IsThreadRunning(TaskType::SW_CODEC)); |
| 214 } | 241 } |
| 215 | 242 |
| 216 TEST_F(AVDACodecAllocatorTest, TestHangThread) { | 243 TEST_F(AVDACodecAllocatorTest, TestHangThread) { |
| 217 ASSERT_EQ(AVDACodecAllocator::TaskType::AUTO_CODEC, TaskTypeForAllocation()); | 244 ASSERT_EQ(TaskType::AUTO_CODEC, TaskTypeForAllocation()); |
| 218 | 245 |
| 219 // Hang the AUTO_CODEC thread. | 246 // Hang the AUTO_CODEC thread. |
| 220 base::WaitableEvent about_to_wait_event( | 247 base::WaitableEvent about_to_wait_event( |
| 221 base::WaitableEvent::ResetPolicy::MANUAL, | 248 base::WaitableEvent::ResetPolicy::MANUAL, |
| 222 base::WaitableEvent::InitialState::NOT_SIGNALED); | 249 base::WaitableEvent::InitialState::NOT_SIGNALED); |
| 223 base::WaitableEvent wait_event( | 250 base::WaitableEvent wait_event( |
| 224 base::WaitableEvent::ResetPolicy::MANUAL, | 251 base::WaitableEvent::ResetPolicy::MANUAL, |
| 225 base::WaitableEvent::InitialState::NOT_SIGNALED); | 252 base::WaitableEvent::InitialState::NOT_SIGNALED); |
| 226 TaskRunnerFor(AVDACodecAllocator::TaskType::AUTO_CODEC) | 253 TaskRunnerFor(TaskType::AUTO_CODEC) |
| 227 ->PostTask(FROM_HERE, | 254 ->PostTask(FROM_HERE, base::Bind(&WaitUntilRestarted, |
| 228 base::Bind(&AVDACodecAllocatorTest::WaitUntilRestarted, | 255 &about_to_wait_event, &wait_event)); |
| 229 &about_to_wait_event, &wait_event)); | |
| 230 // Wait until the task starts, so that |allocator_| starts the hang timer. | 256 // Wait until the task starts, so that |allocator_| starts the hang timer. |
| 231 about_to_wait_event.Wait(); | 257 about_to_wait_event.Wait(); |
| 232 | 258 |
| 233 // Verify that we've failed over after a long time has passed. | 259 // Verify that we've failed over after a long time has passed. |
| 234 static_cast<MockTickClock*>(test_information_->tick_clock_.get()) | 260 static_cast<MockTickClock*>(test_information_->tick_clock_.get()) |
| 235 ->Advance(1000); | 261 ->Advance(1000); |
| 236 // Note that this should return the SW codec task type even if that thread | 262 // Note that this should return the SW codec task type even if that thread |
| 237 // failed to start. TaskRunnerFor() will return the current thread in that | 263 // failed to start. TaskRunnerFor() will return the current thread in that |
| 238 // case too. | 264 // case too. |
| 239 ASSERT_EQ(AVDACodecAllocator::TaskType::SW_CODEC, TaskTypeForAllocation()); | 265 ASSERT_EQ(TaskType::SW_CODEC, TaskTypeForAllocation()); |
| 240 | 266 |
| 241 // Un-hang the thread and wait for it to let another task run. This will | 267 // Un-hang the thread and wait for it to let another task run. This will |
| 242 // notify |allocator_| that the thread is no longer hung. | 268 // notify |allocator_| that the thread is no longer hung. |
| 243 base::WaitableEvent done_waiting_event( | 269 base::WaitableEvent done_waiting_event( |
| 244 base::WaitableEvent::ResetPolicy::MANUAL, | 270 base::WaitableEvent::ResetPolicy::MANUAL, |
| 245 base::WaitableEvent::InitialState::NOT_SIGNALED); | 271 base::WaitableEvent::InitialState::NOT_SIGNALED); |
| 246 TaskRunnerFor(AVDACodecAllocator::TaskType::AUTO_CODEC) | 272 TaskRunnerFor(TaskType::AUTO_CODEC) |
| 247 ->PostTask(FROM_HERE, | 273 ->PostTask(FROM_HERE, |
| 248 base::Bind(&AVDACodecAllocatorTest::SignalImmediately, | 274 base::Bind(&SignalImmediately, &done_waiting_event)); |
| 249 &done_waiting_event)); | |
| 250 wait_event.Signal(); | 275 wait_event.Signal(); |
| 251 done_waiting_event.Wait(); | 276 done_waiting_event.Wait(); |
| 252 | 277 |
| 253 // Verify that we've un-failed over. | 278 // Verify that we've un-failed over. |
| 254 ASSERT_EQ(AVDACodecAllocator::TaskType::AUTO_CODEC, TaskTypeForAllocation()); | 279 ASSERT_EQ(TaskType::AUTO_CODEC, TaskTypeForAllocation()); |
| 280 } |
| 281 |
| 282 TEST_F(AVDACodecAllocatorTest, AllocatingASurfaceTextureAlwaysSucceeds) { |
| 283 ASSERT_TRUE( |
| 284 allocator2_->AllocateSurface(avda1_, SurfaceManager::kNoSurfaceID)); |
| 285 ASSERT_TRUE( |
| 286 allocator2_->AllocateSurface(avda2_, SurfaceManager::kNoSurfaceID)); |
| 287 } |
| 288 |
| 289 TEST_F(AVDACodecAllocatorTest, AllocatingAnOwnedSurfaceFails) { |
| 290 ASSERT_TRUE(allocator2_->AllocateSurface(avda1_, 1)); |
| 291 ASSERT_FALSE(allocator2_->AllocateSurface(avda2_, 1)); |
| 292 } |
| 293 |
| 294 TEST_F(AVDACodecAllocatorTest, LaterWaitersReplaceEarlierWaiters) { |
| 295 allocator2_->AllocateSurface(avda1_, 1); |
| 296 allocator2_->AllocateSurface(avda2_, 1); |
| 297 EXPECT_CALL(*avda2_, OnSurfaceAvailable(false)); |
| 298 allocator2_->AllocateSurface(avda3_, 1); |
| 299 } |
| 300 |
| 301 TEST_F(AVDACodecAllocatorTest, WaitersBecomeOwnersWhenSurfacesAreReleased) { |
| 302 allocator2_->AllocateSurface(avda1_, 1); |
| 303 allocator2_->AllocateSurface(avda2_, 1); |
| 304 EXPECT_CALL(*avda2_, OnSurfaceAvailable(true)); |
| 305 allocator2_->DeallocateSurface(avda1_, 1); |
| 306 // The surface should still be owned. |
| 307 ASSERT_FALSE(allocator2_->AllocateSurface(avda1_, 1)); |
| 308 } |
| 309 |
| 310 TEST_F(AVDACodecAllocatorTest, DeallocatingUnownedSurfacesIsSafe) { |
| 311 allocator2_->DeallocateSurface(avda1_, 1); |
| 312 allocator2_->DeallocateSurface(avda1_, SurfaceManager::kNoSurfaceID); |
| 313 } |
| 314 |
| 315 TEST_F(AVDACodecAllocatorTest, WaitersAreRemovedIfTheyDeallocate) { |
| 316 allocator2_->AllocateSurface(avda1_, 1); |
| 317 allocator2_->AllocateSurface(avda2_, 1); |
| 318 allocator2_->DeallocateSurface(avda2_, 1); |
| 319 // avda2_ should should not receive a notification. |
| 320 EXPECT_CALL(*avda2_, OnSurfaceAvailable(_)).Times(0); |
| 321 allocator2_->DeallocateSurface(avda1_, 1); |
| 322 } |
| 323 |
| 324 TEST_F(AVDACodecAllocatorTest, OwnersAreNotifiedOnDestruction) { |
| 325 allocator2_->AllocateSurface(avda1_, 1); |
| 326 // Not notified for a surface it doesn't own. |
| 327 EXPECT_CALL(*avda1_, OnSurfaceDestroyed()).Times(0); |
| 328 allocator2_->OnSurfaceDestroyed(123); |
| 329 // But notified for a surface it does own. |
| 330 EXPECT_CALL(*avda1_, OnSurfaceDestroyed()); |
| 331 allocator2_->OnSurfaceDestroyed(1); |
| 332 } |
| 333 |
| 334 TEST_F(AVDACodecAllocatorTest, WaitersAreNotifiedOnDestruction) { |
| 335 allocator2_->AllocateSurface(avda1_, 1); |
| 336 allocator2_->AllocateSurface(avda2_, 1); |
| 337 EXPECT_CALL(*avda2_, OnSurfaceAvailable(false)); |
| 338 allocator2_->OnSurfaceDestroyed(1); |
| 339 } |
| 340 |
| 341 TEST_F(AVDACodecAllocatorTest, DeallocatingIsSafeDuringSurfaceDestroyed) { |
| 342 allocator2_->AllocateSurface(avda1_, 1); |
| 343 EXPECT_CALL(*avda1_, OnSurfaceDestroyed()).WillOnce(Invoke([=]() { |
| 344 allocator2_->DeallocateSurface(avda1_, 1); |
| 345 })); |
| 346 allocator2_->OnSurfaceDestroyed(1); |
| 255 } | 347 } |
| 256 | 348 |
| 257 } // namespace media | 349 } // namespace media |
| OLD | NEW |