// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/renderer/pepper/ppb_video_decoder_impl.h"

#include <string>

#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram.h"
#include "content/common/gpu/client/gpu_channel_host.h"
#include "content/renderer/pepper/common.h"
#include "content/renderer/pepper/host_globals.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
#include "content/renderer/pepper/plugin_module.h"
#include "content/renderer/pepper/ppb_buffer_impl.h"
#include "content/renderer/pepper/ppb_graphics_3d_impl.h"
#include "content/renderer/render_thread_impl.h"
#include "gpu/command_buffer/client/gles2_implementation.h"
#include "media/video/picture.h"
#include "media/video/video_decode_accelerator.h"
#include "ppapi/c/dev/pp_video_dev.h"
#include "ppapi/c/dev/ppb_video_decoder_dev.h"
#include "ppapi/c/dev/ppp_video_decoder_dev.h"
#include "ppapi/c/pp_completion_callback.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/shared_impl/resource_tracker.h"
#include "ppapi/thunk/enter.h"

using ppapi::TrackedCallback;
using ppapi::thunk::EnterResourceNoLock;
using ppapi::thunk::PPB_Buffer_API;
using ppapi::thunk::PPB_Graphics3D_API;

namespace {

// Convert PP_VideoDecoder_Profile to media::VideoCodecProfile.
media::VideoCodecProfile PPToMediaProfile(
    const PP_VideoDecoder_Profile pp_profile) {
  switch (pp_profile) {
    case PP_VIDEODECODER_H264PROFILE_NONE:
    // HACK: PPAPI contains a bogus "none" h264 profile that doesn't
    // correspond to anything in h.264; but a number of released chromium
    // versions silently promoted this to Baseline profile, so we retain that
    // behavior here.  Fall through.
    case PP_VIDEODECODER_H264PROFILE_BASELINE:
      return media::H264PROFILE_BASELINE;
    case PP_VIDEODECODER_H264PROFILE_MAIN:
      return media::H264PROFILE_MAIN;
    case PP_VIDEODECODER_H264PROFILE_EXTENDED:
      return media::H264PROFILE_EXTENDED;
    case PP_VIDEODECODER_H264PROFILE_HIGH:
      return media::H264PROFILE_HIGH;
    case PP_VIDEODECODER_H264PROFILE_HIGH10PROFILE:
      return media::H264PROFILE_HIGH10PROFILE;
    case PP_VIDEODECODER_H264PROFILE_HIGH422PROFILE:
      return media::H264PROFILE_HIGH422PROFILE;
    case PP_VIDEODECODER_H264PROFILE_HIGH444PREDICTIVEPROFILE:
      return media::H264PROFILE_HIGH444PREDICTIVEPROFILE;
    case PP_VIDEODECODER_H264PROFILE_SCALABLEBASELINE:
      return media::H264PROFILE_SCALABLEBASELINE;
    case PP_VIDEODECODER_H264PROFILE_SCALABLEHIGH:
      return media::H264PROFILE_SCALABLEHIGH;
    case PP_VIDEODECODER_H264PROFILE_STEREOHIGH:
      return media::H264PROFILE_STEREOHIGH;
    case PP_VIDEODECODER_H264PROFILE_MULTIVIEWHIGH:
      return media::H264PROFILE_MULTIVIEWHIGH;
    case PP_VIDEODECODER_VP8PROFILE_MAIN:
      return media::VP8PROFILE_MAIN;
    default:
      return media::VIDEO_CODEC_PROFILE_UNKNOWN;
  }
}

PP_VideoDecodeError_Dev MediaToPPError(
    media::VideoDecodeAccelerator::Error error) {
  switch (error) {
    case media::VideoDecodeAccelerator::ILLEGAL_STATE:
      return PP_VIDEODECODERERROR_ILLEGAL_STATE;
    case media::VideoDecodeAccelerator::INVALID_ARGUMENT:
      return PP_VIDEODECODERERROR_INVALID_ARGUMENT;
    case media::VideoDecodeAccelerator::UNREADABLE_INPUT:
      return PP_VIDEODECODERERROR_UNREADABLE_INPUT;
    case media::VideoDecodeAccelerator::PLATFORM_FAILURE:
      return PP_VIDEODECODERERROR_PLATFORM_FAILURE;
    default:
      NOTREACHED();
      return PP_VIDEODECODERERROR_ILLEGAL_STATE;
  }
}

}  // namespace

namespace content {

PPB_VideoDecoder_Impl::PPB_VideoDecoder_Impl(PP_Instance instance)
    : PPB_VideoDecoder_Shared(instance), ppp_videodecoder_(NULL) {
  PluginModule* plugin_module =
      HostGlobals::Get()->GetInstance(pp_instance())->module();
  if (plugin_module) {
    ppp_videodecoder_ = static_cast<const PPP_VideoDecoder_Dev*>(
        plugin_module->GetPluginInterface(PPP_VIDEODECODER_DEV_INTERFACE));
  }
}

PPB_VideoDecoder_Impl::~PPB_VideoDecoder_Impl() { Destroy(); }

// static
PP_Resource PPB_VideoDecoder_Impl::Create(PP_Instance instance,
                                          PP_Resource graphics_context,
                                          PP_VideoDecoder_Profile profile) {
  scoped_refptr<PPB_VideoDecoder_Impl> decoder(
      new PPB_VideoDecoder_Impl(instance));
  if (decoder->Init(graphics_context, profile))
    return decoder->GetReference();
  return 0;
}

bool PPB_VideoDecoder_Impl::Init(PP_Resource graphics_context,
                                 PP_VideoDecoder_Profile profile) {
  EnterResourceNoLock<PPB_Graphics3D_API> enter_context(graphics_context, true);
  if (enter_context.failed())
    return false;

  PPB_Graphics3D_Impl* graphics_3d =
      static_cast<PPB_Graphics3D_Impl*>(enter_context.object());

  int command_buffer_route_id = graphics_3d->GetCommandBufferRouteId();
  if (command_buffer_route_id == 0)
    return false;

  InitCommon(graphics_context, graphics_3d->gles2_impl());
  FlushCommandBuffer();

  // This is not synchronous, but subsequent IPC messages will be buffered, so
  // it is okay to immediately send IPC messages through the returned channel.
  GpuChannelHost* channel = graphics_3d->channel();
  DCHECK(channel);
  decoder_ = channel->CreateVideoDecoder(command_buffer_route_id);
  return (decoder_ && decoder_->Initialize(PPToMediaProfile(profile), this));
}

int32_t PPB_VideoDecoder_Impl::Decode(
    const PP_VideoBitstreamBuffer_Dev* bitstream_buffer,
    scoped_refptr<TrackedCallback> callback) {
  if (!decoder_)
    return PP_ERROR_BADRESOURCE;

  EnterResourceNoLock<PPB_Buffer_API> enter(bitstream_buffer->data, true);
  if (enter.failed())
    return PP_ERROR_FAILED;

  PPB_Buffer_Impl* buffer = static_cast<PPB_Buffer_Impl*>(enter.object());
  DCHECK_GE(bitstream_buffer->id, 0);
  media::BitstreamBuffer decode_buffer(bitstream_buffer->id,
                                       buffer->shared_memory()->handle(),
                                       bitstream_buffer->size);
  if (!SetBitstreamBufferCallback(bitstream_buffer->id, callback))
    return PP_ERROR_BADARGUMENT;

  FlushCommandBuffer();
  decoder_->Decode(decode_buffer);
  return PP_OK_COMPLETIONPENDING;
}

void PPB_VideoDecoder_Impl::AssignPictureBuffers(
    uint32_t no_of_buffers,
    const PP_PictureBuffer_Dev* buffers) {
  if (!decoder_)
    return;
  UMA_HISTOGRAM_COUNTS_100("Media.PepperVideoDecoderPictureCount",
                           no_of_buffers);

  std::vector<media::PictureBuffer> wrapped_buffers;
  for (uint32 i = 0; i < no_of_buffers; i++) {
    PP_PictureBuffer_Dev in_buf = buffers[i];
    DCHECK_GE(in_buf.id, 0);
    media::PictureBuffer buffer(
        in_buf.id,
        gfx::Size(in_buf.size.width, in_buf.size.height),
        in_buf.texture_id);
    wrapped_buffers.push_back(buffer);
    UMA_HISTOGRAM_COUNTS_10000("Media.PepperVideoDecoderPictureHeight",
                               in_buf.size.height);
  }

  FlushCommandBuffer();
  decoder_->AssignPictureBuffers(wrapped_buffers);
}

void PPB_VideoDecoder_Impl::ReusePictureBuffer(int32_t picture_buffer_id) {
  if (!decoder_)
    return;

  FlushCommandBuffer();
  decoder_->ReusePictureBuffer(picture_buffer_id);
}

int32_t PPB_VideoDecoder_Impl::Flush(scoped_refptr<TrackedCallback> callback) {
  if (!decoder_)
    return PP_ERROR_BADRESOURCE;

  if (!SetFlushCallback(callback))
    return PP_ERROR_INPROGRESS;

  FlushCommandBuffer();
  decoder_->Flush();
  return PP_OK_COMPLETIONPENDING;
}

int32_t PPB_VideoDecoder_Impl::Reset(scoped_refptr<TrackedCallback> callback) {
  if (!decoder_)
    return PP_ERROR_BADRESOURCE;

  if (!SetResetCallback(callback))
    return PP_ERROR_INPROGRESS;

  FlushCommandBuffer();
  decoder_->Reset();
  return PP_OK_COMPLETIONPENDING;
}

void PPB_VideoDecoder_Impl::Destroy() {
  FlushCommandBuffer();

  decoder_.reset();
  ppp_videodecoder_ = NULL;

  ::ppapi::PPB_VideoDecoder_Shared::Destroy();
}

void PPB_VideoDecoder_Impl::ProvidePictureBuffers(
    uint32 requested_num_of_buffers,
    const gfx::Size& dimensions,
    uint32 texture_target) {
  DCHECK(RenderThreadImpl::current());
  if (!ppp_videodecoder_)
    return;

  PP_Size out_dim = PP_MakeSize(dimensions.width(), dimensions.height());
  ppp_videodecoder_->ProvidePictureBuffers(pp_instance(),
                                           pp_resource(),
                                           requested_num_of_buffers,
                                           &out_dim,
                                           texture_target);
}

void PPB_VideoDecoder_Impl::PictureReady(const media::Picture& picture) {
  DCHECK(RenderThreadImpl::current());
  if (!ppp_videodecoder_)
    return;

  PP_Picture_Dev output;
  output.picture_buffer_id = picture.picture_buffer_id();
  output.bitstream_buffer_id = picture.bitstream_buffer_id();
  ppp_videodecoder_->PictureReady(pp_instance(), pp_resource(), &output);
}

void PPB_VideoDecoder_Impl::DismissPictureBuffer(int32 picture_buffer_id) {
  DCHECK(RenderThreadImpl::current());
  if (!ppp_videodecoder_)
    return;
  ppp_videodecoder_->DismissPictureBuffer(
      pp_instance(), pp_resource(), picture_buffer_id);
}

void PPB_VideoDecoder_Impl::NotifyError(
    media::VideoDecodeAccelerator::Error error) {
  DCHECK(RenderThreadImpl::current());
  if (!ppp_videodecoder_)
    return;

  PP_VideoDecodeError_Dev pp_error = MediaToPPError(error);
  ppp_videodecoder_->NotifyError(pp_instance(), pp_resource(), pp_error);
  UMA_HISTOGRAM_ENUMERATION("Media.PepperVideoDecoderError",
                            error,
                            media::VideoDecodeAccelerator::LARGEST_ERROR_ENUM);
}

void PPB_VideoDecoder_Impl::NotifyResetDone() {
  DCHECK(RenderThreadImpl::current());
  RunResetCallback(PP_OK);
}

void PPB_VideoDecoder_Impl::NotifyEndOfBitstreamBuffer(
    int32 bitstream_buffer_id) {
  DCHECK(RenderThreadImpl::current());
  RunBitstreamBufferCallback(bitstream_buffer_id, PP_OK);
}

void PPB_VideoDecoder_Impl::NotifyFlushDone() {
  DCHECK(RenderThreadImpl::current());
  RunFlushCallback(PP_OK);
}

}  // namespace content
