Chromium Code Reviews| Index: content/common/gpu/client/gpu_video_encode_accelerator_host.cc |
| diff --git a/content/common/gpu/client/gpu_video_encode_accelerator_host.cc b/content/common/gpu/client/gpu_video_encode_accelerator_host.cc |
| index 14d330e960fb223ca43b4920d240f8559796fc5d..44859f57d049bf2e8ec48b34cb150b89c9ae2e44 100644 |
| --- a/content/common/gpu/client/gpu_video_encode_accelerator_host.cc |
| +++ b/content/common/gpu/client/gpu_video_encode_accelerator_host.cc |
| @@ -13,19 +13,30 @@ |
| namespace content { |
| +#define NOTIFY_ERROR(error) \ |
| + PostNotifyError(error); \ |
| + DLOG(ERROR) |
| + |
| GpuVideoEncodeAcceleratorHost::GpuVideoEncodeAcceleratorHost( |
| - const scoped_refptr<GpuChannelHost>& gpu_channel_host, |
| - int32 route_id) |
| - : client_(NULL), |
| - channel_(gpu_channel_host), |
| - route_id_(route_id), |
| - next_frame_id_(0) { |
| - channel_->AddRoute(route_id_, AsWeakPtr()); |
| + GpuChannelHost* channel, |
| + CommandBufferProxyImpl* impl) |
| + : channel_(channel), |
| + encoder_route_id_(-1), |
| + client_(NULL), |
| + impl_(impl), |
| + next_frame_id_(0), |
| + weak_this_factory_(this) { |
| + DCHECK(channel_); |
| + DCHECK(impl_); |
| + impl_->AddDeletionObserver(this); |
| } |
| GpuVideoEncodeAcceleratorHost::~GpuVideoEncodeAcceleratorHost() { |
| + DCHECK(CalledOnValidThread()); |
| if (channel_) |
| - channel_->RemoveRoute(route_id_); |
| + channel_->RemoveRoute(encoder_route_id_); |
| + if (impl_) |
| + impl_->RemoveDeletionObserver(this); |
| } |
| // static |
| @@ -38,8 +49,6 @@ bool GpuVideoEncodeAcceleratorHost::OnMessageReceived( |
| const IPC::Message& message) { |
| bool handled = true; |
| IPC_BEGIN_MESSAGE_MAP(GpuVideoEncodeAcceleratorHost, message) |
| - IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderHostMsg_NotifyInitializeDone, |
| - OnNotifyInitializeDone) |
| IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderHostMsg_RequireBitstreamBuffers, |
| OnRequireBitstreamBuffers) |
| IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderHostMsg_NotifyInputDone, |
| @@ -57,47 +66,58 @@ bool GpuVideoEncodeAcceleratorHost::OnMessageReceived( |
| } |
| void GpuVideoEncodeAcceleratorHost::OnChannelError() { |
| - DLOG(ERROR) << "OnChannelError()"; |
| + DCHECK(CalledOnValidThread()); |
| if (channel_) { |
| - channel_->RemoveRoute(route_id_); |
| + channel_->RemoveRoute(encoder_route_id_); |
| channel_ = NULL; |
| + weak_this_factory_.InvalidateWeakPtrs(); |
| } |
| - // See OnNotifyError for why this needs to be the last thing in this |
| - // function. |
| - OnNotifyError(kPlatformFailureError); |
| + DLOG(ERROR) << "OnChannelError()"; |
|
Ami GONE FROM CHROMIUM
2014/03/18 23:53:19
Don't you want to notify the client in case of cha
sheu
2014/03/19 20:38:24
Oh, right. I was thinking for some reason this wa
|
| } |
| -void GpuVideoEncodeAcceleratorHost::Initialize( |
| +bool GpuVideoEncodeAcceleratorHost::Initialize( |
| media::VideoFrame::Format input_format, |
| const gfx::Size& input_visible_size, |
| media::VideoCodecProfile output_profile, |
| uint32 initial_bitrate, |
| Client* client) { |
| + DCHECK(CalledOnValidThread()); |
| client_ = client; |
| - client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client_)); |
| - Send(new AcceleratedVideoEncoderMsg_Initialize(route_id_, |
| - input_format, |
| - input_visible_size, |
| - output_profile, |
| - initial_bitrate)); |
| + if (!impl_) { |
| + DLOG(ERROR) << "impl_ destroyed"; |
| + return false; |
| + } |
| + Send(new GpuCommandBufferMsg_CreateVideoEncoder(impl_->GetRouteID(), |
| + input_format, |
| + input_visible_size, |
| + output_profile, |
| + initial_bitrate, |
| + &encoder_route_id_)); |
| + if (encoder_route_id_ < 0) { |
| + DLOG(ERROR) << "Send(GpuCommandBufferMsg_CreateVideoEncoder()) failed"; |
| + return false; |
| + } |
| + channel_->AddRoute(encoder_route_id_, weak_this_factory_.GetWeakPtr()); |
| + return true; |
| } |
| void GpuVideoEncodeAcceleratorHost::Encode( |
| const scoped_refptr<media::VideoFrame>& frame, |
| bool force_keyframe) { |
| + DCHECK(CalledOnValidThread()); |
| if (!channel_) |
| return; |
| + |
| if (!base::SharedMemory::IsHandleValid(frame->shared_memory_handle())) { |
| - DLOG(ERROR) << "Encode(): cannot encode frame not backed by shared memory"; |
| - NotifyError(kPlatformFailureError); |
| + NOTIFY_ERROR(kPlatformFailureError) |
| + << "Encode(): cannot encode frame not backed by shared memory"; |
| return; |
| } |
| base::SharedMemoryHandle handle = |
| channel_->ShareToGpuProcess(frame->shared_memory_handle()); |
| if (!base::SharedMemory::IsHandleValid(handle)) { |
| - DLOG(ERROR) << "Encode(): failed to duplicate buffer handle for GPU " |
| - "process"; |
| - NotifyError(kPlatformFailureError); |
| + NOTIFY_ERROR(kPlatformFailureError) |
| + << "Encode(): failed to duplicate buffer handle for GPU process"; |
| return; |
| } |
| @@ -113,7 +133,7 @@ void GpuVideoEncodeAcceleratorHost::Encode( |
| } |
| Send(new AcceleratedVideoEncoderMsg_Encode( |
| - route_id_, next_frame_id_, handle, frame_size, force_keyframe)); |
| + encoder_route_id_, next_frame_id_, handle, frame_size, force_keyframe)); |
| frame_map_[next_frame_id_] = frame; |
| // Mask against 30 bits, to avoid (undefined) wraparound on signed integer. |
| @@ -122,51 +142,74 @@ void GpuVideoEncodeAcceleratorHost::Encode( |
| void GpuVideoEncodeAcceleratorHost::UseOutputBitstreamBuffer( |
| const media::BitstreamBuffer& buffer) { |
| + DCHECK(CalledOnValidThread()); |
| if (!channel_) |
| return; |
| + |
| base::SharedMemoryHandle handle = |
| channel_->ShareToGpuProcess(buffer.handle()); |
| if (!base::SharedMemory::IsHandleValid(handle)) { |
| - DLOG(ERROR) << "UseOutputBitstreamBuffer(): failed to duplicate buffer " |
| - "handle for GPU process: buffer.id()=" << buffer.id(); |
| - NotifyError(kPlatformFailureError); |
| + NOTIFY_ERROR(kPlatformFailureError) |
| + << "UseOutputBitstreamBuffer(): failed to duplicate buffer handle " |
| + "for GPU process: buffer.id()=" << buffer.id(); |
| return; |
| } |
| Send(new AcceleratedVideoEncoderMsg_UseOutputBitstreamBuffer( |
| - route_id_, buffer.id(), handle, buffer.size())); |
| + encoder_route_id_, buffer.id(), handle, buffer.size())); |
| } |
| void GpuVideoEncodeAcceleratorHost::RequestEncodingParametersChange( |
| uint32 bitrate, |
| uint32 framerate) { |
| + DCHECK(CalledOnValidThread()); |
| + if (!channel_) |
| + return; |
| + |
| Send(new AcceleratedVideoEncoderMsg_RequestEncodingParametersChange( |
| - route_id_, bitrate, framerate)); |
| + encoder_route_id_, bitrate, framerate)); |
| } |
| void GpuVideoEncodeAcceleratorHost::Destroy() { |
| - Send(new GpuChannelMsg_DestroyVideoEncoder(route_id_)); |
| + DCHECK(CalledOnValidThread()); |
| + if (channel_) |
| + Send(new AcceleratedVideoEncoderMsg_Destroy(encoder_route_id_)); |
| + client_ = NULL; |
| delete this; |
| } |
| -void GpuVideoEncodeAcceleratorHost::NotifyError(Error error) { |
| - DVLOG(2) << "NotifyError(): error=" << error; |
| +void GpuVideoEncodeAcceleratorHost::OnWillDeleteImpl() { |
| + DCHECK(CalledOnValidThread()); |
| + impl_ = NULL; |
| + |
| + // The CommandBufferProxyImpl is going away; error out this VEA. |
| + OnChannelError(); |
| +} |
| + |
| +void GpuVideoEncodeAcceleratorHost::PostNotifyError(Error error) { |
| + DCHECK(CalledOnValidThread()); |
| + DVLOG(2) << "PostNotifyError(): error=" << error; |
| + // Post the error notification back to this thread, to avoid re-entrancy. |
| base::MessageLoopProxy::current()->PostTask( |
| FROM_HERE, |
| - base::Bind(&media::VideoEncodeAccelerator::Client::NotifyError, |
| - client_ptr_factory_->GetWeakPtr(), |
| + base::Bind(&GpuVideoEncodeAcceleratorHost::OnNotifyError, |
| + weak_this_factory_.GetWeakPtr(), |
| error)); |
| } |
| -void GpuVideoEncodeAcceleratorHost::OnNotifyInitializeDone() { |
| - DVLOG(2) << "OnNotifyInitializeDone()"; |
| - if (client_) |
| - client_->NotifyInitializeDone(); |
| +void GpuVideoEncodeAcceleratorHost::Send(IPC::Message* message) { |
| + DCHECK(CalledOnValidThread()); |
| + uint32 message_type = message->type(); |
| + if (!channel_->Send(message)) { |
| + NOTIFY_ERROR(kPlatformFailureError) << "Send(" << message_type |
| + << ") failed"; |
| + } |
| } |
| void GpuVideoEncodeAcceleratorHost::OnRequireBitstreamBuffers( |
| uint32 input_count, |
| const gfx::Size& input_coded_size, |
| uint32 output_buffer_size) { |
| + DCHECK(CalledOnValidThread()); |
| DVLOG(2) << "OnRequireBitstreamBuffers(): input_count=" << input_count |
| << ", input_coded_size=" << input_coded_size.ToString() |
| << ", output_buffer_size=" << output_buffer_size; |
| @@ -177,6 +220,7 @@ void GpuVideoEncodeAcceleratorHost::OnRequireBitstreamBuffers( |
| } |
| void GpuVideoEncodeAcceleratorHost::OnNotifyInputDone(int32 frame_id) { |
| + DCHECK(CalledOnValidThread()); |
| DVLOG(3) << "OnNotifyInputDone(): frame_id=" << frame_id; |
| // Fun-fact: std::hash_map is not spec'd to be re-entrant; since freeing a |
| // frame can trigger a further encode to be kicked off and thus an .insert() |
| @@ -199,6 +243,7 @@ void GpuVideoEncodeAcceleratorHost::OnBitstreamBufferReady( |
| int32 bitstream_buffer_id, |
| uint32 payload_size, |
| bool key_frame) { |
| + DCHECK(CalledOnValidThread()); |
| DVLOG(3) << "OnBitstreamBufferReady(): " |
| "bitstream_buffer_id=" << bitstream_buffer_id |
| << ", payload_size=" << payload_size |
| @@ -208,10 +253,10 @@ void GpuVideoEncodeAcceleratorHost::OnBitstreamBufferReady( |
| } |
| void GpuVideoEncodeAcceleratorHost::OnNotifyError(Error error) { |
| + DCHECK(CalledOnValidThread()); |
| DVLOG(2) << "OnNotifyError(): error=" << error; |
| if (!client_) |
| return; |
| - client_ptr_factory_.reset(); |
| // Client::NotifyError() may Destroy() |this|, so calling it needs to be the |
| // last thing done on this stack! |
| @@ -220,16 +265,4 @@ void GpuVideoEncodeAcceleratorHost::OnNotifyError(Error error) { |
| client->NotifyError(error); |
| } |
| -void GpuVideoEncodeAcceleratorHost::Send(IPC::Message* message) { |
| - if (!channel_) { |
| - DLOG(ERROR) << "Send(): no channel"; |
| - delete message; |
| - NotifyError(kPlatformFailureError); |
| - } else if (!channel_->Send(message)) { |
| - DLOG(ERROR) << "Send(): sending failed: message->type()=" |
| - << message->type(); |
| - NotifyError(kPlatformFailureError); |
| - } |
| -} |
| - |
| } // namespace content |