| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #define _CRT_SECURE_NO_WARNINGS | |
| 6 | |
| 7 #if 0 | |
| 8 #include <deque> | |
| 9 | |
| 10 #include "base/callback.h" | |
| 11 #include "base/message_loop.h" | |
| 12 #include "base/task.h" | |
| 13 #include "media/base/buffers.h" | |
| 14 #include "media/base/mock_filters.h" | |
| 15 #include "media/base/mock_task.h" | |
| 16 #include "media/ffmpeg/ffmpeg_common.h" | |
| 17 #include "media/video/omx_video_decode_engine.h" | |
| 18 #include "media/video/video_decode_engine.h" | |
| 19 #include "media/omx/mock_omx.h" | |
| 20 #include "testing/gtest/include/gtest/gtest.h" | |
| 21 | |
| 22 using ::testing::_; | |
| 23 using ::testing::DoAll; | |
| 24 using ::testing::InSequence; | |
| 25 using ::testing::IsNull; | |
| 26 using ::testing::NotNull; | |
| 27 using ::testing::Return; | |
| 28 using ::testing::SaveArg; | |
| 29 using ::testing::SetArgumentPointee; | |
| 30 using ::testing::StrEq; | |
| 31 using ::testing::StrictMock; | |
| 32 | |
| 33 namespace media { | |
| 34 | |
| 35 static const int kBufferCount = 3; | |
| 36 static const int kBufferSize = 4096; | |
| 37 static const char* kComponentName = "OMX.google.video_decoder.avc"; | |
| 38 | |
| 39 ACTION(ReturnComponentName) { | |
| 40 strcpy(((char**)arg2)[0], kComponentName); | |
| 41 } | |
| 42 | |
| 43 ACTION(GetHandle) { | |
| 44 *arg0 = MockOmx::get()->component(); | |
| 45 MockOmx::get()->component()->pApplicationPrivate = arg2; | |
| 46 memcpy(MockOmx::get()->callbacks(), arg3, sizeof(OMX_CALLBACKTYPE)); | |
| 47 } | |
| 48 | |
| 49 ACTION(GetParameterVideoInit) { | |
| 50 ((OMX_PORT_PARAM_TYPE*)arg1)->nStartPortNumber = 0; | |
| 51 } | |
| 52 | |
| 53 ACTION(GetParameterPortDefinition) { | |
| 54 OMX_PARAM_PORTDEFINITIONTYPE* port_format = | |
| 55 (OMX_PARAM_PORTDEFINITIONTYPE*)arg1; | |
| 56 CHECK(port_format->nPortIndex == 0 || port_format->nPortIndex == 1); | |
| 57 if (port_format->nPortIndex == 0) | |
| 58 port_format->eDir = OMX_DirInput; | |
| 59 else | |
| 60 port_format->eDir = OMX_DirOutput; | |
| 61 port_format->nBufferCountMin = kBufferCount; | |
| 62 port_format->nBufferCountActual = kBufferCount; | |
| 63 port_format->nBufferSize = kBufferSize; | |
| 64 } | |
| 65 | |
| 66 ACTION(AllocateBuffer) { | |
| 67 *arg0 = new OMX_BUFFERHEADERTYPE(); | |
| 68 memset(*arg0, 0, sizeof(OMX_BUFFERHEADERTYPE)); | |
| 69 (*arg0)->nAllocLen = arg3; | |
| 70 (*arg0)->pBuffer = new uint8[arg3]; | |
| 71 (*arg0)->nOutputPortIndex = 1; | |
| 72 (*arg0)->nInputPortIndex = OMX_ALL; | |
| 73 } | |
| 74 | |
| 75 ACTION(UseBuffer) { | |
| 76 *arg0 = new OMX_BUFFERHEADERTYPE(); | |
| 77 memset(*arg0, 0, sizeof(OMX_BUFFERHEADERTYPE)); | |
| 78 (*arg0)->nOutputPortIndex = OMX_ALL; | |
| 79 (*arg0)->nInputPortIndex = 0; | |
| 80 } | |
| 81 | |
| 82 ACTION(FreeBuffer) { | |
| 83 if (1 == arg1->nOutputPortIndex) | |
| 84 delete [] arg1->pBuffer; | |
| 85 delete arg1; | |
| 86 } | |
| 87 | |
| 88 ACTION_P3(SendEvent, event, data1, data2) { | |
| 89 (*MockOmx::get()->callbacks()->EventHandler)( | |
| 90 MockOmx::get()->component(), | |
| 91 MockOmx::get()->component()->pApplicationPrivate, | |
| 92 event, static_cast<OMX_U32>(data1), static_cast<OMX_U32>(data2), NULL); | |
| 93 } | |
| 94 | |
| 95 ACTION_P(EmptyBufferDone, output_pool_ptr) { | |
| 96 (*MockOmx::get()->callbacks()->EmptyBufferDone)( | |
| 97 MockOmx::get()->component(), | |
| 98 MockOmx::get()->component()->pApplicationPrivate, | |
| 99 arg0); | |
| 100 OMX_BUFFERHEADERTYPE* out_buffer = output_pool_ptr->front(); | |
| 101 output_pool_ptr->pop_front(); | |
| 102 if (arg0->nFlags & OMX_BUFFERFLAG_EOS) | |
| 103 out_buffer->nFlags |= OMX_BUFFERFLAG_EOS; | |
| 104 out_buffer->nFilledLen = kBufferSize; | |
| 105 (*MockOmx::get()->callbacks()->FillBufferDone)( | |
| 106 MockOmx::get()->component(), | |
| 107 MockOmx::get()->component()->pApplicationPrivate, | |
| 108 out_buffer); | |
| 109 } | |
| 110 | |
| 111 ACTION_P(EnqueueOutputBuffer, output_pool_ptr) { | |
| 112 output_pool_ptr->push_back(arg0); | |
| 113 } | |
| 114 | |
| 115 ACTION(FillEosBuffer) { | |
| 116 arg0->nFlags = OMX_BUFFERFLAG_EOS; | |
| 117 arg0->nFilledLen = 0; | |
| 118 (*MockOmx::get()->callbacks()->FillBufferDone)( | |
| 119 MockOmx::get()->component(), | |
| 120 MockOmx::get()->component()->pApplicationPrivate, | |
| 121 arg0); | |
| 122 } | |
| 123 | |
| 124 class TestBuffer : public media::Buffer { | |
| 125 public: | |
| 126 TestBuffer() : size_(0), data_(NULL) { } | |
| 127 explicit TestBuffer(int size) : size_(size) { | |
| 128 if (size) | |
| 129 data_.reset(new uint8[size]); | |
| 130 else | |
| 131 data_.reset(NULL); | |
| 132 } | |
| 133 virtual const uint8* GetData() const { | |
| 134 return data_.get(); | |
| 135 } | |
| 136 virtual size_t GetDataSize() const { | |
| 137 return size_; | |
| 138 } | |
| 139 private: | |
| 140 virtual ~TestBuffer() { } | |
| 141 | |
| 142 int size_; | |
| 143 scoped_array<uint8> data_; | |
| 144 DISALLOW_COPY_AND_ASSIGN(TestBuffer); | |
| 145 }; | |
| 146 | |
| 147 class OmxCodecTest : public testing::Test { | |
| 148 public: | |
| 149 OmxCodecTest () | |
| 150 : input_buffer_count_(0), | |
| 151 got_eos_(false), | |
| 152 omx_engine_(new OmxVideoDecodeEngine()) { | |
| 153 av_stream_.codec = &av_codec_context_; | |
| 154 av_codec_context_.width = 16; | |
| 155 av_codec_context_.height = 16; | |
| 156 feed_done_cb_ = | |
| 157 NewCallback(this, &OmxCodecTest::EmptyBufferDoneCallback); | |
| 158 decode_done_cb_ = | |
| 159 NewCallback(this, &OmxCodecTest::FillBufferDoneCallback); | |
| 160 } | |
| 161 | |
| 162 ~OmxCodecTest() { | |
| 163 } | |
| 164 | |
| 165 protected: | |
| 166 void ExpectSettings() { | |
| 167 // Return the component name. | |
| 168 EXPECT_CALL(*MockOmx::get(), GetComponentsOfRole(_, _, IsNull())) | |
| 169 .WillOnce(DoAll(SetArgumentPointee<1>(1), | |
| 170 Return(OMX_ErrorNone))); | |
| 171 EXPECT_CALL(*MockOmx::get(), GetComponentsOfRole(_, _, NotNull())) | |
| 172 .WillOnce(DoAll(SetArgumentPointee<1>(1), | |
| 173 ReturnComponentName(), | |
| 174 Return(OMX_ErrorNone))); | |
| 175 | |
| 176 // Handle get parameter calls. | |
| 177 EXPECT_CALL(*MockOmx::get(), | |
| 178 GetParameter(OMX_IndexParamVideoInit, NotNull())) | |
| 179 .WillRepeatedly(DoAll(GetParameterVideoInit(), Return(OMX_ErrorNone))); | |
| 180 EXPECT_CALL(*MockOmx::get(), | |
| 181 GetParameter(OMX_IndexParamPortDefinition, NotNull())) | |
| 182 .WillRepeatedly(DoAll(GetParameterPortDefinition(), | |
| 183 Return(OMX_ErrorNone))); | |
| 184 | |
| 185 // Ignore all set parameter calls. | |
| 186 EXPECT_CALL(*MockOmx::get(), SetParameter(_, _)) | |
| 187 .WillRepeatedly(Return(OMX_ErrorNone)); | |
| 188 } | |
| 189 | |
| 190 void ExpectToLoaded() { | |
| 191 InSequence s; | |
| 192 | |
| 193 // Expect initialization. | |
| 194 EXPECT_CALL(*MockOmx::get(), Init()) | |
| 195 .WillOnce(Return(OMX_ErrorNone)); | |
| 196 | |
| 197 // Return the handle. | |
| 198 EXPECT_CALL(*MockOmx::get(), | |
| 199 GetHandle(NotNull(), StrEq(kComponentName), | |
| 200 NotNull(), NotNull())) | |
| 201 .WillOnce(DoAll(GetHandle(), | |
| 202 Return(OMX_ErrorNone))); | |
| 203 } | |
| 204 | |
| 205 void ExpectLoadedToIdle() { | |
| 206 InSequence s; | |
| 207 | |
| 208 // Expect transition to idle. | |
| 209 EXPECT_CALL(*MockOmx::get(), | |
| 210 SendCommand(OMX_CommandStateSet, OMX_StateIdle, _)) | |
| 211 .WillOnce( | |
| 212 DoAll( | |
| 213 SendEvent(OMX_EventCmdComplete, OMX_CommandStateSet, | |
| 214 OMX_StateIdle), | |
| 215 Return(OMX_ErrorNone))); | |
| 216 | |
| 217 // Expect allocation of buffers. | |
| 218 EXPECT_CALL(*MockOmx::get(), | |
| 219 UseBuffer(NotNull(), 0, NotNull(), kBufferSize, _)) | |
| 220 .Times(kBufferCount) | |
| 221 .WillRepeatedly(DoAll(UseBuffer(), Return(OMX_ErrorNone))); | |
| 222 | |
| 223 // Expect allocation of output buffers and send command complete. | |
| 224 EXPECT_CALL(*MockOmx::get(), | |
| 225 AllocateBuffer(NotNull(), 1, IsNull(), kBufferSize)) | |
| 226 .Times(kBufferCount) | |
| 227 .WillRepeatedly(DoAll(AllocateBuffer(), Return(OMX_ErrorNone))); | |
| 228 } | |
| 229 | |
| 230 void ExpectToExecuting() { | |
| 231 InSequence s; | |
| 232 | |
| 233 // Expect transition to executing. | |
| 234 EXPECT_CALL(*MockOmx::get(), | |
| 235 SendCommand(OMX_CommandStateSet, OMX_StateExecuting, _)) | |
| 236 .WillOnce(DoAll( | |
| 237 SendEvent(OMX_EventCmdComplete, OMX_CommandStateSet, | |
| 238 OMX_StateExecuting), | |
| 239 Return(OMX_ErrorNone))); | |
| 240 | |
| 241 // Expect initial FillThisBuffer() calls. | |
| 242 EXPECT_CALL(*MockOmx::get(), FillThisBuffer(NotNull())) | |
| 243 .Times(kBufferCount) | |
| 244 .WillRepeatedly(DoAll(EnqueueOutputBuffer(&output_pool_), | |
| 245 Return(OMX_ErrorNone))); | |
| 246 } | |
| 247 | |
| 248 void ExpectToIdle() { | |
| 249 // Expect going to idle | |
| 250 EXPECT_CALL(*MockOmx::get(), | |
| 251 SendCommand(OMX_CommandStateSet, OMX_StateIdle, _)) | |
| 252 .WillOnce(DoAll( | |
| 253 SendEvent(OMX_EventCmdComplete, OMX_CommandStateSet, OMX_StateIdle), | |
| 254 Return(OMX_ErrorNone))); | |
| 255 } | |
| 256 | |
| 257 void ExpectIdleToLoaded() { | |
| 258 InSequence s; | |
| 259 | |
| 260 // Expect transition to loaded. | |
| 261 EXPECT_CALL(*MockOmx::get(), | |
| 262 SendCommand(OMX_CommandStateSet, OMX_StateLoaded, _)) | |
| 263 .WillOnce(DoAll( | |
| 264 SendEvent(OMX_EventCmdComplete, OMX_CommandStateSet, | |
| 265 OMX_StateLoaded), | |
| 266 Return(OMX_ErrorNone))); | |
| 267 | |
| 268 // Expect free buffer for input port. | |
| 269 EXPECT_CALL(*MockOmx::get(), FreeBuffer(0, NotNull())) | |
| 270 .Times(kBufferCount) | |
| 271 .WillRepeatedly(DoAll(FreeBuffer(), Return(OMX_ErrorNone))); | |
| 272 | |
| 273 EXPECT_CALL(*MockOmx::get(), FreeBuffer(1, NotNull())) | |
| 274 .Times(kBufferCount) | |
| 275 .WillRepeatedly(DoAll(FreeBuffer(), Return(OMX_ErrorNone))); | |
| 276 } | |
| 277 | |
| 278 void ExpectToEmpty() { | |
| 279 InSequence s; | |
| 280 | |
| 281 EXPECT_CALL(*MockOmx::get(), FreeHandle(MockOmx::get()->component())) | |
| 282 .WillOnce(Return(OMX_ErrorNone)); | |
| 283 EXPECT_CALL(*MockOmx::get(), Deinit()) | |
| 284 .WillOnce(Return(OMX_ErrorNone)); | |
| 285 } | |
| 286 | |
| 287 // TODO(hclam): Make a more generic about when to stop. | |
| 288 void ExpectStart() { | |
| 289 ExpectToLoaded(); | |
| 290 ExpectLoadedToIdle(); | |
| 291 ExpectToExecuting(); | |
| 292 EXPECT_CALL(init_done_cb_task_, Run()); | |
| 293 } | |
| 294 | |
| 295 void ExpectStop() { | |
| 296 EXPECT_CALL(stop_task_, Run()); | |
| 297 ExpectToIdle(); | |
| 298 ExpectIdleToLoaded(); | |
| 299 ExpectToEmpty(); | |
| 300 } | |
| 301 | |
| 302 void EmptyBufferDoneCallback(scoped_refptr<Buffer> buffer) { | |
| 303 if (buffer.get()) { | |
| 304 input_units_.push_back(buffer); | |
| 305 } else { | |
| 306 input_buffer_count_++; | |
| 307 scoped_refptr<Buffer> buffer_ref = new TestBuffer(input_buffer_count_); | |
| 308 input_units_.push_back(buffer_ref); | |
| 309 } | |
| 310 } | |
| 311 | |
| 312 void FillBufferDoneCallback(scoped_refptr<VideoFrame> frame) { | |
| 313 output_units_.push_back(frame); | |
| 314 if (frame->IsEndOfStream()) | |
| 315 got_eos_ = true; | |
| 316 } | |
| 317 | |
| 318 void MakeEmptyBufferRequest() { | |
| 319 scoped_refptr<Buffer> buffer = input_units_.front(); | |
| 320 input_units_.pop_front(); | |
| 321 omx_engine_->EmptyThisBuffer(buffer); | |
| 322 } | |
| 323 | |
| 324 void SendEOSInputBuffer() { | |
| 325 input_units_.pop_front(); | |
| 326 scoped_refptr<Buffer> buffer_ref = new TestBuffer(); | |
| 327 input_units_.push_front(buffer_ref); | |
| 328 EXPECT_CALL(*MockOmx::get(), EmptyThisBuffer(NotNull())) | |
| 329 .WillOnce(DoAll(EmptyBufferDone(&output_pool_), Return(OMX_ErrorNone))) | |
| 330 .RetiresOnSaturation(); | |
| 331 MakeEmptyBufferRequest(); | |
| 332 message_loop_.RunAllPending(); | |
| 333 } | |
| 334 | |
| 335 int input_buffer_count_; | |
| 336 | |
| 337 std::deque<scoped_refptr<Buffer> > input_units_; | |
| 338 std::deque<scoped_refptr<VideoFrame> > output_units_; | |
| 339 std::deque<OMX_BUFFERHEADERTYPE*> fill_this_buffer_received_; | |
| 340 std::deque<OMX_BUFFERHEADERTYPE*> output_pool_; | |
| 341 | |
| 342 MockOmx mock_omx_; | |
| 343 | |
| 344 bool got_eos_; | |
| 345 MessageLoop message_loop_; | |
| 346 scoped_refptr<OmxVideoDecodeEngine> omx_engine_; | |
| 347 | |
| 348 AVStream av_stream_; | |
| 349 AVCodecContext av_codec_context_; | |
| 350 | |
| 351 VideoDecodeEngine::ProduceVideoSampleCallback* feed_done_cb_; | |
| 352 VideoDecodeEngine::ConsumeVideoFrameCallback* decode_done_cb_; | |
| 353 TaskMocker init_done_cb_task_; | |
| 354 | |
| 355 TaskMocker stop_task_; | |
| 356 | |
| 357 private: | |
| 358 DISALLOW_COPY_AND_ASSIGN(OmxCodecTest); | |
| 359 }; | |
| 360 | |
| 361 TEST_F(OmxCodecTest, SimpleStartAndStop) { | |
| 362 ExpectSettings(); | |
| 363 ExpectStart(); | |
| 364 omx_engine_->Initialize(&message_loop_, | |
| 365 &av_stream_, | |
| 366 feed_done_cb_, | |
| 367 decode_done_cb_, | |
| 368 init_done_cb_task_.CreateTask()); | |
| 369 message_loop_.RunAllPending(); | |
| 370 | |
| 371 EXPECT_EQ(kBufferCount, input_buffer_count_); | |
| 372 EXPECT_EQ(VideoDecodeEngine::kNormal, omx_engine_->state()); | |
| 373 | |
| 374 ExpectStop(); | |
| 375 omx_engine_->Stop(stop_task_.CreateTask()); | |
| 376 message_loop_.RunAllPending(); | |
| 377 } | |
| 378 | |
| 379 TEST_F(OmxCodecTest, NormalFlow) { | |
| 380 ExpectSettings(); | |
| 381 ExpectStart(); | |
| 382 omx_engine_->Initialize(&message_loop_, | |
| 383 &av_stream_, | |
| 384 feed_done_cb_, | |
| 385 decode_done_cb_, | |
| 386 init_done_cb_task_.CreateTask()); | |
| 387 message_loop_.RunAllPending(); | |
| 388 | |
| 389 EXPECT_EQ(kBufferCount, input_buffer_count_); | |
| 390 EXPECT_EQ(VideoDecodeEngine::kNormal, omx_engine_->state()); | |
| 391 | |
| 392 // Make emptybuffer requests. | |
| 393 EXPECT_EQ(0u, output_units_.size()); | |
| 394 int count = output_pool_.size(); | |
| 395 for (int i = 0; i < kBufferCount; ++i) { | |
| 396 // Give input buffers to OmxVideoDecodeEngine. OmxVideoDecodeEngine will | |
| 397 // make a new FillThisBuffer() call for each read. | |
| 398 EXPECT_CALL(*MockOmx::get(), EmptyThisBuffer(NotNull())) | |
| 399 .WillOnce(DoAll(EmptyBufferDone(&output_pool_), Return(OMX_ErrorNone))) | |
| 400 .RetiresOnSaturation(); | |
| 401 EXPECT_CALL(*MockOmx::get(), FillThisBuffer(NotNull())) | |
| 402 .WillOnce(DoAll(EnqueueOutputBuffer(&output_pool_), | |
| 403 Return(OMX_ErrorNone))) | |
| 404 .RetiresOnSaturation(); | |
| 405 MakeEmptyBufferRequest(); | |
| 406 } | |
| 407 message_loop_.RunAllPending(); | |
| 408 EXPECT_EQ(kBufferCount, static_cast<int>(input_units_.size())); | |
| 409 EXPECT_EQ(kBufferCount, static_cast<int>(output_units_.size())); | |
| 410 EXPECT_EQ(count, static_cast<int>(output_pool_.size())); | |
| 411 output_units_.clear(); | |
| 412 | |
| 413 // Send EndOfStream, expect eos flag. | |
| 414 SendEOSInputBuffer(); | |
| 415 EXPECT_EQ(kBufferCount - 1, static_cast<int>(input_units_.size())); | |
| 416 EXPECT_EQ(1, static_cast<int>(output_units_.size())); | |
| 417 EXPECT_EQ(count - 1, static_cast<int>(output_pool_.size())); | |
| 418 EXPECT_TRUE(got_eos_); | |
| 419 | |
| 420 // Shutdown. | |
| 421 ExpectStop(); | |
| 422 omx_engine_->Stop(stop_task_.CreateTask()); | |
| 423 message_loop_.RunAllPending(); | |
| 424 } | |
| 425 | |
| 426 TEST_F(OmxCodecTest, RecycleInputBuffers) { | |
| 427 ExpectSettings(); | |
| 428 ExpectStart(); | |
| 429 omx_engine_->Initialize(&message_loop_, | |
| 430 &av_stream_, | |
| 431 feed_done_cb_, | |
| 432 decode_done_cb_, | |
| 433 init_done_cb_task_.CreateTask()); | |
| 434 message_loop_.RunAllPending(); | |
| 435 | |
| 436 EXPECT_EQ(kBufferCount, input_buffer_count_); | |
| 437 EXPECT_EQ(VideoDecodeEngine::kNormal, omx_engine_->state()); | |
| 438 | |
| 439 // Make emptybuffer requests, also recycle input buffers | |
| 440 EXPECT_EQ(0u, output_units_.size()); | |
| 441 int count = output_pool_.size(); | |
| 442 int repeat_count = kBufferCount * 2; | |
| 443 for (int i = 0; i < repeat_count; ++i) { | |
| 444 // Give input buffers to OmxVideoDecodeEngine. OmxVideoDecodeEngine will | |
| 445 // make a new FillThisBuffer() call for each read. | |
| 446 EXPECT_CALL(*MockOmx::get(), EmptyThisBuffer(NotNull())) | |
| 447 .WillOnce(DoAll(EmptyBufferDone(&output_pool_), Return(OMX_ErrorNone))) | |
| 448 .RetiresOnSaturation(); | |
| 449 EXPECT_CALL(*MockOmx::get(), FillThisBuffer(NotNull())) | |
| 450 .WillOnce(DoAll(EnqueueOutputBuffer(&output_pool_), | |
| 451 Return(OMX_ErrorNone))) | |
| 452 .RetiresOnSaturation(); | |
| 453 MakeEmptyBufferRequest(); | |
| 454 message_loop_.RunAllPending(); | |
| 455 CHECK(kBufferCount == static_cast<int>(input_units_.size())); | |
| 456 CHECK(((i % kBufferCount) + 1) == | |
| 457 static_cast<int>(input_units_.back()->GetDataSize())); | |
| 458 } | |
| 459 message_loop_.RunAllPending(); | |
| 460 EXPECT_EQ(kBufferCount, static_cast<int>(input_units_.size())); | |
| 461 EXPECT_EQ(repeat_count, static_cast<int>(output_units_.size())); | |
| 462 EXPECT_EQ(count, static_cast<int>(output_pool_.size())); | |
| 463 output_units_.clear(); | |
| 464 | |
| 465 // Send EndOfStream, expect eos flag. | |
| 466 SendEOSInputBuffer(); | |
| 467 EXPECT_EQ(kBufferCount - 1, static_cast<int>(input_units_.size())); | |
| 468 EXPECT_EQ(1, static_cast<int>(output_units_.size())); | |
| 469 EXPECT_EQ(count - 1, static_cast<int>(output_pool_.size())); | |
| 470 EXPECT_TRUE(got_eos_); | |
| 471 | |
| 472 // Shutdown. | |
| 473 ExpectStop(); | |
| 474 omx_engine_->Stop(stop_task_.CreateTask()); | |
| 475 message_loop_.RunAllPending(); | |
| 476 } | |
| 477 | |
| 478 // TODO(hclam): Add test case for dynamic port config. | |
| 479 // TODO(hclam): Create a more complicated test case so that read | |
| 480 // requests and reply from FillThisBuffer() arrives out of order. | |
| 481 | |
| 482 } // namespace media | |
| 483 #endif | |
| OLD | NEW |