Home | History | Annotate | Download | only in client
      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