1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Windows specific implementation of VideoCaptureDevice.
6 // MediaFoundation is used for capturing. MediaFoundation provides its own
7 // threads for capturing.
8 
9 #ifndef MEDIA_CAPTURE_VIDEO_WIN_VIDEO_CAPTURE_DEVICE_MF_WIN_H_
10 #define MEDIA_CAPTURE_VIDEO_WIN_VIDEO_CAPTURE_DEVICE_MF_WIN_H_
11 
12 #include <mfcaptureengine.h>
13 #include <mfidl.h>
14 #include <mfreadwrite.h>
15 #include <stdint.h>
16 #include <strmif.h>
17 #include <wrl/client.h>
18 
19 #include <vector>
20 
21 #include "base/callback_forward.h"
22 #include "base/macros.h"
23 #include "base/optional.h"
24 #include "base/sequence_checker.h"
25 #include "media/capture/capture_export.h"
26 #include "media/capture/video/video_capture_device.h"
27 #include "media/capture/video/win/capability_list_win.h"
28 #include "media/capture/video/win/metrics.h"
29 #include "media/capture/video/win/video_capture_dxgi_device_manager.h"
30 
31 interface IMFSourceReader;
32 
33 namespace base {
34 class Location;
35 }  // namespace base
36 
37 namespace media {
38 
39 class MFVideoCallback;
40 
41 class CAPTURE_EXPORT VideoCaptureDeviceMFWin : public VideoCaptureDevice {
42  public:
43   static bool GetPixelFormatFromMFSourceMediaSubtype(const GUID& guid,
44                                                      bool use_hardware_format,
45                                                      VideoPixelFormat* format);
46   static VideoCaptureControlSupport GetControlSupport(
47       Microsoft::WRL::ComPtr<IMFMediaSource> source);
48 
49   explicit VideoCaptureDeviceMFWin(
50       const VideoCaptureDeviceDescriptor& device_descriptor,
51       Microsoft::WRL::ComPtr<IMFMediaSource> source,
52       scoped_refptr<VideoCaptureDXGIDeviceManager> dxgi_device_manager);
53   explicit VideoCaptureDeviceMFWin(
54       const VideoCaptureDeviceDescriptor& device_descriptor,
55       Microsoft::WRL::ComPtr<IMFMediaSource> source,
56       scoped_refptr<VideoCaptureDXGIDeviceManager> dxgi_device_manager,
57       Microsoft::WRL::ComPtr<IMFCaptureEngine> engine);
58 
59   ~VideoCaptureDeviceMFWin() override;
60 
61   // Opens the device driver for this device.
62   bool Init();
63 
64   // VideoCaptureDevice implementation.
65   void AllocateAndStart(
66       const VideoCaptureParams& params,
67       std::unique_ptr<VideoCaptureDevice::Client> client) override;
68   void StopAndDeAllocate() override;
69   void TakePhoto(TakePhotoCallback callback) override;
70   void GetPhotoState(GetPhotoStateCallback callback) override;
71   void SetPhotoOptions(mojom::PhotoSettingsPtr settings,
72                        SetPhotoOptionsCallback callback) override;
73 
74   // Captured new video data.
75   void OnIncomingCapturedData(const uint8_t* data,
76                               int length,
77                               base::TimeTicks reference_time,
78                               base::TimeDelta timestamp);
79   void OnFrameDropped(VideoCaptureFrameDropReason reason);
80   void OnEvent(IMFMediaEvent* media_event);
81 
82   using CreateMFPhotoCallbackCB =
83       base::RepeatingCallback<scoped_refptr<IMFCaptureEngineOnSampleCallback>(
84           VideoCaptureDevice::TakePhotoCallback callback,
85           VideoCaptureFormat format)>;
86 
get_use_photo_stream_to_take_photo_for_testing()87   bool get_use_photo_stream_to_take_photo_for_testing() {
88     return !photo_capabilities_.empty();
89   }
90 
set_create_mf_photo_callback_for_testing(CreateMFPhotoCallbackCB cb)91   void set_create_mf_photo_callback_for_testing(CreateMFPhotoCallbackCB cb) {
92     create_mf_photo_callback_ = cb;
93   }
94 
set_max_retry_count_for_testing(int max_retry_count)95   void set_max_retry_count_for_testing(int max_retry_count) {
96     max_retry_count_ = max_retry_count;
97   }
98 
set_retry_delay_in_ms_for_testing(int retry_delay_in_ms)99   void set_retry_delay_in_ms_for_testing(int retry_delay_in_ms) {
100     retry_delay_in_ms_ = retry_delay_in_ms;
101   }
102 
set_dxgi_device_manager_for_testing(scoped_refptr<VideoCaptureDXGIDeviceManager> dxgi_device_manager)103   void set_dxgi_device_manager_for_testing(
104       scoped_refptr<VideoCaptureDXGIDeviceManager> dxgi_device_manager) {
105     dxgi_device_manager_ = std::move(dxgi_device_manager);
106   }
107 
camera_rotation()108   base::Optional<int> camera_rotation() const { return camera_rotation_; }
109 
110  private:
111   HRESULT ExecuteHresultCallbackWithRetries(
112       base::RepeatingCallback<HRESULT()> callback,
113       MediaFoundationFunctionRequiringRetry which_function);
114   HRESULT GetDeviceStreamCount(IMFCaptureSource* source, DWORD* count);
115   HRESULT GetDeviceStreamCategory(
116       IMFCaptureSource* source,
117       DWORD stream_index,
118       MF_CAPTURE_ENGINE_STREAM_CATEGORY* stream_category);
119   HRESULT GetAvailableDeviceMediaType(IMFCaptureSource* source,
120                                       DWORD stream_index,
121                                       DWORD media_type_index,
122                                       IMFMediaType** type);
123 
124   HRESULT FillCapabilities(IMFCaptureSource* source,
125                            bool photo,
126                            CapabilityList* capabilities);
127   void OnError(VideoCaptureError error,
128                const base::Location& from_here,
129                HRESULT hr);
130   void OnError(VideoCaptureError error,
131                const base::Location& from_here,
132                const char* message);
133   void SendOnStartedIfNotYetSent();
134   HRESULT WaitOnCaptureEvent(GUID capture_event_guid);
135 
136   VideoFacingMode facing_mode_;
137   CreateMFPhotoCallbackCB create_mf_photo_callback_;
138   scoped_refptr<MFVideoCallback> video_callback_;
139   bool is_initialized_;
140   int max_retry_count_;
141   int retry_delay_in_ms_;
142 
143   // Guards the below variables from concurrent access between methods running
144   // on |sequence_checker_| and calls to OnIncomingCapturedData() and OnEvent()
145   // made by MediaFoundation on threads outside of our control.
146   base::Lock lock_;
147 
148   std::unique_ptr<VideoCaptureDevice::Client> client_;
149   const Microsoft::WRL::ComPtr<IMFMediaSource> source_;
150   Microsoft::WRL::ComPtr<IAMCameraControl> camera_control_;
151   Microsoft::WRL::ComPtr<IAMVideoProcAmp> video_control_;
152   Microsoft::WRL::ComPtr<IMFCaptureEngine> engine_;
153   std::unique_ptr<CapabilityWin> selected_video_capability_;
154   CapabilityList photo_capabilities_;
155   std::unique_ptr<CapabilityWin> selected_photo_capability_;
156   bool is_started_;
157   bool has_sent_on_started_to_client_;
158   // These flags keep the manual/auto mode between cycles of SetPhotoOptions().
159   bool exposure_mode_manual_;
160   bool focus_mode_manual_;
161   bool white_balance_mode_manual_;
162   base::queue<TakePhotoCallback> video_stream_take_photo_callbacks_;
163   base::WaitableEvent capture_initialize_;
164   base::WaitableEvent capture_error_;
165   scoped_refptr<VideoCaptureDXGIDeviceManager> dxgi_device_manager_;
166   base::Optional<int> camera_rotation_;
167 
168   SEQUENCE_CHECKER(sequence_checker_);
169 
170   DISALLOW_IMPLICIT_CONSTRUCTORS(VideoCaptureDeviceMFWin);
171 };
172 
173 }  // namespace media
174 
175 #endif  // MEDIA_CAPTURE_VIDEO_WIN_VIDEO_CAPTURE_DEVICE_MF_WIN_H_
176