Revert "Win video capture: use IMFCaptureEngine for Media Foundation"

This reverts commit f9eaa531b5dfe3f6f3dba721ceca8b138d78410f.

Reason for revert: Suspected cause of Win8 Tester failures
https://build.chromium.org/deprecated/chromium.webrtc/builders/Win8%20Tester/builds/38865

Original change's description:
> Win video capture: use IMFCaptureEngine for Media Foundation
> 
> - Full rewrite of the MediaFoundation implementation video part to use
> IMFCaptureEngine
> - Implementation of takePhoto, setPhotoOptions and getPhotoCapabilities
> - takePhoto triggers a still image capture with the highest available
> resolution without stopping the video stream thanks to IMFCaptureEngine
> 
> TEST=adapted video_capture_device_unittest.cc and
> webrtc_image_capture_browsertest.cc; launch Chrome with
> --force-mediafoundation on Win8+ and capture video using
> e.g. https://webrtc.github.io/samples/src/content/getusermedia/gum/
> 
> R=​mcasas@chromium.org
> 
> Bug: 730068
> Change-Id: Ib8e7f475d8120a63dd08c7b215c1eaf2c6f3d800
> Reviewed-on: https://chromium-review.googlesource.com/734042
> Commit-Queue: Christian Fremerey <chfremer@chromium.org>
> Reviewed-by: Miguel Casas <mcasas@chromium.org>
> Reviewed-by: Christian Fremerey <chfremer@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#521435}

TBR=mcasas@chromium.org,chfremer@chromium.org,alaoui.rda@gmail.com

# Not skipping CQ checks because original CL landed > 1 day ago.

Bug: 730068
Change-Id: I439af305a6bb45c26efb1b395e69088344a71536
Reviewed-on: https://chromium-review.googlesource.com/810624
Reviewed-by: Henrik Boström <hbos@chromium.org>
Commit-Queue: Henrik Boström <hbos@chromium.org>
Cr-Commit-Position: refs/heads/master@{#522080}
diff --git a/AUTHORS b/AUTHORS
index d231ba2..d7f0a3d 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -667,7 +667,6 @@
 Ravi Nanjundappa <nravi.n@samsung.com>
 Ravi Phaneendra Kasibhatla <r.kasibhatla@samsung.com>
 Ravi Phaneendra Kasibhatla <ravi.kasibhatla@motorola.com>
-Réda Housni Alaoui <alaoui.rda@gmail.com>
 Refael Ackermann <refack@gmail.com>
 Renata Hodovan <rhodovan.u-szeged@partner.samsung.com>
 Rene Bolldorf <rb@radix.io>
@@ -914,7 +913,6 @@
 Canonical Limited <*@canonical.com>
 Code Aurora Forum <*@codeaurora.org>
 Comodo CA Limited
-Cosium <*@cosium.com>
 Endless Mobile, Inc. <*@endlessm.com>
 Facebook, Inc. <*@fb.com>
 Facebook, Inc. <*@oculus.com>
diff --git a/content/browser/webrtc/webrtc_image_capture_browsertest.cc b/content/browser/webrtc/webrtc_image_capture_browsertest.cc
index 2028b32..f4757d0 100644
--- a/content/browser/webrtc/webrtc_image_capture_browsertest.cc
+++ b/content/browser/webrtc/webrtc_image_capture_browsertest.cc
@@ -46,26 +46,13 @@
 
 static const char kImageCaptureHtmlFile[] = "/media/image_capture_test.html";
 
-enum class Camera {
-  FAKE,
-  DEFAULT,
-#if defined(OS_WIN)
-  // Media Foundation is only available in Windows versions >= 7, below that the
-  // following flag has no effect
-  WIN_MEDIA_FOUNDATION
-#endif
-};
-
 // TODO(mcasas): enable real-camera tests by disabling the Fake Device for
 // platforms where the ImageCaptureCode is landed, https://crbug.com/656810
 static struct TargetCamera {
-  Camera camera;
-} const kTargetCameras[] = {{Camera::FAKE},
+  bool use_fake;
+} const kTargetCameras[] = {{true},
 #if defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_ANDROID)
-                            {Camera::DEFAULT},
-#endif
-#if defined(OS_WIN)
-                            {Camera::WIN_MEDIA_FOUNDATION}
+                            {false}
 #endif
 };
 
@@ -158,23 +145,11 @@
   void SetUpCommandLine(base::CommandLine* command_line) override {
     WebRtcImageCaptureBrowserTestBase::SetUpCommandLine(command_line);
 
-    switch (std::get<0>(GetParam()).camera) {
-      case Camera::FAKE:
-        base::CommandLine::ForCurrentProcess()->AppendSwitch(
-            switches::kUseFakeDeviceForMediaStream);
-        ASSERT_TRUE(base::CommandLine::ForCurrentProcess()->HasSwitch(
-            switches::kUseFakeDeviceForMediaStream));
-        break;
-#if defined(OS_WIN)
-      case Camera::WIN_MEDIA_FOUNDATION:
-        base::CommandLine::ForCurrentProcess()->AppendSwitch(
-            switches::kForceMediaFoundationVideoCapture);
-        ASSERT_TRUE(base::CommandLine::ForCurrentProcess()->HasSwitch(
-            switches::kForceMediaFoundationVideoCapture));
-        break;
-#endif
-      default:
-        break;
+    if (std::get<0>(GetParam()).use_fake) {
+      base::CommandLine::ForCurrentProcess()->AppendSwitch(
+          switches::kUseFakeDeviceForMediaStream);
+      ASSERT_TRUE(base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kUseFakeDeviceForMediaStream));
     }
   }
 
@@ -182,7 +157,7 @@
     // TODO(chfremer): Enable test cases using the video capture service with
     // real cameras as soon as root cause for https://crbug.com/733582 is
     // understood and resolved.
-    if ((std::get<0>(GetParam()).camera != Camera::FAKE) &&
+    if ((!std::get<0>(GetParam()).use_fake) &&
         (std::get<1>(GetParam()).use_video_capture_service)) {
       LOG(INFO) << "Skipping this test case";
       return true;
diff --git a/content/test/data/media/image_capture_test.html b/content/test/data/media/image_capture_test.html
index 5239163..beb85fa 100644
--- a/content/test/data/media/image_capture_test.html
+++ b/content/test/data/media/image_capture_test.html
@@ -6,7 +6,7 @@
 <body>
 <script type="text/javascript" src="webrtc_test_utilities.js"></script>
 <script>
-const WIDTH = 640;
+const WIDTH = 320;
 /** @const */ var CONSTRAINTS = { width: { max : WIDTH } };
 
 // Returns a Promise resolved with |object| after a delay of |delayInMs|.
diff --git a/media/capture/video/video_capture_device_unittest.cc b/media/capture/video/video_capture_device_unittest.cc
index bac8c1c..c9d9cf4 100644
--- a/media/capture/video/video_capture_device_unittest.cc
+++ b/media/capture/video/video_capture_device_unittest.cc
@@ -28,11 +28,9 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 #if defined(OS_WIN)
-#include <mfcaptureengine.h>
 #include "base/win/scoped_com_initializer.h"
 #include "base/win/windows_version.h"  // For fine-grained suppression.
 #include "media/capture/video/win/video_capture_device_factory_win.h"
-#include "media/capture/video/win/video_capture_device_mf_win.h"
 #endif
 
 #if defined(OS_MACOSX)
@@ -90,16 +88,9 @@
 #define MAYBE_GetPhotoState DISABLED_GetPhotoState
 #endif
 
-// Wrap the TEST_P macro into another one to allow to preprocess |test_name|
-// macros. Needed until https://github.com/google/googletest/issues/389 is
-// fixed.
-#define WRAPPED_TEST_P(test_case_name, test_name) \
-  TEST_P(test_case_name, test_name)
-
 using ::testing::_;
 using ::testing::Invoke;
 using ::testing::SaveArg;
-using ::testing::Return;
 
 namespace media {
 namespace {
@@ -125,35 +116,6 @@
 };
 #endif
 
-enum VideoCaptureImplementationTweak {
-  NONE,
-#if defined(OS_WIN)
-  WIN_MEDIA_FOUNDATION
-#endif
-};
-
-#if defined(OS_WIN)
-class MockMFPhotoCallback final : public IMFCaptureEngineOnSampleCallback {
- public:
-  ~MockMFPhotoCallback() {}
-
-  MOCK_METHOD2(DoQueryInterface, HRESULT(REFIID, void**));
-  MOCK_METHOD0(DoAddRef, ULONG(void));
-  MOCK_METHOD0(DoRelease, ULONG(void));
-  MOCK_METHOD1(DoOnSample, HRESULT(IMFSample*));
-
-  STDMETHOD(QueryInterface)(REFIID riid, void** object) override {
-    return DoQueryInterface(riid, object);
-  }
-
-  STDMETHOD_(ULONG, AddRef)() override { return DoAddRef(); }
-
-  STDMETHOD_(ULONG, Release)() override { return DoRelease(); }
-
-  STDMETHOD(OnSample)(IMFSample* sample) override { return DoOnSample(sample); }
-};
-#endif
-
 class MockVideoCaptureClient : public VideoCaptureDevice::Client {
  public:
   MOCK_METHOD0(DoReserveOutputBuffer, void(void));
@@ -299,19 +261,7 @@
 
 }  // namespace
 
-class VideoCaptureDeviceTest
-    : public testing::TestWithParam<
-          std::tuple<gfx::Size, VideoCaptureImplementationTweak>> {
- public:
-#if defined(OS_WIN)
-  scoped_refptr<IMFCaptureEngineOnSampleCallback> CreateMockPhotoCallback(
-      MockMFPhotoCallback* mock_photo_callback,
-      VideoCaptureDevice::TakePhotoCallback callback,
-      VideoCaptureFormat format) {
-    return scoped_refptr<IMFCaptureEngineOnSampleCallback>(mock_photo_callback);
-  }
-#endif
-
+class VideoCaptureDeviceTest : public testing::TestWithParam<gfx::Size> {
  protected:
   typedef VideoCaptureDevice::Client Client;
 
@@ -344,10 +294,6 @@
     static_cast<VideoCaptureDeviceFactoryAndroid*>(
         video_capture_device_factory_.get())
         ->ConfigureForTesting();
-#elif defined(OS_WIN)
-    static_cast<VideoCaptureDeviceFactoryWin*>(
-        video_capture_device_factory_.get())
-        ->set_use_media_foundation_for_testing(UseWinMediaFoundation());
 #endif
     EXPECT_CALL(*video_capture_client_, DoReserveOutputBuffer()).Times(0);
     EXPECT_CALL(*video_capture_client_, DoOnIncomingCapturedBuffer()).Times(0);
@@ -355,12 +301,6 @@
         .Times(0);
   }
 
-#if defined(OS_WIN)
-  bool UseWinMediaFoundation() {
-    return std::get<1>(GetParam()) == WIN_MEDIA_FOUNDATION;
-  }
-#endif
-
   void ResetWithNewClient() {
     video_capture_client_.reset(new MockVideoCaptureClient(base::Bind(
         &VideoCaptureDeviceTest::OnFrameCaptured, base::Unretained(this))));
@@ -467,7 +407,7 @@
 #define MAYBE_OpenInvalidDevice OpenInvalidDevice
 #endif
 // Tries to allocate an invalid device and verifies it doesn't work.
-WRAPPED_TEST_P(VideoCaptureDeviceTest, MAYBE_OpenInvalidDevice) {
+TEST_F(VideoCaptureDeviceTest, MAYBE_OpenInvalidDevice) {
   VideoCaptureDeviceDescriptor invalid_descriptor;
   invalid_descriptor.device_id = "jibberish";
   invalid_descriptor.display_name = "jibberish";
@@ -499,12 +439,12 @@
 }
 
 // Allocates the first enumerated device, and expects a frame.
-WRAPPED_TEST_P(VideoCaptureDeviceTest, CaptureWithSize) {
+TEST_P(VideoCaptureDeviceTest, CaptureWithSize) {
   const auto descriptor = FindUsableDeviceDescriptor();
   if (!descriptor)
     return;
 
-  const gfx::Size& size = std::get<0>(GetParam());
+  const gfx::Size& size = GetParam();
   if (!IsCaptureSizeSupported(*descriptor, size))
     return;
   const int width = size.width();
@@ -534,22 +474,14 @@
 }
 
 const gfx::Size kCaptureSizes[] = {gfx::Size(640, 480), gfx::Size(1280, 720)};
-const VideoCaptureImplementationTweak kCaptureImplementationTweaks[] = {
-    NONE,
-#if defined(OS_WIN)
-    WIN_MEDIA_FOUNDATION
-#endif
-};
 
-INSTANTIATE_TEST_CASE_P(
-    VideoCaptureDeviceTests,
-    VideoCaptureDeviceTest,
-    testing::Combine(testing::ValuesIn(kCaptureSizes),
-                     testing::ValuesIn(kCaptureImplementationTweaks)));
+INSTANTIATE_TEST_CASE_P(VideoCaptureDeviceTests,
+                        VideoCaptureDeviceTest,
+                        testing::ValuesIn(kCaptureSizes));
 
 // Allocates a device with an uncommon resolution and verifies frames are
 // captured in a close, much more typical one.
-WRAPPED_TEST_P(VideoCaptureDeviceTest, MAYBE_AllocateBadSize) {
+TEST_F(VideoCaptureDeviceTest, MAYBE_AllocateBadSize) {
   const auto descriptor = FindUsableDeviceDescriptor();
   if (!descriptor)
     return;
@@ -576,7 +508,7 @@
 }
 
 // Cause hangs on Windows, Linux. Fails Android. https://crbug.com/417824
-WRAPPED_TEST_P(VideoCaptureDeviceTest, DISABLED_ReAllocateCamera) {
+TEST_F(VideoCaptureDeviceTest, DISABLED_ReAllocateCamera) {
   const auto descriptor = FindUsableDeviceDescriptor();
   if (!descriptor)
     return;
@@ -620,7 +552,7 @@
 }
 
 // Starts the camera in 720p to try and capture MJPEG format.
-WRAPPED_TEST_P(VideoCaptureDeviceTest, MAYBE_CaptureMjpeg) {
+TEST_F(VideoCaptureDeviceTest, MAYBE_CaptureMjpeg) {
   std::unique_ptr<VideoCaptureDeviceDescriptor> device_descriptor =
       GetFirstDeviceDescriptorSupportingPixelFormat(PIXEL_FORMAT_MJPEG);
   if (!device_descriptor) {
@@ -657,7 +589,7 @@
   device->StopAndDeAllocate();
 }
 
-WRAPPED_TEST_P(VideoCaptureDeviceTest, NoCameraSupportsPixelFormatMax) {
+TEST_F(VideoCaptureDeviceTest, NoCameraSupportsPixelFormatMax) {
   // Use PIXEL_FORMAT_MAX to iterate all device names for testing
   // GetDeviceSupportedFormats().
   std::unique_ptr<VideoCaptureDeviceDescriptor> device_descriptor =
@@ -669,7 +601,7 @@
 
 // Starts the camera and verifies that a photo can be taken. The correctness of
 // the photo is enforced by MockImageCaptureClient.
-WRAPPED_TEST_P(VideoCaptureDeviceTest, MAYBE_TakePhoto) {
+TEST_F(VideoCaptureDeviceTest, MAYBE_TakePhoto) {
   const auto descriptor = FindUsableDeviceDescriptor();
   if (!descriptor)
     return;
@@ -718,7 +650,7 @@
 }
 
 // Starts the camera and verifies that the photo capabilities can be retrieved.
-WRAPPED_TEST_P(VideoCaptureDeviceTest, MAYBE_GetPhotoState) {
+TEST_F(VideoCaptureDeviceTest, MAYBE_GetPhotoState) {
   const auto descriptor = FindUsableDeviceDescriptor();
   if (!descriptor)
     return;
@@ -769,55 +701,4 @@
   device->StopAndDeAllocate();
 }
 
-#if defined(OS_WIN)
-// Verifies that the photo callback is correctly released by MediaFoundation
-WRAPPED_TEST_P(VideoCaptureDeviceTest, CheckPhotoCallbackRelease) {
-  if (!UseWinMediaFoundation())
-    return;
-
-  std::unique_ptr<VideoCaptureDeviceDescriptor> descriptor =
-      GetFirstDeviceDescriptorSupportingPixelFormat(PIXEL_FORMAT_MJPEG);
-  if (!descriptor) {
-    DVLOG(1) << "No usable media foundation device descriptor. Exiting test.";
-    return;
-  }
-
-  MockMFPhotoCallback* callback = new MockMFPhotoCallback();
-  EXPECT_CALL(*callback, DoQueryInterface(_, _)).WillRepeatedly(Return(S_OK));
-  EXPECT_CALL(*callback, DoAddRef()).WillOnce(Return(1U));
-  EXPECT_CALL(*callback, DoRelease()).WillOnce(Return(1U));
-  EXPECT_CALL(*callback, DoOnSample(_)).WillOnce(Return(S_OK));
-
-  EXPECT_CALL(*video_capture_client_, OnError(_, _)).Times(0);
-  EXPECT_CALL(*video_capture_client_, OnStarted());
-
-  std::unique_ptr<VideoCaptureDevice> device(
-      video_capture_device_factory_->CreateDevice(*descriptor));
-  ASSERT_TRUE(device);
-  static_cast<VideoCaptureDeviceMFWin*>(device.get())
-      ->set_create_mf_photo_callback_for_testing(
-          base::Bind(&VideoCaptureDeviceTest::CreateMockPhotoCallback,
-                     base::Unretained(this), callback));
-
-  VideoCaptureParams capture_params;
-  capture_params.requested_format.frame_size.SetSize(320, 240);
-  capture_params.requested_format.frame_rate = 30;
-  capture_params.requested_format.pixel_format = PIXEL_FORMAT_MJPEG;
-  device->AllocateAndStart(capture_params, std::move(video_capture_client_));
-
-  VideoCaptureDevice::TakePhotoCallback scoped_callback = base::BindOnce(
-      &MockImageCaptureClient::DoOnPhotoTaken, image_capture_client_);
-
-  base::RunLoop run_loop;
-  base::Closure quit_closure = BindToCurrentLoop(run_loop.QuitClosure());
-  EXPECT_CALL(*image_capture_client_.get(), OnCorrectPhotoTaken())
-      .WillOnce(RunClosure(quit_closure));
-
-  device->TakePhoto(std::move(scoped_callback));
-  run_loop.Run();
-
-  device->StopAndDeAllocate();
-}
-#endif
-
 };  // namespace media
diff --git a/media/capture/video/win/video_capture_device_factory_win.cc b/media/capture/video/win/video_capture_device_factory_win.cc
index 8f6168f..fec2ed9 100644
--- a/media/capture/video/win/video_capture_device_factory_win.cc
+++ b/media/capture/video/win/video_capture_device_factory_win.cc
@@ -69,9 +69,10 @@
 
 static bool LoadMediaFoundationDlls() {
   static const wchar_t* const kMfDLLs[] = {
-      L"%WINDIR%\\system32\\mf.dll", L"%WINDIR%\\system32\\mfplat.dll",
+      L"%WINDIR%\\system32\\mf.dll",
+      L"%WINDIR%\\system32\\mfplat.dll",
       L"%WINDIR%\\system32\\mfreadwrite.dll",
-      L"%WINDIR%\\system32\\MFCaptureEngine.dll"};
+  };
 
   for (const wchar_t* kMfDLL : kMfDLLs) {
     wchar_t path[MAX_PATH] = {0};
@@ -85,13 +86,8 @@
 static bool PrepareVideoCaptureAttributesMediaFoundation(
     IMFAttributes** attributes,
     int count) {
-  // Once https://bugs.chromium.org/p/chromium/issues/detail?id=791615 is fixed,
-  // we must make sure that this method succeeds in capture_unittests context
-  // when MediaFoundation is enabled.
-  if (!VideoCaptureDeviceFactoryWin::PlatformSupportsMediaFoundation() ||
-      !InitializeMediaFoundation()) {
+  if (!InitializeMediaFoundation())
     return false;
-  }
 
   if (FAILED(MFCreateAttributes(attributes, count)))
     return false;
@@ -290,9 +286,8 @@
 
   DWORD stream_index = 0;
   ComPtr<IMFMediaType> type;
-  while (SUCCEEDED(hr = reader->GetNativeMediaType(
-                       static_cast<DWORD>(MF_SOURCE_READER_FIRST_VIDEO_STREAM),
-                       stream_index, type.GetAddressOf()))) {
+  while (SUCCEEDED(reader->GetNativeMediaType(kFirstVideoStream, stream_index,
+                                              type.GetAddressOf()))) {
     UINT32 width, height;
     hr = MFGetAttributeSize(type.Get(), MF_MT_FRAME_SIZE, &width, &height);
     if (FAILED(hr)) {
diff --git a/media/capture/video/win/video_capture_device_factory_win.h b/media/capture/video/win/video_capture_device_factory_win.h
index a7d36783..9afcc64 100644
--- a/media/capture/video/win/video_capture_device_factory_win.h
+++ b/media/capture/video/win/video_capture_device_factory_win.h
@@ -30,12 +30,10 @@
       const VideoCaptureDeviceDescriptor& device_descriptor,
       VideoCaptureFormats* supported_formats) override;
 
-  void set_use_media_foundation_for_testing(bool use) {
-    use_media_foundation_ = use;
-  }
-
  private:
-  bool use_media_foundation_;
+  // Media Foundation is available in Win7 and later, use it if explicitly
+  // forced via flag, else use DirectShow.
+  const bool use_media_foundation_;
 
   DISALLOW_COPY_AND_ASSIGN(VideoCaptureDeviceFactoryWin);
 };
diff --git a/media/capture/video/win/video_capture_device_mf_win.cc b/media/capture/video/win/video_capture_device_mf_win.cc
index 1c07614..73a144b 100644
--- a/media/capture/video/win/video_capture_device_mf_win.cc
+++ b/media/capture/video/win/video_capture_device_mf_win.cc
@@ -7,9 +7,7 @@
 #include <mfapi.h>
 #include <mferror.h>
 #include <stddef.h>
-#include <wincodec.h>
 
-#include <thread>
 #include <utility>
 
 #include "base/location.h"
@@ -19,102 +17,14 @@
 #include "base/synchronization/waitable_event.h"
 #include "base/win/scoped_co_mem.h"
 #include "base/win/windows_version.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"
 
 using base::win::ScopedCoMem;
-using Microsoft::WRL::ComPtr;
-using base::Location;
 
 namespace media {
 
-namespace {
-class MFPhotoCallback final
-    : public base::RefCountedThreadSafe<MFPhotoCallback>,
-      public IMFCaptureEngineOnSampleCallback {
- public:
-  MFPhotoCallback(VideoCaptureDevice::TakePhotoCallback callback,
-                  VideoCaptureFormat format)
-      : callback_(std::move(callback)), format_(format) {}
-
-  STDMETHOD(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;
-  }
-
-  STDMETHOD_(ULONG, AddRef)() override {
-    base::RefCountedThreadSafe<MFPhotoCallback>::AddRef();
-    return 1U;
-  }
-
-  STDMETHOD_(ULONG, Release)() override {
-    base::RefCountedThreadSafe<MFPhotoCallback>::Release();
-    return 1U;
-  }
-
-  STDMETHOD(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.GetAddressOf());
-      if (!buffer)
-        continue;
-
-      BYTE* data = nullptr;
-      DWORD max_length = 0;
-      DWORD length = 0;
-      buffer->Lock(&data, &max_length, &length);
-      mojom::BlobPtr blob = Blobify(data, length, format_);
-      buffer->Unlock();
-      if (blob) {
-        std::move(callback_).Run(std::move(blob));
-        // 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() = default;
-
-  VideoCaptureDevice::TakePhotoCallback callback_;
-  const VideoCaptureFormat format_;
-
-  DISALLOW_COPY_AND_ASSIGN(MFPhotoCallback);
-};
-
-scoped_refptr<IMFCaptureEngineOnSampleCallback> CreateMFPhotoCallback(
-    VideoCaptureDevice::TakePhotoCallback callback,
-    VideoCaptureFormat format) {
-  return scoped_refptr<IMFCaptureEngineOnSampleCallback>(
-      new MFPhotoCallback(std::move(callback), format));
-}
-}  // namespace
-
-void LogError(const Location& from_here, HRESULT hr) {
-#if !defined(NDEBUG)
-  DPLOG(ERROR) << from_here.ToString()
-               << " hr = " << logging::SystemErrorCodeToString(hr);
-#endif
-}
-
-static bool GetFrameSizeFromMediaType(IMFMediaType* type,
-                                      gfx::Size* frame_size) {
+static bool GetFrameSize(IMFMediaType* type, gfx::Size* frame_size) {
   UINT32 width32, height32;
   if (FAILED(MFGetAttributeSize(type, MF_MT_FRAME_SIZE, &width32, &height32)))
     return false;
@@ -122,7 +32,7 @@
   return true;
 }
 
-static bool GetFrameRateFromMediaType(IMFMediaType* type, float* frame_rate) {
+static bool GetFrameRate(IMFMediaType* type, float* frame_rate) {
   UINT32 numerator, denominator;
   if (FAILED(MFGetAttributeRatio(type, MF_MT_FRAME_RATE, &numerator,
                                  &denominator)) ||
@@ -133,19 +43,12 @@
   return true;
 }
 
-static bool GetFormatFromMediaType(IMFMediaType* type,
-                                   VideoCaptureFormat* format) {
-  GUID major_type_guid;
-  if (FAILED(type->GetGUID(MF_MT_MAJOR_TYPE, &major_type_guid)) ||
-      (major_type_guid != MFMediaType_Image &&
-       !GetFrameRateFromMediaType(type, &format->frame_rate))) {
-    return false;
-  }
-
-  GUID sub_type_guid;
-  if (FAILED(type->GetGUID(MF_MT_SUBTYPE, &sub_type_guid)) ||
-      !GetFrameSizeFromMediaType(type, &format->frame_size) ||
-      !VideoCaptureDeviceMFWin::FormatFromGuid(sub_type_guid,
+static bool FillFormat(IMFMediaType* type, VideoCaptureFormat* format) {
+  GUID type_guid;
+  if (FAILED(type->GetGUID(MF_MT_SUBTYPE, &type_guid)) ||
+      !GetFrameSize(type, &format->frame_size) ||
+      !GetFrameRate(type, &format->frame_rate) ||
+      !VideoCaptureDeviceMFWin::FormatFromGuid(type_guid,
                                                &format->pixel_format)) {
     return false;
   }
@@ -153,98 +56,18 @@
   return true;
 }
 
-static 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;
-}
-
-static HRESULT ConvertToPhotoJpegMediaType(
-    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;
-
-  hr = destination_media_type->SetGUID(MF_MT_SUBTYPE, GUID_ContainerFormatJpeg);
-  if (FAILED(hr))
-    return hr;
-
-  return CopyAttribute(source_media_type, destination_media_type,
-                       MF_MT_FRAME_SIZE);
-}
-
-static 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 GetAvailableDeviceMediaType(IMFCaptureSource* source,
-                                    DWORD stream_index,
-                                    DWORD media_type_index,
-                                    IMFMediaType** type) {
-  HRESULT hr;
-  // Rarely, for some unknown reason, GetAvailableDeviceMediaType returns an
-  // undocumented MF_E_INVALIDREQUEST. Retrying solves the issue.
-  int retry_count = 0;
-  do {
-    hr = source->GetAvailableDeviceMediaType(stream_index, media_type_index,
-                                             type);
-    if (FAILED(hr))
-      base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(50));
-
-    // Give up after ~10 seconds
-  } while (hr == MF_E_INVALIDREQUEST && retry_count++ < 200);
-
-  return hr;
-}
-
-HRESULT FillCapabilities(DWORD stream,
-                         IMFCaptureSource* source,
+HRESULT FillCapabilities(IMFSourceReader* source,
                          CapabilityList* capabilities) {
-  DWORD media_type_index = 0;
-  ComPtr<IMFMediaType> type;
+  DWORD stream_index = 0;
+  Microsoft::WRL::ComPtr<IMFMediaType> type;
   HRESULT hr;
-
-  while (
-      SUCCEEDED(hr = GetAvailableDeviceMediaType(
-                    source, stream, media_type_index, type.GetAddressOf()))) {
+  while (SUCCEEDED(hr = source->GetNativeMediaType(
+                       kFirstVideoStream, stream_index, type.GetAddressOf()))) {
     VideoCaptureFormat format;
-    if (GetFormatFromMediaType(type.Get(), &format))
-      capabilities->emplace_back(media_type_index, format);
+    if (FillFormat(type.Get(), &format))
+      capabilities->emplace_back(stream_index, format);
     type.Reset();
-    ++media_type_index;
+    ++stream_index;
   }
 
   if (capabilities->empty() && (SUCCEEDED(hr) || hr == MF_E_NO_MORE_TYPES))
@@ -253,51 +76,40 @@
   return (hr == MF_E_NO_MORE_TYPES) ? S_OK : hr;
 }
 
-class MFVideoCallback final
-    : public base::RefCountedThreadSafe<MFVideoCallback>,
-      public IMFCaptureEngineOnSampleCallback,
-      public IMFCaptureEngineOnEventCallback {
+class MFReaderCallback final
+    : public base::RefCountedThreadSafe<MFReaderCallback>,
+      public IMFSourceReaderCallback {
  public:
-  MFVideoCallback(VideoCaptureDeviceMFWin* observer) : observer_(observer) {}
+  MFReaderCallback(VideoCaptureDeviceMFWin* observer)
+      : observer_(observer), wait_event_(NULL) {}
+
+  void SetSignalOnFlush(base::WaitableEvent* event) { wait_event_ = event; }
 
   STDMETHOD(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;
+    if (riid != IID_IUnknown && riid != IID_IMFSourceReaderCallback)
+      return E_NOINTERFACE;
+    *object = static_cast<IMFSourceReaderCallback*>(this);
+    AddRef();
+    return S_OK;
   }
 
   STDMETHOD_(ULONG, AddRef)() override {
-    base::RefCountedThreadSafe<MFVideoCallback>::AddRef();
+    base::RefCountedThreadSafe<MFReaderCallback>::AddRef();
     return 1U;
   }
 
   STDMETHOD_(ULONG, Release)() override {
-    base::RefCountedThreadSafe<MFVideoCallback>::Release();
+    base::RefCountedThreadSafe<MFReaderCallback>::Release();
     return 1U;
   }
 
-  STDMETHOD(OnEvent)(IMFMediaEvent* media_event) override {
-    observer_->OnEvent(media_event);
-    return S_OK;
-  }
-
-  STDMETHOD(OnSample)(IMFSample* sample) override {
+  STDMETHOD(OnReadSample)
+  (HRESULT status,
+   DWORD stream_index,
+   DWORD stream_flags,
+   LONGLONG raw_time_stamp,
+   IMFSample* sample) override {
     base::TimeTicks reference_time(base::TimeTicks::Now());
-
-    LONGLONG raw_time_stamp = 0;
-    sample->GetSampleTime(&raw_time_stamp);
     base::TimeDelta timestamp =
         base::TimeDelta::FromMicroseconds(raw_time_stamp / 10);
     if (!sample) {
@@ -309,9 +121,9 @@
     sample->GetBufferCount(&count);
 
     for (DWORD i = 0; i < count; ++i) {
-      ComPtr<IMFMediaBuffer> buffer;
+      Microsoft::WRL::ComPtr<IMFMediaBuffer> buffer;
       sample->GetBufferByIndex(i, buffer.GetAddressOf());
-      if (buffer) {
+      if (buffer.Get()) {
         DWORD length = 0, max_length = 0;
         BYTE* data = NULL;
         buffer->Lock(&data, &max_length, &length);
@@ -323,10 +135,25 @@
     return S_OK;
   }
 
+  STDMETHOD(OnFlush)(DWORD stream_index) override {
+    if (wait_event_) {
+      wait_event_->Signal();
+      wait_event_ = NULL;
+    }
+    return S_OK;
+  }
+
+  STDMETHOD(OnEvent)(DWORD stream_index, IMFMediaEvent* event) override {
+    NOTIMPLEMENTED();
+    return S_OK;
+  }
+
  private:
-  friend class base::RefCountedThreadSafe<MFVideoCallback>;
-  ~MFVideoCallback() {}
+  friend class base::RefCountedThreadSafe<MFReaderCallback>;
+  ~MFReaderCallback() {}
+
   VideoCaptureDeviceMFWin* observer_;
+  base::WaitableEvent* wait_event_;
 };
 
 // static
@@ -342,7 +169,6 @@
       {MFVideoFormat_RGB24, PIXEL_FORMAT_RGB24},
       {MFVideoFormat_ARGB32, PIXEL_FORMAT_ARGB},
       {MFVideoFormat_MJPG, PIXEL_FORMAT_MJPEG},
-      {GUID_ContainerFormatJpeg, PIXEL_FORMAT_MJPEG},
       {MFVideoFormat_YV12, PIXEL_FORMAT_YV12},
       {kMediaSubTypeY16, PIXEL_FORMAT_Y16},
       {kMediaSubTypeZ16, PIXEL_FORMAT_Y16},
@@ -361,9 +187,7 @@
 
 VideoCaptureDeviceMFWin::VideoCaptureDeviceMFWin(
     const VideoCaptureDeviceDescriptor& device_descriptor)
-    : descriptor_(device_descriptor),
-      create_mf_photo_callback_(base::Bind(&CreateMFPhotoCallback)),
-      is_started_(false) {
+    : descriptor_(device_descriptor), capture_(0) {
   DETACH_FROM_SEQUENCE(sequence_checker_);
 }
 
@@ -371,44 +195,20 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 }
 
-bool VideoCaptureDeviceMFWin::Init(const ComPtr<IMFMediaSource>& source) {
+bool VideoCaptureDeviceMFWin::Init(
+    const Microsoft::WRL::ComPtr<IMFMediaSource>& source) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  DCHECK(!engine_);
+  DCHECK(!reader_.Get());
 
-  HRESULT hr = S_OK;
-  ComPtr<IMFAttributes> attributes;
-  ComPtr<IMFCaptureEngineClassFactory> capture_engine_class_factory;
+  Microsoft::WRL::ComPtr<IMFAttributes> attributes;
   MFCreateAttributes(attributes.GetAddressOf(), 1);
-  DCHECK(attributes);
+  DCHECK(attributes.Get());
 
-  hr = CoCreateInstance(
-      CLSID_MFCaptureEngineClassFactory, NULL, CLSCTX_INPROC_SERVER,
-      IID_PPV_ARGS(capture_engine_class_factory.GetAddressOf()));
-  if (FAILED(hr)) {
-    LogError(FROM_HERE, hr);
-    return false;
-  }
-  hr = capture_engine_class_factory->CreateInstance(
-      CLSID_MFCaptureEngine, IID_PPV_ARGS(engine_.GetAddressOf()));
-  if (FAILED(hr)) {
-    LogError(FROM_HERE, hr);
-    return false;
-  }
+  callback_ = new MFReaderCallback(this);
+  attributes->SetUnknown(MF_SOURCE_READER_ASYNC_CALLBACK, callback_.get());
 
-  video_callback_ = new MFVideoCallback(this);
-  if (FAILED(hr)) {
-    LogError(FROM_HERE, hr);
-    return false;
-  }
-
-  hr = engine_->Initialize(video_callback_.get(), attributes.Get(), nullptr,
-                           source.Get());
-  if (FAILED(hr)) {
-    LogError(FROM_HERE, hr);
-    return false;
-  }
-
-  return true;
+  return SUCCEEDED(MFCreateSourceReaderFromMediaSource(
+      source.Get(), attributes.Get(), reader_.GetAddressOf()));
 }
 
 void VideoCaptureDeviceMFWin::AllocateAndStart(
@@ -419,314 +219,65 @@
   base::AutoLock lock(lock_);
 
   client_ = std::move(client);
-  DCHECK_EQ(false, is_started_);
+  DCHECK_EQ(capture_, false);
 
   CapabilityList capabilities;
-  if (!engine_) {
-    OnError(FROM_HERE, E_FAIL);
-    return;
+  HRESULT hr = S_OK;
+  if (reader_.Get()) {
+    hr = FillCapabilities(reader_.Get(), &capabilities);
+    if (SUCCEEDED(hr)) {
+      const CapabilityWin found_capability =
+          GetBestMatchedCapability(params.requested_format, capabilities);
+      Microsoft::WRL::ComPtr<IMFMediaType> type;
+      hr = reader_->GetNativeMediaType(kFirstVideoStream,
+                                       found_capability.stream_index,
+                                       type.GetAddressOf());
+      if (SUCCEEDED(hr)) {
+        hr = reader_->SetCurrentMediaType(kFirstVideoStream, NULL, type.Get());
+        if (SUCCEEDED(hr)) {
+          hr =
+              reader_->ReadSample(kFirstVideoStream, 0, NULL, NULL, NULL, NULL);
+          if (SUCCEEDED(hr)) {
+            capture_format_ = found_capability.supported_format;
+            client_->OnStarted();
+            capture_ = true;
+            return;
+          }
+        }
+      }
+    }
   }
 
-  ComPtr<IMFCaptureSource> source;
-  HRESULT hr = engine_->GetSource(source.GetAddressOf());
-  if (FAILED(hr)) {
-    OnError(FROM_HERE, hr);
-    return;
-  }
-
-  hr = FillCapabilities(kPreferredVideoPreviewStream, source.Get(),
-                        &capabilities);
-  if (FAILED(hr)) {
-    OnError(FROM_HERE, hr);
-    return;
-  }
-
-  const CapabilityWin found_capability =
-      GetBestMatchedCapability(params.requested_format, capabilities);
-  ComPtr<IMFMediaType> type;
-  hr = GetAvailableDeviceMediaType(source.Get(), kPreferredVideoPreviewStream,
-                                   found_capability.stream_index,
-                                   type.GetAddressOf());
-  if (FAILED(hr)) {
-    OnError(FROM_HERE, hr);
-    return;
-  }
-
-  hr = source->SetCurrentDeviceMediaType(kPreferredVideoPreviewStream,
-                                         type.Get());
-  if (FAILED(hr)) {
-    OnError(FROM_HERE, hr);
-    return;
-  }
-
-  ComPtr<IMFCaptureSink> sink;
-  hr = engine_->GetSink(MF_CAPTURE_ENGINE_SINK_TYPE_PREVIEW,
-                        sink.GetAddressOf());
-  if (FAILED(hr)) {
-    OnError(FROM_HERE, hr);
-    return;
-  }
-
-  ComPtr<IMFCapturePreviewSink> preview_sink;
-  hr = sink->QueryInterface(IID_PPV_ARGS(preview_sink.GetAddressOf()));
-  if (FAILED(hr)) {
-    OnError(FROM_HERE, hr);
-    return;
-  }
-
-  hr = preview_sink->RemoveAllStreams();
-  if (FAILED(hr)) {
-    OnError(FROM_HERE, hr);
-    return;
-  }
-
-  DWORD dw_sink_stream_index = 0;
-  hr = preview_sink->AddStream(kPreferredVideoPreviewStream, type.Get(), NULL,
-                               &dw_sink_stream_index);
-  if (FAILED(hr)) {
-    OnError(FROM_HERE, hr);
-    return;
-  }
-
-  hr = preview_sink->SetSampleCallback(dw_sink_stream_index,
-                                       video_callback_.get());
-  if (FAILED(hr)) {
-    OnError(FROM_HERE, hr);
-    return;
-  }
-
-  hr = engine_->StartPreview();
-  if (FAILED(hr)) {
-    OnError(FROM_HERE, hr);
-    return;
-  }
-
-  capture_video_format_ = found_capability.supported_format;
-  client_->OnStarted();
-  is_started_ = true;
+  OnError(FROM_HERE, hr);
 }
 
 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_);
-
-  if (!is_started_)
-    return;
-
-  ComPtr<IMFCaptureSource> source;
-  HRESULT hr = engine_->GetSource(source.GetAddressOf());
-  if (FAILED(hr)) {
-    LogError(FROM_HERE, hr);
-    return;
-  }
-
-  ComPtr<IMFMediaType> current_media_type;
-  hr = source->GetCurrentDeviceMediaType(kPreferredPhotoStream,
-                                         current_media_type.GetAddressOf());
-  if (FAILED(hr)) {
-    LogError(FROM_HERE, hr);
-    return;
-  }
-
-  ComPtr<IMFMediaType> photo_media_type;
-  hr = MFCreateMediaType(photo_media_type.GetAddressOf());
-  if (FAILED(hr)) {
-    LogError(FROM_HERE, hr);
-    return;
-  }
-
-  hr = ConvertToPhotoJpegMediaType(current_media_type.Get(),
-                                   photo_media_type.Get());
-  if (FAILED(hr)) {
-    LogError(FROM_HERE, hr);
-    return;
-  }
-
-  hr = source->SetCurrentDeviceMediaType(kPreferredPhotoStream,
-                                         photo_media_type.Get());
-  if (FAILED(hr)) {
-    LogError(FROM_HERE, hr);
-    return;
-  }
-
-  VideoCaptureFormat format;
-  hr = GetFormatFromMediaType(photo_media_type.Get(), &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.GetAddressOf());
-  if (FAILED(hr)) {
-    LogError(FROM_HERE, hr);
-    return;
-  }
-
-  ComPtr<IMFCapturePhotoSink> photo_sink;
-  hr = sink->QueryInterface(IID_PPV_ARGS(photo_sink.GetAddressOf()));
-  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(kPreferredPhotoStream, photo_media_type.Get(),
-                             NULL, &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.GetAddressOf());
-  if (FAILED(hr)) {
-    LogError(FROM_HERE, hr);
-    return;
-  }
-
-  CapabilityList capabilities;
-  hr = FillCapabilities(kPreferredPhotoStream, source.Get(), &capabilities);
-  if (FAILED(hr)) {
-    LogError(FROM_HERE, hr);
-    return;
-  }
-
-  ComPtr<IMFMediaType> current_media_type;
-  hr = source->GetCurrentDeviceMediaType(kPreferredPhotoStream,
-                                         current_media_type.GetAddressOf());
-  if (FAILED(hr)) {
-    LogError(FROM_HERE, hr);
-    return;
-  }
-
-  auto photo_capabilities = mojom::PhotoState::New();
-  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 : 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);
-
-  photo_capabilities->exposure_compensation = mojom::Range::New();
-  photo_capabilities->color_temperature = mojom::Range::New();
-  photo_capabilities->iso = mojom::Range::New();
-  photo_capabilities->brightness = mojom::Range::New();
-  photo_capabilities->contrast = mojom::Range::New();
-  photo_capabilities->saturation = mojom::Range::New();
-  photo_capabilities->sharpness = mojom::Range::New();
-  photo_capabilities->zoom = mojom::Range::New();
-  photo_capabilities->red_eye_reduction = mojom::RedEyeReduction::NEVER;
-
-  photo_capabilities->torch = false;
-  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.GetAddressOf());
-
-  if (FAILED(hr)) {
-    LogError(FROM_HERE, hr);
-    return;
-  }
-
-  if (settings->has_height || settings->has_width) {
-    CapabilityList capabilities;
-    hr = FillCapabilities(kPreferredPhotoStream, source.Get(), &capabilities);
-
-    if (FAILED(hr)) {
-      LogError(FROM_HERE, hr);
-      return;
+  base::WaitableEvent flushed(base::WaitableEvent::ResetPolicy::AUTOMATIC,
+                              base::WaitableEvent::InitialState::NOT_SIGNALED);
+  const int kFlushTimeOutInMs = 1000;
+  bool wait = false;
+  {
+    base::AutoLock lock(lock_);
+    if (capture_) {
+      capture_ = false;
+      callback_->SetSignalOnFlush(&flushed);
+      wait = SUCCEEDED(
+          reader_->Flush(static_cast<DWORD>(MF_SOURCE_READER_ALL_STREAMS)));
+      if (!wait) {
+        callback_->SetSignalOnFlush(NULL);
+      }
     }
-
-    ComPtr<IMFMediaType> current_media_type;
-    hr = source->GetCurrentDeviceMediaType(kPreferredPhotoStream,
-                                           current_media_type.GetAddressOf());
-
-    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_media_type, requested_size, capabilities);
-
-    ComPtr<IMFMediaType> type;
-    hr = GetAvailableDeviceMediaType(source.Get(), kPreferredPhotoStream,
-                                     best_match.stream_index,
-                                     type.GetAddressOf());
-    if (FAILED(hr)) {
-      LogError(FROM_HERE, hr);
-      return;
-    }
-
-    hr = source->SetCurrentDeviceMediaType(kPreferredPhotoStream, type.Get());
-    if (FAILED(hr)) {
-      LogError(FROM_HERE, hr);
-      return;
-    }
+    client_.reset();
   }
 
-  std::move(callback).Run(true);
+  // If the device has been unplugged, the Flush() won't trigger the event
+  // and a timeout will happen.
+  // TODO(tommi): Hook up the IMFMediaEventGenerator notifications API and
+  // do not wait at all after getting MEVideoCaptureDeviceRemoved event.
+  // See issue/226396.
+  if (wait)
+    flushed.TimedWait(base::TimeDelta::FromMilliseconds(kFlushTimeOutInMs));
 }
 
 void VideoCaptureDeviceMFWin::OnIncomingCapturedData(
@@ -736,27 +287,27 @@
     base::TimeTicks reference_time,
     base::TimeDelta timestamp) {
   base::AutoLock lock(lock_);
-
   if (data && client_.get()) {
-    client_->OnIncomingCapturedData(data, length, capture_video_format_,
-                                    rotation, reference_time, timestamp);
+    client_->OnIncomingCapturedData(data, length, capture_format_, rotation,
+                                    reference_time, timestamp);
+  }
+
+  if (capture_) {
+    HRESULT hr =
+        reader_->ReadSample(kFirstVideoStream, 0, NULL, NULL, NULL, NULL);
+    if (FAILED(hr)) {
+      // If running the *VideoCap* unit tests on repeat, this can sometimes
+      // fail with HRESULT_FROM_WINHRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION).
+      // It's not clear to me why this is, but it is possible that it has
+      // something to do with this bug:
+      // http://support.microsoft.com/kb/979567
+      OnError(FROM_HERE, hr);
+    }
   }
 }
 
-void VideoCaptureDeviceMFWin::OnEvent(IMFMediaEvent* media_event) {
-  base::AutoLock lock(lock_);
-
-  GUID event_type;
-  HRESULT hr = media_event->GetExtendedType(&event_type);
-
-  if (SUCCEEDED(hr) && event_type == MF_CAPTURE_ENGINE_ERROR)
-    media_event->GetStatus(&hr);
-
-  if (FAILED(hr))
-    OnError(FROM_HERE, hr);
-}
-
-void VideoCaptureDeviceMFWin::OnError(const Location& from_here, HRESULT hr) {
+void VideoCaptureDeviceMFWin::OnError(const base::Location& from_here,
+                                      HRESULT hr) {
   if (client_.get()) {
     client_->OnError(
         from_here,
@@ -765,4 +316,4 @@
   }
 }
 
-}  // namespace media
\ No newline at end of file
+}  // namespace media
diff --git a/media/capture/video/win/video_capture_device_mf_win.h b/media/capture/video/win/video_capture_device_mf_win.h
index 8cc5f58..93534f9 100644
--- a/media/capture/video/win/video_capture_device_mf_win.h
+++ b/media/capture/video/win/video_capture_device_mf_win.h
@@ -3,13 +3,12 @@
 // found in the LICENSE file.
 
 // Windows specific implementation of VideoCaptureDevice.
-// MediaFoundation is used for capturing. MediaFoundation provides its own
-// threads for capturing.
+// DirectShow is used for capturing. DirectShow provide its own threads
+// for capturing.
 
 #ifndef MEDIA_CAPTURE_VIDEO_WIN_VIDEO_CAPTURE_DEVICE_MF_WIN_H_
 #define MEDIA_CAPTURE_VIDEO_WIN_VIDEO_CAPTURE_DEVICE_MF_WIN_H_
 
-#include <mfcaptureengine.h>
 #include <mfidl.h>
 #include <mfreadwrite.h>
 #include <stdint.h>
@@ -17,9 +16,9 @@
 
 #include <vector>
 
-#include "base/callback_forward.h"
 #include "base/macros.h"
 #include "base/sequence_checker.h"
+#include "base/synchronization/lock.h"
 #include "media/capture/capture_export.h"
 #include "media/capture/video/video_capture_device.h"
 
@@ -31,12 +30,10 @@
 
 namespace media {
 
-class MFVideoCallback;
+class MFReaderCallback;
 
-const DWORD kPreferredVideoPreviewStream = static_cast<DWORD>(
-    MF_CAPTURE_ENGINE_PREFERRED_SOURCE_STREAM_FOR_VIDEO_PREVIEW);
-const DWORD kPreferredPhotoStream =
-    static_cast<DWORD>(MF_CAPTURE_ENGINE_PREFERRED_SOURCE_STREAM_FOR_PHOTO);
+const DWORD kFirstVideoStream =
+    static_cast<DWORD>(MF_SOURCE_READER_FIRST_VIDEO_STREAM);
 
 class CAPTURE_EXPORT VideoCaptureDeviceMFWin : public VideoCaptureDevice {
  public:
@@ -54,10 +51,6 @@
       const VideoCaptureParams& params,
       std::unique_ptr<VideoCaptureDevice::Client> client) override;
   void StopAndDeAllocate() override;
-  void TakePhoto(TakePhotoCallback callback) override;
-  void GetPhotoState(GetPhotoStateCallback callback) override;
-  void SetPhotoOptions(mojom::PhotoSettingsPtr settings,
-                       SetPhotoOptionsCallback callback) override;
 
   // Captured new video data.
   void OnIncomingCapturedData(const uint8_t* data,
@@ -65,33 +58,19 @@
                               int rotation,
                               base::TimeTicks reference_time,
                               base::TimeDelta timestamp);
-  void OnEvent(IMFMediaEvent* media_event);
-
-  using CreateMFPhotoCallbackCB =
-      base::Callback<scoped_refptr<IMFCaptureEngineOnSampleCallback>(
-          VideoCaptureDevice::TakePhotoCallback callback,
-          VideoCaptureFormat format)>;
-
-  void set_create_mf_photo_callback_for_testing(CreateMFPhotoCallbackCB cb) {
-    create_mf_photo_callback_ = cb;
-  }
 
  private:
   void OnError(const base::Location& from_here, HRESULT hr);
 
   VideoCaptureDeviceDescriptor descriptor_;
-  CreateMFPhotoCallbackCB create_mf_photo_callback_;
-  scoped_refptr<MFVideoCallback> video_callback_;
+  Microsoft::WRL::ComPtr<IMFActivate> device_;
+  scoped_refptr<MFReaderCallback> callback_;
 
-  // Guards the below variables from concurrent access between methods running
-  // on |sequence_checker_| and calls to OnIncomingCapturedData() and OnEvent()
-  // made by MediaFoundation on threads outside of our control.
-  base::Lock lock_;
-
+  base::Lock lock_;  // Used to guard the below variables.
   std::unique_ptr<VideoCaptureDevice::Client> client_;
-  Microsoft::WRL::ComPtr<IMFCaptureEngine> engine_;
-  VideoCaptureFormat capture_video_format_;
-  bool is_started_;
+  Microsoft::WRL::ComPtr<IMFSourceReader> reader_;
+  VideoCaptureFormat capture_format_;
+  bool capture_;
 
   SEQUENCE_CHECKER(sequence_checker_);