blob: b0fabda3cdea55815d4a784f81f0510bd47212d7 [file] [log] [blame]
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef MODULES_VIDEO_CAPTURE_MAIN_SOURCE_WINDOWS_SINK_FILTER_DS_H_
#define MODULES_VIDEO_CAPTURE_MAIN_SOURCE_WINDOWS_SINK_FILTER_DS_H_
#include <dshow.h>
#include <atomic>
#include <memory>
#include <vector>
#include "api/sequence_checker.h"
#include "modules/video_capture/video_capture_impl.h"
#include "modules/video_capture/windows/help_functions_ds.h"
#include "rtc_base/thread_annotations.h"
namespace webrtc {
namespace videocapturemodule {
// forward declarations
class CaptureSinkFilter;
// Input pin for camera input
// Implements IMemInputPin, IPin.
class CaptureInputPin : public IMemInputPin, public IPin {
public:
CaptureInputPin(CaptureSinkFilter* filter);
HRESULT SetRequestedCapability(const VideoCaptureCapability& capability);
// Notifications from the filter.
void OnFilterActivated();
void OnFilterDeactivated();
protected:
virtual ~CaptureInputPin();
private:
CaptureSinkFilter* Filter() const;
HRESULT AttemptConnection(IPin* receive_pin, const AM_MEDIA_TYPE* media_type);
std::vector<AM_MEDIA_TYPE*> DetermineCandidateFormats(
IPin* receive_pin,
const AM_MEDIA_TYPE* media_type);
void ClearAllocator(bool decommit);
HRESULT CheckDirection(IPin* pin) const;
// IUnknown
STDMETHOD(QueryInterface)(REFIID riid, void** ppv) override;
// clang-format off
// clang isn't sure what to do with the longer STDMETHOD() function
// declarations.
// IPin
STDMETHOD(Connect)(IPin* receive_pin,
const AM_MEDIA_TYPE* media_type) override;
STDMETHOD(ReceiveConnection)(IPin* connector,
const AM_MEDIA_TYPE* media_type) override;
STDMETHOD(Disconnect)() override;
STDMETHOD(ConnectedTo)(IPin** pin) override;
STDMETHOD(ConnectionMediaType)(AM_MEDIA_TYPE* media_type) override;
STDMETHOD(QueryPinInfo)(PIN_INFO* info) override;
STDMETHOD(QueryDirection)(PIN_DIRECTION* pin_dir) override;
STDMETHOD(QueryId)(LPWSTR* id) override;
STDMETHOD(QueryAccept)(const AM_MEDIA_TYPE* media_type) override;
STDMETHOD(EnumMediaTypes)(IEnumMediaTypes** types) override;
STDMETHOD(QueryInternalConnections)(IPin** pins, ULONG* count) override;
STDMETHOD(EndOfStream)() override;
STDMETHOD(BeginFlush)() override;
STDMETHOD(EndFlush)() override;
STDMETHOD(NewSegment)(REFERENCE_TIME start, REFERENCE_TIME stop,
double rate) override;
// IMemInputPin
STDMETHOD(GetAllocator)(IMemAllocator** allocator) override;
STDMETHOD(NotifyAllocator)(IMemAllocator* allocator, BOOL read_only) override;
STDMETHOD(GetAllocatorRequirements)(ALLOCATOR_PROPERTIES* props) override;
STDMETHOD(Receive)(IMediaSample* sample) override;
STDMETHOD(ReceiveMultiple)(IMediaSample** samples, long count,
long* processed) override;
STDMETHOD(ReceiveCanBlock)() override;
// clang-format on
SequenceChecker main_checker_;
SequenceChecker capture_checker_;
VideoCaptureCapability requested_capability_ RTC_GUARDED_BY(main_checker_);
// Accessed on the main thread when Filter()->IsStopped() (capture thread not
// running), otherwise accessed on the capture thread.
VideoCaptureCapability resulting_capability_;
DWORD capture_thread_id_ = 0;
rtc::scoped_refptr<IMemAllocator> allocator_ RTC_GUARDED_BY(main_checker_);
rtc::scoped_refptr<IPin> receive_pin_ RTC_GUARDED_BY(main_checker_);
std::atomic_bool flushing_{false};
std::atomic_bool runtime_error_{false};
// Holds a referenceless pointer to the owning filter, the name and
// direction of the pin. The filter pointer can be considered const.
PIN_INFO info_ = {};
AM_MEDIA_TYPE media_type_ RTC_GUARDED_BY(main_checker_) = {};
};
// Implement IBaseFilter (including IPersist and IMediaFilter).
class CaptureSinkFilter : public IBaseFilter {
public:
CaptureSinkFilter(VideoCaptureImpl* capture_observer);
HRESULT SetRequestedCapability(const VideoCaptureCapability& capability);
// Called on the capture thread.
void ProcessCapturedFrame(unsigned char* buffer,
size_t length,
const VideoCaptureCapability& frame_info);
void NotifyEvent(long code, LONG_PTR param1, LONG_PTR param2);
bool IsStopped() const;
// IUnknown
STDMETHOD(QueryInterface)(REFIID riid, void** ppv) override;
// IPersist
STDMETHOD(GetClassID)(CLSID* clsid) override;
// IMediaFilter.
STDMETHOD(GetState)(DWORD msecs, FILTER_STATE* state) override;
STDMETHOD(SetSyncSource)(IReferenceClock* clock) override;
STDMETHOD(GetSyncSource)(IReferenceClock** clock) override;
STDMETHOD(Pause)() override;
STDMETHOD(Run)(REFERENCE_TIME start) override;
STDMETHOD(Stop)() override;
// IBaseFilter
STDMETHOD(EnumPins)(IEnumPins** pins) override;
STDMETHOD(FindPin)(LPCWSTR id, IPin** pin) override;
STDMETHOD(QueryFilterInfo)(FILTER_INFO* info) override;
STDMETHOD(JoinFilterGraph)(IFilterGraph* graph, LPCWSTR name) override;
STDMETHOD(QueryVendorInfo)(LPWSTR* vendor_info) override;
protected:
virtual ~CaptureSinkFilter();
private:
SequenceChecker main_checker_;
const rtc::scoped_refptr<ComRefCount<CaptureInputPin>> input_pin_;
VideoCaptureImpl* const capture_observer_;
FILTER_INFO info_ RTC_GUARDED_BY(main_checker_) = {};
// Set/cleared in JoinFilterGraph. The filter must be stopped (no capture)
// at that time, so no lock is required. While the state is not stopped,
// the sink will be used from the capture thread.
IMediaEventSink* sink_ = nullptr;
FILTER_STATE state_ RTC_GUARDED_BY(main_checker_) = State_Stopped;
};
} // namespace videocapturemodule
} // namespace webrtc
#endif // MODULES_VIDEO_CAPTURE_MAIN_SOURCE_WINDOWS_SINK_FILTER_DS_H_