#pragma once
#ifndef CAMERA_CAPTURE_DSHOW_H
#define CAMERA_CAPTURE_DSHOW_H
#if defined(_WIN32) || defined(_MSC_VER)
#include "ccap_imp.h"
#include <atomic>
#include <deque>
#include <dshow.h>
#include <mutex>
#ifdef _MSC_VER
#pragma include_alias("dxtrans.h", "qedit.h")
#endif
#define __IDxtCompositor_INTERFACE_DEFINED__
#define __IDxtAlphaSetter_INTERFACE_DEFINED__
#define __IDxtJpeg_INTERFACE_DEFINED__
#define __IDxtKey_INTERFACE_DEFINED__
#include <aviriff.h>
#include <windows.h>
MIDL_INTERFACE("0579154A-2B53-4994-B0D0-E773148EFF85")
ISampleGrabberCB : public IUnknown {
public:
virtual HRESULT STDMETHODCALLTYPE SampleCB(double SampleTime, IMediaSample* pSample) = 0;
virtual HRESULT STDMETHODCALLTYPE BufferCB(double SampleTime, BYTE* pBuffer, long BufferLen) = 0;
};
MIDL_INTERFACE("6B652FFF-11FE-4fce-92AD-0266B5D7C78F")
ISampleGrabber : public IUnknown {
public:
virtual HRESULT STDMETHODCALLTYPE SetOneShot(BOOL OneShot) = 0;
virtual HRESULT STDMETHODCALLTYPE SetMediaType(const AM_MEDIA_TYPE* pType) = 0;
virtual HRESULT STDMETHODCALLTYPE GetConnectedMediaType(AM_MEDIA_TYPE * pType) = 0;
virtual HRESULT STDMETHODCALLTYPE SetBufferSamples(BOOL BufferThem) = 0;
virtual HRESULT STDMETHODCALLTYPE GetCurrentBuffer(
long* pBufferSize,
long* pBuffer) = 0;
virtual HRESULT STDMETHODCALLTYPE GetCurrentSample(
IMediaSample * *ppSample) = 0;
virtual HRESULT STDMETHODCALLTYPE SetCallback(ISampleGrabberCB * pCallback, long WhichMethodToCallback) = 0;
};
namespace ccap {
#ifdef CCAP_ENABLE_FILE_PLAYBACK
class FileReaderWindows;
#endif
class ProviderDirectShow : public ProviderImp, public ISampleGrabberCB {
public:
ProviderDirectShow();
~ProviderDirectShow() override;
std::vector<std::string> findDeviceNames() override;
bool open(std::string_view deviceName) override;
bool isOpened() const override;
std::optional<DeviceInfo> getDeviceInfo() const override;
void close() override;
bool start() override;
void stop() override;
bool isStarted() const override;
HRESULT STDMETHODCALLTYPE SampleCB(double SampleTime, IMediaSample* pSample) override;
HRESULT STDMETHODCALLTYPE BufferCB(double SampleTime, BYTE* pBuffer, long BufferLen) override;
bool setFileProperty(PropertyName prop, double value) override;
double getFileProperty(PropertyName prop) const override;
using ProviderImp::getFreeFrame;
using ProviderImp::newFrameAvailable;
inline FrameOrientation frameOrientation() const { return m_frameOrientation; }
private:
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, _COM_Outptr_ void __RPC_FAR * __RPC_FAR * ppvObject) override;
ULONG STDMETHODCALLTYPE AddRef(void) override;
ULONG STDMETHODCALLTYPE Release(void) override;
bool setup();
void enumerateDevices(std::function<bool(IMoniker* moniker, std::string_view)> callback);
bool buildGraph();
bool createStream();
bool setGrabberOutputSubtype(GUID subtype);
struct MediaInfo {
~MediaInfo();
IAMStreamConfig* streamConfig = nullptr;
std::vector<AM_MEDIA_TYPE*> mediaTypes;
std::vector<AM_MEDIA_TYPE*> videoMediaTypes;
};
std::unique_ptr<MediaInfo> enumerateMediaInfo(
std::function<bool(AM_MEDIA_TYPE* mediaType, const char* name, PixelFormat pixelFormat, const DeviceInfo::Resolution& resolution)>
callback);
bool openCamera(std::string_view deviceName);
bool openFile(std::string_view filePath);
private:
IGraphBuilder* m_graph = nullptr;
ICaptureGraphBuilder2* m_captureBuilder = nullptr;
IBaseFilter* m_deviceFilter = nullptr;
IBaseFilter* m_sampleGrabberFilter = nullptr;
IBaseFilter* m_dstNullFilter = nullptr;
ISampleGrabber* m_sampleGrabber = nullptr;
IMediaControl* m_mediaControl = nullptr;
std::string m_deviceName;
std::vector<std::string> m_allDeviceNames;
std::chrono::steady_clock::time_point m_startTime{};
FrameOrientation m_inputOrientation = FrameOrientation::TopToBottom;
bool m_firstFrameArrived = false;
bool m_didSetup{ false };
bool m_isOpened{ false };
bool m_isRunning{ false };
std::mutex m_callbackMutex;
#ifdef CCAP_ENABLE_FILE_PLAYBACK
std::unique_ptr<FileReaderWindows> m_fileReader;
#endif
};
ProviderImp* createProviderDirectShow();
}
#endif
#endif