15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/gpu/media/gpu_video_decode_accelerator.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/command_line.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/gpu/gpu_channel.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/gpu/gpu_messages.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/common/content_switches.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/common/command_buffer.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_message_macros.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_message_utils.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_context.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_surface_egl.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/windows_version.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/gpu/media/dxva_video_decode_accelerator.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#elif defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) && defined(USE_X11)
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/common/gpu/media/exynos_video_decode_accelerator.h"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) && defined(USE_X11)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_context_glx.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/gpu/media/vaapi_video_decode_accelerator.h"
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#elif defined(OS_ANDROID)
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/common/gpu/media/android_video_decode_accelerator.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/service/texture_manager.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/size.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using gpu::gles2::TextureManager;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool MakeDecoderContextCurrent(
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::WeakPtr<GpuCommandBufferStub> stub) {
44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!stub.get()) {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(ERROR) << "Stub is gone; won't MakeCurrent().";
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!stub->decoder()->MakeCurrent()) {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(ERROR) << "Failed to MakeCurrent()";
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)GpuVideoDecodeAccelerator::GpuVideoDecodeAccelerator(int32 host_route_id,
587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                                     GpuCommandBufferStub* stub)
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : init_done_msg_(NULL),
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      host_route_id_(host_route_id),
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      stub_(stub),
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      texture_target_(0) {
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(stub_);
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stub_->AddDestructionObserver(this);
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  stub_->channel()->AddRoute(host_route_id_, this);
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  make_context_current_ =
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&MakeDecoderContextCurrent, stub_->AsWeakPtr());
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GpuVideoDecodeAccelerator::~GpuVideoDecodeAccelerator() {
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(stub_);
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (video_decode_accelerator_)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    video_decode_accelerator_.release()->Destroy();
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  stub_->channel()->RemoveRoute(host_route_id_);
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  stub_->RemoveDestructionObserver(this);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GpuVideoDecodeAccelerator::OnMessageReceived(const IPC::Message& msg) {
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(stub_);
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!video_decode_accelerator_)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool handled = true;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC_BEGIN_MESSAGE_MAP(GpuVideoDecodeAccelerator, msg)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_Decode, OnDecode)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_AssignPictureBuffers,
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        OnAssignPictureBuffers)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_ReusePictureBuffer,
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        OnReusePictureBuffer)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_Flush, OnFlush)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_Reset, OnReset)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_Destroy, OnDestroy)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_UNHANDLED(handled = false)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC_END_MESSAGE_MAP()
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return handled;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuVideoDecodeAccelerator::ProvidePictureBuffers(
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32 requested_num_of_buffers,
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Size& dimensions,
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32 texture_target) {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!Send(new AcceleratedVideoDecoderHostMsg_ProvidePictureBuffers(
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          host_route_id_, requested_num_of_buffers, dimensions,
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          texture_target))) {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_ProvidePictureBuffers) "
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                << "failed";
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  texture_target_ = texture_target;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuVideoDecodeAccelerator::DismissPictureBuffer(
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32 picture_buffer_id) {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Notify client that picture buffer is now unused.
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!Send(new AcceleratedVideoDecoderHostMsg_DismissPictureBuffer(
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          host_route_id_, picture_buffer_id))) {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_DismissPictureBuffer) "
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                << "failed";
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuVideoDecodeAccelerator::PictureReady(
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const media::Picture& picture) {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!Send(new AcceleratedVideoDecoderHostMsg_PictureReady(
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          host_route_id_,
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          picture.picture_buffer_id(),
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          picture.bitstream_buffer_id()))) {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_PictureReady) failed";
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuVideoDecodeAccelerator::NotifyError(
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    media::VideoDecodeAccelerator::Error error) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (init_done_msg_) {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If we get an error while we're initializing, NotifyInitializeDone won't
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // be called, so we need to send the reply (with an error) here.
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GpuCommandBufferMsg_CreateVideoDecoder::WriteReplyParams(
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        init_done_msg_, -1);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!Send(init_done_msg_))
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DLOG(ERROR) << "Send(init_done_msg_) failed";
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    init_done_msg_ = NULL;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!Send(new AcceleratedVideoDecoderHostMsg_ErrorNotification(
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          host_route_id_, error))) {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_ErrorNotification) "
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                << "failed";
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuVideoDecodeAccelerator::Initialize(
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const media::VideoCodecProfile profile,
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC::Message* init_done_msg) {
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(stub_);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!video_decode_accelerator_.get());
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!init_done_msg_);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(init_done_msg);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_done_msg_ = init_done_msg;
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_WIN)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure we will be able to get a GL context at all before initializing
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // non-Windows VDAs.
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!make_context_current_.Run()) {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (base::win::GetVersion() < base::win::VERSION_WIN7) {
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTIMPLEMENTED() << "HW video decode acceleration not available.";
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE);
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DLOG(INFO) << "Initializing DXVA HW decoder for windows.";
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  video_decode_accelerator_.reset(new DXVAVideoDecodeAccelerator(
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this, make_context_current_));
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#elif defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) && defined(USE_X11)
1783240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  video_decode_accelerator_.reset(new ExynosVideoDecodeAccelerator(
1793240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      gfx::GLSurfaceEGL::GetHardwareDisplay(),
1803240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      stub_->decoder()->GetGLContext()->GetHandle(),
1813240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      this,
1823240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      make_context_current_));
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) && defined(USE_X11)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::GLContextGLX* glx_context =
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<gfx::GLContextGLX*>(stub_->decoder()->GetGLContext());
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLXContext glx_context_handle =
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<GLXContext>(glx_context->GetHandle());
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  video_decode_accelerator_.reset(new VaapiVideoDecodeAccelerator(
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      glx_context->display(), glx_context_handle, this,
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      make_context_current_));
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#elif defined(OS_ANDROID)
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  video_decode_accelerator_.reset(new AndroidVideoDecodeAccelerator(
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      this,
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      stub_->decoder()->AsWeakPtr(),
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      make_context_current_));
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTIMPLEMENTED() << "HW video decode acceleration not available.";
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE);
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!video_decode_accelerator_->Initialize(profile))
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE);
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuVideoDecodeAccelerator::OnDecode(
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::SharedMemoryHandle handle, int32 id, uint32 size) {
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(video_decode_accelerator_.get());
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (id < 0) {
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DLOG(FATAL) << "BitstreamBuffer id " << id << " out of range";
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT);
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  video_decode_accelerator_->Decode(media::BitstreamBuffer(id, handle, size));
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuVideoDecodeAccelerator::OnAssignPictureBuffers(
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::vector<int32>& buffer_ids,
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::vector<uint32>& texture_ids,
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::vector<gfx::Size>& sizes) {
221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(stub_);
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (buffer_ids.size() != texture_ids.size() ||
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      buffer_ids.size() != sizes.size()) {
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT);
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gpu::gles2::GLES2Decoder* command_decoder = stub_->decoder();
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gpu::gles2::TextureManager* texture_manager =
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      command_decoder->GetContextGroup()->texture_manager();
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<media::PictureBuffer> buffers;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (uint32 i = 0; i < buffer_ids.size(); ++i) {
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (buffer_ids[i] < 0) {
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DLOG(FATAL) << "Buffer id " << buffer_ids[i] << " out of range";
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT);
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
23990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    gpu::gles2::TextureRef* texture_ref = texture_manager->GetTexture(
24090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        texture_ids[i]);
24190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (!texture_ref) {
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DLOG(FATAL) << "Failed to find texture id " << texture_ids[i];
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT);
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
24690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    gpu::gles2::Texture* info = texture_ref->texture();
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (info->target() != texture_target_) {
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DLOG(FATAL) << "Texture target mismatch for texture id "
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  << texture_ids[i];
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT);
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // GL_TEXTURE_EXTERNAL_OES textures have their dimensions defined by the
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // underlying EGLImage.
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (texture_target_ != GL_TEXTURE_EXTERNAL_OES) {
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GLsizei width = 0, height = 0;
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      info->GetLevelSize(texture_target_, 0, &width, &height);
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (width != sizes[i].width() || height != sizes[i].height()) {
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        DLOG(FATAL) << "Size mismatch for texture id " << texture_ids[i];
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT);
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return;
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
26490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (!texture_manager->ClearRenderableLevels(command_decoder, texture_ref)) {
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DLOG(FATAL) << "Failed to Clear texture id " << texture_ids[i];
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE);
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32 service_texture_id;
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!command_decoder->GetServiceTextureId(
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            texture_ids[i], &service_texture_id)) {
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DLOG(FATAL) << "Failed to translate texture!";
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE);
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffers.push_back(media::PictureBuffer(
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        buffer_ids[i], sizes[i], service_texture_id));
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  video_decode_accelerator_->AssignPictureBuffers(buffers);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuVideoDecodeAccelerator::OnReusePictureBuffer(
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32 picture_buffer_id) {
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(video_decode_accelerator_.get());
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  video_decode_accelerator_->ReusePictureBuffer(picture_buffer_id);
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuVideoDecodeAccelerator::OnFlush() {
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(video_decode_accelerator_.get());
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  video_decode_accelerator_->Flush();
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuVideoDecodeAccelerator::OnReset() {
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(video_decode_accelerator_.get());
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  video_decode_accelerator_->Reset();
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuVideoDecodeAccelerator::OnDestroy() {
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(video_decode_accelerator_.get());
300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  delete this;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer(
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32 bitstream_buffer_id) {
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!Send(new AcceleratedVideoDecoderHostMsg_BitstreamBufferProcessed(
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          host_route_id_, bitstream_buffer_id))) {
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(ERROR)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << "Send(AcceleratedVideoDecoderHostMsg_BitstreamBufferProcessed) "
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << "failed";
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuVideoDecodeAccelerator::NotifyInitializeDone() {
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GpuCommandBufferMsg_CreateVideoDecoder::WriteReplyParams(
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      init_done_msg_, host_route_id_);
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!Send(init_done_msg_))
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(ERROR) << "Send(init_done_msg_) failed";
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_done_msg_ = NULL;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuVideoDecodeAccelerator::NotifyFlushDone() {
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!Send(new AcceleratedVideoDecoderHostMsg_FlushDone(host_route_id_)))
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_FlushDone) failed";
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuVideoDecodeAccelerator::NotifyResetDone() {
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!Send(new AcceleratedVideoDecoderHostMsg_ResetDone(host_route_id_)))
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_ResetDone) failed";
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void GpuVideoDecodeAccelerator::OnWillDestroyStub() {
332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  delete this;
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GpuVideoDecodeAccelerator::Send(IPC::Message* message) {
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(stub_);
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return stub_->channel()->Send(message);
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
341