// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/gpu/windows/dxva_video_decode_accelerator_win.h"

#include <algorithm>
#include <memory>

#if !defined(OS_WIN)
#error This file should only be built on Windows.
#endif  // !defined(OS_WIN)

#include <codecapi.h>
#include <dxgi1_2.h>
#include <ks.h>
#include <mfapi.h>
#include <mferror.h>
#include <ntverp.h>
#include <objbase.h>
#include <stddef.h>
#include <string.h>
#include <wmcodecdsp.h>

#include "base/atomicops.h"
#include "base/base_paths_win.h"
#include "base/bind.h"
#include "base/callback.h"
#include "base/command_line.h"
#include "base/debug/alias.h"
#include "base/file_version_info.h"
#include "base/files/file_path.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/shared_memory.h"
#include "base/metrics/histogram_macros.h"
#include "base/path_service.h"
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
#include "base/threading/thread_local_storage.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
#include "base/win/scoped_co_mem.h"
#include "base/win/windows_version.h"
#include "build/build_config.h"
#include "gpu/config/gpu_driver_bug_workarounds.h"
#include "gpu/config/gpu_preferences.h"
#include "media/base/media_log.h"
#include "media/base/media_switches.h"
#include "media/base/win/mf_helpers.h"
#include "media/base/win/mf_initializer.h"
#include "media/filters/vp9_parser.h"
#include "media/gpu/windows/dxva_picture_buffer_win.h"
#include "media/video/h264_parser.h"
#include "media/video/video_decode_accelerator.h"
#include "third_party/angle/include/EGL/egl.h"
#include "third_party/angle/include/EGL/eglext.h"
#include "ui/display/display_switches.h"
#include "ui/gfx/color_space_win.h"
#include "ui/gl/gl_angle_util_win.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_fence.h"
#include "ui/gl/gl_surface_egl.h"

namespace {

// AMD
// Path is appended on to the PROGRAM_FILES base path.
const wchar_t kAMDVPXDecoderDLLPath[] =
    L"Common Files\\ATI Technologies\\Multimedia\\";

const wchar_t kAMDVP9DecoderDLLName[] =
#if defined(ARCH_CPU_X86)
    L"amf-mft-decvp9-decoder32.dll";
#elif defined(ARCH_CPU_X86_64)
    L"amf-mft-decvp9-decoder64.dll";
#else
#error Unsupported Windows CPU Architecture
#endif

const CLSID CLSID_AMDWebmMfVp9Dec = {
    0x2d2d728a,
    0x67d6,
    0x48ab,
    {0x89, 0xfb, 0xa6, 0xec, 0x65, 0x55, 0x49, 0x70}};

const wchar_t kMSVP9DecoderDLLName[] = L"MSVP9DEC.dll";

const CLSID MEDIASUBTYPE_VP80 = {
    0x30385056,
    0x0000,
    0x0010,
    {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};

const CLSID MEDIASUBTYPE_VP90 = {
    0x30395056,
    0x0000,
    0x0010,
    {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};

// The CLSID of the video processor media foundation transform which we use for
// texture color conversion in DX11.
// Defined in mfidl.h in the Windows 10 SDK. ntverp.h provides VER_PRODUCTBUILD
// to detect which SDK we are compiling with.
#if VER_PRODUCTBUILD < 10011  // VER_PRODUCTBUILD for 10.0.10158.0 SDK.
DEFINE_GUID(CLSID_VideoProcessorMFT,
            0x88753b26,
            0x5b24,
            0x49bd,
            0xb2,
            0xe7,
            0xc,
            0x44,
            0x5c,
            0x78,
            0xc9,
            0x82);
#endif

// MF_XVP_PLAYBACK_MODE
// Data type: UINT32 (treat as BOOL)
// If this attribute is TRUE, the video processor will run in playback mode
// where it allows callers to allocate output samples and allows last frame
// regeneration (repaint).
DEFINE_GUID(MF_XVP_PLAYBACK_MODE,
            0x3c5d293f,
            0xad67,
            0x4e29,
            0xaf,
            0x12,
            0xcf,
            0x3e,
            0x23,
            0x8a,
            0xcc,
            0xe9);

// Defines the GUID for the Intel H264 DXVA device.
static const GUID DXVA2_Intel_ModeH264_E = {
    0x604F8E68,
    0x4951,
    0x4c54,
    {0x88, 0xFE, 0xAB, 0xD2, 0x5C, 0x15, 0xB3, 0xD6}};

// R600, R700, Evergreen and Cayman AMD cards. These support DXVA via UVD3
// or earlier, and don't handle resolutions higher than 1920 x 1088 well.
//
// NOTE: This list must be kept in sorted order.
static const uint16_t kLegacyAmdGpuList[] = {
    0x130f, 0x6700, 0x6701, 0x6702, 0x6703, 0x6704, 0x6705, 0x6706, 0x6707,
    0x6708, 0x6709, 0x6718, 0x6719, 0x671c, 0x671d, 0x671f, 0x6720, 0x6721,
    0x6722, 0x6723, 0x6724, 0x6725, 0x6726, 0x6727, 0x6728, 0x6729, 0x6738,
    0x6739, 0x673e, 0x6740, 0x6741, 0x6742, 0x6743, 0x6744, 0x6745, 0x6746,
    0x6747, 0x6748, 0x6749, 0x674a, 0x6750, 0x6751, 0x6758, 0x6759, 0x675b,
    0x675d, 0x675f, 0x6760, 0x6761, 0x6762, 0x6763, 0x6764, 0x6765, 0x6766,
    0x6767, 0x6768, 0x6770, 0x6771, 0x6772, 0x6778, 0x6779, 0x677b, 0x6798,
    0x67b1, 0x6821, 0x683d, 0x6840, 0x6841, 0x6842, 0x6843, 0x6849, 0x6850,
    0x6858, 0x6859, 0x6880, 0x6888, 0x6889, 0x688a, 0x688c, 0x688d, 0x6898,
    0x6899, 0x689b, 0x689c, 0x689d, 0x689e, 0x68a0, 0x68a1, 0x68a8, 0x68a9,
    0x68b0, 0x68b8, 0x68b9, 0x68ba, 0x68be, 0x68bf, 0x68c0, 0x68c1, 0x68c7,
    0x68c8, 0x68c9, 0x68d8, 0x68d9, 0x68da, 0x68de, 0x68e0, 0x68e1, 0x68e4,
    0x68e5, 0x68e8, 0x68e9, 0x68f1, 0x68f2, 0x68f8, 0x68f9, 0x68fa, 0x68fe,
    0x9400, 0x9401, 0x9402, 0x9403, 0x9405, 0x940a, 0x940b, 0x940f, 0x9440,
    0x9441, 0x9442, 0x9443, 0x9444, 0x9446, 0x944a, 0x944b, 0x944c, 0x944e,
    0x9450, 0x9452, 0x9456, 0x945a, 0x945b, 0x945e, 0x9460, 0x9462, 0x946a,
    0x946b, 0x947a, 0x947b, 0x9480, 0x9487, 0x9488, 0x9489, 0x948a, 0x948f,
    0x9490, 0x9491, 0x9495, 0x9498, 0x949c, 0x949e, 0x949f, 0x94a0, 0x94a1,
    0x94a3, 0x94b1, 0x94b3, 0x94b4, 0x94b5, 0x94b9, 0x94c0, 0x94c1, 0x94c3,
    0x94c4, 0x94c5, 0x94c6, 0x94c7, 0x94c8, 0x94c9, 0x94cb, 0x94cc, 0x94cd,
    0x9500, 0x9501, 0x9504, 0x9505, 0x9506, 0x9507, 0x9508, 0x9509, 0x950f,
    0x9511, 0x9515, 0x9517, 0x9519, 0x9540, 0x9541, 0x9542, 0x954e, 0x954f,
    0x9552, 0x9553, 0x9555, 0x9557, 0x955f, 0x9580, 0x9581, 0x9583, 0x9586,
    0x9587, 0x9588, 0x9589, 0x958a, 0x958b, 0x958c, 0x958d, 0x958e, 0x958f,
    0x9590, 0x9591, 0x9593, 0x9595, 0x9596, 0x9597, 0x9598, 0x9599, 0x959b,
    0x95c0, 0x95c2, 0x95c4, 0x95c5, 0x95c6, 0x95c7, 0x95c9, 0x95cc, 0x95cd,
    0x95ce, 0x95cf, 0x9610, 0x9611, 0x9612, 0x9613, 0x9614, 0x9615, 0x9616,
    0x9640, 0x9641, 0x9642, 0x9643, 0x9644, 0x9645, 0x9647, 0x9648, 0x9649,
    0x964a, 0x964b, 0x964c, 0x964e, 0x964f, 0x9710, 0x9711, 0x9712, 0x9713,
    0x9714, 0x9715, 0x9802, 0x9803, 0x9804, 0x9805, 0x9806, 0x9807, 0x9808,
    0x9809, 0x980a, 0x9830, 0x983d, 0x9850, 0x9851, 0x9874, 0x9900, 0x9901,
    0x9903, 0x9904, 0x9905, 0x9906, 0x9907, 0x9908, 0x9909, 0x990a, 0x990b,
    0x990c, 0x990d, 0x990e, 0x990f, 0x9910, 0x9913, 0x9917, 0x9918, 0x9919,
    0x9990, 0x9991, 0x9992, 0x9993, 0x9994, 0x9995, 0x9996, 0x9997, 0x9998,
    0x9999, 0x999a, 0x999b, 0x999c, 0x999d, 0x99a0, 0x99a2, 0x99a4};

// Legacy Intel GPUs which have trouble even querying if resolutions higher than
// 1920 x 1088 are supported. Updated based on crash reports.
//
// NOTE: This list must be kept in sorted order.
static const uint16_t kLegacyIntelGpuList[] = {
    0x102, 0x106, 0x116, 0x126, 0x152, 0x156, 0x166,
    0x402, 0x406, 0x416, 0x41e, 0xa06, 0xa16, 0xf31,
};

constexpr const wchar_t* const kMediaFoundationVideoDecoderDLLs[] = {
    L"mf.dll", L"mfplat.dll", L"msmpeg2vdec.dll",
};

uint64_t GetCurrentQPC() {
  LARGE_INTEGER perf_counter_now = {};
  // Use raw QueryPerformanceCounter to avoid grabbing locks or allocating
  // memory in an exception handler;
  ::QueryPerformanceCounter(&perf_counter_now);
  return perf_counter_now.QuadPart;
}

uint64_t g_last_process_output_time;
HRESULT g_last_device_removed_reason;

// Certain AMD GPU drivers like R600, R700, Evergreen and Cayman and some second
// generation Intel GPU drivers crash if we create a video device with a
// resolution higher then 1920 x 1088. This function checks if the GPU is in
// this list and if yes returns true.
bool IsLegacyGPU(ID3D11Device* device) {
  DCHECK(std::is_sorted(std::begin(kLegacyAmdGpuList),
                        std::end(kLegacyAmdGpuList)));
  DCHECK(std::is_sorted(std::begin(kLegacyIntelGpuList),
                        std::end(kLegacyIntelGpuList)));

  constexpr int kAMDGPUId1 = 0x1002;
  constexpr int kAMDGPUId2 = 0x1022;
  constexpr int kIntelGPU = 0x8086;

  Microsoft::WRL::ComPtr<IDXGIDevice> dxgi_device;
  HRESULT hr = device->QueryInterface(IID_PPV_ARGS(&dxgi_device));
  if (FAILED(hr))
    return true;

  Microsoft::WRL::ComPtr<IDXGIAdapter> adapter;
  hr = dxgi_device->GetAdapter(adapter.GetAddressOf());
  if (FAILED(hr))
    return true;

  DXGI_ADAPTER_DESC adapter_desc = {};
  hr = adapter->GetDesc(&adapter_desc);
  if (FAILED(hr))
    return true;

  // All the values in the legacy gpu list are uint16_t.
  if (adapter_desc.DeviceId > std::numeric_limits<uint16_t>::max())
    return false;

  const uint16_t device_id = adapter_desc.DeviceId;

  // We check if the device is an Intel or an AMD device and whether it is in
  // the global list defined by the kLegacyAmdGpuList and kLegacyIntelGpuList
  // arrays above. If yes then the device is treated as a legacy device.
  if (adapter_desc.VendorId == kAMDGPUId1 ||
      adapter_desc.VendorId == kAMDGPUId2) {
    if (std::binary_search(std::begin(kLegacyAmdGpuList),
                           std::end(kLegacyAmdGpuList), device_id)) {
      return true;
    }
  } else if (adapter_desc.VendorId == kIntelGPU) {
    if (std::binary_search(std::begin(kLegacyIntelGpuList),
                           std::end(kLegacyIntelGpuList), device_id)) {
      return true;
    }
  }

  return false;
}

// Returns true if a ID3D11VideoDecoder can be created for |resolution_to_test|
// on the given |video_device|.
bool IsResolutionSupportedForDevice(const gfx::Size& resolution_to_test,
                                    const GUID& decoder_guid,
                                    ID3D11VideoDevice* video_device) {
  D3D11_VIDEO_DECODER_DESC desc = {};
  desc.Guid = decoder_guid;
  desc.SampleWidth = resolution_to_test.width();
  desc.SampleHeight = resolution_to_test.height();
  desc.OutputFormat = DXGI_FORMAT_NV12;
  UINT config_count = 0;
  HRESULT hr = video_device->GetVideoDecoderConfigCount(&desc, &config_count);
  if (FAILED(hr) || config_count == 0)
    return false;

  D3D11_VIDEO_DECODER_CONFIG config = {};
  hr = video_device->GetVideoDecoderConfig(&desc, 0, &config);
  UMA_HISTOGRAM_BOOLEAN("Media.DXVAVDA.GetDecoderConfigStatus", SUCCEEDED(hr));
  if (FAILED(hr))
    return false;

  Microsoft::WRL::ComPtr<ID3D11VideoDecoder> video_decoder;
  hr = video_device->CreateVideoDecoder(&desc, &config,
                                        video_decoder.GetAddressOf());
  UMA_HISTOGRAM_BOOLEAN("Media.DXVAVDA.CreateDecoderStatus", !!video_decoder);
  return !!video_decoder;
}

// Returns a tuple of (LandscapeMax, PortraitMax). If landscape maximum can not
// be computed, the value of |default_max| is returned for the landscape maximum
// and a zero size value is returned for portrait max (erring conservatively).
using ResolutionPair = std::pair<gfx::Size, gfx::Size>;
ResolutionPair GetMaxResolutionsForGUIDs(
    const gfx::Size& default_max,
    ID3D11VideoDevice* video_device,
    const std::vector<GUID>& valid_guids,
    const std::vector<gfx::Size>& resolutions_to_test) {
  TRACE_EVENT0("gpu,startup", "GetMaxResolutionsForGUIDs");
  ResolutionPair result(default_max, gfx::Size());

  // Enumerate supported video profiles and look for the profile.
  GUID decoder_guid = GUID_NULL;
  UINT profile_count = video_device->GetVideoDecoderProfileCount();
  for (UINT profile_idx = 0; profile_idx < profile_count; profile_idx++) {
    GUID profile_id = {};
    if (SUCCEEDED(
            video_device->GetVideoDecoderProfile(profile_idx, &profile_id)) &&
        std::find(valid_guids.begin(), valid_guids.end(), profile_id) !=
            valid_guids.end()) {
      decoder_guid = profile_id;
      break;
    }
  }
  if (decoder_guid == GUID_NULL)
    return result;

  // Verify input is in ascending order by height.
  DCHECK(std::is_sorted(resolutions_to_test.begin(), resolutions_to_test.end(),
                        [](const gfx::Size& a, const gfx::Size& b) {
                          return a.height() < b.height();
                        }));

  for (const auto& res : resolutions_to_test) {
    if (!IsResolutionSupportedForDevice(res, decoder_guid, video_device))
      break;
    result.first = res;
  }

  // The max supported portrait resolution should be just be a w/h flip of the
  // max supported landscape resolution.
  gfx::Size flipped(result.first.height(), result.first.width());
  if (IsResolutionSupportedForDevice(flipped, decoder_guid, video_device))
    result.second = flipped;

  return result;
}

}  // namespace

namespace media {

static const VideoCodecProfile kSupportedProfiles[] = {
    H264PROFILE_BASELINE, H264PROFILE_MAIN,    H264PROFILE_HIGH,
    VP8PROFILE_ANY,       VP9PROFILE_PROFILE0, VP9PROFILE_PROFILE1,
    VP9PROFILE_PROFILE2,  VP9PROFILE_PROFILE3};

CreateDXGIDeviceManager
    DXVAVideoDecodeAccelerator::create_dxgi_device_manager_ = NULL;

enum {
  // Maximum number of iterations we allow before aborting the attempt to flush
  // the batched queries to the driver and allow torn/corrupt frames to be
  // rendered.
  kFlushDecoderSurfaceTimeoutMs = 1,
  // Maximum iterations where we try to flush the d3d device.
  kMaxIterationsForD3DFlush = 4,
  // Maximum iterations where we try to flush the ANGLE device before reusing
  // the texture.
  kMaxIterationsForANGLEReuseFlush = 16,
  // We only request 5 picture buffers from the client which are used to hold
  // the decoded samples. These buffers are then reused when the client tells
  // us that it is done with the buffer.
  kNumPictureBuffers = 5,
  // When GetTextureTarget() returns GL_TEXTURE_EXTERNAL_OES, allocated
  // PictureBuffers do not consume significant resources, so we can optimize for
  // latency more aggressively.
  kNumPictureBuffersForZeroCopy = 10,
  // The keyed mutex should always be released before the other thread
  // attempts to acquire it, so AcquireSync should always return immediately.
  kAcquireSyncWaitMs = 0,
};

// Creates a Media Foundation sample with one buffer containing a copy of the
// given Annex B stream data.
// If duration and sample time are not known, provide 0.
// |min_size| specifies the minimum size of the buffer (might be required by
// the decoder for input). If no alignment is required, provide 0.
static Microsoft::WRL::ComPtr<IMFSample> CreateInputSample(
    const uint8_t* stream,
    uint32_t size,
    uint32_t min_size,
    int alignment) {
  CHECK(stream);
  CHECK_GT(size, 0U);
  Microsoft::WRL::ComPtr<IMFSample> sample;
  sample = mf::CreateEmptySampleWithBuffer(std::max(min_size, size), alignment);
  RETURN_ON_FAILURE(sample.Get(), "Failed to create empty sample",
                    Microsoft::WRL::ComPtr<IMFSample>());

  Microsoft::WRL::ComPtr<IMFMediaBuffer> buffer;
  HRESULT hr = sample->GetBufferByIndex(0, buffer.GetAddressOf());
  RETURN_ON_HR_FAILURE(hr, "Failed to get buffer from sample",
                       Microsoft::WRL::ComPtr<IMFSample>());

  DWORD max_length = 0;
  DWORD current_length = 0;
  uint8_t* destination = NULL;
  hr = buffer->Lock(&destination, &max_length, &current_length);
  RETURN_ON_HR_FAILURE(hr, "Failed to lock buffer",
                       Microsoft::WRL::ComPtr<IMFSample>());

  CHECK_EQ(current_length, 0u);
  CHECK_GE(max_length, size);
  memcpy(destination, stream, size);

  hr = buffer->SetCurrentLength(size);
  RETURN_ON_HR_FAILURE(hr, "Failed to set buffer length",
                       Microsoft::WRL::ComPtr<IMFSample>());

  hr = buffer->Unlock();
  RETURN_ON_HR_FAILURE(hr, "Failed to unlock buffer",
                       Microsoft::WRL::ComPtr<IMFSample>());

  return sample;
}

// Helper function to create a COM object instance from a DLL. The alternative
// is to use the CoCreateInstance API which requires the COM apartment to be
// initialized which is not the case on the GPU main thread. We want to avoid
// initializing COM as it may have sideeffects.
HRESULT CreateCOMObjectFromDll(HMODULE dll,
                               const CLSID& clsid,
                               const IID& iid,
                               void** object) {
  if (!dll || !object)
    return E_INVALIDARG;

  using GetClassObject =
      HRESULT(WINAPI*)(const CLSID& clsid, const IID& iid, void** object);

  GetClassObject get_class_object = reinterpret_cast<GetClassObject>(
      GetProcAddress(dll, "DllGetClassObject"));
  RETURN_ON_FAILURE(get_class_object, "Failed to get DllGetClassObject pointer",
                    E_FAIL);

  Microsoft::WRL::ComPtr<IClassFactory> factory;
  HRESULT hr = get_class_object(clsid, IID_PPV_ARGS(&factory));
  RETURN_ON_HR_FAILURE(hr, "DllGetClassObject failed", hr);

  hr = factory->CreateInstance(NULL, iid, object);
  return hr;
}

ConfigChangeDetector::~ConfigChangeDetector() {}

// Provides functionality to detect H.264 stream configuration changes.
// TODO(ananta)
// Move this to a common place so that all VDA's can use this.
class H264ConfigChangeDetector : public ConfigChangeDetector {
 public:
  H264ConfigChangeDetector();
  ~H264ConfigChangeDetector() override;

  // Detects stream configuration changes.
  // Returns false on failure.
  bool DetectConfig(const uint8_t* stream, unsigned int size) override;
  gfx::Rect current_visible_rect(
      const gfx::Rect& container_visible_rect) const override;
  VideoColorSpace current_color_space(
      const VideoColorSpace& container_color_space) const override;

 private:
  // These fields are used to track the SPS/PPS in the H.264 bitstream and
  // are eventually compared against the SPS/PPS in the bitstream to detect
  // a change.
  int last_sps_id_;
  std::vector<uint8_t> last_sps_;
  int last_pps_id_;
  std::vector<uint8_t> last_pps_;
  // We want to indicate configuration changes only after we see IDR slices.
  // This flag tracks that we potentially have a configuration change which
  // we want to honor after we see an IDR slice.
  bool pending_config_changed_;

  std::unique_ptr<H264Parser> parser_;

  DISALLOW_COPY_AND_ASSIGN(H264ConfigChangeDetector);
};

H264ConfigChangeDetector::H264ConfigChangeDetector()
    : last_sps_id_(0), last_pps_id_(0), pending_config_changed_(false) {}

H264ConfigChangeDetector::~H264ConfigChangeDetector() {}

bool H264ConfigChangeDetector::DetectConfig(const uint8_t* stream,
                                            unsigned int size) {
  std::vector<uint8_t> sps;
  std::vector<uint8_t> pps;
  H264NALU nalu;
  bool idr_seen = false;

  if (!parser_.get())
    parser_.reset(new H264Parser);

  parser_->SetStream(stream, size);
  config_changed_ = false;

  while (true) {
    H264Parser::Result result = parser_->AdvanceToNextNALU(&nalu);

    if (result == H264Parser::kEOStream)
      break;

    if (result == H264Parser::kUnsupportedStream) {
      DLOG(ERROR) << "Unsupported H.264 stream";
      return false;
    }

    if (result != H264Parser::kOk) {
      DLOG(ERROR) << "Failed to parse H.264 stream";
      return false;
    }

    switch (nalu.nal_unit_type) {
      case H264NALU::kSPS:
        result = parser_->ParseSPS(&last_sps_id_);
        if (result == H264Parser::kUnsupportedStream) {
          DLOG(ERROR) << "Unsupported SPS";
          return false;
        }

        if (result != H264Parser::kOk) {
          DLOG(ERROR) << "Could not parse SPS";
          return false;
        }

        sps.assign(nalu.data, nalu.data + nalu.size);
        break;

      case H264NALU::kPPS:
        result = parser_->ParsePPS(&last_pps_id_);
        if (result == H264Parser::kUnsupportedStream) {
          DLOG(ERROR) << "Unsupported PPS";
          return false;
        }
        if (result != H264Parser::kOk) {
          DLOG(ERROR) << "Could not parse PPS";
          return false;
        }
        pps.assign(nalu.data, nalu.data + nalu.size);
        break;

      case H264NALU::kIDRSlice:
        idr_seen = true;
        // If we previously detected a configuration change, and see an IDR
        // slice next time around, we need to flag a configuration change.
        if (pending_config_changed_) {
          config_changed_ = true;
          pending_config_changed_ = false;
        }
        break;

      default:
        break;
    }
  }

  if (!sps.empty() && sps != last_sps_) {
    if (!last_sps_.empty()) {
      // Flag configuration changes after we see an IDR slice.
      if (idr_seen) {
        config_changed_ = true;
      } else {
        pending_config_changed_ = true;
      }
    }
    last_sps_.swap(sps);
  }

  if (!pps.empty() && pps != last_pps_) {
    if (!last_pps_.empty()) {
      // Flag configuration changes after we see an IDR slice.
      if (idr_seen) {
        config_changed_ = true;
      } else {
        pending_config_changed_ = true;
      }
    }
    last_pps_.swap(pps);
  }
  return true;
}

gfx::Rect H264ConfigChangeDetector::current_visible_rect(
    const gfx::Rect& container_visible_rect) const {
  if (!parser_)
    return container_visible_rect;
  // TODO(hubbe): Is using last_sps_id_ correct here?
  const H264SPS* sps = parser_->GetSPS(last_sps_id_);
  if (!sps)
    return container_visible_rect;
  return sps->GetVisibleRect().value_or(container_visible_rect);
}

VideoColorSpace H264ConfigChangeDetector::current_color_space(
    const VideoColorSpace& container_color_space) const {
  if (!parser_)
    return container_color_space;
  // TODO(hubbe): Is using last_sps_id_ correct here?
  const H264SPS* sps = parser_->GetSPS(last_sps_id_);
  if (sps && sps->GetColorSpace().IsSpecified()) {
    return sps->GetColorSpace();
  }
  return container_color_space;
}

// Doesn't actually detect config changes, only stream metadata.
class VP9ConfigChangeDetector : public ConfigChangeDetector {
 public:
  VP9ConfigChangeDetector() : ConfigChangeDetector(), parser_(false) {}
  ~VP9ConfigChangeDetector() override {}

  // Detects stream configuration changes.
  // Returns false on failure.
  bool DetectConfig(const uint8_t* stream, unsigned int size) override {
    parser_.SetStream(stream, size);
    Vp9FrameHeader fhdr;
    while (parser_.ParseNextFrame(&fhdr) == Vp9Parser::kOk) {
      visible_rect_ = gfx::Rect(fhdr.render_width, fhdr.render_height);

      // TODO(hubbe): move the conversion from Vp9FrameHeader to VideoColorSpace
      // into a common, reusable location.
      color_space_.range = fhdr.color_range ? gfx::ColorSpace::RangeID::FULL
                                            : gfx::ColorSpace::RangeID::INVALID;
      color_space_.primaries = VideoColorSpace::PrimaryID::INVALID;
      color_space_.transfer = VideoColorSpace::TransferID::INVALID;
      color_space_.matrix = VideoColorSpace::MatrixID::INVALID;
      switch (fhdr.color_space) {
        case Vp9ColorSpace::RESERVED:
        case Vp9ColorSpace::UNKNOWN:
          break;
        case Vp9ColorSpace::BT_601:
        case Vp9ColorSpace::SMPTE_170:
          color_space_.primaries = VideoColorSpace::PrimaryID::SMPTE170M;
          color_space_.transfer = VideoColorSpace::TransferID::SMPTE170M;
          color_space_.matrix = VideoColorSpace::MatrixID::SMPTE170M;
          break;
        case Vp9ColorSpace::BT_709:
          color_space_.primaries = VideoColorSpace::PrimaryID::BT709;
          color_space_.transfer = VideoColorSpace::TransferID::BT709;
          color_space_.matrix = VideoColorSpace::MatrixID::BT709;
          break;
        case Vp9ColorSpace::SMPTE_240:
          color_space_.primaries = VideoColorSpace::PrimaryID::SMPTE240M;
          color_space_.transfer = VideoColorSpace::TransferID::SMPTE240M;
          color_space_.matrix = VideoColorSpace::MatrixID::SMPTE240M;
          break;
        case Vp9ColorSpace::BT_2020:
          color_space_.primaries = VideoColorSpace::PrimaryID::BT2020;
          color_space_.transfer = VideoColorSpace::TransferID::BT2020_10;
          color_space_.matrix = VideoColorSpace::MatrixID::BT2020_NCL;
          break;
        case Vp9ColorSpace::SRGB:
          color_space_.primaries = VideoColorSpace::PrimaryID::BT709;
          color_space_.transfer = VideoColorSpace::TransferID::IEC61966_2_1;
          color_space_.matrix = VideoColorSpace::MatrixID::BT709;
          break;
      }

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

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

  gfx::Rect current_visible_rect(
      const gfx::Rect& container_visible_rect) const override {
    return visible_rect_.IsEmpty() ? container_visible_rect : visible_rect_;
  }

  VideoColorSpace current_color_space(
      const VideoColorSpace& container_color_space) const override {
    // For VP9, container color spaces override video stream color spaces.
    if (container_color_space.IsSpecified()) {
      return container_color_space;
    }
    return color_space_;
  }

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

DXVAVideoDecodeAccelerator::PendingSampleInfo::PendingSampleInfo(
    int32_t buffer_id,
    Microsoft::WRL::ComPtr<IMFSample> sample,
    const gfx::Rect& visible_rect,
    const gfx::ColorSpace& color_space)
    : input_buffer_id(buffer_id),
      picture_buffer_id(-1),
      visible_rect(visible_rect),
      color_space(color_space),
      output_sample(sample) {}

DXVAVideoDecodeAccelerator::PendingSampleInfo::PendingSampleInfo(
    const PendingSampleInfo& other) = default;

DXVAVideoDecodeAccelerator::PendingSampleInfo::~PendingSampleInfo() {}

DXVAVideoDecodeAccelerator::DXVAVideoDecodeAccelerator(
    const GetGLContextCallback& get_gl_context_cb,
    const MakeGLContextCurrentCallback& make_context_current_cb,
    const BindGLImageCallback& bind_image_cb,
    const gpu::GpuDriverBugWorkarounds& workarounds,
    const gpu::GpuPreferences& gpu_preferences,
    MediaLog* media_log)
    : client_(NULL),
      dev_manager_reset_token_(0),
      dx11_dev_manager_reset_token_(0),
      egl_config_(NULL),
      state_(kUninitialized),
      pictures_requested_(false),
      inputs_before_decode_(0),
      sent_drain_message_(false),
      get_gl_context_cb_(get_gl_context_cb),
      make_context_current_cb_(make_context_current_cb),
      bind_image_cb_(bind_image_cb),
      media_log_(media_log),
      codec_(kUnknownVideoCodec),
      decoder_thread_("DXVAVideoDecoderThread"),
      pending_flush_(false),
      enable_low_latency_(gpu_preferences.enable_low_latency_dxva),
      support_share_nv12_textures_(
          gpu_preferences.enable_zero_copy_dxgi_video &&
          !workarounds.disable_dxgi_zero_copy_video),
      num_picture_buffers_requested_(support_share_nv12_textures_
                                         ? kNumPictureBuffersForZeroCopy
                                         : kNumPictureBuffers),
      support_copy_nv12_textures_(gpu_preferences.enable_nv12_dxgi_video &&
                                  !workarounds.disable_nv12_dxgi_video),
      support_delayed_copy_nv12_textures_(
          base::FeatureList::IsEnabled(kDelayCopyNV12Textures) &&
          !workarounds.disable_delayed_copy_nv12),
      use_dx11_(false),
      use_keyed_mutex_(false),
      using_angle_device_(false),
      enable_accelerated_vpx_decode_(
          workarounds.disable_accelerated_vpx_decode
              ? gpu::GpuPreferences::VpxDecodeVendors::VPX_VENDOR_NONE
              : gpu_preferences.enable_accelerated_vpx_decode),
      processing_config_changed_(false),
      weak_this_factory_(this) {
  weak_ptr_ = weak_this_factory_.GetWeakPtr();
  memset(&input_stream_info_, 0, sizeof(input_stream_info_));
  memset(&output_stream_info_, 0, sizeof(output_stream_info_));
  use_color_info_ = base::FeatureList::IsEnabled(kVideoBlitColorAccuracy);
}

DXVAVideoDecodeAccelerator::~DXVAVideoDecodeAccelerator() {
  client_ = NULL;
}

bool DXVAVideoDecodeAccelerator::Initialize(const Config& config,
                                            Client* client) {
  if (!get_gl_context_cb_ || !make_context_current_cb_) {
    NOTREACHED() << "GL callbacks are required for this VDA";
    return false;
  }

  if (config.is_encrypted()) {
    NOTREACHED() << "Encrypted streams are not supported for this VDA";
    return false;
  }

  if (config.output_mode != Config::OutputMode::ALLOCATE) {
    NOTREACHED() << "Only ALLOCATE OutputMode is supported by this VDA";
    return false;
  }

  client_ = client;

  main_thread_task_runner_ = base::ThreadTaskRunnerHandle::Get();

  if (!config.supported_output_formats.empty() &&
      !base::ContainsValue(config.supported_output_formats,
                           PIXEL_FORMAT_NV12)) {
    DisableSharedTextureSupport();
    support_copy_nv12_textures_ = false;
  }

  bool profile_supported = false;
  for (const auto& supported_profile : kSupportedProfiles) {
    if (config.profile == supported_profile) {
      profile_supported = true;
      break;
    }
  }
  if (!profile_supported) {
    RETURN_AND_NOTIFY_ON_FAILURE(false,
                                 "Unsupported h.264, vp8, or vp9 profile",
                                 PLATFORM_FAILURE, false);
  }

  if (config.profile == VP9PROFILE_PROFILE2 ||
      config.profile == VP9PROFILE_PROFILE3 ||
      config.profile == H264PROFILE_HIGH10PROFILE) {
    // Input file has more than 8 bits per channel.
    use_fp16_ = true;
  }

  // Unfortunately, the profile is currently unreliable for
  // VP9 (https://crbug.com/592074) so also try to use fp16 if HDR is on.
  if (config.target_color_space.IsHDR()) {
    use_fp16_ = true;
  }

  // Not all versions of Windows 7 and later include Media Foundation DLLs.
  // Instead of crashing while delay loading the DLL when calling MFStartup()
  // below, probe whether we can successfully load the DLL now.
  // See http://crbug.com/339678 for details.
  HMODULE dxgi_manager_dll = ::GetModuleHandle(L"MFPlat.dll");
  RETURN_ON_FAILURE(dxgi_manager_dll, "MFPlat.dll is required for decoding",
                    false);

// On Windows 8+ mfplat.dll provides the MFCreateDXGIDeviceManager API.
// On Windows 7 mshtmlmedia.dll provides it.

// TODO(ananta)
// The code below works, as in we can create the DX11 device manager for
// Windows 7. However the IMFTransform we use for texture conversion and
// copy does not exist on Windows 7. Look into an alternate approach
// and enable the code below.
#if defined(ENABLE_DX11_FOR_WIN7)
  if (base::win::GetVersion() == base::win::VERSION_WIN7) {
    dxgi_manager_dll = ::GetModuleHandle(L"mshtmlmedia.dll");
    RETURN_ON_FAILURE(dxgi_manager_dll,
                      "mshtmlmedia.dll is required for decoding", false);
  }
#endif
  // If we don't find the MFCreateDXGIDeviceManager API we fallback to D3D9
  // decoding.
  if (dxgi_manager_dll && !create_dxgi_device_manager_) {
    create_dxgi_device_manager_ = reinterpret_cast<CreateDXGIDeviceManager>(
        ::GetProcAddress(dxgi_manager_dll, "MFCreateDXGIDeviceManager"));
  }

  RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_cb_.Run(),
                               "Failed to make context current",
                               PLATFORM_FAILURE, false);

  RETURN_AND_NOTIFY_ON_FAILURE(
      gl::g_driver_egl.ext.b_EGL_ANGLE_surface_d3d_texture_2d_share_handle,
      "EGL_ANGLE_surface_d3d_texture_2d_share_handle unavailable",
      PLATFORM_FAILURE, false);

  RETURN_AND_NOTIFY_ON_FAILURE(gl::GLFence::IsSupported(),
                               "GL fences are unsupported", PLATFORM_FAILURE,
                               false);

  State state = GetState();
  RETURN_AND_NOTIFY_ON_FAILURE((state == kUninitialized),
                               "Initialize: invalid state: " << state,
                               ILLEGAL_STATE, false);

  RETURN_AND_NOTIFY_ON_FAILURE(InitializeMediaFoundation(),
                               "Could not initialize Media Foundartion",
                               PLATFORM_FAILURE, false);

  config_ = config;

  RETURN_AND_NOTIFY_ON_FAILURE(InitDecoder(config.profile),
                               "Failed to initialize decoder", PLATFORM_FAILURE,
                               false);

  RETURN_AND_NOTIFY_ON_FAILURE(GetStreamsInfoAndBufferReqs(),
                               "Failed to get input/output stream info.",
                               PLATFORM_FAILURE, false);

  RETURN_AND_NOTIFY_ON_FAILURE(
      SendMFTMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0),
      "Send MFT_MESSAGE_NOTIFY_BEGIN_STREAMING notification failed",
      PLATFORM_FAILURE, false);

  RETURN_AND_NOTIFY_ON_FAILURE(
      SendMFTMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0),
      "Send MFT_MESSAGE_NOTIFY_START_OF_STREAM notification failed",
      PLATFORM_FAILURE, false);

  if (codec_ == kCodecH264)
    config_change_detector_.reset(new H264ConfigChangeDetector);
  if (codec_ == kCodecVP9)
    config_change_detector_.reset(new VP9ConfigChangeDetector);

  SetState(kNormal);

  UMA_HISTOGRAM_ENUMERATION("Media.DXVAVDA.PictureBufferMechanism",
                            GetPictureBufferMechanism());

  return StartDecoderThread();
}

bool DXVAVideoDecodeAccelerator::CreateD3DDevManager() {
  TRACE_EVENT0("gpu", "DXVAVideoDecodeAccelerator_CreateD3DDevManager");
  // The device may exist if the last state was a config change.
  if (d3d9_.Get())
    return true;

  HRESULT hr = E_FAIL;

  hr = Direct3DCreate9Ex(D3D_SDK_VERSION, d3d9_.GetAddressOf());
  RETURN_ON_HR_FAILURE(hr, "Direct3DCreate9Ex failed", false);

  hr = d3d9_->CheckDeviceFormatConversion(
      D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
      static_cast<D3DFORMAT>(MAKEFOURCC('N', 'V', '1', '2')), D3DFMT_X8R8G8B8);
  RETURN_ON_HR_FAILURE(hr, "D3D9 driver does not support H/W format conversion",
                       false);

  Microsoft::WRL::ComPtr<IDirect3DDevice9> angle_device =
      gl::QueryD3D9DeviceObjectFromANGLE();
  if (angle_device.Get())
    using_angle_device_ = true;

  if (using_angle_device_) {
    hr = angle_device.CopyTo(d3d9_device_ex_.GetAddressOf());
    RETURN_ON_HR_FAILURE(
        hr, "QueryInterface for IDirect3DDevice9Ex from angle device failed",
        false);
  } else {
    D3DPRESENT_PARAMETERS present_params = {0};
    present_params.BackBufferWidth = 1;
    present_params.BackBufferHeight = 1;
    present_params.BackBufferFormat = D3DFMT_UNKNOWN;
    present_params.BackBufferCount = 1;
    present_params.SwapEffect = D3DSWAPEFFECT_DISCARD;
    present_params.hDeviceWindow = NULL;
    present_params.Windowed = TRUE;
    present_params.Flags = D3DPRESENTFLAG_VIDEO;
    present_params.FullScreen_RefreshRateInHz = 0;
    present_params.PresentationInterval = 0;

    hr = d3d9_->CreateDeviceEx(
        D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, NULL,
        D3DCREATE_FPU_PRESERVE | D3DCREATE_MIXED_VERTEXPROCESSING |
            D3DCREATE_MULTITHREADED,
        &present_params, NULL, d3d9_device_ex_.GetAddressOf());
    RETURN_ON_HR_FAILURE(hr, "Failed to create D3D device", false);
  }

  hr = DXVA2CreateDirect3DDeviceManager9(&dev_manager_reset_token_,
                                         device_manager_.GetAddressOf());
  RETURN_ON_HR_FAILURE(hr, "DXVA2CreateDirect3DDeviceManager9 failed", false);

  hr = device_manager_->ResetDevice(d3d9_device_ex_.Get(),
                                    dev_manager_reset_token_);
  RETURN_ON_HR_FAILURE(hr, "Failed to reset device", false);

  hr = d3d9_device_ex_->CreateQuery(D3DQUERYTYPE_EVENT, query_.GetAddressOf());
  RETURN_ON_HR_FAILURE(hr, "Failed to create D3D device query", false);
  // Ensure query_ API works (to avoid an infinite loop later in
  // CopyOutputSampleDataToPictureBuffer).
  hr = query_->Issue(D3DISSUE_END);
  RETURN_ON_HR_FAILURE(hr, "Failed to issue END test query", false);

  CreateVideoProcessor();
  return true;
}

bool DXVAVideoDecodeAccelerator::CreateVideoProcessor() {
  if (!use_color_info_)
    return false;

  // TODO(Hubbe): Don't try again if we tried and failed already.
  if (video_processor_service_.Get())
    return true;
  HRESULT hr = DXVA2CreateVideoService(d3d9_device_ex_.Get(),
                                       IID_PPV_ARGS(&video_processor_service_));
  RETURN_ON_HR_FAILURE(hr, "DXVA2CreateVideoService failed", false);

  // TODO(Hubbe): Use actual video settings.
  DXVA2_VideoDesc inputDesc;
  inputDesc.SampleWidth = 1920;
  inputDesc.SampleHeight = 1080;
  inputDesc.SampleFormat.VideoChromaSubsampling =
      DXVA2_VideoChromaSubsampling_MPEG2;
  inputDesc.SampleFormat.NominalRange = DXVA2_NominalRange_16_235;
  inputDesc.SampleFormat.VideoTransferMatrix = DXVA2_VideoTransferMatrix_BT709;
  inputDesc.SampleFormat.VideoLighting = DXVA2_VideoLighting_dim;
  inputDesc.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_BT709;
  inputDesc.SampleFormat.VideoTransferFunction = DXVA2_VideoTransFunc_709;
  inputDesc.SampleFormat.SampleFormat = DXVA2_SampleProgressiveFrame;
  inputDesc.Format = (D3DFORMAT)MAKEFOURCC('N', 'V', '1', '2');
  inputDesc.InputSampleFreq.Numerator = 30;
  inputDesc.InputSampleFreq.Denominator = 1;
  inputDesc.OutputFrameFreq.Numerator = 30;
  inputDesc.OutputFrameFreq.Denominator = 1;

  UINT guid_count = 0;
  base::win::ScopedCoMem<GUID> guids;
  hr = video_processor_service_->GetVideoProcessorDeviceGuids(
      &inputDesc, &guid_count, &guids);
  RETURN_ON_HR_FAILURE(hr, "GetVideoProcessorDeviceGuids failed", false);

  for (UINT g = 0; g < guid_count; g++) {
    DXVA2_VideoProcessorCaps caps;
    hr = video_processor_service_->GetVideoProcessorCaps(
        guids[g], &inputDesc, D3DFMT_X8R8G8B8, &caps);
    if (hr)
      continue;

    if (!(caps.VideoProcessorOperations & DXVA2_VideoProcess_YUV2RGB))
      continue;

    base::win::ScopedCoMem<D3DFORMAT> formats;
    UINT format_count = 0;
    hr = video_processor_service_->GetVideoProcessorRenderTargets(
        guids[g], &inputDesc, &format_count, &formats);
    if (hr)
      continue;

    UINT f;
    for (f = 0; f < format_count; f++) {
      if (formats[f] == D3DFMT_X8R8G8B8) {
        break;
      }
    }
    if (f == format_count)
      continue;

    // Create video processor
    hr = video_processor_service_->CreateVideoProcessor(
        guids[g], &inputDesc, D3DFMT_X8R8G8B8, 0, processor_.GetAddressOf());
    if (hr)
      continue;

    DXVA2_ValueRange range;
    processor_->GetProcAmpRange(DXVA2_ProcAmp_Brightness, &range);
    default_procamp_values_.Brightness = range.DefaultValue;
    processor_->GetProcAmpRange(DXVA2_ProcAmp_Contrast, &range);
    default_procamp_values_.Contrast = range.DefaultValue;
    processor_->GetProcAmpRange(DXVA2_ProcAmp_Hue, &range);
    default_procamp_values_.Hue = range.DefaultValue;
    processor_->GetProcAmpRange(DXVA2_ProcAmp_Saturation, &range);
    default_procamp_values_.Saturation = range.DefaultValue;

    return true;
  }
  return false;
}

bool DXVAVideoDecodeAccelerator::CreateDX11DevManager() {
  // The device may exist if the last state was a config change.
  if (D3D11Device())
    return true;

  HRESULT hr = create_dxgi_device_manager_(
      &dx11_dev_manager_reset_token_, d3d11_device_manager_.GetAddressOf());
  RETURN_ON_HR_FAILURE(hr, "MFCreateDXGIDeviceManager failed", false);

  angle_device_ = gl::QueryD3D11DeviceObjectFromANGLE();
  if (!angle_device_) {
    support_copy_nv12_textures_ = false;
  }
  if (ShouldUseANGLEDevice()) {
    RETURN_ON_FAILURE(angle_device_.Get(), "Failed to get d3d11 device", false);

    using_angle_device_ = true;
    DCHECK(!use_fp16_);
    angle_device_->GetImmediateContext(d3d11_device_context_.GetAddressOf());

    hr = angle_device_.CopyTo(video_device_.GetAddressOf());
    RETURN_ON_HR_FAILURE(hr, "Failed to get video device", false);
  } else {
    // This array defines the set of DirectX hardware feature levels we support.
    // The ordering MUST be preserved. All applications are assumed to support
    // 9.1 unless otherwise stated by the application.
    D3D_FEATURE_LEVEL feature_levels[] = {
        D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1,
        D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_9_3,  D3D_FEATURE_LEVEL_9_2,
        D3D_FEATURE_LEVEL_9_1};

    UINT flags = D3D11_CREATE_DEVICE_VIDEO_SUPPORT;

    D3D_FEATURE_LEVEL feature_level_out = D3D_FEATURE_LEVEL_11_0;
#if defined _DEBUG
    flags |= D3D11_CREATE_DEVICE_DEBUG;

    hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, flags,
                           feature_levels, arraysize(feature_levels),
                           D3D11_SDK_VERSION, d3d11_device_.GetAddressOf(),
                           &feature_level_out,
                           d3d11_device_context_.GetAddressOf());
    if (hr == DXGI_ERROR_SDK_COMPONENT_MISSING) {
      LOG(ERROR)
          << "Debug DXGI device creation failed, falling back to release.";
      flags &= ~D3D11_CREATE_DEVICE_DEBUG;
    } else {
      RETURN_ON_HR_FAILURE(hr, "Failed to create debug DX11 device", false);
    }
#endif
    if (!d3d11_device_context_) {
      hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, flags,
                             feature_levels, arraysize(feature_levels),
                             D3D11_SDK_VERSION, d3d11_device_.GetAddressOf(),
                             &feature_level_out,
                             d3d11_device_context_.GetAddressOf());
      RETURN_ON_HR_FAILURE(hr, "Failed to create DX11 device", false);
    }

    hr = d3d11_device_.CopyTo(video_device_.GetAddressOf());
    RETURN_ON_HR_FAILURE(hr, "Failed to get video device", false);
  }

  hr = d3d11_device_context_.CopyTo(video_context_.GetAddressOf());
  RETURN_ON_HR_FAILURE(hr, "Failed to get video context", false);

  D3D11_FEATURE_DATA_D3D11_OPTIONS options;
  hr = D3D11Device()->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &options,
                                          sizeof(options));
  RETURN_ON_HR_FAILURE(hr, "Failed to retrieve D3D11 options", false);

  // Need extended resource sharing so we can share the NV12 texture between
  // ANGLE and the decoder context.
  if (!options.ExtendedResourceSharing)
    support_copy_nv12_textures_ = false;

  UINT nv12_format_support = 0;
  hr =
      D3D11Device()->CheckFormatSupport(DXGI_FORMAT_NV12, &nv12_format_support);
  RETURN_ON_HR_FAILURE(hr, "Failed to check NV12 format support", false);

  if (!(nv12_format_support & D3D11_FORMAT_SUPPORT_VIDEO_PROCESSOR_OUTPUT))
    support_copy_nv12_textures_ = false;

  UINT fp16_format_support = 0;
  hr = D3D11Device()->CheckFormatSupport(DXGI_FORMAT_R16G16B16A16_FLOAT,
                                         &fp16_format_support);
  if (FAILED(hr) ||
      !(fp16_format_support & D3D11_FORMAT_SUPPORT_VIDEO_PROCESSOR_OUTPUT))
    use_fp16_ = false;

  // Enable multithreaded mode on the device. This ensures that accesses to
  // context are synchronized across threads. We have multiple threads
  // accessing the context, the media foundation decoder threads and the
  // decoder thread via the video format conversion transform.
  hr = D3D11Device()->QueryInterface(IID_PPV_ARGS(&multi_threaded_));
  RETURN_ON_HR_FAILURE(hr, "Failed to query ID3D10Multithread", false);
  multi_threaded_->SetMultithreadProtected(TRUE);

  hr = d3d11_device_manager_->ResetDevice(D3D11Device(),
                                          dx11_dev_manager_reset_token_);
  RETURN_ON_HR_FAILURE(hr, "Failed to reset device", false);

  D3D11_QUERY_DESC query_desc;
  query_desc.Query = D3D11_QUERY_EVENT;
  query_desc.MiscFlags = 0;
  hr = D3D11Device()->CreateQuery(&query_desc, d3d11_query_.GetAddressOf());
  RETURN_ON_HR_FAILURE(hr, "Failed to create DX11 device query", false);

  return true;
}

void DXVAVideoDecodeAccelerator::Decode(const BitstreamBuffer& bitstream) {
  Decode(bitstream.ToDecoderBuffer(), bitstream.id());
}

void DXVAVideoDecodeAccelerator::Decode(scoped_refptr<DecoderBuffer> buffer,
                                        int32_t bitstream_id) {
  TRACE_EVENT0("media", "DXVAVideoDecodeAccelerator::Decode");
  DCHECK(main_thread_task_runner_->BelongsToCurrentThread());

  RETURN_AND_NOTIFY_ON_FAILURE(bitstream_id >= 0,
                               "Invalid bitstream, id: " << bitstream_id,
                               INVALID_ARGUMENT, );

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

  State state = GetState();
  RETURN_AND_NOTIFY_ON_FAILURE(
      (state == kNormal || state == kStopped || state == kFlushing),
      "Invalid state: " << state, ILLEGAL_STATE, );

  Microsoft::WRL::ComPtr<IMFSample> sample;
  sample = CreateInputSample(
      buffer->data(), buffer->data_size(),
      std::min<uint32_t>(buffer->data_size(), input_stream_info_.cbSize),
      input_stream_info_.cbAlignment);
  RETURN_AND_NOTIFY_ON_FAILURE(sample.Get(), "Failed to create input sample",
                               PLATFORM_FAILURE, );

  RETURN_AND_NOTIFY_ON_HR_FAILURE(
      sample->SetSampleTime(bitstream_id),
      "Failed to associate input buffer id with sample", PLATFORM_FAILURE, );

  decoder_thread_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&DXVAVideoDecodeAccelerator::DecodeInternal,
                                base::Unretained(this), sample));
}

void DXVAVideoDecodeAccelerator::AssignPictureBuffers(
    const std::vector<PictureBuffer>& buffers) {
  DCHECK(main_thread_task_runner_->BelongsToCurrentThread());

  State state = GetState();
  RETURN_AND_NOTIFY_ON_FAILURE((state != kUninitialized),
                               "Invalid state: " << state, ILLEGAL_STATE, );
  RETURN_AND_NOTIFY_ON_FAILURE(
      (num_picture_buffers_requested_ <= static_cast<int>(buffers.size())),
      "Failed to provide requested picture buffers. (Got "
          << buffers.size() << ", requested " << num_picture_buffers_requested_
          << ")",
      INVALID_ARGUMENT, );

  RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_cb_.Run(),
                               "Failed to make context current",
                               PLATFORM_FAILURE, );
  // Copy the picture buffers provided by the client to the available list,
  // and mark these buffers as available for use.
  for (size_t buffer_index = 0; buffer_index < buffers.size(); ++buffer_index) {
    linked_ptr<DXVAPictureBuffer> picture_buffer =
        DXVAPictureBuffer::Create(*this, buffers[buffer_index], egl_config_);
    RETURN_AND_NOTIFY_ON_FAILURE(picture_buffer.get(),
                                 "Failed to allocate picture buffer",
                                 PLATFORM_FAILURE, );
    if (bind_image_cb_) {
      for (uint32_t client_id : buffers[buffer_index].client_texture_ids()) {
        // The picture buffer handles the actual binding of its contents to
        // texture ids. This call just causes the texture manager to hold a
        // reference to the GLImage as long as either texture exists.
        bind_image_cb_.Run(client_id, GetTextureTarget(),
                           picture_buffer->gl_image(), false);
      }
    }

    bool inserted =
        output_picture_buffers_
            .insert(std::make_pair(buffers[buffer_index].id(), picture_buffer))
            .second;
    DCHECK(inserted);
  }

  ProcessPendingSamples();
  if (pending_flush_ || processing_config_changed_) {
    decoder_thread_task_runner_->PostTask(
        FROM_HERE, base::BindOnce(&DXVAVideoDecodeAccelerator::FlushInternal,
                                  base::Unretained(this)));
  }
}

void DXVAVideoDecodeAccelerator::ReusePictureBuffer(int32_t picture_buffer_id) {
  TRACE_EVENT0("media", "DXVAVideoDecodeAccelerator::ReusePictureBuffer");
  DCHECK(main_thread_task_runner_->BelongsToCurrentThread());

  State state = GetState();
  RETURN_AND_NOTIFY_ON_FAILURE((state != kUninitialized),
                               "Invalid state: " << state, ILLEGAL_STATE, );

  if (output_picture_buffers_.empty() && stale_output_picture_buffers_.empty())
    return;

  OutputBuffers::iterator it = output_picture_buffers_.find(picture_buffer_id);
  // If we didn't find the picture id in the |output_picture_buffers_| map we
  // try the |stale_output_picture_buffers_| map, as this may have been an
  // output picture buffer from before a resolution change, that at resolution
  // change time had yet to be displayed. The client is calling us back to tell
  // us that we can now recycle this picture buffer, so if we were waiting to
  // dispose of it we now can.
  if (it == output_picture_buffers_.end()) {
    if (!stale_output_picture_buffers_.empty()) {
      it = stale_output_picture_buffers_.find(picture_buffer_id);
      RETURN_AND_NOTIFY_ON_FAILURE(it != stale_output_picture_buffers_.end(),
                                   "Invalid picture id: " << picture_buffer_id,
                                   INVALID_ARGUMENT, );
      main_thread_task_runner_->PostTask(
          FROM_HERE,
          base::BindOnce(
              &DXVAVideoDecodeAccelerator::DeferredDismissStaleBuffer,
              weak_ptr_, picture_buffer_id));
    }
    return;
  }

  if (it->second->available() || it->second->waiting_to_reuse())
    return;

  RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_cb_.Run(),
                               "Failed to make context current",
                               PLATFORM_FAILURE, );
  if (use_keyed_mutex_ || using_angle_device_) {
    RETURN_AND_NOTIFY_ON_FAILURE(it->second->ReusePictureBuffer(),
                                 "Failed to reuse picture buffer",
                                 PLATFORM_FAILURE, );
    if (bind_image_cb_ && (GetPictureBufferMechanism() ==
                           PictureBufferMechanism::DELAYED_COPY_TO_NV12)) {
      // Unbind the image to ensure it will be copied again the next time it's
      // needed.
      for (uint32_t client_id :
           it->second->picture_buffer().client_texture_ids()) {
        bind_image_cb_.Run(client_id, GetTextureTarget(),
                           it->second->gl_image(), false);
      }
    }

    ProcessPendingSamples();
    if (pending_flush_) {
      decoder_thread_task_runner_->PostTask(
          FROM_HERE, base::BindOnce(&DXVAVideoDecodeAccelerator::FlushInternal,
                                    base::Unretained(this)));
    }
  } else {
    it->second->ResetReuseFence();

    WaitForOutputBuffer(picture_buffer_id, 0);
  }
}

void DXVAVideoDecodeAccelerator::WaitForOutputBuffer(int32_t picture_buffer_id,
                                                     int count) {
  TRACE_EVENT0("media", "DXVAVideoDecodeAccelerator::WaitForOutputBuffer");
  DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
  OutputBuffers::iterator it = output_picture_buffers_.find(picture_buffer_id);
  if (it == output_picture_buffers_.end())
    return;

  DXVAPictureBuffer* picture_buffer = it->second.get();

  DCHECK(!picture_buffer->available());
  DCHECK(picture_buffer->waiting_to_reuse());

  gl::GLFence* fence = picture_buffer->reuse_fence();
  RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_cb_.Run(),
                               "Failed to make context current",
                               PLATFORM_FAILURE, );
  if (count <= kMaxIterationsForANGLEReuseFlush && !fence->HasCompleted()) {
    main_thread_task_runner_->PostDelayedTask(
        FROM_HERE,
        base::BindOnce(&DXVAVideoDecodeAccelerator::WaitForOutputBuffer,
                       weak_ptr_, picture_buffer_id, count + 1),
        base::TimeDelta::FromMilliseconds(kFlushDecoderSurfaceTimeoutMs));
    return;
  }
  RETURN_AND_NOTIFY_ON_FAILURE(picture_buffer->ReusePictureBuffer(),
                               "Failed to reuse picture buffer",
                               PLATFORM_FAILURE, );

  ProcessPendingSamples();
  if (pending_flush_ || processing_config_changed_) {
    decoder_thread_task_runner_->PostTask(
        FROM_HERE, base::BindOnce(&DXVAVideoDecodeAccelerator::FlushInternal,
                                  base::Unretained(this)));
  }
}

void DXVAVideoDecodeAccelerator::Flush() {
  DCHECK(main_thread_task_runner_->BelongsToCurrentThread());

  DVLOG(1) << "DXVAVideoDecodeAccelerator::Flush";

  State state = GetState();
  RETURN_AND_NOTIFY_ON_FAILURE((state == kNormal || state == kStopped),
                               "Unexpected decoder state: " << state,
                               ILLEGAL_STATE, );

  SetState(kFlushing);

  pending_flush_ = true;

  // If we receive a flush while processing a video stream config change,  then
  // we treat this as a regular flush, i.e we process queued decode packets,
  // etc.
  // We are resetting the processing_config_changed_ flag here which means that
  // we won't be tearing down the decoder instance and recreating it to handle
  // the changed configuration. The expectation here is that after the decoder
  // is drained it should be able to handle a changed configuration.
  // TODO(ananta)
  // If a flush is sufficient to get the decoder to process video stream config
  // changes correctly, then we don't need to tear down the decoder instance
  // and recreate it. Check if this is indeed the case.
  processing_config_changed_ = false;

  decoder_thread_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&DXVAVideoDecodeAccelerator::FlushInternal,
                                base::Unretained(this)));
}

void DXVAVideoDecodeAccelerator::Reset() {
  DCHECK(main_thread_task_runner_->BelongsToCurrentThread());

  DVLOG(1) << "DXVAVideoDecodeAccelerator::Reset";

  State state = GetState();
  RETURN_AND_NOTIFY_ON_FAILURE(
      (state == kNormal || state == kStopped || state == kFlushing),
      "Reset: invalid state: " << state, ILLEGAL_STATE, );

  StopDecoderThread();

  if (state == kFlushing)
    NotifyFlushDone();

  SetState(kResetting);

  // If we have pending output frames waiting for display then we drop those
  // frames and set the corresponding picture buffer as available.
  PendingOutputSamples::iterator index;
  for (index = pending_output_samples_.begin();
       index != pending_output_samples_.end(); ++index) {
    if (index->picture_buffer_id != -1) {
      OutputBuffers::iterator it =
          output_picture_buffers_.find(index->picture_buffer_id);
      if (it != output_picture_buffers_.end()) {
        DXVAPictureBuffer* picture_buffer = it->second.get();
        if (picture_buffer->state() == DXVAPictureBuffer::State::BOUND ||
            picture_buffer->state() == DXVAPictureBuffer::State::COPYING) {
          picture_buffer->ReusePictureBuffer();
        }
      }
    }
  }

  pending_output_samples_.clear();

  RETURN_AND_NOTIFY_ON_FAILURE(SendMFTMessage(MFT_MESSAGE_COMMAND_FLUSH, 0),
                               "Reset: Failed to send message.",
                               PLATFORM_FAILURE, );

  main_thread_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&DXVAVideoDecodeAccelerator::NotifyInputBuffersDropped,
                     weak_ptr_, std::move(pending_input_buffers_)));
  pending_input_buffers_.clear();
  main_thread_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&DXVAVideoDecodeAccelerator::NotifyResetDone, weak_ptr_));

  RETURN_AND_NOTIFY_ON_FAILURE(StartDecoderThread(),
                               "Failed to start decoder thread.",
                               PLATFORM_FAILURE, );
  SetState(kNormal);
}

void DXVAVideoDecodeAccelerator::Destroy() {
  DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
  Invalidate();
  delete this;
}

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

GLenum DXVAVideoDecodeAccelerator::GetSurfaceInternalFormat() const {
  return GL_BGRA_EXT;
}

// static
VideoDecodeAccelerator::SupportedProfiles
DXVAVideoDecodeAccelerator::GetSupportedProfiles(
    const gpu::GpuPreferences& preferences,
    const gpu::GpuDriverBugWorkarounds& workarounds) {
  TRACE_EVENT0("gpu,startup",
               "DXVAVideoDecodeAccelerator::GetSupportedProfiles");

  SupportedProfiles profiles;
  for (const wchar_t* mfdll : kMediaFoundationVideoDecoderDLLs) {
    if (!::GetModuleHandle(mfdll)) {
      // Windows N is missing the media foundation DLLs unless the media
      // feature pack is installed.
      DVLOG(ERROR) << mfdll << " is required for hardware video decoding";
      return profiles;
    }
  }

  // On Windows 7 the maximum resolution supported by media foundation is
  // 1920 x 1088. We use 1088 to account for 16x16 macroblocks.
  ResolutionPair max_h264_resolutions(gfx::Size(1920, 1088), gfx::Size());

  // VPX has no default resolutions since it may not even be supported.
  ResolutionPair max_vpx_resolutions;

  if (base::win::GetVersion() > base::win::VERSION_WIN7) {
    // To detect if a driver supports the desired resolutions, we try and create
    // a DXVA decoder instance for that resolution and profile. If that succeeds
    // we assume that the driver supports decoding for that resolution.
    Microsoft::WRL::ComPtr<ID3D11Device> device =
        gl::QueryD3D11DeviceObjectFromANGLE();

    // Legacy AMD drivers with UVD3 or earlier and some Intel GPU's crash while
    // creating surfaces larger than 1920 x 1088.
    if (device && !IsLegacyGPU(device.Get())) {
      Microsoft::WRL::ComPtr<ID3D11VideoDevice> video_device;
      if (SUCCEEDED(device.CopyTo(IID_PPV_ARGS(&video_device)))) {
        max_h264_resolutions = GetMaxResolutionsForGUIDs(
            max_h264_resolutions.first, video_device.Get(),
            {DXVA2_ModeH264_E, DXVA2_Intel_ModeH264_E},
            {gfx::Size(2560, 1440), gfx::Size(3840, 2160),
             gfx::Size(4096, 2160), gfx::Size(4096, 2304)});

        // Despite the name this is the GUID for VP8/VP9.
        if (preferences.enable_accelerated_vpx_decode &&
            !workarounds.disable_accelerated_vpx_decode) {
          max_vpx_resolutions = GetMaxResolutionsForGUIDs(
              max_vpx_resolutions.first, video_device.Get(),
              {D3D11_DECODER_PROFILE_VP9_VLD_PROFILE0},
              {gfx::Size(4096, 2160), gfx::Size(4096, 2304),
               gfx::Size(7680, 4320)});
        }
      }
    }
  }

  for (const auto& supported_profile : kSupportedProfiles) {
    const bool kIsVPX = supported_profile >= VP8PROFILE_MIN &&
                        supported_profile <= VP9PROFILE_MAX;

    // Skip adding VPX profiles if it's not supported or disabled.
    if (kIsVPX && max_vpx_resolutions.first.IsEmpty())
      continue;

    const bool kIsH264 = supported_profile >= H264PROFILE_MIN &&
                         supported_profile <= H264PROFILE_MAX;
    DCHECK(kIsH264 || kIsVPX);

    // Windows Media Foundation H.264 decoding does not support decoding videos
    // with any dimension smaller than 48 pixels:
    // http://msdn.microsoft.com/en-us/library/windows/desktop/dd797815
    //
    // TODO(dalecurtis): These values are too low. We should only be using
    // hardware decode for videos above ~360p, see http://crbug.com/684792.
    const gfx::Size kMinResolution =
        kIsH264 ? gfx::Size(48, 48) : gfx::Size(16, 16);

    {
      SupportedProfile profile;
      profile.profile = supported_profile;
      profile.min_resolution = kMinResolution;
      profile.max_resolution =
          kIsH264 ? max_h264_resolutions.first : max_vpx_resolutions.first;
      profiles.push_back(profile);
    }

    const gfx::Size kPortraitMax =
        kIsH264 ? max_h264_resolutions.second : max_vpx_resolutions.second;
    if (!kPortraitMax.IsEmpty()) {
      SupportedProfile profile;
      profile.profile = supported_profile;
      profile.min_resolution = kMinResolution;
      profile.max_resolution = kPortraitMax;
      profiles.push_back(profile);
    }
  }

  return profiles;
}

// static
void DXVAVideoDecodeAccelerator::PreSandboxInitialization() {
  for (const wchar_t* mfdll : kMediaFoundationVideoDecoderDLLs)
    ::LoadLibrary(mfdll);
  ::LoadLibrary(L"dxva2.dll");

  if (base::win::GetVersion() >= base::win::VERSION_WIN8) {
    LoadLibrary(L"msvproc.dll");
  } else {
#if defined(ENABLE_DX11_FOR_WIN7)
    LoadLibrary(L"mshtmlmedia.dll");
#endif
  }
}

bool DXVAVideoDecodeAccelerator::InitDecoder(VideoCodecProfile profile) {
  HMODULE decoder_dll = NULL;

  CLSID clsid = {};

  // Profile must fall within the valid range for one of the supported codecs.
  if (profile >= H264PROFILE_MIN && profile <= H264PROFILE_MAX) {
    // We mimic the steps CoCreateInstance uses to instantiate the object. This
    // was previously done because it failed inside the sandbox, and now is done
    // as a more minimal approach to avoid other side-effects CCI might have (as
    // we are still in a reduced sandbox).
    decoder_dll = ::GetModuleHandle(L"msmpeg2vdec.dll");
    RETURN_ON_FAILURE(decoder_dll,
                      "msmpeg2vdec.dll required for decoding is not loaded",
                      false);

    // Check version of DLL, version 6.1.7140 is blacklisted due to high crash
    // rates in browsers loading that DLL. If that is the version installed we
    // fall back to software decoding. See crbug/403440.
    std::unique_ptr<FileVersionInfo> version_info(
        FileVersionInfo::CreateFileVersionInfoForModule(decoder_dll));
    RETURN_ON_FAILURE(version_info, "unable to get version of msmpeg2vdec.dll",
                      false);
    base::string16 file_version = version_info->file_version();
    RETURN_ON_FAILURE(file_version.find(L"6.1.7140") == base::string16::npos,
                      "blacklisted version of msmpeg2vdec.dll 6.1.7140", false);
    codec_ = kCodecH264;
    clsid = __uuidof(CMSH264DecoderMFT);
  } else if (enable_accelerated_vpx_decode_ &&
             (profile == VP8PROFILE_ANY || profile == VP9PROFILE_PROFILE0 ||
              profile == VP9PROFILE_PROFILE1 ||
              profile == VP9PROFILE_PROFILE2 ||
              profile == VP9PROFILE_PROFILE3)) {
    if (profile != VP8PROFILE_ANY &&
        (enable_accelerated_vpx_decode_ &
         gpu::GpuPreferences::VPX_VENDOR_MICROSOFT)) {
      codec_ = kCodecVP9;
      clsid = CLSID_MSVPxDecoder;
      decoder_dll = ::LoadLibrary(kMSVP9DecoderDLLName);
      if (decoder_dll)
        using_ms_vp9_mft_ = true;
    }

    int program_files_key = base::DIR_PROGRAM_FILES;
    if (base::win::OSInfo::GetInstance()->wow64_status() ==
        base::win::OSInfo::WOW64_ENABLED) {
      program_files_key = base::DIR_PROGRAM_FILES6432;
    }

    // AMD
    if (!decoder_dll &&
        enable_accelerated_vpx_decode_ & gpu::GpuPreferences::VPX_VENDOR_AMD &&
        profile == VP9PROFILE_PROFILE0) {
      base::FilePath dll_path;
      if (base::PathService::Get(program_files_key, &dll_path)) {
        codec_ = media::kCodecVP9;
        dll_path = dll_path.Append(kAMDVPXDecoderDLLPath);
        dll_path = dll_path.Append(kAMDVP9DecoderDLLName);
        clsid = CLSID_AMDWebmMfVp9Dec;
        decoder_dll = ::LoadLibraryEx(dll_path.value().data(), NULL,
                                      LOAD_WITH_ALTERED_SEARCH_PATH);
      }
    }
  }

  if (!decoder_dll) {
    RETURN_ON_FAILURE(false, "Unsupported codec.", false);
  }

  HRESULT hr =
      CreateCOMObjectFromDll(decoder_dll, clsid, IID_PPV_ARGS(&decoder_));
  RETURN_ON_HR_FAILURE(hr, "Failed to create decoder instance", false);

  RETURN_ON_FAILURE(CheckDecoderDxvaSupport(),
                    "Failed to check decoder DXVA support", false);

  ULONG_PTR device_manager_to_use = NULL;
  if (use_dx11_) {
    CHECK(create_dxgi_device_manager_);
    if (media_log_)
      MEDIA_LOG(INFO, media_log_) << "Using D3D11 device for DXVA";
    RETURN_AND_NOTIFY_ON_FAILURE(CreateDX11DevManager(),
                                 "Failed to initialize DX11 device and manager",
                                 PLATFORM_FAILURE, false);
    device_manager_to_use =
        reinterpret_cast<ULONG_PTR>(d3d11_device_manager_.Get());
  } else {
    if (media_log_)
      MEDIA_LOG(INFO, media_log_) << "Using D3D9 device for DXVA";
    RETURN_AND_NOTIFY_ON_FAILURE(CreateD3DDevManager(),
                                 "Failed to initialize D3D device and manager",
                                 PLATFORM_FAILURE, false);
    device_manager_to_use = reinterpret_cast<ULONG_PTR>(device_manager_.Get());
  }

  hr = decoder_->ProcessMessage(MFT_MESSAGE_SET_D3D_MANAGER,
                                device_manager_to_use);
  if (use_dx11_) {
    RETURN_ON_HR_FAILURE(hr, "Failed to pass DX11 manager to decoder", false);
  } else {
    RETURN_ON_HR_FAILURE(hr, "Failed to pass D3D manager to decoder", false);
  }

  EGLDisplay egl_display = gl::GLSurfaceEGL::GetHardwareDisplay();

  while (true) {
    EGLint config_attribs[] = {EGL_BUFFER_SIZE,  32,
                               EGL_RED_SIZE,     use_fp16_ ? 16 : 8,
                               EGL_GREEN_SIZE,   use_fp16_ ? 16 : 8,
                               EGL_BLUE_SIZE,    use_fp16_ ? 16 : 8,
                               EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
                               EGL_ALPHA_SIZE,   0,
                               EGL_NONE};

    EGLint num_configs = 0;

    if (eglChooseConfig(egl_display, config_attribs, NULL, 0, &num_configs) &&
        num_configs > 0) {
      std::vector<EGLConfig> configs(num_configs);
      if (eglChooseConfig(egl_display, config_attribs, configs.data(),
                          num_configs, &num_configs)) {
        egl_config_ = configs[0];
        for (int i = 0; i < num_configs; i++) {
          EGLint red_bits;
          eglGetConfigAttrib(egl_display, configs[i], EGL_RED_SIZE, &red_bits);
          // Try to pick a configuration with the right number of bits rather
          // than one that just has enough bits.
          if (red_bits == (use_fp16_ ? 16 : 8)) {
            egl_config_ = configs[i];
            break;
          }
        }
      }

      if (!num_configs) {
        if (use_fp16_) {
          // Try again, but without use_fp16_
          use_fp16_ = false;
          continue;
        }
        return false;
      }
    }

    break;
  }

  if (use_fp16_) {
    // TODO(hubbe): Share/copy P010/P016 textures.
    DisableSharedTextureSupport();
    support_copy_nv12_textures_ = false;
  }

  return SetDecoderMediaTypes();
}

bool DXVAVideoDecodeAccelerator::CheckDecoderDxvaSupport() {
  Microsoft::WRL::ComPtr<IMFAttributes> attributes;
  HRESULT hr = decoder_->GetAttributes(attributes.GetAddressOf());
  RETURN_ON_HR_FAILURE(hr, "Failed to get decoder attributes", false);

  UINT32 dxva = 0;
  hr = attributes->GetUINT32(MF_SA_D3D_AWARE, &dxva);
  RETURN_ON_HR_FAILURE(hr, "Failed to check if decoder supports DXVA", false);

  if (codec_ == kCodecH264) {
    hr = attributes->SetUINT32(CODECAPI_AVDecVideoAcceleration_H264, TRUE);
    RETURN_ON_HR_FAILURE(hr, "Failed to enable DXVA H/W decoding", false);
  }

  if (enable_low_latency_) {
    hr = attributes->SetUINT32(CODECAPI_AVLowLatencyMode, TRUE);
    if (SUCCEEDED(hr)) {
      DVLOG(1) << "Successfully set Low latency mode on decoder.";
    } else {
      DVLOG(1) << "Failed to set Low latency mode on decoder. Error: " << hr;
    }
  }

  // Each picture buffer can store a sample, plus one in
  // pending_output_samples_. The decoder adds this number to the number of
  // reference pictures it expects to need and uses that to determine the
  // array size of the output texture.
  const int kMaxOutputSamples = num_picture_buffers_requested_ + 1;
  attributes->SetUINT32(MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT_PROGRESSIVE,
                        kMaxOutputSamples);
  attributes->SetUINT32(MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT, kMaxOutputSamples);

  auto* gl_context = get_gl_context_cb_.Run();
  RETURN_ON_FAILURE(gl_context, "Couldn't get GL context", false);

  // The decoder should use DX11 iff
  // 1. The underlying H/W decoder supports it.
  // 2. We have a pointer to the MFCreateDXGIDeviceManager function needed for
  //    this. This should always be true for Windows 8+.
  // 3. ANGLE is using DX11.
  if (create_dxgi_device_manager_ &&
      (gl_context->GetGLRenderer().find("Direct3D11") != std::string::npos)) {
    UINT32 dx11_aware = 0;
    attributes->GetUINT32(MF_SA_D3D11_AWARE, &dx11_aware);
    use_dx11_ = !!dx11_aware;
  }

  use_keyed_mutex_ =
      use_dx11_ && gl::GLSurfaceEGL::HasEGLExtension("EGL_ANGLE_keyed_mutex");

  if (!use_dx11_ ||
      !gl::g_driver_egl.ext.b_EGL_ANGLE_stream_producer_d3d_texture ||
      !gl::g_driver_egl.ext.b_EGL_KHR_stream ||
      !gl::g_driver_egl.ext.b_EGL_KHR_stream_consumer_gltexture ||
      !gl::g_driver_egl.ext.b_EGL_NV_stream_consumer_gltexture_yuv) {
    DisableSharedTextureSupport();
    support_copy_nv12_textures_ = false;
  }

  return true;
}

bool DXVAVideoDecodeAccelerator::SetDecoderMediaTypes() {
  RETURN_ON_FAILURE(SetDecoderInputMediaType(),
                    "Failed to set decoder input media type", false);
  return SetDecoderOutputMediaType(MFVideoFormat_NV12) ||
         SetDecoderOutputMediaType(MFVideoFormat_P010) ||
         SetDecoderOutputMediaType(MFVideoFormat_P016);
}

bool DXVAVideoDecodeAccelerator::SetDecoderInputMediaType() {
  Microsoft::WRL::ComPtr<IMFMediaType> media_type;
  HRESULT hr = MFCreateMediaType(media_type.GetAddressOf());
  RETURN_ON_HR_FAILURE(hr, "MFCreateMediaType failed", false);

  hr = media_type->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
  RETURN_ON_HR_FAILURE(hr, "Failed to set major input type", false);

  if (codec_ == kCodecH264) {
    hr = media_type->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264);
  } else if (codec_ == kCodecVP8) {
    hr = media_type->SetGUID(MF_MT_SUBTYPE, MEDIASUBTYPE_VP80);
  } else if (codec_ == kCodecVP9) {
    hr = media_type->SetGUID(MF_MT_SUBTYPE, MEDIASUBTYPE_VP90);
  } else {
    NOTREACHED();
    RETURN_ON_FAILURE(false, "Unsupported codec on input media type.", false);
  }
  RETURN_ON_HR_FAILURE(hr, "Failed to set subtype", false);

  if (using_ms_vp9_mft_) {
    hr = MFSetAttributeSize(media_type.Get(), MF_MT_FRAME_SIZE,
                            config_.initial_expected_coded_size.width(),
                            config_.initial_expected_coded_size.height());
    RETURN_ON_HR_FAILURE(hr, "Failed to set attribute size", false);

    hr = media_type->SetUINT32(MF_MT_INTERLACE_MODE,
                               MFVideoInterlace_Progressive);
    RETURN_ON_HR_FAILURE(hr, "Failed to set interlace mode", false);
  } else {
    // Not sure about this. msdn recommends setting this value on the input
    // media type.
    hr = media_type->SetUINT32(MF_MT_INTERLACE_MODE,
                               MFVideoInterlace_MixedInterlaceOrProgressive);
    RETURN_ON_HR_FAILURE(hr, "Failed to set interlace mode", false);
  }

  // These bind flags _must_ be set before SetInputType or SetOutputType to
  // ensure that we get the proper surfaces created under the hood.
  if (GetPictureBufferMechanism() == PictureBufferMechanism::BIND) {
    Microsoft::WRL::ComPtr<IMFAttributes> out_attributes;
    HRESULT hr =
        decoder_->GetOutputStreamAttributes(0, out_attributes.GetAddressOf());
    RETURN_ON_HR_FAILURE(hr, "Failed to get stream attributes", false);
    out_attributes->SetUINT32(MF_SA_D3D11_BINDFLAGS,
                              D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DECODER);
    // For some reason newer Intel drivers need D3D11_BIND_DECODER textures to
    // be created with a share handle or they'll crash in
    // CreateShaderResourceView.  Technically MF_SA_D3D11_SHARED_WITHOUT_MUTEX
    // is only honored by the sample allocator, not by the media foundation
    // transform, but Microsoft's h.264 transform happens to pass it through.
    out_attributes->SetUINT32(MF_SA_D3D11_SHARED_WITHOUT_MUTEX, TRUE);
  }

  hr = decoder_->SetInputType(0, media_type.Get(), 0);  // No flags
  RETURN_ON_HR_FAILURE(hr, "Failed to set decoder input type", false);
  return true;
}

bool DXVAVideoDecodeAccelerator::SetDecoderOutputMediaType(
    const GUID& subtype) {
  return SetTransformOutputType(decoder_.Get(), subtype, 0, 0);
}

bool DXVAVideoDecodeAccelerator::SendMFTMessage(MFT_MESSAGE_TYPE msg,
                                                int32_t param) {
  HRESULT hr = decoder_->ProcessMessage(msg, param);
  return SUCCEEDED(hr);
}

// Gets the minimum buffer sizes for input and output samples. The MFT will not
// allocate buffer for input nor output, so we have to do it ourselves and make
// sure they're the correct size. We only provide decoding if DXVA is enabled.
bool DXVAVideoDecodeAccelerator::GetStreamsInfoAndBufferReqs() {
  HRESULT hr = decoder_->GetInputStreamInfo(0, &input_stream_info_);
  RETURN_ON_HR_FAILURE(hr, "Failed to get input stream info", false);

  hr = decoder_->GetOutputStreamInfo(0, &output_stream_info_);
  RETURN_ON_HR_FAILURE(hr, "Failed to get decoder output stream info", false);

  DVLOG(1) << "Input stream info: ";
  DVLOG(1) << "Max latency: " << input_stream_info_.hnsMaxLatency;
  if (codec_ == kCodecH264) {
    // There should be three flags, one for requiring a whole frame be in a
    // single sample, one for requiring there be one buffer only in a single
    // sample, and one that specifies a fixed sample size. (as in cbSize)
    CHECK_EQ(input_stream_info_.dwFlags, 0x7u);
  }

  DVLOG(1) << "Min buffer size: " << input_stream_info_.cbSize;
  DVLOG(1) << "Max lookahead: " << input_stream_info_.cbMaxLookahead;
  DVLOG(1) << "Alignment: " << input_stream_info_.cbAlignment;

  DVLOG(1) << "Output stream info: ";
  // The flags here should be the same and mean the same thing, except when
  // DXVA is enabled, there is an extra 0x100 flag meaning decoder will
  // allocate its own sample.
  DVLOG(1) << "Flags: " << std::hex << std::showbase
           << output_stream_info_.dwFlags;
  if (codec_ == kCodecH264) {
    CHECK_EQ(output_stream_info_.dwFlags, 0x107u);
  }
  DVLOG(1) << "Min buffer size: " << output_stream_info_.cbSize;
  DVLOG(1) << "Alignment: " << output_stream_info_.cbAlignment;
  return true;
}

void DXVAVideoDecodeAccelerator::DoDecode(const gfx::Rect& visible_rect,
                                          const gfx::ColorSpace& color_space) {
  TRACE_EVENT0("media", "DXVAVideoDecodeAccelerator::DoDecode");
  DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
  // This function is also called from FlushInternal in a loop which could
  // result in the state transitioning to kStopped due to no decoded output.
  State state = GetState();
  RETURN_AND_NOTIFY_ON_FAILURE(
      (state == kNormal || state == kFlushing || state == kStopped),
      "DoDecode: not in normal/flushing/stopped state", ILLEGAL_STATE, );

  if (D3D11Device())
    g_last_device_removed_reason = D3D11Device()->GetDeviceRemovedReason();

  Microsoft::WRL::ComPtr<IMFSample> output_sample;
  int retries = 10;
  while (true) {
    output_sample.Reset();
    MFT_OUTPUT_DATA_BUFFER output_data_buffer = {0};
    DWORD status = 0;
    HRESULT hr;
    g_last_process_output_time = GetCurrentQPC();
    hr = decoder_->ProcessOutput(0,  // No flags
                                 1,  // # of out streams to pull from
                                 &output_data_buffer, &status);
    IMFCollection* events = output_data_buffer.pEvents;
    if (events != NULL) {
      DVLOG(1) << "Got events from ProcessOuput, but discarding";
      events->Release();
    }
    output_sample.Attach(output_data_buffer.pSample);
    if (FAILED(hr)) {
      // A stream change needs further ProcessInput calls to get back decoder
      // output which is why we need to set the state to stopped.
      if (hr == MF_E_TRANSFORM_STREAM_CHANGE) {
        if (!SetDecoderOutputMediaType(MFVideoFormat_NV12) &&
            !SetDecoderOutputMediaType(MFVideoFormat_P010) &&
            !SetDecoderOutputMediaType(MFVideoFormat_P016)) {
          // Decoder didn't let us set NV12 output format. Not sure as to why
          // this can happen. Give up in disgust.
          NOTREACHED() << "Failed to set decoder output media type to NV12";
          SetState(kStopped);
        } else {
          if (retries-- > 0) {
            DVLOG(1) << "Received format change from the decoder, retrying.";
            continue;  // Retry
          } else {
            RETURN_AND_NOTIFY_ON_FAILURE(
                false, "Received too many format changes from decoder.",
                PLATFORM_FAILURE, );
          }
        }
        return;
      } else if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) {
        // No more output from the decoder. Stop playback.
        SetState(kStopped);
        return;
      } else if (hr == E_FAIL) {
        // This shouldn't happen, but does, log it and ignore it.
        // https://crbug.com/839057
        LOG(ERROR) << "Received E_FAIL in DoDecode()";
        return;
      } else {
        // Unknown error, stop playback and log error.
        SetState(kStopped);
        RETURN_AND_NOTIFY_ON_FAILURE(hr, "Unhandled error in DoDecode()",
                                     PLATFORM_FAILURE, );
      }
    }

    break;  // No more retries needed.
  }
  TRACE_EVENT_ASYNC_END0("gpu", "DXVAVideoDecodeAccelerator.Decoding", this);

  TRACE_COUNTER1("DXVA Decoding", "TotalPacketsBeforeDecode",
                 inputs_before_decode_);

  inputs_before_decode_ = 0;

  RETURN_AND_NOTIFY_ON_FAILURE(
      ProcessOutputSample(output_sample, visible_rect, color_space),
      "Failed to process output sample.", PLATFORM_FAILURE, );
}

bool DXVAVideoDecodeAccelerator::ProcessOutputSample(
    Microsoft::WRL::ComPtr<IMFSample> sample,
    const gfx::Rect& visible_rect,
    const gfx::ColorSpace& color_space) {
  RETURN_ON_FAILURE(sample, "Decode succeeded with NULL output sample", false);

  LONGLONG input_buffer_id = 0;
  RETURN_ON_HR_FAILURE(sample->GetSampleTime(&input_buffer_id),
                       "Failed to get input buffer id associated with sample",
                       false);

  {
    base::AutoLock lock(decoder_lock_);
    DCHECK(pending_output_samples_.empty());
    pending_output_samples_.push_back(
        PendingSampleInfo(input_buffer_id, sample, visible_rect, color_space));
  }

  if (pictures_requested_) {
    DVLOG(1) << "Waiting for picture slots from the client.";
    main_thread_task_runner_->PostTask(
        FROM_HERE,
        base::BindOnce(&DXVAVideoDecodeAccelerator::ProcessPendingSamples,
                       weak_ptr_));
    return true;
  }

  int width = 0;
  int height = 0;
  if (!GetVideoFrameDimensions(sample.Get(), &width, &height)) {
    RETURN_ON_FAILURE(false, "Failed to get D3D surface from output sample",
                      false);
  }

  // Go ahead and request picture buffers.
  main_thread_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&DXVAVideoDecodeAccelerator::RequestPictureBuffers,
                     weak_ptr_, width, height));

  pictures_requested_ = true;
  return true;
}

void DXVAVideoDecodeAccelerator::ProcessPendingSamples() {
  TRACE_EVENT0("media", "DXVAVideoDecodeAccelerator::ProcessPendingSamples");
  DCHECK(main_thread_task_runner_->BelongsToCurrentThread());

  if (output_picture_buffers_.empty())
    return;

  RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_cb_.Run(),
                               "Failed to make context current",
                               PLATFORM_FAILURE, );

  OutputBuffers::iterator index;

  for (index = output_picture_buffers_.begin();
       index != output_picture_buffers_.end() && OutputSamplesPresent();
       ++index) {
    if (index->second->available()) {
      PendingSampleInfo* pending_sample = NULL;
      {
        base::AutoLock lock(decoder_lock_);
        PendingSampleInfo& sample_info = pending_output_samples_.front();
        if (sample_info.picture_buffer_id != -1)
          continue;
        pending_sample = &sample_info;
      }

      int width = 0;
      int height = 0;
      if (!GetVideoFrameDimensions(pending_sample->output_sample.Get(), &width,
                                   &height)) {
        RETURN_AND_NOTIFY_ON_FAILURE(
            false, "Failed to get D3D surface from output sample",
            PLATFORM_FAILURE, );
      }

      if (width != index->second->size().width() ||
          height != index->second->size().height()) {
        HandleResolutionChanged(width, height);
        return;
      }

      pending_sample->picture_buffer_id = index->second->id();
      index->second->set_bound();
      index->second->set_visible_rect(pending_sample->visible_rect);
      index->second->set_color_space(pending_sample->color_space);

      if (index->second->CanBindSamples()) {
        main_thread_task_runner_->PostTask(
            FROM_HERE,
            base::BindOnce(
                &DXVAVideoDecodeAccelerator::BindPictureBufferToSample,
                weak_ptr_, pending_sample->output_sample,
                pending_sample->picture_buffer_id,
                pending_sample->input_buffer_id));
        continue;
      }

      Microsoft::WRL::ComPtr<IMFMediaBuffer> output_buffer;
      HRESULT hr = pending_sample->output_sample->GetBufferByIndex(
          0, output_buffer.GetAddressOf());
      RETURN_AND_NOTIFY_ON_HR_FAILURE(
          hr, "Failed to get buffer from output sample", PLATFORM_FAILURE, );

      Microsoft::WRL::ComPtr<IDirect3DSurface9> surface;
      Microsoft::WRL::ComPtr<ID3D11Texture2D> d3d11_texture;

      if (use_dx11_) {
        Microsoft::WRL::ComPtr<IMFDXGIBuffer> dxgi_buffer;
        hr = output_buffer.CopyTo(dxgi_buffer.GetAddressOf());
        RETURN_AND_NOTIFY_ON_HR_FAILURE(
            hr, "Failed to get DXGIBuffer from output sample",
            PLATFORM_FAILURE, );
        hr = dxgi_buffer->GetResource(
            __uuidof(ID3D11Texture2D),
            reinterpret_cast<void**>(d3d11_texture.GetAddressOf()));
      } else {
        hr = MFGetService(output_buffer.Get(), MR_BUFFER_SERVICE,
                          IID_PPV_ARGS(surface.GetAddressOf()));
      }
      RETURN_AND_NOTIFY_ON_HR_FAILURE(
          hr, "Failed to get surface from output sample", PLATFORM_FAILURE, );

      RETURN_AND_NOTIFY_ON_FAILURE(
          index->second->CopyOutputSampleDataToPictureBuffer(
              this, surface.Get(), d3d11_texture.Get(),
              pending_sample->input_buffer_id),
          "Failed to copy output sample", PLATFORM_FAILURE, );
    }
  }
}

void DXVAVideoDecodeAccelerator::StopOnError(
    VideoDecodeAccelerator::Error error) {
  if (!main_thread_task_runner_->BelongsToCurrentThread()) {
    main_thread_task_runner_->PostTask(
        FROM_HERE, base::BindOnce(&DXVAVideoDecodeAccelerator::StopOnError,
                                  weak_ptr_, error));
    return;
  }

  if (client_)
    client_->NotifyError(error);
  client_ = NULL;

  if (GetState() != kUninitialized) {
    Invalidate();
  }
}

void DXVAVideoDecodeAccelerator::Invalidate() {
  if (GetState() == kUninitialized)
    return;

  // Best effort to make the GL context current.
  make_context_current_cb_.Run();

  StopDecoderThread();
  weak_this_factory_.InvalidateWeakPtrs();
  weak_ptr_ = weak_this_factory_.GetWeakPtr();
  pending_output_samples_.clear();
  decoder_.Reset();
  config_change_detector_.reset();

  // If we are processing a config change, then leave the d3d9/d3d11 objects
  // along with the output picture buffers intact as they can be reused. The
  // output picture buffers may need to be recreated in case the video
  // resolution changes. We already handle that in the
  // HandleResolutionChanged() function.
  if (GetState() != kConfigChange) {
    output_picture_buffers_.clear();
    stale_output_picture_buffers_.clear();
    // We want to continue processing pending input after detecting a config
    // change.
    pending_input_buffers_.clear();
    pictures_requested_ = false;
    if (use_dx11_) {
      d3d11_processor_.Reset();
      enumerator_.Reset();
      video_context_.Reset();
      video_device_.Reset();
      d3d11_device_context_.Reset();
      d3d11_device_.Reset();
      d3d11_device_manager_.Reset();
      d3d11_query_.Reset();
      multi_threaded_.Reset();
      processor_width_ = processor_height_ = 0;
    } else {
      d3d9_.Reset();
      d3d9_device_ex_.Reset();
      device_manager_.Reset();
      query_.Reset();
    }
  }
  sent_drain_message_ = false;
  SetState(kUninitialized);
}

void DXVAVideoDecodeAccelerator::StopDecoderThread() {
  // Try to determine what, if any exception last happened before a hang. See
  // http://crbug.com/613701
  uint64_t last_process_output_time = g_last_process_output_time;
  HRESULT last_device_removed_reason = g_last_device_removed_reason;
  LARGE_INTEGER perf_frequency;
  ::QueryPerformanceFrequency(&perf_frequency);
  uint32_t output_array_size = output_array_size_;
  size_t sample_count;
  {
    base::AutoLock lock(decoder_lock_);
    sample_count = pending_output_samples_.size();
  }
  size_t stale_output_picture_buffers_size =
      stale_output_picture_buffers_.size();
  PictureBufferMechanism mechanism = GetPictureBufferMechanism();

  base::debug::Alias(&last_process_output_time);
  base::debug::Alias(&last_device_removed_reason);
  base::debug::Alias(&perf_frequency.QuadPart);
  base::debug::Alias(&output_array_size);
  base::debug::Alias(&sample_count);
  base::debug::Alias(&stale_output_picture_buffers_size);
  base::debug::Alias(&mechanism);
  decoder_thread_.Stop();
}

void DXVAVideoDecodeAccelerator::NotifyInputBufferRead(int input_buffer_id) {
  DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
  if (client_)
    client_->NotifyEndOfBitstreamBuffer(input_buffer_id);
}

void DXVAVideoDecodeAccelerator::NotifyFlushDone() {
  DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
  if (client_ && pending_flush_) {
    pending_flush_ = false;
    {
      base::AutoLock lock(decoder_lock_);
      sent_drain_message_ = false;
    }

    client_->NotifyFlushDone();
  }
}

void DXVAVideoDecodeAccelerator::NotifyResetDone() {
  DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
  if (client_)
    client_->NotifyResetDone();
}

void DXVAVideoDecodeAccelerator::RequestPictureBuffers(int width, int height) {
  DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
  // This task could execute after the decoder has been torn down.
  if (GetState() != kUninitialized && client_) {
    // When sharing NV12 textures, the client needs to provide 2 texture IDs
    // per picture buffer, 1 for the Y channel and 1 for the UV channels.
    // They're shared to ANGLE using EGL_NV_stream_consumer_gltexture_yuv, so
    // they need to be GL_TEXTURE_EXTERNAL_OES.
    bool provide_nv12_textures =
        GetPictureBufferMechanism() != PictureBufferMechanism::COPY_TO_RGB;
    client_->ProvidePictureBuffers(
        num_picture_buffers_requested_,
        provide_nv12_textures ? PIXEL_FORMAT_NV12 : PIXEL_FORMAT_UNKNOWN,
        provide_nv12_textures ? 2 : 1, gfx::Size(width, height),
        GetTextureTarget());
  }
}

void DXVAVideoDecodeAccelerator::NotifyPictureReady(
    int picture_buffer_id,
    int input_buffer_id,
    const gfx::Rect& visible_rect,
    const gfx::ColorSpace& color_space,
    bool allow_overlay) {
  DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
  // This task could execute after the decoder has been torn down.
  if (GetState() != kUninitialized && client_) {
    Picture picture(picture_buffer_id, input_buffer_id, visible_rect,
                    color_space, allow_overlay);
    client_->PictureReady(picture);
  }
}

void DXVAVideoDecodeAccelerator::NotifyInputBuffersDropped(
    const PendingInputs& pending_buffers) {
  DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
  if (!client_)
    return;

  for (const auto& buffer : pending_buffers) {
    LONGLONG input_buffer_id = 0;
    RETURN_ON_HR_FAILURE(buffer->GetSampleTime(&input_buffer_id),
                         "Failed to get buffer id associated with sample", );
    client_->NotifyEndOfBitstreamBuffer(input_buffer_id);
  }
}

void DXVAVideoDecodeAccelerator::DecodePendingInputBuffers() {
  TRACE_EVENT0("media",
               "DXVAVideoDecodeAccelerator::DecodePendingInputBuffers");
  DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
  DCHECK(!processing_config_changed_);

  State state = GetState();
  RETURN_AND_NOTIFY_ON_FAILURE((state != kUninitialized),
                               "Invalid state: " << state, ILLEGAL_STATE, );

  if (pending_input_buffers_.empty() || OutputSamplesPresent())
    return;

  PendingInputs pending_input_buffers_copy;
  std::swap(pending_input_buffers_, pending_input_buffers_copy);

  for (PendingInputs::iterator it = pending_input_buffers_copy.begin();
       it != pending_input_buffers_copy.end(); ++it) {
    DecodeInternal(*it);
  }
}

void DXVAVideoDecodeAccelerator::FlushInternal() {
  TRACE_EVENT0("media", "DXVAVideoDecodeAccelerator::FlushInternal");
  DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());

  // We allow only one output frame to be present at any given time. If we have
  // an output frame, then we cannot complete the flush at this time.
  if (OutputSamplesPresent())
    return;

  // First drain the pending input because once the drain message is sent below,
  // the decoder will ignore further input until it's drained.
  // If we are processing a video configuration change, then we should just
  // the drain the decoder.
  if (!processing_config_changed_ && !pending_input_buffers_.empty()) {
    decoder_thread_task_runner_->PostTask(
        FROM_HERE,
        base::BindOnce(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers,
                       base::Unretained(this)));
    decoder_thread_task_runner_->PostTask(
        FROM_HERE, base::BindOnce(&DXVAVideoDecodeAccelerator::FlushInternal,
                                  base::Unretained(this)));
    return;
  }

  {
    base::AutoLock lock(decoder_lock_);
    if (!sent_drain_message_) {
      RETURN_AND_NOTIFY_ON_FAILURE(SendMFTMessage(MFT_MESSAGE_COMMAND_DRAIN, 0),
                                   "Failed to send drain message",
                                   PLATFORM_FAILURE, );
      sent_drain_message_ = true;
    }
  }

  // Attempt to retrieve an output frame from the decoder. If we have one,
  // return and proceed when the output frame is processed. If we don't have a
  // frame then we are done.
  DoDecode(current_visible_rect_, current_color_space_.ToGfxColorSpace());
  if (OutputSamplesPresent())
    return;

  if (!processing_config_changed_) {
    SetState(kFlushing);

    main_thread_task_runner_->PostTask(
        FROM_HERE, base::BindOnce(&DXVAVideoDecodeAccelerator::NotifyFlushDone,
                                  weak_ptr_));
  } else {
    processing_config_changed_ = false;
    main_thread_task_runner_->PostTask(
        FROM_HERE, base::BindOnce(&DXVAVideoDecodeAccelerator::ConfigChanged,
                                  weak_ptr_, config_));
  }

  SetState(kNormal);
}

void DXVAVideoDecodeAccelerator::DecodeInternal(
    const Microsoft::WRL::ComPtr<IMFSample>& sample) {
  TRACE_EVENT0("media", "DXVAVideoDecodeAccelerator::DecodeInternal");
  DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());

  if (GetState() == kUninitialized)
    return;

  if (OutputSamplesPresent() || !pending_input_buffers_.empty()) {
    pending_input_buffers_.push_back(sample);
    return;
  }

  // Check if the resolution, bit rate, etc changed in the stream. If yes we
  // reinitialize the decoder to ensure that the stream decodes correctly.
  bool config_changed = false;

  HRESULT hr = CheckConfigChanged(sample.Get(), &config_changed);
  RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to check video stream config",
                                  PLATFORM_FAILURE, );

  processing_config_changed_ = config_changed;

  if (config_changed) {
    pending_input_buffers_.push_back(sample);
    FlushInternal();
    return;
  }

  gfx::Rect visible_rect;
  VideoColorSpace color_space = config_.container_color_space;
  if (config_change_detector_) {
    visible_rect = config_change_detector_->current_visible_rect(visible_rect);
    color_space = config_change_detector_->current_color_space(color_space);
  }
  current_visible_rect_ = visible_rect;
  current_color_space_ = color_space;

  if (!inputs_before_decode_) {
    TRACE_EVENT_ASYNC_BEGIN0("gpu", "DXVAVideoDecodeAccelerator.Decoding",
                             this);
  }
  inputs_before_decode_++;
  hr = decoder_->ProcessInput(0, sample.Get(), 0);
  // As per msdn if the decoder returns MF_E_NOTACCEPTING then it means that it
  // has enough data to produce one or more output samples. In this case the
  // recommended options are to
  // 1. Generate new output by calling IMFTransform::ProcessOutput until it
  //    returns MF_E_TRANSFORM_NEED_MORE_INPUT.
  // 2. Flush the input data
  // We implement the first option, i.e to retrieve the output sample and then
  // process the input again. Failure in either of these steps is treated as a
  // decoder failure.
  if (hr == MF_E_NOTACCEPTING) {
    DoDecode(visible_rect, color_space.ToGfxColorSpace());
    // If the DoDecode call resulted in an output frame then we should not
    // process any more input until that frame is copied to the target surface.
    if (!OutputSamplesPresent()) {
      State state = GetState();
      RETURN_AND_NOTIFY_ON_FAILURE(
          (state == kStopped || state == kNormal || state == kFlushing),
          "Failed to process output. Unexpected decoder state: " << state,
          PLATFORM_FAILURE, );
      hr = decoder_->ProcessInput(0, sample.Get(), 0);
    }
    // If we continue to get the MF_E_NOTACCEPTING error we do the following:-
    // 1. Add the input sample to the pending queue.
    // 2. If we don't have any output samples we post the
    //    DecodePendingInputBuffers task to process the pending input samples.
    //    If we have an output sample then the above task is posted when the
    //    output samples are sent to the client.
    // This is because we only support 1 pending output sample at any
    // given time due to the limitation with the Microsoft media foundation
    // decoder where it recycles the output Decoder surfaces.
    if (hr == MF_E_NOTACCEPTING) {
      pending_input_buffers_.push_back(sample);
      decoder_thread_task_runner_->PostTask(
          FROM_HERE,
          base::BindOnce(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers,
                         base::Unretained(this)));
      return;
    }
  }
  RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to process input sample",
                                  PLATFORM_FAILURE, );

  DoDecode(visible_rect, color_space.ToGfxColorSpace());

  State state = GetState();
  RETURN_AND_NOTIFY_ON_FAILURE(
      (state == kStopped || state == kNormal || state == kFlushing),
      "Failed to process output. Unexpected decoder state: " << state,
      ILLEGAL_STATE, );

  LONGLONG input_buffer_id = 0;
  RETURN_ON_HR_FAILURE(
      sample->GetSampleTime(&input_buffer_id),
      "Failed to get input buffer id associated with sample", );
  // The Microsoft Media foundation decoder internally buffers up to 30 frames
  // before returning a decoded frame. We need to inform the client that this
  // input buffer is processed as it may stop sending us further input.
  // Note: This may break clients which expect every input buffer to be
  // associated with a decoded output buffer.
  // TODO(ananta)
  // Do some more investigation into whether it is possible to get the MFT
  // decoder to emit an output packet for every input packet.
  // http://code.google.com/p/chromium/issues/detail?id=108121
  // http://code.google.com/p/chromium/issues/detail?id=150925
  main_thread_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&DXVAVideoDecodeAccelerator::NotifyInputBufferRead,
                     weak_ptr_, input_buffer_id));
}

void DXVAVideoDecodeAccelerator::HandleResolutionChanged(int width,
                                                         int height) {
  main_thread_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&DXVAVideoDecodeAccelerator::DismissStaleBuffers,
                     weak_ptr_, false));

  main_thread_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&DXVAVideoDecodeAccelerator::RequestPictureBuffers,
                     weak_ptr_, width, height));
}

void DXVAVideoDecodeAccelerator::DismissStaleBuffers(bool force) {
  RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_cb_.Run(),
                               "Failed to make context current",
                               PLATFORM_FAILURE, );

  OutputBuffers::iterator index;

  for (index = output_picture_buffers_.begin();
       index != output_picture_buffers_.end(); ++index) {
    if (force || index->second->available()) {
      DVLOG(1) << "Dismissing picture id: " << index->second->id();
      client_->DismissPictureBuffer(index->second->id());
    } else {
      // Move to |stale_output_picture_buffers_| for deferred deletion.
      stale_output_picture_buffers_.insert(
          std::make_pair(index->first, index->second));
    }
  }

  output_picture_buffers_.clear();
}

void DXVAVideoDecodeAccelerator::DeferredDismissStaleBuffer(
    int32_t picture_buffer_id) {
  RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_cb_.Run(),
                               "Failed to make context current",
                               PLATFORM_FAILURE, );

  OutputBuffers::iterator it =
      stale_output_picture_buffers_.find(picture_buffer_id);
  DCHECK(it != stale_output_picture_buffers_.end());
  DVLOG(1) << "Dismissing picture id: " << it->second->id();
  client_->DismissPictureBuffer(it->second->id());
  stale_output_picture_buffers_.erase(it);
}

DXVAVideoDecodeAccelerator::State DXVAVideoDecodeAccelerator::GetState() {
  static_assert(sizeof(State) == sizeof(long), "mismatched type sizes");
  State state = static_cast<State>(
      InterlockedAdd(reinterpret_cast<volatile long*>(&state_), 0));
  return state;
}

void DXVAVideoDecodeAccelerator::SetState(State new_state) {
  if (!main_thread_task_runner_->BelongsToCurrentThread()) {
    main_thread_task_runner_->PostTask(
        FROM_HERE, base::BindOnce(&DXVAVideoDecodeAccelerator::SetState,
                                  weak_ptr_, new_state));
    return;
  }

  static_assert(sizeof(State) == sizeof(long), "mismatched type sizes");
  ::InterlockedExchange(reinterpret_cast<volatile long*>(&state_), new_state);
  DCHECK_EQ(state_, new_state);
}

bool DXVAVideoDecodeAccelerator::StartDecoderThread() {
  decoder_thread_.init_com_with_mta(true);
  decoder_thread_.Start();
  decoder_thread_task_runner_ = decoder_thread_.task_runner();
  if (!decoder_thread_task_runner_) {
    LOG(ERROR) << "Failed to initialize decoder thread";
    return false;
  }
  return true;
}

bool DXVAVideoDecodeAccelerator::OutputSamplesPresent() {
  base::AutoLock lock(decoder_lock_);
  return !pending_output_samples_.empty();
}

void DXVAVideoDecodeAccelerator::CopySurface(
    IDirect3DSurface9* src_surface,
    IDirect3DSurface9* dest_surface,
    int picture_buffer_id,
    int input_buffer_id,
    const gfx::ColorSpace& color_space) {
  TRACE_EVENT0("media", "DXVAVideoDecodeAccelerator::CopySurface");
  if (!decoder_thread_task_runner_->BelongsToCurrentThread()) {
    decoder_thread_task_runner_->PostTask(
        FROM_HERE,
        base::BindOnce(&DXVAVideoDecodeAccelerator::CopySurface,
                       base::Unretained(this), base::Unretained(src_surface),
                       base::Unretained(dest_surface), picture_buffer_id,
                       input_buffer_id, color_space));
    return;
  }

  HRESULT hr;
  if (processor_) {
    D3DSURFACE_DESC src_desc;
    src_surface->GetDesc(&src_desc);
    int width = src_desc.Width;
    int height = src_desc.Height;
    RECT rect = {0, 0, width, height};
    DXVA2_VideoSample sample = {0};
    sample.End = 1000;
    if (use_color_info_) {
      sample.SampleFormat = gfx::ColorSpaceWin::GetExtendedFormat(color_space);
    } else {
      sample.SampleFormat.SampleFormat = DXVA2_SampleProgressiveFrame;
    }

    sample.SrcSurface = src_surface;
    sample.SrcRect = rect;
    sample.DstRect = rect;
    sample.PlanarAlpha = DXVA2_Fixed32OpaqueAlpha();

    DXVA2_VideoProcessBltParams params = {0};
    params.TargetFrame = 0;
    params.TargetRect = rect;
    params.ConstrictionSize = {width, height};
    params.BackgroundColor = {0, 0, 0, 0xFFFF};
    params.ProcAmpValues = default_procamp_values_;

    params.Alpha = DXVA2_Fixed32OpaqueAlpha();

    hr = processor_->VideoProcessBlt(dest_surface, &params, &sample, 1, NULL);
    if (hr != S_OK) {
      LOG(ERROR) << "VideoProcessBlt failed with code " << hr
                 << "  E_INVALIDARG= " << E_INVALIDARG;

      // Release the processor and fall back to StretchRect()
      processor_ = nullptr;
    }
  }

  if (!processor_) {
    hr = d3d9_device_ex_->StretchRect(src_surface, NULL, dest_surface, NULL,
                                      D3DTEXF_NONE);
    RETURN_ON_HR_FAILURE(hr, "Colorspace conversion via StretchRect failed", );
  }
  // Ideally, this should be done immediately before the draw call that uses
  // the texture. Flush it once here though.
  hr = query_->Issue(D3DISSUE_END);
  RETURN_ON_HR_FAILURE(hr, "Failed to issue END", );

  // If we are sharing the ANGLE device we don't need to wait for the Flush to
  // complete.
  if (using_angle_device_) {
    main_thread_task_runner_->PostTask(
        FROM_HERE,
        base::BindOnce(&DXVAVideoDecodeAccelerator::CopySurfaceComplete,
                       weak_ptr_, base::Unretained(src_surface),
                       base::Unretained(dest_surface), picture_buffer_id,
                       input_buffer_id));
    return;
  }

  // Flush the decoder device to ensure that the decoded frame is copied to the
  // target surface.
  decoder_thread_task_runner_->PostDelayedTask(
      FROM_HERE,
      base::BindOnce(&DXVAVideoDecodeAccelerator::FlushDecoder,
                     base::Unretained(this), 0, base::Unretained(src_surface),
                     base::Unretained(dest_surface), picture_buffer_id,
                     input_buffer_id),
      base::TimeDelta::FromMilliseconds(kFlushDecoderSurfaceTimeoutMs));
}

void DXVAVideoDecodeAccelerator::CopySurfaceComplete(
    IDirect3DSurface9* src_surface,
    IDirect3DSurface9* dest_surface,
    int picture_buffer_id,
    int input_buffer_id) {
  TRACE_EVENT0("media", "DXVAVideoDecodeAccelerator::CopySurfaceComplete");
  DCHECK(main_thread_task_runner_->BelongsToCurrentThread());

  // The output buffers may have changed in the following scenarios:-
  // 1. A resolution change.
  // 2. Decoder instance was destroyed.
  // Ignore copy surface notifications for such buffers.
  OutputBuffers::iterator it = output_picture_buffers_.find(picture_buffer_id);
  if (it == output_picture_buffers_.end())
    return;

  // If the picture buffer is marked as available it probably means that there
  // was a Reset operation which dropped the output frame.
  DXVAPictureBuffer* picture_buffer = it->second.get();
  if (picture_buffer->available())
    return;

  RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_cb_.Run(),
                               "Failed to make context current",
                               PLATFORM_FAILURE, );

  DCHECK(!output_picture_buffers_.empty());

  bool result = picture_buffer->CopySurfaceComplete(src_surface, dest_surface);
  RETURN_AND_NOTIFY_ON_FAILURE(result, "Failed to complete copying surface",
                               PLATFORM_FAILURE, );

  NotifyPictureReady(
      picture_buffer->id(), input_buffer_id, picture_buffer->visible_rect(),
      picture_buffer->color_space(), picture_buffer->AllowOverlay());

  {
    base::AutoLock lock(decoder_lock_);
    if (!pending_output_samples_.empty())
      pending_output_samples_.pop_front();
  }

  if (pending_flush_ || processing_config_changed_) {
    decoder_thread_task_runner_->PostTask(
        FROM_HERE, base::BindOnce(&DXVAVideoDecodeAccelerator::FlushInternal,
                                  base::Unretained(this)));
    return;
  }
  decoder_thread_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers,
                     base::Unretained(this)));
}

void DXVAVideoDecodeAccelerator::BindPictureBufferToSample(
    Microsoft::WRL::ComPtr<IMFSample> sample,
    int picture_buffer_id,
    int input_buffer_id) {
  TRACE_EVENT0("media",
               "DXVAVideoDecodeAccelerator::BindPictureBufferToSample");
  DCHECK(main_thread_task_runner_->BelongsToCurrentThread());

  // The output buffers may have changed in the following scenarios:-
  // 1. A resolution change.
  // 2. Decoder instance was destroyed.
  // Ignore copy surface notifications for such buffers.
  OutputBuffers::iterator it = output_picture_buffers_.find(picture_buffer_id);
  if (it == output_picture_buffers_.end())
    return;

  // If the picture buffer is marked as available it probably means that there
  // was a Reset operation which dropped the output frame.
  DXVAPictureBuffer* picture_buffer = it->second.get();
  if (picture_buffer->available())
    return;

  RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_cb_.Run(),
                               "Failed to make context current",
                               PLATFORM_FAILURE, );

  DCHECK(!output_picture_buffers_.empty());

  bool result = picture_buffer->BindSampleToTexture(this, sample);
  RETURN_AND_NOTIFY_ON_FAILURE(result, "Failed to complete copying surface",
                               PLATFORM_FAILURE, );

  NotifyPictureReady(
      picture_buffer->id(), input_buffer_id, picture_buffer->visible_rect(),
      picture_buffer->color_space(), picture_buffer->AllowOverlay());

  {
    base::AutoLock lock(decoder_lock_);
    if (!pending_output_samples_.empty())
      pending_output_samples_.pop_front();
  }

  if (pending_flush_ || processing_config_changed_) {
    decoder_thread_task_runner_->PostTask(
        FROM_HERE, base::BindOnce(&DXVAVideoDecodeAccelerator::FlushInternal,
                                  base::Unretained(this)));
    return;
  }
  decoder_thread_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers,
                     base::Unretained(this)));
}

void DXVAVideoDecodeAccelerator::CopyTexture(
    ID3D11Texture2D* src_texture,
    ID3D11Texture2D* dest_texture,
    Microsoft::WRL::ComPtr<IDXGIKeyedMutex> dest_keyed_mutex,
    uint64_t keyed_mutex_value,
    int picture_buffer_id,
    int input_buffer_id,
    const gfx::ColorSpace& color_space) {
  TRACE_EVENT0("media", "DXVAVideoDecodeAccelerator::CopyTexture");
  DCHECK(main_thread_task_runner_->BelongsToCurrentThread());

  DCHECK(use_dx11_);

  // The media foundation H.264 decoder outputs YUV12 textures which we
  // cannot copy into ANGLE as they expect ARGB textures. In D3D land
  // the StretchRect API in the IDirect3DDevice9Ex interface did the color
  // space conversion for us. Sadly in DX11 land the API does not provide
  // a straightforward way to do this.

  D3D11_TEXTURE2D_DESC source_desc;
  src_texture->GetDesc(&source_desc);
  if (!InitializeID3D11VideoProcessor(source_desc.Width, source_desc.Height,
                                      color_space)) {
    RETURN_AND_NOTIFY_ON_FAILURE(false,
                                 "Failed to initialize D3D11 video processor.",
                                 PLATFORM_FAILURE, );
  }

  OutputBuffers::iterator it = output_picture_buffers_.find(picture_buffer_id);
  if (it != output_picture_buffers_.end()) {
    it->second->set_color_space(dx11_converter_output_color_space_);
  }

  // The input to the video processor is the output sample.
  Microsoft::WRL::ComPtr<IMFSample> input_sample_for_conversion;
  {
    base::AutoLock lock(decoder_lock_);
    PendingSampleInfo& sample_info = pending_output_samples_.front();
    input_sample_for_conversion = sample_info.output_sample;
  }

  decoder_thread_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&DXVAVideoDecodeAccelerator::CopyTextureOnDecoderThread,
                     base::Unretained(this), base::Unretained(dest_texture),
                     dest_keyed_mutex, keyed_mutex_value,
                     input_sample_for_conversion, picture_buffer_id,
                     input_buffer_id));
}

void DXVAVideoDecodeAccelerator::CopyTextureOnDecoderThread(
    ID3D11Texture2D* dest_texture,
    Microsoft::WRL::ComPtr<IDXGIKeyedMutex> dest_keyed_mutex,
    uint64_t keyed_mutex_value,
    Microsoft::WRL::ComPtr<IMFSample> input_sample,
    int picture_buffer_id,
    int input_buffer_id) {
  TRACE_EVENT0("media",
               "DXVAVideoDecodeAccelerator::CopyTextureOnDecoderThread");
  DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
  HRESULT hr = E_FAIL;

  DCHECK(use_dx11_);
  DCHECK(!!input_sample);
  DCHECK(d3d11_processor_.Get());

  if (dest_keyed_mutex) {
    HRESULT hr =
        dest_keyed_mutex->AcquireSync(keyed_mutex_value, kAcquireSyncWaitMs);
    RETURN_AND_NOTIFY_ON_FAILURE(
        hr == S_OK, "D3D11 failed to acquire keyed mutex for texture.",
        PLATFORM_FAILURE, );
  }

  Microsoft::WRL::ComPtr<IMFMediaBuffer> output_buffer;
  hr = input_sample->GetBufferByIndex(0, output_buffer.GetAddressOf());
  RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to get buffer from output sample",
                                  PLATFORM_FAILURE, );

  Microsoft::WRL::ComPtr<IMFDXGIBuffer> dxgi_buffer;
  hr = output_buffer.CopyTo(dxgi_buffer.GetAddressOf());
  RETURN_AND_NOTIFY_ON_HR_FAILURE(
      hr, "Failed to get DXGIBuffer from output sample", PLATFORM_FAILURE, );
  UINT index = 0;
  hr = dxgi_buffer->GetSubresourceIndex(&index);
  RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to get resource index",
                                  PLATFORM_FAILURE, );

  Microsoft::WRL::ComPtr<ID3D11Texture2D> dx11_decoding_texture;
  hr = dxgi_buffer->GetResource(
      IID_PPV_ARGS(dx11_decoding_texture.GetAddressOf()));
  RETURN_AND_NOTIFY_ON_HR_FAILURE(
      hr, "Failed to get resource from output sample", PLATFORM_FAILURE, );

  D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC output_view_desc = {
      D3D11_VPOV_DIMENSION_TEXTURE2D};
  output_view_desc.Texture2D.MipSlice = 0;
  Microsoft::WRL::ComPtr<ID3D11VideoProcessorOutputView> output_view;
  hr = video_device_->CreateVideoProcessorOutputView(
      dest_texture, enumerator_.Get(), &output_view_desc,
      output_view.GetAddressOf());
  RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to get output view",
                                  PLATFORM_FAILURE, );

  D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC input_view_desc = {0};
  input_view_desc.ViewDimension = D3D11_VPIV_DIMENSION_TEXTURE2D;
  input_view_desc.Texture2D.ArraySlice = index;
  input_view_desc.Texture2D.MipSlice = 0;
  Microsoft::WRL::ComPtr<ID3D11VideoProcessorInputView> input_view;
  hr = video_device_->CreateVideoProcessorInputView(
      dx11_decoding_texture.Get(), enumerator_.Get(), &input_view_desc,
      input_view.GetAddressOf());
  RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to get input view",
                                  PLATFORM_FAILURE, );

  D3D11_VIDEO_PROCESSOR_STREAM streams = {0};
  streams.Enable = TRUE;
  streams.pInputSurface = input_view.Get();

  hr = video_context_->VideoProcessorBlt(d3d11_processor_.Get(),
                                         output_view.Get(), 0, 1, &streams);

  RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "VideoProcessBlit failed",
                                  PLATFORM_FAILURE, );

  if (dest_keyed_mutex) {
    HRESULT hr = dest_keyed_mutex->ReleaseSync(keyed_mutex_value + 1);
    RETURN_AND_NOTIFY_ON_FAILURE(hr == S_OK, "Failed to release keyed mutex.",
                                 PLATFORM_FAILURE, );

    main_thread_task_runner_->PostTask(
        FROM_HERE,
        base::BindOnce(&DXVAVideoDecodeAccelerator::CopySurfaceComplete,
                       weak_ptr_, nullptr, nullptr, picture_buffer_id,
                       input_buffer_id));
  } else {
    d3d11_device_context_->Flush();
    d3d11_device_context_->End(d3d11_query_.Get());

    decoder_thread_task_runner_->PostDelayedTask(
        FROM_HERE,
        base::BindOnce(&DXVAVideoDecodeAccelerator::FlushDecoder,
                       base::Unretained(this), 0, nullptr, nullptr,
                       picture_buffer_id, input_buffer_id),
        base::TimeDelta::FromMilliseconds(kFlushDecoderSurfaceTimeoutMs));
  }
}

void DXVAVideoDecodeAccelerator::FlushDecoder(int iterations,
                                              IDirect3DSurface9* src_surface,
                                              IDirect3DSurface9* dest_surface,
                                              int picture_buffer_id,
                                              int input_buffer_id) {
  TRACE_EVENT0("media", "DXVAVideoDecodeAccelerator::FlushDecoder");
  DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());

  // The DXVA decoder has its own device which it uses for decoding. ANGLE
  // has its own device which we don't have access to.
  // The above code attempts to copy the decoded picture into a surface
  // which is owned by ANGLE. As there are multiple devices involved in
  // this, the StretchRect call above is not synchronous.
  // We attempt to flush the batched operations to ensure that the picture is
  // copied to the surface owned by ANGLE.
  // We need to do this in a loop and call flush multiple times.
  // We have seen the GetData call for flushing the command buffer fail to
  // return success occassionally on multi core machines, leading to an
  // infinite loop.
  // Workaround is to have an upper limit of 4 on the number of iterations to
  // wait for the Flush to finish.

  HRESULT hr = E_FAIL;
  if (use_dx11_) {
    BOOL query_data = 0;
    hr = d3d11_device_context_->GetData(d3d11_query_.Get(), &query_data,
                                        sizeof(BOOL), 0);
    if (FAILED(hr))
      DCHECK(false);
  } else {
    hr = query_->GetData(NULL, 0, D3DGETDATA_FLUSH);
  }

  if ((hr == S_FALSE) && (++iterations < kMaxIterationsForD3DFlush)) {
    decoder_thread_task_runner_->PostDelayedTask(
        FROM_HERE,
        base::BindOnce(
            &DXVAVideoDecodeAccelerator::FlushDecoder, base::Unretained(this),
            iterations, base::Unretained(src_surface),
            base::Unretained(dest_surface), picture_buffer_id, input_buffer_id),
        base::TimeDelta::FromMilliseconds(kFlushDecoderSurfaceTimeoutMs));
    return;
  }

  main_thread_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&DXVAVideoDecodeAccelerator::CopySurfaceComplete,
                     weak_ptr_, base::Unretained(src_surface),
                     base::Unretained(dest_surface), picture_buffer_id,
                     input_buffer_id));
}

bool DXVAVideoDecodeAccelerator::InitializeID3D11VideoProcessor(
    int width,
    int height,
    const gfx::ColorSpace& color_space) {
  if (width < processor_width_ || height != processor_height_) {
    d3d11_processor_.Reset();
    enumerator_.Reset();
    processor_width_ = 0;
    processor_height_ = 0;

    D3D11_VIDEO_PROCESSOR_CONTENT_DESC desc;
    desc.InputFrameFormat = D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE;
    desc.InputFrameRate.Numerator = 60;
    desc.InputFrameRate.Denominator = 1;
    desc.InputWidth = width;
    desc.InputHeight = height;
    desc.OutputFrameRate.Numerator = 60;
    desc.OutputFrameRate.Denominator = 1;
    desc.OutputWidth = width;
    desc.OutputHeight = height;
    desc.Usage = D3D11_VIDEO_USAGE_PLAYBACK_NORMAL;

    HRESULT hr = video_device_->CreateVideoProcessorEnumerator(
        &desc, enumerator_.GetAddressOf());
    RETURN_ON_HR_FAILURE(hr, "Failed to enumerate video processors", false);

    // TODO(Hubbe): Find correct index
    hr = video_device_->CreateVideoProcessor(enumerator_.Get(), 0,
                                             d3d11_processor_.GetAddressOf());
    RETURN_ON_HR_FAILURE(hr, "Failed to create video processor.", false);
    processor_width_ = width;
    processor_height_ = height;

    video_context_->VideoProcessorSetStreamAutoProcessingMode(
        d3d11_processor_.Get(), 0, false);
  }

  if (GetPictureBufferMechanism() == PictureBufferMechanism::COPY_TO_NV12 ||
      GetPictureBufferMechanism() ==
          PictureBufferMechanism::DELAYED_COPY_TO_NV12) {
    // If we're copying NV12 textures, make sure we set the same
    // color space on input and output.
    D3D11_VIDEO_PROCESSOR_COLOR_SPACE d3d11_color_space = {0};
    d3d11_color_space.RGB_Range = 1;
    d3d11_color_space.Nominal_Range = D3D11_VIDEO_PROCESSOR_NOMINAL_RANGE_0_255;

    video_context_->VideoProcessorSetOutputColorSpace(d3d11_processor_.Get(),
                                                      &d3d11_color_space);

    video_context_->VideoProcessorSetStreamColorSpace(d3d11_processor_.Get(), 0,
                                                      &d3d11_color_space);
    dx11_converter_output_color_space_ = color_space;
  } else {
    dx11_converter_output_color_space_ = gfx::ColorSpace::CreateSRGB();
    if (use_color_info_ || use_fp16_) {
      Microsoft::WRL::ComPtr<ID3D11VideoContext1> video_context1;
      HRESULT hr = video_context_.CopyTo(video_context1.GetAddressOf());
      if (SUCCEEDED(hr)) {
        if (use_fp16_ && config_.target_color_space.IsHDR() &&
            color_space.IsHDR()) {
          // Note, we only use the SCRGBLinear output color space when
          // the input is PQ, because nvidia drivers will not convert
          // G22 to G10 for some reason.
          dx11_converter_output_color_space_ =
              gfx::ColorSpace::CreateSCRGBLinear();
        }
        // Since the video processor doesn't support HLG, let's just do the
        // YUV->RGB conversion and let the output color space be HLG.
        // This won't work well unless color management is on, but if color
        // management is off we don't support HLG anyways.
        if (color_space ==
            gfx::ColorSpace(gfx::ColorSpace::PrimaryID::BT2020,
                            gfx::ColorSpace::TransferID::ARIB_STD_B67,
                            gfx::ColorSpace::MatrixID::BT709,
                            gfx::ColorSpace::RangeID::LIMITED)) {
          video_context1->VideoProcessorSetStreamColorSpace1(
              d3d11_processor_.Get(), 0,
              DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_LEFT_P2020);
          video_context1->VideoProcessorSetOutputColorSpace1(
              d3d11_processor_.Get(),
              DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020);
          dx11_converter_output_color_space_ = color_space.GetAsFullRangeRGB();
        } else {
          DVLOG(2) << "input color space: " << color_space
                   << " DXGIColorSpace: "
                   << gfx::ColorSpaceWin::GetDXGIColorSpace(color_space);
          DVLOG(2) << "output color space:"
                   << dx11_converter_output_color_space_ << " DXGIColorSpace: "
                   << gfx::ColorSpaceWin::GetDXGIColorSpace(
                          dx11_converter_output_color_space_);
          video_context1->VideoProcessorSetStreamColorSpace1(
              d3d11_processor_.Get(), 0,
              gfx::ColorSpaceWin::GetDXGIColorSpace(color_space));
          video_context1->VideoProcessorSetOutputColorSpace1(
              d3d11_processor_.Get(), gfx::ColorSpaceWin::GetDXGIColorSpace(
                                          dx11_converter_output_color_space_));
        }
      } else {
        D3D11_VIDEO_PROCESSOR_COLOR_SPACE d3d11_color_space =
            gfx::ColorSpaceWin::GetD3D11ColorSpace(color_space);
        video_context_->VideoProcessorSetStreamColorSpace(
            d3d11_processor_.Get(), 0, &d3d11_color_space);
        d3d11_color_space = gfx::ColorSpaceWin::GetD3D11ColorSpace(
            dx11_converter_output_color_space_);
        video_context_->VideoProcessorSetOutputColorSpace(
            d3d11_processor_.Get(), &d3d11_color_space);
      }
    }
  }
  return true;
}

bool DXVAVideoDecodeAccelerator::GetVideoFrameDimensions(IMFSample* sample,
                                                         int* width,
                                                         int* height) {
  Microsoft::WRL::ComPtr<IMFMediaBuffer> output_buffer;
  HRESULT hr = sample->GetBufferByIndex(0, output_buffer.GetAddressOf());
  RETURN_ON_HR_FAILURE(hr, "Failed to get buffer from output sample", false);

  if (use_dx11_) {
    Microsoft::WRL::ComPtr<IMFDXGIBuffer> dxgi_buffer;
    Microsoft::WRL::ComPtr<ID3D11Texture2D> d3d11_texture;
    hr = output_buffer.CopyTo(dxgi_buffer.GetAddressOf());
    RETURN_ON_HR_FAILURE(hr, "Failed to get DXGIBuffer from output sample",
                         false);
    hr = dxgi_buffer->GetResource(
        __uuidof(ID3D11Texture2D),
        reinterpret_cast<void**>(d3d11_texture.GetAddressOf()));
    RETURN_ON_HR_FAILURE(hr, "Failed to get D3D11Texture from output buffer",
                         false);
    D3D11_TEXTURE2D_DESC d3d11_texture_desc;
    d3d11_texture->GetDesc(&d3d11_texture_desc);
    *width = d3d11_texture_desc.Width;
    *height = d3d11_texture_desc.Height;
    output_array_size_ = d3d11_texture_desc.ArraySize;
  } else {
    Microsoft::WRL::ComPtr<IDirect3DSurface9> surface;
    hr = MFGetService(output_buffer.Get(), MR_BUFFER_SERVICE,
                      IID_PPV_ARGS(surface.GetAddressOf()));
    RETURN_ON_HR_FAILURE(hr, "Failed to get D3D surface from output sample",
                         false);
    D3DSURFACE_DESC surface_desc;
    hr = surface->GetDesc(&surface_desc);
    RETURN_ON_HR_FAILURE(hr, "Failed to get surface description", false);
    *width = surface_desc.Width;
    *height = surface_desc.Height;
  }
  return true;
}

bool DXVAVideoDecodeAccelerator::SetTransformOutputType(IMFTransform* transform,
                                                        const GUID& output_type,
                                                        int width,
                                                        int height) {
  HRESULT hr = E_FAIL;
  Microsoft::WRL::ComPtr<IMFMediaType> media_type;

  for (uint32_t i = 0; SUCCEEDED(
           transform->GetOutputAvailableType(0, i, media_type.GetAddressOf()));
       ++i) {
    GUID out_subtype = {0};
    hr = media_type->GetGUID(MF_MT_SUBTYPE, &out_subtype);
    RETURN_ON_HR_FAILURE(hr, "Failed to get output major type", false);

    if (out_subtype == output_type) {
      if (width && height) {
        hr = MFSetAttributeSize(media_type.Get(), MF_MT_FRAME_SIZE, width,
                                height);
        RETURN_ON_HR_FAILURE(hr, "Failed to set media type attributes", false);
      }
      hr = transform->SetOutputType(0, media_type.Get(), 0);  // No flags
      RETURN_ON_HR_FAILURE(hr, "Failed to set output type", false);
      return true;
    }
    media_type.Reset();
  }
  return false;
}

HRESULT DXVAVideoDecodeAccelerator::CheckConfigChanged(IMFSample* sample,
                                                       bool* config_changed) {
  if (!config_change_detector_) {
    *config_changed = false;
    return S_OK;
  }

  Microsoft::WRL::ComPtr<IMFMediaBuffer> buffer;
  HRESULT hr = sample->GetBufferByIndex(0, buffer.GetAddressOf());
  RETURN_ON_HR_FAILURE(hr, "Failed to get buffer from input sample", hr);

  mf::MediaBufferScopedPointer scoped_media_buffer(buffer.Get());

  if (!config_change_detector_->DetectConfig(
          scoped_media_buffer.get(), scoped_media_buffer.current_length())) {
    RETURN_ON_HR_FAILURE(E_FAIL, "Failed to detect H.264 stream config",
                         E_FAIL);
  }
  *config_changed = config_change_detector_->config_changed();
  return S_OK;
}

void DXVAVideoDecodeAccelerator::ConfigChanged(const Config& config) {
  DCHECK(main_thread_task_runner_->BelongsToCurrentThread());

  SetState(kConfigChange);
  Invalidate();
  Initialize(config_, client_);
  decoder_thread_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers,
                     base::Unretained(this)));
}

uint32_t DXVAVideoDecodeAccelerator::GetTextureTarget() const {
  switch (GetPictureBufferMechanism()) {
    case PictureBufferMechanism::BIND:
    case PictureBufferMechanism::DELAYED_COPY_TO_NV12:
    case PictureBufferMechanism::COPY_TO_NV12:
      return GL_TEXTURE_EXTERNAL_OES;
    case PictureBufferMechanism::COPY_TO_RGB:
      return GL_TEXTURE_2D;
  }
  NOTREACHED();
  return 0;
}

void DXVAVideoDecodeAccelerator::DisableSharedTextureSupport() {
  support_share_nv12_textures_ = false;
  num_picture_buffers_requested_ = kNumPictureBuffers;
}

DXVAVideoDecodeAccelerator::PictureBufferMechanism
DXVAVideoDecodeAccelerator::GetPictureBufferMechanism() const {
  if (use_fp16_)
    return PictureBufferMechanism::COPY_TO_RGB;
  if (support_share_nv12_textures_)
    return PictureBufferMechanism::BIND;
  if (support_delayed_copy_nv12_textures_ && support_copy_nv12_textures_)
    return PictureBufferMechanism::DELAYED_COPY_TO_NV12;
  if (support_copy_nv12_textures_)
    return PictureBufferMechanism::COPY_TO_NV12;
  return PictureBufferMechanism::COPY_TO_RGB;
}

bool DXVAVideoDecodeAccelerator::ShouldUseANGLEDevice() const {
  switch (GetPictureBufferMechanism()) {
    case PictureBufferMechanism::BIND:
    case PictureBufferMechanism::DELAYED_COPY_TO_NV12:
      return true;
    case PictureBufferMechanism::COPY_TO_NV12:
    case PictureBufferMechanism::COPY_TO_RGB:
      return false;
  }
  NOTREACHED();
  return false;
}
ID3D11Device* DXVAVideoDecodeAccelerator::D3D11Device() const {
  return ShouldUseANGLEDevice() ? angle_device_.Get() : d3d11_device_.Get();
}

}  // namespace media
