// 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 <utility>

#include "base/bind.h"
#include "base/callback.h"
#include "base/callback_helpers.h"
#include "base/debug/crash_logging.h"
#include "base/debug/dump_without_crashing.h"
#include "base/feature_list.h"
#include "base/memory/ref_counted_delete_on_sequence.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
#include "media/base/bind_to_current_loop.h"
#include "media/base/decoder_buffer.h"
#include "media/base/media_log.h"
#include "media/base/media_switches.h"
#include "media/base/video_aspect_ratio.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/base/win/hresult_status_helper.h"
#include "media/gpu/windows/d3d11_av1_accelerator.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 "media/gpu/windows/d3d11_video_device_format_support.h"
#include "media/gpu/windows/supported_profile_helpers.h"
#include "media/media_buildflags.h"
#include "ui/gl/gl_angle_util_win.h"
#include "ui/gl/gl_switches.h"
#include "ui/gl/hdr_metadata_helper_win.h"

namespace media {

namespace {

// 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,
    bool is_hdr_supported) {
  // 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(
      gpu_task_runner, std::move(media_log), gpu_preferences, gpu_workarounds,
      base::SequenceBound<D3D11VideoDecoderImpl>(
          gpu_task_runner, std::move(cloned_media_log), get_helper_cb),
      get_helper_cb, std::move(get_d3d11_device_cb),
      std::move(supported_configs), is_hdr_supported));
}

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,
    base::SequenceBound<D3D11VideoDecoderImpl> impl,
    base::RepeatingCallback<scoped_refptr<CommandBufferHelper>()> get_helper_cb,
    GetD3D11DeviceCB get_d3d11_device_cb,
    SupportedConfigs supported_configs,
    bool is_hdr_supported)
    : media_log_(std::move(media_log)),
      impl_(std::move(impl)),
      gpu_task_runner_(std::move(gpu_task_runner)),
      decoder_task_runner_(base::SequencedTaskRunnerHandle::Get()),
      already_initialized_(false),
      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)),
      is_hdr_supported_(is_hdr_supported) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(media_log_);
}

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_);

  impl_.Reset();

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

  if (already_initialized_)
    AddLifetimeProgressionStage(D3D11LifetimeProgression::kPlaybackSucceeded);
}

VideoDecoderType D3D11VideoDecoder::GetDecoderType() const {
  return VideoDecoderType::kD3D11;
}

HRESULT D3D11VideoDecoder::InitializeAcceleratedDecoder(
    const VideoDecoderConfig& config,
    ComD3D11VideoDecoder video_decoder) {
  TRACE_EVENT0("gpu", "D3D11VideoDecoder::InitializeAcceleratedDecoder");
  // 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;

  profile_ = config.profile();
  if (config.codec() == VideoCodec::kVP9) {
    accelerated_video_decoder_ = std::make_unique<VP9Decoder>(
        std::make_unique<D3D11VP9Accelerator>(
            this, media_log_.get(), video_device_, std::move(video_context)),
        profile_, config.color_space_info());
  } else if (config.codec() == VideoCodec::kH264) {
    accelerated_video_decoder_ = std::make_unique<H264Decoder>(
        std::make_unique<D3D11H264Accelerator>(
            this, media_log_.get(), video_device_, std::move(video_context)),
        profile_, config.color_space_info());
  } else if (config.codec() == VideoCodec::kAV1) {
    accelerated_video_decoder_ = std::make_unique<AV1Decoder>(
        std::make_unique<D3D11AV1Accelerator>(
            this, media_log_.get(), video_device_, std::move(video_context)),
        profile_, config.color_space_info());
  } else {
    return E_FAIL;
  }

  // Provide the initial video decoder object.
  DCHECK(set_accelerator_decoder_cb_);
  set_accelerator_decoder_cb_.Run(std::move(video_decoder));

  return hr;
}

StatusOr<ComD3D11VideoDecoder> D3D11VideoDecoder::CreateD3D11Decoder() {
  // By default we assume outputs are 8-bit for SDR color spaces and 10 bit for
  // HDR color spaces (or VP9.2). We'll get a config change once we know the
  // real bit depth if this turns out to be wrong.
  bit_depth_ =
      accelerated_video_decoder_
          ? accelerated_video_decoder_->GetBitDepth()
          : (config_.profile() == VP9PROFILE_PROFILE2 ||
                     config_.color_space_info().ToGfxColorSpace().IsHDR()
                 ? 10
                 : 8);

  // OS prevent read any content from encrypted video frame. No need to support
  // shared handle and keyed_mutex system for the encrypted frame.
  const bool use_shared_handle =
      base::FeatureList::IsEnabled(kD3D11VideoDecoderUseSharedHandle) &&
      !config_.is_encrypted();

  // TODO: supported check?
  decoder_configurator_ = D3D11DecoderConfigurator::Create(
      gpu_preferences_, gpu_workarounds_, config_, bit_depth_, media_log_.get(),
      use_shared_handle);
  if (!decoder_configurator_)
    return StatusCode::kDecoderUnsupportedProfile;

  if (!decoder_configurator_->SupportsDevice(video_device_))
    return StatusCode::kDecoderUnsupportedCodec;

  FormatSupportChecker format_checker(device_);
  if (!format_checker.Initialize()) {
    // Don't fail; it'll just return no support a lot.
    MEDIA_LOG(WARNING, media_log_)
        << "Could not create format checker, continuing";
  }

  // Use IsHDRSupported to guess whether the compositor can output HDR textures.
  // See TextureSelector for notes about why the decoder should not care.
  texture_selector_ = TextureSelector::Create(
      gpu_preferences_, gpu_workarounds_,
      decoder_configurator_->TextureFormat(),
      is_hdr_supported_ ? TextureSelector::HDRMode::kSDROrHDR
                        : TextureSelector::HDRMode::kSDROnly,
      &format_checker, video_device_, device_context_, media_log_.get(),
      use_shared_handle);
  if (!texture_selector_)
    return StatusCode::kCreateTextureSelectorFailed;

  UINT config_count = 0;
  auto hr = video_device_->GetVideoDecoderConfigCount(
      decoder_configurator_->DecoderDescriptor(), &config_count);
  if (FAILED(hr)) {
    return Status(StatusCode::kGetDecoderConfigCountFailed)
        .AddCause(HresultToStatus(hr));
  }

  if (config_count == 0)
    return Status(StatusCode::kGetDecoderConfigCountFailed);

  D3D11_VIDEO_DECODER_CONFIG dec_config = {};
  bool found = false;

  for (UINT i = 0; i < config_count; i++) {
    hr = video_device_->GetVideoDecoderConfig(
        decoder_configurator_->DecoderDescriptor(), i, &dec_config);
    if (FAILED(hr)) {
      return Status(StatusCode::kGetDecoderConfigFailed)
          .AddCause(HresultToStatus(hr));
    }

    if ((config_.codec() == VideoCodec::kVP9 ||
         config_.codec() == VideoCodec::kAV1) &&
        dec_config.ConfigBitstreamRaw == 1) {
      // DXVA VP9 and AV1 specifications say ConfigBitstreamRaw "shall be 1".
      found = true;
      break;
    }

    if (config_.codec() == VideoCodec::kH264 &&
        dec_config.ConfigBitstreamRaw == 2) {
      // ConfigBitstreamRaw == 2 means the decoder uses DXVA_Slice_H264_Short.
      found = true;
      break;
    }
  }
  if (!found)
    return StatusCode::kDecoderUnsupportedConfig;

  // Prefer whatever the config tells us about whether to use one Texture2D with
  // multiple array slices, or multiple Texture2Ds with one slice each.  If bit
  // 14 is clear, then it's the former, else it's the latter.
  //
  // Let the workaround override array texture mode, if enabled.
  // TODO(crbug.com/971952): Ignore |use_single_video_decoder_texture_| here,
  // since it might be the case that it's not actually the right fix.  Instead,
  // We use this workaround to force a copy later.  The workaround will be
  // renamed if this turns out to fix the issue, but we might need to merge back
  // and smaller changes are better.
  //
  // For more information, please see:
  // https://download.microsoft.com/download/9/2/A/92A4E198-67E0-4ABD-9DB7-635D711C2752/DXVA_VPx.pdf
  // https://download.microsoft.com/download/5/f/c/5fc4ec5c-bd8c-4624-8034-319c1bab7671/DXVA_H264.pdf
  //
  // When creating output texture with shared handle supports, we can't use a
  // texture array. Because the keyed mutex applies on the entire texture array
  // causing a deadlock when multiple threads try to use different slots of the
  // array. More info here: https://crbug.com/1238943
  use_single_video_decoder_texture_ =
      !!(dec_config.ConfigDecoderSpecific & (1 << 14)) || use_shared_handle;
  if (use_single_video_decoder_texture_)
    MEDIA_LOG(INFO, media_log_) << "D3D11VideoDecoder is using single textures";
  else
    MEDIA_LOG(INFO, media_log_) << "D3D11VideoDecoder is using array texture";

  Microsoft::WRL::ComPtr<ID3D11VideoDecoder> video_decoder;
  hr = video_device_->CreateVideoDecoder(
      decoder_configurator_->DecoderDescriptor(), &dec_config, &video_decoder);

  if (!video_decoder.Get())
    return Status(StatusCode::kDecoderCreationFailed);

  if (FAILED(hr)) {
    return Status(StatusCode::kDecoderCreationFailed)
        .AddCause(HresultToStatus(hr));
  }

  return {std::move(video_decoder)};
}

void D3D11VideoDecoder::Initialize(const VideoDecoderConfig& config,
                                   bool low_delay,
                                   CdmContext* /* cdm_context */,
                                   InitCB init_cb,
                                   const OutputCB& output_cb,
                                   const WaitingCB& /* waiting_cb */) {
  TRACE_EVENT0("gpu", "D3D11VideoDecoder::Initialize");
  if (already_initialized_)
    AddLifetimeProgressionStage(D3D11LifetimeProgression::kPlaybackSucceeded);
  AddLifetimeProgressionStage(D3D11LifetimeProgression::kInitializeStarted);

  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(output_cb);

  state_ = State::kInitializing;

  config_ = config;
  init_cb_ = std::move(init_cb);
  output_cb_ = output_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;
  }

  if (config.is_encrypted()) {
    NotifyError("D3D11VideoDecoder does not support encrypted stream");
    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.
  // TODO(liberato): This isn't allowed off the main thread, since the callback
  // does who-knows-what.  Either we should be given the angle device, or we
  // should thread-hop to get it.
  device_ = get_d3d11_device_cb_.Run();
  if (!device_) {
    // This happens if, for example, if chrome is configured to use
    // D3D9 for ANGLE.
    NotifyError("ANGLE did not provide D3D11 device");
    return;
  }

  if (!GetD3D11FeatureLevel(device_, gpu_workarounds_,
                            &usable_feature_level_)) {
    NotifyError("D3D11 feature level not supported");
    return;
  }

  device_->GetImmediateContext(&device_context_);

  HRESULT hr;

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

  ComD3D11Multithread multi_threaded;
  hr = device_->QueryInterface(IID_PPV_ARGS(&multi_threaded));
  if (FAILED(hr)) {
    return NotifyError(Status(StatusCode::kQueryID3D11MultithreadFailed)
                           .AddCause(HresultToStatus(hr)));
  }

  multi_threaded->SetMultithreadProtected(TRUE);

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

  auto video_decoder_or_error = CreateD3D11Decoder();
  if (video_decoder_or_error.has_error()) {
    NotifyError(std::move(video_decoder_or_error).error());
    return;
  }

  hr = InitializeAcceleratedDecoder(config,
                                    std::move(video_decoder_or_error).value());

  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(INFO, media_log_) << "Video is supported by D3D11VideoDecoder";

  if (base::FeatureList::IsEnabled(kD3D11PrintCodecOnCrash)) {
    static base::debug::CrashKeyString* codec_name =
        base::debug::AllocateCrashKeyString("d3d11_playback_video_codec",
                                            base::debug::CrashKeySize::Size32);
    base::debug::SetCrashKeyString(codec_name,
                                   config.GetHumanReadableCodecName());
  }

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

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

  AddLifetimeProgressionStage(D3D11LifetimeProgression::kInitializeSucceeded);

  // Initialize the gpu side.  It would be nice if we could ask SB<> to elide
  // the post if we're already on that thread, but it can't.
  // 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_.AsyncCall(&D3D11VideoDecoderImpl::Initialize)
      .WithArgs(BindToCurrentLoop(std::move(impl_init_cb)));
}

void D3D11VideoDecoder::AddLifetimeProgressionStage(
    D3D11LifetimeProgression stage) {
  already_initialized_ =
      (stage == D3D11LifetimeProgression::kInitializeSucceeded);
  const std::string uma_name("Media.D3D11.DecoderLifetimeProgression");
  base::UmaHistogramEnumeration(uma_name, stage);
}

void D3D11VideoDecoder::ReceivePictureBufferFromClient(
    scoped_refptr<D3D11PictureBuffer> buffer) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  TRACE_EVENT0("gpu", "D3D11VideoDecoder::ReceivePictureBufferFromClient");

  // 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->remove_client_use();

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

void D3D11VideoDecoder::OnGpuInitComplete(
    bool success,
    D3D11VideoDecoderImpl::ReleaseMailboxCB release_mailbox_cb) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  TRACE_EVENT0("gpu", "D3D11VideoDecoder::OnGpuInitComplete");

  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;
  }

  release_mailbox_cb_ = std::move(release_mailbox_cb);

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

void D3D11VideoDecoder::Decode(scoped_refptr<DecoderBuffer> buffer,
                               DecodeCB decode_cb) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  TRACE_EVENT0("gpu", "D3D11VideoDecoder::Decode");

  // If we aren't given a decode cb, then record that.
  // crbug.com/1012464 .
  if (!decode_cb)
    base::debug::DumpWithoutCrashing();

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

  input_buffer_queue_.push_back(
      std::make_pair(std::move(buffer), std::move(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_);
  TRACE_EVENT0("gpu", "D3D11VideoDecoder::DoDecode");

  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_ = std::move(input_buffer_queue_.front().second);
    // If we pop a null decode cb off the stack, record it so we can see if this
    // is from a top-level call, or through Decode.
    // crbug.com/1012464 .
    if (!current_decode_cb_)
      base::debug::DumpWithoutCrashing();
    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(StatusCode::kAcceleratorFlushFailed);
        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_);
  }

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

    // If somebody cleared the buffer, then stop and post.
    // TODO(liberato): It's unclear to me how this might happen.  If it does
    // fix the crash, then more investigation is required.  Please see
    // crbug.com/1012464 for more information.
    if (!current_buffer_)
      break;

    // Record if we get here with a buffer, but without a decode cb.  This
    // shouldn't happen, but does.  This will prevent the crash, and record how
    // we got here.
    // crbug.com/1012464 .
    if (!current_decode_cb_) {
      base::debug::DumpWithoutCrashing();
      current_buffer_ = nullptr;
      break;
    }

    media::AcceleratedVideoDecoder::DecodeResult result =
        accelerated_video_decoder_->Decode();
    if (state_ == State::kError) {
      // Transitioned to an error at some point.  The h264 accelerator can do
      // this if picture output fails, at least.  Until that's fixed, check
      // here and exit if so.
      return;
    }
    // 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::kConfigChange) {
      // Before the first frame, we get a config change that we should ignore.
      // We only want to take action if this is a mid-stream config change.  We
      // could wait until now to allocate the first D3D11VideoDecoder, but we
      // don't, so that init can fail rather than decoding if there's a problem
      // creating it.  We could also unconditionally re-allocate the decoder,
      // but we keep it if it's ready to go.
      const auto new_bit_depth = accelerated_video_decoder_->GetBitDepth();
      const auto new_profile = accelerated_video_decoder_->GetProfile();
      const auto new_coded_size = accelerated_video_decoder_->GetPicSize();
      if (new_profile == config_.profile() &&
          new_coded_size == config_.coded_size() &&
          new_bit_depth == bit_depth_ && !picture_buffers_.size()) {
        continue;
      }

      // Update the config.
      MEDIA_LOG(INFO, media_log_)
          << "D3D11VideoDecoder config change: profile: "
          << static_cast<int>(new_profile) << " coded_size: ("
          << new_coded_size.width() << ", " << new_coded_size.height() << ")";
      profile_ = new_profile;
      config_.set_profile(profile_);
      config_.set_coded_size(new_coded_size);

      // Replace the decoder, and clear any picture buffers we have.  It's okay
      // if we don't have any picture buffer yet; this might be before the
      // accelerated decoder asked for any.
      auto video_decoder_or_error = CreateD3D11Decoder();
      if (video_decoder_or_error.has_error()) {
        NotifyError(std::move(video_decoder_or_error).error());
        return;
      }
      DCHECK(set_accelerator_decoder_cb_);
      set_accelerator_decoder_cb_.Run(
          std::move(video_decoder_or_error).value());
      picture_buffers_.clear();
    } else if (result == media::AcceleratedVideoDecoder::kTryAgain) {
      LOG(ERROR) << "Try again is not supported";
      NotifyError(StatusCode::kTryAgainNotSupported);
      return;
    } else {
      std::ostringstream message;
      message << "VDA Error " << result;
      NotifyError(Status(StatusCode::kDecoderFailedDecode, message.str()));
      return;
    }
  }

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

void D3D11VideoDecoder::Reset(base::OnceClosure closure) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK_NE(state_, State::kInitializing);
  TRACE_EVENT0("gpu", "D3D11VideoDecoder::Reset");

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

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

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

  std::move(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.
  TRACE_EVENT0("gpu", "D3D11VideoDecoder::CreatePictureBuffers");
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(decoder_configurator_);
  DCHECK(texture_selector_);
  gfx::Size size = accelerated_video_decoder_->GetPicSize();

  gfx::HDRMetadata stream_metadata;
  if (config_.hdr_metadata())
    stream_metadata = *config_.hdr_metadata();
  // else leave |stream_metadata| default-initialized.  We might use it anyway.

  absl::optional<DXGI_HDR_METADATA_HDR10> display_metadata;
  if (decoder_configurator_->TextureFormat() == DXGI_FORMAT_P010) {
    // For HDR formats, try to get the display metadata.  This may fail, which
    // is okay.  We'll just skip sending the metadata.
    gl::HDRMetadataHelperWin hdr_metadata_helper(device_);
    display_metadata = hdr_metadata_helper.GetDisplayMetadata();
  }

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

  ComD3D11Texture2D in_texture;

  // Create each picture buffer.
  for (size_t i = 0; i < D3D11DecoderConfigurator::BUFFER_COUNT; i++) {
    // Create an input texture / texture array if we haven't already.
    if (!in_texture) {
      auto result = decoder_configurator_->CreateOutputTexture(
          device_, size,
          use_single_video_decoder_texture_
              ? 1
              : D3D11DecoderConfigurator::BUFFER_COUNT,
          texture_selector_->DoesDecoderOutputUseSharedHandle());
      if (result.has_value()) {
        in_texture = std::move(result).value();
      } else {
        NotifyError(std::move(result).error().AddHere());
        return;
      }
    }

    DCHECK(!!in_texture);

    auto tex_wrapper = texture_selector_->CreateTextureWrapper(device_, size);
    if (!tex_wrapper) {
      NotifyError(StatusCode::kAllocateTextureForCopyingWrapperFailed);
      return;
    }

    const size_t array_slice = use_single_video_decoder_texture_ ? 0 : i;
    picture_buffers_.push_back(
        new D3D11PictureBuffer(decoder_task_runner_, in_texture, array_slice,
                               std::move(tex_wrapper), size, i /* level */));
    Status result = picture_buffers_[i]->Init(
        gpu_task_runner_, get_helper_cb_, video_device_,
        decoder_configurator_->DecoderGuid(), media_log_->Clone());
    if (!result.is_ok()) {
      NotifyError(std::move(result).AddHere());
      return;
    }

    // If we're using one texture per buffer, rather than an array, then clear
    // the ref to it so that we allocate a new one above.
    if (use_single_video_decoder_texture_)
      in_texture = nullptr;

    // If we have display metadata, then tell the processor.  Note that the
    // order of these calls is important, and we must set the display metadata
    // if we set the stream metadata, else it can crash on some AMD cards.
    if (display_metadata) {
      if (config_.hdr_metadata() ||
          gpu_workarounds_.use_empty_video_hdr_metadata) {
        // It's okay if this has an empty-initialized metadata.
        picture_buffers_[i]->texture_wrapper()->SetStreamHDRMetadata(
            stream_metadata);
      }
      picture_buffers_[i]->texture_wrapper()->SetDisplayHDRMetadata(
          *display_metadata);
    }
  }
}

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::UpdateTimestamp(D3D11PictureBuffer* picture_buffer) {
  // A picture is being reused with a different timestamp; since we've already
  // generated a VideoFrame from the previous picture buffer, we can just stamp
  // the new timestamp directly onto the buffer.
  picture_buffer->timestamp_ = current_timestamp_;
}

bool D3D11VideoDecoder::OutputResult(const CodecPicture* picture,
                                     D3D11PictureBuffer* picture_buffer) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(texture_selector_);
  TRACE_EVENT0("gpu", "D3D11VideoDecoder::OutputResult");

  picture_buffer->add_client_use();

  // 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
  // the config's aspect ratio isn't valid.
  gfx::Size natural_size = config_.aspect_ratio().GetNaturalSize(visible_rect);

  base::TimeDelta timestamp = picture_buffer->timestamp_;

  MailboxHolderArray mailbox_holders;
  gfx::ColorSpace output_color_space;
  Status result = picture_buffer->ProcessTexture(
      picture->get_colorspace().ToGfxColorSpace(), &mailbox_holders,
      &output_color_space);
  if (!result.is_ok()) {
    NotifyError(std::move(result).AddHere());
    return false;
  }

  scoped_refptr<VideoFrame> frame = VideoFrame::WrapNativeTextures(
      texture_selector_->PixelFormat(), mailbox_holders,
      VideoFrame::ReleaseMailboxCB(), picture_buffer->size(), visible_rect,
      natural_size, timestamp);

  if (!frame) {
    // This can happen if, somehow, we get an unsupported combination of
    // pixel format, etc.
    NotifyError(StatusCode::kDecoderVideoFrameConstructionFailed);
    return false;
  }

  // Remember that this will likely thread-hop to the GPU main thread.  Note
  // that |picture_buffer| will delete on sequence, so it's okay even if
  // |wait_complete_cb| doesn't ever run.
  auto wait_complete_cb = BindToCurrentLoop(
      base::BindOnce(&D3D11VideoDecoder::ReceivePictureBufferFromClient,
                     weak_factory_.GetWeakPtr(),
                     scoped_refptr<D3D11PictureBuffer>(picture_buffer)));
  frame->SetReleaseMailboxCB(
      base::BindOnce(release_mailbox_cb_, std::move(wait_complete_cb)));

  // 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.
  //
  // Since all of our picture buffers allow overlay, we just set this to true.
  // However, we may choose to set ALLOW_OVERLAY to false even if
  // the finch flag is enabled.  We may not choose to set ALLOW_OVERLAY if the
  // flag is off, however.
  //
  // Also note that, since we end up binding textures with GLImageDXGI, it's
  // probably okay just to allow overlay always, and let the swap chain
  // presenter decide if it wants to.
  frame->metadata().allow_overlay = true;

  frame->metadata().power_efficient = true;
  frame->set_color_space(output_color_space);
  frame->set_hdr_metadata(config_.hdr_metadata());
  output_cb_.Run(frame);
  return true;
}

void D3D11VideoDecoder::SetDecoderCB(const SetAcceleratorDecoderCB& cb) {
  set_accelerator_decoder_cb_ = cb;
}

// TODO(tmathmeyer): Please don't add new uses of this overload.
void D3D11VideoDecoder::NotifyError(const char* reason) {
  NotifyError(Status(StatusCode::kDecoderInitializeNeverCompleted, reason));
}

void D3D11VideoDecoder::NotifyError(const Status& reason) {
  TRACE_EVENT0("gpu", "D3D11VideoDecoder::NotifyError");
  state_ = State::kError;

  // Log why this failed.
  base::UmaHistogramSparse("Media.D3D11.NotifyErrorStatus",
                           static_cast<int>(reason.code()));

  if (init_cb_) {
    std::move(init_cb_).Run(reason);
  } else {
    // TODO(tmathmeyer) - Remove this after plumbing Status through the
    // decode_cb and input_buffer_queue cb's.
    // Let the init handler set the error string if this is an init failure.
    MEDIA_LOG(ERROR, media_log_) << "D3D11VideoDecoder error: 0x" << std::hex
                                 << reason.code() << " " << reason.message();
  }

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

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

// static
bool D3D11VideoDecoder::GetD3D11FeatureLevel(
    ComD3D11Device dev,
    const gpu::GpuDriverBugWorkarounds& gpu_workarounds,
    D3D_FEATURE_LEVEL* feature_level) {
  if (!dev || !feature_level)
    return false;

  *feature_level = dev->GetFeatureLevel();
  if (*feature_level < D3D_FEATURE_LEVEL_11_0)
    return false;

  // TODO(tmathmeyer) should we log this to UMA?
  if (gpu_workarounds.limit_d3d11_video_decoder_to_11_0 &&
      !base::FeatureList::IsEnabled(kD3D11VideoDecoderIgnoreWorkarounds)) {
    *feature_level = D3D_FEATURE_LEVEL_11_0;
  }

  return true;
}

// 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");

  if (!base::FeatureList::IsEnabled(kD3D11VideoDecoderIgnoreWorkarounds)) {
    // Allow all of d3d11 to be turned off by workaround.
    if (gpu_workarounds.disable_d3d11_video_decoder) {
      UMA_HISTOGRAM_ENUMERATION(uma_name, NotSupportedReason::kOffByWorkaround);
      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;
  if (!GetD3D11FeatureLevel(d3d11_device, gpu_workarounds,
                            &usable_feature_level)) {
    UMA_HISTOGRAM_ENUMERATION(
        uma_name, NotSupportedReason::kInsufficientD3D11FeatureLevel);
    return {};
  }

  const auto supported_resolutions = GetSupportedD3D11VideoDecoderResolutions(
      d3d11_device, gpu_workarounds,
      base::FeatureList::IsEnabled(kD3D11VideoDecoderAV1) &&
          !gpu_workarounds.disable_accelerated_av1_decode_d3d11);

  std::vector<SupportedVideoDecoderConfig> configs;
  for (const auto& kv : supported_resolutions) {
    const auto profile = kv.first;
    if (profile == VP9PROFILE_PROFILE2 &&
        !base::FeatureList::IsEnabled(kD3D11VideoDecoderVP9Profile2)) {
      continue;
    }

    // TODO(liberato): Add VP8 support to D3D11VideoDecoder.
    if (profile == VP8PROFILE_ANY)
      continue;

    const auto& resolution_range = kv.second;
    configs.emplace_back(profile, profile, resolution_range.min_resolution,
                         resolution_range.max_landscape_resolution,
                         /*allow_encrypted=*/false,
                         /*require_encrypted=*/false);
    if (!resolution_range.max_portrait_resolution.IsEmpty() &&
        resolution_range.max_portrait_resolution !=
            resolution_range.max_landscape_resolution) {
      configs.emplace_back(profile, profile, resolution_range.min_resolution,
                           resolution_range.max_portrait_resolution,
                           /*allow_encrypted=*/false,
                           /*require_encrypted=*/false);
    }
  }

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

  return configs;
}

}  // namespace media
