diff options
author | fischman@chromium.org <fischman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-15 17:09:18 +0000 |
---|---|---|
committer | fischman@chromium.org <fischman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-15 17:09:18 +0000 |
commit | ce2d72c6918e9707ef3dc9987369241108ed239f (patch) | |
tree | e6cd9b58cebe325676fae66b65921282c652b2ab /content | |
parent | e849792e6b65f2d495934633cc918dccfacdda5a (diff) | |
download | chromium_src-ce2d72c6918e9707ef3dc9987369241108ed239f.zip chromium_src-ce2d72c6918e9707ef3dc9987369241108ed239f.tar.gz chromium_src-ce2d72c6918e9707ef3dc9987369241108ed239f.tar.bz2 |
Enable fire-and-forget Destroy of HW video decoder, and misc other improvements.
- Instead of requiring the client to wait for NotifyDestroyDone
we do the asynchronous OMX teardown dance on the client's
behalf.
- Prettify/simplify error handling in OVDA for easier matching of
errors to OMX_Core.h and to remove redundant information.
- Enable previously-DISABLED_ early-teardown unittests!
- Remove passing VideoDecoder_Dev object in PPP_VideoDecoder_Dev
calls, because it was unnecssary, and because the
~VideoDecoder_Dev dtor is now not a no-op so we don't want to
call it spuriously.
- Remove accidentally re-added
gpu_video_service_host.cc (originally removed in 92251,
accidentally reintroduced by a bad rebase in 92383).
BUG=none
TEST=ovdatest passes (incl. early-teardown tests) and gles2 works (including reload and EOS handling, no crashes)
Review URL: http://codereview.chromium.org/7361010
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@92704 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
13 files changed, 209 insertions, 233 deletions
diff --git a/content/common/gpu/gpu_messages.h b/content/common/gpu/gpu_messages.h index 8f7c926..888da59 100644 --- a/content/common/gpu/gpu_messages.h +++ b/content/common/gpu/gpu_messages.h @@ -496,8 +496,8 @@ IPC_MESSAGE_ROUTED1(AcceleratedVideoDecoderMsg_Reset, gpu::ReadWriteTokens) /* tokens */ // Send destroy request to the decoder. -IPC_MESSAGE_ROUTED1(AcceleratedVideoDecoderMsg_Destroy, - gpu::ReadWriteTokens) /* tokens */ +IPC_SYNC_MESSAGE_ROUTED1_0(AcceleratedVideoDecoderMsg_Destroy, + gpu::ReadWriteTokens) /* tokens */ //------------------------------------------------------------------------------ // Accelerated Video Decoder Host Messages @@ -536,9 +536,6 @@ IPC_MESSAGE_ROUTED0(AcceleratedVideoDecoderHostMsg_FlushDone) // Confirm decoder has been reset. IPC_MESSAGE_ROUTED0(AcceleratedVideoDecoderHostMsg_ResetDone) -// Confirm decoder has been destroyed. -IPC_MESSAGE_ROUTED0(AcceleratedVideoDecoderHostMsg_DestroyDone) - // Decoder has faced end of stream marker in the stream. IPC_MESSAGE_ROUTED0(AcceleratedVideoDecoderHostMsg_EndOfStream) diff --git a/content/common/gpu/media/gpu_video_decode_accelerator.cc b/content/common/gpu/media/gpu_video_decode_accelerator.cc index 82fd408..6d9b17f 100644 --- a/content/common/gpu/media/gpu_video_decode_accelerator.cc +++ b/content/common/gpu/media/gpu_video_decode_accelerator.cc @@ -163,7 +163,7 @@ void GpuVideoDecodeAccelerator::Initialize(const std::vector<uint32>& configs) { omx_decoder->SetEglState( gfx::GLSurfaceEGL::GetDisplay(), stub_->scheduler()->decoder()->GetGLContext()->GetHandle()); - video_decode_accelerator_.reset(omx_decoder); + video_decode_accelerator_ = omx_decoder; video_decode_accelerator_->Initialize(configs); #else NOTIMPLEMENTED() << "HW video decode acceleration not available."; @@ -250,11 +250,6 @@ void GpuVideoDecodeAccelerator::NotifyResetDone() { LOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_ResetDone) failed"; } -void GpuVideoDecodeAccelerator::NotifyDestroyDone() { - if (!Send(new AcceleratedVideoDecoderHostMsg_DestroyDone(host_route_id_))) - LOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_DestroyDone) failed"; -} - bool GpuVideoDecodeAccelerator::Send(IPC::Message* message) { DCHECK(sender_); return sender_->Send(message); diff --git a/content/common/gpu/media/gpu_video_decode_accelerator.h b/content/common/gpu/media/gpu_video_decode_accelerator.h index 5d0302d..621e47c 100644 --- a/content/common/gpu/media/gpu_video_decode_accelerator.h +++ b/content/common/gpu/media/gpu_video_decode_accelerator.h @@ -47,7 +47,6 @@ class GpuVideoDecodeAccelerator virtual void NotifyEndOfBitstreamBuffer(int32 bitstream_buffer_id) OVERRIDE; virtual void NotifyFlushDone() OVERRIDE; virtual void NotifyResetDone() OVERRIDE; - virtual void NotifyDestroyDone() OVERRIDE; // Function to delegate sending to actual sender. virtual bool Send(IPC::Message* message); @@ -93,7 +92,7 @@ class GpuVideoDecodeAccelerator GpuCommandBufferStub* stub_; // Pointer to the underlying VideoDecodeAccelerator. - scoped_ptr<media::VideoDecodeAccelerator> video_decode_accelerator_; + scoped_refptr<media::VideoDecodeAccelerator> video_decode_accelerator_; DISALLOW_IMPLICIT_CONSTRUCTORS(GpuVideoDecodeAccelerator); }; diff --git a/content/common/gpu/media/omx_video_decode_accelerator.cc b/content/common/gpu/media/omx_video_decode_accelerator.cc index 28614f2..5d05668 100644 --- a/content/common/gpu/media/omx_video_decode_accelerator.cc +++ b/content/common/gpu/media/omx_video_decode_accelerator.cc @@ -57,10 +57,10 @@ static bool AreOMXFunctionPointersInitialized() { } while (0) // OMX-specific version of RETURN_ON_FAILURE which compares with OMX_ErrorNone. -#define RETURN_ON_OMX_FAILURE(omx_result, log, error, ret_val) \ - RETURN_ON_FAILURE( \ - ((omx_result) == OMX_ErrorNone), \ - log << ", OMX result: " << std::hex << std::showbase << omx_result, \ +#define RETURN_ON_OMX_FAILURE(omx_result, log, error, ret_val) \ + RETURN_ON_FAILURE( \ + ((omx_result) == OMX_ErrorNone), \ + log << ", OMX result: 0x" << std::hex << omx_result, \ error, ret_val) OmxVideoDecodeAccelerator::OmxVideoDecodeAccelerator( @@ -182,6 +182,7 @@ bool OmxVideoDecodeAccelerator::CreateComponent() { VIDEODECODERERROR_UNSUPPORTED, false); // Get the handle to the component. + AddRef(); // To reflect passing |this| to OMX_GetHandle below. result = omx_gethandle( &component_handle_, reinterpret_cast<OMX_STRING>(component.get()), this, &omx_accelerator_callbacks); @@ -265,7 +266,7 @@ bool OmxVideoDecodeAccelerator::CreateComponent() { OMX_BUFFERHEADERTYPE* buffer; result = OMX_UseBuffer(component_handle_, &buffer, output_port_, NULL, 0, reinterpret_cast<OMX_U8*>(0x1)); - RETURN_ON_OMX_FAILURE(result, "OMX_UseBuffer failed with: " << result, + RETURN_ON_OMX_FAILURE(result, "OMX_UseBuffer failed", VIDEODECODERERROR_INVALIDINPUT, false); buffer->pAppPrivate = NULL; buffer->nTimeStamp = -1; @@ -284,7 +285,7 @@ void OmxVideoDecodeAccelerator::Decode( RETURN_ON_FAILURE(current_state_change_ == NO_TRANSITION && (client_state_ == OMX_StateIdle || client_state_ == OMX_StateExecuting), - "Call to Decode() during invalid state or transition:" + "Call to Decode() during invalid state or transition: " << current_state_change_ << ", " << client_state_, VIDEODECODERERROR_UNSUPPORTED,); @@ -315,8 +316,7 @@ void OmxVideoDecodeAccelerator::Decode( // Give this buffer to OMX. OMX_ERRORTYPE result = OMX_EmptyThisBuffer(component_handle_, omx_buffer); - RETURN_ON_OMX_FAILURE(result, - "OMX_EmptyThisBuffer() failed with result " << result, + RETURN_ON_OMX_FAILURE(result, "OMX_EmptyThisBuffer() failed", VIDEODECODERERROR_INVALIDINPUT,); input_buffers_at_component_++; @@ -365,8 +365,7 @@ void OmxVideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id) { ++output_buffers_at_component_; OMX_ERRORTYPE result = OMX_FillThisBuffer(component_handle_, output_picture.omx_buffer_header); - RETURN_ON_OMX_FAILURE(result, - "OMX_FillThisBuffer() failed with result " << result, + RETURN_ON_OMX_FAILURE(result, "OMX_FillThisBuffer() failed", VIDEODECODERERROR_INVALIDINPUT,); } @@ -384,8 +383,7 @@ void OmxVideoDecodeAccelerator::Flush() { omx_buffer->nFlags |= OMX_BUFFERFLAG_EOS; omx_buffer->nTimeStamp = -2; OMX_ERRORTYPE result = OMX_EmptyThisBuffer(component_handle_, omx_buffer); - RETURN_ON_OMX_FAILURE(result, - "OMX_EmptyThisBuffer() failed with result " << result, + RETURN_ON_OMX_FAILURE(result, "OMX_EmptyThisBuffer() failed", VIDEODECODERERROR_INVALIDINPUT,); input_buffers_at_component_++; } @@ -426,16 +424,33 @@ void OmxVideoDecodeAccelerator::Reset() { void OmxVideoDecodeAccelerator::Destroy() { DCHECK_EQ(message_loop_, MessageLoop::current()); + if (current_state_change_ == ERRORING) + return; DCHECK_EQ(current_state_change_, NO_TRANSITION); + // If we were never initializeed there's no teardown to do. + if (client_state_ == OMX_StateMax) + return; + // If we can already call OMX_FreeHandle, simply do so. + if (client_state_ == OMX_StateInvalid || client_state_ == OMX_StateLoaded) { + ShutdownComponent(); + return; + } DCHECK_EQ(client_state_, OMX_StateExecuting); current_state_change_ = DESTROYING; + client_ = NULL; BeginTransitionToState(OMX_StateIdle); + BusyLoopInDestroying(); } void OmxVideoDecodeAccelerator::BeginTransitionToState( OMX_STATETYPE new_state) { DCHECK_EQ(message_loop_, MessageLoop::current()); DCHECK_NE(current_state_change_, NO_TRANSITION); + DCHECK_NE(current_state_change_, ERRORING); + if (current_state_change_ == NO_TRANSITION || + current_state_change_ == ERRORING) { + return; + } OMX_ERRORTYPE result = OMX_SendCommand( component_handle_, OMX_CommandStateSet, new_state, 0); RETURN_ON_OMX_FAILURE(result, "SendCommand(OMX_CommandStateSet) failed", @@ -461,13 +476,13 @@ void OmxVideoDecodeAccelerator::OnReachedExecutingInInitializing() { it != fake_output_buffers_.end(); ++it) { OMX_BUFFERHEADERTYPE* buffer = *it; OMX_ERRORTYPE result = OMX_FillThisBuffer(component_handle_, buffer); - RETURN_ON_OMX_FAILURE(result, - "OMX_FillThisBuffer() failed with: " << result, + RETURN_ON_OMX_FAILURE(result, "OMX_FillThisBuffer()", VIDEODECODERERROR_INVALIDINPUT,); ++output_buffers_at_component_; } - client_->NotifyInitializeDone(); + if (client_) + client_->NotifyInitializeDone(); } void OmxVideoDecodeAccelerator::OnReachedPauseInFlushing() { @@ -482,7 +497,8 @@ void OmxVideoDecodeAccelerator::OnReachedExecutingInFlushing() { DCHECK(saw_eos_during_flush_); saw_eos_during_flush_ = false; current_state_change_ = NO_TRANSITION; - client_->NotifyFlushDone(); + if (client_) + client_->NotifyFlushDone(); } void OmxVideoDecodeAccelerator::OnReachedPauseInResetting() { @@ -495,7 +511,25 @@ void OmxVideoDecodeAccelerator::OnReachedExecutingInResetting() { DCHECK_EQ(client_state_, OMX_StatePause); client_state_ = OMX_StateExecuting; current_state_change_ = NO_TRANSITION; - client_->NotifyResetDone(); + if (client_) + client_->NotifyResetDone(); +} + +// Alert: HORROR ahead! OMX shutdown is an asynchronous dance but our clients +// enjoy the fire-and-forget nature of a synchronous Destroy() call that +// ensures no further callbacks are made. Since the interface between OMX +// callbacks and this class is a MessageLoop, we need to ensure the loop +// outlives the shutdown dance, even during process shutdown. We do this by +// repeatedly enqueuing a no-op task until shutdown is complete, since +// MessageLoop's shutdown drains pending tasks. +void OmxVideoDecodeAccelerator::BusyLoopInDestroying() { + if (!component_handle_) return; + // Can't use PostDelayedTask here because MessageLoop doesn't drain delayed + // tasks. Instead we sleep for 5ms. Really. + base::PlatformThread::Sleep(5); + message_loop_->PostTask( + FROM_HERE, NewRunnableMethod( + this, &OmxVideoDecodeAccelerator::BusyLoopInDestroying)); } void OmxVideoDecodeAccelerator::OnReachedIdleInDestroying() { @@ -514,15 +548,8 @@ void OmxVideoDecodeAccelerator::OnReachedIdleInDestroying() { FreeInputBuffers(); if (!output_buffers_at_component_) FreeOutputBuffers(); -} -void OmxVideoDecodeAccelerator::ShutdownComponent() { - OMX_ERRORTYPE result = omx_free_handle(component_handle_); - if (result != OMX_ErrorNone) - LOG(ERROR) << "OMX_FreeHandle() error. Error code: " << result; - component_handle_ = NULL; - omx_deinit(); - client_state_ = OMX_StateMax; + BusyLoopInDestroying(); } void OmxVideoDecodeAccelerator::OnReachedLoadedInDestroying() { @@ -530,7 +557,6 @@ void OmxVideoDecodeAccelerator::OnReachedLoadedInDestroying() { client_state_ = OMX_StateLoaded; current_state_change_ = NO_TRANSITION; ShutdownComponent(); - client_->NotifyDestroyDone(); } void OmxVideoDecodeAccelerator::OnReachedInvalidInErroring() { @@ -538,17 +564,31 @@ void OmxVideoDecodeAccelerator::OnReachedInvalidInErroring() { ShutdownComponent(); } +void OmxVideoDecodeAccelerator::ShutdownComponent() { + OMX_ERRORTYPE result = omx_free_handle(component_handle_); + if (result != OMX_ErrorNone) + LOG(ERROR) << "OMX_FreeHandle() error. Error code: " << result; + component_handle_ = NULL; + client_state_ = OMX_StateMax; + // This Release() call must happen *after* any access to |*this| because it + // might result in |this| being deleted. + Release(); // Since OMX no longer has |this| to call back to. + omx_deinit(); +} + void OmxVideoDecodeAccelerator::StopOnError( media::VideoDecodeAccelerator::Error error) { DCHECK_EQ(message_loop_, MessageLoop::current()); - current_state_change_ = ERRORING; - client_->NotifyError(error); + if (client_) + client_->NotifyError(error); + client_ = NULL; if (client_state_ == OMX_StateInvalid || client_state_ == OMX_StateMax) return; BeginTransitionToState(OMX_StateInvalid); + current_state_change_ = ERRORING; } bool OmxVideoDecodeAccelerator::AllocateInputBuffers() { @@ -589,7 +629,7 @@ bool OmxVideoDecodeAccelerator::AllocateOutputBuffers() { OMX_ERRORTYPE result = OMX_UseEGLImage( component_handle_, omx_buffer, output_port_, &gles_buffer, it->second.egl_image); - RETURN_ON_OMX_FAILURE(result, "OMX_UseEGLImage failed with: " << result, + RETURN_ON_OMX_FAILURE(result, "OMX_UseEGLImage", VIDEODECODERERROR_MEMFAILURE, false); // Here we set a garbage bitstream buffer id, and then overwrite it before // passing to PictureReady. @@ -610,10 +650,9 @@ void OmxVideoDecodeAccelerator::FreeInputBuffers() { omx_buffer = free_input_buffers_.front(); free_input_buffers_.pop(); result = OMX_FreeBuffer(component_handle_, input_port_, omx_buffer); - RETURN_ON_OMX_FAILURE(result, "OMX_FreeBuffer failed with: " << result, + RETURN_ON_OMX_FAILURE(result, "OMX_FreeBuffer", VIDEODECODERERROR_INVALIDINPUT,); } - VLOG(1) << "Input buffers freed."; } void OmxVideoDecodeAccelerator::FreeOutputBuffers() { @@ -627,11 +666,12 @@ void OmxVideoDecodeAccelerator::FreeOutputBuffers() { CHECK(omx_buffer); delete reinterpret_cast<media::Picture*>(omx_buffer->pAppPrivate); result = OMX_FreeBuffer(component_handle_, output_port_, omx_buffer); - RETURN_ON_OMX_FAILURE(result, "OMX_FreeBuffer failed with: " << result, + RETURN_ON_OMX_FAILURE(result, "OMX_FreeBuffer", VIDEODECODERERROR_INVALIDINPUT,); texture2eglImage_translator.DestroyEglImage(egl_display_, it->second.egl_image); - client_->DismissPictureBuffer(it->first); + if (client_) + client_->DismissPictureBuffer(it->first); } pictures_.clear(); } @@ -643,7 +683,7 @@ void OmxVideoDecodeAccelerator::OnOutputPortDisabled() { port_format.nPortIndex = output_port_; OMX_ERRORTYPE result = OMX_GetParameter( component_handle_, OMX_IndexParamPortDefinition, &port_format); - RETURN_ON_OMX_FAILURE(result, "OMX_GetParameter failed with: " << result, + RETURN_ON_OMX_FAILURE(result, "OMX_GetParameter", VIDEODECODERERROR_UNSUPPORTED,); DCHECK_EQ(port_format.nBufferCountMin, kNumPictureBuffers); @@ -655,10 +695,12 @@ void OmxVideoDecodeAccelerator::OnOutputPortDisabled() { // ProvidePictureBuffers() will trigger AssignGLESBuffers, which ultimately // assigns the textures to the component and re-enables the port. const OMX_VIDEO_PORTDEFINITIONTYPE& vformat = port_format.format.video; - client_->ProvidePictureBuffers( - kNumPictureBuffers, - gfx::Size(vformat.nFrameWidth, vformat.nFrameHeight), - PICTUREBUFFER_MEMORYTYPE_GL_TEXTURE); + if (client_) { + client_->ProvidePictureBuffers( + kNumPictureBuffers, + gfx::Size(vformat.nFrameWidth, vformat.nFrameHeight), + PICTUREBUFFER_MEMORYTYPE_GL_TEXTURE); + } } void OmxVideoDecodeAccelerator::OnOutputPortEnabled() { @@ -679,8 +721,7 @@ void OmxVideoDecodeAccelerator::OnOutputPortEnabled() { omx_buffer->nOutputPortIndex = output_port_; ++output_buffers_at_component_; OMX_ERRORTYPE result = OMX_FillThisBuffer(component_handle_, omx_buffer); - RETURN_ON_OMX_FAILURE(result, - "OMX_FillThisBuffer() failed with result " << result, + RETURN_ON_OMX_FAILURE(result, "OMX_FillThisBuffer() failed", VIDEODECODERERROR_INSUFFICIENT_BUFFERS,); } } @@ -695,7 +736,7 @@ void OmxVideoDecodeAccelerator::FillBufferDoneTask( CHECK_EQ(fake_output_buffers_.erase(buffer), 1U); OMX_ERRORTYPE result = OMX_FreeBuffer(component_handle_, output_port_, buffer); - RETURN_ON_OMX_FAILURE(result, "OMX_FreeBuffer failed with: " << result, + RETURN_ON_OMX_FAILURE(result, "OMX_FreeBuffer failed", VIDEODECODERERROR_INVALIDINPUT,); return; } @@ -721,7 +762,8 @@ void OmxVideoDecodeAccelerator::FillBufferDoneTask( reinterpret_cast<media::Picture*>(buffer->pAppPrivate); // See Decode() for an explanation of this abuse of nTimeStamp. picture->set_bitstream_buffer_id(buffer->nTimeStamp); - client_->PictureReady(*picture); + if (client_) + client_->PictureReady(*picture); } void OmxVideoDecodeAccelerator::EmptyBufferDoneTask( @@ -739,7 +781,8 @@ void OmxVideoDecodeAccelerator::EmptyBufferDoneTask( reinterpret_cast<SharedMemoryAndId*>(buffer->pAppPrivate); DCHECK(input_buffer_details); buffer->pAppPrivate = NULL; - client_->NotifyEndOfBitstreamBuffer(input_buffer_details->second); + if (client_) + client_->NotifyEndOfBitstreamBuffer(input_buffer_details->second); delete input_buffer_details; } @@ -790,6 +833,14 @@ void OmxVideoDecodeAccelerator::DispatchStateReached(OMX_STATETYPE reached) { default: NOTREACHED() << "Unexpected state in DESTROYING: " << reached; } + case ERRORING: + switch (reached) { + case OMX_StateInvalid: + OnReachedInvalidInErroring(); + return; + default: + NOTREACHED() << "Unexpected state in ERRORING: " << reached; + } default: NOTREACHED() << "Unexpected state in " << current_state_change_ << ": " << reached; @@ -801,23 +852,19 @@ void OmxVideoDecodeAccelerator::EventHandlerCompleteTask(OMX_EVENTTYPE event, OMX_U32 data2) { DCHECK_EQ(message_loop_, MessageLoop::current()); switch (event) { - case OMX_EventCmdComplete: { - // If the last command was successful, we have completed - // a state transition. So notify that we have done it - // accordingly. - OMX_COMMANDTYPE cmd = static_cast<OMX_COMMANDTYPE>(data1); - switch (cmd) { + case OMX_EventCmdComplete: + switch (data1) { case OMX_CommandPortDisable: DCHECK_EQ(data2, output_port_); OnOutputPortDisabled(); - break; + return; case OMX_CommandPortEnable: DCHECK_EQ(data2, output_port_); OnOutputPortEnabled(); - break; + return; case OMX_CommandStateSet: DispatchStateReached(static_cast<OMX_STATETYPE>(data2)); - break; + return; case OMX_CommandFlush: DCHECK(current_state_change_ == FLUSHING || current_state_change_ == RESETTING || @@ -828,16 +875,19 @@ void OmxVideoDecodeAccelerator::EventHandlerCompleteTask(OMX_EVENTTYPE event, OutputPortFlushDone(); else NOTREACHED() << "Unexpected port flushed: " << data2; - break; + return; default: RETURN_ON_FAILURE(false, "Unknown command completed: " << data1, VIDEODECODERERROR_HARDWARE,); } - break; - } + return; case OMX_EventError: - RETURN_ON_FAILURE(false, "EventError: " << data1, - VIDEODECODERERROR_HARDWARE,); + if (current_state_change_ != DESTROYING && + current_state_change_ != ERRORING) { + RETURN_ON_FAILURE(false, "EventError: 0x" << std::hex << data1, + VIDEODECODERERROR_HARDWARE,); + } + return; case OMX_EventPortSettingsChanged: if (data2 == OMX_IndexParamPortDefinition) { DCHECK_EQ(data1, output_port_); @@ -853,7 +903,7 @@ void OmxVideoDecodeAccelerator::EventHandlerCompleteTask(OMX_EVENTTYPE event, << data1 << ", " << data2, VIDEODECODERERROR_HARDWARE,); } - break; + return; case OMX_EventBufferFlag: if (data1 == output_port_) { DCHECK_EQ(current_state_change_, FLUSHING); @@ -864,7 +914,7 @@ void OmxVideoDecodeAccelerator::EventHandlerCompleteTask(OMX_EVENTTYPE event, << data1 << ", " << data2, VIDEODECODERERROR_HARDWARE,); } - break; + return; default: RETURN_ON_FAILURE(false, "Unexpected unhandled event: " << event, VIDEODECODERERROR_HARDWARE,); @@ -883,10 +933,9 @@ OMX_ERRORTYPE OmxVideoDecodeAccelerator::EventHandler(OMX_HANDLETYPE component, static_cast<OmxVideoDecodeAccelerator*>(priv_data); DCHECK_EQ(component, decoder->component_handle_); decoder->message_loop_->PostTask( - FROM_HERE, - NewRunnableMethod(decoder, - &OmxVideoDecodeAccelerator::EventHandlerCompleteTask, - event, data1, data2)); + FROM_HERE, NewRunnableMethod( + decoder, &OmxVideoDecodeAccelerator::EventHandlerCompleteTask, + event, data1, data2)); return OMX_ErrorNone; } @@ -926,6 +975,10 @@ OMX_ERRORTYPE OmxVideoDecodeAccelerator::FillBufferCallback( bool OmxVideoDecodeAccelerator::CanFillBuffer() { DCHECK_EQ(message_loop_, MessageLoop::current()); + if (current_state_change_ == DESTROYING || + current_state_change_ == ERRORING) { + return false; + } return client_state_ == OMX_StateIdle || client_state_ == OMX_StateExecuting || client_state_ == OMX_StatePause; @@ -936,9 +989,7 @@ bool OmxVideoDecodeAccelerator::SendCommandToPort( DCHECK_EQ(message_loop_, MessageLoop::current()); OMX_ERRORTYPE result = OMX_SendCommand(component_handle_, cmd, port_index, 0); - RETURN_ON_OMX_FAILURE(result, "SendCommand() failed" << cmd << ":" << result, + RETURN_ON_OMX_FAILURE(result, "SendCommand() failed" << cmd, VIDEODECODERERROR_INVALIDINPUT, false); return true; } - -DISABLE_RUNNABLE_METHOD_REFCOUNT(OmxVideoDecodeAccelerator); diff --git a/content/common/gpu/media/omx_video_decode_accelerator.h b/content/common/gpu/media/omx_video_decode_accelerator.h index 4c246d0..edced28 100644 --- a/content/common/gpu/media/omx_video_decode_accelerator.h +++ b/content/common/gpu/media/omx_video_decode_accelerator.h @@ -15,7 +15,9 @@ #include "base/bind.h" #include "base/callback.h" +#include "base/compiler_specific.h" #include "base/logging.h" +#include "base/memory/ref_counted.h" #include "base/message_loop.h" #include "base/shared_memory.h" #include "media/video/video_decode_accelerator.h" @@ -31,12 +33,13 @@ // // This class lives on a single thread and DCHECKs that it is never accessed // from any other. OMX callbacks are trampolined from the OMX component's -// thread to maintain this invariant. +// thread to maintain this invariant. The only exception to thread-unsafety is +// that references can be added from any thread (practically used only by the +// OMX thread). class OmxVideoDecodeAccelerator : public media::VideoDecodeAccelerator { public: // Does not take ownership of |client| which must outlive |*this|. OmxVideoDecodeAccelerator(media::VideoDecodeAccelerator::Client* client); - virtual ~OmxVideoDecodeAccelerator(); // media::VideoDecodeAccelerator implementation. bool Initialize(const std::vector<uint32>& config) OVERRIDE; @@ -51,6 +54,8 @@ class OmxVideoDecodeAccelerator : public media::VideoDecodeAccelerator { void SetEglState(EGLDisplay egl_display, EGLContext egl_context); private: + virtual ~OmxVideoDecodeAccelerator(); + // Because OMX state-transitions are described solely by the "state reached" // (3.1.2.9.1, table 3-7 of the spec), we track what transition was requested // using this enum. Note that it is an error to request a transition while @@ -84,7 +89,6 @@ class OmxVideoDecodeAccelerator : public media::VideoDecodeAccelerator { // Create the Component for OMX. Handles all OMX initialization. bool CreateComponent(); - void ShutdownComponent(); // Buffer allocation/free methods for input and output buffers. bool AllocateInputBuffers(); bool AllocateOutputBuffers(); @@ -110,6 +114,8 @@ class OmxVideoDecodeAccelerator : public media::VideoDecodeAccelerator { void OnReachedLoadedInDestroying(); void OnReachedEOSInFlushing(); void OnReachedInvalidInErroring(); + void ShutdownComponent(); + void BusyLoopInDestroying(); // Port-flushing helpers. void FlushIOPorts(); diff --git a/content/common/gpu/media/omx_video_decode_accelerator_unittest.cc b/content/common/gpu/media/omx_video_decode_accelerator_unittest.cc index 6a6d35c..b08d0ae2 100644 --- a/content/common/gpu/media/omx_video_decode_accelerator_unittest.cc +++ b/content/common/gpu/media/omx_video_decode_accelerator_unittest.cc @@ -200,9 +200,9 @@ void RenderingHelper::Initialize( // Per-window/surface X11 & EGL initialization. for (int i = 0; i < num_windows; ++i) { - // Arrange X windows side by side whimsically. - int top_left_x = (width + 50) * i; - int top_left_y = 100 + (i % 2) * 250; + // Arrange X windows whimsically, with some padding. + int top_left_x = (width + 20) * (i % 4); + int top_left_y = (height + 12) * (i % 3); Window x_window = XCreateWindow( x_display_, DefaultRootWindow(x_display_), top_left_x, top_left_y, width_, height_, @@ -421,7 +421,6 @@ class EglRenderingVDAClient : public VideoDecodeAccelerator::Client { virtual void NotifyEndOfBitstreamBuffer(int32 bitstream_buffer_id); virtual void NotifyFlushDone(); virtual void NotifyResetDone(); - virtual void NotifyDestroyDone(); virtual void NotifyError(VideoDecodeAccelerator::Error error); // Simple getters for inspecting the state of the Client. @@ -432,7 +431,7 @@ class EglRenderingVDAClient : public VideoDecodeAccelerator::Client { EGLDisplay egl_display() { return rendering_helper_->egl_display(); } EGLContext egl_context() { return rendering_helper_->egl_context(); } double frames_per_second(); - bool decoder_deleted() { return !decoder_.get(); } + bool decoder_deleted() { return !decoder_; } private: typedef std::map<int, media::GLESBuffer*> PictureBufferById; @@ -456,7 +455,7 @@ class EglRenderingVDAClient : public VideoDecodeAccelerator::Client { size_t encoded_data_next_pos_to_decode_; int next_bitstream_buffer_id_; ClientStateNotification* note_; - scoped_ptr<OmxVideoDecodeAccelerator> decoder_; + scoped_refptr<OmxVideoDecodeAccelerator> decoder_; int delete_decoder_state_; ClientState state_; VideoDecodeAccelerator::Error error_; @@ -485,17 +484,18 @@ EglRenderingVDAClient::EglRenderingVDAClient(RenderingHelper* rendering_helper, } EglRenderingVDAClient::~EglRenderingVDAClient() { - CHECK(!decoder_.get()); + DeleteDecoder(); // Clean up in case of expected error. + CHECK(decoder_deleted()); STLDeleteValues(&picture_buffers_by_id_); SetState(CS_DESTROYED); } void EglRenderingVDAClient::CreateDecoder() { - CHECK(!decoder_.get()); - decoder_.reset(new OmxVideoDecodeAccelerator(this)); + CHECK(decoder_deleted()); + decoder_ = new OmxVideoDecodeAccelerator(this); decoder_->SetEglState(egl_display(), egl_context()); SetState(CS_DECODER_SET); - if (!decoder_.get()) + if (decoder_deleted()) return; // Configure the decoder. @@ -514,7 +514,7 @@ void EglRenderingVDAClient::ProvidePictureBuffers( uint32 requested_num_of_buffers, const gfx::Size& dimensions, VideoDecodeAccelerator::MemoryType type) { - if (!decoder_.get()) + if (decoder_deleted()) return; CHECK_EQ(type, VideoDecodeAccelerator::PICTUREBUFFER_MEMORYTYPE_GL_TEXTURE); std::vector<media::GLESBuffer> buffers; @@ -550,7 +550,7 @@ void EglRenderingVDAClient::PictureReady(const media::Picture& picture) { // We shouldn't be getting pictures delivered after Reset has completed. DCHECK_LT(state_, CS_RESET); - if (!decoder_.get()) + if (decoder_deleted()) return; last_frame_delivered_ticks_ = base::TimeTicks::Now(); @@ -587,25 +587,20 @@ void EglRenderingVDAClient::NotifyEndOfBitstreamBuffer( } void EglRenderingVDAClient::NotifyFlushDone() { - if (!decoder_.get()) + if (decoder_deleted()) return; SetState(CS_FLUSHED); - if (!decoder_.get()) + if (decoder_deleted()) return; decoder_->Reset(); } void EglRenderingVDAClient::NotifyResetDone() { - if (!decoder_.get()) + if (decoder_deleted()) return; SetState(CS_RESET); - if (!decoder_.get()) - return; - decoder_->Destroy(); -} - -void EglRenderingVDAClient::NotifyDestroyDone() { - SetState(CS_DESTROYED); + if (!decoder_deleted()) + DeleteDecoder(); } void EglRenderingVDAClient::NotifyError(VideoDecodeAccelerator::Error error) { @@ -622,12 +617,17 @@ static bool LookingAtNAL(const std::string& encoded, size_t pos) { void EglRenderingVDAClient::SetState(ClientState new_state) { note_->Notify(new_state); state_ = new_state; - if (new_state == delete_decoder_state_) + if (new_state == delete_decoder_state_) { + CHECK(!decoder_deleted()); DeleteDecoder(); + } } void EglRenderingVDAClient::DeleteDecoder() { - decoder_.reset(); + if (decoder_deleted()) + return; + decoder_->Destroy(); + decoder_ = NULL; // Cascade through the rest of the states to simplify test code below. for (int i = state_ + 1; i < CS_MAX; ++i) SetState(static_cast<ClientState>(i)); @@ -651,7 +651,7 @@ void EglRenderingVDAClient::GetRangeForNextNALUs( } void EglRenderingVDAClient::DecodeNextNALUs() { - if (!decoder_.get()) + if (decoder_deleted()) return; if (encoded_data_next_pos_to_decode_ == encoded_data_->size()) { decoder_->Flush(); @@ -680,7 +680,8 @@ void EglRenderingVDAClient::DecodeNextNALUs() { double EglRenderingVDAClient::frames_per_second() { base::TimeDelta delta = last_frame_delivered_ticks_ - initialize_done_ticks_; - CHECK_GT(delta.InSecondsF(), 0); + if (delta.InSecondsF() == 0) + return 0; return num_decoded_frames_ / delta.InSecondsF(); } @@ -705,6 +706,10 @@ static void AssertWaitForStateOrDeleted(ClientStateNotification* note, << ", instead of " << expected_state; } +// We assert the exact number of concurrent decoders we expect to succeed and +// that one more than that fails initialization. +enum { kMaxSupportedNumConcurrentDecoders = 5 }; + // Test the most straightforward case possible: data is decoded from a single // chunk and rendered to the screen. TEST_P(OmxVideoDecodeAcceleratorTest, TestSimpleDecode) { @@ -763,9 +768,19 @@ TEST_P(OmxVideoDecodeAcceleratorTest, TestSimpleDecode) { ASSERT_EQ(note->Wait(), CS_DECODER_SET); } // Then wait for all the decodes to finish. + bool saw_init_failure = false; for (size_t i = 0; i < num_concurrent_decoders; ++i) { ClientStateNotification* note = notes[i]; - ASSERT_EQ(note->Wait(), CS_INITIALIZED); + ClientState state = note->Wait(); + if (state != CS_INITIALIZED) { + saw_init_failure = true; + // We expect initialization to fail only when more than the supported + // number of decoders is instantiated. Assert here that something else + // didn't trigger failure. + ASSERT_GT(num_concurrent_decoders, kMaxSupportedNumConcurrentDecoders); + continue; + } + ASSERT_EQ(state, CS_INITIALIZED); // InitializeDone kicks off decoding inside the client, so we just need to // wait for Flush. ASSERT_NO_FATAL_FAILURE( @@ -777,8 +792,11 @@ TEST_P(OmxVideoDecodeAcceleratorTest, TestSimpleDecode) { ASSERT_NO_FATAL_FAILURE( AssertWaitForStateOrDeleted(note, clients[i], CS_DESTROYED)); } + ASSERT_EQ(saw_init_failure, + num_concurrent_decoders > kMaxSupportedNumConcurrentDecoders) + << num_concurrent_decoders; // Finally assert that decoding went as expected. - for (size_t i = 0; i < num_concurrent_decoders; ++i) { + for (size_t i = 0; i < num_concurrent_decoders && !saw_init_failure; ++i) { // We can only make performance/correctness assertions if the decoder was // allowed to finish. if (delete_decoder_state < CS_FLUSHED) @@ -813,10 +831,8 @@ TEST_P(OmxVideoDecodeAcceleratorTest, TestSimpleDecode) { rendering_thread.Stop(); }; -// TODO(fischman): Remove DISABLED_ prefix when ~OVDA can tear down OMX -// synchronously (http://crosbug.com/p/4869). INSTANTIATE_TEST_CASE_P( - DISABLED_TearDownTiming, OmxVideoDecodeAcceleratorTest, + TearDownTiming, OmxVideoDecodeAcceleratorTest, ::testing::Values( MakeTuple(1, 1, CS_DECODER_SET), MakeTuple(1, 1, CS_INITIALIZED), MakeTuple(1, 1, CS_FLUSHED), MakeTuple(1, 1, CS_RESET), @@ -824,7 +840,7 @@ INSTANTIATE_TEST_CASE_P( MakeTuple(1, 1, static_cast<ClientState>(-10)), MakeTuple(1, 1, static_cast<ClientState>(-100)))); -// TODO(fischman): using 2nd param of 16 and higher below breaks decode - visual +// TODO(fischman): using 1st param of 16 and higher below breaks decode - visual // artifacts are introduced as well as spurious frames are delivered (more // pictures are returned than NALUs are fed to the decoder). Increase the "15" // below when http://code.google.com/p/chrome-os-partner/issues/detail?id=4378 @@ -832,10 +848,19 @@ INSTANTIATE_TEST_CASE_P( INSTANTIATE_TEST_CASE_P( DecodeVariations, OmxVideoDecodeAcceleratorTest, ::testing::Values( - MakeTuple(1, 1, CS_DESTROYED), MakeTuple(1, 3, CS_DESTROYED), - MakeTuple(2, 1, CS_DESTROYED), MakeTuple(3, 1, CS_DESTROYED), - MakeTuple(5, 1, CS_DESTROYED), MakeTuple(8, 1, CS_DESTROYED), - MakeTuple(15, 1, CS_DESTROYED))); + MakeTuple(1, 1, CS_RESET), MakeTuple(1, 3, CS_RESET), + MakeTuple(2, 1, CS_RESET), MakeTuple(3, 1, CS_RESET), + MakeTuple(5, 1, CS_RESET), MakeTuple(8, 1, CS_RESET), + MakeTuple(15, 1, CS_RESET))); + +// Find out how many concurrent decoders can go before we exhaust system +// resources. +INSTANTIATE_TEST_CASE_P( + ResourceExhaustion, OmxVideoDecodeAcceleratorTest, + ::testing::Values( + // +0 hack below to promote enum to int. + MakeTuple(1, kMaxSupportedNumConcurrentDecoders + 0, CS_RESET), + MakeTuple(1, kMaxSupportedNumConcurrentDecoders + 1, CS_RESET))); // TODO(fischman, vrk): add more tests! In particular: // - Test life-cycle: Seek/Stop/Pause/Play/RePlay for a single decoder. diff --git a/content/renderer/gpu/command_buffer_proxy.cc b/content/renderer/gpu/command_buffer_proxy.cc index 42949b6..f9fe8d5 100644 --- a/content/renderer/gpu/command_buffer_proxy.cc +++ b/content/renderer/gpu/command_buffer_proxy.cc @@ -50,7 +50,7 @@ bool CommandBufferProxy::OnMessageReceived(const IPC::Message& message) { IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() - if (!handled && video_decoder_host_.get()) + if (!handled && video_decoder_host_) handled = video_decoder_host_->OnMessageReceived(message); DCHECK(handled); @@ -386,19 +386,20 @@ void CommandBufferProxy::SetNotifyRepaintTask(Task* task) { notify_repaint_task_.reset(task); } -GpuVideoDecodeAcceleratorHost* CommandBufferProxy::CreateVideoDecoder( +scoped_refptr<GpuVideoDecodeAcceleratorHost> +CommandBufferProxy::CreateVideoDecoder( const std::vector<uint32>& configs, gpu::CommandBufferHelper* cmd_buffer_helper, media::VideoDecodeAccelerator::Client* client) { - video_decoder_host_.reset(new GpuVideoDecodeAcceleratorHost( - channel_, route_id_, cmd_buffer_helper, client)); + video_decoder_host_ = new GpuVideoDecodeAcceleratorHost( + channel_, route_id_, cmd_buffer_helper, client); if (!Send(new GpuCommandBufferMsg_CreateVideoDecoder(route_id_, configs))) { LOG(ERROR) << "Send(GpuChannelMsg_CreateVideoDecoder) failed"; - video_decoder_host_.reset(); + video_decoder_host_ = NULL; } - return video_decoder_host_.get(); + return video_decoder_host_; } #if defined(OS_MACOSX) diff --git a/content/renderer/gpu/command_buffer_proxy.h b/content/renderer/gpu/command_buffer_proxy.h index 9879169..aba15c9 100644 --- a/content/renderer/gpu/command_buffer_proxy.h +++ b/content/renderer/gpu/command_buffer_proxy.h @@ -83,14 +83,12 @@ class CommandBufferProxy : public gpu::CommandBuffer, void SetNotifyRepaintTask(Task* task); // Sends an IPC message to create a GpuVideoDecodeAccelerator. Creates and - // returns a pointer to a GpuVideoDecodeAcceleratorHost. CommandBufferProxy - // owns the GpuVideoDecodeAcceleratorHost and does not transfer ownership to - // the caller of this method. + // returns a pointer to a GpuVideoDecodeAcceleratorHost. // Returns NULL on failure to create the GpuVideoDecodeAcceleratorHost. // Note that the GpuVideoDecodeAccelerator may still fail to be created in // the GPU process, even if this returns non-NULL. In this case the client is // notified of an error later. - GpuVideoDecodeAcceleratorHost* CreateVideoDecoder( + scoped_refptr<GpuVideoDecodeAcceleratorHost> CreateVideoDecoder( const std::vector<uint32>& configs, gpu::CommandBufferHelper* cmd_buffer_helper, media::VideoDecodeAccelerator::Client* client); @@ -126,7 +124,7 @@ class CommandBufferProxy : public gpu::CommandBuffer, // The video decoder host corresponding to the stub's video decoder in the GPU // process, if one exists. - scoped_ptr<GpuVideoDecodeAcceleratorHost> video_decoder_host_; + scoped_refptr<GpuVideoDecodeAcceleratorHost> video_decoder_host_; // The last cached state received from the service. State last_state_; diff --git a/content/renderer/gpu/gpu_video_decode_accelerator_host.cc b/content/renderer/gpu/gpu_video_decode_accelerator_host.cc index 7c2576b..91d88a1 100644 --- a/content/renderer/gpu/gpu_video_decode_accelerator_host.cc +++ b/content/renderer/gpu/gpu_video_decode_accelerator_host.cc @@ -59,8 +59,6 @@ bool GpuVideoDecodeAcceleratorHost::OnMessageReceived(const IPC::Message& msg) { OnFlushDone) IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_ResetDone, OnResetDone) - IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_DestroyDone, - OnDestroyDone) IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_EndOfStream, OnEndOfStream) IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_ErrorNotification, @@ -137,12 +135,8 @@ void GpuVideoDecodeAcceleratorHost::Flush() { void GpuVideoDecodeAcceleratorHost::Reset() { DCHECK(CalledOnValidThread()); - if (!ipc_sender_->Send(new AcceleratedVideoDecoderMsg_Reset( - command_buffer_route_id_, SyncTokens()))) { - LOG(ERROR) << "Send(AcceleratedVideoDecoderMsg_Reset) failed"; - // TODO(fischman/vrk): signal error to client. - return; - } + Send(new AcceleratedVideoDecoderMsg_Reset( + command_buffer_route_id_, SyncTokens())); } void GpuVideoDecodeAcceleratorHost::Destroy() { @@ -209,11 +203,6 @@ void GpuVideoDecodeAcceleratorHost::OnResetDone() { client_->NotifyResetDone(); } -void GpuVideoDecodeAcceleratorHost::OnDestroyDone() { - DCHECK(CalledOnValidThread()); - client_->NotifyDestroyDone(); -} - void GpuVideoDecodeAcceleratorHost::OnEndOfStream() { DCHECK(CalledOnValidThread()); client_->NotifyEndOfStream(); diff --git a/content/renderer/gpu/gpu_video_decode_accelerator_host.h b/content/renderer/gpu/gpu_video_decode_accelerator_host.h index 9c304ce..98dc30b 100644 --- a/content/renderer/gpu/gpu_video_decode_accelerator_host.h +++ b/content/renderer/gpu/gpu_video_decode_accelerator_host.h @@ -67,7 +67,6 @@ class GpuVideoDecodeAcceleratorHost const gfx::Size& decoded_size); void OnFlushDone(); void OnResetDone(); - void OnDestroyDone(); void OnEndOfStream(); void OnErrorNotification(uint32 error); diff --git a/content/renderer/gpu/gpu_video_service_host.cc b/content/renderer/gpu/gpu_video_service_host.cc deleted file mode 100644 index cb43332..0000000 --- a/content/renderer/gpu/gpu_video_service_host.cc +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/gpu/gpu_video_service_host.h" - -#include "content/common/gpu/gpu_messages.h" -#include "content/renderer/gpu/gpu_video_decode_accelerator_host.h" -#include "content/renderer/render_thread.h" -#include "media/video/video_decode_accelerator.h" - -GpuVideoServiceHost::GpuVideoServiceHost() - : channel_(NULL), - next_decoder_host_id_(0) { - DCHECK(RenderThread::current()); - DCHECK_EQ(RenderThread::current()->message_loop(), MessageLoop::current()); -} - -GpuVideoServiceHost::~GpuVideoServiceHost() { -} - -void GpuVideoServiceHost::set_channel(IPC::SyncChannel* channel) { - DCHECK(CalledOnValidThread()); - DCHECK(!channel_); - channel_ = channel; - if (!on_initialized_.is_null()) - on_initialized_.Run(); -} - -bool GpuVideoServiceHost::OnMessageReceived(const IPC::Message& msg) { - DCHECK(CalledOnValidThread()); - if (!channel_) - return false; - switch (msg.type()) { - case AcceleratedVideoDecoderHostMsg_BitstreamBufferProcessed::ID: - case AcceleratedVideoDecoderHostMsg_ProvidePictureBuffers::ID: - case AcceleratedVideoDecoderHostMsg_InitializeDone::ID: - case AcceleratedVideoDecoderHostMsg_DismissPictureBuffer::ID: - case AcceleratedVideoDecoderHostMsg_PictureReady::ID: - case AcceleratedVideoDecoderHostMsg_FlushDone::ID: - case AcceleratedVideoDecoderHostMsg_ResetDone::ID: - case AcceleratedVideoDecoderHostMsg_DestroyDone::ID: - case AcceleratedVideoDecoderHostMsg_EndOfStream::ID: - case AcceleratedVideoDecoderHostMsg_ErrorNotification::ID: - if (router_.RouteMessage(msg)) - return true; - LOG(ERROR) << "AcceleratedVideoDecoderHostMsg cannot be dispatched."; - default: - return false; - } -} - -void GpuVideoServiceHost::OnChannelError() { - DCHECK(CalledOnValidThread()); - channel_ = NULL; -} - -void GpuVideoServiceHost::SetOnInitialized( - const base::Closure& on_initialized) { - DCHECK(CalledOnValidThread()); - DCHECK(on_initialized_.is_null()); - on_initialized_ = on_initialized; - if (channel_) - on_initialized.Run(); -} - -GpuVideoDecodeAcceleratorHost* GpuVideoServiceHost::CreateVideoAccelerator( - media::VideoDecodeAccelerator::Client* client, - int32 command_buffer_route_id, - gpu::CommandBufferHelper* cmd_buffer_helper) { - DCHECK(CalledOnValidThread()); - DCHECK(channel_); - return new GpuVideoDecodeAcceleratorHost( - &router_, channel_, next_decoder_host_id_++, - command_buffer_route_id, cmd_buffer_helper, client); -} diff --git a/content/renderer/pepper_platform_video_decoder_impl.cc b/content/renderer/pepper_platform_video_decoder_impl.cc index 9c8b247..ac34a3b 100644 --- a/content/renderer/pepper_platform_video_decoder_impl.cc +++ b/content/renderer/pepper_platform_video_decoder_impl.cc @@ -20,8 +20,7 @@ PlatformVideoDecoderImpl::PlatformVideoDecoderImpl( gpu::CommandBufferHelper* cmd_buffer_helper) : client_(client), command_buffer_route_id_(command_buffer_route_id), - cmd_buffer_helper_(cmd_buffer_helper), - decoder_(NULL) { + cmd_buffer_helper_(cmd_buffer_helper) { DCHECK(client); } @@ -133,8 +132,3 @@ void PlatformVideoDecoderImpl::NotifyResetDone() { DCHECK_EQ(RenderThread::current()->message_loop(), MessageLoop::current()); client_->NotifyResetDone(); } - -void PlatformVideoDecoderImpl::NotifyDestroyDone() { - DCHECK_EQ(RenderThread::current()->message_loop(), MessageLoop::current()); - client_->NotifyDestroyDone(); -} diff --git a/content/renderer/pepper_platform_video_decoder_impl.h b/content/renderer/pepper_platform_video_decoder_impl.h index b4d0d03..32b0080 100644 --- a/content/renderer/pepper_platform_video_decoder_impl.h +++ b/content/renderer/pepper_platform_video_decoder_impl.h @@ -25,9 +25,8 @@ class PlatformVideoDecoderImpl media::VideoDecodeAccelerator::Client* client, int32 command_buffer_route_id, gpu::CommandBufferHelper* cmd_buffer_helper); - virtual ~PlatformVideoDecoderImpl(); - // PlatformVideoDecoder implementation. + // PlatformVideoDecoder (a.k.a. VideoDecodeAccelerator) implementation. virtual bool Initialize(const std::vector<uint32>& configs) OVERRIDE; virtual void Decode( const media::BitstreamBuffer& bitstream_buffer) OVERRIDE; @@ -52,9 +51,10 @@ class PlatformVideoDecoderImpl virtual void NotifyEndOfBitstreamBuffer(int32 bitstream_buffer_id) OVERRIDE; virtual void NotifyFlushDone() OVERRIDE; virtual void NotifyResetDone() OVERRIDE; - virtual void NotifyDestroyDone() OVERRIDE; private: + virtual ~PlatformVideoDecoderImpl(); + // Client lifetime must exceed lifetime of this class. // TODO(vrk/fischman): We should take another look at the overall // arcitecture of PPAPI Video Decode to make sure lifetime/ownership makes @@ -67,10 +67,8 @@ class PlatformVideoDecoderImpl // Helper for the command buffer associated with video decoder's context. gpu::CommandBufferHelper* cmd_buffer_helper_; - // Host for GpuVideoDecodeAccelerator. - // This is owned by the CommandBufferProxy associated with - // |command_buffer_route_id|. - media::VideoDecodeAccelerator* decoder_; + // Holds a GpuVideoDecodeAcceleratorHost. + scoped_refptr<media::VideoDecodeAccelerator> decoder_; DISALLOW_COPY_AND_ASSIGN(PlatformVideoDecoderImpl); }; |