gpu_video_decode_accelerator_host.cc revision 9ab5563a3196760eb381d102cbb2bc0f7abc6a50
1// Copyright (c) 2012 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#include "content/common/gpu/client/gpu_video_decode_accelerator_host.h" 6 7#include "base/bind.h" 8#include "base/logging.h" 9#include "base/message_loop/message_loop.h" 10#include "content/common/gpu/client/gpu_channel_host.h" 11#include "content/common/gpu/gpu_messages.h" 12#include "content/common/view_messages.h" 13#include "ipc/ipc_message_macros.h" 14#include "ipc/ipc_message_utils.h" 15 16#if defined(OS_WIN) 17#include "content/public/common/sandbox_init.h" 18#endif // OS_WIN 19 20using media::VideoDecodeAccelerator; 21namespace content { 22 23GpuVideoDecodeAcceleratorHost::GpuVideoDecodeAcceleratorHost( 24 GpuChannelHost* channel, 25 int32 decoder_route_id, 26 VideoDecodeAccelerator::Client* client, 27 CommandBufferProxyImpl* impl) 28 : channel_(channel), 29 decoder_route_id_(decoder_route_id), 30 client_(client), 31 impl_(impl) { 32 DCHECK(channel_); 33 DCHECK(client_); 34 channel_->AddRoute(decoder_route_id, base::AsWeakPtr(this)); 35 impl_->AddDeletionObserver(this); 36} 37 38void GpuVideoDecodeAcceleratorHost::OnChannelError() { 39 DLOG(ERROR) << "GpuVideoDecodeAcceleratorHost::OnChannelError()"; 40 OnErrorNotification(PLATFORM_FAILURE); 41 if (channel_) { 42 channel_->RemoveRoute(decoder_route_id_); 43 channel_ = NULL; 44 } 45} 46 47bool GpuVideoDecodeAcceleratorHost::OnMessageReceived(const IPC::Message& msg) { 48 DCHECK(CalledOnValidThread()); 49 bool handled = true; 50 IPC_BEGIN_MESSAGE_MAP(GpuVideoDecodeAcceleratorHost, msg) 51 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_BitstreamBufferProcessed, 52 OnBitstreamBufferProcessed) 53 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_ProvidePictureBuffers, 54 OnProvidePictureBuffer) 55 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_PictureReady, 56 OnPictureReady) 57 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_FlushDone, 58 OnFlushDone) 59 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_ResetDone, 60 OnResetDone) 61 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_ErrorNotification, 62 OnErrorNotification) 63 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_DismissPictureBuffer, 64 OnDismissPictureBuffer) 65 IPC_MESSAGE_UNHANDLED(handled = false) 66 IPC_END_MESSAGE_MAP() 67 DCHECK(handled); 68 return handled; 69} 70 71bool GpuVideoDecodeAcceleratorHost::Initialize( 72 media::VideoCodecProfile profile) { 73 NOTREACHED(); 74 return true; 75} 76 77void GpuVideoDecodeAcceleratorHost::Decode( 78 const media::BitstreamBuffer& bitstream_buffer) { 79 DCHECK(CalledOnValidThread()); 80 // Can happen if a decode task was posted before an error was delivered. 81 if (!channel_) 82 return; 83 84 base::SharedMemoryHandle handle = channel_->ShareToGpuProcess( 85 bitstream_buffer.handle()); 86 if (!base::SharedMemory::IsHandleValid(handle)) { 87 NOTREACHED() << "Failed to duplicate buffer handler"; 88 return; 89 } 90 91 Send(new AcceleratedVideoDecoderMsg_Decode( 92 decoder_route_id_, handle, bitstream_buffer.id(), 93 bitstream_buffer.size())); 94} 95 96void GpuVideoDecodeAcceleratorHost::AssignPictureBuffers( 97 const std::vector<media::PictureBuffer>& buffers) { 98 DCHECK(CalledOnValidThread()); 99 // Rearrange data for IPC command. 100 std::vector<int32> buffer_ids; 101 std::vector<uint32> texture_ids; 102 std::vector<gfx::Size> sizes; 103 for (uint32 i = 0; i < buffers.size(); i++) { 104 const media::PictureBuffer& buffer = buffers[i]; 105 texture_ids.push_back(buffer.texture_id()); 106 buffer_ids.push_back(buffer.id()); 107 sizes.push_back(buffer.size()); 108 } 109 Send(new AcceleratedVideoDecoderMsg_AssignPictureBuffers( 110 decoder_route_id_, buffer_ids, texture_ids, sizes)); 111} 112 113void GpuVideoDecodeAcceleratorHost::ReusePictureBuffer( 114 int32 picture_buffer_id) { 115 DCHECK(CalledOnValidThread()); 116 Send(new AcceleratedVideoDecoderMsg_ReusePictureBuffer( 117 decoder_route_id_, picture_buffer_id)); 118} 119 120void GpuVideoDecodeAcceleratorHost::Flush() { 121 DCHECK(CalledOnValidThread()); 122 Send(new AcceleratedVideoDecoderMsg_Flush(decoder_route_id_)); 123} 124 125void GpuVideoDecodeAcceleratorHost::Reset() { 126 DCHECK(CalledOnValidThread()); 127 Send(new AcceleratedVideoDecoderMsg_Reset(decoder_route_id_)); 128} 129 130void GpuVideoDecodeAcceleratorHost::Destroy() { 131 DCHECK(CalledOnValidThread()); 132 client_ = NULL; 133 Send(new AcceleratedVideoDecoderMsg_Destroy(decoder_route_id_)); 134 delete this; 135} 136 137void GpuVideoDecodeAcceleratorHost::OnWillDeleteImpl() { 138 impl_ = NULL; 139 140 // The CommandBufferProxyImpl is going away; error out this VDA. 141 OnChannelError(); 142} 143 144GpuVideoDecodeAcceleratorHost::~GpuVideoDecodeAcceleratorHost() { 145 DCHECK(CalledOnValidThread()); 146 DCHECK(!client_) << "destructor called without Destroy being called!"; 147 148 if (channel_) 149 channel_->RemoveRoute(decoder_route_id_); 150 if (impl_) 151 impl_->RemoveDeletionObserver(this); 152} 153 154void GpuVideoDecodeAcceleratorHost::Send(IPC::Message* message) { 155 // After OnChannelError is called, the client should no longer send 156 // messages to the gpu channel through this object. But queued posted tasks 157 // can still be draining, so we're forgiving and simply ignore them. 158 bool error = false; 159 uint32 message_type = message->type(); 160 if (!channel_) { 161 delete message; 162 DLOG(ERROR) << "Send(" << message_type << ") after error ignored"; 163 error = true; 164 } else if (!channel_->Send(message)) { 165 DLOG(ERROR) << "Send(" << message_type << ") failed"; 166 error = true; 167 } 168 if (error) 169 OnErrorNotification(PLATFORM_FAILURE); 170} 171 172void GpuVideoDecodeAcceleratorHost::OnBitstreamBufferProcessed( 173 int32 bitstream_buffer_id) { 174 DCHECK(CalledOnValidThread()); 175 if (client_) 176 client_->NotifyEndOfBitstreamBuffer(bitstream_buffer_id); 177} 178 179void GpuVideoDecodeAcceleratorHost::OnProvidePictureBuffer( 180 uint32 num_requested_buffers, 181 const gfx::Size& buffer_size, 182 uint32 texture_target) { 183 DCHECK(CalledOnValidThread()); 184 if (client_) { 185 client_->ProvidePictureBuffers( 186 num_requested_buffers, buffer_size, texture_target); 187 } 188} 189 190void GpuVideoDecodeAcceleratorHost::OnDismissPictureBuffer( 191 int32 picture_buffer_id) { 192 DCHECK(CalledOnValidThread()); 193 if (client_) 194 client_->DismissPictureBuffer(picture_buffer_id); 195} 196 197void GpuVideoDecodeAcceleratorHost::OnPictureReady( 198 int32 picture_buffer_id, int32 bitstream_buffer_id) { 199 DCHECK(CalledOnValidThread()); 200 if (!client_) 201 return; 202 media::Picture picture(picture_buffer_id, bitstream_buffer_id); 203 client_->PictureReady(picture); 204} 205 206void GpuVideoDecodeAcceleratorHost::OnFlushDone() { 207 DCHECK(CalledOnValidThread()); 208 if (client_) 209 client_->NotifyFlushDone(); 210} 211 212void GpuVideoDecodeAcceleratorHost::OnResetDone() { 213 DCHECK(CalledOnValidThread()); 214 if (client_) 215 client_->NotifyResetDone(); 216} 217 218void GpuVideoDecodeAcceleratorHost::OnErrorNotification(uint32 error) { 219 DCHECK(CalledOnValidThread()); 220 if (!client_) 221 return; 222 client_->NotifyError( 223 static_cast<media::VideoDecodeAccelerator::Error>(error)); 224 client_ = NULL; 225} 226 227} // namespace content 228