// 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/capture/video/win/video_capture_device_mf_win.h"

#include <d3d11_4.h>
#include <mfapi.h>
#include <mferror.h>
#include <stddef.h>
#include <wincodec.h>

#include <memory>
#include <thread>
#include <utility>

#include "base/bind.h"
#include "base/location.h"
#include "base/memory/ref_counted.h"
#include "base/metrics/histogram_functions.h"
#include "base/strings/stringprintf.h"
#include "base/strings/sys_string_conversions.h"
#include "base/synchronization/waitable_event.h"
#include "base/win/scoped_co_mem.h"
#include "base/win/windows_version.h"
#include "media/capture/mojom/image_capture_types.h"
#include "media/capture/video/blob_utils.h"
#include "media/capture/video/win/capability_list_win.h"
#include "media/capture/video/win/sink_filter_win.h"
#include "media/capture/video/win/video_capture_device_utils_win.h"

using base::Location;
using base::win::ScopedCoMem;
using Microsoft::WRL::ComPtr;

namespace media {

#if DCHECK_IS_ON()
#define DLOG_IF_FAILED_WITH_HRESULT(message, hr)                      \
  {                                                                   \
    DLOG_IF(ERROR, FAILED(hr))                                        \
        << (message) << ": " << logging::SystemErrorCodeToString(hr); \
  }
#else
#define DLOG_IF_FAILED_WITH_HRESULT(message, hr) \
  {}
#endif

namespace {

class MFPhotoCallback final
    : public base::RefCountedThreadSafe<MFPhotoCallback>,
      public IMFCaptureEngineOnSampleCallback {
 public:
  MFPhotoCallback(VideoCaptureDevice::TakePhotoCallback callback,
                  VideoCaptureFormat format)
      : callback_(std::move(callback)), format_(format) {}

  IFACEMETHODIMP QueryInterface(REFIID riid, void** object) override {
    if (riid == IID_IUnknown || riid == IID_IMFCaptureEngineOnSampleCallback) {
      AddRef();
      *object = static_cast<IMFCaptureEngineOnSampleCallback*>(this);
      return S_OK;
    }
    return E_NOINTERFACE;
  }

  IFACEMETHODIMP_(ULONG) AddRef() override {
    base::RefCountedThreadSafe<MFPhotoCallback>::AddRef();
    return 1U;
  }

  IFACEMETHODIMP_(ULONG) Release() override {
    base::RefCountedThreadSafe<MFPhotoCallback>::Release();
    return 1U;
  }

  IFACEMETHODIMP OnSample(IMFSample* sample) override {
    if (!sample)
      return S_OK;

    DWORD buffer_count = 0;
    sample->GetBufferCount(&buffer_count);

    for (DWORD i = 0; i < buffer_count; ++i) {
      ComPtr<IMFMediaBuffer> buffer;
      sample->GetBufferByIndex(i, &buffer);
      if (!buffer)
        continue;

      BYTE* data = nullptr;
      DWORD max_length = 0;
      DWORD length = 0;
      buffer->Lock(&data, &max_length, &length);
      mojom::BlobPtr blob = RotateAndBlobify(data, length, format_, 0);
      buffer->Unlock();
      if (blob) {
        std::move(callback_).Run(std::move(blob));
        LogWindowsImageCaptureOutcome(
            VideoCaptureWinBackend::kMediaFoundation,
            ImageCaptureOutcome::kSucceededUsingPhotoStream,
            IsHighResolution(format_));

        // What is it supposed to mean if there is more than one buffer sent to
        // us as a response to requesting a single still image? Are we supposed
        // to somehow concatenate the buffers? Or is it safe to ignore extra
        // buffers? For now, we ignore extra buffers.
        break;
      }
    }
    return S_OK;
  }

 private:
  friend class base::RefCountedThreadSafe<MFPhotoCallback>;
  ~MFPhotoCallback() {
    if (callback_) {
      LogWindowsImageCaptureOutcome(
          VideoCaptureWinBackend::kMediaFoundation,
          ImageCaptureOutcome::kFailedUsingPhotoStream,
          IsHighResolution(format_));
    }
  }

  VideoCaptureDevice::TakePhotoCallback callback_;
  const VideoCaptureFormat format_;

  DISALLOW_COPY_AND_ASSIGN(MFPhotoCallback);
};

// Locks the given buffer using the fastest supported method when constructed,
// and automatically unlocks the buffer when destroyed.
class ScopedBufferLock {
 public:
  explicit ScopedBufferLock(ComPtr<IMFMediaBuffer> buffer)
      : buffer_(std::move(buffer)) {
    if (FAILED(buffer_.As(&buffer_2d_))) {
      LockSlow();
      return;
    }
    // Try lock methods from fastest to slowest: Lock2DSize(), then Lock2D(),
    // then finally LockSlow().
    if (Lock2DSize() || Lock2D()) {
      if (IsContiguous())
        return;
      buffer_2d_->Unlock2D();
    }
    // Fall back to LockSlow() if 2D buffer was unsupported or noncontiguous.
    buffer_2d_ = nullptr;
    LockSlow();
  }

  // Returns whether |buffer_2d_| is contiguous with positive pitch, i.e., the
  // buffer format that the surrounding code expects.
  bool IsContiguous() {
    BOOL is_contiguous;
    return pitch_ > 0 &&
           SUCCEEDED(buffer_2d_->IsContiguousFormat(&is_contiguous)) &&
           is_contiguous &&
           (length_ || SUCCEEDED(buffer_2d_->GetContiguousLength(&length_)));
  }

  bool Lock2DSize() {
    ComPtr<IMF2DBuffer2> buffer_2d_2;
    if (FAILED(buffer_.As(&buffer_2d_2)))
      return false;
    BYTE* data_start;
    return SUCCEEDED(buffer_2d_2->Lock2DSize(MF2DBuffer_LockFlags_Read, &data_,
                                             &pitch_, &data_start, &length_));
  }

  bool Lock2D() { return SUCCEEDED(buffer_2d_->Lock2D(&data_, &pitch_)); }

  void LockSlow() {
    DWORD max_length = 0;
    buffer_->Lock(&data_, &max_length, &length_);
  }

  ~ScopedBufferLock() {
    if (buffer_2d_)
      buffer_2d_->Unlock2D();
    else
      buffer_->Unlock();
  }

  ScopedBufferLock(const ScopedBufferLock&) = delete;
  ScopedBufferLock& operator=(const ScopedBufferLock&) = delete;

  BYTE* data() const { return data_; }
  DWORD length() const { return length_; }

 private:
  ComPtr<IMFMediaBuffer> buffer_;
  ComPtr<IMF2DBuffer> buffer_2d_;
  BYTE* data_ = nullptr;
  DWORD length_ = 0;
  LONG pitch_ = 0;
};

scoped_refptr<IMFCaptureEngineOnSampleCallback> CreateMFPhotoCallback(
    VideoCaptureDevice::TakePhotoCallback callback,
    VideoCaptureFormat format) {
  return scoped_refptr<IMFCaptureEngineOnSampleCallback>(
      new MFPhotoCallback(std::move(callback), format));
}

void LogError(const Location& from_here, HRESULT hr) {
  DPLOG(ERROR) << from_here.ToString()
               << " hr = " << logging::SystemErrorCodeToString(hr);
}

bool GetFrameSizeFromMediaType(IMFMediaType* type, gfx::Size* frame_size) {
  UINT32 width32, height32;
  if (FAILED(MFGetAttributeSize(type, MF_MT_FRAME_SIZE, &width32, &height32)))
    return false;
  frame_size->SetSize(width32, height32);
  return true;
}

bool GetFrameRateFromMediaType(IMFMediaType* type, float* frame_rate) {
  UINT32 numerator, denominator;
  if (FAILED(MFGetAttributeRatio(type, MF_MT_FRAME_RATE, &numerator,
                                 &denominator)) ||
      !denominator) {
    return false;
  }
  *frame_rate = static_cast<float>(numerator) / denominator;
  return true;
}

struct PixelFormatMap {
  GUID mf_source_media_subtype;
  VideoPixelFormat pixel_format;
};

VideoPixelFormat MfSubTypeToSourcePixelFormat(
    const GUID& mf_source_media_subtype) {
  static const PixelFormatMap kPixelFormatMap[] = {

      {MFVideoFormat_I420, PIXEL_FORMAT_I420},
      {MFVideoFormat_YUY2, PIXEL_FORMAT_YUY2},
      {MFVideoFormat_UYVY, PIXEL_FORMAT_UYVY},
      {MFVideoFormat_RGB24, PIXEL_FORMAT_RGB24},
      {MFVideoFormat_RGB32, PIXEL_FORMAT_XRGB},
      {MFVideoFormat_ARGB32, PIXEL_FORMAT_ARGB},
      {MFVideoFormat_MJPG, PIXEL_FORMAT_MJPEG},
      {MFVideoFormat_NV12, PIXEL_FORMAT_NV12},
      {MFVideoFormat_YV12, PIXEL_FORMAT_YV12},
      {GUID_ContainerFormatJpeg, PIXEL_FORMAT_MJPEG}};

  for (const auto& kEntry : kPixelFormatMap) {
    if (kEntry.mf_source_media_subtype == mf_source_media_subtype) {
      return kEntry.pixel_format;
    }
  }
  return PIXEL_FORMAT_UNKNOWN;
}

bool GetFormatFromSourceMediaType(IMFMediaType* source_media_type,
                                  bool photo,
                                  bool use_hardware_format,
                                  VideoCaptureFormat* format,
                                  VideoPixelFormat* source_pixel_format) {
  GUID major_type_guid;
  if (FAILED(source_media_type->GetGUID(MF_MT_MAJOR_TYPE, &major_type_guid)) ||
      (major_type_guid != MFMediaType_Image &&
       (photo ||
        !GetFrameRateFromMediaType(source_media_type, &format->frame_rate)))) {
    return false;
  }

  GUID sub_type_guid;
  if (FAILED(source_media_type->GetGUID(MF_MT_SUBTYPE, &sub_type_guid)) ||
      !GetFrameSizeFromMediaType(source_media_type, &format->frame_size) ||
      !VideoCaptureDeviceMFWin::GetPixelFormatFromMFSourceMediaSubtype(
          sub_type_guid, use_hardware_format, &format->pixel_format)) {
    return false;
  }

  *source_pixel_format = MfSubTypeToSourcePixelFormat(sub_type_guid);
  return true;
}

HRESULT CopyAttribute(IMFAttributes* source_attributes,
                      IMFAttributes* destination_attributes,
                      const GUID& key) {
  PROPVARIANT var;
  PropVariantInit(&var);
  HRESULT hr = source_attributes->GetItem(key, &var);
  if (FAILED(hr))
    return hr;

  hr = destination_attributes->SetItem(key, var);
  PropVariantClear(&var);
  return hr;
}

struct MediaFormatConfiguration {
  bool is_hardware_format;
  GUID mf_source_media_subtype;
  GUID mf_sink_media_subtype;
  VideoPixelFormat pixel_format;
};

bool GetMediaFormatConfigurationFromMFSourceMediaSubtype(
    const GUID& mf_source_media_subtype,
    bool use_hardware_format,
    MediaFormatConfiguration* media_format_configuration) {
  static const MediaFormatConfiguration kMediaFormatConfigurationMap[] = {
      // IMFCaptureEngine inevitably performs the video frame decoding itself.
      // This means that the sink must always be set to an uncompressed video
      // format.

      // Since chromium uses I420 at the other end of the pipe, MF known video
      // output formats are always set to I420.
      {false, MFVideoFormat_I420, MFVideoFormat_I420, PIXEL_FORMAT_I420},
      {false, MFVideoFormat_YUY2, MFVideoFormat_I420, PIXEL_FORMAT_I420},
      {false, MFVideoFormat_UYVY, MFVideoFormat_I420, PIXEL_FORMAT_I420},
      {false, MFVideoFormat_RGB24, MFVideoFormat_I420, PIXEL_FORMAT_I420},
      {false, MFVideoFormat_RGB32, MFVideoFormat_I420, PIXEL_FORMAT_I420},
      {false, MFVideoFormat_ARGB32, MFVideoFormat_I420, PIXEL_FORMAT_I420},
      {false, MFVideoFormat_MJPG, MFVideoFormat_I420, PIXEL_FORMAT_I420},
      {false, MFVideoFormat_NV12, MFVideoFormat_I420, PIXEL_FORMAT_I420},
      {false, MFVideoFormat_YV12, MFVideoFormat_I420, PIXEL_FORMAT_I420},

      // Depth cameras use 16-bit uncompressed video formats.
      // We ask IMFCaptureEngine to let the frame pass through, without
      // transcoding, since transcoding would lead to precision loss.
      {false, kMediaSubTypeY16, kMediaSubTypeY16, PIXEL_FORMAT_Y16},
      {false, kMediaSubTypeZ16, kMediaSubTypeZ16, PIXEL_FORMAT_Y16},
      {false, kMediaSubTypeINVZ, kMediaSubTypeINVZ, PIXEL_FORMAT_Y16},
      {false, MFVideoFormat_D16, MFVideoFormat_D16, PIXEL_FORMAT_Y16},

      // Photo type
      {false, GUID_ContainerFormatJpeg, GUID_ContainerFormatJpeg,
       PIXEL_FORMAT_MJPEG},

      // For hardware path we always convert to NV12, since it's the only
      // supported by GMBs format.
      {true, MFVideoFormat_I420, MFVideoFormat_NV12, PIXEL_FORMAT_NV12},
      {true, MFVideoFormat_YUY2, MFVideoFormat_NV12, PIXEL_FORMAT_NV12},
      {true, MFVideoFormat_UYVY, MFVideoFormat_NV12, PIXEL_FORMAT_NV12},
      {true, MFVideoFormat_RGB24, MFVideoFormat_NV12, PIXEL_FORMAT_NV12},
      {true, MFVideoFormat_RGB32, MFVideoFormat_NV12, PIXEL_FORMAT_NV12},
      {true, MFVideoFormat_ARGB32, MFVideoFormat_NV12, PIXEL_FORMAT_NV12},
      {true, MFVideoFormat_MJPG, MFVideoFormat_NV12, PIXEL_FORMAT_NV12},
      {true, MFVideoFormat_NV12, MFVideoFormat_NV12, PIXEL_FORMAT_NV12},
      {true, MFVideoFormat_YV12, MFVideoFormat_NV12, PIXEL_FORMAT_NV12},

      // 16-bit formats can't be converted without loss of precision,
      // so if leave an option to get Y16 pixel format even though the
      // HW path won't be used for it.
      {true, kMediaSubTypeY16, kMediaSubTypeY16, PIXEL_FORMAT_Y16},
      {true, kMediaSubTypeZ16, kMediaSubTypeZ16, PIXEL_FORMAT_Y16},
      {true, kMediaSubTypeINVZ, kMediaSubTypeINVZ, PIXEL_FORMAT_Y16},
      {true, MFVideoFormat_D16, MFVideoFormat_D16, PIXEL_FORMAT_Y16},

      // Photo type
      {true, GUID_ContainerFormatJpeg, GUID_ContainerFormatJpeg,
       PIXEL_FORMAT_MJPEG}};

  for (const auto& kMediaFormatConfiguration : kMediaFormatConfigurationMap) {
    if (kMediaFormatConfiguration.is_hardware_format == use_hardware_format &&
        kMediaFormatConfiguration.mf_source_media_subtype ==
            mf_source_media_subtype) {
      *media_format_configuration = kMediaFormatConfiguration;
      return true;
    }
  }

  return false;
}

// Calculate sink subtype based on source subtype. |passthrough| is set when
// sink and source are the same and means that there should be no transcoding
// done by IMFCaptureEngine.
HRESULT GetMFSinkMediaSubtype(IMFMediaType* source_media_type,
                              bool use_hardware_format,
                              GUID* mf_sink_media_subtype,
                              bool* passthrough) {
  GUID source_subtype;
  HRESULT hr = source_media_type->GetGUID(MF_MT_SUBTYPE, &source_subtype);
  if (FAILED(hr))
    return hr;
  MediaFormatConfiguration media_format_configuration;
  if (!GetMediaFormatConfigurationFromMFSourceMediaSubtype(
          source_subtype, use_hardware_format, &media_format_configuration))
    return E_FAIL;
  *mf_sink_media_subtype = media_format_configuration.mf_sink_media_subtype;
  *passthrough =
      (media_format_configuration.mf_sink_media_subtype == source_subtype);
  return S_OK;
}

HRESULT ConvertToPhotoSinkMediaType(IMFMediaType* source_media_type,
                                    IMFMediaType* destination_media_type) {
  HRESULT hr =
      destination_media_type->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Image);
  if (FAILED(hr))
    return hr;

  bool passthrough = false;
  GUID mf_sink_media_subtype;
  hr = GetMFSinkMediaSubtype(source_media_type, /*use_hardware_format=*/false,
                             &mf_sink_media_subtype, &passthrough);
  if (FAILED(hr))
    return hr;

  hr = destination_media_type->SetGUID(MF_MT_SUBTYPE, mf_sink_media_subtype);
  if (FAILED(hr))
    return hr;

  return CopyAttribute(source_media_type, destination_media_type,
                       MF_MT_FRAME_SIZE);
}

HRESULT ConvertToVideoSinkMediaType(IMFMediaType* source_media_type,
                                    bool use_hardware_format,
                                    IMFMediaType* sink_media_type) {
  HRESULT hr = sink_media_type->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
  if (FAILED(hr))
    return hr;

  bool passthrough = false;
  GUID mf_sink_media_subtype;
  hr = GetMFSinkMediaSubtype(source_media_type, use_hardware_format,
                             &mf_sink_media_subtype, &passthrough);
  if (FAILED(hr))
    return hr;

  hr = sink_media_type->SetGUID(MF_MT_SUBTYPE, mf_sink_media_subtype);
  // Copying attribute values for passthrough mode is redundant, since the
  // format is kept unchanged, and causes AddStream error MF_E_INVALIDMEDIATYPE.
  if (FAILED(hr) || passthrough)
    return hr;

  hr = CopyAttribute(source_media_type, sink_media_type, MF_MT_FRAME_SIZE);
  if (FAILED(hr))
    return hr;

  hr = CopyAttribute(source_media_type, sink_media_type, MF_MT_FRAME_RATE);
  if (FAILED(hr))
    return hr;

  hr = CopyAttribute(source_media_type, sink_media_type,
                     MF_MT_PIXEL_ASPECT_RATIO);
  if (FAILED(hr))
    return hr;

  return CopyAttribute(source_media_type, sink_media_type,
                       MF_MT_INTERLACE_MODE);
}

const CapabilityWin& GetBestMatchedPhotoCapability(
    ComPtr<IMFMediaType> current_media_type,
    gfx::Size requested_size,
    const CapabilityList& capabilities) {
  gfx::Size current_size;
  GetFrameSizeFromMediaType(current_media_type.Get(), &current_size);

  int requested_height = requested_size.height() > 0 ? requested_size.height()
                                                     : current_size.height();
  int requested_width = requested_size.width() > 0 ? requested_size.width()
                                                   : current_size.width();

  const CapabilityWin* best_match = &(*capabilities.begin());
  for (const CapabilityWin& capability : capabilities) {
    int height = capability.supported_format.frame_size.height();
    int width = capability.supported_format.frame_size.width();
    int best_height = best_match->supported_format.frame_size.height();
    int best_width = best_match->supported_format.frame_size.width();

    if (std::abs(height - requested_height) <= std::abs(height - best_height) &&
        std::abs(width - requested_width) <= std::abs(width - best_width)) {
      best_match = &capability;
    }
  }
  return *best_match;
}

HRESULT CreateCaptureEngine(IMFCaptureEngine** engine) {
  ComPtr<IMFCaptureEngineClassFactory> capture_engine_class_factory;
  HRESULT hr = CoCreateInstance(CLSID_MFCaptureEngineClassFactory, nullptr,
                                CLSCTX_INPROC_SERVER,
                                IID_PPV_ARGS(&capture_engine_class_factory));
  if (FAILED(hr))
    return hr;

  return capture_engine_class_factory->CreateInstance(CLSID_MFCaptureEngine,
                                                      IID_PPV_ARGS(engine));
}

bool GetCameraControlSupport(ComPtr<IAMCameraControl> camera_control,
                             CameraControlProperty control_property) {
  long min, max, step, default_value, flags;
  HRESULT hr = camera_control->GetRange(control_property, &min, &max, &step,
                                        &default_value, &flags);
  return SUCCEEDED(hr) && min < max;
}

// Retrieves the control range and value, and
// optionally returns the associated supported and current mode.
template <typename ControlInterface, typename ControlProperty>
mojom::RangePtr RetrieveControlRangeAndCurrent(
    ComPtr<ControlInterface>& control_interface,
    ControlProperty control_property,
    std::vector<mojom::MeteringMode>* supported_modes = nullptr,
    mojom::MeteringMode* current_mode = nullptr,
    double (*value_converter)(long) = PlatformToCaptureValue,
    double (*step_converter)(long, double, double) = PlatformToCaptureStep) {
  return media::RetrieveControlRangeAndCurrent(
      [&control_interface, control_property](auto... args) {
        return control_interface->GetRange(control_property, args...);
      },
      [&control_interface, control_property](auto... args) {
        return control_interface->Get(control_property, args...);
      },
      supported_modes, current_mode, value_converter, step_converter);
}

HRESULT GetTextureFromMFBuffer(IMFMediaBuffer* mf_buffer,
                               ID3D11Texture2D** texture_out) {
  Microsoft::WRL::ComPtr<IMFDXGIBuffer> dxgi_buffer;
  HRESULT hr = mf_buffer->QueryInterface(IID_PPV_ARGS(&dxgi_buffer));
  DLOG_IF_FAILED_WITH_HRESULT("Failed to retrieve IMFDXGIBuffer", hr);

  Microsoft::WRL::ComPtr<ID3D11Texture2D> d3d_texture;
  if (SUCCEEDED(hr)) {
    hr = dxgi_buffer->GetResource(IID_PPV_ARGS(&d3d_texture));
    DLOG_IF_FAILED_WITH_HRESULT("Failed to retrieve ID3D11Texture2D", hr);
  }

  *texture_out = d3d_texture.Detach();
  if (SUCCEEDED(hr)) {
    CHECK(*texture_out);
  }
  return hr;
}

void GetTextureSizeAndFormat(ID3D11Texture2D* texture,
                             gfx::Size& size,
                             VideoPixelFormat& format) {
  D3D11_TEXTURE2D_DESC desc;
  texture->GetDesc(&desc);
  size.set_width(desc.Width);
  size.set_height(desc.Height);

  switch (desc.Format) {
    // Only support NV12
    case DXGI_FORMAT_NV12:
      format = PIXEL_FORMAT_NV12;
      break;
    default:
      DLOG(ERROR) << "Unsupported camera DXGI texture format: " << desc.Format;
      format = PIXEL_FORMAT_UNKNOWN;
      break;
  }
}

HRESULT CopyTextureToGpuMemoryBuffer(ID3D11Texture2D* texture,
                                     HANDLE dxgi_handle) {
  Microsoft::WRL::ComPtr<ID3D11Device> texture_device;
  texture->GetDevice(&texture_device);

  Microsoft::WRL::ComPtr<ID3D11Device1> device1;
  HRESULT hr = texture_device.As(&device1);
  if (FAILED(hr)) {
    DLOG(ERROR) << "Failed to get ID3D11Device1: "
                << logging::SystemErrorCodeToString(hr);
    return hr;
  }

  // Open shared resource from GpuMemoryBuffer on source texture D3D11 device
  Microsoft::WRL::ComPtr<ID3D11Texture2D> target_texture;
  hr = device1->OpenSharedResource1(dxgi_handle, IID_PPV_ARGS(&target_texture));
  if (FAILED(hr)) {
    DLOG(ERROR) << "Failed to open shared camera target texture: "
                << logging::SystemErrorCodeToString(hr);
    return hr;
  }

  Microsoft::WRL::ComPtr<ID3D11DeviceContext> device_context;
  texture_device->GetImmediateContext(&device_context);

  Microsoft::WRL::ComPtr<IDXGIKeyedMutex> keyed_mutex;
  hr = target_texture.As(&keyed_mutex);
  CHECK(SUCCEEDED(hr));

  keyed_mutex->AcquireSync(0, INFINITE);
  device_context->CopySubresourceRegion(target_texture.Get(), 0, 0, 0, 0,
                                        texture, 0, nullptr);
  keyed_mutex->ReleaseSync(0);

  // Need to flush context to ensure that other devices receive updated contents
  // of shared resource
  device_context->Flush();

  return S_OK;
}

}  // namespace

class MFVideoCallback final
    : public base::RefCountedThreadSafe<MFVideoCallback>,
      public IMFCaptureEngineOnSampleCallback,
      public IMFCaptureEngineOnEventCallback {
 public:
  MFVideoCallback(VideoCaptureDeviceMFWin* observer) : observer_(observer) {}

  IFACEMETHODIMP QueryInterface(REFIID riid, void** object) override {
    HRESULT hr = E_NOINTERFACE;
    if (riid == IID_IUnknown) {
      *object = this;
      hr = S_OK;
    } else if (riid == IID_IMFCaptureEngineOnSampleCallback) {
      *object = static_cast<IMFCaptureEngineOnSampleCallback*>(this);
      hr = S_OK;
    } else if (riid == IID_IMFCaptureEngineOnEventCallback) {
      *object = static_cast<IMFCaptureEngineOnEventCallback*>(this);
      hr = S_OK;
    }
    if (SUCCEEDED(hr))
      AddRef();

    return hr;
  }

  IFACEMETHODIMP_(ULONG) AddRef() override {
    base::RefCountedThreadSafe<MFVideoCallback>::AddRef();
    return 1U;
  }

  IFACEMETHODIMP_(ULONG) Release() override {
    base::RefCountedThreadSafe<MFVideoCallback>::Release();
    return 1U;
  }

  IFACEMETHODIMP OnEvent(IMFMediaEvent* media_event) override {
    base::AutoLock lock(lock_);
    if (!observer_) {
      return S_OK;
    }
    observer_->OnEvent(media_event);
    return S_OK;
  }

  IFACEMETHODIMP OnSample(IMFSample* sample) override {
    base::AutoLock lock(lock_);
    if (!observer_) {
      return S_OK;
    }
    if (!sample) {
      observer_->OnFrameDropped(
          VideoCaptureFrameDropReason::kWinMediaFoundationReceivedSampleIsNull);
      return S_OK;
    }

    base::TimeTicks reference_time(base::TimeTicks::Now());
    LONGLONG raw_time_stamp = 0;
    sample->GetSampleTime(&raw_time_stamp);
    base::TimeDelta timestamp = base::Microseconds(raw_time_stamp / 10);

    DWORD count = 0;
    sample->GetBufferCount(&count);

    for (DWORD i = 0; i < count; ++i) {
      ComPtr<IMFMediaBuffer> buffer;
      sample->GetBufferByIndex(i, &buffer);
      if (buffer) {
        observer_->OnIncomingCapturedData(buffer.Get(), reference_time,
                                          timestamp);
      } else {
        observer_->OnFrameDropped(
            VideoCaptureFrameDropReason::
                kWinMediaFoundationGetBufferByIndexReturnedNull);
      }
    }
    return S_OK;
  }

  void Shutdown() {
    base::AutoLock lock(lock_);
    observer_ = nullptr;
  }

 private:
  friend class base::RefCountedThreadSafe<MFVideoCallback>;
  ~MFVideoCallback() {}

  // Protects access to |observer_|.
  base::Lock lock_;
  VideoCaptureDeviceMFWin* observer_ GUARDED_BY(lock_);
};

// static
bool VideoCaptureDeviceMFWin::GetPixelFormatFromMFSourceMediaSubtype(
    const GUID& mf_source_media_subtype,
    bool use_hardware_format,
    VideoPixelFormat* pixel_format) {
  MediaFormatConfiguration media_format_configuration;
  if (!GetMediaFormatConfigurationFromMFSourceMediaSubtype(
          mf_source_media_subtype, use_hardware_format,
          &media_format_configuration))
    return false;

  *pixel_format = media_format_configuration.pixel_format;
  return true;
}

// Check if the video capture device supports pan, tilt and zoom controls.
// static
VideoCaptureControlSupport VideoCaptureDeviceMFWin::GetControlSupport(
    ComPtr<IMFMediaSource> source) {
  VideoCaptureControlSupport control_support;

  ComPtr<IAMCameraControl> camera_control;
  HRESULT hr = source.As(&camera_control);
  DLOG_IF_FAILED_WITH_HRESULT("Failed to retrieve IAMCameraControl", hr);
  ComPtr<IAMVideoProcAmp> video_control;
  hr = source.As(&video_control);
  DLOG_IF_FAILED_WITH_HRESULT("Failed to retrieve IAMVideoProcAmp", hr);

  // On Windows platform, some Image Capture video constraints and settings are
  // get or set using IAMCameraControl interface while the rest are get or set
  // using IAMVideoProcAmp interface and most device drivers define both of
  // them. So for simplicity GetPhotoState and SetPhotoState support Image
  // Capture API constraints and settings only if both interfaces are available.
  // Therefore, if either of these interface is missing, this backend does not
  // really support pan, tilt nor zoom.
  if (camera_control && video_control) {
    control_support.pan =
        GetCameraControlSupport(camera_control, CameraControl_Pan);
    control_support.tilt =
        GetCameraControlSupport(camera_control, CameraControl_Tilt);
    control_support.zoom =
        GetCameraControlSupport(camera_control, CameraControl_Zoom);
  }

  return control_support;
}

HRESULT VideoCaptureDeviceMFWin::ExecuteHresultCallbackWithRetries(
    base::RepeatingCallback<HRESULT()> callback,
    MediaFoundationFunctionRequiringRetry which_function) {
  // Retry callback execution on MF_E_INVALIDREQUEST.
  // MF_E_INVALIDREQUEST is not documented in MediaFoundation documentation.
  // It could mean that MediaFoundation or the underlying device can be in a
  // state that reject these calls. Since MediaFoundation gives no intel about
  // that state beginning and ending (i.e. via some kind of event), we retry the
  // call until it succeed.
  HRESULT hr;
  int retry_count = 0;
  do {
    hr = callback.Run();
    if (FAILED(hr))
      base::PlatformThread::Sleep(base::Milliseconds(retry_delay_in_ms_));

    // Give up after some amount of time
  } while (hr == MF_E_INVALIDREQUEST && retry_count++ < max_retry_count_);
  LogNumberOfRetriesNeededToWorkAroundMFInvalidRequest(which_function,
                                                       retry_count);

  return hr;
}

HRESULT VideoCaptureDeviceMFWin::GetDeviceStreamCount(IMFCaptureSource* source,
                                                      DWORD* count) {
  // Sometimes, GetDeviceStreamCount returns an
  // undocumented MF_E_INVALIDREQUEST. Retrying solves the issue.
  return ExecuteHresultCallbackWithRetries(
      base::BindRepeating(
          [](IMFCaptureSource* source, DWORD* count) {
            return source->GetDeviceStreamCount(count);
          },
          base::Unretained(source), count),
      MediaFoundationFunctionRequiringRetry::kGetDeviceStreamCount);
}

HRESULT VideoCaptureDeviceMFWin::GetDeviceStreamCategory(
    IMFCaptureSource* source,
    DWORD stream_index,
    MF_CAPTURE_ENGINE_STREAM_CATEGORY* stream_category) {
  // We believe that GetDeviceStreamCategory could be affected by the same
  // behaviour of GetDeviceStreamCount and GetAvailableDeviceMediaType
  return ExecuteHresultCallbackWithRetries(
      base::BindRepeating(
          [](IMFCaptureSource* source, DWORD stream_index,
             MF_CAPTURE_ENGINE_STREAM_CATEGORY* stream_category) {
            return source->GetDeviceStreamCategory(stream_index,
                                                   stream_category);
          },
          base::Unretained(source), stream_index, stream_category),
      MediaFoundationFunctionRequiringRetry::kGetDeviceStreamCategory);
}

HRESULT VideoCaptureDeviceMFWin::GetAvailableDeviceMediaType(
    IMFCaptureSource* source,
    DWORD stream_index,
    DWORD media_type_index,
    IMFMediaType** type) {
  // Rarely, for some unknown reason, GetAvailableDeviceMediaType returns an
  // undocumented MF_E_INVALIDREQUEST. Retrying solves the issue.
  return ExecuteHresultCallbackWithRetries(
      base::BindRepeating(
          [](IMFCaptureSource* source, DWORD stream_index,
             DWORD media_type_index, IMFMediaType** type) {
            return source->GetAvailableDeviceMediaType(stream_index,
                                                       media_type_index, type);
          },
          base::Unretained(source), stream_index, media_type_index, type),
      MediaFoundationFunctionRequiringRetry::kGetAvailableDeviceMediaType);
}

HRESULT VideoCaptureDeviceMFWin::FillCapabilities(
    IMFCaptureSource* source,
    bool photo,
    CapabilityList* capabilities) {
  DWORD stream_count = 0;
  HRESULT hr = GetDeviceStreamCount(source, &stream_count);
  if (FAILED(hr))
    return hr;

  for (DWORD stream_index = 0; stream_index < stream_count; stream_index++) {
    MF_CAPTURE_ENGINE_STREAM_CATEGORY stream_category;
    hr = GetDeviceStreamCategory(source, stream_index, &stream_category);
    if (FAILED(hr))
      return hr;

    if ((photo && stream_category !=
                      MF_CAPTURE_ENGINE_STREAM_CATEGORY_PHOTO_INDEPENDENT) ||
        (!photo &&
         stream_category != MF_CAPTURE_ENGINE_STREAM_CATEGORY_VIDEO_PREVIEW &&
         stream_category != MF_CAPTURE_ENGINE_STREAM_CATEGORY_VIDEO_CAPTURE)) {
      continue;
    }

    DWORD media_type_index = 0;
    ComPtr<IMFMediaType> type;
    while (SUCCEEDED(hr = GetAvailableDeviceMediaType(
                         source, stream_index, media_type_index, &type))) {
      VideoCaptureFormat format;
      VideoPixelFormat source_pixel_format;
      if (GetFormatFromSourceMediaType(
              type.Get(), photo,
              /*use_hardware_format=*/!photo &&
                  static_cast<bool>(dxgi_device_manager_),
              &format, &source_pixel_format))
        capabilities->emplace_back(media_type_index, format, stream_index,
                                   source_pixel_format);
      type.Reset();
      ++media_type_index;
    }
    if (hr == MF_E_NO_MORE_TYPES) {
      hr = S_OK;
    }
    if (FAILED(hr)) {
      return hr;
    }
  }

  return hr;
}

VideoCaptureDeviceMFWin::VideoCaptureDeviceMFWin(
    const VideoCaptureDeviceDescriptor& device_descriptor,
    ComPtr<IMFMediaSource> source,
    scoped_refptr<DXGIDeviceManager> dxgi_device_manager)
    : VideoCaptureDeviceMFWin(device_descriptor,
                              source,
                              std::move(dxgi_device_manager),
                              nullptr) {}

VideoCaptureDeviceMFWin::VideoCaptureDeviceMFWin(
    const VideoCaptureDeviceDescriptor& device_descriptor,
    ComPtr<IMFMediaSource> source,
    scoped_refptr<DXGIDeviceManager> dxgi_device_manager,
    ComPtr<IMFCaptureEngine> engine)
    : facing_mode_(device_descriptor.facing),
      create_mf_photo_callback_(base::BindRepeating(&CreateMFPhotoCallback)),
      is_initialized_(false),
      max_retry_count_(200),
      retry_delay_in_ms_(50),
      source_(source),
      engine_(engine),
      is_started_(false),
      has_sent_on_started_to_client_(false),
      exposure_mode_manual_(false),
      focus_mode_manual_(false),
      white_balance_mode_manual_(false),
      capture_initialize_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
                          base::WaitableEvent::InitialState::NOT_SIGNALED),
      // We never want to reset |capture_error_|.
      capture_error_(base::WaitableEvent::ResetPolicy::MANUAL,
                     base::WaitableEvent::InitialState::NOT_SIGNALED),
      dxgi_device_manager_(std::move(dxgi_device_manager)) {
  DETACH_FROM_SEQUENCE(sequence_checker_);
}

VideoCaptureDeviceMFWin::~VideoCaptureDeviceMFWin() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  if (!video_stream_take_photo_callbacks_.empty()) {
    for (size_t k = 0; k < video_stream_take_photo_callbacks_.size(); k++) {
      LogWindowsImageCaptureOutcome(
          VideoCaptureWinBackend::kMediaFoundation,
          ImageCaptureOutcome::kFailedUsingVideoStream,
          selected_video_capability_
              ? IsHighResolution(selected_video_capability_->supported_format)
              : false);
    }
  }
  if (video_callback_) {
    video_callback_->Shutdown();
  }
}

bool VideoCaptureDeviceMFWin::Init() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(!is_initialized_);
  HRESULT hr;

  hr = source_.As(&camera_control_);
  DLOG_IF_FAILED_WITH_HRESULT("Failed to retrieve IAMCameraControl", hr);

  hr = source_.As(&video_control_);
  DLOG_IF_FAILED_WITH_HRESULT("Failed to retrieve IAMVideoProcAmp", hr);

  if (!engine_) {
    hr = CreateCaptureEngine(&engine_);
    if (FAILED(hr)) {
      LogError(FROM_HERE, hr);
      return false;
    }
  }

  ComPtr<IMFAttributes> attributes;
  hr = MFCreateAttributes(&attributes, 1);
  if (FAILED(hr)) {
    LogError(FROM_HERE, hr);
    return false;
  }

  hr = attributes->SetUINT32(MF_CAPTURE_ENGINE_USE_VIDEO_DEVICE_ONLY, TRUE);
  if (FAILED(hr)) {
    LogError(FROM_HERE, hr);
    return false;
  }

  if (dxgi_device_manager_) {
    dxgi_device_manager_->RegisterInCaptureEngineAttributes(attributes.Get());
  }

  video_callback_ = new MFVideoCallback(this);
  hr = engine_->Initialize(video_callback_.get(), attributes.Get(), nullptr,
                           source_.Get());
  if (FAILED(hr)) {
    LogError(FROM_HERE, hr);
    return false;
  }

  hr = WaitOnCaptureEvent(MF_CAPTURE_ENGINE_INITIALIZED);
  if (FAILED(hr)) {
    LogError(FROM_HERE, hr);
    return false;
  }

  is_initialized_ = true;
  return true;
}

void VideoCaptureDeviceMFWin::AllocateAndStart(
    const VideoCaptureParams& params,
    std::unique_ptr<VideoCaptureDevice::Client> client) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  base::AutoLock lock(lock_);

  client_ = std::move(client);
  DCHECK_EQ(false, is_started_);

  if (!engine_) {
    OnError(VideoCaptureError::kWinMediaFoundationEngineIsNull, FROM_HERE,
            E_FAIL);
    return;
  }

  ComPtr<IMFCaptureSource> source;
  HRESULT hr = engine_->GetSource(&source);
  if (FAILED(hr)) {
    OnError(VideoCaptureError::kWinMediaFoundationEngineGetSourceFailed,
            FROM_HERE, hr);
    return;
  }

  hr = FillCapabilities(source.Get(), true, &photo_capabilities_);
  if (FAILED(hr)) {
    OnError(VideoCaptureError::kWinMediaFoundationFillPhotoCapabilitiesFailed,
            FROM_HERE, hr);
    return;
  }

  if (!photo_capabilities_.empty()) {
    selected_photo_capability_ =
        std::make_unique<CapabilityWin>(photo_capabilities_.front());
  }

  CapabilityList video_capabilities;
  hr = FillCapabilities(source.Get(), false, &video_capabilities);
  if (FAILED(hr)) {
    OnError(VideoCaptureError::kWinMediaFoundationFillVideoCapabilitiesFailed,
            FROM_HERE, hr);
    return;
  }

  if (video_capabilities.empty()) {
    OnError(VideoCaptureError::kWinMediaFoundationNoVideoCapabilityFound,
            FROM_HERE, "No video capability found");
    return;
  }

  const CapabilityWin best_match_video_capability =
      GetBestMatchedCapability(params.requested_format, video_capabilities);
  ComPtr<IMFMediaType> source_video_media_type;
  hr = GetAvailableDeviceMediaType(
      source.Get(), best_match_video_capability.stream_index,
      best_match_video_capability.media_type_index, &source_video_media_type);
  if (FAILED(hr)) {
    OnError(
        VideoCaptureError::kWinMediaFoundationGetAvailableDeviceMediaTypeFailed,
        FROM_HERE, hr);
    return;
  }

  hr = source->SetCurrentDeviceMediaType(
      best_match_video_capability.stream_index, source_video_media_type.Get());
  if (FAILED(hr)) {
    OnError(
        VideoCaptureError::kWinMediaFoundationSetCurrentDeviceMediaTypeFailed,
        FROM_HERE, hr);
    return;
  }

  ComPtr<IMFCaptureSink> sink;
  hr = engine_->GetSink(MF_CAPTURE_ENGINE_SINK_TYPE_PREVIEW, &sink);
  if (FAILED(hr)) {
    OnError(VideoCaptureError::kWinMediaFoundationEngineGetSinkFailed,
            FROM_HERE, hr);
    return;
  }

  ComPtr<IMFCapturePreviewSink> preview_sink;
  hr = sink->QueryInterface(IID_PPV_ARGS(&preview_sink));
  if (FAILED(hr)) {
    OnError(VideoCaptureError::
                kWinMediaFoundationSinkQueryCapturePreviewInterfaceFailed,
            FROM_HERE, hr);
    return;
  }

  hr = preview_sink->RemoveAllStreams();
  if (FAILED(hr)) {
    OnError(VideoCaptureError::kWinMediaFoundationSinkRemoveAllStreamsFailed,
            FROM_HERE, hr);
    return;
  }

  ComPtr<IMFMediaType> sink_video_media_type;
  hr = MFCreateMediaType(&sink_video_media_type);
  if (FAILED(hr)) {
    OnError(
        VideoCaptureError::kWinMediaFoundationCreateSinkVideoMediaTypeFailed,
        FROM_HERE, hr);
    return;
  }

  hr = ConvertToVideoSinkMediaType(
      source_video_media_type.Get(),
      /*use_hardware_format=*/static_cast<bool>(dxgi_device_manager_),
      sink_video_media_type.Get());
  if (FAILED(hr)) {
    OnError(
        VideoCaptureError::kWinMediaFoundationConvertToVideoSinkMediaTypeFailed,
        FROM_HERE, hr);
    return;
  }

  DWORD dw_sink_stream_index = 0;
  hr = preview_sink->AddStream(best_match_video_capability.stream_index,
                               sink_video_media_type.Get(), nullptr,
                               &dw_sink_stream_index);
  if (FAILED(hr)) {
    OnError(VideoCaptureError::kWinMediaFoundationSinkAddStreamFailed,
            FROM_HERE, hr);
    return;
  }

  hr = preview_sink->SetSampleCallback(dw_sink_stream_index,
                                       video_callback_.get());
  if (FAILED(hr)) {
    OnError(VideoCaptureError::kWinMediaFoundationSinkSetSampleCallbackFailed,
            FROM_HERE, hr);
    return;
  }

  // Note, that it is not sufficient to wait for
  // MF_CAPTURE_ENGINE_PREVIEW_STARTED as an indicator that starting capture has
  // succeeded. If the capture device is already in use by a different
  // application, MediaFoundation will still emit
  // MF_CAPTURE_ENGINE_PREVIEW_STARTED, and only after that raise an error
  // event. For the lack of any other events indicating success, we have to wait
  // for the first video frame to arrive before sending our |OnStarted| event to
  // |client_|.
  has_sent_on_started_to_client_ = false;
  hr = engine_->StartPreview();
  if (FAILED(hr)) {
    OnError(VideoCaptureError::kWinMediaFoundationEngineStartPreviewFailed,
            FROM_HERE, hr);
    return;
  }

  selected_video_capability_ =
      std::make_unique<CapabilityWin>(best_match_video_capability);

  is_started_ = true;

  base::UmaHistogramEnumeration(
      "Media.VideoCapture.Win.Device.InternalPixelFormat",
      best_match_video_capability.source_pixel_format,
      media::VideoPixelFormat::PIXEL_FORMAT_MAX);
  base::UmaHistogramEnumeration(
      "Media.VideoCapture.Win.Device.CapturePixelFormat",
      best_match_video_capability.supported_format.pixel_format,
      media::VideoPixelFormat::PIXEL_FORMAT_MAX);
  base::UmaHistogramEnumeration(
      "Media.VideoCapture.Win.Device.RequestedPixelFormat",
      params.requested_format.pixel_format,
      media::VideoPixelFormat::PIXEL_FORMAT_MAX);
}

void VideoCaptureDeviceMFWin::StopAndDeAllocate() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  base::AutoLock lock(lock_);

  if (is_started_ && engine_)
    engine_->StopPreview();
  is_started_ = false;

  client_.reset();
}

void VideoCaptureDeviceMFWin::TakePhoto(TakePhotoCallback callback) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  base::AutoLock lock(lock_);

  if (!is_started_)
    return;

  if (!selected_photo_capability_) {
    video_stream_take_photo_callbacks_.push(std::move(callback));
    return;
  }

  ComPtr<IMFCaptureSource> source;
  HRESULT hr = engine_->GetSource(&source);
  if (FAILED(hr)) {
    LogError(FROM_HERE, hr);
    return;
  }

  ComPtr<IMFMediaType> source_media_type;
  hr = GetAvailableDeviceMediaType(
      source.Get(), selected_photo_capability_->stream_index,
      selected_photo_capability_->media_type_index, &source_media_type);
  if (FAILED(hr)) {
    LogError(FROM_HERE, hr);
    return;
  }

  hr = source->SetCurrentDeviceMediaType(
      selected_photo_capability_->stream_index, source_media_type.Get());
  if (FAILED(hr)) {
    LogError(FROM_HERE, hr);
    return;
  }

  ComPtr<IMFMediaType> sink_media_type;
  hr = MFCreateMediaType(&sink_media_type);
  if (FAILED(hr)) {
    LogError(FROM_HERE, hr);
    return;
  }

  hr = ConvertToPhotoSinkMediaType(source_media_type.Get(),
                                   sink_media_type.Get());
  if (FAILED(hr)) {
    LogError(FROM_HERE, hr);
    return;
  }

  VideoCaptureFormat format;
  VideoPixelFormat source_format;
  hr = GetFormatFromSourceMediaType(sink_media_type.Get(), true,
                                    /*use_hardware_format=*/false, &format,
                                    &source_format)
           ? S_OK
           : E_FAIL;
  if (FAILED(hr)) {
    LogError(FROM_HERE, hr);
    return;
  }

  ComPtr<IMFCaptureSink> sink;
  hr = engine_->GetSink(MF_CAPTURE_ENGINE_SINK_TYPE_PHOTO, &sink);
  if (FAILED(hr)) {
    LogError(FROM_HERE, hr);
    return;
  }

  ComPtr<IMFCapturePhotoSink> photo_sink;
  hr = sink->QueryInterface(IID_PPV_ARGS(&photo_sink));
  if (FAILED(hr)) {
    LogError(FROM_HERE, hr);
    return;
  }

  hr = photo_sink->RemoveAllStreams();
  if (FAILED(hr)) {
    LogError(FROM_HERE, hr);
    return;
  }

  DWORD dw_sink_stream_index = 0;
  hr = photo_sink->AddStream(selected_photo_capability_->stream_index,
                             sink_media_type.Get(), nullptr,
                             &dw_sink_stream_index);
  if (FAILED(hr)) {
    LogError(FROM_HERE, hr);
    return;
  }

  scoped_refptr<IMFCaptureEngineOnSampleCallback> photo_callback =
      create_mf_photo_callback_.Run(std::move(callback), format);
  hr = photo_sink->SetSampleCallback(photo_callback.get());
  if (FAILED(hr)) {
    LogError(FROM_HERE, hr);
    return;
  }

  hr = engine_->TakePhoto();
  if (FAILED(hr))
    LogError(FROM_HERE, hr);
}

void VideoCaptureDeviceMFWin::GetPhotoState(GetPhotoStateCallback callback) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  if (!is_started_)
    return;

  ComPtr<IMFCaptureSource> source;
  HRESULT hr = engine_->GetSource(&source);
  if (FAILED(hr)) {
    LogError(FROM_HERE, hr);
    return;
  }

  ComPtr<IMFMediaType> current_media_type;
  hr = source->GetCurrentDeviceMediaType(
      selected_photo_capability_ ? selected_photo_capability_->stream_index
                                 : selected_video_capability_->stream_index,
      &current_media_type);
  if (FAILED(hr)) {
    LogError(FROM_HERE, hr);
    return;
  }

  auto photo_capabilities = mojo::CreateEmptyPhotoState();
  gfx::Size current_size;
  GetFrameSizeFromMediaType(current_media_type.Get(), &current_size);

  gfx::Size min_size = gfx::Size(current_size.width(), current_size.height());
  gfx::Size max_size = gfx::Size(current_size.width(), current_size.height());
  for (const CapabilityWin& capability : photo_capabilities_) {
    min_size.SetToMin(capability.supported_format.frame_size);
    max_size.SetToMax(capability.supported_format.frame_size);
  }

  photo_capabilities->height = mojom::Range::New(
      max_size.height(), min_size.height(), current_size.height(), 1);
  photo_capabilities->width = mojom::Range::New(
      max_size.width(), min_size.width(), current_size.width(), 1);

  if (camera_control_ && video_control_) {
    photo_capabilities->color_temperature = RetrieveControlRangeAndCurrent(
        video_control_, VideoProcAmp_WhiteBalance,
        &photo_capabilities->supported_white_balance_modes,
        &photo_capabilities->current_white_balance_mode);

    photo_capabilities->exposure_time = RetrieveControlRangeAndCurrent(
        camera_control_, CameraControl_Exposure,
        &photo_capabilities->supported_exposure_modes,
        &photo_capabilities->current_exposure_mode,
        PlatformExposureTimeToCaptureValue, PlatformExposureTimeToCaptureStep);

    photo_capabilities->focus_distance = RetrieveControlRangeAndCurrent(
        camera_control_, CameraControl_Focus,
        &photo_capabilities->supported_focus_modes,
        &photo_capabilities->current_focus_mode);

    photo_capabilities->brightness =
        RetrieveControlRangeAndCurrent(video_control_, VideoProcAmp_Brightness);
    photo_capabilities->contrast =
        RetrieveControlRangeAndCurrent(video_control_, VideoProcAmp_Contrast);
    photo_capabilities->exposure_compensation =
        RetrieveControlRangeAndCurrent(video_control_, VideoProcAmp_Gain);
    // There is no ISO control property in IAMCameraControl or IAMVideoProcAmp
    // interfaces nor any other control property with direct mapping to ISO.
    photo_capabilities->iso = mojom::Range::New();
    photo_capabilities->red_eye_reduction = mojom::RedEyeReduction::NEVER;
    photo_capabilities->saturation =
        RetrieveControlRangeAndCurrent(video_control_, VideoProcAmp_Saturation);
    photo_capabilities->sharpness =
        RetrieveControlRangeAndCurrent(video_control_, VideoProcAmp_Sharpness);
    photo_capabilities->torch = false;
    photo_capabilities->pan = RetrieveControlRangeAndCurrent(
        camera_control_, CameraControl_Pan, nullptr, nullptr,
        PlatformAngleToCaptureValue, PlatformAngleToCaptureStep);
    photo_capabilities->tilt = RetrieveControlRangeAndCurrent(
        camera_control_, CameraControl_Tilt, nullptr, nullptr,
        PlatformAngleToCaptureValue, PlatformAngleToCaptureStep);
    photo_capabilities->zoom =
        RetrieveControlRangeAndCurrent(camera_control_, CameraControl_Zoom);
  }

  std::move(callback).Run(std::move(photo_capabilities));
}

void VideoCaptureDeviceMFWin::SetPhotoOptions(
    mojom::PhotoSettingsPtr settings,
    SetPhotoOptionsCallback callback) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  if (!is_started_)
    return;

  HRESULT hr = S_OK;
  ComPtr<IMFCaptureSource> source;
  hr = engine_->GetSource(&source);

  if (FAILED(hr)) {
    LogError(FROM_HERE, hr);
    return;
  }

  if (!photo_capabilities_.empty() &&
      (settings->has_height || settings->has_width)) {
    if (FAILED(hr)) {
      LogError(FROM_HERE, hr);
      return;
    }

    ComPtr<IMFMediaType> current_source_media_type;
    hr = source->GetCurrentDeviceMediaType(
        selected_photo_capability_->stream_index, &current_source_media_type);

    if (FAILED(hr)) {
      LogError(FROM_HERE, hr);
      return;
    }

    gfx::Size requested_size = gfx::Size();
    if (settings->has_height)
      requested_size.set_height(settings->height);

    if (settings->has_width)
      requested_size.set_width(settings->width);

    const CapabilityWin best_match = GetBestMatchedPhotoCapability(
        current_source_media_type, requested_size, photo_capabilities_);
    selected_photo_capability_ = std::make_unique<CapabilityWin>(best_match);
  }

  if (camera_control_ && video_control_) {
    if (settings->has_white_balance_mode) {
      if (settings->white_balance_mode == mojom::MeteringMode::CONTINUOUS) {
        hr = video_control_->Set(VideoProcAmp_WhiteBalance, 0L,
                                 VideoProcAmp_Flags_Auto);
        DLOG_IF_FAILED_WITH_HRESULT("Auto white balance config failed", hr);
        if (FAILED(hr))
          return;
        white_balance_mode_manual_ = false;
      } else {
        white_balance_mode_manual_ = true;
      }
    }
    if (white_balance_mode_manual_ && settings->has_color_temperature) {
      hr = video_control_->Set(VideoProcAmp_WhiteBalance,
                               settings->color_temperature,
                               VideoProcAmp_Flags_Manual);
      DLOG_IF_FAILED_WITH_HRESULT("Color temperature config failed", hr);
      if (FAILED(hr))
        return;
    }

    if (settings->has_exposure_mode) {
      if (settings->exposure_mode == mojom::MeteringMode::CONTINUOUS) {
        hr = camera_control_->Set(CameraControl_Exposure, 0L,
                                  CameraControl_Flags_Auto);
        DLOG_IF_FAILED_WITH_HRESULT("Auto exposure config failed", hr);
        if (FAILED(hr))
          return;
        exposure_mode_manual_ = false;
      } else {
        exposure_mode_manual_ = true;
      }
    }
    if (exposure_mode_manual_ && settings->has_exposure_time) {
      hr = camera_control_->Set(
          CameraControl_Exposure,
          CaptureExposureTimeToPlatformValue(settings->exposure_time),
          CameraControl_Flags_Manual);
      DLOG_IF_FAILED_WITH_HRESULT("Exposure Time config failed", hr);
      if (FAILED(hr))
        return;
    }

    if (settings->has_focus_mode) {
      if (settings->focus_mode == mojom::MeteringMode::CONTINUOUS) {
        hr = camera_control_->Set(CameraControl_Focus, 0L,
                                  CameraControl_Flags_Auto);
        DLOG_IF_FAILED_WITH_HRESULT("Auto focus config failed", hr);
        if (FAILED(hr))
          return;
        focus_mode_manual_ = false;
      } else {
        focus_mode_manual_ = true;
      }
    }
    if (focus_mode_manual_ && settings->has_focus_distance) {
      hr = camera_control_->Set(CameraControl_Focus, settings->focus_distance,
                                CameraControl_Flags_Manual);
      DLOG_IF_FAILED_WITH_HRESULT("Focus Distance config failed", hr);
      if (FAILED(hr))
        return;
    }

    if (settings->has_brightness) {
      hr = video_control_->Set(VideoProcAmp_Brightness, settings->brightness,
                               VideoProcAmp_Flags_Manual);
      DLOG_IF_FAILED_WITH_HRESULT("Brightness config failed", hr);
      if (FAILED(hr))
        return;
    }
    if (settings->has_contrast) {
      hr = video_control_->Set(VideoProcAmp_Contrast, settings->contrast,
                               VideoProcAmp_Flags_Manual);
      DLOG_IF_FAILED_WITH_HRESULT("Contrast config failed", hr);
      if (FAILED(hr))
        return;
    }
    if (settings->has_exposure_compensation) {
      hr = video_control_->Set(VideoProcAmp_Gain,
                               settings->exposure_compensation,
                               VideoProcAmp_Flags_Manual);
      DLOG_IF_FAILED_WITH_HRESULT("Exposure Compensation config failed", hr);
      if (FAILED(hr))
        return;
    }
    if (settings->has_saturation) {
      hr = video_control_->Set(VideoProcAmp_Saturation, settings->saturation,
                               VideoProcAmp_Flags_Manual);
      DLOG_IF_FAILED_WITH_HRESULT("Saturation config failed", hr);
      if (FAILED(hr))
        return;
    }
    if (settings->has_sharpness) {
      hr = video_control_->Set(VideoProcAmp_Sharpness, settings->sharpness,
                               VideoProcAmp_Flags_Manual);
      DLOG_IF_FAILED_WITH_HRESULT("Sharpness config failed", hr);
      if (FAILED(hr))
        return;
    }
    if (settings->has_pan) {
      hr = camera_control_->Set(CameraControl_Pan,
                                CaptureAngleToPlatformValue(settings->pan),
                                CameraControl_Flags_Manual);
      DLOG_IF_FAILED_WITH_HRESULT("Pan config failed", hr);
      if (FAILED(hr))
        return;
    }
    if (settings->has_tilt) {
      hr = camera_control_->Set(CameraControl_Tilt,
                                CaptureAngleToPlatformValue(settings->tilt),
                                CameraControl_Flags_Manual);
      DLOG_IF_FAILED_WITH_HRESULT("Tilt config failed", hr);
      if (FAILED(hr))
        return;
    }
    if (settings->has_zoom) {
      hr = camera_control_->Set(CameraControl_Zoom, settings->zoom,
                                CameraControl_Flags_Manual);
      DLOG_IF_FAILED_WITH_HRESULT("Zoom config failed", hr);
      if (FAILED(hr))
        return;
    }
  }

  std::move(callback).Run(true);
}

void VideoCaptureDeviceMFWin::OnUtilizationReport(
    int frame_feedback_id,
    media::VideoCaptureFeedback feedback) {
  base::AutoLock lock(lock_);
  last_feedback_ = feedback;
}

void VideoCaptureDeviceMFWin::OnIncomingCapturedData(
    IMFMediaBuffer* buffer,
    base::TimeTicks reference_time,
    base::TimeDelta timestamp) {
  VideoCaptureFrameDropReason frame_drop_reason =
      VideoCaptureFrameDropReason::kNone;
  OnIncomingCapturedDataInternal(buffer, reference_time, timestamp,
                                 frame_drop_reason);
  if (frame_drop_reason != VideoCaptureFrameDropReason::kNone) {
    OnFrameDropped(frame_drop_reason);
  }
}

HRESULT VideoCaptureDeviceMFWin::DeliverTextureToClient(
    ID3D11Texture2D* texture,
    base::TimeTicks reference_time,
    base::TimeDelta timestamp) {
  // Check for device loss
  Microsoft::WRL::ComPtr<ID3D11Device> texture_device;
  texture->GetDevice(&texture_device);

  HRESULT hr = texture_device->GetDeviceRemovedReason();

  if (FAILED(hr)) {
    DLOG(ERROR) << "Camera texture device lost.";
    DCHECK(dxgi_device_manager_->ResetDevice());
    return hr;
  }

  gfx::Size texture_size;
  VideoPixelFormat pixel_format;
  GetTextureSizeAndFormat(texture, texture_size, pixel_format);

  if (pixel_format != PIXEL_FORMAT_NV12) {
    return MF_E_UNSUPPORTED_FORMAT;
  }

  VideoCaptureDevice::Client::Buffer capture_buffer;
  constexpr int kDummyFrameFeedbackId = 0;
  auto result = client_->ReserveOutputBuffer(
      texture_size, pixel_format, kDummyFrameFeedbackId, &capture_buffer);
  if (result != VideoCaptureDevice::Client::ReserveResult::kSucceeded) {
    DLOG(ERROR) << "Failed to reserve output capture buffer: " << (int)result;
    return MF_E_UNEXPECTED;
  }

  auto gmb_handle = capture_buffer.handle_provider->GetGpuMemoryBufferHandle();
  hr = CopyTextureToGpuMemoryBuffer(texture, gmb_handle.dxgi_handle.Get());

  capture_buffer.is_premapped = false;
  if (last_feedback_.require_mapped_frame) {
    // Only a flag on the Buffer is set here; the region itself isn't passed
    // anywhere because it was passed when the buffer was created.
    // Now the flag would tell the consumer that the region contains actual
    // frame data.
    if (capture_buffer.handle_provider->DuplicateAsUnsafeRegion().IsValid()) {
      capture_buffer.is_premapped = true;
    }
  }

  if (FAILED(hr)) {
    DLOG(ERROR) << "Failed to copy camera device texture to output texture: "
                << logging::SystemErrorCodeToString(hr);
    return hr;
  }

  VideoRotation frame_rotation = VIDEO_ROTATION_0;
  DCHECK(camera_rotation_.has_value());
  switch (camera_rotation_.value()) {
    case 0:
      frame_rotation = VIDEO_ROTATION_0;
      break;
    case 90:
      frame_rotation = VIDEO_ROTATION_90;
      break;
    case 180:
      frame_rotation = VIDEO_ROTATION_180;
      break;
    case 270:
      frame_rotation = VIDEO_ROTATION_270;
      break;
    default:
      break;
  }

  VideoFrameMetadata frame_metadata;
  frame_metadata.transformation = VideoTransformation(frame_rotation);

  client_->OnIncomingCapturedBufferExt(
      std::move(capture_buffer),
      VideoCaptureFormat(
          texture_size, selected_video_capability_->supported_format.frame_rate,
          pixel_format),
      gfx::ColorSpace(), reference_time, timestamp, gfx::Rect(texture_size),
      frame_metadata);

  return hr;
}

void VideoCaptureDeviceMFWin::OnIncomingCapturedDataInternal(
    IMFMediaBuffer* buffer,
    base::TimeTicks reference_time,
    base::TimeDelta timestamp,
    VideoCaptureFrameDropReason& frame_drop_reason) {
  base::AutoLock lock(lock_);

  SendOnStartedIfNotYetSent();

  bool delivered_texture = false;

  if (client_.get()) {
    if (!has_sent_on_started_to_client_) {
      has_sent_on_started_to_client_ = true;
      client_->OnStarted();
    }

    // We always calculate camera rotation for the first frame. We also cache
    // the latest value to use when AutoRotation is turned off.
    if (!camera_rotation_.has_value() || IsAutoRotationEnabled())
      camera_rotation_ = GetCameraRotation(facing_mode_);

    Microsoft::WRL::ComPtr<ID3D11Texture2D> texture;
    // Use the hardware path only if it is enabled and the selected pixel format
    // is NV12 (which is the only supported one).
    if (dxgi_device_manager_ &&
        selected_video_capability_->supported_format.pixel_format ==
            PIXEL_FORMAT_NV12 &&
        SUCCEEDED(GetTextureFromMFBuffer(buffer, &texture))) {
      HRESULT hr =
          DeliverTextureToClient(texture.Get(), reference_time, timestamp);
      DLOG_IF_FAILED_WITH_HRESULT("Failed to deliver D3D11 texture to client.",
                                  hr);
      delivered_texture = SUCCEEDED(hr);
    }
  }

  if (delivered_texture && video_stream_take_photo_callbacks_.empty()) {
    return;
  }

  ScopedBufferLock locked_buffer(buffer);
  if (!locked_buffer.data()) {
    DLOG(ERROR) << "Locked buffer delivered nullptr";
    frame_drop_reason = VideoCaptureFrameDropReason::
        kWinMediaFoundationLockingBufferDelieveredNullptr;
    return;
  }

  if (!delivered_texture && client_.get()) {
    // TODO(julien.isorce): retrieve the color space information using Media
    // Foundation api, MFGetAttributeSize/MF_MT_VIDEO_PRIMARIES,in order to
    // build a gfx::ColorSpace. See http://crbug.com/959988.
    client_->OnIncomingCapturedData(
        locked_buffer.data(), locked_buffer.length(),
        selected_video_capability_->supported_format, gfx::ColorSpace(),
        camera_rotation_.value(), false /* flip_y */, reference_time,
        timestamp);
  }

  while (!video_stream_take_photo_callbacks_.empty()) {
    TakePhotoCallback cb =
        std::move(video_stream_take_photo_callbacks_.front());
    video_stream_take_photo_callbacks_.pop();

    mojom::BlobPtr blob =
        RotateAndBlobify(locked_buffer.data(), locked_buffer.length(),
                         selected_video_capability_->supported_format, 0);
    if (!blob) {
      LogWindowsImageCaptureOutcome(
          VideoCaptureWinBackend::kMediaFoundation,
          ImageCaptureOutcome::kFailedUsingVideoStream,
          IsHighResolution(selected_video_capability_->supported_format));
      continue;
    }

    std::move(cb).Run(std::move(blob));
    LogWindowsImageCaptureOutcome(
        VideoCaptureWinBackend::kMediaFoundation,
        ImageCaptureOutcome::kSucceededUsingVideoStream,
        IsHighResolution(selected_video_capability_->supported_format));
  }
}

void VideoCaptureDeviceMFWin::OnFrameDropped(
    VideoCaptureFrameDropReason reason) {
  base::AutoLock lock(lock_);

  SendOnStartedIfNotYetSent();

  if (client_.get()) {
    client_->OnFrameDropped(reason);
  }
}

void VideoCaptureDeviceMFWin::OnEvent(IMFMediaEvent* media_event) {
  base::AutoLock lock(lock_);

  HRESULT hr;
  GUID capture_event_guid = GUID_NULL;

  media_event->GetStatus(&hr);
  media_event->GetExtendedType(&capture_event_guid);
  // TODO(http://crbug.com/1093521): Add cases for Start
  // MF_CAPTURE_ENGINE_PREVIEW_STARTED and MF_CAPTURE_ENGINE_PREVIEW_STOPPED
  // When MF_CAPTURE_ENGINE_ERROR is returned the captureengine object is no
  // longer valid.
  if (capture_event_guid == MF_CAPTURE_ENGINE_ERROR || FAILED(hr)) {
    capture_error_.Signal();
    // There should always be a valid error
    hr = SUCCEEDED(hr) ? E_UNEXPECTED : hr;
  } else if (capture_event_guid == MF_CAPTURE_ENGINE_INITIALIZED) {
    capture_initialize_.Signal();
  }

  if (FAILED(hr)) {
    base::UmaHistogramSparse("Media.VideoCapture.Win.ErrorEvent", hr);
    OnError(VideoCaptureError::kWinMediaFoundationGetMediaEventStatusFailed,
            FROM_HERE, hr);
  }
}

void VideoCaptureDeviceMFWin::OnError(VideoCaptureError error,
                                      const Location& from_here,
                                      HRESULT hr) {
  OnError(error, from_here, logging::SystemErrorCodeToString(hr).c_str());
}

void VideoCaptureDeviceMFWin::OnError(VideoCaptureError error,
                                      const Location& from_here,
                                      const char* message) {
  if (!client_.get())
    return;

  client_->OnError(error, from_here,
                   base::StringPrintf("VideoCaptureDeviceMFWin: %s", message));
}

void VideoCaptureDeviceMFWin::SendOnStartedIfNotYetSent() {
  if (!client_ || has_sent_on_started_to_client_)
    return;
  has_sent_on_started_to_client_ = true;
  client_->OnStarted();
}

HRESULT VideoCaptureDeviceMFWin::WaitOnCaptureEvent(GUID capture_event_guid) {
  HRESULT hr = S_OK;
  HANDLE events[] = {nullptr, capture_error_.handle()};

  // TODO(http://crbug.com/1093521): Add cases for Start
  // MF_CAPTURE_ENGINE_PREVIEW_STARTED and MF_CAPTURE_ENGINE_PREVIEW_STOPPED
  if (capture_event_guid == MF_CAPTURE_ENGINE_INITIALIZED) {
    events[0] = capture_initialize_.handle();
  } else {
    // no registered event handle for the event requested
    hr = E_NOTIMPL;
    LogError(FROM_HERE, hr);
    return hr;
  }

  DWORD wait_result =
      ::WaitForMultipleObjects(base::size(events), events, FALSE, INFINITE);
  switch (wait_result) {
    case WAIT_OBJECT_0:
      break;
    case WAIT_FAILED:
      hr = HRESULT_FROM_WIN32(::GetLastError());
      LogError(FROM_HERE, hr);
      break;
    default:
      hr = E_UNEXPECTED;
      LogError(FROM_HERE, hr);
      break;
  }
  return hr;
}
}  // namespace media
