// Copyright 2014 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/gpu/mac/vt_video_decode_accelerator_mac.h"

#include <CoreFoundation/CoreFoundation.h>
#include <CoreVideo/CoreVideo.h>
#include <OpenGL/CGLIOSurface.h>
#include <OpenGL/gl.h>
#include <stddef.h>

#include <algorithm>
#include <iterator>
#include <memory>

#include "base/atomic_sequence_num.h"
#include "base/bind.h"
#include "base/logging.h"
#include "base/mac/mac_logging.h"
#include "base/mac/mac_util.h"
#include "base/mac/sdk_forward_declarations.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/no_destructor.h"
#include "base/numerics/safe_conversions.h"
#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/sys_string_conversions.h"
#include "base/sys_byteorder.h"
#include "base/system/sys_info.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/memory_allocator_dump.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/process_memory_dump.h"
#include "base/version.h"
#include "components/crash/core/common/crash_key.h"
#include "components/viz/common/resources/resource_format_utils.h"
#include "gpu/command_buffer/common/gpu_memory_buffer_support.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "gpu/command_buffer/common/shared_image_usage.h"
#include "gpu/command_buffer/service/shared_image_backing_gl_image.h"
#include "gpu/command_buffer/service/shared_image_factory.h"
#include "gpu/ipc/service/shared_image_stub.h"
#include "media/base/limits.h"
#include "media/base/mac/color_space_util_mac.h"
#include "media/base/media_switches.h"
#include "media/filters/vp9_parser.h"
#include "media/gpu/mac/vp9_super_frame_bitstream_filter.h"
#include "media/gpu/mac/vt_config_util.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_image_io_surface.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/scoped_binders.h"

#define NOTIFY_STATUS(name, status, session_failure) \
  do {                                               \
    OSSTATUS_DLOG(ERROR, status) << name;            \
    NotifyError(PLATFORM_FAILURE, session_failure);  \
  } while (0)

namespace media {

namespace {

// A sequence of ids for memory tracing.
base::AtomicSequenceNumber g_memory_dump_ids;

// A sequence of shared memory ids for CVPixelBufferRefs.
base::AtomicSequenceNumber g_cv_pixel_buffer_ids;

// Only H.264 with 4:2:0 chroma sampling is supported.
constexpr VideoCodecProfile kSupportedProfiles[] = {
    H264PROFILE_BASELINE, H264PROFILE_EXTENDED, H264PROFILE_MAIN,
    H264PROFILE_HIGH,

    // These are only supported on macOS 11+.
    VP9PROFILE_PROFILE0, VP9PROFILE_PROFILE2,

    // TODO(sandersd): Hi10p fails during
    // CMVideoFormatDescriptionCreateFromH264ParameterSets with
    // kCMFormatDescriptionError_InvalidParameter.
    //
    // H264PROFILE_HIGH10PROFILE,

    // TODO(sandersd): Find and test media with these profiles before enabling.
    //
    // H264PROFILE_SCALABLEBASELINE,
    // H264PROFILE_SCALABLEHIGH,
    // H264PROFILE_STEREOHIGH,
    // H264PROFILE_MULTIVIEWHIGH,
};

// Size to use for NALU length headers in AVC format (can be 1, 2, or 4).
constexpr int kNALUHeaderLength = 4;

// We request 16 picture buffers from the client, each of which has a texture ID
// that we can bind decoded frames to. The resource requirements are low, as we
// don't need the textures to be backed by storage.
//
// The lower limit is |limits::kMaxVideoFrames + 1|, enough to have one
// composited frame plus |limits::kMaxVideoFrames| frames to satisfy preroll.
//
// However, there can be pathological behavior where VideoRendererImpl will
// continue to call Decode() as long as it is willing to queue more output
// frames, which is variable but starts at |limits::kMaxVideoFrames +
// GetMaxDecodeRequests()|. If we don't have enough picture buffers, it will
// continue to call Decode() until we stop calling NotifyEndOfBistreamBuffer(),
// which for VTVDA is when the reorder queue is full. In testing this results in
// ~20 extra frames held by VTVDA.
//
// Allocating more picture buffers than VideoRendererImpl is willing to queue
// counterintuitively reduces memory usage in this case.
constexpr int kNumPictureBuffers = limits::kMaxVideoFrames * 4;

// Maximum number of frames to queue for reordering. (Also controls the maximum
// number of in-flight frames, since NotifyEndOfBitstreamBuffer() is called when
// frames are moved into the reorder queue.)
//
// Since the maximum possible |reorder_window| is 16 for H.264, 17 is the
// minimum safe (static) size of the reorder queue.
constexpr int kMaxReorderQueueSize = 17;

// Build an |image_config| dictionary for VideoToolbox initialization.
base::ScopedCFTypeRef<CFMutableDictionaryRef> BuildImageConfig(
    CMVideoDimensions coded_dimensions,
    bool is_hbd) {
  base::ScopedCFTypeRef<CFMutableDictionaryRef> image_config;

  // Note that 4:2:0 textures cannot be used directly as RGBA in OpenGL, but are
  // lower power than 4:2:2 when composited directly by CoreAnimation.
  int32_t pixel_format = is_hbd
                             ? kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange
                             : kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange;
#define CFINT(i) CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &i)
  base::ScopedCFTypeRef<CFNumberRef> cf_pixel_format(CFINT(pixel_format));
  base::ScopedCFTypeRef<CFNumberRef> cf_width(CFINT(coded_dimensions.width));
  base::ScopedCFTypeRef<CFNumberRef> cf_height(CFINT(coded_dimensions.height));
#undef CFINT
  if (!cf_pixel_format.get() || !cf_width.get() || !cf_height.get())
    return image_config;

  image_config.reset(CFDictionaryCreateMutable(
      kCFAllocatorDefault,
      3,  // capacity
      &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
  if (!image_config.get())
    return image_config;

  CFDictionarySetValue(image_config, kCVPixelBufferPixelFormatTypeKey,
                       cf_pixel_format);
  CFDictionarySetValue(image_config, kCVPixelBufferWidthKey, cf_width);
  CFDictionarySetValue(image_config, kCVPixelBufferHeightKey, cf_height);

  return image_config;
}

// Create a CMFormatDescription using the provided |pps| and |sps|.
base::ScopedCFTypeRef<CMFormatDescriptionRef> CreateVideoFormatH264(
    const std::vector<uint8_t>& sps,
    const std::vector<uint8_t>& spsext,
    const std::vector<uint8_t>& pps) {
  DCHECK(!sps.empty());
  DCHECK(!pps.empty());

  // Build the configuration records.
  std::vector<const uint8_t*> nalu_data_ptrs;
  std::vector<size_t> nalu_data_sizes;
  nalu_data_ptrs.reserve(3);
  nalu_data_sizes.reserve(3);
  nalu_data_ptrs.push_back(&sps.front());
  nalu_data_sizes.push_back(sps.size());
  if (!spsext.empty()) {
    nalu_data_ptrs.push_back(&spsext.front());
    nalu_data_sizes.push_back(spsext.size());
  }
  nalu_data_ptrs.push_back(&pps.front());
  nalu_data_sizes.push_back(pps.size());

  // Construct a new format description from the parameter sets.
  base::ScopedCFTypeRef<CMFormatDescriptionRef> format;
  OSStatus status = CMVideoFormatDescriptionCreateFromH264ParameterSets(
      kCFAllocatorDefault,
      nalu_data_ptrs.size(),     // parameter_set_count
      &nalu_data_ptrs.front(),   // &parameter_set_pointers
      &nalu_data_sizes.front(),  // &parameter_set_sizes
      kNALUHeaderLength,         // nal_unit_header_length
      format.InitializeInto());
  OSSTATUS_DLOG_IF(WARNING, status != noErr, status)
      << "CMVideoFormatDescriptionCreateFromH264ParameterSets()";
  return format;
}

base::ScopedCFTypeRef<CMFormatDescriptionRef> CreateVideoFormatVP9(
    media::VideoColorSpace color_space,
    media::VideoCodecProfile profile,
    absl::optional<gfx::HDRMetadata> hdr_metadata,
    const gfx::Size& coded_size) {
  base::ScopedCFTypeRef<CFMutableDictionaryRef> format_config(
      CreateFormatExtensions(kCMVideoCodecType_VP9, profile, color_space,
                             hdr_metadata));

  base::ScopedCFTypeRef<CMFormatDescriptionRef> format;
  if (!format_config) {
    DLOG(ERROR) << "Failed to configure vp9 decoder.";
    return format;
  }

  OSStatus status = CMVideoFormatDescriptionCreate(
      kCFAllocatorDefault, kCMVideoCodecType_VP9, coded_size.width(),
      coded_size.height(), format_config, format.InitializeInto());
  OSSTATUS_DLOG_IF(WARNING, status != noErr, status)
      << "CMVideoFormatDescriptionCreate()";
  return format;
}

// Create a VTDecompressionSession using the provided |format|. If
// |require_hardware| is true, the session will only use the hardware decoder.
bool CreateVideoToolboxSession(
    const CMFormatDescriptionRef format,
    bool require_hardware,
    bool is_hbd,
    const VTDecompressionOutputCallbackRecord* callback,
    base::ScopedCFTypeRef<VTDecompressionSessionRef>* session,
    gfx::Size* configured_size) {
  // Prepare VideoToolbox configuration dictionaries.
  base::ScopedCFTypeRef<CFMutableDictionaryRef> decoder_config(
      CFDictionaryCreateMutable(kCFAllocatorDefault,
                                1,  // capacity
                                &kCFTypeDictionaryKeyCallBacks,
                                &kCFTypeDictionaryValueCallBacks));
  if (!decoder_config) {
    DLOG(ERROR) << "Failed to create CFMutableDictionary";
    return false;
  }

  CFDictionarySetValue(
      decoder_config,
      kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder,
      kCFBooleanTrue);
  CFDictionarySetValue(
      decoder_config,
      kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder,
      require_hardware ? kCFBooleanTrue : kCFBooleanFalse);

  // VideoToolbox scales the visible rect to the output size, so we set the
  // output size for a 1:1 ratio. (Note though that VideoToolbox does not handle
  // top or left crops correctly.) We expect the visible rect to be integral.
  CGRect visible_rect = CMVideoFormatDescriptionGetCleanAperture(format, true);
  CMVideoDimensions visible_dimensions = {
      base::ClampFloor(visible_rect.size.width),
      base::ClampFloor(visible_rect.size.height)};
  base::ScopedCFTypeRef<CFMutableDictionaryRef> image_config(
      BuildImageConfig(visible_dimensions, is_hbd));
  if (!image_config) {
    DLOG(ERROR) << "Failed to create decoder image configuration";
    return false;
  }

  OSStatus status = VTDecompressionSessionCreate(
      kCFAllocatorDefault,
      format,          // video_format_description
      decoder_config,  // video_decoder_specification
      image_config,    // destination_image_buffer_attributes
      callback,        // output_callback
      session->InitializeInto());
  if (status != noErr) {
    OSSTATUS_DLOG(WARNING, status) << "VTDecompressionSessionCreate()";
    return false;
  }

  *configured_size =
      gfx::Size(visible_rect.size.width, visible_rect.size.height);

  return true;
}

// The purpose of this function is to preload the generic and hardware-specific
// libraries required by VideoToolbox before the GPU sandbox is enabled.
// VideoToolbox normally loads the hardware-specific libraries lazily, so we
// must actually create a decompression session. If creating a decompression
// session fails, hardware decoding will be disabled (Initialize() will always
// return false).
bool InitializeVideoToolboxInternal() {
  VTDecompressionOutputCallbackRecord callback = {0};
  base::ScopedCFTypeRef<VTDecompressionSessionRef> session;
  gfx::Size configured_size;

  // Create a hardware decoding session.
  // SPS and PPS data are taken from a 480p sample (buck2.mp4).
  const std::vector<uint8_t> sps_normal = {
      0x67, 0x64, 0x00, 0x1e, 0xac, 0xd9, 0x80, 0xd4, 0x3d, 0xa1, 0x00, 0x00,
      0x03, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00, 0x30, 0x8f, 0x16, 0x2d, 0x9a};
  const std::vector<uint8_t> pps_normal = {0x68, 0xe9, 0x7b, 0xcb};
  if (!CreateVideoToolboxSession(
          CreateVideoFormatH264(sps_normal, std::vector<uint8_t>(), pps_normal),
          /*require_hardware=*/true, /*is_hbd=*/false, &callback, &session,
          &configured_size)) {
    DVLOG(1) << "Hardware H264 decoding with VideoToolbox is not supported";
    return false;
  }

  session.reset();

  // Create a software decoding session.
  // SPS and PPS data are taken from a 18p sample (small2.mp4).
  const std::vector<uint8_t> sps_small = {
      0x67, 0x64, 0x00, 0x0a, 0xac, 0xd9, 0x89, 0x7e, 0x22, 0x10, 0x00,
      0x00, 0x3e, 0x90, 0x00, 0x0e, 0xa6, 0x08, 0xf1, 0x22, 0x59, 0xa0};
  const std::vector<uint8_t> pps_small = {0x68, 0xe9, 0x79, 0x72, 0xc0};
  if (!CreateVideoToolboxSession(
          CreateVideoFormatH264(sps_small, std::vector<uint8_t>(), pps_small),
          /*require_hardware=*/false, /*is_hbd=*/false, &callback, &session,
          &configured_size)) {
    DVLOG(1) << "Software H264 decoding with VideoToolbox is not supported";
    return false;
  }

  session.reset();

  if (__builtin_available(macOS 11.0, *)) {
    VTRegisterSupplementalVideoDecoderIfAvailable(kCMVideoCodecType_VP9);

    // Create a VP9 decoding session.
    if (!CreateVideoToolboxSession(
            CreateVideoFormatVP9(VideoColorSpace::REC709(), VP9PROFILE_PROFILE0,
                                 absl::nullopt, gfx::Size(720, 480)),
            /*require_hardware=*/true, /*is_hbd=*/false, &callback, &session,
            &configured_size)) {
      DVLOG(1) << "Hardware VP9 decoding with VideoToolbox is not supported";

      // We don't return false here since VP9 support is optional.
    }
  }

  return true;
}

// TODO(sandersd): Share this computation with the VAAPI decoder.
int32_t ComputeReorderWindow(const H264SPS* sps) {
  // When |pic_order_cnt_type| == 2, decode order always matches presentation
  // order.
  // TODO(sandersd): For |pic_order_cnt_type| == 1, analyze the delta cycle to
  // find the minimum required reorder window.
  if (sps->pic_order_cnt_type == 2)
    return 0;

  // TODO(sandersd): Compute MaxDpbFrames.
  int32_t max_dpb_frames = 16;

  // See AVC spec section E.2.1 definition of |max_num_reorder_frames|.
  if (sps->vui_parameters_present_flag && sps->bitstream_restriction_flag) {
    return std::min(sps->max_num_reorder_frames, max_dpb_frames);
  } else if (sps->constraint_set3_flag) {
    if (sps->profile_idc == 44 || sps->profile_idc == 86 ||
        sps->profile_idc == 100 || sps->profile_idc == 110 ||
        sps->profile_idc == 122 || sps->profile_idc == 244) {
      return 0;
    }
  }
  return max_dpb_frames;
}

// Route decoded frame callbacks back into the VTVideoDecodeAccelerator.
void OutputThunk(void* decompression_output_refcon,
                 void* source_frame_refcon,
                 OSStatus status,
                 VTDecodeInfoFlags info_flags,
                 CVImageBufferRef image_buffer,
                 CMTime presentation_time_stamp,
                 CMTime presentation_duration) {
  VTVideoDecodeAccelerator* vda =
      reinterpret_cast<VTVideoDecodeAccelerator*>(decompression_output_refcon);
  vda->Output(source_frame_refcon, status, image_buffer);
}

}  // namespace

// Detects coded size and color space changes. Also indicates when a frame won't
// generate any output.
class VP9ConfigChangeDetector {
 public:
  VP9ConfigChangeDetector() : parser_(false) {}
  ~VP9ConfigChangeDetector() = default;

  void DetectConfig(const uint8_t* stream, unsigned int size) {
    parser_.SetStream(stream, size, nullptr);
    config_changed_ = false;

    Vp9FrameHeader fhdr;
    gfx::Size allocate_size;
    std::unique_ptr<DecryptConfig> null_config;
    while (parser_.ParseNextFrame(&fhdr, &allocate_size, &null_config) ==
           Vp9Parser::kOk) {
      color_space_ = fhdr.GetColorSpace();

      gfx::Size new_size(fhdr.frame_width, fhdr.frame_height);
      if (!size_.IsEmpty() && !pending_config_changed_ && !config_changed_ &&
          size_ != new_size) {
        pending_config_changed_ = true;
        DVLOG(1) << "Configuration changed from " << size_.ToString() << " to "
                 << new_size.ToString();
      }
      size_ = new_size;

      // Resolution changes can happen on any frame technically, so wait for a
      // keyframe before signaling the config change.
      if (fhdr.IsKeyframe() && pending_config_changed_) {
        config_changed_ = true;
        pending_config_changed_ = false;
      }
    }
    if (pending_config_changed_)
      DVLOG(1) << "Deferring config change until next keyframe...";
  }

  gfx::Size GetCodedSize(const gfx::Size& container_coded_size) const {
    return size_.IsEmpty() ? container_coded_size : size_;
  }

  VideoColorSpace GetColorSpace(const VideoColorSpace& container_cs) const {
    return container_cs.IsSpecified() ? container_cs : color_space_;
  }

  bool config_changed() const { return config_changed_; }

 private:
  gfx::Size size_;
  bool config_changed_ = false;
  bool pending_config_changed_ = false;
  VideoColorSpace color_space_;
  Vp9Parser parser_;
};

bool InitializeVideoToolbox() {
  // InitializeVideoToolbox() is called only from the GPU process main thread:
  // once for sandbox warmup, and then once each time a VTVideoDecodeAccelerator
  // is initialized. This ensures that everything is loaded whether or not the
  // sandbox is enabled.
  static const bool succeeded = InitializeVideoToolboxInternal();
  return succeeded;
}

VTVideoDecodeAccelerator::Task::Task(TaskType type) : type(type) {}

VTVideoDecodeAccelerator::Task::Task(Task&& other) = default;

VTVideoDecodeAccelerator::Task::~Task() {}

VTVideoDecodeAccelerator::Frame::Frame(int32_t bitstream_id)
    : bitstream_id(bitstream_id) {}

VTVideoDecodeAccelerator::Frame::~Frame() {}

VTVideoDecodeAccelerator::PictureInfo::PictureInfo()
    : uses_shared_images(true) {}

VTVideoDecodeAccelerator::PictureInfo::PictureInfo(uint32_t client_texture_id,
                                                   uint32_t service_texture_id)
    : uses_shared_images(false),
      client_texture_id(client_texture_id),
      service_texture_id(service_texture_id) {}

VTVideoDecodeAccelerator::PictureInfo::~PictureInfo() {}

bool VTVideoDecodeAccelerator::FrameOrder::operator()(
    const std::unique_ptr<Frame>& lhs,
    const std::unique_ptr<Frame>& rhs) const {
  // TODO(sandersd): When it is provided, use the bitstream timestamp.
  if (lhs->pic_order_cnt != rhs->pic_order_cnt)
    return lhs->pic_order_cnt > rhs->pic_order_cnt;

  // If |pic_order_cnt| is the same, fall back on using the bitstream order.
  return lhs->bitstream_id > rhs->bitstream_id;
}

VTVideoDecodeAccelerator::VTVideoDecodeAccelerator(
    const GpuVideoDecodeGLClient& gl_client,
    const gpu::GpuDriverBugWorkarounds& workarounds,
    MediaLog* media_log)
    : gl_client_(gl_client),
      workarounds_(workarounds),
      // Non media/ use cases like PPAPI may not provide a MediaLog.
      media_log_(media_log ? media_log->Clone() : nullptr),
      gpu_task_runner_(base::ThreadTaskRunnerHandle::Get()),
      decoder_task_runner_(base::ThreadPool::CreateSequencedTaskRunner(
          {base::TaskPriority::USER_VISIBLE})),
      decoder_weak_this_factory_(this),
      weak_this_factory_(this) {
  DCHECK(gl_client_.bind_image);

  callback_.decompressionOutputCallback = OutputThunk;
  callback_.decompressionOutputRefCon = this;
  decoder_weak_this_ = decoder_weak_this_factory_.GetWeakPtr();
  weak_this_ = weak_this_factory_.GetWeakPtr();

  memory_dump_id_ = g_memory_dump_ids.GetNext();
  base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
      this, "VTVideoDecodeAccelerator", gpu_task_runner_);
}

VTVideoDecodeAccelerator::~VTVideoDecodeAccelerator() {
  DVLOG(1) << __func__;
  DCHECK(gpu_task_runner_->BelongsToCurrentThread());

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

bool VTVideoDecodeAccelerator::OnMemoryDump(
    const base::trace_event::MemoryDumpArgs& args,
    base::trace_event::ProcessMemoryDump* pmd) {
  DCHECK(gpu_task_runner_->BelongsToCurrentThread());

  // Dump output pictures (decoded frames for which PictureReady() has been
  // called already).
  for (const auto& it : picture_info_map_) {
    PictureInfo* picture_info = it.second.get();
    for (const auto& gl_image : picture_info->gl_images) {
      std::string dump_name =
          base::StringPrintf("media/vt_video_decode_accelerator_%d/picture_%d",
                             memory_dump_id_, picture_info->bitstream_id);
      gl_image->OnMemoryDump(pmd, 0, dump_name);
    }
  }

  // Dump the output queue (decoded frames for which
  // NotifyEndOfBitstreamBuffer() has not been called yet).
  {
    uint64_t total_count = 0;
    uint64_t total_size = 0;
    for (const auto& it : base::GetUnderlyingContainer(task_queue_)) {
      if (it.frame.get() && it.frame->image) {
        IOSurfaceRef io_surface = CVPixelBufferGetIOSurface(it.frame->image);
        if (io_surface) {
          ++total_count;
          total_size += IOSurfaceGetAllocSize(io_surface);
        }
      }
    }
    base::trace_event::MemoryAllocatorDump* dump = pmd->CreateAllocatorDump(
        base::StringPrintf("media/vt_video_decode_accelerator_%d/output_queue",
                           memory_dump_id_));
    dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameObjectCount,
                    base::trace_event::MemoryAllocatorDump::kUnitsObjects,
                    total_count);
    dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
                    base::trace_event::MemoryAllocatorDump::kUnitsBytes,
                    total_size);
  }

  // Dump the reorder queue (decoded frames for which
  // NotifyEndOfBitstreamBuffer() has been called already).
  {
    uint64_t total_count = 0;
    uint64_t total_size = 0;
    for (const auto& it : base::GetUnderlyingContainer(reorder_queue_)) {
      if (it.get() && it->image) {
        IOSurfaceRef io_surface = CVPixelBufferGetIOSurface(it->image);
        if (io_surface) {
          ++total_count;
          total_size += IOSurfaceGetAllocSize(io_surface);
        }
      }
    }
    base::trace_event::MemoryAllocatorDump* dump = pmd->CreateAllocatorDump(
        base::StringPrintf("media/vt_video_decode_accelerator_%d/reorder_queue",
                           memory_dump_id_));
    dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameObjectCount,
                    base::trace_event::MemoryAllocatorDump::kUnitsObjects,
                    total_count);
    dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
                    base::trace_event::MemoryAllocatorDump::kUnitsBytes,
                    total_size);
  }

  return true;
}

bool VTVideoDecodeAccelerator::Initialize(const Config& config,
                                          Client* client) {
  DVLOG(1) << __func__;
  DCHECK(gpu_task_runner_->BelongsToCurrentThread());

  // All of these checks should be handled by the caller inspecting
  // SupportedProfiles(). PPAPI does not do that, however.
  if (config.output_mode != Config::OutputMode::ALLOCATE) {
    DVLOG(2) << "Output mode must be ALLOCATE";
    return false;
  }

  if (config.is_encrypted()) {
    DVLOG(2) << "Encrypted streams are not supported";
    return false;
  }

  static const base::NoDestructor<VideoDecodeAccelerator::SupportedProfiles>
      kActualSupportedProfiles(GetSupportedProfiles(workarounds_));
  if (std::find_if(kActualSupportedProfiles->begin(),
                   kActualSupportedProfiles->end(), [config](const auto& p) {
                     return p.profile == config.profile;
                   }) == kActualSupportedProfiles->end()) {
    DVLOG(2) << "Unsupported profile";
    return false;
  }

  if (!InitializeVideoToolbox()) {
    DVLOG(2) << "VideoToolbox is unavailable";
    return false;
  }

  client_ = client;
  config_ = config;

  switch (config.profile) {
    case H264PROFILE_BASELINE:
    case H264PROFILE_EXTENDED:
    case H264PROFILE_MAIN:
    case H264PROFILE_HIGH:
      codec_ = VideoCodec::kH264;
      break;
    case VP9PROFILE_PROFILE0:
    case VP9PROFILE_PROFILE2:
      codec_ = VideoCodec::kVP9;
      break;
    default:
      NOTREACHED() << "Unsupported profile.";
  };

  // Count the session as successfully initialized.
  UMA_HISTOGRAM_ENUMERATION("Media.VTVDA.SessionFailureReason",
                            SFT_SUCCESSFULLY_INITIALIZED, SFT_MAX + 1);
  return true;
}

bool VTVideoDecodeAccelerator::FinishDelayedFrames() {
  DVLOG(3) << __func__;
  DCHECK(decoder_task_runner_->RunsTasksInCurrentSequence());
  if (session_) {
    OSStatus status = VTDecompressionSessionWaitForAsynchronousFrames(session_);
    if (status) {
      NOTIFY_STATUS("VTDecompressionSessionWaitForAsynchronousFrames()", status,
                    SFT_PLATFORM_ERROR);
      return false;
    }
  }
  return true;
}

bool VTVideoDecodeAccelerator::ConfigureDecoder() {
  DVLOG(2) << __func__;
  DCHECK(decoder_task_runner_->RunsTasksInCurrentSequence());

  base::ScopedCFTypeRef<CMFormatDescriptionRef> format;
  switch (codec_) {
    case VideoCodec::kH264:
      format = CreateVideoFormatH264(active_sps_, active_spsext_, active_pps_);
      break;
    case VideoCodec::kVP9:
      format = CreateVideoFormatVP9(
          cc_detector_->GetColorSpace(config_.container_color_space),
          config_.profile, config_.hdr_metadata,
          cc_detector_->GetCodedSize(config_.initial_expected_coded_size));
      break;
    default:
      NOTREACHED() << "Unsupported codec.";
  }

  if (!format) {
    NotifyError(PLATFORM_FAILURE, SFT_PLATFORM_ERROR);
    return false;
  }

  // TODO(crbug.com/1103432): We should use
  // VTDecompressionSessionCanAcceptFormatDescription() on |format| here to
  // avoid the configuration change if possible.

  // Ensure that the old decoder emits all frames before the new decoder can
  // emit any.
  if (!FinishDelayedFrames())
    return false;

  format_ = format;
  session_.reset();

  // Note: We can always require hardware once Flash and PPAPI are gone.
  const bool require_hardware = config_.profile == VP9PROFILE_PROFILE0 ||
                                config_.profile == VP9PROFILE_PROFILE2;
  const bool is_hbd = config_.profile == VP9PROFILE_PROFILE2;
  if (!CreateVideoToolboxSession(format_, require_hardware, is_hbd, &callback_,
                                 &session_, &configured_size_)) {
    NotifyError(PLATFORM_FAILURE, SFT_PLATFORM_ERROR);
    return false;
  }

  // Report whether hardware decode is being used.
  bool using_hardware = false;
  base::ScopedCFTypeRef<CFBooleanRef> cf_using_hardware;
  if (VTSessionCopyProperty(
          session_,
          // kVTDecompressionPropertyKey_UsingHardwareAcceleratedVideoDecoder
          CFSTR("UsingHardwareAcceleratedVideoDecoder"), kCFAllocatorDefault,
          cf_using_hardware.InitializeInto()) == 0) {
    using_hardware = CFBooleanGetValue(cf_using_hardware);
  }
  UMA_HISTOGRAM_BOOLEAN("Media.VTVDA.HardwareAccelerated", using_hardware);

  if (codec_ == VideoCodec::kVP9 && !vp9_bsf_)
    vp9_bsf_ = std::make_unique<VP9SuperFrameBitstreamFilter>();

  // Record that the configuration change is complete.
  configured_sps_ = active_sps_;
  configured_spsext_ = active_spsext_;
  configured_pps_ = active_pps_;
  return true;
}

void VTVideoDecodeAccelerator::DecodeTaskVp9(
    scoped_refptr<DecoderBuffer> buffer,
    Frame* frame) {
  DVLOG(2) << __func__ << ": bit_stream=" << frame->bitstream_id
           << ", buffer=" << buffer->AsHumanReadableString();
  DCHECK(decoder_task_runner_->RunsTasksInCurrentSequence());

  if (!cc_detector_)
    cc_detector_ = std::make_unique<VP9ConfigChangeDetector>();
  cc_detector_->DetectConfig(buffer->data(), buffer->data_size());

  if (!session_ || cc_detector_->config_changed()) {
    // ConfigureDecoder() calls NotifyError() on failure.
    if (!ConfigureDecoder())
      return;
  }

  // Now that the configuration is up to date, copy it into the frame.
  frame->image_size = configured_size_;

  if (!vp9_bsf_->EnqueueBuffer(std::move(buffer))) {
    WriteToMediaLog(MediaLogMessageLevel::kERROR, "Unsupported VP9 stream");
    NotifyError(UNREADABLE_INPUT, SFT_INVALID_STREAM);
    return;
  }

  // If we have no buffer this bitstream buffer is part of a super frame that we
  // need to assemble before giving to VideoToolbox.
  auto data = vp9_bsf_->take_buffer();
  if (!data) {
    gpu_task_runner_->PostTask(
        FROM_HERE, base::BindOnce(&VTVideoDecodeAccelerator::DecodeDone,
                                  weak_this_, frame));
    return;
  }

  // Package the data in a CMSampleBuffer.
  base::ScopedCFTypeRef<CMSampleBufferRef> sample;
  OSStatus status = CMSampleBufferCreateReady(kCFAllocatorDefault,
                                              data,     // data_buffer
                                              format_,  // format_description
                                              1,        // num_samples
                                              0,  // num_sample_timing_entries
                                              nullptr,  // &sample_timing_array
                                              0,  // num_sample_size_entries
                                              nullptr,  // &sample_size_array
                                              sample.InitializeInto());
  if (status) {
    NOTIFY_STATUS("CMSampleBufferCreate()", status, SFT_PLATFORM_ERROR);
    return;
  }

  // Send the frame for decoding.
  // Asynchronous Decompression allows for parallel submission of frames
  // (without it, DecodeFrame() does not return until the frame has been
  // decoded). We don't enable Temporal Processing because we are not passing
  // timestamps anyway.
  VTDecodeFrameFlags decode_flags =
      kVTDecodeFrame_EnableAsynchronousDecompression;
  status = VTDecompressionSessionDecodeFrame(
      session_,
      sample,                          // sample_buffer
      decode_flags,                    // decode_flags
      reinterpret_cast<void*>(frame),  // source_frame_refcon
      nullptr);                        // &info_flags_out
  if (status) {
    NOTIFY_STATUS("VTDecompressionSessionDecodeFrame()", status,
                  SFT_DECODE_ERROR);
    return;
  }
}

void VTVideoDecodeAccelerator::DecodeTask(scoped_refptr<DecoderBuffer> buffer,
                                          Frame* frame) {
  DVLOG(2) << __func__ << "(" << frame->bitstream_id << ")";
  DCHECK(decoder_task_runner_->RunsTasksInCurrentSequence());

  // NALUs are stored with Annex B format in the bitstream buffer (start codes),
  // but VideoToolbox expects AVC format (length headers), so we must rewrite
  // the data.
  //
  // Locate relevant NALUs and compute the size of the rewritten data. Also
  // record parameter sets for VideoToolbox initialization.
  size_t data_size = 0;
  std::vector<H264NALU> nalus;
  parser_.SetStream(buffer->data(), buffer->data_size());
  H264NALU nalu;
  while (true) {
    H264Parser::Result result = parser_.AdvanceToNextNALU(&nalu);
    if (result == H264Parser::kEOStream)
      break;
    if (result == H264Parser::kUnsupportedStream) {
      WriteToMediaLog(MediaLogMessageLevel::kERROR, "Unsupported H.264 stream");
      NotifyError(PLATFORM_FAILURE, SFT_UNSUPPORTED_STREAM);
      return;
    }
    if (result != H264Parser::kOk) {
      WriteToMediaLog(MediaLogMessageLevel::kERROR,
                      "Failed to parse H.264 stream");
      NotifyError(UNREADABLE_INPUT, SFT_INVALID_STREAM);
      return;
    }
    switch (nalu.nal_unit_type) {
      case H264NALU::kSPS: {
        int sps_id = -1;
        result = parser_.ParseSPS(&sps_id);
        if (result == H264Parser::kUnsupportedStream) {
          WriteToMediaLog(MediaLogMessageLevel::kERROR, "Unsupported SPS");
          NotifyError(PLATFORM_FAILURE, SFT_UNSUPPORTED_STREAM);
          return;
        }
        if (result != H264Parser::kOk) {
          WriteToMediaLog(MediaLogMessageLevel::kERROR, "Could not parse SPS");
          NotifyError(UNREADABLE_INPUT, SFT_INVALID_STREAM);
          return;
        }
        seen_sps_[sps_id].assign(nalu.data, nalu.data + nalu.size);
        seen_spsext_.erase(sps_id);
        break;
      }

      case H264NALU::kSPSExt: {
        int sps_id = -1;
        result = parser_.ParseSPSExt(&sps_id);
        if (result != H264Parser::kOk) {
          WriteToMediaLog(MediaLogMessageLevel::kERROR,
                          "Could not parse SPS extension");
          NotifyError(UNREADABLE_INPUT, SFT_INVALID_STREAM);
          return;
        }
        seen_spsext_[sps_id].assign(nalu.data, nalu.data + nalu.size);
        break;
      }

      case H264NALU::kPPS: {
        int pps_id = -1;
        result = parser_.ParsePPS(&pps_id);
        if (result == H264Parser::kUnsupportedStream) {
          WriteToMediaLog(MediaLogMessageLevel::kERROR, "Unsupported PPS");
          NotifyError(PLATFORM_FAILURE, SFT_UNSUPPORTED_STREAM);
          return;
        }
        if (result != H264Parser::kOk) {
          WriteToMediaLog(MediaLogMessageLevel::kERROR, "Could not parse PPS");
          NotifyError(UNREADABLE_INPUT, SFT_INVALID_STREAM);
          return;
        }
        seen_pps_[pps_id].assign(nalu.data, nalu.data + nalu.size);
        break;
      }

      case H264NALU::kSEIMessage: {
        H264SEIMessage sei_msg;
        result = parser_.ParseSEI(&sei_msg);
        if (result == H264Parser::kOk &&
            sei_msg.type == H264SEIMessage::kSEIRecoveryPoint &&
            sei_msg.recovery_point.recovery_frame_cnt == 0) {
          // We only support immediate recovery points. Supporting future points
          // would require dropping |recovery_frame_cnt| frames when needed.
          frame->has_recovery_point = true;
        }
        nalus.push_back(nalu);
        data_size += kNALUHeaderLength + nalu.size;
        break;
      }

      case H264NALU::kSliceDataA:
      case H264NALU::kSliceDataB:
      case H264NALU::kSliceDataC:
      case H264NALU::kNonIDRSlice:
      case H264NALU::kIDRSlice:
        // Only the first slice is examined. Other slices are at least one of:
        // the same frame, not decoded, invalid.
        if (!frame->has_slice) {
          // Parse slice header.
          H264SliceHeader slice_hdr;
          result = parser_.ParseSliceHeader(nalu, &slice_hdr);
          if (result == H264Parser::kUnsupportedStream) {
            WriteToMediaLog(MediaLogMessageLevel::kERROR,
                            "Unsupported slice header");
            NotifyError(PLATFORM_FAILURE, SFT_UNSUPPORTED_STREAM);
            return;
          }
          if (result != H264Parser::kOk) {
            WriteToMediaLog(MediaLogMessageLevel::kERROR,
                            "Could not parse slice header");
            NotifyError(UNREADABLE_INPUT, SFT_INVALID_STREAM);
            return;
          }

          // Lookup SPS and PPS.
          const H264PPS* pps = parser_.GetPPS(slice_hdr.pic_parameter_set_id);
          if (!pps) {
            WriteToMediaLog(MediaLogMessageLevel::kERROR,
                            "Missing PPS referenced by slice");
            NotifyError(UNREADABLE_INPUT, SFT_INVALID_STREAM);
            return;
          }

          const H264SPS* sps = parser_.GetSPS(pps->seq_parameter_set_id);
          if (!sps) {
            WriteToMediaLog(MediaLogMessageLevel::kERROR,
                            "Missing SPS referenced by PPS");
            NotifyError(UNREADABLE_INPUT, SFT_INVALID_STREAM);
            return;
          }

          // Record the configuration.
          DCHECK(seen_pps_.count(slice_hdr.pic_parameter_set_id));
          DCHECK(seen_sps_.count(pps->seq_parameter_set_id));
          active_sps_ = seen_sps_[pps->seq_parameter_set_id];
          // Note: SPS extension lookup may create an empty entry.
          active_spsext_ = seen_spsext_[pps->seq_parameter_set_id];
          active_pps_ = seen_pps_[slice_hdr.pic_parameter_set_id];

          // Compute and store frame properties. |image_size| gets filled in
          // later, since it comes from the decoder configuration.
          absl::optional<int32_t> pic_order_cnt =
              poc_.ComputePicOrderCnt(sps, slice_hdr);
          if (!pic_order_cnt.has_value()) {
            WriteToMediaLog(MediaLogMessageLevel::kERROR,
                            "Unable to compute POC");
            NotifyError(UNREADABLE_INPUT, SFT_INVALID_STREAM);
            return;
          }

          frame->has_slice = true;
          frame->is_idr = nalu.nal_unit_type == media::H264NALU::kIDRSlice;
          frame->has_mmco5 = poc_.IsPendingMMCO5();
          frame->pic_order_cnt = *pic_order_cnt;
          frame->reorder_window = ComputeReorderWindow(sps);
        }
        FALLTHROUGH;

      default:
        nalus.push_back(nalu);
        data_size += kNALUHeaderLength + nalu.size;
        break;
    }
  }

  if (frame->is_idr || frame->has_recovery_point)
    waiting_for_idr_ = false;

  // If no IDR has been seen yet, skip decoding. Note that Flash sends
  // configuration changes as a bitstream with only SPS/PPS; we don't print
  // error messages for those.
  if (frame->has_slice && waiting_for_idr_) {
    if (!missing_idr_logged_) {
      WriteToMediaLog(MediaLogMessageLevel::kERROR,
                      ("Illegal attempt to decode without IDR. "
                       "Discarding decode requests until the next IDR."));
      missing_idr_logged_ = true;
    }
    frame->has_slice = false;
  }

  // If there is nothing to decode, drop the request by returning a frame with
  // no image.
  if (!frame->has_slice) {
    gpu_task_runner_->PostTask(
        FROM_HERE, base::BindOnce(&VTVideoDecodeAccelerator::DecodeDone,
                                  weak_this_, frame));
    return;
  }

  // Apply any configuration change, but only at an IDR. If there is no IDR, we
  // just hope for the best from the decoder.
  if (frame->is_idr &&
      (configured_sps_ != active_sps_ || configured_spsext_ != active_spsext_ ||
       configured_pps_ != active_pps_)) {
    if (active_sps_.empty()) {
      WriteToMediaLog(MediaLogMessageLevel::kERROR,
                      "Invalid configuration (no SPS)");
      NotifyError(INVALID_ARGUMENT, SFT_INVALID_STREAM);
      return;
    }
    if (active_pps_.empty()) {
      WriteToMediaLog(MediaLogMessageLevel::kERROR,
                      "Invalid configuration (no PPS)");
      NotifyError(INVALID_ARGUMENT, SFT_INVALID_STREAM);
      return;
    }

    // ConfigureDecoder() calls NotifyError() on failure.
    if (!ConfigureDecoder())
      return;
  }

  // If the session is not configured by this point, fail.
  if (!session_) {
    WriteToMediaLog(MediaLogMessageLevel::kERROR,
                    "Cannot decode without configuration");
    NotifyError(INVALID_ARGUMENT, SFT_INVALID_STREAM);
    return;
  }

  // Now that the configuration is up to date, copy it into the frame.
  frame->image_size = configured_size_;

  // Create a memory-backed CMBlockBuffer for the translated data.
  // TODO(sandersd): Pool of memory blocks.
  base::ScopedCFTypeRef<CMBlockBufferRef> data;
  OSStatus status = CMBlockBufferCreateWithMemoryBlock(
      kCFAllocatorDefault,
      nullptr,              // &memory_block
      data_size,            // block_length
      kCFAllocatorDefault,  // block_allocator
      nullptr,              // &custom_block_source
      0,                    // offset_to_data
      data_size,            // data_length
      0,                    // flags
      data.InitializeInto());
  if (status) {
    NOTIFY_STATUS("CMBlockBufferCreateWithMemoryBlock()", status,
                  SFT_PLATFORM_ERROR);
    return;
  }

  // Make sure that the memory is actually allocated.
  // CMBlockBufferReplaceDataBytes() is documented to do this, but prints a
  // message each time starting in Mac OS X 10.10.
  status = CMBlockBufferAssureBlockMemory(data);
  if (status) {
    NOTIFY_STATUS("CMBlockBufferAssureBlockMemory()", status,
                  SFT_PLATFORM_ERROR);
    return;
  }

  // Copy NALU data into the CMBlockBuffer, inserting length headers.
  size_t offset = 0;
  for (size_t i = 0; i < nalus.size(); i++) {
    H264NALU& nalu = nalus[i];
    uint32_t header = base::HostToNet32(static_cast<uint32_t>(nalu.size));
    status =
        CMBlockBufferReplaceDataBytes(&header, data, offset, kNALUHeaderLength);
    if (status) {
      NOTIFY_STATUS("CMBlockBufferReplaceDataBytes()", status,
                    SFT_PLATFORM_ERROR);
      return;
    }
    offset += kNALUHeaderLength;
    status = CMBlockBufferReplaceDataBytes(nalu.data, data, offset, nalu.size);
    if (status) {
      NOTIFY_STATUS("CMBlockBufferReplaceDataBytes()", status,
                    SFT_PLATFORM_ERROR);
      return;
    }
    offset += nalu.size;
  }

  // Package the data in a CMSampleBuffer.
  base::ScopedCFTypeRef<CMSampleBufferRef> sample;
  status = CMSampleBufferCreate(kCFAllocatorDefault,
                                data,        // data_buffer
                                true,        // data_ready
                                nullptr,     // make_data_ready_callback
                                nullptr,     // make_data_ready_refcon
                                format_,     // format_description
                                1,           // num_samples
                                0,           // num_sample_timing_entries
                                nullptr,     // &sample_timing_array
                                1,           // num_sample_size_entries
                                &data_size,  // &sample_size_array
                                sample.InitializeInto());
  if (status) {
    NOTIFY_STATUS("CMSampleBufferCreate()", status, SFT_PLATFORM_ERROR);
    return;
  }

  // Send the frame for decoding.
  // Asynchronous Decompression allows for parallel submission of frames
  // (without it, DecodeFrame() does not return until the frame has been
  // decoded). We don't enable Temporal Processing because we are not passing
  // timestamps anyway.
  VTDecodeFrameFlags decode_flags =
      kVTDecodeFrame_EnableAsynchronousDecompression;
  status = VTDecompressionSessionDecodeFrame(
      session_,
      sample,                          // sample_buffer
      decode_flags,                    // decode_flags
      reinterpret_cast<void*>(frame),  // source_frame_refcon
      nullptr);                        // &info_flags_out
  if (status) {
    NOTIFY_STATUS("VTDecompressionSessionDecodeFrame()", status,
                  SFT_DECODE_ERROR);
    return;
  }
}

// This method may be called on any VideoToolbox thread.
void VTVideoDecodeAccelerator::Output(void* source_frame_refcon,
                                      OSStatus status,
                                      CVImageBufferRef image_buffer) {
  if (status) {
    NOTIFY_STATUS("Decoding", status, SFT_DECODE_ERROR);
    return;
  }

  // The type of |image_buffer| is CVImageBuffer, but we only handle
  // CVPixelBuffers. This should be guaranteed as we set
  // kCVPixelBufferOpenGLCompatibilityKey in |image_config|.
  //
  // Sometimes, for unknown reasons (http://crbug.com/453050), |image_buffer| is
  // NULL, which causes CFGetTypeID() to crash. While the rest of the code would
  // smoothly handle NULL as a dropped frame, we choose to fail permanantly here
  // until the issue is better understood.
  if (!image_buffer || CFGetTypeID(image_buffer) != CVPixelBufferGetTypeID()) {
    DLOG(ERROR) << "Decoded frame is not a CVPixelBuffer";
    NotifyError(PLATFORM_FAILURE, SFT_DECODE_ERROR);
    return;
  }

  Frame* frame = reinterpret_cast<Frame*>(source_frame_refcon);
  frame->image.reset(image_buffer, base::scoped_policy::RETAIN);
  gpu_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&VTVideoDecodeAccelerator::DecodeDone, weak_this_, frame));
}

void VTVideoDecodeAccelerator::DecodeDone(Frame* frame) {
  DVLOG(3) << __func__ << "(" << frame->bitstream_id << ")";
  DCHECK(gpu_task_runner_->BelongsToCurrentThread());

  // pending_frames_.erase() will delete |frame|.
  int32_t bitstream_id = frame->bitstream_id;
  DCHECK_EQ(1u, pending_frames_.count(bitstream_id));

  if (state_ == STATE_ERROR || state_ == STATE_DESTROYING) {
    // Destroy() handles NotifyEndOfBitstreamBuffer().
    pending_frames_.erase(bitstream_id);
    return;
  }

  DCHECK_EQ(state_, STATE_DECODING);
  if (!frame->image.get()) {
    pending_frames_.erase(bitstream_id);
    assigned_bitstream_ids_.erase(bitstream_id);
    client_->NotifyEndOfBitstreamBuffer(bitstream_id);
    return;
  }

  Task task(TASK_FRAME);
  task.frame = std::move(pending_frames_[bitstream_id]);
  pending_frames_.erase(bitstream_id);
  task_queue_.push(std::move(task));
  ProcessWorkQueues();
}

void VTVideoDecodeAccelerator::FlushTask(TaskType type) {
  DVLOG(3) << __func__;
  DCHECK(decoder_task_runner_->RunsTasksInCurrentSequence());

  FinishDelayedFrames();

  // All the frames that are going to be sent must have been sent by now. So
  // clear any state in the bitstream filter.
  if (vp9_bsf_)
    vp9_bsf_->Flush();

  if (type == TASK_DESTROY) {
    if (session_) {
      // Destroy the decoding session before returning from the decoder thread.
      VTDecompressionSessionInvalidate(session_);
      session_.reset();
    }

    // This must be done on |decoder_task_runner_|.
    decoder_weak_this_factory_.InvalidateWeakPtrs();
  }

  // Queue a task even if flushing fails, so that destruction always completes.
  gpu_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&VTVideoDecodeAccelerator::FlushDone, weak_this_, type));
}

void VTVideoDecodeAccelerator::FlushDone(TaskType type) {
  DVLOG(3) << __func__;
  DCHECK(gpu_task_runner_->BelongsToCurrentThread());
  task_queue_.push(Task(type));
  ProcessWorkQueues();
}

void VTVideoDecodeAccelerator::Decode(BitstreamBuffer bitstream) {
  Decode(bitstream.ToDecoderBuffer(), bitstream.id());
}

void VTVideoDecodeAccelerator::Decode(scoped_refptr<DecoderBuffer> buffer,
                                      int32_t bitstream_id) {
  DVLOG(2) << __func__ << "(" << bitstream_id << ")";
  DCHECK(gpu_task_runner_->BelongsToCurrentThread());

  if (bitstream_id < 0) {
    DLOG(ERROR) << "Invalid bitstream, id: " << bitstream_id;
    NotifyError(INVALID_ARGUMENT, SFT_INVALID_STREAM);
    return;
  }

  if (!buffer) {
    client_->NotifyEndOfBitstreamBuffer(bitstream_id);
    return;
  }

  DCHECK_EQ(0u, assigned_bitstream_ids_.count(bitstream_id));
  assigned_bitstream_ids_.insert(bitstream_id);

  Frame* frame = new Frame(bitstream_id);
  pending_frames_[bitstream_id] = base::WrapUnique(frame);

  if (codec_ == VideoCodec::kVP9) {
    decoder_task_runner_->PostTask(
        FROM_HERE,
        base::BindOnce(&VTVideoDecodeAccelerator::DecodeTaskVp9,
                       decoder_weak_this_, std::move(buffer), frame));
  } else {
    decoder_task_runner_->PostTask(
        FROM_HERE,
        base::BindOnce(&VTVideoDecodeAccelerator::DecodeTask,
                       decoder_weak_this_, std::move(buffer), frame));
  }
}

void VTVideoDecodeAccelerator::AssignPictureBuffers(
    const std::vector<PictureBuffer>& pictures) {
  DVLOG(1) << __func__;
  DCHECK(gpu_task_runner_->BelongsToCurrentThread());

  for (const PictureBuffer& picture : pictures) {
    DVLOG(3) << "AssignPictureBuffer(" << picture.id() << ")";
    DCHECK(!picture_info_map_.count(picture.id()));
    assigned_picture_ids_.insert(picture.id());
    available_picture_ids_.push_back(picture.id());
    if (picture.client_texture_ids().empty() &&
        picture.service_texture_ids().empty()) {
      picture_info_map_.insert(
          std::make_pair(picture.id(), std::make_unique<PictureInfo>()));
    } else {
      DCHECK_LE(1u, picture.client_texture_ids().size());
      DCHECK_LE(1u, picture.service_texture_ids().size());
      picture_info_map_.insert(std::make_pair(
          picture.id(),
          std::make_unique<PictureInfo>(picture.client_texture_ids()[0],
                                        picture.service_texture_ids()[0])));
    }
  }

  // Pictures are not marked as uncleared until after this method returns, and
  // they will be broken if they are used before that happens. So, schedule
  // future work after that happens.
  gpu_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&VTVideoDecodeAccelerator::ProcessWorkQueues, weak_this_));
}

void VTVideoDecodeAccelerator::ReusePictureBuffer(int32_t picture_id) {
  DVLOG(2) << __func__ << "(" << picture_id << ")";
  DCHECK(gpu_task_runner_->BelongsToCurrentThread());

  // It's possible there was a ReusePictureBuffer() request in flight when we
  // called DismissPictureBuffer(), in which case we won't find it. In that case
  // we should just drop the ReusePictureBuffer() request.
  auto it = picture_info_map_.find(picture_id);
  if (it == picture_info_map_.end())
    return;

  // Drop references to allow the underlying buffer to be released.
  PictureInfo* picture_info = it->second.get();
  if (picture_info->uses_shared_images) {
    picture_info->scoped_shared_images.clear();
  } else {
    gl_client_.bind_image.Run(picture_info->client_texture_id,
                              gpu::GetPlatformSpecificTextureTarget(), nullptr,
                              false);
  }
  picture_info->gl_images.clear();
  picture_info->bitstream_id = 0;

  // Mark the picture as available and try to complete pending output work.
  DCHECK(assigned_picture_ids_.count(picture_id));
  available_picture_ids_.push_back(picture_id);
  ProcessWorkQueues();
}

void VTVideoDecodeAccelerator::ProcessWorkQueues() {
  DVLOG(3) << __func__;
  DCHECK(gpu_task_runner_->BelongsToCurrentThread());
  switch (state_) {
    case STATE_DECODING:
      if (codec_ != VideoCodec::kH264) {
        while (state_ == STATE_DECODING) {
          if (!ProcessOutputQueue() && !ProcessTaskQueue())
            break;
        }
        return;
      }

      // TODO(sandersd): Batch where possible.
      while (state_ == STATE_DECODING) {
        if (!ProcessReorderQueue() && !ProcessTaskQueue())
          break;
      }
      return;

    case STATE_ERROR:
      // Do nothing until Destroy() is called.
      return;

    case STATE_DESTROYING:
      // Drop tasks until we are ready to destruct.
      while (!task_queue_.empty()) {
        if (task_queue_.front().type == TASK_DESTROY) {
          delete this;
          return;
        }
        task_queue_.pop();
      }
      return;
  }
}

bool VTVideoDecodeAccelerator::ProcessTaskQueue() {
  DVLOG(3) << __func__ << " size=" << task_queue_.size();
  DCHECK(gpu_task_runner_->BelongsToCurrentThread());
  DCHECK_EQ(state_, STATE_DECODING);

  if (task_queue_.empty())
    return false;

  Task& task = task_queue_.front();
  switch (task.type) {
    case TASK_FRAME: {
      if (codec_ == VideoCodec::kVP9) {
        // Once we've reached our maximum output queue size, defer end of
        // bitstream buffer signals to avoid piling up too many frames.
        if (output_queue_.size() >= limits::kMaxVideoFrames)
          return false;

        assigned_bitstream_ids_.erase(task.frame->bitstream_id);
        client_->NotifyEndOfBitstreamBuffer(task.frame->bitstream_id);
        output_queue_.push_back(std::move(task.frame));
        task_queue_.pop();
        return true;
      }

      bool reorder_queue_has_space =
          reorder_queue_.size() < kMaxReorderQueueSize;
      bool reorder_queue_flush_needed =
          task.frame->is_idr || task.frame->has_mmco5;
      bool reorder_queue_flush_done = reorder_queue_.empty();
      if (reorder_queue_has_space &&
          (!reorder_queue_flush_needed || reorder_queue_flush_done)) {
        DVLOG(2) << "Decode(" << task.frame->bitstream_id << ") complete";
        assigned_bitstream_ids_.erase(task.frame->bitstream_id);
        client_->NotifyEndOfBitstreamBuffer(task.frame->bitstream_id);
        reorder_queue_.push(std::move(task.frame));
        task_queue_.pop();
        return true;
      }
      return false;
    }

    case TASK_FLUSH:
      DCHECK_EQ(task.type, pending_flush_tasks_.front());
      if ((codec_ == VideoCodec::kH264 && reorder_queue_.size() == 0) ||
          (codec_ == VideoCodec::kVP9 && output_queue_.empty())) {
        DVLOG(1) << "Flush complete";
        pending_flush_tasks_.pop();
        client_->NotifyFlushDone();
        task_queue_.pop();
        return true;
      }
      return false;

    case TASK_RESET:
      DCHECK_EQ(task.type, pending_flush_tasks_.front());
      if ((codec_ == VideoCodec::kH264 && reorder_queue_.size() == 0) ||
          (codec_ == VideoCodec::kVP9 && output_queue_.empty())) {
        DVLOG(1) << "Reset complete";
        waiting_for_idr_ = true;
        pending_flush_tasks_.pop();
        client_->NotifyResetDone();
        task_queue_.pop();
        return true;
      }
      return false;

    case TASK_DESTROY:
      NOTREACHED() << "Can't destroy while in STATE_DECODING";
      NotifyError(ILLEGAL_STATE, SFT_PLATFORM_ERROR);
      return false;
  }
}

bool VTVideoDecodeAccelerator::ProcessReorderQueue() {
  DCHECK(gpu_task_runner_->BelongsToCurrentThread());
  DCHECK_EQ(state_, STATE_DECODING);

  if (reorder_queue_.empty())
    return false;

  // If the next task is a flush (because there is a pending flush or because
  // the next frame is an IDR), then we don't need a full reorder buffer to send
  // the next frame.
  bool flushing =
      !task_queue_.empty() && (task_queue_.front().type != TASK_FRAME ||
                               task_queue_.front().frame->is_idr ||
                               task_queue_.front().frame->has_mmco5);

  size_t reorder_window = std::max(0, reorder_queue_.top()->reorder_window);
  DVLOG(3) << __func__ << " size=" << reorder_queue_.size()
           << " window=" << reorder_window << " flushing=" << flushing;
  if (flushing || reorder_queue_.size() > reorder_window) {
    if (ProcessFrame(*reorder_queue_.top())) {
      reorder_queue_.pop();
      return true;
    }
  }

  return false;
}

bool VTVideoDecodeAccelerator::ProcessOutputQueue() {
  DCHECK(gpu_task_runner_->BelongsToCurrentThread());
  DCHECK_EQ(state_, STATE_DECODING);

  if (output_queue_.empty())
    return false;

  if (ProcessFrame(*output_queue_.front())) {
    output_queue_.pop_front();
    return true;
  }

  return false;
}

bool VTVideoDecodeAccelerator::ProcessFrame(const Frame& frame) {
  DVLOG(3) << __func__ << "(" << frame.bitstream_id << ")";
  DCHECK(gpu_task_runner_->BelongsToCurrentThread());
  DCHECK_EQ(state_, STATE_DECODING);

  // If the next pending flush is for a reset, then the frame will be dropped.
  bool resetting = !pending_flush_tasks_.empty() &&
                   pending_flush_tasks_.front() == TASK_RESET;
  if (resetting)
    return true;

  DCHECK(frame.image.get());
  // If the |image_size| has changed, request new picture buffers and then
  // wait for them.
  //
  // TODO(sandersd): When used by GpuVideoDecoder, we don't need to bother
  // with this. We can tell that is the case when we also have a timestamp.
  if (picture_size_ != frame.image_size) {
    // Dismiss current pictures.
    for (int32_t picture_id : assigned_picture_ids_) {
      DVLOG(3) << "DismissPictureBuffer(" << picture_id << ")";
      client_->DismissPictureBuffer(picture_id);
    }
    assigned_picture_ids_.clear();
    picture_info_map_.clear();
    available_picture_ids_.clear();

    // Request new pictures.
    picture_size_ = frame.image_size;

    // TODO(https://crbug.com/1210994): Remove XRGB support, and expose only
    // PIXEL_FORMAT_NV12 and PIXEL_FORMAT_YUV420P10.
    picture_format_ = PIXEL_FORMAT_XRGB;
    if (base::FeatureList::IsEnabled(kMultiPlaneVideoToolboxSharedImages)) {
      // TODO(https://crbug.com/1233228): The UV planes of P010 frames cannot
      // be represented in the current gfx::BufferFormat.
      if (config_.profile != VP9PROFILE_PROFILE2)
        picture_format_ = PIXEL_FORMAT_NV12;
    }

    DVLOG(3) << "ProvidePictureBuffers(" << kNumPictureBuffers
             << frame.image_size.ToString() << ")";
    client_->ProvidePictureBuffers(kNumPictureBuffers, picture_format_, 1,
                                   frame.image_size,
                                   gpu::GetPlatformSpecificTextureTarget());
    return false;
  }
  return SendFrame(frame);
}

bool VTVideoDecodeAccelerator::SendFrame(const Frame& frame) {
  DVLOG(2) << __func__ << "(" << frame.bitstream_id << ")";
  DCHECK(gpu_task_runner_->BelongsToCurrentThread());
  DCHECK_EQ(state_, STATE_DECODING);
  DCHECK(frame.image.get());

  if (available_picture_ids_.empty())
    return false;

  int32_t picture_id = available_picture_ids_.back();
  auto it = picture_info_map_.find(picture_id);
  DCHECK(it != picture_info_map_.end());
  PictureInfo* picture_info = it->second.get();
  DCHECK(picture_info->gl_images.empty());

  const gfx::BufferFormat buffer_format =
      config_.profile == VP9PROFILE_PROFILE2
          ? gfx::BufferFormat::P010
          : gfx::BufferFormat::YUV_420_BIPLANAR;
  gfx::ColorSpace color_space = GetImageBufferColorSpace(frame.image);

  std::vector<gfx::BufferPlane> planes;
  switch (picture_format_) {
    case PIXEL_FORMAT_NV12:
    case PIXEL_FORMAT_YUV420P10:
      planes.push_back(gfx::BufferPlane::Y);
      planes.push_back(gfx::BufferPlane::UV);
      break;
    case PIXEL_FORMAT_XRGB:
      planes.push_back(gfx::BufferPlane::DEFAULT);
      break;
    default:
      NOTREACHED();
      break;
  }

  for (size_t plane = 0; plane < planes.size(); ++plane) {
    const gfx::Size plane_size(
        CVPixelBufferGetWidthOfPlane(frame.image.get(), plane),
        CVPixelBufferGetHeightOfPlane(frame.image.get(), plane));
    gfx::BufferFormat plane_buffer_format =
        gpu::GetPlaneBufferFormat(planes[plane], buffer_format);
    // TODO(https://crbug.com/1108909): BGRA is not an appropriate value for
    // these parameters.
    const viz::ResourceFormat viz_resource_format =
        (picture_format_ == PIXEL_FORMAT_XRGB)
            ? viz::ResourceFormat::BGRA_8888
            : viz::GetResourceFormat(plane_buffer_format);
    const GLenum gl_format = viz::GLDataFormat(viz_resource_format);

    scoped_refptr<gl::GLImageIOSurface> gl_image(
        gl::GLImageIOSurface::Create(plane_size, gl_format));
    if (!gl_image->InitializeWithCVPixelBuffer(
            frame.image.get(), plane,
            gfx::GenericSharedMemoryId(g_cv_pixel_buffer_ids.GetNext()),
            plane_buffer_format)) {
      NOTIFY_STATUS("Failed to initialize GLImageIOSurface", PLATFORM_FAILURE,
                    SFT_PLATFORM_ERROR);
    }
    gl_image->DisableInUseByWindowServer();
    gl_image->SetColorSpaceForYUVToRGBConversion(color_space);
    gl_image->SetColorSpaceShallow(color_space);

    if (picture_info->uses_shared_images) {
      gpu::SharedImageStub* shared_image_stub = client_->GetSharedImageStub();
      DCHECK(shared_image_stub);
      const uint32_t shared_image_usage =
          gpu::SHARED_IMAGE_USAGE_DISPLAY | gpu::SHARED_IMAGE_USAGE_SCANOUT;
      gpu::Mailbox mailbox = gpu::Mailbox::GenerateForSharedImage();

      gpu::SharedImageBackingGLCommon::InitializeGLTextureParams gl_params;
      // ANGLE-on-Metal exposes IOSurfaces via GL_TEXTURE_2D. Be robust to that.
      gl_params.target = gl_client_.supports_arb_texture_rectangle
                             ? GL_TEXTURE_RECTANGLE_ARB
                             : GL_TEXTURE_2D;
      gl_params.internal_format = gl_format;
      gl_params.format = gl_format;
      gl_params.type = GL_UNSIGNED_BYTE;
      gl_params.is_cleared = true;
      gpu::SharedImageBackingGLCommon::UnpackStateAttribs gl_attribs;

      // A GL texture id is needed to create the legacy mailbox, which requires
      // that the GL context be made current.
      const bool kCreateLegacyMailbox = true;
      if (!gl_client_.make_context_current.Run()) {
        DLOG(ERROR) << "Failed to make context current";
        NotifyError(PLATFORM_FAILURE, SFT_PLATFORM_ERROR);
        return false;
      }

      auto shared_image = std::make_unique<gpu::SharedImageBackingGLImage>(
          gl_image, mailbox, viz_resource_format, plane_size, color_space,
          kTopLeft_GrSurfaceOrigin, kOpaque_SkAlphaType, shared_image_usage,
          gl_params, gl_attribs, gl_client_.is_passthrough);

      const bool success = shared_image_stub->factory()->RegisterBacking(
          std::move(shared_image), kCreateLegacyMailbox);
      if (!success) {
        DLOG(ERROR) << "Failed to register shared image";
        NotifyError(PLATFORM_FAILURE, SFT_PLATFORM_ERROR);
        return false;
      }

      // Wrap the destroy callback in a lambda that ensures that it be called on
      // the appropriate thread.
      auto destroy_shared_image_lambda =
          [](gpu::SharedImageStub::SharedImageDestructionCallback callback,
             scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
            task_runner->PostTask(FROM_HERE, base::BindOnce(std::move(callback),
                                                            gpu::SyncToken()));
          };
      auto destroy_shared_image_callback = base::BindOnce(
          destroy_shared_image_lambda,
          shared_image_stub->GetSharedImageDestructionCallback(mailbox),
          gpu_task_runner_);
      picture_info->scoped_shared_images.push_back(
          scoped_refptr<Picture::ScopedSharedImage>(
              new Picture::ScopedSharedImage(
                  mailbox, gl_params.target,
                  std::move(destroy_shared_image_callback))));
    } else {
      if (!gl_client_.bind_image.Run(picture_info->client_texture_id,
                                     gpu::GetPlatformSpecificTextureTarget(),
                                     gl_image, false)) {
        DLOG(ERROR) << "Failed to bind image";
        NotifyError(PLATFORM_FAILURE, SFT_PLATFORM_ERROR);
        return false;
      }
    }
    picture_info->gl_images.push_back(gl_image);
  }
  picture_info->bitstream_id = frame.bitstream_id;
  available_picture_ids_.pop_back();

  DVLOG(3) << "PictureReady(picture_id=" << picture_id << ", "
           << "bitstream_id=" << frame.bitstream_id << ")";
  Picture picture(picture_id, frame.bitstream_id, gfx::Rect(frame.image_size),
                  color_space, true);
  // The GLImageIOSurface keeps the IOSurface alive as long as it exists, but
  // bound textures do not, and they can outlive the GLImageIOSurface if they
  // are deleted in the command buffer before they are used by the platform GL
  // implementation. (https://crbug.com/930479#c69)
  //
  // A fence is required whenever a GLImage is bound, but we can't know in
  // advance whether that will happen.
  //
  // TODO(sandersd): Can GLImageIOSurface be responsible for fences, so that
  // we don't need to use them when the image is never bound? Bindings are
  // typically only created when WebGL is in use.
  picture.set_read_lock_fences_enabled(true);
  for (size_t plane = 0; plane < planes.size(); ++plane) {
    picture.set_scoped_shared_image(picture_info->scoped_shared_images[plane],
                                    plane);
  }
  client_->PictureReady(std::move(picture));
  return true;
}

void VTVideoDecodeAccelerator::NotifyError(
    Error vda_error_type,
    VTVDASessionFailureType session_failure_type) {
  DCHECK_LT(session_failure_type, SFT_MAX + 1);
  if (!gpu_task_runner_->BelongsToCurrentThread()) {
    gpu_task_runner_->PostTask(
        FROM_HERE,
        base::BindOnce(&VTVideoDecodeAccelerator::NotifyError, weak_this_,
                       vda_error_type, session_failure_type));
  } else if (state_ == STATE_DECODING) {
    state_ = STATE_ERROR;
    UMA_HISTOGRAM_ENUMERATION("Media.VTVDA.SessionFailureReason",
                              session_failure_type, SFT_MAX + 1);
    client_->NotifyError(vda_error_type);
  }
}

void VTVideoDecodeAccelerator::WriteToMediaLog(MediaLogMessageLevel level,
                                               const std::string& message) {
  if (!gpu_task_runner_->BelongsToCurrentThread()) {
    gpu_task_runner_->PostTask(
        FROM_HERE, base::BindOnce(&VTVideoDecodeAccelerator::WriteToMediaLog,
                                  weak_this_, level, message));
    return;
  }

  DVLOG(1) << __func__ << "(" << static_cast<int>(level) << ") " << message;

  if (media_log_)
    media_log_->AddMessage(level, message);
}

void VTVideoDecodeAccelerator::QueueFlush(TaskType type) {
  DCHECK(gpu_task_runner_->BelongsToCurrentThread());
  pending_flush_tasks_.push(type);
  decoder_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&VTVideoDecodeAccelerator::FlushTask,
                                decoder_weak_this_, type));

  // If this is a new flush request, see if we can make progress.
  if (pending_flush_tasks_.size() == 1)
    ProcessWorkQueues();
}

void VTVideoDecodeAccelerator::Flush() {
  DVLOG(1) << __func__;
  DCHECK(gpu_task_runner_->BelongsToCurrentThread());
  QueueFlush(TASK_FLUSH);
}

void VTVideoDecodeAccelerator::Reset() {
  DVLOG(1) << __func__;
  DCHECK(gpu_task_runner_->BelongsToCurrentThread());
  QueueFlush(TASK_RESET);
}

void VTVideoDecodeAccelerator::Destroy() {
  DVLOG(1) << __func__;
  DCHECK(gpu_task_runner_->BelongsToCurrentThread());

  // For a graceful shutdown, return assigned buffers and flush before
  // destructing |this|.
  for (int32_t bitstream_id : assigned_bitstream_ids_)
    client_->NotifyEndOfBitstreamBuffer(bitstream_id);
  assigned_bitstream_ids_.clear();
  state_ = STATE_DESTROYING;
  QueueFlush(TASK_DESTROY);
}

bool VTVideoDecodeAccelerator::TryToSetupDecodeOnSeparateThread(
    const base::WeakPtr<Client>& decode_client,
    const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) {
  return false;
}

bool VTVideoDecodeAccelerator::SupportsSharedImagePictureBuffers() const {
  return true;
}

VideoDecodeAccelerator::TextureAllocationMode
VTVideoDecodeAccelerator::GetSharedImageTextureAllocationMode() const {
  return VideoDecodeAccelerator::TextureAllocationMode::
      kDoNotAllocateGLTextures;
}

// static
VideoDecodeAccelerator::SupportedProfiles
VTVideoDecodeAccelerator::GetSupportedProfiles(
    const gpu::GpuDriverBugWorkarounds& workarounds) {
  SupportedProfiles profiles;
  if (!InitializeVideoToolbox())
    return profiles;

  for (const auto& supported_profile : kSupportedProfiles) {
    if (supported_profile == VP9PROFILE_PROFILE0 ||
        supported_profile == VP9PROFILE_PROFILE2) {
      if (workarounds.disable_accelerated_vp9_decode)
        continue;
      if (!base::mac::IsAtLeastOS11())
        continue;
      if (__builtin_available(macOS 10.13, *)) {
        if ((supported_profile == VP9PROFILE_PROFILE0 ||
             supported_profile == VP9PROFILE_PROFILE2) &&
            !VTIsHardwareDecodeSupported(kCMVideoCodecType_VP9)) {
          continue;
        }

        // Success! We have VP9 hardware decoding support.
      } else {
        continue;
      }
    }

    SupportedProfile profile;
    profile.profile = supported_profile;
    profile.min_resolution.SetSize(16, 16);
    profile.max_resolution.SetSize(4096, 4096);
    profiles.push_back(profile);
  }
  return profiles;
}

}  // namespace media
