| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 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 "content/common/gpu/media/omx_video_decode_accelerator.h" | 5 #include "content/common/gpu/media/omx_video_decode_accelerator.h" |
| 6 | 6 |
| 7 #include "base/stl_util-inl.h" | 7 #include "base/stl_util-inl.h" |
| 8 #include "base/string_util.h" | 8 #include "base/string_util.h" |
| 9 #include "content/common/gpu/gpu_channel.h" | 9 #include "content/common/gpu/gpu_channel.h" |
| 10 #include "content/common/gpu/media/gles2_texture_to_egl_image_translator.h" | 10 #include "content/common/gpu/media/gles2_texture_to_egl_image_translator.h" |
| (...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 328 } | 328 } |
| 329 buffer->pAppPrivate = NULL; | 329 buffer->pAppPrivate = NULL; |
| 330 buffer->nTimeStamp = 0; | 330 buffer->nTimeStamp = 0; |
| 331 buffer->nOutputPortIndex = output_port_; | 331 buffer->nOutputPortIndex = output_port_; |
| 332 CHECK(fake_output_buffers_.insert(buffer).second); | 332 CHECK(fake_output_buffers_.insert(buffer).second); |
| 333 } | 333 } |
| 334 | 334 |
| 335 return true; | 335 return true; |
| 336 } | 336 } |
| 337 | 337 |
| 338 bool OmxVideoDecodeAccelerator::Decode( | 338 void OmxVideoDecodeAccelerator::Decode( |
| 339 const media::BitstreamBuffer& bitstream_buffer) { | 339 const media::BitstreamBuffer& bitstream_buffer) { |
| 340 DCHECK(!free_input_buffers_.empty()); | 340 DCHECK(!free_input_buffers_.empty()); |
| 341 | 341 |
| 342 if (!CanAcceptInput()) | 342 if (!CanAcceptInput()) |
| 343 return false; | 343 return; |
| 344 | 344 |
| 345 OMX_BUFFERHEADERTYPE* omx_buffer = free_input_buffers_.front(); | 345 OMX_BUFFERHEADERTYPE* omx_buffer = free_input_buffers_.front(); |
| 346 free_input_buffers_.pop(); | 346 free_input_buffers_.pop(); |
| 347 | 347 |
| 348 // Setup |omx_buffer|. | 348 // Setup |omx_buffer|. |
| 349 scoped_ptr<base::SharedMemory> shm( | 349 scoped_ptr<base::SharedMemory> shm( |
| 350 new base::SharedMemory(bitstream_buffer.handle(), true)); | 350 new base::SharedMemory(bitstream_buffer.handle(), true)); |
| 351 if (!shm->Map(bitstream_buffer.size())) { | 351 if (!shm->Map(bitstream_buffer.size())) { |
| 352 LOG(ERROR) << "Failed to SharedMemory::Map()."; | 352 LOG(ERROR) << "Failed to SharedMemory::Map()."; |
| 353 return false; | 353 return; |
| 354 } | 354 } |
| 355 SharedMemoryAndId* input_buffer_details = new SharedMemoryAndId(); | 355 SharedMemoryAndId* input_buffer_details = new SharedMemoryAndId(); |
| 356 input_buffer_details->first.reset(shm.release()); | 356 input_buffer_details->first.reset(shm.release()); |
| 357 input_buffer_details->second = bitstream_buffer.id(); | 357 input_buffer_details->second = bitstream_buffer.id(); |
| 358 DCHECK(!omx_buffer->pAppPrivate); | 358 DCHECK(!omx_buffer->pAppPrivate); |
| 359 omx_buffer->pAppPrivate = input_buffer_details; | 359 omx_buffer->pAppPrivate = input_buffer_details; |
| 360 omx_buffer->pBuffer = | 360 omx_buffer->pBuffer = |
| 361 static_cast<OMX_U8*>(input_buffer_details->first->memory()); | 361 static_cast<OMX_U8*>(input_buffer_details->first->memory()); |
| 362 omx_buffer->nFilledLen = bitstream_buffer.size(); | 362 omx_buffer->nFilledLen = bitstream_buffer.size(); |
| 363 omx_buffer->nAllocLen = omx_buffer->nFilledLen; | 363 omx_buffer->nAllocLen = omx_buffer->nFilledLen; |
| 364 omx_buffer->nFlags &= ~OMX_BUFFERFLAG_EOS; | 364 omx_buffer->nFlags &= ~OMX_BUFFERFLAG_EOS; |
| 365 // Abuse the header's nTimeStamp field to propagate the bitstream buffer ID to | 365 // Abuse the header's nTimeStamp field to propagate the bitstream buffer ID to |
| 366 // the output buffer's nTimeStamp field, so we can report it back to the | 366 // the output buffer's nTimeStamp field, so we can report it back to the |
| 367 // client in PictureReady(). | 367 // client in PictureReady(). |
| 368 omx_buffer->nTimeStamp = bitstream_buffer.id(); | 368 omx_buffer->nTimeStamp = bitstream_buffer.id(); |
| 369 | 369 |
| 370 // Give this buffer to OMX. | 370 // Give this buffer to OMX. |
| 371 OMX_ERRORTYPE result = OMX_ErrorNone; | 371 OMX_ERRORTYPE result = OMX_ErrorNone; |
| 372 result = OMX_EmptyThisBuffer(component_handle_, omx_buffer); | 372 result = OMX_EmptyThisBuffer(component_handle_, omx_buffer); |
| 373 if (result != OMX_ErrorNone) { | 373 if (result != OMX_ErrorNone) { |
| 374 LOG(ERROR) << "OMX_EmptyThisBuffer() failed with result " << result; | 374 LOG(ERROR) << "OMX_EmptyThisBuffer() failed with result " << result; |
| 375 StopOnError(); | 375 StopOnError(); |
| 376 return false; | 376 return; |
| 377 } | 377 } |
| 378 input_buffers_at_component_++; | 378 input_buffers_at_component_++; |
| 379 return true; | |
| 380 } | 379 } |
| 381 | 380 |
| 382 void OmxVideoDecodeAccelerator::AssignGLESBuffers( | 381 void OmxVideoDecodeAccelerator::AssignGLESBuffers( |
| 383 const std::vector<media::GLESBuffer>& buffers) { | 382 const std::vector<media::GLESBuffer>& buffers) { |
| 384 if (!CanFillBuffer()) { | 383 if (!CanFillBuffer()) { |
| 385 StopOnError(); | 384 StopOnError(); |
| 386 return; | 385 return; |
| 387 } | 386 } |
| 388 CHECK_EQ(output_buffers_at_component_, 0); | 387 CHECK_EQ(output_buffers_at_component_, 0); |
| 389 CHECK_EQ(fake_output_buffers_.size(), 0U); | 388 CHECK_EQ(fake_output_buffers_.size(), 0U); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 433 ++output_buffers_at_component_; | 432 ++output_buffers_at_component_; |
| 434 OMX_ERRORTYPE result = | 433 OMX_ERRORTYPE result = |
| 435 OMX_FillThisBuffer(component_handle_, output_picture.omx_buffer_header); | 434 OMX_FillThisBuffer(component_handle_, output_picture.omx_buffer_header); |
| 436 if (result != OMX_ErrorNone) { | 435 if (result != OMX_ErrorNone) { |
| 437 LOG(ERROR) << "OMX_FillThisBuffer() failed with result " << result; | 436 LOG(ERROR) << "OMX_FillThisBuffer() failed with result " << result; |
| 438 StopOnError(); | 437 StopOnError(); |
| 439 return; | 438 return; |
| 440 } | 439 } |
| 441 } | 440 } |
| 442 | 441 |
| 443 bool OmxVideoDecodeAccelerator::Flush() { | 442 void OmxVideoDecodeAccelerator::Flush() { |
| 444 OMX_STATETYPE il_state; | 443 OMX_STATETYPE il_state; |
| 445 OMX_GetState(component_handle_, &il_state); | 444 OMX_GetState(component_handle_, &il_state); |
| 446 DCHECK_EQ(il_state, OMX_StateExecuting); | 445 DCHECK_EQ(il_state, OMX_StateExecuting); |
| 447 // Decode the pending data first. Then flush I/O ports. | 446 // Decode the pending data first. Then flush I/O ports. |
| 448 if (il_state != OMX_StateExecuting) { | 447 if (il_state != OMX_StateExecuting) { |
| 449 client_->NotifyFlushDone(); | 448 client_->NotifyFlushDone(); |
| 450 return false; | 449 return; |
| 451 } | 450 } |
| 452 on_buffer_flag_event_func_ = &OmxVideoDecodeAccelerator::FlushBegin; | 451 on_buffer_flag_event_func_ = &OmxVideoDecodeAccelerator::FlushBegin; |
| 453 | 452 |
| 454 OMX_BUFFERHEADERTYPE* omx_buffer = free_input_buffers_.front(); | 453 OMX_BUFFERHEADERTYPE* omx_buffer = free_input_buffers_.front(); |
| 455 free_input_buffers_.pop(); | 454 free_input_buffers_.pop(); |
| 456 | 455 |
| 457 omx_buffer->nFilledLen = 0; | 456 omx_buffer->nFilledLen = 0; |
| 458 omx_buffer->nAllocLen = omx_buffer->nFilledLen; | 457 omx_buffer->nAllocLen = omx_buffer->nFilledLen; |
| 459 omx_buffer->nFlags |= OMX_BUFFERFLAG_EOS; | 458 omx_buffer->nFlags |= OMX_BUFFERFLAG_EOS; |
| 460 omx_buffer->nTimeStamp = 0; | 459 omx_buffer->nTimeStamp = 0; |
| 461 // Give this buffer to OMX. | 460 // Give this buffer to OMX. |
| 462 OMX_ERRORTYPE result = OMX_ErrorNone; | 461 OMX_ERRORTYPE result = OMX_ErrorNone; |
| 463 result = OMX_EmptyThisBuffer(component_handle_, omx_buffer); | 462 result = OMX_EmptyThisBuffer(component_handle_, omx_buffer); |
| 464 if (result != OMX_ErrorNone) { | 463 if (result != OMX_ErrorNone) { |
| 465 LOG(ERROR) << "OMX_EmptyThisBuffer() failed with result " << result; | 464 LOG(ERROR) << "OMX_EmptyThisBuffer() failed with result " << result; |
| 466 StopOnError(); | 465 StopOnError(); |
| 467 return false; | 466 return; |
| 468 } | 467 } |
| 469 input_buffers_at_component_++; | 468 input_buffers_at_component_++; |
| 470 return true; | |
| 471 } | 469 } |
| 472 | 470 |
| 473 void OmxVideoDecodeAccelerator::FlushBegin() { | 471 void OmxVideoDecodeAccelerator::FlushBegin() { |
| 474 VLOG(1) << "Starting actual flush for EOS"; | 472 VLOG(1) << "Starting actual flush for EOS"; |
| 475 DCHECK(!on_state_event_func_); | 473 DCHECK(!on_state_event_func_); |
| 476 on_state_event_func_ = &OmxVideoDecodeAccelerator::PauseFromExecuting; | 474 on_state_event_func_ = &OmxVideoDecodeAccelerator::PauseFromExecuting; |
| 477 TransitionToState(OMX_StatePause); | 475 TransitionToState(OMX_StatePause); |
| 478 } | 476 } |
| 479 | 477 |
| 480 void OmxVideoDecodeAccelerator::PauseFromExecuting(OMX_STATETYPE ignored) { | 478 void OmxVideoDecodeAccelerator::PauseFromExecuting(OMX_STATETYPE ignored) { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 518 | 516 |
| 519 void OmxVideoDecodeAccelerator::OutputPortFlushDone(int port) { | 517 void OmxVideoDecodeAccelerator::OutputPortFlushDone(int port) { |
| 520 DCHECK_EQ(port, output_port_); | 518 DCHECK_EQ(port, output_port_); |
| 521 | 519 |
| 522 VLOG(1) << "Output Port has been flushed"; | 520 VLOG(1) << "Output Port has been flushed"; |
| 523 DCHECK_EQ(output_buffers_at_component_, 0); | 521 DCHECK_EQ(output_buffers_at_component_, 0); |
| 524 client_state_ = OMX_StatePause; | 522 client_state_ = OMX_StatePause; |
| 525 client_->NotifyFlushDone(); | 523 client_->NotifyFlushDone(); |
| 526 } | 524 } |
| 527 | 525 |
| 528 bool OmxVideoDecodeAccelerator::Abort() { | 526 void OmxVideoDecodeAccelerator::Abort() { |
| 529 CHECK_EQ(message_loop_, MessageLoop::current()); | 527 CHECK_EQ(message_loop_, MessageLoop::current()); |
| 530 // Abort() implies immediacy but Flush() actually decodes pending data first. | 528 // Abort() implies immediacy but Flush() actually decodes pending data first. |
| 531 // TODO(vhiremath@nvidia.com) Fix the Abort to handle this immediacy. | 529 // TODO(vhiremath@nvidia.com) Fix the Abort to handle this immediacy. |
| 532 ShutDownOMXFromExecuting(); | 530 ShutDownOMXFromExecuting(); |
| 533 return true; | 531 return; |
| 534 } | 532 } |
| 535 | 533 |
| 536 // Event callback during initialization to handle DoneStateSet to idle | 534 // Event callback during initialization to handle DoneStateSet to idle |
| 537 void OmxVideoDecodeAccelerator::OnStateChangeLoadedToIdle(OMX_STATETYPE state) { | 535 void OmxVideoDecodeAccelerator::OnStateChangeLoadedToIdle(OMX_STATETYPE state) { |
| 538 DCHECK(!on_state_event_func_); | 536 DCHECK(!on_state_event_func_); |
| 539 DCHECK_EQ(client_state_, OMX_StateLoaded); | 537 DCHECK_EQ(client_state_, OMX_StateLoaded); |
| 540 DCHECK_EQ(OMX_StateIdle, state); | 538 DCHECK_EQ(OMX_StateIdle, state); |
| 541 | 539 |
| 542 VLOG(1) << "OMX video decode engine is in Idle"; | 540 VLOG(1) << "OMX video decode engine is in Idle"; |
| 543 | 541 |
| (...skipping 478 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1022 OMX_ERRORTYPE result = OMX_SendCommand(component_handle_, | 1020 OMX_ERRORTYPE result = OMX_SendCommand(component_handle_, |
| 1023 cmd, port_index, 0); | 1021 cmd, port_index, 0); |
| 1024 if (result != OMX_ErrorNone) { | 1022 if (result != OMX_ErrorNone) { |
| 1025 LOG(ERROR) << "SendCommand() failed" << cmd << ":" << result; | 1023 LOG(ERROR) << "SendCommand() failed" << cmd << ":" << result; |
| 1026 StopOnError(); | 1024 StopOnError(); |
| 1027 return; | 1025 return; |
| 1028 } | 1026 } |
| 1029 } | 1027 } |
| 1030 | 1028 |
| 1031 DISABLE_RUNNABLE_METHOD_REFCOUNT(OmxVideoDecodeAccelerator); | 1029 DISABLE_RUNNABLE_METHOD_REFCOUNT(OmxVideoDecodeAccelerator); |
| OLD | NEW |