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

bool IsUnsupportedVP9Profile(const VideoDecoderConfig& config) {
  return config.profile() == VP9PROFILE_PROFILE1 ||
         config.profile() == VP9PROFILE_PROFILE3;
}

#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) {
  // 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));
}

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)
    : 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),
      create_device_func_(base::BindRepeating(D3D11CreateDevice)),
      get_helper_cb_(std::move(get_helper_cb)),
      weak_factory_(this) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  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) && base::FeatureList::IsEnabled(kD3D11VP9Decoder))
    // TODO(tmathmeyer) set up a finch experiment.
    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 WaitingForDecryptionKeyCB& waiting_for_decryption_key_cb) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  if (!IsPotentiallySupported(config)) {
    DVLOG(3) << "D3D11 video decoder not supported for the config.";
    init_cb.Run(false);
    return;
  }

  init_cb_ = init_cb;
  output_cb_ = output_cb;
  is_encrypted_ = config.is_encrypted();

  D3D11VideoDecoderImpl::InitCB cb = base::BindOnce(
      &D3D11VideoDecoder::OnGpuInitComplete, weak_factory_.GetWeakPtr());

  D3D11VideoDecoderImpl::ReturnPictureBufferCB return_picture_buffer_cb =
      base::BindRepeating(&D3D11VideoDecoder::ReceivePictureBufferFromClient,
                          weak_factory_.GetWeakPtr());

  // Initialize the video decoder.

  // Use the ANGLE device, rather than create our own.  It would be nice if we
  // could use our own device, and run on the mojo thread, but texture sharing
  // seems to be difficult.
  // TODO(liberato): take |device_| as input.
  // TODO(liberato): On re-init, we can probably re-use the device.
  device_ = gl::QueryD3D11DeviceObjectFromANGLE();
  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("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;
  }
  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 (dec_config.ConfigBitstreamRaw == 2) {
      found = true;
      break;
    }
  }
  if (!found) {
    NotifyError("Failed to find decoder config");
    return;
  }

  if (is_encrypted_)
    dec_config.guidConfigBitstreamEncryption = D3D11_DECODER_ENCRYPTION_HW_CENC;

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

  // |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->RegisterNewKeyCB(base::BindRepeating(
            &D3D11VideoDecoder::NotifyNewKey, 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(cb), std::move(return_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(cb)),
                     BindToCurrentLoop(std::move(return_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.
    return;
  }

  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)
    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;
      // Note that another DoDecode() task would be posted in NotifyNewKey().
      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_);

  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();
  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;
  texture_desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED;
  if (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());
  // TODO(liberato): Pixel aspect ratio should come from the VideoDecoderConfig
  // (except when it should come from the SPS).
  // https://crbug.com/837337
  double pixel_aspect_ratio = 1.0;
  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 (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::NotifyNewKey() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  if (state_ != State::kWaitingForNewKey) {
    // Note that this method may be called before DoDecode() because the key
    // acquisition stack may be running independently of the media decoding
    // stack. So if this isn't in kWaitingForNewKey state no "resuming" is
    // required therefore no special action taken here.
    return;
  }

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

void D3D11VideoDecoder::NotifyError(const char* reason) {
  state_ = State::kError;
  DLOG(ERROR) << reason;
  if (media_log_) {
    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();
}

void D3D11VideoDecoder::SetCreateDeviceCallbackForTesting(
    D3D11CreateDeviceCB callback) {
  create_device_func_ = std::move(callback);
}

void D3D11VideoDecoder::SetWasSupportedReason(
    D3D11VideoNotSupportedReason enum_value) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  UMA_HISTOGRAM_ENUMERATION("Media.D3D11.WasVideoSupported", enum_value);

  const char* reason = nullptr;
  switch (enum_value) {
    case D3D11VideoNotSupportedReason::kVideoIsSupported:
      reason = "Playback is supported by D3D11VideoDecoder";
      break;
    case D3D11VideoNotSupportedReason::kInsufficientD3D11FeatureLevel:
      reason = "Insufficient D3D11 feature level";
      break;
    case D3D11VideoNotSupportedReason::kProfileNotSupported:
      reason = "Video profile is not supported by D3D11VideoDecoder";
      break;
    case D3D11VideoNotSupportedReason::kCodecNotSupported:
      reason = "H264 is required for D3D11VideoDecoder";
      break;
    case D3D11VideoNotSupportedReason::kZeroCopyNv12Required:
      reason = "Must allow zero-copy NV12 for D3D11VideoDecoder";
      break;
    case D3D11VideoNotSupportedReason::kZeroCopyVideoRequired:
      reason = "Must allow zero-copy video for D3D11VideoDecoder";
      break;
    case D3D11VideoNotSupportedReason::kEncryptedMedia:
      reason = "Encrypted media is not enabled for D3D11VideoDecoder";
      break;
  }

  DVLOG(2) << reason;
  if (media_log_) {
    media_log_->AddEvent(media_log_->CreateStringEvent(
        MediaLogEvent::MEDIA_INFO_LOG_ENTRY, "info", reason));
  }
}

bool D3D11VideoDecoder::IsPotentiallySupported(
    const VideoDecoderConfig& config) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  // TODO(liberato): All of this could be moved into MojoVideoDecoder, so that
  // it could run on the client side and save the IPC hop.

  // Must allow zero-copy of nv12 textures.
  if (!gpu_preferences_.enable_zero_copy_dxgi_video) {
    SetWasSupportedReason(D3D11VideoNotSupportedReason::kZeroCopyNv12Required);
    return false;
  }

  if (gpu_workarounds_.disable_dxgi_zero_copy_video) {
    SetWasSupportedReason(D3D11VideoNotSupportedReason::kZeroCopyVideoRequired);
    return false;
  }

  if (config.profile() == H264PROFILE_HIGH10PROFILE) {
    // H264 HIGH10 is never supported.
    SetWasSupportedReason(D3D11VideoNotSupportedReason::kProfileNotSupported);
    return false;
  }

  if (IsUnsupportedVP9Profile(config)) {
    SetWasSupportedReason(D3D11VideoNotSupportedReason::kProfileNotSupported);
    return false;
  }

  bool encrypted_stream = config.is_encrypted();

  if (encrypted_stream && !base::FeatureList::IsEnabled(kD3D11EncryptedMedia)) {
    SetWasSupportedReason(D3D11VideoNotSupportedReason::kEncryptedMedia);
    return false;
  }

  // Converts one of chromium's VideoCodecProfile options to a dxguid value.
  // If this GUID comes back empty then the profile is not supported.
  GUID decoder_GUID = GetD3D11DecoderGUID(config);

  // If we got the empty guid, fail.
  GUID empty_guid = {};
  if (decoder_GUID == empty_guid) {
    SetWasSupportedReason(D3D11VideoNotSupportedReason::kCodecNotSupported);
    return false;
  }

  // TODO(liberato): It would be nice to QueryD3D11DeviceObjectFromANGLE, but
  // we don't know what thread we're on.
  D3D_FEATURE_LEVEL levels[] = {
      D3D_FEATURE_LEVEL_11_1,  // We need 11.1 for encrypted playback,
      D3D_FEATURE_LEVEL_11_0,  // but make sure we have at least 11.0 for clear.
  };

  // This is also the most expensive check, so make sure it is last.
  HRESULT hr = create_device_func_.Run(
      nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0, levels, ARRAYSIZE(levels),
      D3D11_SDK_VERSION, nullptr, &usable_feature_level_, nullptr);

  if (FAILED(hr)) {
    SetWasSupportedReason(
        D3D11VideoNotSupportedReason::kInsufficientD3D11FeatureLevel);
    return false;
  }

  if (encrypted_stream && usable_feature_level_ == D3D_FEATURE_LEVEL_11_0) {
    SetWasSupportedReason(
        D3D11VideoNotSupportedReason::kInsufficientD3D11FeatureLevel);
    return false;
  }

  // TODO(liberato): dxva checks IsHDR() in the target colorspace, but we don't
  // have the target colorspace.  It's commented as being for vpx, though, so
  // we skip it here for now.
  SetWasSupportedReason(D3D11VideoNotSupportedReason::kVideoIsSupported);
  return true;
}

}  // namespace media
