// Copyright 2017 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/windows/d3d11_video_decoder.h"

#include <d3d11_4.h>
#include <memory>

#include "base/bind.h"
#include "base/callback.h"
#include "base/feature_list.h"
#include "base/memory/ref_counted_delete_on_sequence.h"
#include "base/metrics/histogram_macros.h"
#include "gpu/config/gpu_finch_features.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/video_codecs.h"
#include "media/base/video_decoder_config.h"
#include "media/base/video_frame.h"
#include "media/base/video_util.h"
#include "media/gpu/windows/d3d11_picture_buffer.h"
#include "media/gpu/windows/d3d11_video_context_wrapper.h"
#include "media/gpu/windows/d3d11_video_decoder_impl.h"
#include "ui/gl/gl_angle_util_win.h"

namespace media {

namespace {

#define INRANGE(_profile, codecname) \
  (_profile >= codecname##PROFILE_MIN && _profile <= codecname##PROFILE_MAX)

bool IsVP9(const VideoDecoderConfig& config) {
  return INRANGE(config.profile(), VP9);
}

bool IsH264(const VideoDecoderConfig& config) {
  return INRANGE(config.profile(), H264);
}

#undef INRANGE

// Holder class, so that we don't keep creating CommandBufferHelpers every time
// somebody calls a callback.  We can't actually create it until we're on the
// right thread.
struct CommandBufferHelperHolder
    : base::RefCountedDeleteOnSequence<CommandBufferHelperHolder> {
  CommandBufferHelperHolder(
      scoped_refptr<base::SequencedTaskRunner> task_runner)
      : base::RefCountedDeleteOnSequence<CommandBufferHelperHolder>(
            std::move(task_runner)) {}
  scoped_refptr<CommandBufferHelper> helper;

 private:
  ~CommandBufferHelperHolder() = default;
  friend class base::RefCountedDeleteOnSequence<CommandBufferHelperHolder>;
  friend class base::DeleteHelper<CommandBufferHelperHolder>;

  DISALLOW_COPY_AND_ASSIGN(CommandBufferHelperHolder);
};

scoped_refptr<CommandBufferHelper> CreateCommandBufferHelper(
    base::RepeatingCallback<gpu::CommandBufferStub*()> get_stub_cb,
    scoped_refptr<CommandBufferHelperHolder> holder) {
  gpu::CommandBufferStub* stub = get_stub_cb.Run();
  if (!stub)
    return nullptr;

  DCHECK(holder);
  if (!holder->helper)
    holder->helper = CommandBufferHelper::Create(stub);

  return holder->helper;
}

}  // namespace

std::unique_ptr<VideoDecoder> D3D11VideoDecoder::Create(
    scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
    std::unique_ptr<MediaLog> media_log,
    const gpu::GpuPreferences& gpu_preferences,
    const gpu::GpuDriverBugWorkarounds& gpu_workarounds,
    base::RepeatingCallback<gpu::CommandBufferStub*()> get_stub_cb,
    D3D11VideoDecoder::GetD3D11DeviceCB get_d3d11_device_cb,
    SupportedConfigs supported_configs) {
  // We create |impl_| on the wrong thread, but we never use it here.
  // Note that the output callback will hop to our thread, post the video
  // frame, and along with a callback that will hop back to the impl thread
  // when it's released.
  // Note that we WrapUnique<VideoDecoder> rather than D3D11VideoDecoder to make
  // this castable; the deleters have to match.
  std::unique_ptr<MediaLog> cloned_media_log = media_log->Clone();
  auto get_helper_cb =
      base::BindRepeating(CreateCommandBufferHelper, std::move(get_stub_cb),
                          scoped_refptr<CommandBufferHelperHolder>(
                              new CommandBufferHelperHolder(gpu_task_runner)));
  return base::WrapUnique<VideoDecoder>(
      new D3D11VideoDecoder(std::move(gpu_task_runner), std::move(media_log),
                            gpu_preferences, gpu_workarounds,
                            std::make_unique<D3D11VideoDecoderImpl>(
                                std::move(cloned_media_log), get_helper_cb),
                            get_helper_cb, std::move(get_d3d11_device_cb),
                            std::move(supported_configs)));
}

D3D11VideoDecoder::D3D11VideoDecoder(
    scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
    std::unique_ptr<MediaLog> media_log,
    const gpu::GpuPreferences& gpu_preferences,
    const gpu::GpuDriverBugWorkarounds& gpu_workarounds,
    std::unique_ptr<D3D11VideoDecoderImpl> impl,
    base::RepeatingCallback<scoped_refptr<CommandBufferHelper>()> get_helper_cb,
    GetD3D11DeviceCB get_d3d11_device_cb,
    SupportedConfigs supported_configs)
    : media_log_(std::move(media_log)),
      impl_(std::move(impl)),
      impl_task_runner_(std::move(gpu_task_runner)),
      gpu_preferences_(gpu_preferences),
      gpu_workarounds_(gpu_workarounds),
      get_d3d11_device_cb_(std::move(get_d3d11_device_cb)),
      get_helper_cb_(std::move(get_helper_cb)),
      supported_configs_(std::move(supported_configs)),
      weak_factory_(this) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(media_log_);

  impl_weak_ = impl_->GetWeakPtr();
}

D3D11VideoDecoder::~D3D11VideoDecoder() {
  // Post destruction to the main thread.  When this executes, it will also
  // cancel pending callbacks into |impl_| via |impl_weak_|.  Callbacks out
  // from |impl_| will be cancelled by |weak_factory_| when we return.
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  if (impl_task_runner_->RunsTasksInCurrentSequence())
    impl_.reset();
  else
    impl_task_runner_->DeleteSoon(FROM_HERE, std::move(impl_));

  // Explicitly destroy the decoder, since it can reference picture buffers.
  accelerated_video_decoder_.reset();
}

std::string D3D11VideoDecoder::GetDisplayName() const {
  return "D3D11VideoDecoder";
}

HRESULT D3D11VideoDecoder::InitializeAcceleratedDecoder(
    const VideoDecoderConfig& config,
    CdmProxyContext* proxy_context,
    Microsoft::WRL::ComPtr<ID3D11VideoDecoder> video_decoder) {
  // If we got an 11.1 D3D11 Device, we can use a |ID3D11VideoContext1|,
  // otherwise we have to make sure we only use a |ID3D11VideoContext|.
  HRESULT hr;

  // |device_context_| is the primary display context, but currently
  // we share it for decoding purposes.
  auto video_context = VideoContextWrapper::CreateWrapper(usable_feature_level_,
                                                          device_context_, &hr);

  if (!SUCCEEDED(hr))
    return hr;

  if (IsVP9(config)) {
    accelerated_video_decoder_ = std::make_unique<VP9Decoder>(
        std::make_unique<D3D11VP9Accelerator>(
            this, media_log_.get(), proxy_context, video_decoder, video_device_,
            std::move(video_context)),
        config.color_space_info());
    return hr;
  }

  if (IsH264(config)) {
    accelerated_video_decoder_ = std::make_unique<H264Decoder>(
        std::make_unique<D3D11H264Accelerator>(
            this, media_log_.get(), proxy_context, video_decoder, video_device_,
            std::move(video_context)),
        config.color_space_info());
    return hr;
  }

  return E_FAIL;
}

bool D3D11VideoDecoder::DeviceHasDecoderID(GUID decoder_guid) {
  UINT index = video_device_->GetVideoDecoderProfileCount();
  while (index-- > 0) {
    GUID profile = {};
    if (SUCCEEDED(video_device_->GetVideoDecoderProfile(index, &profile))) {
      if (profile == decoder_guid)
        return true;
    }
  }
  return false;
}

GUID D3D11VideoDecoder::GetD3D11DecoderGUID(const VideoDecoderConfig& config) {
  if (IsVP9(config))
    return D3D11_DECODER_PROFILE_VP9_VLD_PROFILE0;

  if (IsH264(config))
    return D3D11_DECODER_PROFILE_H264_VLD_NOFGT;

  return {};
}

void D3D11VideoDecoder::Initialize(const VideoDecoderConfig& config,
                                   bool low_delay,
                                   CdmContext* cdm_context,
                                   const InitCB& init_cb,
                                   const OutputCB& output_cb,
                                   const WaitingCB& waiting_cb) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(output_cb);
  DCHECK(waiting_cb);

  state_ = State::kInitializing;

  config_ = config;
  init_cb_ = init_cb;
  output_cb_ = output_cb;
  waiting_cb_ = waiting_cb;

  // Verify that |config| matches one of the supported configurations.  This
  // helps us skip configs that are supported by the VDA but not us, since
  // GpuMojoMediaClient merges them.  This is not hacky, even in the tiniest
  // little bit, nope.  Definitely not.  Convinced?
  bool is_supported = false;
  for (const auto& supported_config : supported_configs_) {
    if (supported_config.Matches(config)) {
      is_supported = true;
      break;
    }
  }

  if (!is_supported) {
    NotifyError("D3D11VideoDecoder does not support this config");
    return;
  }

  // Initialize the video decoder.

  // Note that we assume that this is the ANGLE device, since we don't implement
  // texture sharing properly.  That also implies that this is the GPU main
  // thread, since we use non-threadsafe properties of the device (e.g., we get
  // the immediate context).
  //
  // Also note that we don't technically have a guarantee that the ANGLE device
  // will use the most recent version of D3D11; it might be configured to use
  // D3D9.  In practice, though, it seems to use 11.1 if it's available, unless
  // it's been specifically configured via switch to avoid d3d11.
  //
  // TODO(liberato): On re-init, we can probably re-use the device.
  device_ = get_d3d11_device_cb_.Run();
  usable_feature_level_ = device_->GetFeatureLevel();

  if (!device_) {
    // This happens if, for example, if chrome is configured to use
    // D3D9 for ANGLE.
    NotifyError("ANGLE did not provide D3D11 device");
    return;
  }
  device_->GetImmediateContext(device_context_.ReleaseAndGetAddressOf());

  HRESULT hr;

  // TODO(liberato): Handle cleanup better.  Also consider being less chatty in
  // the logs, since this will fall back.

  hr = device_.CopyTo(video_device_.ReleaseAndGetAddressOf());
  if (!SUCCEEDED(hr)) {
    NotifyError("Failed to get video device");
    return;
  }

  GUID decoder_guid = GetD3D11DecoderGUID(config);
  if (!DeviceHasDecoderID(decoder_guid)) {
    NotifyError("D3D11: Did not find a supported profile");
    return;
  }

  // TODO(liberato): dxva does this.  don't know if we need to.
  Microsoft::WRL::ComPtr<ID3D11Multithread> multi_threaded;
  hr = device_->QueryInterface(IID_PPV_ARGS(&multi_threaded));
  if (!SUCCEEDED(hr)) {
    NotifyError("Failed to query ID3D11Multithread");
    return;
  }
  // TODO(liberato): This is a hack, since the unittest returns
  // success without providing |multi_threaded|.
  if (multi_threaded)
    multi_threaded->SetMultithreadProtected(TRUE);

  D3D11_VIDEO_DECODER_DESC desc = {};
  desc.Guid = decoder_guid;
  desc.SampleWidth = config.coded_size().width();
  desc.SampleHeight = config.coded_size().height();
  desc.OutputFormat = DXGI_FORMAT_NV12;
  UINT config_count = 0;
  hr = video_device_->GetVideoDecoderConfigCount(&desc, &config_count);
  if (FAILED(hr) || config_count == 0) {
    NotifyError("Failed to get video decoder config count");
    return;
  }

  D3D11_VIDEO_DECODER_CONFIG dec_config = {};
  bool found = false;
  for (UINT i = 0; i < config_count; i++) {
    hr = video_device_->GetVideoDecoderConfig(&desc, i, &dec_config);
    if (FAILED(hr)) {
      NotifyError("Failed to get decoder config");
      return;
    }

    if (config.is_encrypted() && dec_config.guidConfigBitstreamEncryption !=
                                     D3D11_DECODER_ENCRYPTION_HW_CENC) {
      // For encrypted media, it has to use HW CENC decoder config.
      continue;
    }

    if (IsVP9(config) && dec_config.ConfigBitstreamRaw == 1) {
      // DXVA VP9 specification mentions ConfigBitstreamRaw "shall be 1".
      found = true;
      break;
    }

    if (IsH264(config) && dec_config.ConfigBitstreamRaw == 2) {
      // ConfigBitstreamRaw == 2 means the decoder uses DXVA_Slice_H264_Short.
      found = true;
      break;
    }
  }
  if (!found) {
    NotifyError("Failed to find decoder config");
    return;
  }

  memcpy(&decoder_guid_, &decoder_guid, sizeof decoder_guid_);

  Microsoft::WRL::ComPtr<ID3D11VideoDecoder> video_decoder;
  hr = video_device_->CreateVideoDecoder(
      &desc, &dec_config, video_decoder.ReleaseAndGetAddressOf());
  if (!video_decoder.Get()) {
    NotifyError("Failed to create a video decoder");
    return;
  }

  CdmProxyContext* proxy_context = nullptr;
#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
  if (cdm_context)
    proxy_context = cdm_context->GetCdmProxyContext();
#endif

  // Ensure that if we are encrypted, that we have a CDM.
  if (config_.is_encrypted() && !proxy_context) {
    NotifyError("Video stream is encrypted, but no cdm was found");
    return;
  }

  hr = InitializeAcceleratedDecoder(config, proxy_context, video_decoder);

  if (!SUCCEEDED(hr)) {
    NotifyError("Failed to get device context");
    return;
  }

  // At this point, playback is supported so add a line in the media log to help
  // us figure that out.
  media_log_->AddEvent(
      media_log_->CreateStringEvent(MediaLogEvent::MEDIA_INFO_LOG_ENTRY, "info",
                                    "Video is supported by D3D11VideoDecoder"));

  // |cdm_context| could be null for clear playback.
  // TODO(liberato): On re-init, should this still happen?
  if (cdm_context) {
    new_key_callback_registration_ =
        cdm_context->RegisterEventCB(base::BindRepeating(
            &D3D11VideoDecoder::OnCdmContextEvent, weak_factory_.GetWeakPtr()));
  }

  auto impl_init_cb = base::BindOnce(&D3D11VideoDecoder::OnGpuInitComplete,
                                     weak_factory_.GetWeakPtr());

  auto get_picture_buffer_cb =
      base::BindRepeating(&D3D11VideoDecoder::ReceivePictureBufferFromClient,
                          weak_factory_.GetWeakPtr());

  // Initialize the gpu side.  We wait until everything else is initialized,
  // since we allow it to call us back re-entrantly to reduce latency.  Note
  // that if we're not on the same thread, then we should probably post the
  // call earlier, since re-entrancy won't be an issue.
  if (impl_task_runner_->RunsTasksInCurrentSequence()) {
    impl_->Initialize(std::move(impl_init_cb),
                      std::move(get_picture_buffer_cb));
    return;
  }

  // Bind our own init / output cb that hop to this thread, so we don't call
  // the originals on some other thread.
  // Important but subtle note: base::Bind will copy |config_| since it's a
  // const ref.
  impl_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&D3D11VideoDecoderImpl::Initialize, impl_weak_,
                     BindToCurrentLoop(std::move(impl_init_cb)),
                     BindToCurrentLoop(std::move(get_picture_buffer_cb))));
}

void D3D11VideoDecoder::ReceivePictureBufferFromClient(
    scoped_refptr<D3D11PictureBuffer> buffer) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  // We may decode into this buffer again.
  // Note that |buffer| might no longer be in |picture_buffers_| if we've
  // replaced them.  That's okay.
  buffer->set_in_client_use(false);

  // Also re-start decoding in case it was waiting for more pictures.
  DoDecode();
}

void D3D11VideoDecoder::OnGpuInitComplete(bool success) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  if (!init_cb_) {
    // We already failed, so just do nothing.
    DCHECK_EQ(state_, State::kError);
    return;
  }

  DCHECK_EQ(state_, State::kInitializing);

  if (!success) {
    NotifyError("Gpu init failed");
    return;
  }

  state_ = State::kRunning;
  std::move(init_cb_).Run(true);
}

void D3D11VideoDecoder::Decode(scoped_refptr<DecoderBuffer> buffer,
                               const DecodeCB& decode_cb) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  if (state_ == State::kError) {
    // TODO(liberato): consider posting, though it likely doesn't matter.
    decode_cb.Run(DecodeStatus::DECODE_ERROR);
    return;
  }

  input_buffer_queue_.push_back(std::make_pair(std::move(buffer), decode_cb));

  // Post, since we're not supposed to call back before this returns.  It
  // probably doesn't matter since we're in the gpu process anyway.
  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE,
      base::BindOnce(&D3D11VideoDecoder::DoDecode, weak_factory_.GetWeakPtr()));
}

void D3D11VideoDecoder::DoDecode() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  if (state_ != State::kRunning) {
    DVLOG(2) << __func__ << ": Do nothing in " << static_cast<int>(state_)
             << " state.";
    return;
  }

  if (!current_buffer_) {
    if (input_buffer_queue_.empty()) {
      return;
    }
    current_buffer_ = std::move(input_buffer_queue_.front().first);
    current_decode_cb_ = input_buffer_queue_.front().second;
    input_buffer_queue_.pop_front();
    if (current_buffer_->end_of_stream()) {
      // Flush, then signal the decode cb once all pictures have been output.
      current_buffer_ = nullptr;
      if (!accelerated_video_decoder_->Flush()) {
        // This will also signal error |current_decode_cb_|.
        NotifyError("Flush failed");
        return;
      }
      // Pictures out output synchronously during Flush.  Signal the decode
      // cb now.
      std::move(current_decode_cb_).Run(DecodeStatus::OK);
      return;
    }
    // This must be after checking for EOS because there is no timestamp for an
    // EOS buffer.
    current_timestamp_ = current_buffer_->timestamp();

    accelerated_video_decoder_->SetStream(-1, current_buffer_->data(),
                                          current_buffer_->data_size(),
                                          current_buffer_->decrypt_config());
  }

  while (true) {
    // If we transition to the error state, then stop here.
    if (state_ == State::kError)
      return;

    media::AcceleratedVideoDecoder::DecodeResult result =
        accelerated_video_decoder_->Decode();
    // TODO(liberato): switch + class enum.
    if (result == media::AcceleratedVideoDecoder::kRanOutOfStreamData) {
      current_buffer_ = nullptr;
      std::move(current_decode_cb_).Run(DecodeStatus::OK);
      break;
    } else if (result == media::AcceleratedVideoDecoder::kRanOutOfSurfaces) {
      // At this point, we know the picture size.
      // If we haven't allocated picture buffers yet, then allocate some now.
      // Otherwise, stop here.  We'll restart when a picture comes back.
      if (picture_buffers_.size())
        return;
      CreatePictureBuffers();
    } else if (result == media::AcceleratedVideoDecoder::kAllocateNewSurfaces) {
      CreatePictureBuffers();
    } else if (result == media::AcceleratedVideoDecoder::kTryAgain) {
      state_ = State::kWaitingForNewKey;
      waiting_cb_.Run(WaitingReason::kNoDecryptionKey);
      // Another DoDecode() task would be posted in OnCdmContextEvent().
      return;
    } else {
      LOG(ERROR) << "VDA Error " << result;
      NotifyError("Accelerated decode failed");
      return;
    }
  }

  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE,
      base::BindOnce(&D3D11VideoDecoder::DoDecode, weak_factory_.GetWeakPtr()));
}

void D3D11VideoDecoder::Reset(const base::RepeatingClosure& closure) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK_NE(state_, State::kInitializing);

  current_buffer_ = nullptr;
  if (current_decode_cb_)
    std::move(current_decode_cb_).Run(DecodeStatus::ABORTED);

  for (auto& queue_pair : input_buffer_queue_)
    queue_pair.second.Run(DecodeStatus::ABORTED);
  input_buffer_queue_.clear();

  // TODO(liberato): how do we signal an error?
  accelerated_video_decoder_->Reset();

  if (state_ == State::kWaitingForReset && config_.is_encrypted()) {
    // On a hardware context loss event, a new swap chain has to be created (in
    // the compositor). By clearing the picture buffers, next DoDecode() call
    // will create a new texture. This makes the compositor to create a new swap
    // chain.
    // More detailed explanation at crbug.com/858286
    picture_buffers_.clear();
  }

  // Transition out of kWaitingForNewKey since the new buffer could be clear or
  // have a different key ID. Transition out of kWaitingForReset since reset
  // just happened.
  if (state_ == State::kWaitingForNewKey || state_ == State::kWaitingForReset)
    state_ = State::kRunning;

  closure.Run();
}

bool D3D11VideoDecoder::NeedsBitstreamConversion() const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  return true;
}

bool D3D11VideoDecoder::CanReadWithoutStalling() const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  return false;
}

int D3D11VideoDecoder::GetMaxDecodeRequests() const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  return 4;
}

void D3D11VideoDecoder::CreatePictureBuffers() {
  // TODO(liberato): When we run off the gpu main thread, this call will need
  // to signal success / failure asynchronously.  We'll need to transition into
  // a "waiting for pictures" state, since D3D11PictureBuffer will post the gpu
  // thread work.
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  // TODO(liberato): what's the minimum that we need for the decoder?
  // the VDA requests 20.
  const int num_buffers = 20;

  gfx::Size size = accelerated_video_decoder_->GetPicSize();

  // Create an array of |num_buffers| elements to back the PictureBuffers.
  D3D11_TEXTURE2D_DESC texture_desc = {};
  texture_desc.Width = size.width();
  texture_desc.Height = size.height();
  texture_desc.MipLevels = 1;
  texture_desc.ArraySize = num_buffers;
  texture_desc.Format = DXGI_FORMAT_NV12;
  texture_desc.SampleDesc.Count = 1;
  texture_desc.Usage = D3D11_USAGE_DEFAULT;
  texture_desc.BindFlags = D3D11_BIND_DECODER | D3D11_BIND_SHADER_RESOURCE;
  if (base::FeatureList::IsEnabled(
          features::kDirectCompositionUseNV12DecodeSwapChain)) {
    // Decode swap chains do not support shared resources.
    // TODO(sunnyps): Find a workaround for when the decoder moves to its own
    // thread and D3D device.  See https://crbug.com/911847
    texture_desc.MiscFlags = 0;
  } else {
    texture_desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED;
  }
  if (config_.is_encrypted())
    texture_desc.MiscFlags |= D3D11_RESOURCE_MISC_HW_PROTECTED;

  Microsoft::WRL::ComPtr<ID3D11Texture2D> out_texture;
  HRESULT hr = device_->CreateTexture2D(&texture_desc, nullptr,
                                        out_texture.ReleaseAndGetAddressOf());
  if (!SUCCEEDED(hr)) {
    NotifyError("Failed to create a Texture2D for PictureBuffers");
    return;
  }

  // Drop any old pictures.
  for (auto& buffer : picture_buffers_)
    DCHECK(!buffer->in_picture_use());
  picture_buffers_.clear();

  // Create each picture buffer.
  const int textures_per_picture = 2;  // From the VDA
  for (size_t i = 0; i < num_buffers; i++) {
    picture_buffers_.push_back(
        new D3D11PictureBuffer(GL_TEXTURE_EXTERNAL_OES, size, i));
    if (!picture_buffers_[i]->Init(get_helper_cb_, video_device_, out_texture,
                                   decoder_guid_, textures_per_picture)) {
      NotifyError("Unable to allocate PictureBuffer");
      return;
    }
  }
}

D3D11PictureBuffer* D3D11VideoDecoder::GetPicture() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  for (auto& buffer : picture_buffers_) {
    if (!buffer->in_client_use() && !buffer->in_picture_use()) {
      buffer->timestamp_ = current_timestamp_;
      return buffer.get();
    }
  }

  return nullptr;
}

void D3D11VideoDecoder::OutputResult(const CodecPicture* picture,
                                     D3D11PictureBuffer* picture_buffer) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  picture_buffer->set_in_client_use(true);

  // Note: The pixel format doesn't matter.
  gfx::Rect visible_rect = picture->visible_rect();
  if (visible_rect.IsEmpty())
    visible_rect = config_.visible_rect();

  // TODO(https://crbug.com/843150): Use aspect ratio from decoder (SPS) if
  // stream metadata doesn't overrride it.
  double pixel_aspect_ratio = config_.GetPixelAspectRatio();

  base::TimeDelta timestamp = picture_buffer->timestamp_;
  scoped_refptr<VideoFrame> frame = VideoFrame::WrapNativeTextures(
      PIXEL_FORMAT_NV12, picture_buffer->mailbox_holders(),
      VideoFrame::ReleaseMailboxCB(), picture_buffer->size(), visible_rect,
      GetNaturalSize(visible_rect, pixel_aspect_ratio), timestamp);

  // TODO(liberato): bind this to the gpu main thread.
  frame->SetReleaseMailboxCB(media::BindToCurrentLoop(
      base::BindOnce(&D3D11VideoDecoderImpl::OnMailboxReleased, impl_weak_,
                     scoped_refptr<D3D11PictureBuffer>(picture_buffer))));
  frame->metadata()->SetBoolean(VideoFrameMetadata::POWER_EFFICIENT, true);
  // For NV12, overlay is allowed by default. If the decoder is going to support
  // non-NV12 textures, then this may have to be conditionally set. Also note
  // that ALLOW_OVERLAY is required for encrypted video path.
  frame->metadata()->SetBoolean(VideoFrameMetadata::ALLOW_OVERLAY, true);

  if (config_.is_encrypted()) {
    frame->metadata()->SetBoolean(VideoFrameMetadata::PROTECTED_VIDEO, true);
    frame->metadata()->SetBoolean(VideoFrameMetadata::HW_PROTECTED, true);
  }

  frame->set_color_space(picture->get_colorspace().ToGfxColorSpace());
  output_cb_.Run(frame);
}

void D3D11VideoDecoder::OnCdmContextEvent(CdmContext::Event event) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DVLOG(1) << __func__ << ": event = " << static_cast<int>(event);

  if (state_ == State::kInitializing || state_ == State::kError) {
    DVLOG(1) << "Do nothing in " << static_cast<int>(state_) << " state.";
    return;
  }

  switch (event) {
    case CdmContext::Event::kHasAdditionalUsableKey:
      // Note that this event may happen before DoDecode() because the key
      // acquisition stack runs independently of the media decoding stack.
      // So if this isn't in kWaitingForNewKey state no "resuming" is
      // required therefore no special action taken here.
      if (state_ != State::kWaitingForNewKey)
        return;

      state_ = State::kRunning;
      base::ThreadTaskRunnerHandle::Get()->PostTask(
          FROM_HERE, base::BindOnce(&D3D11VideoDecoder::DoDecode,
                                    weak_factory_.GetWeakPtr()));
      return;

    case CdmContext::Event::kHardwareContextLost:
      state_ = State::kWaitingForReset;
      waiting_cb_.Run(WaitingReason::kDecoderStateLost);
      return;
  }
}

void D3D11VideoDecoder::NotifyError(const char* reason) {
  state_ = State::kError;
  DLOG(ERROR) << reason;
  media_log_->AddEvent(media_log_->CreateStringEvent(
      MediaLogEvent::MEDIA_ERROR_LOG_ENTRY, "error", reason));

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

  if (current_decode_cb_)
    std::move(current_decode_cb_).Run(DecodeStatus::DECODE_ERROR);

  for (auto& queue_pair : input_buffer_queue_)
    queue_pair.second.Run(DecodeStatus::DECODE_ERROR);
  input_buffer_queue_.clear();
}

// static
std::vector<SupportedVideoDecoderConfig>
D3D11VideoDecoder::GetSupportedVideoDecoderConfigs(
    const gpu::GpuPreferences& gpu_preferences,
    const gpu::GpuDriverBugWorkarounds& gpu_workarounds,
    GetD3D11DeviceCB get_d3d11_device_cb) {
  const std::string uma_name("Media.D3D11.WasVideoSupported");

  // Must allow zero-copy of nv12 textures.
  if (!gpu_preferences.enable_zero_copy_dxgi_video) {
    UMA_HISTOGRAM_ENUMERATION(uma_name,
                              NotSupportedReason::kZeroCopyNv12Required);
    return {};
  }

  // This workaround accounts for almost half of all startup results, and it's
  // unclear that it's relevant here.
  if (!base::FeatureList::IsEnabled(kD3D11VideoDecoderIgnoreWorkarounds)) {
    if (gpu_workarounds.disable_dxgi_zero_copy_video) {
      UMA_HISTOGRAM_ENUMERATION(uma_name,
                                NotSupportedReason::kZeroCopyVideoRequired);
      return {};
    }
  }

  // Remember that this might query the angle device, so this won't work if
  // we're not on the GPU main thread.  Also remember that devices are thread
  // safe (contexts are not), so we could use the angle device from any thread
  // as long as we're not calling into possible not-thread-safe things to get
  // it.  I.e., if this cached it, then it'd be fine.  It's up to our caller
  // to guarantee that, though.
  //
  // Note also that, currently, we are called from the GPU main thread only.
  auto d3d11_device = get_d3d11_device_cb.Run();
  if (!d3d11_device) {
    UMA_HISTOGRAM_ENUMERATION(uma_name,
                              NotSupportedReason::kCouldNotGetD3D11Device);
    return {};
  }

  D3D_FEATURE_LEVEL usable_feature_level = d3d11_device->GetFeatureLevel();

  const bool allow_encrypted =
      (usable_feature_level > D3D_FEATURE_LEVEL_11_0) &&
      base::FeatureList::IsEnabled(kHardwareSecureDecryption);

  std::vector<SupportedVideoDecoderConfig> configs;

  // Now check specific configs.
  // For now, just return something that matches everything, since that's
  // effectively what the workaround in mojo_video_decoder does.  Eventually, we
  // should check resolutions and guids from the device we just created for both
  // portrait and landscape orientations.
  const gfx::Size min_resolution(64, 64);
  const gfx::Size max_resolution(8192, 8192);  // Profile or landscape 8k

  // Push H264 configs, except HIGH10.
  configs.push_back(SupportedVideoDecoderConfig(
      H264PROFILE_MIN,  // profile_min
      static_cast<VideoCodecProfile>(H264PROFILE_HIGH10PROFILE -
                                     1),  // profile_max
      min_resolution,                     // coded_size_min
      max_resolution,                     // coded_size_max
      allow_encrypted,                    // allow_encrypted
      false));                            // require_encrypted
  configs.push_back(SupportedVideoDecoderConfig(
      static_cast<VideoCodecProfile>(H264PROFILE_HIGH10PROFILE +
                                     1),  // profile_min
      H264PROFILE_MAX,                    // profile_max
      min_resolution,                     // coded_size_min
      max_resolution,                     // coded_size_max
      allow_encrypted,                    // allow_encrypted
      false));                            // require_encrypted

  configs.push_back(
      SupportedVideoDecoderConfig(VP9PROFILE_PROFILE0,  // profile_min
                                  VP9PROFILE_PROFILE0,  // profile_max
                                  min_resolution,       // coded_size_min
                                  max_resolution,       // coded_size_max
                                  allow_encrypted,      // allow_encrypted
                                  false));              // require_encrypted

  // TODO(liberato): Should we separate out h264, vp9, and encrypted?
  UMA_HISTOGRAM_ENUMERATION(uma_name, NotSupportedReason::kVideoIsSupported);

  return configs;
}

}  // namespace media
