// 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 "media/filters/gpu_video_decoder.h"

#include <algorithm>
#include <array>
#include <cinttypes>
#include <utility>

#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/command_line.h"
#include "base/cpu.h"
#include "base/location.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "base/task_runner_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/process_memory_dump.h"
#include "build/build_config.h"
#include "gpu/command_buffer/client/context_support.h"
#include "gpu/command_buffer/common/mailbox_holder.h"
#include "media/base/bind_to_current_loop.h"
#include "media/base/cdm_context.h"
#include "media/base/decoder_buffer.h"
#include "media/base/media_log.h"
#include "media/base/media_switches.h"
#include "media/base/pipeline_status.h"
#include "media/base/video_decoder_config.h"
#include "media/base/video_util.h"
#include "media/media_buildflags.h"
#include "media/video/gpu_video_accelerator_factories.h"
#include "media/video/trace_util.h"
#include "third_party/skia/include/core/SkBitmap.h"

#if defined(OS_ANDROID) && BUILDFLAG(USE_PROPRIETARY_CODECS)
#include "media/base/android/extract_sps_and_pps.h"
#endif

namespace media {
const char GpuVideoDecoder::kDecoderName[] = "GpuVideoDecoder";

// Maximum number of concurrent VDA::Decode() operations GVD will maintain.
// Higher values allow better pipelining in the GPU, but also require more
// resources.
enum { kMaxInFlightDecodes = 4 };

// Number of bitstream buffers returned before GC is attempted on shared memory
// segments. Value chosen arbitrarily.
enum { kBufferCountBeforeGC = 1024 };

struct GpuVideoDecoder::PendingDecoderBuffer {
  PendingDecoderBuffer(std::unique_ptr<base::SharedMemory> s,
                       const DecodeCB& done_cb)
      : shared_memory(std::move(s)), done_cb(done_cb) {}
  std::unique_ptr<base::SharedMemory> shared_memory;
  DecodeCB done_cb;
};

GpuVideoDecoder::BufferData::BufferData(int32_t bbid,
                                        base::TimeDelta ts,
                                        const gfx::Rect& vr,
                                        const gfx::Size& ns)
    : bitstream_buffer_id(bbid),
      timestamp(ts),
      visible_rect(vr),
      natural_size(ns) {}

GpuVideoDecoder::BufferData::~BufferData() = default;

GpuVideoDecoder::GpuVideoDecoder(
    GpuVideoAcceleratorFactories* factories,
    const RequestOverlayInfoCB& request_overlay_info_cb,
    const gfx::ColorSpace& target_color_space,
    MediaLog* media_log)
    : needs_bitstream_conversion_(false),
      factories_(factories),
      request_overlay_info_cb_(request_overlay_info_cb),
      overlay_info_requested_(false),
      target_color_space_(target_color_space),
      media_log_(media_log),
      vda_initialized_(false),
      state_(kNormal),
      next_picture_buffer_id_(0),
      next_bitstream_buffer_id_(0),
      needs_all_picture_buffers_to_decode_(false),
      supports_deferred_initialization_(false),
      requires_texture_copy_(false),
      cdm_id_(CdmContext::kInvalidCdmId),
      min_shared_memory_segment_size_(0),
      bitstream_buffer_id_of_last_gc_(0),
      weak_factory_(this) {
  DCHECK(factories_);
  base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
      this, "media::GpuVideoDecoder", base::ThreadTaskRunnerHandle::Get());
}

void GpuVideoDecoder::Reset(const base::Closure& closure) {
  DVLOG(3) << "Reset()";
  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();

  if (state_ == kDrainingDecoder) {
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE, base::BindOnce(&GpuVideoDecoder::Reset,
                                  weak_factory_.GetWeakPtr(), closure));
    return;
  }

  if (!vda_) {
    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, closure);
    return;
  }

  DCHECK(!pending_reset_cb_);
  pending_reset_cb_ = BindToCurrentLoop(closure);

  vda_->Reset();
}

static bool IsCodedSizeSupported(const gfx::Size& coded_size,
                                 const gfx::Size& min_resolution,
                                 const gfx::Size& max_resolution) {
  return (coded_size.width() <= max_resolution.width() &&
          coded_size.height() <= max_resolution.height() &&
          coded_size.width() >= min_resolution.width() &&
          coded_size.height() >= min_resolution.height());
}

// Report |success| to UMA and run |cb| with it.  This is super-specific to the
// UMA stat reported because the UMA_HISTOGRAM_ENUMERATION API requires a
// callsite to always be called with the same stat name (can't parameterize it).
static void ReportGpuVideoDecoderInitializeStatusToUMAAndRunCB(
    const VideoDecoder::InitCB& cb,
    MediaLog* media_log,
    bool success) {
  // TODO(xhwang): Report |success| directly.
  PipelineStatus status = success ? PIPELINE_OK : DECODER_ERROR_NOT_SUPPORTED;
  UMA_HISTOGRAM_ENUMERATION("Media.GpuVideoDecoderInitializeStatus", status,
                            PIPELINE_STATUS_MAX + 1);

  if (!success) {
    media_log->RecordRapporWithSecurityOrigin(
        "Media.OriginUrl.GpuVideoDecoderInitFailure");
  }

  cb.Run(success);
}

bool GpuVideoDecoder::IsPlatformDecoder() const {
  return true;
}

std::string GpuVideoDecoder::GetDisplayName() const {
  return kDecoderName;
}

void GpuVideoDecoder::Initialize(const VideoDecoderConfig& config,
                                 bool /* low_delay */,
                                 CdmContext* cdm_context,
                                 const InitCB& init_cb,
                                 const OutputCB& output_cb,
                                 const WaitingCB& /* waiting_cb */) {
  DVLOG(3) << "Initialize()";
  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
  DCHECK(config.IsValidConfig());

  InitCB bound_init_cb =
      base::Bind(&ReportGpuVideoDecoderInitializeStatusToUMAAndRunCB,
                 BindToCurrentLoop(init_cb), media_log_);

  bool previously_initialized = config_.IsValidConfig();
  DVLOG(1) << (previously_initialized ? "Reinitializing" : "Initializing")
           << " GVD with config: " << config.AsHumanReadableString();

  auto encryption_mode = config.encryption_scheme().mode();
  if (encryption_mode != EncryptionScheme::CIPHER_MODE_UNENCRYPTED &&
      encryption_mode != EncryptionScheme::CIPHER_MODE_AES_CTR) {
    DVLOG(1) << "VDAs only support clear or cenc encrypted streams.";
    bound_init_cb.Run(false);
    return;
  }

  // Disallow codec changes between configuration changes.
  if (previously_initialized && config_.codec() != config.codec()) {
    DVLOG(1) << "Codec changed, cannot reinitialize.";
    bound_init_cb.Run(false);
    return;
  }

  // TODO(sandersd): This should be moved to capabilities if we ever have a
  // hardware decoder which supports alpha formats.
  if (config.format() == PIXEL_FORMAT_I420A) {
    DVLOG(1) << "Alpha transparency formats are not supported.";
    bound_init_cb.Run(false);
    return;
  }

  VideoDecodeAccelerator::Capabilities capabilities =
      factories_->GetVideoDecodeAcceleratorCapabilities();

  const bool supports_encrypted_streams =
      capabilities.flags &
      VideoDecodeAccelerator::Capabilities::SUPPORTS_ENCRYPTED_STREAMS;
  if (config.is_encrypted() && (!cdm_context || !supports_encrypted_streams)) {
    DVLOG(1) << "Encrypted stream not supported.";
    bound_init_cb.Run(false);
    return;
  }

  if (!IsProfileSupported(capabilities, config.profile(), config.coded_size(),
                          config.is_encrypted())) {
    DVLOG(1) << "Unsupported profile " << GetProfileName(config.profile())
             << ", unsupported coded size " << config.coded_size().ToString()
             << ", or accelerator should only be used for encrypted content. "
             << " is_encrypted: " << (config.is_encrypted() ? "yes." : "no.");
    bound_init_cb.Run(false);
    return;
  }

  config_ = config;
  needs_all_picture_buffers_to_decode_ =
      capabilities.flags &
      VideoDecodeAccelerator::Capabilities::NEEDS_ALL_PICTURE_BUFFERS_TO_DECODE;
  needs_bitstream_conversion_ =
      (config.codec() == kCodecH264) || (config.codec() == kCodecHEVC);
  requires_texture_copy_ =
      !!(capabilities.flags &
         VideoDecodeAccelerator::Capabilities::REQUIRES_TEXTURE_COPY);
  supports_deferred_initialization_ = !!(
      capabilities.flags &
      VideoDecodeAccelerator::Capabilities::SUPPORTS_DEFERRED_INITIALIZATION);
  output_cb_ = output_cb;

  // Attempt to choose a reasonable size for the shared memory segments based on
  // the size of video. These values are chosen based on experiments with common
  // videos from the web. Too small and you'll end up creating too many segments
  // too large and you end up wasting significant amounts of memory.
  const int height = config.coded_size().height();
  if (height >= 4000)  // ~4320p
    min_shared_memory_segment_size_ = 384 * 1024;
  else if (height >= 2000)  // ~2160p
    min_shared_memory_segment_size_ = 192 * 1024;
  else if (height >= 1000)  // ~1080p
    min_shared_memory_segment_size_ = 96 * 1024;
  else if (height >= 700)  // ~720p
    min_shared_memory_segment_size_ = 72 * 1024;
  else if (height >= 400)  // ~480p
    min_shared_memory_segment_size_ = 48 * 1024;
  else  // ~360p or less
    min_shared_memory_segment_size_ = 32 * 1024;

  if (config.is_encrypted() && !supports_deferred_initialization_) {
    DVLOG(1) << __func__
             << " Encrypted stream requires deferred initialialization.";
    bound_init_cb.Run(false);
    return;
  }

  if (previously_initialized) {
    DVLOG(3) << __func__
             << " Expecting initialized VDA to detect in-stream config change.";
    // Reinitialization with a different config (but same codec and profile).
    // VDA should handle it by detecting this in-stream by itself,
    // no need to notify it.
    bound_init_cb.Run(true);
    return;
  }

  vda_ = factories_->CreateVideoDecodeAccelerator();
  if (!vda_) {
    DVLOG(1) << "Failed to create a VDA.";
    bound_init_cb.Run(false);
    return;
  }

  if (cdm_context)
    cdm_id_ = cdm_context->GetCdmId();

  if (config.is_encrypted() && cdm_id_ == CdmContext::kInvalidCdmId) {
    DVLOG(1) << "CDM ID not available.";
    bound_init_cb.Run(false);
    return;
  }

  init_cb_ = bound_init_cb;

  const bool supports_external_output_surface = !!(
      capabilities.flags &
      VideoDecodeAccelerator::Capabilities::SUPPORTS_EXTERNAL_OUTPUT_SURFACE);
  if (supports_external_output_surface && request_overlay_info_cb_) {
    const bool requires_restart_for_external_output_surface =
        !(capabilities.flags & VideoDecodeAccelerator::Capabilities::
                                   SUPPORTS_SET_EXTERNAL_OUTPUT_SURFACE);

    // If we have a surface request callback we should call it and complete
    // initialization with the returned surface.
    request_overlay_info_cb_.Run(
        requires_restart_for_external_output_surface,
        BindToCurrentLoop(base::Bind(&GpuVideoDecoder::OnOverlayInfoAvailable,
                                     weak_factory_.GetWeakPtr())));
    overlay_info_requested_ = true;
    return;
  }

  // If external surfaces are not supported we can complete initialization now.
  CompleteInitialization(OverlayInfo());
}

// OnOverlayInfoAvailable() might be called at any time between Initialize() and
// ~GpuVideoDecoder() so we have to be careful to not make assumptions about
// the current state.
// At most one of |surface_id| and |token| should be provided.  The other will
// be kNoSurfaceID or an empty token, respectively.
void GpuVideoDecoder::OnOverlayInfoAvailable(const OverlayInfo& overlay_info) {
  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();

  if (!vda_)
    return;

  // If the VDA has not been initialized, we were waiting for the first surface
  // so it can be passed to Initialize() via the config. We can't call
  // SetSurface() before initializing because there is no remote VDA to handle
  // the call yet.
  if (!vda_initialized_) {
    CompleteInitialization(overlay_info);
    return;
  }

  // The VDA must be already initialized (or async initialization is in
  // progress) so we can call SetSurface().
  vda_->SetOverlayInfo(overlay_info);
}

void GpuVideoDecoder::CompleteInitialization(const OverlayInfo& overlay_info) {
  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
  DCHECK(vda_);
  DCHECK(init_cb_);
  DCHECK(!vda_initialized_);

  VideoDecodeAccelerator::Config vda_config;
  vda_config.profile = config_.profile();
  vda_config.cdm_id = cdm_id_;
  vda_config.overlay_info = overlay_info;
  vda_config.encryption_scheme = config_.encryption_scheme();
  vda_config.is_deferred_initialization_allowed = true;
  vda_config.initial_expected_coded_size = config_.coded_size();
  vda_config.container_color_space = config_.color_space_info();
  vda_config.target_color_space = target_color_space_;
  vda_config.hdr_metadata = config_.hdr_metadata();

#if defined(OS_ANDROID) && BUILDFLAG(USE_PROPRIETARY_CODECS)
  // We pass the SPS and PPS on Android because it lets us initialize
  // MediaCodec more reliably (http://crbug.com/649185).
  if (config_.codec() == kCodecH264)
    ExtractSpsAndPps(config_.extra_data(), &vda_config.sps, &vda_config.pps);
#endif

  vda_initialized_ = true;
  if (!vda_->Initialize(vda_config, this)) {
    DVLOG(1) << "VDA::Initialize failed.";
    // It's important to set |vda_| to null so that OnSurfaceAvailable() will
    // not call SetSurface() on a nonexistent remote VDA.
    DestroyVDA();
    std::move(init_cb_).Run(false);
    return;
  }

  // If deferred initialization is not supported, initialization is complete.
  // Otherwise, a call to NotifyInitializationComplete will follow with the
  // result of deferred initialization.
  if (!supports_deferred_initialization_)
    std::move(init_cb_).Run(true);
}

void GpuVideoDecoder::NotifyInitializationComplete(bool success) {
  DVLOG_IF(1, !success) << __func__ << " Deferred initialization failed.";

  if (init_cb_)
    std::move(init_cb_).Run(success);
}

void GpuVideoDecoder::DestroyPictureBuffers() {
  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();

  for (const auto& kv : assigned_picture_buffers_) {
    int64_t picture_buffer_id = kv.first;
    PictureBuffer::TextureIds texture_ids = kv.second.client_texture_ids();

    // Not destroying PictureBuffers in |picture_buffers_at_display_| yet, since
    // their textures may still be in use by the user of this GpuVideoDecoder.
    if (picture_buffers_at_display_.find(picture_buffer_id) ==
        picture_buffers_at_display_.end()) {
      for (uint32_t id : texture_ids)
        factories_->DeleteTexture(id);
    }
  }
  factories_->ShallowFlushCHROMIUM();
  assigned_picture_buffers_.clear();
}

void GpuVideoDecoder::DestroyVDA() {
  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();

  vda_.reset();

  DestroyPictureBuffers();
}

void GpuVideoDecoder::Decode(scoped_refptr<DecoderBuffer> buffer,
                             const DecodeCB& decode_cb) {
  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
  DCHECK(!pending_reset_cb_);

  DVLOG(3) << __func__ << " " << buffer->AsHumanReadableString();

  DecodeCB bound_decode_cb = BindToCurrentLoop(decode_cb);

  if (state_ == kError || !vda_) {
    bound_decode_cb.Run(DecodeStatus::DECODE_ERROR);
    return;
  }

  switch (state_) {
    case kDecoderDrained:
      state_ = kNormal;
      FALLTHROUGH;
    case kNormal:
      break;
    case kDrainingDecoder:
    case kError:
      NOTREACHED();
      return;
  }

  DCHECK_EQ(state_, kNormal);

  if (buffer->end_of_stream()) {
    DVLOG(3) << __func__ << " Initiating Flush for EOS.";
    state_ = kDrainingDecoder;
    eos_decode_cb_ = bound_decode_cb;
    vda_->Flush();
    return;
  }

  size_t size = buffer->data_size();
  auto shared_memory = GetSharedMemory(size);
  if (!shared_memory) {
    bound_decode_cb.Run(DecodeStatus::DECODE_ERROR);
    return;
  }

  memcpy(shared_memory->memory(), buffer->data(), size);
  // AndroidVideoDecodeAccelerator needs the timestamp to output frames in
  // presentation order.
  BitstreamBuffer bitstream_buffer(
      next_bitstream_buffer_id_, shared_memory->handle(), false /* read_only */,
      size, 0, buffer->timestamp());

  if (buffer->decrypt_config()) {
    bitstream_buffer.SetDecryptionSettings(
        buffer->decrypt_config()->key_id(), buffer->decrypt_config()->iv(),
        buffer->decrypt_config()->subsamples());
  }

  // Mask against 30 bits, to avoid (undefined) wraparound on signed integer.
  next_bitstream_buffer_id_ = (next_bitstream_buffer_id_ + 1) & 0x3FFFFFFF;
  DCHECK(
      !base::ContainsKey(bitstream_buffers_in_decoder_, bitstream_buffer.id()));
  RecordBufferData(bitstream_buffer, *buffer);

  bitstream_buffers_in_decoder_.emplace(
      bitstream_buffer.id(),
      PendingDecoderBuffer(std::move(shared_memory), decode_cb));
  DCHECK_LE(static_cast<int>(bitstream_buffers_in_decoder_.size()),
            kMaxInFlightDecodes);

  vda_->Decode(std::move(bitstream_buffer));
}

void GpuVideoDecoder::RecordBufferData(const BitstreamBuffer& bitstream_buffer,
                                       const DecoderBuffer& buffer) {
  input_buffer_data_.push_front(
      BufferData(bitstream_buffer.id(), buffer.timestamp(),
                 config_.visible_rect(), config_.natural_size()));
  // Why this value?  Because why not.  avformat.h:MAX_REORDER_DELAY is 16, but
  // that's too small for some pathological B-frame test videos.  The cost of
  // using too-high a value is low (192 bits per extra slot).
  static const size_t kMaxInputBufferDataSize = 128;
  // Pop from the back of the list, because that's the oldest and least likely
  // to be useful in the future data.
  if (input_buffer_data_.size() > kMaxInputBufferDataSize)
    input_buffer_data_.pop_back();
}

void GpuVideoDecoder::GetBufferData(int32_t id,
                                    base::TimeDelta* timestamp,
                                    gfx::Rect* visible_rect,
                                    gfx::Size* natural_size) {
  for (std::list<BufferData>::const_iterator it = input_buffer_data_.begin();
       it != input_buffer_data_.end(); ++it) {
    if (it->bitstream_buffer_id != id)
      continue;
    *timestamp = it->timestamp;
    *visible_rect = it->visible_rect;
    *natural_size = it->natural_size;
    return;
  }
  NOTREACHED() << "Missing bitstreambuffer id: " << id;
}

bool GpuVideoDecoder::NeedsBitstreamConversion() const {
  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
  return needs_bitstream_conversion_;
}

bool GpuVideoDecoder::CanReadWithoutStalling() const {
  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
  size_t available_pictures = AvailablePictures();
  return next_picture_buffer_id_ ==
             0 ||  // Decode() will ProvidePictureBuffers().
         (!needs_all_picture_buffers_to_decode_ && available_pictures > 0) ||
         available_pictures == assigned_picture_buffers_.size();
}

size_t GpuVideoDecoder::AvailablePictures() const {
  size_t ret = 0;
  for (const auto& kv : assigned_picture_buffers_) {
    if (picture_buffers_at_display_.find(kv.first) ==
        picture_buffers_at_display_.end()) {
      ++ret;
    }
  }
  return ret;
}

int GpuVideoDecoder::GetMaxDecodeRequests() const {
  return kMaxInFlightDecodes;
}

void GpuVideoDecoder::ProvidePictureBuffers(uint32_t count,
                                            VideoPixelFormat format,
                                            uint32_t textures_per_buffer,
                                            const gfx::Size& size,
                                            uint32_t texture_target) {
  DVLOG(3) << "ProvidePictureBuffers(" << count << ", " << size.width() << "x"
           << size.height() << ")";
  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();

  std::vector<uint32_t> texture_ids;
  std::vector<gpu::Mailbox> texture_mailboxes;

  if (format == PIXEL_FORMAT_UNKNOWN) {
    format = IsOpaque(config_.format()) ? PIXEL_FORMAT_XRGB : PIXEL_FORMAT_ARGB;
  }

  if (!factories_->CreateTextures(count * textures_per_buffer, size,
                                  &texture_ids, &texture_mailboxes,
                                  texture_target)) {
    NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE);
    return;
  }

  sync_token_ = factories_->CreateSyncToken();
  DCHECK_EQ(count * textures_per_buffer, texture_ids.size());
  DCHECK_EQ(count * textures_per_buffer, texture_mailboxes.size());

  if (!vda_)
    return;

  std::vector<PictureBuffer> picture_buffers;
  size_t index = 0;
  for (size_t i = 0; i < count; ++i) {
    PictureBuffer::TextureIds ids;
    std::vector<gpu::Mailbox> mailboxes;
    for (size_t j = 0; j < textures_per_buffer; j++) {
      ids.push_back(texture_ids[index]);
      mailboxes.push_back(texture_mailboxes[index]);
      index++;
    }

    picture_buffers.push_back(PictureBuffer(next_picture_buffer_id_++, size,
                                            ids, mailboxes, texture_target,
                                            format));
    bool inserted = assigned_picture_buffers_
                        .insert(std::make_pair(picture_buffers.back().id(),
                                               picture_buffers.back()))
                        .second;
    DCHECK(inserted);
  }

  vda_->AssignPictureBuffers(picture_buffers);
}

void GpuVideoDecoder::DismissPictureBuffer(int32_t id) {
  DVLOG(3) << "DismissPictureBuffer(" << id << ")";
  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();

  auto it = assigned_picture_buffers_.find(id);
  if (it == assigned_picture_buffers_.end()) {
    NOTREACHED() << "Missing picture buffer: " << id;
    return;
  }

  // If it's in |picture_buffers_at_display_|, postpone deletion of it until
  // it's returned to us.
  if (picture_buffers_at_display_.find(id) ==
      picture_buffers_at_display_.end()) {
    for (const auto texture_id : (it->second).client_texture_ids())
      factories_->DeleteTexture(texture_id);
  }

  assigned_picture_buffers_.erase(it);
}

void GpuVideoDecoder::PictureReady(const media::Picture& picture) {
  DVLOG(3) << "PictureReady()";
  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();

  auto it = assigned_picture_buffers_.find(picture.picture_buffer_id());
  if (it == assigned_picture_buffers_.end()) {
    DLOG(ERROR) << "Missing picture buffer: " << picture.picture_buffer_id();
    NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE);
    return;
  }
  PictureBuffer& pb = it->second;
  if (picture.size_changed()) {
    // Update the PictureBuffer size to match that of the Picture. Some VDA's
    // (e.g. Android) will handle resolution changes internally without
    // requesting new PictureBuffers. Sending a Picture of unmatched size is
    // the signal that we should update the size of our PictureBuffer.
    DCHECK(pb.size() != picture.visible_rect().size());
    DVLOG(3) << __func__ << " Updating size of PictureBuffer[" << pb.id()
             << "] from:" << pb.size().ToString()
             << " to:" << picture.visible_rect().size().ToString();
    pb.set_size(picture.visible_rect().size());
  }

  // Update frame's timestamp.
  base::TimeDelta timestamp;
  // Some of the VDAs like DXVA, and VTVDA don't support and thus don't provide
  // us with visible size in picture.size, passing (0, 0) instead, so for those
  // cases drop it and use config information instead.
  gfx::Rect visible_rect;
  gfx::Size natural_size;
  GetBufferData(picture.bitstream_buffer_id(), &timestamp, &visible_rect,
                &natural_size);

  double pixel_aspect_ratio = GetPixelAspectRatio(visible_rect, natural_size);
  if (!picture.visible_rect().IsEmpty()) {
    visible_rect = picture.visible_rect();
    natural_size = GetNaturalSize(visible_rect, pixel_aspect_ratio);
  }
  if (!gfx::Rect(pb.size()).Contains(visible_rect)) {
    LOG(WARNING) << "Visible size " << visible_rect.ToString()
                 << " is larger than coded size " << pb.size().ToString();
    visible_rect.Intersect(gfx::Rect(pb.size()));
    natural_size = GetNaturalSize(visible_rect, pixel_aspect_ratio);
  }

  DCHECK(pb.texture_target());

  gpu::MailboxHolder mailbox_holders[VideoFrame::kMaxPlanes];
  for (size_t i = 0; i < pb.client_texture_ids().size(); ++i) {
    mailbox_holders[i] = gpu::MailboxHolder(pb.texture_mailbox(i), sync_token_,
                                            pb.texture_target());
  }

  scoped_refptr<VideoFrame> frame(VideoFrame::WrapNativeTextures(
      pb.pixel_format(), mailbox_holders,
      // Always post ReleaseMailbox to avoid deadlock with the compositor when
      // releasing video frames on the media thread; http://crbug.com/710209.
      BindToCurrentLoop(base::Bind(
          &GpuVideoDecoder::ReleaseMailbox, weak_factory_.GetWeakPtr(),
          factories_, picture.picture_buffer_id(), pb.client_texture_ids())),
      pb.size(), visible_rect, natural_size, timestamp));
  if (!frame) {
    DLOG(ERROR) << "Create frame failed for: " << picture.picture_buffer_id();
    NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE);
    return;
  }
  frame->set_color_space(picture.color_space());
  if (picture.allow_overlay())
    frame->metadata()->SetBoolean(VideoFrameMetadata::ALLOW_OVERLAY, true);
  if (picture.read_lock_fences_enabled()) {
    frame->metadata()->SetBoolean(VideoFrameMetadata::READ_LOCK_FENCES_ENABLED,
                                  true);
  }
  if (picture.texture_owner())
    frame->metadata()->SetBoolean(VideoFrameMetadata::TEXTURE_OWNER, true);
  if (picture.wants_promotion_hint()) {
    frame->metadata()->SetBoolean(VideoFrameMetadata::WANTS_PROMOTION_HINT,
                                  true);
  }

  if (requires_texture_copy_)
    frame->metadata()->SetBoolean(VideoFrameMetadata::COPY_REQUIRED, true);

  picture_buffers_at_display_.insert(
      std::make_pair(picture.picture_buffer_id(), pb.client_texture_ids()));

  DeliverFrame(frame);
}

void GpuVideoDecoder::DeliverFrame(scoped_refptr<VideoFrame> frame) {
  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();

  // During a pending vda->Reset(), we don't accumulate frames.  Drop it on the
  // floor and return.
  if (pending_reset_cb_)
    return;

  frame->metadata()->SetBoolean(VideoFrameMetadata::POWER_EFFICIENT, true);

  output_cb_.Run(std::move(frame));
}

// static
void GpuVideoDecoder::ReleaseMailbox(
    base::WeakPtr<GpuVideoDecoder> decoder,
    media::GpuVideoAcceleratorFactories* factories,
    int64_t picture_buffer_id,
    PictureBuffer::TextureIds ids,
    const gpu::SyncToken& release_sync_token) {
  DCHECK(factories->GetTaskRunner()->BelongsToCurrentThread());
  factories->WaitSyncToken(release_sync_token);

  if (decoder) {
    decoder->ReusePictureBuffer(picture_buffer_id);
    return;
  }
  // It's the last chance to delete the texture after display,
  // because GpuVideoDecoder was destructed.
  for (uint32_t id : ids)
    factories->DeleteTexture(id);

  // Flush the delete(s) to the server, to avoid crbug.com/737992 .
  factories->ShallowFlushCHROMIUM();
}

void GpuVideoDecoder::ReusePictureBuffer(int64_t picture_buffer_id) {
  DVLOG(3) << "ReusePictureBuffer(" << picture_buffer_id << ")";
  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();

  auto iter_range = picture_buffers_at_display_.equal_range(picture_buffer_id);
  DCHECK(iter_range.first != iter_range.second);
  bool only_one_element = (std::next(iter_range.first) == iter_range.second);
  PictureBuffer::TextureIds ids = iter_range.first->second;
  picture_buffers_at_display_.erase(iter_range.first);

  if (only_one_element && assigned_picture_buffers_.find(picture_buffer_id) ==
                              assigned_picture_buffers_.end()) {
    // This picture was dismissed while in display, so we postponed deletion.
    for (const auto id : ids)
      factories_->DeleteTexture(id);
    return;
  }

  // DestroyVDA() might already have been called.
  if (vda_)
    vda_->ReusePictureBuffer(picture_buffer_id);
}

std::unique_ptr<base::SharedMemory> GpuVideoDecoder::GetSharedMemory(
    size_t min_size) {
  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
  auto it = std::lower_bound(available_shm_segments_.begin(),
                             available_shm_segments_.end(), min_size,
                             [](const ShMemEntry& entry, const size_t size) {
                               return entry.first->mapped_size() < size;
                             });
  if (it != available_shm_segments_.end()) {
    auto ret = std::move(it->first);
    available_shm_segments_.erase(it);
    return ret;
  }

  return factories_->CreateSharedMemory(
      std::max(min_shared_memory_segment_size_, min_size));
}

void GpuVideoDecoder::PutSharedMemory(
    std::unique_ptr<base::SharedMemory> shared_memory,
    int32_t last_bitstream_buffer_id) {
  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
  available_shm_segments_.emplace(std::move(shared_memory),
                                  last_bitstream_buffer_id);

  if (next_bitstream_buffer_id_ < bitstream_buffer_id_of_last_gc_ ||
      next_bitstream_buffer_id_ - bitstream_buffer_id_of_last_gc_ >
          kBufferCountBeforeGC) {
    base::EraseIf(available_shm_segments_, [this](const ShMemEntry& entry) {
      // Check for overflow rollover...
      if (next_bitstream_buffer_id_ < entry.second)
        return next_bitstream_buffer_id_ > kBufferCountBeforeGC;

      return next_bitstream_buffer_id_ - entry.second > kBufferCountBeforeGC;
    });
    bitstream_buffer_id_of_last_gc_ = next_bitstream_buffer_id_;
  }
}

void GpuVideoDecoder::NotifyEndOfBitstreamBuffer(int32_t id) {
  DVLOG(3) << "NotifyEndOfBitstreamBuffer(" << id << ")";
  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();

  auto it = bitstream_buffers_in_decoder_.find(id);
  if (it == bitstream_buffers_in_decoder_.end()) {
    NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE);
    NOTREACHED() << "Missing bitstream buffer: " << id;
    return;
  }

  PutSharedMemory(std::move(it->second.shared_memory), id);
  it->second.done_cb.Run(state_ == kError ? DecodeStatus::DECODE_ERROR
                                          : DecodeStatus::OK);
  bitstream_buffers_in_decoder_.erase(it);
}

GpuVideoDecoder::~GpuVideoDecoder() {
  DVLOG(3) << __func__;
  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();

  base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
      this);

  if (vda_)
    DestroyVDA();
  DCHECK(assigned_picture_buffers_.empty());

  if (init_cb_)
    std::move(init_cb_).Run(false);
  if (request_overlay_info_cb_ && overlay_info_requested_) {
    std::move(request_overlay_info_cb_).Run(false, ProvideOverlayInfoCB());
  }

  for (auto it = bitstream_buffers_in_decoder_.begin();
       it != bitstream_buffers_in_decoder_.end(); ++it) {
    it->second.done_cb.Run(DecodeStatus::ABORTED);
  }
  bitstream_buffers_in_decoder_.clear();

  if (pending_reset_cb_)
    std::move(pending_reset_cb_).Run();
}

void GpuVideoDecoder::NotifyFlushDone() {
  DVLOG(3) << "NotifyFlushDone()";
  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
  DCHECK_EQ(state_, kDrainingDecoder);
  state_ = kDecoderDrained;
  std::move(eos_decode_cb_).Run(DecodeStatus::OK);

  // Assume flush is for a config change, so drop shared memory segments in
  // anticipation of a resize occurring.
  available_shm_segments_.clear();
}

void GpuVideoDecoder::NotifyResetDone() {
  DVLOG(3) << "NotifyResetDone()";
  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
  DCHECK(bitstream_buffers_in_decoder_.empty());

  // This needs to happen after the Reset() on vda_ is done to ensure pictures
  // delivered during the reset can find their time data.
  input_buffer_data_.clear();

  if (pending_reset_cb_)
    std::move(pending_reset_cb_).Run();
}

void GpuVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) {
  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
  if (!vda_)
    return;

  if (init_cb_)
    std::move(init_cb_).Run(false);

  // If we have any bitstream buffers, then notify one that an error has
  // occurred.  This guarantees that somebody finds out about the error.  If
  // we don't do this, and if the max decodes are already in flight, then there
  // won't be another decode request to report the error.
  if (!bitstream_buffers_in_decoder_.empty()) {
    auto it = bitstream_buffers_in_decoder_.begin();
    it->second.done_cb.Run(DecodeStatus::DECODE_ERROR);
    bitstream_buffers_in_decoder_.erase(it);
  }

  if (state_ == kDrainingDecoder)
    std::move(eos_decode_cb_).Run(DecodeStatus::DECODE_ERROR);

  state_ = kError;

  DLOG(ERROR) << "VDA Error: " << error;
  UMA_HISTOGRAM_ENUMERATION("Media.GpuVideoDecoderError", error,
                            media::VideoDecodeAccelerator::ERROR_MAX + 1);

  DestroyVDA();
}

bool GpuVideoDecoder::OnMemoryDump(
    const base::trace_event::MemoryDumpArgs& args,
    base::trace_event::ProcessMemoryDump* pmd) {
  using base::trace_event::MemoryAllocatorDump;
  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
  if (assigned_picture_buffers_.empty())
    return false;

  if (!factories_)
    return false;
  auto* context_support = factories_->GetMediaContextProviderContextSupport();
  if (!context_support)
    return false;
  const uint64_t context_group_tracing_id =
      context_support->ShareGroupTracingGUID();

  for (const auto& picture_buffer : assigned_picture_buffers_) {
    PictureBuffer::TextureIds texture_ids =
        picture_buffer.second.client_texture_ids();

    for (uint32_t id : texture_ids) {
      const auto dump_name = base::StringPrintf(
          "gpu/video_decoding/context_group_0x%" PRIx64 "/texture_0x%" PRIX32,
          context_group_tracing_id, id);
      MemoryAllocatorDump* dump = pmd->CreateAllocatorDump(dump_name);
      dump->AddScalar(
          MemoryAllocatorDump::kNameSize, MemoryAllocatorDump::kUnitsBytes,
          static_cast<uint64_t>(picture_buffer.second.size().GetArea() * 4));

      const auto client_guid =
          GetGLTextureClientGUIDForTracing(context_group_tracing_id, id);
      pmd->CreateSharedGlobalAllocatorDump(client_guid);
      pmd->AddOwnershipEdge(dump->guid(), client_guid, 2 /* importance */);
    }
  }
  return true;
}

bool GpuVideoDecoder::IsProfileSupported(
    const VideoDecodeAccelerator::Capabilities& capabilities,
    VideoCodecProfile profile,
    const gfx::Size& coded_size,
    bool is_encrypted) {
  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
  for (const auto& supported_profile : capabilities.supported_profiles) {
    if (profile == supported_profile.profile &&
        !(supported_profile.encrypted_only && !is_encrypted) &&
        IsCodedSizeSupported(coded_size, supported_profile.min_resolution,
                             supported_profile.max_resolution)) {
      return true;
    }
  }
  return false;
}

void GpuVideoDecoder::DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent()
    const {
  DCHECK(factories_->GetTaskRunner()->BelongsToCurrentThread());
}

}  // namespace media
