1 /*
2  *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #ifndef MODULES_VIDEO_CAPTURE_MAIN_SOURCE_WINDOWS_SINK_FILTER_DS_H_
12 #define MODULES_VIDEO_CAPTURE_MAIN_SOURCE_WINDOWS_SINK_FILTER_DS_H_
13 
14 #include <dshow.h>
15 
16 #include <atomic>
17 #include <memory>
18 #include <vector>
19 
20 #include "modules/video_capture/video_capture_impl.h"
21 #include "modules/video_capture/windows/help_functions_ds.h"
22 #include "rtc_base/thread_annotations.h"
23 #include "rtc_base/thread_checker.h"
24 
25 namespace webrtc {
26 namespace videocapturemodule {
27 // forward declarations
28 class CaptureSinkFilter;
29 
30 // Input pin for camera input
31 // Implements IMemInputPin, IPin.
32 class CaptureInputPin : public IMemInputPin, public IPin {
33  public:
34   CaptureInputPin(CaptureSinkFilter* filter);
35 
36   HRESULT SetRequestedCapability(const VideoCaptureCapability& capability);
37 
38   // Notifications from the filter.
39   void OnFilterActivated();
40   void OnFilterDeactivated();
41 
42  protected:
43   virtual ~CaptureInputPin();
44 
45  private:
46   CaptureSinkFilter* Filter() const;
47 
48   HRESULT AttemptConnection(IPin* receive_pin, const AM_MEDIA_TYPE* media_type);
49   std::vector<AM_MEDIA_TYPE*> DetermineCandidateFormats(
50       IPin* receive_pin,
51       const AM_MEDIA_TYPE* media_type);
52   void ClearAllocator(bool decommit);
53   HRESULT CheckDirection(IPin* pin) const;
54 
55   // IUnknown
56   STDMETHOD(QueryInterface)(REFIID riid, void** ppv) override;
57 
58   // clang-format off
59   // clang isn't sure what to do with the longer STDMETHOD() function
60   // declarations.
61 
62   // IPin
63   STDMETHOD(Connect)(IPin* receive_pin,
64                      const AM_MEDIA_TYPE* media_type) override;
65   STDMETHOD(ReceiveConnection)(IPin* connector,
66                                const AM_MEDIA_TYPE* media_type) override;
67   STDMETHOD(Disconnect)() override;
68   STDMETHOD(ConnectedTo)(IPin** pin) override;
69   STDMETHOD(ConnectionMediaType)(AM_MEDIA_TYPE* media_type) override;
70   STDMETHOD(QueryPinInfo)(PIN_INFO* info) override;
71   STDMETHOD(QueryDirection)(PIN_DIRECTION* pin_dir) override;
72   STDMETHOD(QueryId)(LPWSTR* id) override;
73   STDMETHOD(QueryAccept)(const AM_MEDIA_TYPE* media_type) override;
74   STDMETHOD(EnumMediaTypes)(IEnumMediaTypes** types) override;
75   STDMETHOD(QueryInternalConnections)(IPin** pins, ULONG* count) override;
76   STDMETHOD(EndOfStream)() override;
77   STDMETHOD(BeginFlush)() override;
78   STDMETHOD(EndFlush)() override;
79   STDMETHOD(NewSegment)(REFERENCE_TIME start, REFERENCE_TIME stop,
80                         double rate) override;
81 
82   // IMemInputPin
83   STDMETHOD(GetAllocator)(IMemAllocator** allocator) override;
84   STDMETHOD(NotifyAllocator)(IMemAllocator* allocator, BOOL read_only) override;
85   STDMETHOD(GetAllocatorRequirements)(ALLOCATOR_PROPERTIES* props) override;
86   STDMETHOD(Receive)(IMediaSample* sample) override;
87   STDMETHOD(ReceiveMultiple)(IMediaSample** samples, long count,
88                              long* processed) override;
89   STDMETHOD(ReceiveCanBlock)() override;
90   // clang-format on
91 
92   rtc::ThreadChecker main_checker_;
93   rtc::ThreadChecker capture_checker_;
94 
95   VideoCaptureCapability requested_capability_ RTC_GUARDED_BY(main_checker_);
96   // Accessed on the main thread when Filter()->IsStopped() (capture thread not
97   // running), otherwise accessed on the capture thread.
98   VideoCaptureCapability resulting_capability_;
99   DWORD capture_thread_id_ = 0;
100   rtc::scoped_refptr<IMemAllocator> allocator_ RTC_GUARDED_BY(main_checker_);
101   rtc::scoped_refptr<IPin> receive_pin_ RTC_GUARDED_BY(main_checker_);
102   std::atomic_bool flushing_{false};
103   std::atomic_bool runtime_error_{false};
104   // Holds a referenceless pointer to the owning filter, the name and
105   // direction of the pin. The filter pointer can be considered const.
106   PIN_INFO info_ = {};
107   AM_MEDIA_TYPE media_type_ RTC_GUARDED_BY(main_checker_) = {};
108 };
109 
110 // Implement IBaseFilter (including IPersist and IMediaFilter).
111 class CaptureSinkFilter : public IBaseFilter {
112  public:
113   CaptureSinkFilter(VideoCaptureImpl* capture_observer);
114 
115   HRESULT SetRequestedCapability(const VideoCaptureCapability& capability);
116 
117   // Called on the capture thread.
118   void ProcessCapturedFrame(unsigned char* buffer,
119                             size_t length,
120                             const VideoCaptureCapability& frame_info);
121 
122   void NotifyEvent(long code, LONG_PTR param1, LONG_PTR param2);
123   bool IsStopped() const;
124 
125   //  IUnknown
126   STDMETHOD(QueryInterface)(REFIID riid, void** ppv) override;
127 
128   // IPersist
129   STDMETHOD(GetClassID)(CLSID* clsid) override;
130 
131   // IMediaFilter.
132   STDMETHOD(GetState)(DWORD msecs, FILTER_STATE* state) override;
133   STDMETHOD(SetSyncSource)(IReferenceClock* clock) override;
134   STDMETHOD(GetSyncSource)(IReferenceClock** clock) override;
135   STDMETHOD(Pause)() override;
136   STDMETHOD(Run)(REFERENCE_TIME start) override;
137   STDMETHOD(Stop)() override;
138 
139   // IBaseFilter
140   STDMETHOD(EnumPins)(IEnumPins** pins) override;
141   STDMETHOD(FindPin)(LPCWSTR id, IPin** pin) override;
142   STDMETHOD(QueryFilterInfo)(FILTER_INFO* info) override;
143   STDMETHOD(JoinFilterGraph)(IFilterGraph* graph, LPCWSTR name) override;
144   STDMETHOD(QueryVendorInfo)(LPWSTR* vendor_info) override;
145 
146  protected:
147   virtual ~CaptureSinkFilter();
148 
149  private:
150   rtc::ThreadChecker main_checker_;
151   const rtc::scoped_refptr<ComRefCount<CaptureInputPin>> input_pin_;
152   VideoCaptureImpl* const capture_observer_;
153   FILTER_INFO info_ RTC_GUARDED_BY(main_checker_) = {};
154   // Set/cleared in JoinFilterGraph. The filter must be stopped (no capture)
155   // at that time, so no lock is required. While the state is not stopped,
156   // the sink will be used from the capture thread.
157   IMediaEventSink* sink_ = nullptr;
158   FILTER_STATE state_ RTC_GUARDED_BY(main_checker_) = State_Stopped;
159 };
160 }  // namespace videocapturemodule
161 }  // namespace webrtc
162 #endif  // MODULES_VIDEO_CAPTURE_MAIN_SOURCE_WINDOWS_SINK_FILTER_DS_H_
163