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