diff --git a/modules/videoio/src/cap_msmf.cpp b/modules/videoio/src/cap_msmf.cpp index 393aa93b6c..56ac29e746 100644 --- a/modules/videoio/src/cap_msmf.cpp +++ b/modules/videoio/src/cap_msmf.cpp @@ -52,9 +52,6 @@ #undef WINVER #define WINVER _WIN32_WINNT_WIN8 #endif -#if defined _MSC_VER && _MSC_VER >= 1600 - #define HAVE_CONCURRENCY -#endif #include #include #include @@ -97,15 +94,6 @@ struct IMFAttributes; namespace { -template void SafeRelease(T **ppT) -{ - if (*ppT) - { - (*ppT)->Release(); - *ppT = NULL; - } -} - #ifdef _DEBUG void DPOprintOut(const wchar_t *format, ...) { @@ -138,166 +126,154 @@ void DPOprintOut(const wchar_t *format, ...) #define DebugPrintOut(...) void() #endif -#include "cap_msmf.hpp" +template +class ComPtr +{ +public: + ComPtr() throw() + { + } + ComPtr(T* lp) throw() + { + p = lp; + } + ComPtr(_In_ const ComPtr& lp) throw() + { + p = lp.p; + } + virtual ~ComPtr() + { + } + + T** operator&() throw() + { + assert(p == NULL); + return p.operator&(); + } + T* operator->() const throw() + { + assert(p != NULL); + return p.operator->(); + } + bool operator!() const throw() + { + return p.operator==(NULL); + } + bool operator==(_In_opt_ T* pT) const throw() + { + return p.operator==(pT); + } + bool operator!=(_In_opt_ T* pT) const throw() + { + return p.operator!=(pT); + } + operator bool() + { + return p.operator!=(NULL); + } + + T* const* GetAddressOf() const throw() + { + return &p; + } + + T** GetAddressOf() throw() + { + return &p; + } + + T** ReleaseAndGetAddressOf() throw() + { + p.Release(); + return &p; + } + + T* Get() const throw() + { + return p; + } + + // Attach to an existing interface (does not AddRef) + void Attach(_In_opt_ T* p2) throw() + { + p.Attach(p2); + } + // Detach the interface (does not Release) + T* Detach() throw() + { + return p.Detach(); + } + _Check_return_ HRESULT CopyTo(_Deref_out_opt_ T** ppT) throw() + { + assert(ppT != NULL); + if (ppT == NULL) + return E_POINTER; + *ppT = p; + if (p != NULL) + p->AddRef(); + return S_OK; + } + + void Reset() + { + p.Release(); + } + + // query for U interface + template + HRESULT As(_Inout_ U** lp) const throw() + { + return p->QueryInterface(__uuidof(U), reinterpret_cast(lp)); + } + // query for U interface + template + HRESULT As(_Out_ ComPtr* lp) const throw() + { + return p->QueryInterface(__uuidof(U), reinterpret_cast(lp->ReleaseAndGetAddressOf())); + } +private: + _COM_SMARTPTR_TYPEDEF(T, __uuidof(T)); + TPtr p; +}; + +#define _ComPtr ComPtr // Structure for collecting info about types of video, which are supported by current video device struct MediaType { unsigned int MF_MT_FRAME_SIZE; - unsigned int height; - unsigned int width; + UINT32 height; + UINT32 width; unsigned int MF_MT_YUV_MATRIX; unsigned int MF_MT_VIDEO_LIGHTING; int MF_MT_DEFAULT_STRIDE; // stride is negative if image is bottom-up unsigned int MF_MT_VIDEO_CHROMA_SITING; GUID MF_MT_AM_FORMAT_TYPE; - wchar_t *pMF_MT_AM_FORMAT_TYPEName; + LPCWSTR pMF_MT_AM_FORMAT_TYPEName; unsigned int MF_MT_FIXED_SIZE_SAMPLES; unsigned int MF_MT_VIDEO_NOMINAL_RANGE; - unsigned int MF_MT_FRAME_RATE_NUMERATOR; - unsigned int MF_MT_FRAME_RATE_DENOMINATOR; - unsigned int MF_MT_PIXEL_ASPECT_RATIO; - unsigned int MF_MT_PIXEL_ASPECT_RATIO_low; + UINT32 MF_MT_FRAME_RATE_NUMERATOR; + UINT32 MF_MT_FRAME_RATE_DENOMINATOR; + UINT32 MF_MT_PIXEL_ASPECT_RATIO; + UINT32 MF_MT_PIXEL_ASPECT_RATIO_low; unsigned int MF_MT_ALL_SAMPLES_INDEPENDENT; - unsigned int MF_MT_FRAME_RATE_RANGE_MIN; - unsigned int MF_MT_FRAME_RATE_RANGE_MIN_low; + UINT32 MF_MT_FRAME_RATE_RANGE_MIN; + UINT32 MF_MT_FRAME_RATE_RANGE_MIN_low; unsigned int MF_MT_SAMPLE_SIZE; unsigned int MF_MT_VIDEO_PRIMARIES; unsigned int MF_MT_INTERLACE_MODE; - unsigned int MF_MT_FRAME_RATE_RANGE_MAX; - unsigned int MF_MT_FRAME_RATE_RANGE_MAX_low; + UINT32 MF_MT_FRAME_RATE_RANGE_MAX; + UINT32 MF_MT_FRAME_RATE_RANGE_MAX_low; GUID MF_MT_MAJOR_TYPE; GUID MF_MT_SUBTYPE; - wchar_t *pMF_MT_MAJOR_TYPEName; - wchar_t *pMF_MT_SUBTYPEName; + LPCWSTR pMF_MT_MAJOR_TYPEName; + LPCWSTR pMF_MT_SUBTYPEName; MediaType(); + MediaType(IMFMediaType *pType); ~MediaType(); void Clear(); }; -/// Class for parsing info from IMFMediaType into the local MediaType -class FormatReader -{ -public: - static MediaType Read(IMFMediaType *pType); - ~FormatReader(void); -private: - FormatReader(void); -}; - -DWORD WINAPI MainThreadFunction( LPVOID lpParam ); -typedef void(*emergensyStopEventCallback)(int, void *); - -class RawImage -{ -public: - ~RawImage(void); - // Function of creation of the instance of the class - static long CreateInstance(RawImage **ppRImage,unsigned int size); - void setCopy(const BYTE * pSampleBuffer); - void fastCopy(const BYTE * pSampleBuffer); - unsigned char * getpPixels(); - bool isNew(); - unsigned int getSize(); -private: - bool ri_new; - unsigned int ri_size; - unsigned char *ri_pixels; - RawImage(unsigned int size); -}; - -class ImageGrabberCallback : public IMFSampleGrabberSinkCallback -{ -public: - void pauseGrabbing(); - void resumeGrabbing(); - RawImage *getRawImage(); - // IMFClockStateSink methods - STDMETHODIMP OnClockStart(MFTIME hnsSystemTime, LONGLONG llClockStartOffset); - STDMETHODIMP OnClockStop(MFTIME hnsSystemTime); - STDMETHODIMP OnClockPause(MFTIME hnsSystemTime); - STDMETHODIMP OnClockRestart(MFTIME hnsSystemTime); - STDMETHODIMP OnClockSetRate(MFTIME hnsSystemTime, float flRate); - // IMFSampleGrabberSinkCallback methods - STDMETHODIMP OnSetPresentationClock(IMFPresentationClock* pClock); - STDMETHODIMP OnProcessSample(REFGUID guidMajorMediaType, DWORD dwSampleFlags, - LONGLONG llSampleTime, LONGLONG llSampleDuration, const BYTE * pSampleBuffer, - DWORD dwSampleSize); - STDMETHODIMP OnShutdown(); - - const HANDLE ig_hFrameReady; - const HANDLE ig_hFrameGrabbed; - const HANDLE ig_hFinish; -protected: - ImageGrabberCallback(bool synchronous); - bool ig_RIE; - bool ig_Close; - bool ig_Synchronous; - long m_cRef; - - RawImage *ig_RIFirst; - RawImage *ig_RISecond; - RawImage *ig_RIOut; -private: - ImageGrabberCallback& operator=(const ImageGrabberCallback&); // Declared to fix compilation warning. - }; - -// Class for grabbing image from video stream -class ImageGrabber : public ImageGrabberCallback -{ -public: - ~ImageGrabber(void); - HRESULT initImageGrabber(IMFMediaSource *pSource); - HRESULT startGrabbing(void); - void stopGrabbing(); - // IUnknown methods - STDMETHODIMP QueryInterface(REFIID iid, void** ppv); - STDMETHODIMP_(ULONG) AddRef(); - STDMETHODIMP_(ULONG) Release(); - // Function of creation of the instance of the class - static HRESULT CreateInstance(ImageGrabber **ppIG, unsigned int deviceID, bool synchronous = false); - const MediaType* getCaptureFormat() { return &captureFormat; } - -private: - unsigned int ig_DeviceID; - - IMFMediaSource *ig_pSource; - MediaType captureFormat; - IMFMediaSession *ig_pSession; - IMFTopology *ig_pTopology; - ImageGrabber(unsigned int deviceID, bool synchronous); - HRESULT CreateTopology(IMFMediaSource *pSource, IMFActivate *pSinkActivate, IMFTopology **ppTopo); - HRESULT AddSourceNode(IMFTopology *pTopology, IMFMediaSource *pSource, - IMFPresentationDescriptor *pPD, IMFStreamDescriptor *pSD, IMFTopologyNode **ppNode); - HRESULT AddOutputNode(IMFTopology *pTopology, IMFActivate *pActivate, DWORD dwId, IMFTopologyNode **ppNode); - - ImageGrabber& operator=(const ImageGrabber&); // Declared to fix comiplation error. -}; - -/// Class for controlling of thread of the grabbing raw data from video device -class ImageGrabberThread -{ - friend DWORD WINAPI MainThreadFunction( LPVOID lpParam ); -public: - ~ImageGrabberThread(void); - static HRESULT CreateInstance(ImageGrabberThread **ppIGT, IMFMediaSource *pSource, unsigned int deviceID, bool synchronious = false); - void start(); - void stop(); - void setEmergencyStopEvent(void *userData, void(*func)(int, void *)); - ImageGrabber *getImageGrabber(); -protected: - virtual void run(); -private: - ImageGrabberThread(IMFMediaSource *pSource, unsigned int deviceID, bool synchronious); - HANDLE igt_Handle; - DWORD igt_ThreadIdArray; - ImageGrabber *igt_pImageGrabber; - emergensyStopEventCallback igt_func; - void *igt_userData; - bool igt_stop; - unsigned int igt_DeviceID; -}; - // Structure for collecting info about one parametr of current video device struct Parametr { @@ -307,97 +283,112 @@ struct Parametr long Step; long Default; long Flag; - Parametr(); + Parametr() + { + CurrentValue = 0; + Min = 0; + Max = 0; + Step = 0; + Default = 0; + Flag = 0; + } }; // Structure for collecting info about 17 parametrs of current video device struct CamParametrs { - Parametr Brightness; - Parametr Contrast; - Parametr Hue; - Parametr Saturation; - Parametr Sharpness; - Parametr Gamma; - Parametr ColorEnable; - Parametr WhiteBalance; - Parametr BacklightCompensation; - Parametr Gain; - Parametr Pan; - Parametr Tilt; - Parametr Roll; - Parametr Zoom; - Parametr Exposure; - Parametr Iris; - Parametr Focus; + Parametr Brightness; + Parametr Contrast; + Parametr Hue; + Parametr Saturation; + Parametr Sharpness; + Parametr Gamma; + Parametr ColorEnable; + Parametr WhiteBalance; + Parametr BacklightCompensation; + Parametr Gain; + Parametr Pan; + Parametr Tilt; + Parametr Roll; + Parametr Zoom; + Parametr Exposure; + Parametr Iris; + Parametr Focus; }; -typedef std::wstring String; -typedef std::vector vectorNum; -typedef std::map SUBTYPEMap; -typedef std::map FrameRateMap; -typedef void(*emergensyStopEventCallback)(int, void *); - -/// Class for controlling of video device -class videoDevice +CamParametrs videoDevice__getParametrs(IMFMediaSource* vd_pSource) { -public: - videoDevice(void); - ~videoDevice(void); - void closeDevice(); - CamParametrs getParametrs(); - void setParametrs(CamParametrs parametrs); - void setEmergencyStopEvent(void *userData, void(*func)(int, void *)); - long readInfoOfDevice(IMFActivate *pActivate, unsigned int Num); - int getCountFormats(); - unsigned int getWidth(); - unsigned int getHeight(); - unsigned int getFrameRate() const; - MediaType getFormat(unsigned int id); - bool setupDevice(unsigned int w, unsigned int h, unsigned int idealFramerate = 0); - bool setupDevice(unsigned int id); - bool isDeviceSetup(); - bool isDeviceMediaSource(); - bool isDeviceRawDataSource(); - bool isFrameNew(); - IMFMediaSource *getMediaSource(); - RawImage *getRawImageOut(); -private: - enum typeLock + CamParametrs out; + if (vd_pSource) { - MediaSourceLock, - RawDataLock, - OpenLock - } vd_LockOut; - wchar_t *vd_pFriendlyName; - ImageGrabberThread *vd_pImGrTh; - unsigned int vd_Width; - unsigned int vd_Height; - unsigned int vd_FrameRate; - unsigned int vd_CurrentNumber; - bool vd_IsSetuped; - std::map vd_CaptureFormats; - std::vector vd_CurrentFormats; - IMFMediaSource *vd_pSource; - emergensyStopEventCallback vd_func; - void *vd_userData; - HRESULT enumerateCaptureFormats(IMFMediaSource *pSource); - long setDeviceFormat(IMFMediaSource *pSource, unsigned long dwFormatIndex); - void buildLibraryofTypes(); - int findType(unsigned int size, unsigned int frameRate = 0); - long checkDevice(IMFActivate **pDevice); - long initDevice(); -}; + Parametr *pParametr = (Parametr *)(&out); + IAMVideoProcAmp *pProcAmp = NULL; + HRESULT hr = vd_pSource->QueryInterface(IID_PPV_ARGS(&pProcAmp)); + if (SUCCEEDED(hr)) + { + for (unsigned int i = 0; i < 10; i++) + { + Parametr temp; + hr = pProcAmp->GetRange(VideoProcAmp_Brightness + i, &temp.Min, &temp.Max, &temp.Step, &temp.Default, &temp.Flag); + if (SUCCEEDED(hr)) + { + temp.CurrentValue = temp.Default; + pParametr[i] = temp; + } + } + pProcAmp->Release(); + } + IAMCameraControl *pProcControl = NULL; + hr = vd_pSource->QueryInterface(IID_PPV_ARGS(&pProcControl)); + if (SUCCEEDED(hr)) + { + for (unsigned int i = 0; i < 7; i++) + { + Parametr temp; + hr = pProcControl->GetRange(CameraControl_Pan + i, &temp.Min, &temp.Max, &temp.Step, &temp.Default, &temp.Flag); + if (SUCCEEDED(hr)) + { + temp.CurrentValue = temp.Default; + pParametr[10 + i] = temp; + } + } + pProcControl->Release(); + } + } + return out; +} -/// Class for managing of list of video devices -class videoDevices +void videoDevice__setParametrs(IMFMediaSource* vd_pSource, CamParametrs parametrs) { -public: - ~videoDevices(void); - static cv::Ptr getDevice(unsigned int i, bool fallback = false); -private: - videoDevices(void); -}; + if (vd_pSource) + { + CamParametrs vd_PrevParametrs = videoDevice__getParametrs(vd_pSource); + Parametr *pParametr = (Parametr *)(¶metrs); + Parametr *pPrevParametr = (Parametr *)(&vd_PrevParametrs); + IAMVideoProcAmp *pProcAmp = NULL; + HRESULT hr = vd_pSource->QueryInterface(IID_PPV_ARGS(&pProcAmp)); + if (SUCCEEDED(hr)) + { + for (unsigned int i = 0; i < 10; i++) + { + if (pPrevParametr[i].CurrentValue != pParametr[i].CurrentValue || pPrevParametr[i].Flag != pParametr[i].Flag) + hr = pProcAmp->Set(VideoProcAmp_Brightness + i, pParametr[i].CurrentValue, pParametr[i].Flag); + } + pProcAmp->Release(); + } + IAMCameraControl *pProcControl = NULL; + hr = vd_pSource->QueryInterface(IID_PPV_ARGS(&pProcControl)); + if (SUCCEEDED(hr)) + { + for (unsigned int i = 0; i < 7; i++) + { + if (pPrevParametr[10 + i].CurrentValue != pParametr[10 + i].CurrentValue || pPrevParametr[10 + i].Flag != pParametr[10 + i].Flag) + hr = pProcControl->Set(CameraControl_Pan + i, pParametr[10 + i].CurrentValue, pParametr[10 + i].Flag); + } + pProcControl->Release(); + } + } +} // Class for creating of Media Foundation context class Media_Foundation @@ -413,1548 +404,354 @@ private: Media_Foundation(void) { CV_Assert(SUCCEEDED(MFStartup(MF_VERSION))); } }; -LPCWSTR GetGUIDNameConstNew(const GUID& guid); -HRESULT GetGUIDNameNew(const GUID& guid, WCHAR **ppwsz); -HRESULT LogAttributeValueByIndexNew(IMFAttributes *pAttr, DWORD index); -HRESULT SpecialCaseAttributeValueNew(GUID guid, const PROPVARIANT& var, MediaType &out); - -unsigned int *GetParametr(GUID guid, MediaType &out) -{ - if(guid == MF_MT_YUV_MATRIX) - return &(out.MF_MT_YUV_MATRIX); - if(guid == MF_MT_VIDEO_LIGHTING) - return &(out.MF_MT_VIDEO_LIGHTING); - if(guid == MF_MT_DEFAULT_STRIDE) - return (unsigned int*)&(out.MF_MT_DEFAULT_STRIDE); - if(guid == MF_MT_VIDEO_CHROMA_SITING) - return &(out.MF_MT_VIDEO_CHROMA_SITING); - if(guid == MF_MT_VIDEO_NOMINAL_RANGE) - return &(out.MF_MT_VIDEO_NOMINAL_RANGE); - if(guid == MF_MT_ALL_SAMPLES_INDEPENDENT) - return &(out.MF_MT_ALL_SAMPLES_INDEPENDENT); - if(guid == MF_MT_FIXED_SIZE_SAMPLES) - return &(out.MF_MT_FIXED_SIZE_SAMPLES); - if(guid == MF_MT_SAMPLE_SIZE) - return &(out.MF_MT_SAMPLE_SIZE); - if(guid == MF_MT_VIDEO_PRIMARIES) - return &(out.MF_MT_VIDEO_PRIMARIES); - if(guid == MF_MT_INTERLACE_MODE) - return &(out.MF_MT_INTERLACE_MODE); - return NULL; -} - -HRESULT LogAttributeValueByIndexNew(IMFAttributes *pAttr, DWORD index, MediaType &out) -{ - WCHAR *pGuidName = NULL; - WCHAR *pGuidValName = NULL; - GUID guid = { 0 }; - PROPVARIANT var; - PropVariantInit(&var); - HRESULT hr = pAttr->GetItemByIndex(index, &guid, &var); - if (FAILED(hr)) - { - goto done; - } - hr = GetGUIDNameNew(guid, &pGuidName); - if (FAILED(hr)) - { - goto done; - } - hr = SpecialCaseAttributeValueNew(guid, var, out); - unsigned int *p; - if (FAILED(hr)) - { - goto done; - } - if (hr == S_FALSE) - { - switch (var.vt) - { - case VT_UI4: - p = GetParametr(guid, out); - if(p) - { - *p = var.ulVal; - } - break; - case VT_UI8: - break; - case VT_R8: - break; - case VT_CLSID: - if(guid == MF_MT_AM_FORMAT_TYPE) - { - hr = GetGUIDNameNew(*var.puuid, &pGuidValName); - if (SUCCEEDED(hr)) - { - out.MF_MT_AM_FORMAT_TYPE = *var.puuid; - out.pMF_MT_AM_FORMAT_TYPEName = pGuidValName; - pGuidValName = NULL; - } - } - if(guid == MF_MT_MAJOR_TYPE) - { - hr = GetGUIDNameNew(*var.puuid, &pGuidValName); - if (SUCCEEDED(hr)) - { - out.MF_MT_MAJOR_TYPE = *var.puuid; - out.pMF_MT_MAJOR_TYPEName = pGuidValName; - pGuidValName = NULL; - } - } - if(guid == MF_MT_SUBTYPE) - { - hr = GetGUIDNameNew(*var.puuid, &pGuidValName); - if (SUCCEEDED(hr)) - { - out.MF_MT_SUBTYPE = *var.puuid; - out.pMF_MT_SUBTYPEName = pGuidValName; - pGuidValName = NULL; - } - } - break; - case VT_LPWSTR: - break; - case VT_VECTOR | VT_UI1: - break; - case VT_UNKNOWN: - break; - default: - break; - } - } -done: - CoTaskMemFree(pGuidName); - CoTaskMemFree(pGuidValName); - PropVariantClear(&var); - return hr; -} - -HRESULT GetGUIDNameNew(const GUID& guid, WCHAR **ppwsz) -{ - HRESULT hr = S_OK; - WCHAR *pName = NULL; - LPCWSTR pcwsz = GetGUIDNameConstNew(guid); - if (pcwsz) - { - size_t cchLength = 0; - hr = StringCchLengthW(pcwsz, STRSAFE_MAX_CCH, &cchLength); - if (FAILED(hr)) - { - goto done; - } - pName = (WCHAR*)CoTaskMemAlloc((cchLength + 1) * sizeof(WCHAR)); - if (pName == NULL) - { - hr = E_OUTOFMEMORY; - goto done; - } - hr = StringCchCopyW(pName, cchLength + 1, pcwsz); - if (FAILED(hr)) - { - goto done; - } - } - else - { - hr = StringFromCLSID(guid, &pName); - } -done: - if (FAILED(hr)) - { - *ppwsz = NULL; - CoTaskMemFree(pName); - } - else - { - *ppwsz = pName; - } - return hr; -} - -void LogUINT32AsUINT64New(const PROPVARIANT& var, UINT32 &uHigh, UINT32 &uLow) -{ - Unpack2UINT32AsUINT64(var.uhVal.QuadPart, &uHigh, &uLow); -} - -float OffsetToFloatNew(const MFOffset& offset) -{ - return offset.value + (static_cast(offset.fract) / 65536.0f); -} - -HRESULT LogVideoAreaNew(const PROPVARIANT& var) -{ - if (var.caub.cElems < sizeof(MFVideoArea)) - { - return S_OK; - } - return S_OK; -} - -HRESULT SpecialCaseAttributeValueNew(GUID guid, const PROPVARIANT& var, MediaType &out) -{ - if (guid == MF_MT_DEFAULT_STRIDE) - { - out.MF_MT_DEFAULT_STRIDE = var.intVal; - } else - if (guid == MF_MT_FRAME_SIZE) - { - UINT32 uHigh = 0, uLow = 0; - LogUINT32AsUINT64New(var, uHigh, uLow); - out.width = uHigh; - out.height = uLow; - out.MF_MT_FRAME_SIZE = out.width * out.height; - } - else - if (guid == MF_MT_FRAME_RATE) - { - UINT32 uHigh = 0, uLow = 0; - LogUINT32AsUINT64New(var, uHigh, uLow); - out.MF_MT_FRAME_RATE_NUMERATOR = uHigh; - out.MF_MT_FRAME_RATE_DENOMINATOR = uLow; - } - else - if (guid == MF_MT_FRAME_RATE_RANGE_MAX) - { - UINT32 uHigh = 0, uLow = 0; - LogUINT32AsUINT64New(var, uHigh, uLow); - out.MF_MT_FRAME_RATE_RANGE_MAX = uHigh; - out.MF_MT_FRAME_RATE_RANGE_MAX_low = uLow; - } - else - if (guid == MF_MT_FRAME_RATE_RANGE_MIN) - { - UINT32 uHigh = 0, uLow = 0; - LogUINT32AsUINT64New(var, uHigh, uLow); - out.MF_MT_FRAME_RATE_RANGE_MIN = uHigh; - out.MF_MT_FRAME_RATE_RANGE_MIN_low = uLow; - } - else - if (guid == MF_MT_PIXEL_ASPECT_RATIO) - { - UINT32 uHigh = 0, uLow = 0; - LogUINT32AsUINT64New(var, uHigh, uLow); - out.MF_MT_PIXEL_ASPECT_RATIO = uHigh; - out.MF_MT_PIXEL_ASPECT_RATIO_low = uLow; - } - else - { - return S_FALSE; - } - return S_OK; -} - -#ifndef IF_EQUAL_RETURN -#define IF_EQUAL_RETURN(param, val) if(val == param) return L#val +#ifndef IF_GUID_EQUAL_RETURN +#define IF_GUID_EQUAL_RETURN(val) if(val == guid) return L#val #endif - LPCWSTR GetGUIDNameConstNew(const GUID& guid) { - IF_EQUAL_RETURN(guid, MF_MT_MAJOR_TYPE); - IF_EQUAL_RETURN(guid, MF_MT_MAJOR_TYPE); - IF_EQUAL_RETURN(guid, MF_MT_SUBTYPE); - IF_EQUAL_RETURN(guid, MF_MT_ALL_SAMPLES_INDEPENDENT); - IF_EQUAL_RETURN(guid, MF_MT_FIXED_SIZE_SAMPLES); - IF_EQUAL_RETURN(guid, MF_MT_COMPRESSED); - IF_EQUAL_RETURN(guid, MF_MT_SAMPLE_SIZE); - IF_EQUAL_RETURN(guid, MF_MT_WRAPPED_TYPE); - IF_EQUAL_RETURN(guid, MF_MT_AUDIO_NUM_CHANNELS); - IF_EQUAL_RETURN(guid, MF_MT_AUDIO_SAMPLES_PER_SECOND); - IF_EQUAL_RETURN(guid, MF_MT_AUDIO_FLOAT_SAMPLES_PER_SECOND); - IF_EQUAL_RETURN(guid, MF_MT_AUDIO_AVG_BYTES_PER_SECOND); - IF_EQUAL_RETURN(guid, MF_MT_AUDIO_BLOCK_ALIGNMENT); - IF_EQUAL_RETURN(guid, MF_MT_AUDIO_BITS_PER_SAMPLE); - IF_EQUAL_RETURN(guid, MF_MT_AUDIO_VALID_BITS_PER_SAMPLE); - IF_EQUAL_RETURN(guid, MF_MT_AUDIO_SAMPLES_PER_BLOCK); - IF_EQUAL_RETURN(guid, MF_MT_AUDIO_CHANNEL_MASK); - IF_EQUAL_RETURN(guid, MF_MT_AUDIO_FOLDDOWN_MATRIX); - IF_EQUAL_RETURN(guid, MF_MT_AUDIO_WMADRC_PEAKREF); - IF_EQUAL_RETURN(guid, MF_MT_AUDIO_WMADRC_PEAKTARGET); - IF_EQUAL_RETURN(guid, MF_MT_AUDIO_WMADRC_AVGREF); - IF_EQUAL_RETURN(guid, MF_MT_AUDIO_WMADRC_AVGTARGET); - IF_EQUAL_RETURN(guid, MF_MT_AUDIO_PREFER_WAVEFORMATEX); - IF_EQUAL_RETURN(guid, MF_MT_AAC_PAYLOAD_TYPE); - IF_EQUAL_RETURN(guid, MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION); - IF_EQUAL_RETURN(guid, MF_MT_FRAME_SIZE); - IF_EQUAL_RETURN(guid, MF_MT_FRAME_RATE); - IF_EQUAL_RETURN(guid, MF_MT_FRAME_RATE_RANGE_MAX); - IF_EQUAL_RETURN(guid, MF_MT_FRAME_RATE_RANGE_MIN); - IF_EQUAL_RETURN(guid, MF_MT_PIXEL_ASPECT_RATIO); - IF_EQUAL_RETURN(guid, MF_MT_DRM_FLAGS); - IF_EQUAL_RETURN(guid, MF_MT_PAD_CONTROL_FLAGS); - IF_EQUAL_RETURN(guid, MF_MT_SOURCE_CONTENT_HINT); - IF_EQUAL_RETURN(guid, MF_MT_VIDEO_CHROMA_SITING); - IF_EQUAL_RETURN(guid, MF_MT_INTERLACE_MODE); - IF_EQUAL_RETURN(guid, MF_MT_TRANSFER_FUNCTION); - IF_EQUAL_RETURN(guid, MF_MT_VIDEO_PRIMARIES); - IF_EQUAL_RETURN(guid, MF_MT_CUSTOM_VIDEO_PRIMARIES); - IF_EQUAL_RETURN(guid, MF_MT_YUV_MATRIX); - IF_EQUAL_RETURN(guid, MF_MT_VIDEO_LIGHTING); - IF_EQUAL_RETURN(guid, MF_MT_VIDEO_NOMINAL_RANGE); - IF_EQUAL_RETURN(guid, MF_MT_GEOMETRIC_APERTURE); - IF_EQUAL_RETURN(guid, MF_MT_MINIMUM_DISPLAY_APERTURE); - IF_EQUAL_RETURN(guid, MF_MT_PAN_SCAN_APERTURE); - IF_EQUAL_RETURN(guid, MF_MT_PAN_SCAN_ENABLED); - IF_EQUAL_RETURN(guid, MF_MT_AVG_BITRATE); - IF_EQUAL_RETURN(guid, MF_MT_AVG_BIT_ERROR_RATE); - IF_EQUAL_RETURN(guid, MF_MT_MAX_KEYFRAME_SPACING); - IF_EQUAL_RETURN(guid, MF_MT_DEFAULT_STRIDE); - IF_EQUAL_RETURN(guid, MF_MT_PALETTE); - IF_EQUAL_RETURN(guid, MF_MT_USER_DATA); - IF_EQUAL_RETURN(guid, MF_MT_AM_FORMAT_TYPE); - IF_EQUAL_RETURN(guid, MF_MT_MPEG_START_TIME_CODE); - IF_EQUAL_RETURN(guid, MF_MT_MPEG2_PROFILE); - IF_EQUAL_RETURN(guid, MF_MT_MPEG2_LEVEL); - IF_EQUAL_RETURN(guid, MF_MT_MPEG2_FLAGS); - IF_EQUAL_RETURN(guid, MF_MT_MPEG_SEQUENCE_HEADER); - IF_EQUAL_RETURN(guid, MF_MT_DV_AAUX_SRC_PACK_0); - IF_EQUAL_RETURN(guid, MF_MT_DV_AAUX_CTRL_PACK_0); - IF_EQUAL_RETURN(guid, MF_MT_DV_AAUX_SRC_PACK_1); - IF_EQUAL_RETURN(guid, MF_MT_DV_AAUX_CTRL_PACK_1); - IF_EQUAL_RETURN(guid, MF_MT_DV_VAUX_SRC_PACK); - IF_EQUAL_RETURN(guid, MF_MT_DV_VAUX_CTRL_PACK); - IF_EQUAL_RETURN(guid, MF_MT_ARBITRARY_HEADER); - IF_EQUAL_RETURN(guid, MF_MT_ARBITRARY_FORMAT); - IF_EQUAL_RETURN(guid, MF_MT_IMAGE_LOSS_TOLERANT); - IF_EQUAL_RETURN(guid, MF_MT_MPEG4_SAMPLE_DESCRIPTION); - IF_EQUAL_RETURN(guid, MF_MT_MPEG4_CURRENT_SAMPLE_ENTRY); - IF_EQUAL_RETURN(guid, MF_MT_ORIGINAL_4CC); - IF_EQUAL_RETURN(guid, MF_MT_ORIGINAL_WAVE_FORMAT_TAG); + IF_GUID_EQUAL_RETURN(MF_MT_MAJOR_TYPE); + IF_GUID_EQUAL_RETURN(MF_MT_SUBTYPE); + IF_GUID_EQUAL_RETURN(MF_MT_ALL_SAMPLES_INDEPENDENT); + IF_GUID_EQUAL_RETURN(MF_MT_FIXED_SIZE_SAMPLES); + IF_GUID_EQUAL_RETURN(MF_MT_COMPRESSED); + IF_GUID_EQUAL_RETURN(MF_MT_SAMPLE_SIZE); + IF_GUID_EQUAL_RETURN(MF_MT_WRAPPED_TYPE); + IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_NUM_CHANNELS); + IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_SAMPLES_PER_SECOND); + IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_FLOAT_SAMPLES_PER_SECOND); + IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_AVG_BYTES_PER_SECOND); + IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_BLOCK_ALIGNMENT); + IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_BITS_PER_SAMPLE); + IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_VALID_BITS_PER_SAMPLE); + IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_SAMPLES_PER_BLOCK); + IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_CHANNEL_MASK); + IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_FOLDDOWN_MATRIX); + IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_WMADRC_PEAKREF); + IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_WMADRC_PEAKTARGET); + IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_WMADRC_AVGREF); + IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_WMADRC_AVGTARGET); + IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_PREFER_WAVEFORMATEX); + IF_GUID_EQUAL_RETURN(MF_MT_AAC_PAYLOAD_TYPE); + IF_GUID_EQUAL_RETURN(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION); + IF_GUID_EQUAL_RETURN(MF_MT_FRAME_SIZE); + IF_GUID_EQUAL_RETURN(MF_MT_FRAME_RATE); + IF_GUID_EQUAL_RETURN(MF_MT_FRAME_RATE_RANGE_MAX); + IF_GUID_EQUAL_RETURN(MF_MT_FRAME_RATE_RANGE_MIN); + IF_GUID_EQUAL_RETURN(MF_MT_PIXEL_ASPECT_RATIO); + IF_GUID_EQUAL_RETURN(MF_MT_DRM_FLAGS); + IF_GUID_EQUAL_RETURN(MF_MT_PAD_CONTROL_FLAGS); + IF_GUID_EQUAL_RETURN(MF_MT_SOURCE_CONTENT_HINT); + IF_GUID_EQUAL_RETURN(MF_MT_VIDEO_CHROMA_SITING); + IF_GUID_EQUAL_RETURN(MF_MT_INTERLACE_MODE); + IF_GUID_EQUAL_RETURN(MF_MT_TRANSFER_FUNCTION); + IF_GUID_EQUAL_RETURN(MF_MT_VIDEO_PRIMARIES); + IF_GUID_EQUAL_RETURN(MF_MT_CUSTOM_VIDEO_PRIMARIES); + IF_GUID_EQUAL_RETURN(MF_MT_YUV_MATRIX); + IF_GUID_EQUAL_RETURN(MF_MT_VIDEO_LIGHTING); + IF_GUID_EQUAL_RETURN(MF_MT_VIDEO_NOMINAL_RANGE); + IF_GUID_EQUAL_RETURN(MF_MT_GEOMETRIC_APERTURE); + IF_GUID_EQUAL_RETURN(MF_MT_MINIMUM_DISPLAY_APERTURE); + IF_GUID_EQUAL_RETURN(MF_MT_PAN_SCAN_APERTURE); + IF_GUID_EQUAL_RETURN(MF_MT_PAN_SCAN_ENABLED); + IF_GUID_EQUAL_RETURN(MF_MT_AVG_BITRATE); + IF_GUID_EQUAL_RETURN(MF_MT_AVG_BIT_ERROR_RATE); + IF_GUID_EQUAL_RETURN(MF_MT_MAX_KEYFRAME_SPACING); + IF_GUID_EQUAL_RETURN(MF_MT_DEFAULT_STRIDE); + IF_GUID_EQUAL_RETURN(MF_MT_PALETTE); + IF_GUID_EQUAL_RETURN(MF_MT_USER_DATA); + IF_GUID_EQUAL_RETURN(MF_MT_AM_FORMAT_TYPE); + IF_GUID_EQUAL_RETURN(MF_MT_MPEG_START_TIME_CODE); + IF_GUID_EQUAL_RETURN(MF_MT_MPEG2_PROFILE); + IF_GUID_EQUAL_RETURN(MF_MT_MPEG2_LEVEL); + IF_GUID_EQUAL_RETURN(MF_MT_MPEG2_FLAGS); + IF_GUID_EQUAL_RETURN(MF_MT_MPEG_SEQUENCE_HEADER); + IF_GUID_EQUAL_RETURN(MF_MT_DV_AAUX_SRC_PACK_0); + IF_GUID_EQUAL_RETURN(MF_MT_DV_AAUX_CTRL_PACK_0); + IF_GUID_EQUAL_RETURN(MF_MT_DV_AAUX_SRC_PACK_1); + IF_GUID_EQUAL_RETURN(MF_MT_DV_AAUX_CTRL_PACK_1); + IF_GUID_EQUAL_RETURN(MF_MT_DV_VAUX_SRC_PACK); + IF_GUID_EQUAL_RETURN(MF_MT_DV_VAUX_CTRL_PACK); + IF_GUID_EQUAL_RETURN(MF_MT_ARBITRARY_HEADER); + IF_GUID_EQUAL_RETURN(MF_MT_ARBITRARY_FORMAT); + IF_GUID_EQUAL_RETURN(MF_MT_IMAGE_LOSS_TOLERANT); + IF_GUID_EQUAL_RETURN(MF_MT_MPEG4_SAMPLE_DESCRIPTION); + IF_GUID_EQUAL_RETURN(MF_MT_MPEG4_CURRENT_SAMPLE_ENTRY); + IF_GUID_EQUAL_RETURN(MF_MT_ORIGINAL_4CC); + IF_GUID_EQUAL_RETURN(MF_MT_ORIGINAL_WAVE_FORMAT_TAG); // Media types - IF_EQUAL_RETURN(guid, MFMediaType_Audio); - IF_EQUAL_RETURN(guid, MFMediaType_Video); - IF_EQUAL_RETURN(guid, MFMediaType_Protected); - IF_EQUAL_RETURN(guid, MFMediaType_SAMI); - IF_EQUAL_RETURN(guid, MFMediaType_Script); - IF_EQUAL_RETURN(guid, MFMediaType_Image); - IF_EQUAL_RETURN(guid, MFMediaType_HTML); - IF_EQUAL_RETURN(guid, MFMediaType_Binary); - IF_EQUAL_RETURN(guid, MFMediaType_FileTransfer); - IF_EQUAL_RETURN(guid, MFVideoFormat_AI44); // FCC('AI44') - IF_EQUAL_RETURN(guid, MFVideoFormat_ARGB32); // D3DFMT_A8R8G8B8 - IF_EQUAL_RETURN(guid, MFVideoFormat_AYUV); // FCC('AYUV') - IF_EQUAL_RETURN(guid, MFVideoFormat_DV25); // FCC('dv25') - IF_EQUAL_RETURN(guid, MFVideoFormat_DV50); // FCC('dv50') - IF_EQUAL_RETURN(guid, MFVideoFormat_DVH1); // FCC('dvh1') - IF_EQUAL_RETURN(guid, MFVideoFormat_DVSD); // FCC('dvsd') - IF_EQUAL_RETURN(guid, MFVideoFormat_DVSL); // FCC('dvsl') - IF_EQUAL_RETURN(guid, MFVideoFormat_H264); // FCC('H264') - IF_EQUAL_RETURN(guid, MFVideoFormat_I420); // FCC('I420') - IF_EQUAL_RETURN(guid, MFVideoFormat_IYUV); // FCC('IYUV') - IF_EQUAL_RETURN(guid, MFVideoFormat_M4S2); // FCC('M4S2') - IF_EQUAL_RETURN(guid, MFVideoFormat_MJPG); - IF_EQUAL_RETURN(guid, MFVideoFormat_MP43); // FCC('MP43') - IF_EQUAL_RETURN(guid, MFVideoFormat_MP4S); // FCC('MP4S') - IF_EQUAL_RETURN(guid, MFVideoFormat_MP4V); // FCC('MP4V') - IF_EQUAL_RETURN(guid, MFVideoFormat_MPG1); // FCC('MPG1') - IF_EQUAL_RETURN(guid, MFVideoFormat_MSS1); // FCC('MSS1') - IF_EQUAL_RETURN(guid, MFVideoFormat_MSS2); // FCC('MSS2') - IF_EQUAL_RETURN(guid, MFVideoFormat_NV11); // FCC('NV11') - IF_EQUAL_RETURN(guid, MFVideoFormat_NV12); // FCC('NV12') - IF_EQUAL_RETURN(guid, MFVideoFormat_P010); // FCC('P010') - IF_EQUAL_RETURN(guid, MFVideoFormat_P016); // FCC('P016') - IF_EQUAL_RETURN(guid, MFVideoFormat_P210); // FCC('P210') - IF_EQUAL_RETURN(guid, MFVideoFormat_P216); // FCC('P216') - IF_EQUAL_RETURN(guid, MFVideoFormat_RGB24); // D3DFMT_R8G8B8 - IF_EQUAL_RETURN(guid, MFVideoFormat_RGB32); // D3DFMT_X8R8G8B8 - IF_EQUAL_RETURN(guid, MFVideoFormat_RGB555); // D3DFMT_X1R5G5B5 - IF_EQUAL_RETURN(guid, MFVideoFormat_RGB565); // D3DFMT_R5G6B5 - IF_EQUAL_RETURN(guid, MFVideoFormat_RGB8); - IF_EQUAL_RETURN(guid, MFVideoFormat_UYVY); // FCC('UYVY') - IF_EQUAL_RETURN(guid, MFVideoFormat_v210); // FCC('v210') - IF_EQUAL_RETURN(guid, MFVideoFormat_v410); // FCC('v410') - IF_EQUAL_RETURN(guid, MFVideoFormat_WMV1); // FCC('WMV1') - IF_EQUAL_RETURN(guid, MFVideoFormat_WMV2); // FCC('WMV2') - IF_EQUAL_RETURN(guid, MFVideoFormat_WMV3); // FCC('WMV3') - IF_EQUAL_RETURN(guid, MFVideoFormat_WVC1); // FCC('WVC1') - IF_EQUAL_RETURN(guid, MFVideoFormat_Y210); // FCC('Y210') - IF_EQUAL_RETURN(guid, MFVideoFormat_Y216); // FCC('Y216') - IF_EQUAL_RETURN(guid, MFVideoFormat_Y410); // FCC('Y410') - IF_EQUAL_RETURN(guid, MFVideoFormat_Y416); // FCC('Y416') - IF_EQUAL_RETURN(guid, MFVideoFormat_Y41P); - IF_EQUAL_RETURN(guid, MFVideoFormat_Y41T); - IF_EQUAL_RETURN(guid, MFVideoFormat_YUY2); // FCC('YUY2') - IF_EQUAL_RETURN(guid, MFVideoFormat_YV12); // FCC('YV12') - IF_EQUAL_RETURN(guid, MFVideoFormat_YVYU); - IF_EQUAL_RETURN(guid, MFAudioFormat_PCM); // WAVE_FORMAT_PCM - IF_EQUAL_RETURN(guid, MFAudioFormat_Float); // WAVE_FORMAT_IEEE_FLOAT - IF_EQUAL_RETURN(guid, MFAudioFormat_DTS); // WAVE_FORMAT_DTS - IF_EQUAL_RETURN(guid, MFAudioFormat_Dolby_AC3_SPDIF); // WAVE_FORMAT_DOLBY_AC3_SPDIF - IF_EQUAL_RETURN(guid, MFAudioFormat_DRM); // WAVE_FORMAT_DRM - IF_EQUAL_RETURN(guid, MFAudioFormat_WMAudioV8); // WAVE_FORMAT_WMAUDIO2 - IF_EQUAL_RETURN(guid, MFAudioFormat_WMAudioV9); // WAVE_FORMAT_WMAUDIO3 - IF_EQUAL_RETURN(guid, MFAudioFormat_WMAudio_Lossless); // WAVE_FORMAT_WMAUDIO_LOSSLESS - IF_EQUAL_RETURN(guid, MFAudioFormat_WMASPDIF); // WAVE_FORMAT_WMASPDIF - IF_EQUAL_RETURN(guid, MFAudioFormat_MSP1); // WAVE_FORMAT_WMAVOICE9 - IF_EQUAL_RETURN(guid, MFAudioFormat_MP3); // WAVE_FORMAT_MPEGLAYER3 - IF_EQUAL_RETURN(guid, MFAudioFormat_MPEG); // WAVE_FORMAT_MPEG - IF_EQUAL_RETURN(guid, MFAudioFormat_AAC); // WAVE_FORMAT_MPEG_HEAAC - IF_EQUAL_RETURN(guid, MFAudioFormat_ADTS); // WAVE_FORMAT_MPEG_ADTS_AAC + IF_GUID_EQUAL_RETURN(MFMediaType_Audio); + IF_GUID_EQUAL_RETURN(MFMediaType_Video); + IF_GUID_EQUAL_RETURN(MFMediaType_Protected); +#ifdef MFMediaType_Perception + IF_GUID_EQUAL_RETURN(MFMediaType_Perception); +#endif + IF_GUID_EQUAL_RETURN(MFMediaType_Stream); + IF_GUID_EQUAL_RETURN(MFMediaType_SAMI); + IF_GUID_EQUAL_RETURN(MFMediaType_Script); + IF_GUID_EQUAL_RETURN(MFMediaType_Image); + IF_GUID_EQUAL_RETURN(MFMediaType_HTML); + IF_GUID_EQUAL_RETURN(MFMediaType_Binary); + IF_GUID_EQUAL_RETURN(MFMediaType_FileTransfer); + IF_GUID_EQUAL_RETURN(MFVideoFormat_AI44); // FCC('AI44') + IF_GUID_EQUAL_RETURN(MFVideoFormat_ARGB32); // D3DFMT_A8R8G8B8 + IF_GUID_EQUAL_RETURN(MFVideoFormat_AYUV); // FCC('AYUV') + IF_GUID_EQUAL_RETURN(MFVideoFormat_DV25); // FCC('dv25') + IF_GUID_EQUAL_RETURN(MFVideoFormat_DV50); // FCC('dv50') + IF_GUID_EQUAL_RETURN(MFVideoFormat_DVH1); // FCC('dvh1') + IF_GUID_EQUAL_RETURN(MFVideoFormat_DVC); + IF_GUID_EQUAL_RETURN(MFVideoFormat_DVHD); + IF_GUID_EQUAL_RETURN(MFVideoFormat_DVSD); // FCC('dvsd') + IF_GUID_EQUAL_RETURN(MFVideoFormat_DVSL); // FCC('dvsl') + IF_GUID_EQUAL_RETURN(MFVideoFormat_H264); // FCC('H264') + IF_GUID_EQUAL_RETURN(MFVideoFormat_I420); // FCC('I420') + IF_GUID_EQUAL_RETURN(MFVideoFormat_IYUV); // FCC('IYUV') + IF_GUID_EQUAL_RETURN(MFVideoFormat_M4S2); // FCC('M4S2') + IF_GUID_EQUAL_RETURN(MFVideoFormat_MJPG); + IF_GUID_EQUAL_RETURN(MFVideoFormat_MP43); // FCC('MP43') + IF_GUID_EQUAL_RETURN(MFVideoFormat_MP4S); // FCC('MP4S') + IF_GUID_EQUAL_RETURN(MFVideoFormat_MP4V); // FCC('MP4V') + IF_GUID_EQUAL_RETURN(MFVideoFormat_MPG1); // FCC('MPG1') + IF_GUID_EQUAL_RETURN(MFVideoFormat_MSS1); // FCC('MSS1') + IF_GUID_EQUAL_RETURN(MFVideoFormat_MSS2); // FCC('MSS2') + IF_GUID_EQUAL_RETURN(MFVideoFormat_NV11); // FCC('NV11') + IF_GUID_EQUAL_RETURN(MFVideoFormat_NV12); // FCC('NV12') + IF_GUID_EQUAL_RETURN(MFVideoFormat_P010); // FCC('P010') + IF_GUID_EQUAL_RETURN(MFVideoFormat_P016); // FCC('P016') + IF_GUID_EQUAL_RETURN(MFVideoFormat_P210); // FCC('P210') + IF_GUID_EQUAL_RETURN(MFVideoFormat_P216); // FCC('P216') + IF_GUID_EQUAL_RETURN(MFVideoFormat_RGB24); // D3DFMT_R8G8B8 + IF_GUID_EQUAL_RETURN(MFVideoFormat_RGB32); // D3DFMT_X8R8G8B8 + IF_GUID_EQUAL_RETURN(MFVideoFormat_RGB555); // D3DFMT_X1R5G5B5 + IF_GUID_EQUAL_RETURN(MFVideoFormat_RGB565); // D3DFMT_R5G6B5 + IF_GUID_EQUAL_RETURN(MFVideoFormat_RGB8); + IF_GUID_EQUAL_RETURN(MFVideoFormat_UYVY); // FCC('UYVY') + IF_GUID_EQUAL_RETURN(MFVideoFormat_v210); // FCC('v210') + IF_GUID_EQUAL_RETURN(MFVideoFormat_v410); // FCC('v410') + IF_GUID_EQUAL_RETURN(MFVideoFormat_WMV1); // FCC('WMV1') + IF_GUID_EQUAL_RETURN(MFVideoFormat_WMV2); // FCC('WMV2') + IF_GUID_EQUAL_RETURN(MFVideoFormat_WMV3); // FCC('WMV3') + IF_GUID_EQUAL_RETURN(MFVideoFormat_WVC1); // FCC('WVC1') + IF_GUID_EQUAL_RETURN(MFVideoFormat_Y210); // FCC('Y210') + IF_GUID_EQUAL_RETURN(MFVideoFormat_Y216); // FCC('Y216') + IF_GUID_EQUAL_RETURN(MFVideoFormat_Y410); // FCC('Y410') + IF_GUID_EQUAL_RETURN(MFVideoFormat_Y416); // FCC('Y416') + IF_GUID_EQUAL_RETURN(MFVideoFormat_Y41P); + IF_GUID_EQUAL_RETURN(MFVideoFormat_Y41T); + IF_GUID_EQUAL_RETURN(MFVideoFormat_YUY2); // FCC('YUY2') + IF_GUID_EQUAL_RETURN(MFVideoFormat_YV12); // FCC('YV12') + IF_GUID_EQUAL_RETURN(MFVideoFormat_YVYU); +#ifdef MFVideoFormat_H263 + IF_GUID_EQUAL_RETURN(MFVideoFormat_H263); +#endif +#ifdef MFVideoFormat_H265 + IF_GUID_EQUAL_RETURN(MFVideoFormat_H265); +#endif +#ifdef MFVideoFormat_H264_ES + IF_GUID_EQUAL_RETURN(MFVideoFormat_H264_ES); +#endif +#ifdef MFVideoFormat_HEVC + IF_GUID_EQUAL_RETURN(MFVideoFormat_HEVC); +#endif +#ifdef MFVideoFormat_HEVC_ES + IF_GUID_EQUAL_RETURN(MFVideoFormat_HEVC_ES); +#endif +#ifdef MFVideoFormat_MPEG2 + IF_GUID_EQUAL_RETURN(MFVideoFormat_MPEG2); +#endif +#ifdef MFVideoFormat_VP80 + IF_GUID_EQUAL_RETURN(MFVideoFormat_VP80); +#endif +#ifdef MFVideoFormat_VP90 + IF_GUID_EQUAL_RETURN(MFVideoFormat_VP90); +#endif +#ifdef MFVideoFormat_420O + IF_GUID_EQUAL_RETURN(MFVideoFormat_420O); +#endif +#ifdef MFVideoFormat_Y42T + IF_GUID_EQUAL_RETURN(MFVideoFormat_Y42T); +#endif +#ifdef MFVideoFormat_YVU9 + IF_GUID_EQUAL_RETURN(MFVideoFormat_YVU9); +#endif +#ifdef MFVideoFormat_v216 + IF_GUID_EQUAL_RETURN(MFVideoFormat_v216); +#endif +#ifdef MFVideoFormat_L8 + IF_GUID_EQUAL_RETURN(MFVideoFormat_L8); +#endif +#ifdef MFVideoFormat_L16 + IF_GUID_EQUAL_RETURN(MFVideoFormat_L16); +#endif +#ifdef MFVideoFormat_D16 + IF_GUID_EQUAL_RETURN(MFVideoFormat_D16); +#endif +#ifdef D3DFMT_X8R8G8B8 + IF_GUID_EQUAL_RETURN(D3DFMT_X8R8G8B8); +#endif +#ifdef D3DFMT_A8R8G8B8 + IF_GUID_EQUAL_RETURN(D3DFMT_A8R8G8B8); +#endif +#ifdef D3DFMT_R8G8B8 + IF_GUID_EQUAL_RETURN(D3DFMT_R8G8B8); +#endif +#ifdef D3DFMT_X1R5G5B5 + IF_GUID_EQUAL_RETURN(D3DFMT_X1R5G5B5); +#endif +#ifdef D3DFMT_A4R4G4B4 + IF_GUID_EQUAL_RETURN(D3DFMT_A4R4G4B4); +#endif +#ifdef D3DFMT_R5G6B5 + IF_GUID_EQUAL_RETURN(D3DFMT_R5G6B5); +#endif +#ifdef D3DFMT_P8 + IF_GUID_EQUAL_RETURN(D3DFMT_P8); +#endif +#ifdef D3DFMT_A2R10G10B10 + IF_GUID_EQUAL_RETURN(D3DFMT_A2R10G10B10); +#endif +#ifdef D3DFMT_A2B10G10R10 + IF_GUID_EQUAL_RETURN(D3DFMT_A2B10G10R10); +#endif +#ifdef D3DFMT_L8 + IF_GUID_EQUAL_RETURN(D3DFMT_L8); +#endif +#ifdef D3DFMT_L16 + IF_GUID_EQUAL_RETURN(D3DFMT_L16); +#endif +#ifdef D3DFMT_D16 + IF_GUID_EQUAL_RETURN(D3DFMT_D16); +#endif +#ifdef MFVideoFormat_A2R10G10B10 + IF_GUID_EQUAL_RETURN(MFVideoFormat_A2R10G10B10); +#endif +#ifdef MFVideoFormat_A16B16G16R16F + IF_GUID_EQUAL_RETURN(MFVideoFormat_A16B16G16R16F); +#endif + IF_GUID_EQUAL_RETURN(MFAudioFormat_PCM); // WAVE_FORMAT_PCM + IF_GUID_EQUAL_RETURN(MFAudioFormat_Float); // WAVE_FORMAT_IEEE_FLOAT + IF_GUID_EQUAL_RETURN(MFAudioFormat_DTS); // WAVE_FORMAT_DTS + IF_GUID_EQUAL_RETURN(MFAudioFormat_Dolby_AC3_SPDIF); // WAVE_FORMAT_DOLBY_AC3_SPDIF + IF_GUID_EQUAL_RETURN(MFAudioFormat_DRM); // WAVE_FORMAT_DRM + IF_GUID_EQUAL_RETURN(MFAudioFormat_WMAudioV8); // WAVE_FORMAT_WMAUDIO2 + IF_GUID_EQUAL_RETURN(MFAudioFormat_WMAudioV9); // WAVE_FORMAT_WMAUDIO3 + IF_GUID_EQUAL_RETURN(MFAudioFormat_WMAudio_Lossless); // WAVE_FORMAT_WMAUDIO_LOSSLESS + IF_GUID_EQUAL_RETURN(MFAudioFormat_WMASPDIF); // WAVE_FORMAT_WMASPDIF + IF_GUID_EQUAL_RETURN(MFAudioFormat_MSP1); // WAVE_FORMAT_WMAVOICE9 + IF_GUID_EQUAL_RETURN(MFAudioFormat_MP3); // WAVE_FORMAT_MPEGLAYER3 + IF_GUID_EQUAL_RETURN(MFAudioFormat_MPEG); // WAVE_FORMAT_MPEG + IF_GUID_EQUAL_RETURN(MFAudioFormat_AAC); // WAVE_FORMAT_MPEG_HEAAC + IF_GUID_EQUAL_RETURN(MFAudioFormat_ADTS); // WAVE_FORMAT_MPEG_ADTS_AAC +#ifdef MFAudioFormat_ALAC + IF_GUID_EQUAL_RETURN(MFAudioFormat_ALAC); +#endif +#ifdef MFAudioFormat_AMR_NB + IF_GUID_EQUAL_RETURN(MFAudioFormat_AMR_NB); +#endif +#ifdef MFAudioFormat_AMR_WB + IF_GUID_EQUAL_RETURN(MFAudioFormat_AMR_WB); +#endif +#ifdef MFAudioFormat_AMR_WP + IF_GUID_EQUAL_RETURN(MFAudioFormat_AMR_WP); +#endif +#ifdef MFAudioFormat_Dolby_AC3 + IF_GUID_EQUAL_RETURN(MFAudioFormat_Dolby_AC3); +#endif +#ifdef MFAudioFormat_Dolby_DDPlus + IF_GUID_EQUAL_RETURN(MFAudioFormat_Dolby_DDPlus); +#endif +#ifdef MFAudioFormat_FLAC + IF_GUID_EQUAL_RETURN(MFAudioFormat_FLAC); +#endif +#ifdef MFAudioFormat_Opus + IF_GUID_EQUAL_RETURN(MFAudioFormat_Opus); +#endif +#ifdef MEDIASUBTYPE_RAW_AAC1 + IF_GUID_EQUAL_RETURN(MEDIASUBTYPE_RAW_AAC1); +#endif +#ifdef MFAudioFormat_Float_SpatialObjects + IF_GUID_EQUAL_RETURN(MFAudioFormat_Float_SpatialObjects); +#endif +#ifdef MFAudioFormat_QCELP + IF_GUID_EQUAL_RETURN(MFAudioFormat_QCELP); +#endif + return NULL; } -FormatReader::FormatReader(void) -{ -} - -MediaType FormatReader::Read(IMFMediaType *pType) -{ - UINT32 count = 0; - MediaType out; - HRESULT hr = pType->LockStore(); - if (FAILED(hr)) - { - return out; - } - hr = pType->GetCount(&count); - if (FAILED(hr)) - { - return out; - } - for (UINT32 i = 0; i < count; i++) - { - hr = LogAttributeValueByIndexNew(pType, i, out); - if (FAILED(hr)) - { - break; - } - } - hr = pType->UnlockStore(); - if (FAILED(hr)) - { - return out; - } - return out; -} - -FormatReader::~FormatReader(void) -{ -} - -#define CHECK_HR(x) if (FAILED(x)) { goto done; } - -ImageGrabberCallback::ImageGrabberCallback(bool synchronous): - m_cRef(1), - ig_RIE(true), - ig_Close(false), - ig_Synchronous(synchronous), - ig_hFrameReady(synchronous ? CreateEvent(NULL, FALSE, FALSE, NULL): 0), - ig_hFrameGrabbed(synchronous ? CreateEvent(NULL, FALSE, FALSE, NULL): 0), - ig_hFinish(CreateEvent(NULL, TRUE, FALSE, NULL)) -{} - -ImageGrabber::ImageGrabber(unsigned int deviceID, bool synchronous): - ImageGrabberCallback(synchronous), - ig_DeviceID(deviceID), - ig_pSource(NULL), - ig_pSession(NULL), - ig_pTopology(NULL) -{} - -ImageGrabber::~ImageGrabber(void) -{ - if (ig_pSession) - { - ig_pSession->Shutdown(); - } - - CloseHandle(ig_hFinish); - - if (ig_Synchronous) - { - CloseHandle(ig_hFrameReady); - CloseHandle(ig_hFrameGrabbed); - } - - SafeRelease(&ig_pSession); - SafeRelease(&ig_pTopology); - - DebugPrintOut(L"IMAGEGRABBER VIDEODEVICE %i: Destroying instance of the ImageGrabber class\n", ig_DeviceID); -} - -HRESULT ImageGrabber::initImageGrabber(IMFMediaSource *pSource) -{ - // Clean up. - if (ig_pSession) - { - ig_pSession->Shutdown(); - } - SafeRelease(&ig_pSession); - SafeRelease(&ig_pTopology); - - HRESULT hr; - ig_pSource = pSource; - // Configure the media type that the Sample Grabber will receive. - // Setting the major and subtype is usually enough for the topology loader - // to resolve the topology. - _ComPtr pType = NULL; - _ComPtr pSinkActivate = NULL; - CHECK_HR(hr = MFCreateMediaType(pType.GetAddressOf())); - CHECK_HR(hr = pType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video)); - CHECK_HR(hr = pType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB24)); - // Create the sample grabber sink. - CHECK_HR(hr = MFCreateSampleGrabberSinkActivate(pType.Get(), this, pSinkActivate.GetAddressOf())); - // To run as fast as possible, set this attribute (requires Windows 7): - CHECK_HR(hr = pSinkActivate->SetUINT32(MF_SAMPLEGRABBERSINK_IGNORE_CLOCK, TRUE)); - // Create the Media Session. - CHECK_HR(hr = MFCreateMediaSession(NULL, &ig_pSession)); - // Create the topology. - CHECK_HR(hr = CreateTopology(pSource, pSinkActivate.Get(), &ig_pTopology)); - - CHECK_HR(hr = RawImage::CreateInstance(&ig_RIFirst, captureFormat.MF_MT_FRAME_SIZE * 3)); // Expect that output image will be RGB24 thus occupy 3 byte per point - CHECK_HR(hr = RawImage::CreateInstance(&ig_RISecond, captureFormat.MF_MT_FRAME_SIZE * 3)); - ig_RIOut = ig_RISecond; -done: - // Clean up. - if (FAILED(hr)) - { - if (ig_pSession) - { - ig_pSession->Shutdown(); - } - SafeRelease(&ig_pSession); - SafeRelease(&ig_pTopology); - } - return hr; -} - -void ImageGrabber::stopGrabbing() -{ - if(ig_pSession) - ig_pSession->Stop(); - DebugPrintOut(L"IMAGEGRABBER VIDEODEVICE %i: Stopping of of grabbing of images\n", ig_DeviceID); -} - -HRESULT ImageGrabber::startGrabbing(void) +bool LogAttributeValueByIndexNew(IMFAttributes *pAttr, DWORD index, MediaType &out) { PROPVARIANT var; PropVariantInit(&var); - HRESULT hr = ig_pSession->SetTopology(0, ig_pTopology); - DebugPrintOut(L"IMAGEGRABBER VIDEODEVICE %i: Start Grabbing of the images\n", ig_DeviceID); - hr = ig_pSession->Start(&GUID_NULL, &var); - for(;;) + GUID guid = { 0 }; + if (SUCCEEDED(pAttr->GetItemByIndex(index, &guid, &var))) { - _ComPtr pEvent = NULL; - HRESULT hrStatus = S_OK; - MediaEventType met; - if(!ig_pSession) break; - hr = ig_pSession->GetEvent(0, &pEvent); - if(!SUCCEEDED(hr)) + if (guid == MF_MT_DEFAULT_STRIDE && var.vt == VT_INT) + out.MF_MT_DEFAULT_STRIDE = var.intVal; + else if (guid == MF_MT_FRAME_RATE && var.vt == VT_UI8) + Unpack2UINT32AsUINT64(var.uhVal.QuadPart, &out.MF_MT_FRAME_RATE_NUMERATOR, &out.MF_MT_FRAME_RATE_DENOMINATOR); + else if (guid == MF_MT_FRAME_RATE_RANGE_MAX && var.vt == VT_UI8) + Unpack2UINT32AsUINT64(var.uhVal.QuadPart, &out.MF_MT_FRAME_RATE_RANGE_MAX, &out.MF_MT_FRAME_RATE_RANGE_MAX_low); + else if (guid == MF_MT_FRAME_RATE_RANGE_MIN && var.vt == VT_UI8) + Unpack2UINT32AsUINT64(var.uhVal.QuadPart, &out.MF_MT_FRAME_RATE_RANGE_MIN, &out.MF_MT_FRAME_RATE_RANGE_MIN_low); + else if (guid == MF_MT_PIXEL_ASPECT_RATIO && var.vt == VT_UI8) + Unpack2UINT32AsUINT64(var.uhVal.QuadPart, &out.MF_MT_PIXEL_ASPECT_RATIO, &out.MF_MT_PIXEL_ASPECT_RATIO_low); + else if (guid == MF_MT_YUV_MATRIX && var.vt == VT_UI4) + out.MF_MT_YUV_MATRIX = var.ulVal; + else if (guid == MF_MT_VIDEO_LIGHTING && var.vt == VT_UI4) + out.MF_MT_VIDEO_LIGHTING = var.ulVal; + else if (guid == MF_MT_DEFAULT_STRIDE && var.vt == VT_UI4) + out.MF_MT_DEFAULT_STRIDE = (int)var.ulVal; + else if (guid == MF_MT_VIDEO_CHROMA_SITING && var.vt == VT_UI4) + out.MF_MT_VIDEO_CHROMA_SITING = var.ulVal; + else if (guid == MF_MT_VIDEO_NOMINAL_RANGE && var.vt == VT_UI4) + out.MF_MT_VIDEO_NOMINAL_RANGE = var.ulVal; + else if (guid == MF_MT_ALL_SAMPLES_INDEPENDENT && var.vt == VT_UI4) + out.MF_MT_ALL_SAMPLES_INDEPENDENT = var.ulVal; + else if (guid == MF_MT_FIXED_SIZE_SAMPLES && var.vt == VT_UI4) + out.MF_MT_FIXED_SIZE_SAMPLES = var.ulVal; + else if (guid == MF_MT_SAMPLE_SIZE && var.vt == VT_UI4) + out.MF_MT_SAMPLE_SIZE = var.ulVal; + else if (guid == MF_MT_VIDEO_PRIMARIES && var.vt == VT_UI4) + out.MF_MT_VIDEO_PRIMARIES = var.ulVal; + else if (guid == MF_MT_INTERLACE_MODE && var.vt == VT_UI4) + out.MF_MT_INTERLACE_MODE = var.ulVal; + else if (guid == MF_MT_AM_FORMAT_TYPE && var.vt == VT_CLSID) + out.MF_MT_AM_FORMAT_TYPE = *var.puuid; + else if (guid == MF_MT_MAJOR_TYPE && var.vt == VT_CLSID) + out.pMF_MT_MAJOR_TYPEName = GetGUIDNameConstNew(out.MF_MT_MAJOR_TYPE = *var.puuid); + else if (guid == MF_MT_SUBTYPE && var.vt == VT_CLSID) + out.pMF_MT_SUBTYPEName = GetGUIDNameConstNew(out.MF_MT_SUBTYPE = *var.puuid); + else if (guid == MF_MT_FRAME_SIZE && var.vt == VT_UI8) { - hr = S_OK; - goto done; + Unpack2UINT32AsUINT64(var.uhVal.QuadPart, &out.width, &out.height); + out.MF_MT_FRAME_SIZE = out.width * out.height; } - hr = pEvent->GetStatus(&hrStatus); - if(!SUCCEEDED(hr)) - { - hr = S_OK; - goto done; - } - hr = pEvent->GetType(&met); - if(!SUCCEEDED(hr)) - { - hr = S_OK; - goto done; - } - if (!SUCCEEDED(hrStatus)) - { - DebugPrintOut(L"IMAGEGRABBER VIDEODEVICE %i: Event Status Error: %u\n", ig_DeviceID, hrStatus); - goto done; - } - if (met == MESessionEnded) - { - DebugPrintOut(L"IMAGEGRABBER VIDEODEVICE %i: MESessionEnded\n", ig_DeviceID); - ig_pSession->Stop(); - break; - } - if (met == MESessionStopped) - { - DebugPrintOut(L"IMAGEGRABBER VIDEODEVICE %i: MESessionStopped \n", ig_DeviceID); - break; - } -#if (WINVER >= 0x0602) // Available since Win 8 - if (met == MEVideoCaptureDeviceRemoved) - { - DebugPrintOut(L"IMAGEGRABBER VIDEODEVICE %i: MEVideoCaptureDeviceRemoved \n", ig_DeviceID); - break; - } -#endif - if ((met == MEError) || (met == MENonFatalError)) - { - pEvent->GetStatus(&hrStatus); - DebugPrintOut(L"IMAGEGRABBER VIDEODEVICE %i: MEError | MENonFatalError: %u\n", ig_DeviceID, hrStatus); - break; - } - } - DebugPrintOut(L"IMAGEGRABBER VIDEODEVICE %i: Finish startGrabbing \n", ig_DeviceID); - -done: - SetEvent(ig_hFinish); - - return hr; -} - -void ImageGrabberCallback::pauseGrabbing() -{ -} - -void ImageGrabberCallback::resumeGrabbing() -{ -} - -HRESULT ImageGrabber::CreateTopology(IMFMediaSource *pSource, IMFActivate *pSinkActivate, IMFTopology **ppTopo) -{ - HRESULT hr = S_OK; - { // "done:" scope - _ComPtr pPD = NULL; - hr = !pSource ? E_POINTER : S_OK; CHECK_HR(hr); - CHECK_HR(hr = pSource->CreatePresentationDescriptor(pPD.GetAddressOf())); - - DWORD cStreams = 0; - CHECK_HR(hr = pPD->GetStreamDescriptorCount(&cStreams)); - DWORD vStream = cStreams; - BOOL vStreamSelected = FALSE; - for (DWORD i = 0; i < cStreams; i++) - { - BOOL fSelected = FALSE; - _ComPtr pSD = NULL; - CHECK_HR(hr = pPD->GetStreamDescriptorByIndex(i, &fSelected, pSD.GetAddressOf())); - - _ComPtr pHandler = NULL; - CHECK_HR(hr = pSD->GetMediaTypeHandler(pHandler.GetAddressOf())); - - GUID majorType; - CHECK_HR(hr = pHandler->GetMajorType(&majorType)); - - if (majorType == MFMediaType_Video && !vStreamSelected) - { - if (fSelected) - { - vStream = i; - vStreamSelected = TRUE; - } - else - vStream = i < vStream ? i : vStream; - } - else - { - CHECK_HR(hr = pPD->DeselectStream(i)); - } - } - - if (vStream < cStreams) - { - if (!vStreamSelected) - CHECK_HR(hr = pPD->SelectStream(vStream)); - BOOL fSelected; - _ComPtr pSD = NULL; - CHECK_HR(hr = pPD->GetStreamDescriptorByIndex(vStream, &fSelected, pSD.GetAddressOf())); - - _ComPtr pHandler = NULL; - CHECK_HR(hr = pSD->GetMediaTypeHandler(pHandler.GetAddressOf())); - - DWORD cTypes = 0; - CHECK_HR(hr = pHandler->GetMediaTypeCount(&cTypes)); - DWORD j = 0; - for (; j < cTypes; j++) // Iterate throug available video subtypes to find supported and fill MediaType structure - { - _ComPtr pType = NULL; - CHECK_HR(hr = pHandler->GetMediaTypeByIndex(j, pType.GetAddressOf())); - MediaType MT = FormatReader::Read(pType.Get()); - if (MT.MF_MT_MAJOR_TYPE == MFMediaType_Video /*&& MT.MF_MT_SUBTYPE == MFVideoFormat_RGB24*/) - { - captureFormat = MT; - break; - } - } - - if (j < cTypes) // If there is supported video subtype create topology - { - IMFTopology* pTopology = NULL; - _ComPtr pNode1 = NULL; - _ComPtr pNode2 = NULL; - - _ComPtr pNode1c1 = NULL; - _ComPtr pNode1c2 = NULL; - - CHECK_HR(hr = MFCreateTopology(&pTopology)); - CHECK_HR(hr = AddSourceNode(pTopology, pSource, pPD.Get(), pSD.Get(), pNode1.GetAddressOf())); - CHECK_HR(hr = AddOutputNode(pTopology, pSinkActivate, 0, pNode2.GetAddressOf())); - CHECK_HR(hr = pNode1->ConnectOutput(0, pNode2.Get(), 0)); - *ppTopo = pTopology; - (*ppTopo)->AddRef(); - } - else - hr = E_INVALIDARG; - } - else - hr = E_INVALIDARG; - - } // "done:" scope -done: - return hr; -} - -HRESULT ImageGrabber::AddSourceNode( - IMFTopology *pTopology, // Topology. - IMFMediaSource *pSource, // Media source. - IMFPresentationDescriptor *pPD, // Presentation descriptor. - IMFStreamDescriptor *pSD, // Stream descriptor. - IMFTopologyNode **ppNode) // Receives the node pointer. -{ - _ComPtr pNode = NULL; - HRESULT hr = S_OK; - CHECK_HR(hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, pNode.GetAddressOf())); - CHECK_HR(hr = pNode->SetUnknown(MF_TOPONODE_SOURCE, pSource)); - CHECK_HR(hr = pNode->SetUnknown(MF_TOPONODE_PRESENTATION_DESCRIPTOR, pPD)); - CHECK_HR(hr = pNode->SetUnknown(MF_TOPONODE_STREAM_DESCRIPTOR, pSD)); - CHECK_HR(hr = pTopology->AddNode(pNode.Get())); - // Return the pointer to the caller. - *ppNode = pNode.Get(); - (*ppNode)->AddRef(); - -done: - return hr; -} - -HRESULT ImageGrabber::AddOutputNode( - IMFTopology *pTopology, // Topology. - IMFActivate *pActivate, // Media sink activation object. - DWORD dwId, // Identifier of the stream sink. - IMFTopologyNode **ppNode) // Receives the node pointer. -{ - _ComPtr pNode = NULL; - HRESULT hr = S_OK; - CHECK_HR(hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, pNode.GetAddressOf())); - CHECK_HR(hr = pNode->SetObject(pActivate)); - CHECK_HR(hr = pNode->SetUINT32(MF_TOPONODE_STREAMID, dwId)); - CHECK_HR(hr = pNode->SetUINT32(MF_TOPONODE_NOSHUTDOWN_ON_REMOVE, FALSE)); - CHECK_HR(hr = pTopology->AddNode(pNode.Get())); - // Return the pointer to the caller. - *ppNode = pNode.Get(); - (*ppNode)->AddRef(); - -done: - return hr; -} - -HRESULT ImageGrabber::CreateInstance(ImageGrabber **ppIG, unsigned int deviceID, bool synchronious) -{ - *ppIG = new (std::nothrow) ImageGrabber(deviceID, synchronious); - if (ppIG == NULL) - { - return E_OUTOFMEMORY; - } - DebugPrintOut(L"IMAGEGRABBER VIDEODEVICE %i: Creating instance of ImageGrabber\n", deviceID); - return S_OK; -} - -STDMETHODIMP ImageGrabber::QueryInterface(REFIID riid, void** ppv) -{ - HRESULT hr = E_NOINTERFACE; - *ppv = NULL; - if(riid == IID_IUnknown || riid == IID_IMFSampleGrabberSinkCallback) - { - *ppv = static_cast(this); - hr = S_OK; - } - if(riid == IID_IMFClockStateSink) - { - *ppv = static_cast(this); - hr = S_OK; - } - if(SUCCEEDED(hr)) - { - reinterpret_cast(*ppv)->AddRef(); - } - return hr; -} - -STDMETHODIMP_(ULONG) ImageGrabber::AddRef() -{ - return InterlockedIncrement(&m_cRef); -} - -STDMETHODIMP_(ULONG) ImageGrabber::Release() -{ - ULONG cRef = InterlockedDecrement(&m_cRef); - if (cRef == 0) - { - delete this; - } - return cRef; -} - -STDMETHODIMP ImageGrabberCallback::OnClockStart(MFTIME hnsSystemTime, LONGLONG llClockStartOffset) -{ - (void)hnsSystemTime; - (void)llClockStartOffset; - return S_OK; -} - -STDMETHODIMP ImageGrabberCallback::OnClockStop(MFTIME hnsSystemTime) -{ - (void)hnsSystemTime; - return S_OK; -} - -STDMETHODIMP ImageGrabberCallback::OnClockPause(MFTIME hnsSystemTime) -{ - (void)hnsSystemTime; - return S_OK; -} - -STDMETHODIMP ImageGrabberCallback::OnClockRestart(MFTIME hnsSystemTime) -{ - (void)hnsSystemTime; - return S_OK; -} - -STDMETHODIMP ImageGrabberCallback::OnClockSetRate(MFTIME hnsSystemTime, float flRate) -{ - (void)flRate; - (void)hnsSystemTime; - return S_OK; -} - -STDMETHODIMP ImageGrabberCallback::OnSetPresentationClock(IMFPresentationClock* pClock) -{ - (void)pClock; - return S_OK; -} - -STDMETHODIMP ImageGrabberCallback::OnProcessSample(REFGUID guidMajorMediaType, DWORD dwSampleFlags, - LONGLONG llSampleTime, LONGLONG llSampleDuration, const BYTE * pSampleBuffer, - DWORD dwSampleSize) -{ - (void)guidMajorMediaType; - (void)llSampleTime; - (void)dwSampleFlags; - (void)llSampleDuration; - (void)dwSampleSize; - - HANDLE tmp[] = {ig_hFinish, ig_hFrameGrabbed, NULL}; - - DWORD status = WaitForMultipleObjects(2, tmp, FALSE, INFINITE); - if (status == WAIT_OBJECT_0) - { - DebugPrintOut(L"OnProcessFrame called after ig_hFinish event\n"); - return S_OK; - } - - if(ig_RIE) - { - ig_RIFirst->fastCopy(pSampleBuffer); - ig_RIOut = ig_RIFirst; - } - else - { - ig_RISecond->fastCopy(pSampleBuffer); - ig_RIOut = ig_RISecond; - } - - if (ig_Synchronous) - { - SetEvent(ig_hFrameReady); - } - else - { - ig_RIE = !ig_RIE; - } - - return S_OK; -} - -STDMETHODIMP ImageGrabberCallback::OnShutdown() -{ - SetEvent(ig_hFinish); - return S_OK; -} - -RawImage *ImageGrabberCallback::getRawImage() -{ - return ig_RIOut; -} - -DWORD WINAPI MainThreadFunction( LPVOID lpParam ) -{ - ImageGrabberThread *pIGT = (ImageGrabberThread *)lpParam; - pIGT->run(); - return 0; -} - -HRESULT ImageGrabberThread::CreateInstance(ImageGrabberThread **ppIGT, IMFMediaSource *pSource, unsigned int deviceID, bool synchronious) -{ - *ppIGT = new (std::nothrow) ImageGrabberThread(pSource, deviceID, synchronious); - if (ppIGT == NULL) - { - DebugPrintOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Memory cannot be allocated\n", deviceID); - return E_OUTOFMEMORY; - } - else - DebugPrintOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Creating of the instance of ImageGrabberThread\n", deviceID); - return S_OK; -} - -ImageGrabberThread::ImageGrabberThread(IMFMediaSource *pSource, unsigned int deviceID, bool synchronious) : - igt_func(NULL), - igt_Handle(NULL), - igt_stop(false) -{ - HRESULT hr = ImageGrabber::CreateInstance(&igt_pImageGrabber, deviceID, synchronious); - igt_DeviceID = deviceID; - if(SUCCEEDED(hr)) - { - hr = igt_pImageGrabber->initImageGrabber(pSource); - if(!SUCCEEDED(hr)) - { - DebugPrintOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: There is a problem with initialization of the instance of the ImageGrabber class\n", deviceID); - } - else - { - DebugPrintOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Initialization of instance of the ImageGrabber class\n", deviceID); - } - } - else - { - DebugPrintOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: There is a problem with creation of the instance of the ImageGrabber class\n", deviceID); - } -} - -void ImageGrabberThread::setEmergencyStopEvent(void *userData, void(*func)(int, void *)) -{ - if(func) - { - igt_func = func; - igt_userData = userData; - } -} - -ImageGrabberThread::~ImageGrabberThread(void) -{ - DebugPrintOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Destroying ImageGrabberThread\n", igt_DeviceID); - if (igt_Handle) - WaitForSingleObject(igt_Handle, INFINITE); - delete igt_pImageGrabber; -} - -void ImageGrabberThread::stop() -{ - igt_stop = true; - if(igt_pImageGrabber) - { - igt_pImageGrabber->stopGrabbing(); - } -} - -void ImageGrabberThread::start() -{ - igt_Handle = CreateThread( - NULL, // default security attributes - 0, // use default stack size - MainThreadFunction, // thread function name - this, // argument to thread function - 0, // use default creation flags - &igt_ThreadIdArray); // returns the thread identifier -} - -void ImageGrabberThread::run() -{ - if(igt_pImageGrabber) - { - DebugPrintOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Thread for grabbing images is started\n", igt_DeviceID); - HRESULT hr = igt_pImageGrabber->startGrabbing(); - if(!SUCCEEDED(hr)) - { - DebugPrintOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: There is a problem with starting the process of grabbing\n", igt_DeviceID); - } - } - else - { - DebugPrintOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i The thread is finished without execution of grabbing\n", igt_DeviceID); - } - if(!igt_stop) - { - DebugPrintOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Emergency Stop thread\n", igt_DeviceID); - if(igt_func) - { - igt_func(igt_DeviceID, igt_userData); - } - } - else - DebugPrintOut(L"IMAGEGRABBERTHREAD VIDEODEVICE %i: Finish thread\n", igt_DeviceID); -} - -ImageGrabber *ImageGrabberThread::getImageGrabber() -{ - return igt_pImageGrabber; -} - -RawImage::RawImage(unsigned int size): ri_new(false), ri_pixels(NULL) -{ - ri_size = size; - ri_pixels = new unsigned char[size]; - memset((void *)ri_pixels,0,ri_size); -} - -bool RawImage::isNew() -{ - return ri_new; -} - -unsigned int RawImage::getSize() -{ - return ri_size; -} - -RawImage::~RawImage(void) -{ - delete []ri_pixels; - ri_pixels = NULL; -} - -long RawImage::CreateInstance(RawImage **ppRImage,unsigned int size) -{ - *ppRImage = new (std::nothrow) RawImage(size); - if (ppRImage == NULL) - { - return E_OUTOFMEMORY; - } - return S_OK; -} - -void RawImage::setCopy(const BYTE * pSampleBuffer) -{ - memcpy(ri_pixels, pSampleBuffer, ri_size); - ri_new = true; -} - -void RawImage::fastCopy(const BYTE * pSampleBuffer) -{ - memcpy(ri_pixels, pSampleBuffer, ri_size); - ri_new = true; -} - -unsigned char * RawImage::getpPixels() -{ - ri_new = false; - return ri_pixels; -} - -videoDevice::videoDevice(void): vd_IsSetuped(false), vd_LockOut(OpenLock), vd_pFriendlyName(NULL), - vd_Width(0), vd_Height(0), vd_FrameRate(0), vd_pSource(NULL), vd_pImGrTh(NULL), vd_func(NULL), vd_userData(NULL) -{ -} - -void videoDevice::setParametrs(CamParametrs parametrs) -{ - if(vd_IsSetuped) - { - if(vd_pSource) - { - CamParametrs vd_PrevParametrs = getParametrs(); - Parametr *pParametr = (Parametr *)(¶metrs); - Parametr *pPrevParametr = (Parametr *)(&vd_PrevParametrs); - IAMVideoProcAmp *pProcAmp = NULL; - HRESULT hr = vd_pSource->QueryInterface(IID_PPV_ARGS(&pProcAmp)); - if (SUCCEEDED(hr)) - { - for(unsigned int i = 0; i < 10; i++) - { - if(pPrevParametr[i].CurrentValue != pParametr[i].CurrentValue || pPrevParametr[i].Flag != pParametr[i].Flag) - hr = pProcAmp->Set(VideoProcAmp_Brightness + i, pParametr[i].CurrentValue, pParametr[i].Flag); - } - pProcAmp->Release(); - } - IAMCameraControl *pProcControl = NULL; - hr = vd_pSource->QueryInterface(IID_PPV_ARGS(&pProcControl)); - if (SUCCEEDED(hr)) - { - for(unsigned int i = 0; i < 7; i++) - { - if(pPrevParametr[10 + i].CurrentValue != pParametr[10 + i].CurrentValue || pPrevParametr[10 + i].Flag != pParametr[10 + i].Flag) - hr = pProcControl->Set(CameraControl_Pan+i, pParametr[10 + i].CurrentValue, pParametr[10 + i].Flag); - } - pProcControl->Release(); - } - vd_PrevParametrs = parametrs; - } - } -} - -CamParametrs videoDevice::getParametrs() -{ - CamParametrs out; - if(vd_IsSetuped) - { - if(vd_pSource) - { - Parametr *pParametr = (Parametr *)(&out); - IAMVideoProcAmp *pProcAmp = NULL; - HRESULT hr = vd_pSource->QueryInterface(IID_PPV_ARGS(&pProcAmp)); - if (SUCCEEDED(hr)) - { - for(unsigned int i = 0; i < 10; i++) - { - Parametr temp; - hr = pProcAmp->GetRange(VideoProcAmp_Brightness+i, &temp.Min, &temp.Max, &temp.Step, &temp.Default, &temp.Flag); - if (SUCCEEDED(hr)) - { - temp.CurrentValue = temp.Default; - pParametr[i] = temp; - } - } - pProcAmp->Release(); - } - IAMCameraControl *pProcControl = NULL; - hr = vd_pSource->QueryInterface(IID_PPV_ARGS(&pProcControl)); - if (SUCCEEDED(hr)) - { - for(unsigned int i = 0; i < 7; i++) - { - Parametr temp; - hr = pProcControl->GetRange(CameraControl_Pan+i, &temp.Min, &temp.Max, &temp.Step, &temp.Default, &temp.Flag); - if (SUCCEEDED(hr)) - { - temp.CurrentValue = temp.Default; - pParametr[10 + i] = temp; - } - } - pProcControl->Release(); - } - } - } - return out; -} - -long videoDevice::readInfoOfDevice(IMFActivate *pActivate, unsigned int Num) -{ - vd_CurrentNumber = Num; - HRESULT hr = E_FAIL; - vd_CurrentFormats.clear(); - if (pActivate) - { - SafeRelease(&vd_pSource); - hr = pActivate->ActivateObject( - __uuidof(IMFMediaSource), - (void**)&vd_pSource - ); - if (SUCCEEDED(hr) && vd_pSource) - { - enumerateCaptureFormats(vd_pSource); - buildLibraryofTypes(); - }//end if (SUCCEEDED(hr) && pSource) - else - DebugPrintOut(L"VIDEODEVICE %i: IMFMediaSource interface cannot be created \n", vd_CurrentNumber); - } - return hr; -} - -MediaType videoDevice::getFormat(unsigned int id) -{ - if(id < vd_CurrentFormats.size()) - { - return vd_CurrentFormats[id]; - } - else return MediaType(); -} -int videoDevice::getCountFormats() -{ - return (int)vd_CurrentFormats.size(); -} -void videoDevice::setEmergencyStopEvent(void *userData, void(*func)(int, void *)) -{ - vd_func = func; - vd_userData = userData; -} -void videoDevice::closeDevice() -{ - if(vd_IsSetuped) - { - vd_IsSetuped = false; - - vd_pSource->Shutdown(); - SafeRelease(&vd_pSource); - if(vd_LockOut == RawDataLock) - { - vd_pImGrTh->stop(); - Sleep(500); - delete vd_pImGrTh; - } - vd_pImGrTh = NULL; - vd_LockOut = OpenLock; - DebugPrintOut(L"VIDEODEVICE %i: Device is stopped \n", vd_CurrentNumber); - } -} -unsigned int videoDevice::getWidth() -{ - if(vd_IsSetuped) - return vd_Width; - else - return 0; -} -unsigned int videoDevice::getHeight() -{ - if(vd_IsSetuped) - return vd_Height; - else - return 0; -} - -unsigned int videoDevice::getFrameRate() const -{ - if(vd_IsSetuped) - return vd_FrameRate; - else - return 0; -} - -IMFMediaSource *videoDevice::getMediaSource() -{ - IMFMediaSource *out = NULL; - if(vd_LockOut == OpenLock) - { - vd_LockOut = MediaSourceLock; - out = vd_pSource; - } - return out; -} -int videoDevice::findType(unsigned int size, unsigned int frameRate) -{ - // For required frame size look for the suitable video format. - // If not found, get the format for the largest available frame size. - FrameRateMap FRM; - std::map::const_iterator fmt; - fmt = vd_CaptureFormats.find(size); - if( fmt != vd_CaptureFormats.end() ) - FRM = fmt->second; - else if( !vd_CaptureFormats.empty() ) - FRM = vd_CaptureFormats.rbegin()->second; - - if( FRM.empty() ) - return -1; - - UINT64 frameRateMax = 0; SUBTYPEMap STMMax; - if(frameRate == 0) - { - std::map::iterator f = FRM.begin(); - for(; f != FRM.end(); f++) - { - // Looking for highest possible frame rate. - if((*f).first >= frameRateMax) - { - frameRateMax = (*f).first; - STMMax = (*f).second; - } - } - } - else - { - std::map::iterator f = FRM.begin(); - for(; f != FRM.end(); f++) - { - // Looking for frame rate higher that recently found but not higher then demanded. - if( (*f).first >= frameRateMax && (*f).first <= frameRate ) - { - frameRateMax = (*f).first; - STMMax = (*f).second; - } - } - } - // Get first (default) item from the list if no suitable frame rate found. - if( STMMax.empty() ) - STMMax = FRM.begin()->second; - - // Check if there are any format types on the list. - if( STMMax.empty() ) - return -1; - - vectorNum VN = STMMax.begin()->second; - if( VN.empty() ) - return -1; - - return VN[0]; -} - -void videoDevice::buildLibraryofTypes() -{ - unsigned int size; - unsigned int framerate; - std::vector::iterator i = vd_CurrentFormats.begin(); - int count = 0; - for(; i != vd_CurrentFormats.end(); i++) - { - // Count only supported video formats. - if( (*i).MF_MT_SUBTYPE == MFVideoFormat_RGB24 || (*i).MF_MT_SUBTYPE == MFVideoFormat_NV12 ) - { - size = (*i).MF_MT_FRAME_SIZE; - framerate = (*i).MF_MT_FRAME_RATE_NUMERATOR / (*i).MF_MT_FRAME_RATE_DENOMINATOR; - FrameRateMap FRM = vd_CaptureFormats[size]; - SUBTYPEMap STM = FRM[framerate]; - String subType((*i).pMF_MT_SUBTYPEName); - vectorNum VN = STM[subType]; - VN.push_back(count); - STM[subType] = VN; - FRM[framerate] = STM; - vd_CaptureFormats[size] = FRM; - } - count++; - } -} - -long videoDevice::setDeviceFormat(IMFMediaSource *pSource, unsigned long dwFormatIndex) -{ - _ComPtr pPD = NULL; - _ComPtr pSD = NULL; - _ComPtr pHandler = NULL; - _ComPtr pType = NULL; - HRESULT hr = pSource->CreatePresentationDescriptor(pPD.GetAddressOf()); - if (FAILED(hr)) - { - goto done; - } - BOOL fSelected; - hr = pPD->GetStreamDescriptorByIndex(0, &fSelected, pSD.GetAddressOf()); - if (FAILED(hr)) - { - goto done; - } - hr = pSD->GetMediaTypeHandler(pHandler.GetAddressOf()); - if (FAILED(hr)) - { - goto done; - } - hr = pHandler->GetMediaTypeByIndex((DWORD)dwFormatIndex, pType.GetAddressOf()); - if (FAILED(hr)) - { - goto done; - } - hr = pHandler->SetCurrentMediaType(pType.Get()); - -done: - return hr; -} - -bool videoDevice::isDeviceSetup() -{ - return vd_IsSetuped; -} - -RawImage * videoDevice::getRawImageOut() -{ - if(!vd_IsSetuped) return NULL; - if(vd_pImGrTh) - return vd_pImGrTh->getImageGrabber()->getRawImage(); - else - { - DebugPrintOut(L"VIDEODEVICE %i: The instance of ImageGrabberThread class does not exist \n", vd_CurrentNumber); - } - return NULL; -} - -bool videoDevice::isFrameNew() -{ - if(!vd_IsSetuped) return false; - if(vd_LockOut == RawDataLock || vd_LockOut == OpenLock) - { - if(vd_LockOut == OpenLock) - { - vd_LockOut = RawDataLock; - - //must already be closed - HRESULT hr = ImageGrabberThread::CreateInstance(&vd_pImGrTh, vd_pSource, vd_CurrentNumber); - if(FAILED(hr)) - { - DebugPrintOut(L"VIDEODEVICE %i: The instance of ImageGrabberThread class cannot be created.\n", vd_CurrentNumber); - return false; - } - vd_pImGrTh->setEmergencyStopEvent(vd_userData, vd_func); - vd_pImGrTh->start(); - return true; - } - if(vd_pImGrTh) - return vd_pImGrTh->getImageGrabber()->getRawImage()->isNew(); + PropVariantClear(&var); + return true; } return false; } -bool videoDevice::isDeviceMediaSource() -{ - if(vd_LockOut == MediaSourceLock) return true; - return false; -} - -bool videoDevice::isDeviceRawDataSource() -{ - if(vd_LockOut == RawDataLock) return true; - return false; -} - -bool videoDevice::setupDevice(unsigned int id) -{ - if(!vd_IsSetuped) - { - HRESULT hr; - vd_Width = vd_CurrentFormats[id].width; - vd_Height = vd_CurrentFormats[id].height; - vd_FrameRate = vd_CurrentFormats[id].MF_MT_FRAME_RATE_NUMERATOR / - vd_CurrentFormats[id].MF_MT_FRAME_RATE_DENOMINATOR; - hr = setDeviceFormat(vd_pSource, (DWORD) id); - vd_IsSetuped = (SUCCEEDED(hr)); - if(vd_IsSetuped) - DebugPrintOut(L"\n\nVIDEODEVICE %i: Device is setuped \n", vd_CurrentNumber); - return vd_IsSetuped; - } - else - { - DebugPrintOut(L"VIDEODEVICE %i: Device is setuped already \n", vd_CurrentNumber); - return false; - } -} - -bool videoDevice::setupDevice(unsigned int w, unsigned int h, unsigned int idealFramerate) -{ - int id = findType(w * h, idealFramerate); - if( id < 0 ) - return false; - - return setupDevice(id); -} - -videoDevice::~videoDevice(void) -{ - closeDevice(); - SafeRelease(&vd_pSource); - if(vd_pFriendlyName) - CoTaskMemFree(vd_pFriendlyName); -} - -HRESULT videoDevice::enumerateCaptureFormats(IMFMediaSource *pSource) -{ - HRESULT hr = S_OK; - { // "done:" scope - - _ComPtr pPD = NULL; - _ComPtr pSD = NULL; - _ComPtr pHandler = NULL; - _ComPtr pType = NULL; - hr = !pSource ? E_POINTER : S_OK; - if (FAILED(hr)) - { - goto done; - } - hr = pSource->CreatePresentationDescriptor(pPD.GetAddressOf()); - if (FAILED(hr)) - { - goto done; - } - BOOL fSelected; - hr = pPD->GetStreamDescriptorByIndex(0, &fSelected, pSD.GetAddressOf()); - if (FAILED(hr)) - { - goto done; - } - hr = pSD->GetMediaTypeHandler(pHandler.GetAddressOf()); - if (FAILED(hr)) - { - goto done; - } - DWORD cTypes = 0; - hr = pHandler->GetMediaTypeCount(&cTypes); - if (FAILED(hr)) - { - goto done; - } - for (DWORD i = 0; i < cTypes; i++) - { - hr = pHandler->GetMediaTypeByIndex(i, pType.GetAddressOf()); - if (FAILED(hr)) - { - goto done; - } - MediaType MT = FormatReader::Read(pType.Get()); - vd_CurrentFormats.push_back(MT); - } - - } // "done:" scope -done: - return hr; -} - -videoDevices::videoDevices(void) -{ - DebugPrintOut(L"\n***** VIDEOINPUT LIBRARY - 2013 (Author: Evgeny Pereguda) *****\n\n"); -} - -videoDevices::~videoDevices(void) -{ - DebugPrintOut(L"\n***** CLOSE VIDEOINPUT LIBRARY - 2013 *****\n\n"); -} - -cv::Ptr videoDevices::getDevice(unsigned int i, bool fallback) -{ - static videoDevices instance; - - cv::Ptr res; - - _ComPtr pAttributes = NULL; - if (SUCCEEDED(MFCreateAttributes(pAttributes.GetAddressOf(), 1)) && - SUCCEEDED(pAttributes->SetGUID( - MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, - MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID - ))) - { - IMFActivate **ppDevices = NULL; - UINT32 count; - if (SUCCEEDED(MFEnumDeviceSources(pAttributes.Get(), &ppDevices, &count))) - { - if (count > 0) - { - if (fallback) - i = std::min(std::max(0U, i), count - 1); - - for (UINT32 ind = 0; ind < count; ind++) - { - if (ind == i) - { - res = cv::Ptr(new videoDevice); - res->readInfoOfDevice(ppDevices[ind], ind); - res->setupDevice(0, 0, 0); - if (!res->isDeviceSetup() || !res->isFrameNew()) - res.release(); - } - SafeRelease(&ppDevices[ind]); - } - } - } - else - DebugPrintOut(L"VIDEODEVICES: The instances of the videoDevice class cannot be created\n"); - CoTaskMemFree(ppDevices); - } - - if (res.empty()) - DebugPrintOut(L"VIDEODEVICE %i: Invalid device ID\n", i); - return res; -} - -Parametr::Parametr() -{ - CurrentValue = 0; - Min = 0; - Max = 0; - Step = 0; - Default = 0; - Flag = 0; -} - MediaType::MediaType() { - pMF_MT_AM_FORMAT_TYPEName = NULL; pMF_MT_MAJOR_TYPEName = NULL; pMF_MT_SUBTYPEName = NULL; Clear(); } +MediaType::MediaType(IMFMediaType *pType) +{ + UINT32 count = 0; + if (SUCCEEDED(pType->GetCount(&count)) && + SUCCEEDED(pType->LockStore())) + { + for (UINT32 i = 0; i < count; i++) + if (!LogAttributeValueByIndexNew(pType, i, *this)) + break; + pType->UnlockStore(); + } +} + MediaType::~MediaType() { Clear(); @@ -2067,7 +864,7 @@ bool CvCaptureCAM_MSMF::configureOutput(unsigned int width, unsigned int height, } else if (SUCCEEDED(hr)) { - MediaType MT = FormatReader::Read(pType.Get()); + MediaType MT(pType.Get()); if (MT.MF_MT_MAJOR_TYPE == MFMediaType_Video) { if (dwStreamFallback < 0 || @@ -2160,7 +957,8 @@ bool CvCaptureCAM_MSMF::open(int _index) configureOutput(0, 0, 0); } } - SafeRelease(&ppDevices[ind]); + if (ppDevices[ind]) + ppDevices[ind]->Release(); } } } @@ -2407,7 +1205,7 @@ bool CvCaptureFile_MSMF::open(const char* filename) } else if (SUCCEEDED(hr)) { - MediaType MT = FormatReader::Read(pType.Get()); + MediaType MT(pType.Get()); if (MT.MF_MT_MAJOR_TYPE == MFMediaType_Video) { captureFormat = MT; diff --git a/modules/videoio/src/cap_msmf.hpp b/modules/videoio/src/cap_msmf.hpp index 04aa3b9806..e69de29bb2 100644 --- a/modules/videoio/src/cap_msmf.hpp +++ b/modules/videoio/src/cap_msmf.hpp @@ -1,2504 +0,0 @@ -EXTERN_C const IID IID_ICustomStreamSink; - -class DECLSPEC_UUID("4F8A1939-2FD3-46DB-AE70-DB7E0DD79B73") DECLSPEC_NOVTABLE ICustomStreamSink : public IUnknown -{ -public: - virtual HRESULT Initialize() = 0; - virtual HRESULT Shutdown() = 0; - virtual HRESULT Start(MFTIME start) = 0; - virtual HRESULT Pause() = 0; - virtual HRESULT Restart() = 0; - virtual HRESULT Stop() = 0; -}; - -#define MF_PROP_SAMPLEGRABBERCALLBACK L"samplegrabbercallback" -#define MF_PROP_VIDTYPE L"vidtype" -#define MF_PROP_VIDENCPROPS L"videncprops" - -#include - -// MF_MEDIASINK_SAMPLEGRABBERCALLBACK: {26957AA7-AFF4-464c-BB8B-07BA65CE11DF} -// Type: IUnknown* -DEFINE_GUID(MF_MEDIASINK_SAMPLEGRABBERCALLBACK, - 0x26957aa7, 0xaff4, 0x464c, 0xbb, 0x8b, 0x7, 0xba, 0x65, 0xce, 0x11, 0xdf); - -// {4BD133CC-EB9B-496E-8865-0813BFBC6FAA} -DEFINE_GUID(MF_STREAMSINK_ID, 0x4bd133cc, 0xeb9b, 0x496e, 0x88, 0x65, 0x8, 0x13, 0xbf, 0xbc, 0x6f, 0xaa); - -// {C9E22A8C-6A50-4D78-9183-0834A02A3780} -DEFINE_GUID(MF_STREAMSINK_MEDIASINKINTERFACE, - 0xc9e22a8c, 0x6a50, 0x4d78, 0x91, 0x83, 0x8, 0x34, 0xa0, 0x2a, 0x37, 0x80); - -// {DABD13AB-26B7-47C2-97C1-4B04C187B838} -DEFINE_GUID(MF_MEDIASINK_PREFERREDTYPE, - 0xdabd13ab, 0x26b7, 0x47c2, 0x97, 0xc1, 0x4b, 0x4, 0xc1, 0x87, 0xb8, 0x38); - -#include -#ifdef _UNICODE -#define MAKE_MAP(e) std::map -#define MAKE_ENUM(e) std::pair -#define MAKE_ENUM_PAIR(e, str) std::pair(str, L#str) -#else -#define MAKE_MAP(e) std::map -#define MAKE_ENUM(e) std::pair -#define MAKE_ENUM_PAIR(e, str) std::pair(str, #str) -#endif - -MAKE_ENUM(MediaEventType) MediaEventTypePairs[] = { - MAKE_ENUM_PAIR(MediaEventType, MEUnknown), - MAKE_ENUM_PAIR(MediaEventType, MEError), - MAKE_ENUM_PAIR(MediaEventType, MEExtendedType), - MAKE_ENUM_PAIR(MediaEventType, MENonFatalError), - MAKE_ENUM_PAIR(MediaEventType, MEGenericV1Anchor), - MAKE_ENUM_PAIR(MediaEventType, MESessionUnknown), - MAKE_ENUM_PAIR(MediaEventType, MESessionTopologySet), - MAKE_ENUM_PAIR(MediaEventType, MESessionTopologiesCleared), - MAKE_ENUM_PAIR(MediaEventType, MESessionStarted), - MAKE_ENUM_PAIR(MediaEventType, MESessionPaused), - MAKE_ENUM_PAIR(MediaEventType, MESessionStopped), - MAKE_ENUM_PAIR(MediaEventType, MESessionClosed), - MAKE_ENUM_PAIR(MediaEventType, MESessionEnded), - MAKE_ENUM_PAIR(MediaEventType, MESessionRateChanged), - MAKE_ENUM_PAIR(MediaEventType, MESessionScrubSampleComplete), - MAKE_ENUM_PAIR(MediaEventType, MESessionCapabilitiesChanged), - MAKE_ENUM_PAIR(MediaEventType, MESessionTopologyStatus), - MAKE_ENUM_PAIR(MediaEventType, MESessionNotifyPresentationTime), - MAKE_ENUM_PAIR(MediaEventType, MENewPresentation), - MAKE_ENUM_PAIR(MediaEventType, MELicenseAcquisitionStart), - MAKE_ENUM_PAIR(MediaEventType, MELicenseAcquisitionCompleted), - MAKE_ENUM_PAIR(MediaEventType, MEIndividualizationStart), - MAKE_ENUM_PAIR(MediaEventType, MEIndividualizationCompleted), - MAKE_ENUM_PAIR(MediaEventType, MEEnablerProgress), - MAKE_ENUM_PAIR(MediaEventType, MEEnablerCompleted), - MAKE_ENUM_PAIR(MediaEventType, MEPolicyError), - MAKE_ENUM_PAIR(MediaEventType, MEPolicyReport), - MAKE_ENUM_PAIR(MediaEventType, MEBufferingStarted), - MAKE_ENUM_PAIR(MediaEventType, MEBufferingStopped), - MAKE_ENUM_PAIR(MediaEventType, MEConnectStart), - MAKE_ENUM_PAIR(MediaEventType, MEConnectEnd), - MAKE_ENUM_PAIR(MediaEventType, MEReconnectStart), - MAKE_ENUM_PAIR(MediaEventType, MEReconnectEnd), - MAKE_ENUM_PAIR(MediaEventType, MERendererEvent), - MAKE_ENUM_PAIR(MediaEventType, MESessionStreamSinkFormatChanged), - MAKE_ENUM_PAIR(MediaEventType, MESessionV1Anchor), - MAKE_ENUM_PAIR(MediaEventType, MESourceUnknown), - MAKE_ENUM_PAIR(MediaEventType, MESourceStarted), - MAKE_ENUM_PAIR(MediaEventType, MEStreamStarted), - MAKE_ENUM_PAIR(MediaEventType, MESourceSeeked), - MAKE_ENUM_PAIR(MediaEventType, MEStreamSeeked), - MAKE_ENUM_PAIR(MediaEventType, MENewStream), - MAKE_ENUM_PAIR(MediaEventType, MEUpdatedStream), - MAKE_ENUM_PAIR(MediaEventType, MESourceStopped), - MAKE_ENUM_PAIR(MediaEventType, MEStreamStopped), - MAKE_ENUM_PAIR(MediaEventType, MESourcePaused), - MAKE_ENUM_PAIR(MediaEventType, MEStreamPaused), - MAKE_ENUM_PAIR(MediaEventType, MEEndOfPresentation), - MAKE_ENUM_PAIR(MediaEventType, MEEndOfStream), - MAKE_ENUM_PAIR(MediaEventType, MEMediaSample), - MAKE_ENUM_PAIR(MediaEventType, MEStreamTick), - MAKE_ENUM_PAIR(MediaEventType, MEStreamThinMode), - MAKE_ENUM_PAIR(MediaEventType, MEStreamFormatChanged), - MAKE_ENUM_PAIR(MediaEventType, MESourceRateChanged), - MAKE_ENUM_PAIR(MediaEventType, MEEndOfPresentationSegment), - MAKE_ENUM_PAIR(MediaEventType, MESourceCharacteristicsChanged), - MAKE_ENUM_PAIR(MediaEventType, MESourceRateChangeRequested), - MAKE_ENUM_PAIR(MediaEventType, MESourceMetadataChanged), - MAKE_ENUM_PAIR(MediaEventType, MESequencerSourceTopologyUpdated), - MAKE_ENUM_PAIR(MediaEventType, MESourceV1Anchor), - MAKE_ENUM_PAIR(MediaEventType, MESinkUnknown), - MAKE_ENUM_PAIR(MediaEventType, MEStreamSinkStarted), - MAKE_ENUM_PAIR(MediaEventType, MEStreamSinkStopped), - MAKE_ENUM_PAIR(MediaEventType, MEStreamSinkPaused), - MAKE_ENUM_PAIR(MediaEventType, MEStreamSinkRateChanged), - MAKE_ENUM_PAIR(MediaEventType, MEStreamSinkRequestSample), - MAKE_ENUM_PAIR(MediaEventType, MEStreamSinkMarker), - MAKE_ENUM_PAIR(MediaEventType, MEStreamSinkPrerolled), - MAKE_ENUM_PAIR(MediaEventType, MEStreamSinkScrubSampleComplete), - MAKE_ENUM_PAIR(MediaEventType, MEStreamSinkFormatChanged), - MAKE_ENUM_PAIR(MediaEventType, MEStreamSinkDeviceChanged), - MAKE_ENUM_PAIR(MediaEventType, MEQualityNotify), - MAKE_ENUM_PAIR(MediaEventType, MESinkInvalidated), - MAKE_ENUM_PAIR(MediaEventType, MEAudioSessionNameChanged), - MAKE_ENUM_PAIR(MediaEventType, MEAudioSessionVolumeChanged), - MAKE_ENUM_PAIR(MediaEventType, MEAudioSessionDeviceRemoved), - MAKE_ENUM_PAIR(MediaEventType, MEAudioSessionServerShutdown), - MAKE_ENUM_PAIR(MediaEventType, MEAudioSessionGroupingParamChanged), - MAKE_ENUM_PAIR(MediaEventType, MEAudioSessionIconChanged), - MAKE_ENUM_PAIR(MediaEventType, MEAudioSessionFormatChanged), - MAKE_ENUM_PAIR(MediaEventType, MEAudioSessionDisconnected), - MAKE_ENUM_PAIR(MediaEventType, MEAudioSessionExclusiveModeOverride), - MAKE_ENUM_PAIR(MediaEventType, MESinkV1Anchor), -#if (WINVER >= 0x0602) // Available since Win 8 - MAKE_ENUM_PAIR(MediaEventType, MECaptureAudioSessionVolumeChanged), - MAKE_ENUM_PAIR(MediaEventType, MECaptureAudioSessionDeviceRemoved), - MAKE_ENUM_PAIR(MediaEventType, MECaptureAudioSessionFormatChanged), - MAKE_ENUM_PAIR(MediaEventType, MECaptureAudioSessionDisconnected), - MAKE_ENUM_PAIR(MediaEventType, MECaptureAudioSessionExclusiveModeOverride), - MAKE_ENUM_PAIR(MediaEventType, MECaptureAudioSessionServerShutdown), - MAKE_ENUM_PAIR(MediaEventType, MESinkV2Anchor), -#endif - MAKE_ENUM_PAIR(MediaEventType, METrustUnknown), - MAKE_ENUM_PAIR(MediaEventType, MEPolicyChanged), - MAKE_ENUM_PAIR(MediaEventType, MEContentProtectionMessage), - MAKE_ENUM_PAIR(MediaEventType, MEPolicySet), - MAKE_ENUM_PAIR(MediaEventType, METrustV1Anchor), - MAKE_ENUM_PAIR(MediaEventType, MEWMDRMLicenseBackupCompleted), - MAKE_ENUM_PAIR(MediaEventType, MEWMDRMLicenseBackupProgress), - MAKE_ENUM_PAIR(MediaEventType, MEWMDRMLicenseRestoreCompleted), - MAKE_ENUM_PAIR(MediaEventType, MEWMDRMLicenseRestoreProgress), - MAKE_ENUM_PAIR(MediaEventType, MEWMDRMLicenseAcquisitionCompleted), - MAKE_ENUM_PAIR(MediaEventType, MEWMDRMIndividualizationCompleted), - MAKE_ENUM_PAIR(MediaEventType, MEWMDRMIndividualizationProgress), - MAKE_ENUM_PAIR(MediaEventType, MEWMDRMProximityCompleted), - MAKE_ENUM_PAIR(MediaEventType, MEWMDRMLicenseStoreCleaned), - MAKE_ENUM_PAIR(MediaEventType, MEWMDRMRevocationDownloadCompleted), - MAKE_ENUM_PAIR(MediaEventType, MEWMDRMV1Anchor), - MAKE_ENUM_PAIR(MediaEventType, METransformUnknown), - MAKE_ENUM_PAIR(MediaEventType, METransformNeedInput), - MAKE_ENUM_PAIR(MediaEventType, METransformHaveOutput), - MAKE_ENUM_PAIR(MediaEventType, METransformDrainComplete), - MAKE_ENUM_PAIR(MediaEventType, METransformMarker), -#if (WINVER >= 0x0602) // Available since Win 8 - MAKE_ENUM_PAIR(MediaEventType, MEByteStreamCharacteristicsChanged), - MAKE_ENUM_PAIR(MediaEventType, MEVideoCaptureDeviceRemoved), - MAKE_ENUM_PAIR(MediaEventType, MEVideoCaptureDevicePreempted), -#endif - MAKE_ENUM_PAIR(MediaEventType, MEReservedMax) -}; -MAKE_MAP(MediaEventType) MediaEventTypeMap(MediaEventTypePairs, MediaEventTypePairs + sizeof(MediaEventTypePairs) / sizeof(MediaEventTypePairs[0])); - -MAKE_ENUM(MFSTREAMSINK_MARKER_TYPE) StreamSinkMarkerTypePairs[] = { - MAKE_ENUM_PAIR(MFSTREAMSINK_MARKER_TYPE, MFSTREAMSINK_MARKER_DEFAULT), - MAKE_ENUM_PAIR(MFSTREAMSINK_MARKER_TYPE, MFSTREAMSINK_MARKER_ENDOFSEGMENT), - MAKE_ENUM_PAIR(MFSTREAMSINK_MARKER_TYPE, MFSTREAMSINK_MARKER_TICK), - MAKE_ENUM_PAIR(MFSTREAMSINK_MARKER_TYPE, MFSTREAMSINK_MARKER_EVENT) -}; -MAKE_MAP(MFSTREAMSINK_MARKER_TYPE) StreamSinkMarkerTypeMap(StreamSinkMarkerTypePairs, StreamSinkMarkerTypePairs + sizeof(StreamSinkMarkerTypePairs) / sizeof(StreamSinkMarkerTypePairs[0])); - - -#define _COM_SMARTPTR_DECLARE(T,var) T ## Ptr var - -template -class ComPtr -{ -public: - ComPtr() throw() - { - } - ComPtr(T* lp) throw() - { - p = lp; - } - ComPtr(_In_ const ComPtr& lp) throw() - { - p = lp.p; - } - virtual ~ComPtr() - { - } - - T** operator&() throw() - { - assert(p == NULL); - return p.operator&(); - } - T* operator->() const throw() - { - assert(p != NULL); - return p.operator->(); - } - bool operator!() const throw() - { - return p.operator==(NULL); - } - bool operator==(_In_opt_ T* pT) const throw() - { - return p.operator==(pT); - } - bool operator!=(_In_opt_ T* pT) const throw() - { - return p.operator!=(pT); - } - operator bool() - { - return p.operator!=(NULL); - } - - T* const* GetAddressOf() const throw() - { - return &p; - } - - T** GetAddressOf() throw() - { - return &p; - } - - T** ReleaseAndGetAddressOf() throw() - { - p.Release(); - return &p; - } - - T* Get() const throw() - { - return p; - } - - // Attach to an existing interface (does not AddRef) - void Attach(_In_opt_ T* p2) throw() - { - p.Attach(p2); - } - // Detach the interface (does not Release) - T* Detach() throw() - { - return p.Detach(); - } - _Check_return_ HRESULT CopyTo(_Deref_out_opt_ T** ppT) throw() - { - assert(ppT != NULL); - if (ppT == NULL) - return E_POINTER; - *ppT = p; - if (p != NULL) - p->AddRef(); - return S_OK; - } - - void Reset() - { - p.Release(); - } - - // query for U interface - template - HRESULT As(_Inout_ U** lp) const throw() - { - return p->QueryInterface(__uuidof(U), reinterpret_cast(lp)); - } - // query for U interface - template - HRESULT As(_Out_ ComPtr* lp) const throw() - { - return p->QueryInterface(__uuidof(U), reinterpret_cast(lp->ReleaseAndGetAddressOf())); - } -private: - _COM_SMARTPTR_TYPEDEF(T, __uuidof(T)); - _COM_SMARTPTR_DECLARE(T, p); -}; - -#define _ComPtr ComPtr - -template -class CBaseAttributes : public TBase -{ -protected: - // This version of the constructor does not initialize the - // attribute store. The derived class must call Initialize() in - // its own constructor. - CBaseAttributes() - { - } - - // This version of the constructor initializes the attribute - // store, but the derived class must pass an HRESULT parameter - // to the constructor. - - CBaseAttributes(HRESULT& hr, UINT32 cInitialSize = 0) - { - hr = Initialize(cInitialSize); - } - - // The next version of the constructor uses a caller-provided - // implementation of IMFAttributes. - - // (Sometimes you want to delegate IMFAttributes calls to some - // other object that implements IMFAttributes, rather than using - // MFCreateAttributes.) - - CBaseAttributes(HRESULT& hr, IUnknown *pUnk) - { - hr = Initialize(pUnk); - } - - virtual ~CBaseAttributes() - { - } - - // Initializes the object by creating the standard Media Foundation attribute store. - HRESULT Initialize(UINT32 cInitialSize = 0) - { - if (_spAttributes.Get() == nullptr) - { - return MFCreateAttributes(&_spAttributes, cInitialSize); - } - else - { - return S_OK; - } - } - - // Initializes this object from a caller-provided attribute store. - // pUnk: Pointer to an object that exposes IMFAttributes. - HRESULT Initialize(IUnknown *pUnk) - { - if (_spAttributes) - { - _spAttributes.Reset(); - _spAttributes = nullptr; - } - - - return pUnk->QueryInterface(IID_PPV_ARGS(&_spAttributes)); - } - -public: - - // IMFAttributes methods - - STDMETHODIMP GetItem(REFGUID guidKey, PROPVARIANT* pValue) - { - assert(_spAttributes); - return _spAttributes->GetItem(guidKey, pValue); - } - - STDMETHODIMP GetItemType(REFGUID guidKey, MF_ATTRIBUTE_TYPE* pType) - { - assert(_spAttributes); - return _spAttributes->GetItemType(guidKey, pType); - } - - STDMETHODIMP CompareItem(REFGUID guidKey, REFPROPVARIANT Value, BOOL* pbResult) - { - assert(_spAttributes); - return _spAttributes->CompareItem(guidKey, Value, pbResult); - } - - STDMETHODIMP Compare( - IMFAttributes* pTheirs, - MF_ATTRIBUTES_MATCH_TYPE MatchType, - BOOL* pbResult - ) - { - assert(_spAttributes); - return _spAttributes->Compare(pTheirs, MatchType, pbResult); - } - - STDMETHODIMP GetUINT32(REFGUID guidKey, UINT32* punValue) - { - assert(_spAttributes); - return _spAttributes->GetUINT32(guidKey, punValue); - } - - STDMETHODIMP GetUINT64(REFGUID guidKey, UINT64* punValue) - { - assert(_spAttributes); - return _spAttributes->GetUINT64(guidKey, punValue); - } - - STDMETHODIMP GetDouble(REFGUID guidKey, double* pfValue) - { - assert(_spAttributes); - return _spAttributes->GetDouble(guidKey, pfValue); - } - - STDMETHODIMP GetGUID(REFGUID guidKey, GUID* pguidValue) - { - assert(_spAttributes); - return _spAttributes->GetGUID(guidKey, pguidValue); - } - - STDMETHODIMP GetStringLength(REFGUID guidKey, UINT32* pcchLength) - { - assert(_spAttributes); - return _spAttributes->GetStringLength(guidKey, pcchLength); - } - - STDMETHODIMP GetString(REFGUID guidKey, LPWSTR pwszValue, UINT32 cchBufSize, UINT32* pcchLength) - { - assert(_spAttributes); - return _spAttributes->GetString(guidKey, pwszValue, cchBufSize, pcchLength); - } - - STDMETHODIMP GetAllocatedString(REFGUID guidKey, LPWSTR* ppwszValue, UINT32* pcchLength) - { - assert(_spAttributes); - return _spAttributes->GetAllocatedString(guidKey, ppwszValue, pcchLength); - } - - STDMETHODIMP GetBlobSize(REFGUID guidKey, UINT32* pcbBlobSize) - { - assert(_spAttributes); - return _spAttributes->GetBlobSize(guidKey, pcbBlobSize); - } - - STDMETHODIMP GetBlob(REFGUID guidKey, UINT8* pBuf, UINT32 cbBufSize, UINT32* pcbBlobSize) - { - assert(_spAttributes); - return _spAttributes->GetBlob(guidKey, pBuf, cbBufSize, pcbBlobSize); - } - - STDMETHODIMP GetAllocatedBlob(REFGUID guidKey, UINT8** ppBuf, UINT32* pcbSize) - { - assert(_spAttributes); - return _spAttributes->GetAllocatedBlob(guidKey, ppBuf, pcbSize); - } - - STDMETHODIMP GetUnknown(REFGUID guidKey, REFIID riid, LPVOID* ppv) - { - assert(_spAttributes); - return _spAttributes->GetUnknown(guidKey, riid, ppv); - } - - STDMETHODIMP SetItem(REFGUID guidKey, REFPROPVARIANT Value) - { - assert(_spAttributes); - return _spAttributes->SetItem(guidKey, Value); - } - - STDMETHODIMP DeleteItem(REFGUID guidKey) - { - assert(_spAttributes); - return _spAttributes->DeleteItem(guidKey); - } - - STDMETHODIMP DeleteAllItems() - { - assert(_spAttributes); - return _spAttributes->DeleteAllItems(); - } - - STDMETHODIMP SetUINT32(REFGUID guidKey, UINT32 unValue) - { - assert(_spAttributes); - return _spAttributes->SetUINT32(guidKey, unValue); - } - - STDMETHODIMP SetUINT64(REFGUID guidKey,UINT64 unValue) - { - assert(_spAttributes); - return _spAttributes->SetUINT64(guidKey, unValue); - } - - STDMETHODIMP SetDouble(REFGUID guidKey, double fValue) - { - assert(_spAttributes); - return _spAttributes->SetDouble(guidKey, fValue); - } - - STDMETHODIMP SetGUID(REFGUID guidKey, REFGUID guidValue) - { - assert(_spAttributes); - return _spAttributes->SetGUID(guidKey, guidValue); - } - - STDMETHODIMP SetString(REFGUID guidKey, LPCWSTR wszValue) - { - assert(_spAttributes); - return _spAttributes->SetString(guidKey, wszValue); - } - - STDMETHODIMP SetBlob(REFGUID guidKey, const UINT8* pBuf, UINT32 cbBufSize) - { - assert(_spAttributes); - return _spAttributes->SetBlob(guidKey, pBuf, cbBufSize); - } - - STDMETHODIMP SetUnknown(REFGUID guidKey, IUnknown* pUnknown) - { - assert(_spAttributes); - return _spAttributes->SetUnknown(guidKey, pUnknown); - } - - STDMETHODIMP LockStore() - { - assert(_spAttributes); - return _spAttributes->LockStore(); - } - - STDMETHODIMP UnlockStore() - { - assert(_spAttributes); - return _spAttributes->UnlockStore(); - } - - STDMETHODIMP GetCount(UINT32* pcItems) - { - assert(_spAttributes); - return _spAttributes->GetCount(pcItems); - } - - STDMETHODIMP GetItemByIndex(UINT32 unIndex, GUID* pguidKey, PROPVARIANT* pValue) - { - assert(_spAttributes); - return _spAttributes->GetItemByIndex(unIndex, pguidKey, pValue); - } - - STDMETHODIMP CopyAllItems(IMFAttributes* pDest) - { - assert(_spAttributes); - return _spAttributes->CopyAllItems(pDest); - } - - // Helper functions - - HRESULT SerializeToStream(DWORD dwOptions, IStream* pStm) - // dwOptions: Flags from MF_ATTRIBUTE_SERIALIZE_OPTIONS - { - assert(_spAttributes); - return MFSerializeAttributesToStream(_spAttributes.Get(), dwOptions, pStm); - } - - HRESULT DeserializeFromStream(DWORD dwOptions, IStream* pStm) - { - assert(_spAttributes); - return MFDeserializeAttributesFromStream(_spAttributes.Get(), dwOptions, pStm); - } - - // SerializeToBlob: Stores the attributes in a byte array. - // - // ppBuf: Receives a pointer to the byte array. - // pcbSize: Receives the size of the byte array. - // - // The caller must free the array using CoTaskMemFree. - HRESULT SerializeToBlob(UINT8 **ppBuffer, UINT *pcbSize) - { - assert(_spAttributes); - - if (ppBuffer == NULL) - { - return E_POINTER; - } - if (pcbSize == NULL) - { - return E_POINTER; - } - - HRESULT hr = S_OK; - UINT32 cbSize = 0; - BYTE *pBuffer = NULL; - - CHECK_HR(hr = MFGetAttributesAsBlobSize(_spAttributes.Get(), &cbSize)); - - pBuffer = (BYTE*)CoTaskMemAlloc(cbSize); - if (pBuffer == NULL) - { - CHECK_HR(hr = E_OUTOFMEMORY); - } - - CHECK_HR(hr = MFGetAttributesAsBlob(_spAttributes.Get(), pBuffer, cbSize)); - - *ppBuffer = pBuffer; - *pcbSize = cbSize; - -done: - if (FAILED(hr)) - { - *ppBuffer = NULL; - *pcbSize = 0; - CoTaskMemFree(pBuffer); - } - return hr; - } - - HRESULT DeserializeFromBlob(const UINT8* pBuffer, UINT cbSize) - { - assert(_spAttributes); - return MFInitAttributesFromBlob(_spAttributes.Get(), pBuffer, cbSize); - } - - HRESULT GetRatio(REFGUID guidKey, UINT32* pnNumerator, UINT32* punDenominator) - { - assert(_spAttributes); - return MFGetAttributeRatio(_spAttributes.Get(), guidKey, pnNumerator, punDenominator); - } - - HRESULT SetRatio(REFGUID guidKey, UINT32 unNumerator, UINT32 unDenominator) - { - assert(_spAttributes); - return MFSetAttributeRatio(_spAttributes.Get(), guidKey, unNumerator, unDenominator); - } - - // Gets an attribute whose value represents the size of something (eg a video frame). - HRESULT GetSize(REFGUID guidKey, UINT32* punWidth, UINT32* punHeight) - { - assert(_spAttributes); - return MFGetAttributeSize(_spAttributes.Get(), guidKey, punWidth, punHeight); - } - - // Sets an attribute whose value represents the size of something (eg a video frame). - HRESULT SetSize(REFGUID guidKey, UINT32 unWidth, UINT32 unHeight) - { - assert(_spAttributes); - return MFSetAttributeSize (_spAttributes.Get(), guidKey, unWidth, unHeight); - } - -protected: - _ComPtr _spAttributes; -}; - -class StreamSink : - public IMFStreamSink, - public IMFMediaTypeHandler, - public CBaseAttributes<>, - public ICustomStreamSink -{ -public: - // IUnknown methods -#if defined(_MSC_VER) && _MSC_VER >= 1700 // '_Outptr_result_nullonfailure_' SAL is avaialable since VS 2012 - STDMETHOD(QueryInterface)(REFIID riid, _Outptr_result_nullonfailure_ void **ppv) -#else - STDMETHOD(QueryInterface)(REFIID riid, void **ppv) -#endif - { - if (ppv == nullptr) { - return E_POINTER; - } - (*ppv) = nullptr; - HRESULT hr = S_OK; - if (riid == IID_IMarshal) { - return MarshalQI(riid, ppv); - } else { - if (riid == IID_IUnknown || riid == IID_IMFStreamSink) { - *ppv = static_cast(this); - AddRef(); - } else if (riid == IID_IMFMediaEventGenerator) { - *ppv = static_cast(this); - AddRef(); - } else if (riid == IID_IMFMediaTypeHandler) { - *ppv = static_cast(this); - AddRef(); - } else if (riid == IID_IMFAttributes) { - *ppv = static_cast(this); - AddRef(); - } else if (riid == IID_ICustomStreamSink) { - *ppv = static_cast(this); - AddRef(); - } else - hr = E_NOINTERFACE; - } - - return hr; - } - - ULONG STDMETHODCALLTYPE AddRef() - { - return InterlockedIncrement(&m_cRef); - } - ULONG STDMETHODCALLTYPE Release() - { - ULONG cRef = InterlockedDecrement(&m_cRef); - if (cRef == 0) - { - delete this; - } - return cRef; - } - HRESULT MarshalQI(REFIID riid, LPVOID* ppv) - { - HRESULT hr = S_OK; - if (m_spFTM == nullptr) { - EnterCriticalSection(&m_critSec); - if (m_spFTM == nullptr) { - hr = CoCreateFreeThreadedMarshaler((IMFStreamSink*)this, &m_spFTM); - } - LeaveCriticalSection(&m_critSec); - } - - if (SUCCEEDED(hr)) { - if (m_spFTM == nullptr) { - hr = E_UNEXPECTED; - } - else { - hr = m_spFTM.Get()->QueryInterface(riid, ppv); - } - } - return hr; - } - enum State - { - State_TypeNotSet = 0, // No media type is set - State_Ready, // Media type is set, Start has never been called. - State_Started, - State_Stopped, - State_Paused, - State_Count // Number of states - }; - StreamSink() : m_IsShutdown(false), - m_StartTime(0), m_fGetStartTimeFromSample(false), m_fWaitingForFirstSample(false), - m_state(State_TypeNotSet), m_pParent(nullptr), - m_imageWidthInPixels(0), m_imageHeightInPixels(0) { - m_bConnected = false; - InitializeCriticalSectionEx(&m_critSec, 3000, 0); - ZeroMemory(&m_guiCurrentSubtype, sizeof(m_guiCurrentSubtype)); - CBaseAttributes::Initialize(0U); - DebugPrintOut(L"StreamSink::StreamSink\n"); - } - virtual ~StreamSink() { - DeleteCriticalSection(&m_critSec); - assert(m_IsShutdown); - DebugPrintOut(L"StreamSink::~StreamSink\n"); - } - - HRESULT Initialize() - { - HRESULT hr; - // Create the event queue helper. - hr = MFCreateEventQueue(&m_spEventQueue); - if (SUCCEEDED(hr)) - { - _ComPtr pMedSink; - hr = CBaseAttributes<>::GetUnknown(MF_STREAMSINK_MEDIASINKINTERFACE, __uuidof(IMFMediaSink), (LPVOID*)pMedSink.GetAddressOf()); - assert(pMedSink.Get() != NULL); - if (SUCCEEDED(hr)) { - hr = pMedSink.Get()->QueryInterface(IID_PPV_ARGS(&m_pParent)); - } - } - return hr; - } - - HRESULT CheckShutdown() const - { - if (m_IsShutdown) - { - return MF_E_SHUTDOWN; - } - else - { - return S_OK; - } - } - // Called when the presentation clock starts. - HRESULT Start(MFTIME start) - { - HRESULT hr = S_OK; - EnterCriticalSection(&m_critSec); - if (m_state != State_TypeNotSet) { - if (start != PRESENTATION_CURRENT_POSITION) - { - m_StartTime = start; // Cache the start time. - m_fGetStartTimeFromSample = false; - } - else - { - m_fGetStartTimeFromSample = true; - } - m_state = State_Started; - GUID guiMajorType; - m_fWaitingForFirstSample = SUCCEEDED(m_spCurrentType->GetMajorType(&guiMajorType)) && (guiMajorType == MFMediaType_Video); - hr = QueueEvent(MEStreamSinkStarted, GUID_NULL, hr, NULL); - if (SUCCEEDED(hr)) { - hr = QueueEvent(MEStreamSinkRequestSample, GUID_NULL, hr, NULL); - } - } - else hr = MF_E_NOT_INITIALIZED; - LeaveCriticalSection(&m_critSec); - return hr; - } - - // Called when the presentation clock pauses. - HRESULT Pause() - { - EnterCriticalSection(&m_critSec); - - HRESULT hr = S_OK; - - if (m_state != State_Stopped && m_state != State_TypeNotSet) { - m_state = State_Paused; - hr = QueueEvent(MEStreamSinkPaused, GUID_NULL, hr, NULL); - } else if (hr == State_TypeNotSet) - hr = MF_E_NOT_INITIALIZED; - else - hr = MF_E_INVALIDREQUEST; - LeaveCriticalSection(&m_critSec); - return hr; - } - // Called when the presentation clock restarts. - HRESULT Restart() - { - EnterCriticalSection(&m_critSec); - - HRESULT hr = S_OK; - - if (m_state == State_Paused) { - m_state = State_Started; - hr = QueueEvent(MEStreamSinkStarted, GUID_NULL, hr, NULL); - if (SUCCEEDED(hr)) { - hr = QueueEvent(MEStreamSinkRequestSample, GUID_NULL, hr, NULL); - } - } else if (hr == State_TypeNotSet) - hr = MF_E_NOT_INITIALIZED; - else - hr = MF_E_INVALIDREQUEST; - LeaveCriticalSection(&m_critSec); - return hr; - } - // Called when the presentation clock stops. - HRESULT Stop() - { - EnterCriticalSection(&m_critSec); - - HRESULT hr = S_OK; - if (m_state != State_TypeNotSet) { - m_state = State_Stopped; - hr = QueueEvent(MEStreamSinkStopped, GUID_NULL, hr, NULL); - } - else hr = MF_E_NOT_INITIALIZED; - LeaveCriticalSection(&m_critSec); - return hr; - } - - // Shuts down the stream sink. - HRESULT Shutdown() - { - _ComPtr pSampleCallback; - HRESULT hr = S_OK; - assert(!m_IsShutdown); - hr = m_pParent->GetUnknown(MF_MEDIASINK_SAMPLEGRABBERCALLBACK, IID_IMFSampleGrabberSinkCallback, (LPVOID*)pSampleCallback.GetAddressOf()); - if (SUCCEEDED(hr)) { - hr = pSampleCallback->OnShutdown(); - } - - if (m_spEventQueue) { - hr = m_spEventQueue->Shutdown(); - } - if (m_pParent) - m_pParent->Release(); - m_spCurrentType.Reset(); - m_IsShutdown = TRUE; - - return hr; - } - - //IMFStreamSink - HRESULT STDMETHODCALLTYPE GetMediaSink( - /* [out] */ __RPC__deref_out_opt IMFMediaSink **ppMediaSink) { - if (ppMediaSink == NULL) - { - return E_INVALIDARG; - } - - EnterCriticalSection(&m_critSec); - - HRESULT hr = CheckShutdown(); - - if (SUCCEEDED(hr)) - { - _ComPtr pMedSink; - hr = CBaseAttributes<>::GetUnknown(MF_STREAMSINK_MEDIASINKINTERFACE, __uuidof(IMFMediaSink), (LPVOID*)pMedSink.GetAddressOf()); - if (SUCCEEDED(hr)) { - *ppMediaSink = pMedSink.Detach(); - } - } - - LeaveCriticalSection(&m_critSec); - DebugPrintOut(L"StreamSink::GetMediaSink: HRESULT=%i\n", hr); - return hr; - } - - HRESULT STDMETHODCALLTYPE GetIdentifier( - /* [out] */ __RPC__out DWORD *pdwIdentifier) { - if (pdwIdentifier == NULL) - { - return E_INVALIDARG; - } - - EnterCriticalSection(&m_critSec); - - HRESULT hr = CheckShutdown(); - - if (SUCCEEDED(hr)) - { - hr = GetUINT32(MF_STREAMSINK_ID, (UINT32*)pdwIdentifier); - } - - LeaveCriticalSection(&m_critSec); - DebugPrintOut(L"StreamSink::GetIdentifier: HRESULT=%i\n", hr); - return hr; - } - - HRESULT STDMETHODCALLTYPE GetMediaTypeHandler( - /* [out] */ __RPC__deref_out_opt IMFMediaTypeHandler **ppHandler) { - if (ppHandler == NULL) - { - return E_INVALIDARG; - } - - EnterCriticalSection(&m_critSec); - - HRESULT hr = CheckShutdown(); - - // This stream object acts as its own type handler, so we QI ourselves. - if (SUCCEEDED(hr)) - { - hr = QueryInterface(IID_IMFMediaTypeHandler, (void**)ppHandler); - } - - LeaveCriticalSection(&m_critSec); - DebugPrintOut(L"StreamSink::GetMediaTypeHandler: HRESULT=%i\n", hr); - return hr; - } - - HRESULT STDMETHODCALLTYPE ProcessSample(IMFSample *pSample) { - _ComPtr pInput; - _ComPtr pSampleCallback; - BYTE *pSrc = NULL; // Source buffer. - // Stride if the buffer does not support IMF2DBuffer - LONGLONG hnsTime = 0; - LONGLONG hnsDuration = 0; - DWORD cbMaxLength; - DWORD cbCurrentLength = 0; - GUID guidMajorType; - if (pSample == NULL) - { - return E_INVALIDARG; - } - HRESULT hr = S_OK; - - EnterCriticalSection(&m_critSec); - - if (m_state != State_Started && m_state != State_Paused) { - if (m_state == State_TypeNotSet) - hr = MF_E_NOT_INITIALIZED; - else - hr = MF_E_INVALIDREQUEST; - } - if (SUCCEEDED(hr)) - hr = CheckShutdown(); - if (SUCCEEDED(hr)) { - hr = pSample->ConvertToContiguousBuffer(&pInput); - if (SUCCEEDED(hr)) { - hr = pSample->GetSampleTime(&hnsTime); - } - if (SUCCEEDED(hr)) { - hr = pSample->GetSampleDuration(&hnsDuration); - } - if (SUCCEEDED(hr)) { - hr = GetMajorType(&guidMajorType); - } - if (SUCCEEDED(hr)) { - hr = m_pParent->GetUnknown(MF_MEDIASINK_SAMPLEGRABBERCALLBACK, IID_IMFSampleGrabberSinkCallback, (LPVOID*)pSampleCallback.GetAddressOf()); - } - if (SUCCEEDED(hr)) { - hr = pInput->Lock(&pSrc, &cbMaxLength, &cbCurrentLength); - } - if (SUCCEEDED(hr)) { - hr = pSampleCallback->OnProcessSample(guidMajorType, 0, hnsTime, hnsDuration, pSrc, cbCurrentLength); - pInput->Unlock(); - } - if (SUCCEEDED(hr)) { - hr = QueueEvent(MEStreamSinkRequestSample, GUID_NULL, S_OK, NULL); - } - } - LeaveCriticalSection(&m_critSec); - return hr; - } - - HRESULT STDMETHODCALLTYPE PlaceMarker( - /* [in] */ MFSTREAMSINK_MARKER_TYPE eMarkerType, - /* [in] */ __RPC__in const PROPVARIANT * /*pvarMarkerValue*/, - /* [in] */ __RPC__in const PROPVARIANT * /*pvarContextValue*/) { - eMarkerType; - EnterCriticalSection(&m_critSec); - - HRESULT hr = S_OK; - if (m_state == State_TypeNotSet) - hr = MF_E_NOT_INITIALIZED; - - if (SUCCEEDED(hr)) - hr = CheckShutdown(); - - if (SUCCEEDED(hr)) - { - //at shutdown will receive MFSTREAMSINK_MARKER_ENDOFSEGMENT - hr = QueueEvent(MEStreamSinkRequestSample, GUID_NULL, S_OK, NULL); - } - - LeaveCriticalSection(&m_critSec); - DebugPrintOut(L"StreamSink::PlaceMarker: HRESULT=%i %s\n", hr, StreamSinkMarkerTypeMap.at(eMarkerType).c_str()); - return hr; - } - - HRESULT STDMETHODCALLTYPE Flush(void) { - EnterCriticalSection(&m_critSec); - - HRESULT hr = CheckShutdown(); - - if (SUCCEEDED(hr)) - { - } - - LeaveCriticalSection(&m_critSec); - DebugPrintOut(L"StreamSink::Flush: HRESULT=%i\n", hr); - return hr; - } - - //IMFMediaEventGenerator - HRESULT STDMETHODCALLTYPE GetEvent( - DWORD dwFlags, IMFMediaEvent **ppEvent) { - // NOTE: - // GetEvent can block indefinitely, so we don't hold the lock. - // This requires some juggling with the event queue pointer. - - HRESULT hr = S_OK; - - _ComPtr pQueue; - - { - EnterCriticalSection(&m_critSec); - - // Check shutdown - hr = CheckShutdown(); - - // Get the pointer to the event queue. - if (SUCCEEDED(hr)) - { - pQueue = m_spEventQueue.Get(); - } - LeaveCriticalSection(&m_critSec); - } - - // Now get the event. - if (SUCCEEDED(hr)) - { - hr = pQueue->GetEvent(dwFlags, ppEvent); - } - MediaEventType meType = MEUnknown; - if (SUCCEEDED(hr) && SUCCEEDED((*ppEvent)->GetType(&meType)) && meType == MEStreamSinkStopped) { - } - HRESULT hrStatus = S_OK; - if (SUCCEEDED(hr)) - hr = (*ppEvent)->GetStatus(&hrStatus); - if (SUCCEEDED(hr)) - DebugPrintOut(L"StreamSink::GetEvent: HRESULT=%i %s\n", hrStatus, MediaEventTypeMap.at(meType).c_str()); - else - DebugPrintOut(L"StreamSink::GetEvent: HRESULT=%i\n", hr); - return hr; - } - - HRESULT STDMETHODCALLTYPE BeginGetEvent( - IMFAsyncCallback *pCallback, IUnknown *punkState) { - HRESULT hr = S_OK; - - EnterCriticalSection(&m_critSec); - - hr = CheckShutdown(); - - if (SUCCEEDED(hr)) - { - hr = m_spEventQueue->BeginGetEvent(pCallback, punkState); - } - LeaveCriticalSection(&m_critSec); - DebugPrintOut(L"StreamSink::BeginGetEvent: HRESULT=%i\n", hr); - return hr; - } - - HRESULT STDMETHODCALLTYPE EndGetEvent( - IMFAsyncResult *pResult, IMFMediaEvent **ppEvent) { - HRESULT hr = S_OK; - - EnterCriticalSection(&m_critSec); - - hr = CheckShutdown(); - - if (SUCCEEDED(hr)) - { - hr = m_spEventQueue->EndGetEvent(pResult, ppEvent); - } - - MediaEventType meType = MEUnknown; - if (SUCCEEDED(hr) && SUCCEEDED((*ppEvent)->GetType(&meType)) && meType == MEStreamSinkStopped) { - } - - LeaveCriticalSection(&m_critSec); - HRESULT hrStatus = S_OK; - if (SUCCEEDED(hr)) - hr = (*ppEvent)->GetStatus(&hrStatus); - if (SUCCEEDED(hr)) - DebugPrintOut(L"StreamSink::EndGetEvent: HRESULT=%i %s\n", hrStatus, MediaEventTypeMap.at(meType).c_str()); - else - DebugPrintOut(L"StreamSink::EndGetEvent: HRESULT=%i\n", hr); - return hr; - } - - HRESULT STDMETHODCALLTYPE QueueEvent( - MediaEventType met, REFGUID guidExtendedType, - HRESULT hrStatus, const PROPVARIANT *pvValue) { - HRESULT hr = S_OK; - - EnterCriticalSection(&m_critSec); - - hr = CheckShutdown(); - - if (SUCCEEDED(hr)) - { - hr = m_spEventQueue->QueueEventParamVar(met, guidExtendedType, hrStatus, pvValue); - } - - LeaveCriticalSection(&m_critSec); - DebugPrintOut(L"StreamSink::QueueEvent: HRESULT=%i %s\n", hrStatus, MediaEventTypeMap.at(met).c_str()); - DebugPrintOut(L"StreamSink::QueueEvent: HRESULT=%i\n", hr); - return hr; - } - - /// IMFMediaTypeHandler methods - - // Check if a media type is supported. - STDMETHODIMP IsMediaTypeSupported( - /* [in] */ IMFMediaType *pMediaType, - /* [out] */ IMFMediaType **ppMediaType) - { - if (pMediaType == nullptr) - { - return E_INVALIDARG; - } - - EnterCriticalSection(&m_critSec); - - GUID majorType = GUID_NULL; - - HRESULT hr = CheckShutdown(); - - if (SUCCEEDED(hr)) - { - hr = pMediaType->GetGUID(MF_MT_MAJOR_TYPE, &majorType); - } - - // First make sure it's video or audio type. - if (SUCCEEDED(hr)) - { - if (majorType != MFMediaType_Video && majorType != MFMediaType_Audio) - { - hr = MF_E_INVALIDTYPE; - } - } - - if (SUCCEEDED(hr) && m_spCurrentType != nullptr) - { - GUID guiNewSubtype; - if (FAILED(pMediaType->GetGUID(MF_MT_SUBTYPE, &guiNewSubtype)) || - guiNewSubtype != m_guiCurrentSubtype) - { - hr = MF_E_INVALIDTYPE; - } - } - // We don't return any "close match" types. - if (ppMediaType) - { - *ppMediaType = nullptr; - } - - if (ppMediaType && SUCCEEDED(hr)) { - _ComPtr pType; - hr = MFCreateMediaType(ppMediaType); - if (SUCCEEDED(hr)) { - hr = m_pParent->GetUnknown(MF_MEDIASINK_PREFERREDTYPE, __uuidof(IMFMediaType), (LPVOID*)&pType); - } - if (SUCCEEDED(hr)) { - hr = pType->LockStore(); - } - bool bLocked = false; - if (SUCCEEDED(hr)) { - bLocked = true; - UINT32 uiCount; - UINT32 uiTotal; - hr = pType->GetCount(&uiTotal); - for (uiCount = 0; SUCCEEDED(hr) && uiCount < uiTotal; uiCount++) { - GUID guid; - PROPVARIANT propval; - hr = pType->GetItemByIndex(uiCount, &guid, &propval); - if (SUCCEEDED(hr) && (guid == MF_MT_FRAME_SIZE || guid == MF_MT_MAJOR_TYPE || guid == MF_MT_PIXEL_ASPECT_RATIO || - guid == MF_MT_ALL_SAMPLES_INDEPENDENT || guid == MF_MT_INTERLACE_MODE || guid == MF_MT_SUBTYPE)) { - hr = (*ppMediaType)->SetItem(guid, propval); - PropVariantClear(&propval); - } - } - } - if (bLocked) { - hr = pType->UnlockStore(); - } - } - LeaveCriticalSection(&m_critSec); - DebugPrintOut(L"StreamSink::IsMediaTypeSupported: HRESULT=%i\n", hr); - return hr; - } - - - // Return the number of preferred media types. - STDMETHODIMP GetMediaTypeCount(DWORD *pdwTypeCount) - { - if (pdwTypeCount == nullptr) - { - return E_INVALIDARG; - } - - EnterCriticalSection(&m_critSec); - - HRESULT hr = CheckShutdown(); - - if (SUCCEEDED(hr)) - { - // We've got only one media type - *pdwTypeCount = 1; - } - - LeaveCriticalSection(&m_critSec); - DebugPrintOut(L"StreamSink::GetMediaTypeCount: HRESULT=%i\n", hr); - return hr; - } - - - // Return a preferred media type by index. - STDMETHODIMP GetMediaTypeByIndex( - /* [in] */ DWORD dwIndex, - /* [out] */ IMFMediaType **ppType) - { - if (ppType == NULL) { - return E_INVALIDARG; - } - - EnterCriticalSection(&m_critSec); - - HRESULT hr = CheckShutdown(); - - if (dwIndex > 0) - { - hr = MF_E_NO_MORE_TYPES; - } else { - //return preferred type based on media capture library 6 elements preferred preview type - //hr = m_spCurrentType.CopyTo(ppType); - if (SUCCEEDED(hr)) { - _ComPtr pType; - hr = MFCreateMediaType(ppType); - if (SUCCEEDED(hr)) { - hr = m_pParent->GetUnknown(MF_MEDIASINK_PREFERREDTYPE, __uuidof(IMFMediaType), (LPVOID*)&pType); - } - if (SUCCEEDED(hr)) { - hr = pType->LockStore(); - } - bool bLocked = false; - if (SUCCEEDED(hr)) { - bLocked = true; - UINT32 uiCount; - UINT32 uiTotal; - hr = pType->GetCount(&uiTotal); - for (uiCount = 0; SUCCEEDED(hr) && uiCount < uiTotal; uiCount++) { - GUID guid; - PROPVARIANT propval; - hr = pType->GetItemByIndex(uiCount, &guid, &propval); - if (SUCCEEDED(hr) && (guid == MF_MT_FRAME_SIZE || guid == MF_MT_MAJOR_TYPE || guid == MF_MT_PIXEL_ASPECT_RATIO || - guid == MF_MT_ALL_SAMPLES_INDEPENDENT || guid == MF_MT_INTERLACE_MODE || guid == MF_MT_SUBTYPE)) { - hr = (*ppType)->SetItem(guid, propval); - PropVariantClear(&propval); - } - } - } - if (bLocked) { - hr = pType->UnlockStore(); - } - } - } - - LeaveCriticalSection(&m_critSec); - DebugPrintOut(L"StreamSink::GetMediaTypeByIndex: HRESULT=%i\n", hr); - return hr; - } - - - // Set the current media type. - STDMETHODIMP SetCurrentMediaType(IMFMediaType *pMediaType) - { - if (pMediaType == NULL) { - return E_INVALIDARG; - } - EnterCriticalSection(&m_critSec); - - HRESULT hr = S_OK; - if (m_state != State_TypeNotSet && m_state != State_Ready) - hr = MF_E_INVALIDREQUEST; - if (SUCCEEDED(hr)) - hr = CheckShutdown(); - - // We don't allow format changes after streaming starts. - - // We set media type already - if (m_state >= State_Ready) - { - if (SUCCEEDED(hr)) - { - hr = IsMediaTypeSupported(pMediaType, NULL); - } - } - - if (SUCCEEDED(hr)) - { - hr = MFCreateMediaType(m_spCurrentType.ReleaseAndGetAddressOf()); - if (SUCCEEDED(hr)) - { - hr = pMediaType->CopyAllItems(m_spCurrentType.Get()); - } - if (SUCCEEDED(hr)) - { - hr = m_spCurrentType->GetGUID(MF_MT_SUBTYPE, &m_guiCurrentSubtype); - } - GUID guid; - if (SUCCEEDED(hr)) { - hr = m_spCurrentType->GetMajorType(&guid); - } - if (SUCCEEDED(hr) && guid == MFMediaType_Video) { - hr = MFGetAttributeSize(m_spCurrentType.Get(), MF_MT_FRAME_SIZE, &m_imageWidthInPixels, &m_imageHeightInPixels); - } - if (SUCCEEDED(hr)) - { - m_state = State_Ready; - } - } - - LeaveCriticalSection(&m_critSec); - DebugPrintOut(L"StreamSink::SetCurrentMediaType: HRESULT=%i\n", hr); - return hr; - } - - // Return the current media type, if any. - STDMETHODIMP GetCurrentMediaType(IMFMediaType **ppMediaType) - { - if (ppMediaType == NULL) { - return E_INVALIDARG; - } - - EnterCriticalSection(&m_critSec); - - HRESULT hr = CheckShutdown(); - - if (SUCCEEDED(hr)) { - if (m_spCurrentType == nullptr) { - hr = MF_E_NOT_INITIALIZED; - } - } - - if (SUCCEEDED(hr)) { - hr = m_spCurrentType.CopyTo(ppMediaType); - } - - LeaveCriticalSection(&m_critSec); - DebugPrintOut(L"StreamSink::GetCurrentMediaType: HRESULT=%i\n", hr); - return hr; - } - - - // Return the major type GUID. - STDMETHODIMP GetMajorType(GUID *pguidMajorType) - { - HRESULT hr; - if (pguidMajorType == nullptr) { - return E_INVALIDARG; - } - - _ComPtr pType; - hr = m_pParent->GetUnknown(MF_MEDIASINK_PREFERREDTYPE, __uuidof(IMFMediaType), (LPVOID*)&pType); - if (SUCCEEDED(hr)) { - hr = pType->GetMajorType(pguidMajorType); - } - DebugPrintOut(L"StreamSink::GetMajorType: HRESULT=%i\n", hr); - return hr; - } -private: - bool m_bConnected; - - bool m_IsShutdown; // Flag to indicate if Shutdown() method was called. - CRITICAL_SECTION m_critSec; - long m_cRef; - IMFAttributes* m_pParent; - _ComPtr m_spCurrentType; - _ComPtr m_spEventQueue; // Event queue - - _ComPtr m_spFTM; - State m_state; - bool m_fGetStartTimeFromSample; - bool m_fWaitingForFirstSample; - MFTIME m_StartTime; // Presentation time when the clock started. - GUID m_guiCurrentSubtype; - UINT32 m_imageWidthInPixels; - UINT32 m_imageHeightInPixels; -}; - -// Notes: -// -// The List class template implements a simple double-linked list. -// It uses STL's copy semantics. - -// There are two versions of the Clear() method: -// Clear(void) clears the list w/out cleaning up the object. -// Clear(FN fn) takes a functor object that releases the objects, if they need cleanup. - -// The List class supports enumeration. Example of usage: -// -// List::POSIITON pos = list.GetFrontPosition(); -// while (pos != list.GetEndPosition()) -// { -// T item; -// hr = list.GetItemPos(&item); -// pos = list.Next(pos); -// } - -// The ComPtrList class template derives from List<> and implements a list of COM pointers. - -template -struct NoOp -{ - void operator()(T& /*t*/) - { - } -}; - -template -class List -{ -protected: - - // Nodes in the linked list - struct Node - { - Node *prev; - Node *next; - T item; - - Node() : prev(nullptr), next(nullptr) - { - } - - Node(T item) : prev(nullptr), next(nullptr) - { - this->item = item; - } - - T Item() const { return item; } - }; - -public: - - // Object for enumerating the list. - class POSITION - { - friend class List; - - public: - POSITION() : pNode(nullptr) - { - } - - bool operator==(const POSITION &p) const - { - return pNode == p.pNode; - } - - bool operator!=(const POSITION &p) const - { - return pNode != p.pNode; - } - - private: - const Node *pNode; - - POSITION(Node *p) : pNode(p) - { - } - }; - -protected: - Node m_anchor; // Anchor node for the linked list. - DWORD m_count; // Number of items in the list. - - Node* Front() const - { - return m_anchor.next; - } - - Node* Back() const - { - return m_anchor.prev; - } - - virtual HRESULT InsertAfter(T item, Node *pBefore) - { - if (pBefore == nullptr) - { - return E_POINTER; - } - - Node *pNode = new Node(item); - if (pNode == nullptr) - { - return E_OUTOFMEMORY; - } - - Node *pAfter = pBefore->next; - - pBefore->next = pNode; - pAfter->prev = pNode; - - pNode->prev = pBefore; - pNode->next = pAfter; - - m_count++; - - return S_OK; - } - - virtual HRESULT GetItem(const Node *pNode, T* ppItem) - { - if (pNode == nullptr || ppItem == nullptr) - { - return E_POINTER; - } - - *ppItem = pNode->item; - return S_OK; - } - - // RemoveItem: - // Removes a node and optionally returns the item. - // ppItem can be nullptr. - virtual HRESULT RemoveItem(Node *pNode, T *ppItem) - { - if (pNode == nullptr) - { - return E_POINTER; - } - - assert(pNode != &m_anchor); // We should never try to remove the anchor node. - if (pNode == &m_anchor) - { - return E_INVALIDARG; - } - - - T item; - - // The next node's previous is this node's previous. - pNode->next->prev = pNode->prev; - - // The previous node's next is this node's next. - pNode->prev->next = pNode->next; - - item = pNode->item; - delete pNode; - - m_count--; - - if (ppItem) - { - *ppItem = item; - } - - return S_OK; - } - -public: - - List() - { - m_anchor.next = &m_anchor; - m_anchor.prev = &m_anchor; - - m_count = 0; - } - - virtual ~List() - { - Clear(); - } - - // Insertion functions - HRESULT InsertBack(T item) - { - return InsertAfter(item, m_anchor.prev); - } - - - HRESULT InsertFront(T item) - { - return InsertAfter(item, &m_anchor); - } - - HRESULT InsertPos(POSITION pos, T item) - { - if (pos.pNode == nullptr) - { - return InsertBack(item); - } - - return InsertAfter(item, pos.pNode->prev); - } - - // RemoveBack: Removes the tail of the list and returns the value. - // ppItem can be nullptr if you don't want the item back. (But the method does not release the item.) - HRESULT RemoveBack(T *ppItem) - { - if (IsEmpty()) - { - return E_FAIL; - } - else - { - return RemoveItem(Back(), ppItem); - } - } - - // RemoveFront: Removes the head of the list and returns the value. - // ppItem can be nullptr if you don't want the item back. (But the method does not release the item.) - HRESULT RemoveFront(T *ppItem) - { - if (IsEmpty()) - { - return E_FAIL; - } - else - { - return RemoveItem(Front(), ppItem); - } - } - - // GetBack: Gets the tail item. - HRESULT GetBack(T *ppItem) - { - if (IsEmpty()) - { - return E_FAIL; - } - else - { - return GetItem(Back(), ppItem); - } - } - - // GetFront: Gets the front item. - HRESULT GetFront(T *ppItem) - { - if (IsEmpty()) - { - return E_FAIL; - } - else - { - return GetItem(Front(), ppItem); - } - } - - - // GetCount: Returns the number of items in the list. - DWORD GetCount() const { return m_count; } - - bool IsEmpty() const - { - return (GetCount() == 0); - } - - // Clear: Takes a functor object whose operator() - // frees the object on the list. - template - void Clear(FN& clear_fn) - { - Node *n = m_anchor.next; - - // Delete the nodes - while (n != &m_anchor) - { - clear_fn(n->item); - - Node *tmp = n->next; - delete n; - n = tmp; - } - - // Reset the anchor to point at itself - m_anchor.next = &m_anchor; - m_anchor.prev = &m_anchor; - - m_count = 0; - } - - // Clear: Clears the list. (Does not delete or release the list items.) - virtual void Clear() - { - NoOp clearOp; - Clear<>(clearOp); - } - - - // Enumerator functions - - POSITION FrontPosition() - { - if (IsEmpty()) - { - return POSITION(nullptr); - } - else - { - return POSITION(Front()); - } - } - - POSITION EndPosition() const - { - return POSITION(); - } - - HRESULT GetItemPos(POSITION pos, T *ppItem) - { - if (pos.pNode) - { - return GetItem(pos.pNode, ppItem); - } - else - { - return E_FAIL; - } - } - - POSITION Next(const POSITION pos) - { - if (pos.pNode && (pos.pNode->next != &m_anchor)) - { - return POSITION(pos.pNode->next); - } - else - { - return POSITION(nullptr); - } - } - - // Remove an item at a position. - // The item is returns in ppItem, unless ppItem is nullptr. - // NOTE: This method invalidates the POSITION object. - HRESULT Remove(POSITION& pos, T *ppItem) - { - if (pos.pNode) - { - // Remove const-ness temporarily... - Node *pNode = const_cast(pos.pNode); - - pos = POSITION(); - - return RemoveItem(pNode, ppItem); - } - else - { - return E_INVALIDARG; - } - } - -}; - - - -// Typical functors for Clear method. - -// ComAutoRelease: Releases COM pointers. -// MemDelete: Deletes pointers to new'd memory. - -class ComAutoRelease -{ -public: - void operator()(IUnknown *p) - { - if (p) - { - p->Release(); - } - } -}; - -class MemDelete -{ -public: - void operator()(void *p) - { - if (p) - { - delete p; - } - } -}; - - -// ComPtrList class -// Derived class that makes it safer to store COM pointers in the List<> class. -// It automatically AddRef's the pointers that are inserted onto the list -// (unless the insertion method fails). -// -// T must be a COM interface type. -// example: ComPtrList -// -// NULLABLE: If true, client can insert nullptr pointers. This means GetItem can -// succeed but return a nullptr pointer. By default, the list does not allow nullptr -// pointers. - -template -class ComPtrList : public List -{ -public: - typedef typename List::Node Node; - typedef T* Ptr; - - void Clear() - { - ComAutoRelease car; - List::Clear(car); - } - - ~ComPtrList() - { - Clear(); - } - -protected: - HRESULT InsertAfter(Ptr item, Node *pBefore) - { - // Do not allow nullptr item pointers unless NULLABLE is true. - if (item == nullptr && !NULLABLE) - { - return E_POINTER; - } - - if (item) - { - item->AddRef(); - } - - HRESULT hr = List::InsertAfter(item, pBefore); - if (FAILED(hr) && item != nullptr) - { - item->Release(); - } - return hr; - } - - HRESULT GetItem(const Node *pNode, Ptr* ppItem) - { - Ptr pItem = nullptr; - - // The base class gives us the pointer without AddRef'ing it. - // If we return the pointer to the caller, we must AddRef(). - HRESULT hr = List::GetItem(pNode, &pItem); - if (SUCCEEDED(hr)) - { - assert(pItem || NULLABLE); - if (pItem) - { - *ppItem = pItem; - (*ppItem)->AddRef(); - } - } - return hr; - } - - HRESULT RemoveItem(Node *pNode, Ptr *ppItem) - { - // ppItem can be nullptr, but we need to get the - // item so that we can release it. - - // If ppItem is not nullptr, we will AddRef it on the way out. - - Ptr pItem = nullptr; - - HRESULT hr = List::RemoveItem(pNode, &pItem); - - if (SUCCEEDED(hr)) - { - assert(pItem || NULLABLE); - if (ppItem && pItem) - { - *ppItem = pItem; - (*ppItem)->AddRef(); - } - - if (pItem) - { - pItem->Release(); - pItem = nullptr; - } - } - - return hr; - } -}; - -extern const __declspec(selectany) WCHAR RuntimeClass_CV_MediaSink[] = L"cv.MediaSink"; - -class MediaSink : - public IMFMediaSink, public IMFClockStateSink, public CBaseAttributes<> -{ -public: - ULONG STDMETHODCALLTYPE AddRef() - { - return InterlockedIncrement(&m_cRef); - } - ULONG STDMETHODCALLTYPE Release() - { - ULONG cRef = InterlockedDecrement(&m_cRef); - if (cRef == 0) - { - delete this; - } - return cRef; - } -#if defined(_MSC_VER) && _MSC_VER >= 1700 // '_Outptr_result_nullonfailure_' SAL is avaialable since VS 2012 - STDMETHOD(QueryInterface)(REFIID riid, _Outptr_result_nullonfailure_ void **ppv) -#else - STDMETHOD(QueryInterface)(REFIID riid, void **ppv) -#endif - { - if (ppv == nullptr) { - return E_POINTER; - } - (*ppv) = nullptr; - HRESULT hr = S_OK; - if (riid == IID_IUnknown || - riid == IID_IMFMediaSink) { - (*ppv) = static_cast(this); - AddRef(); - } else if (riid == IID_IMFClockStateSink) { - (*ppv) = static_cast(this); - AddRef(); - } else if (riid == IID_IMFAttributes) { - (*ppv) = static_cast(this); - AddRef(); - } else { - hr = E_NOINTERFACE; - } - - return hr; - } - MediaSink() : m_IsShutdown(false), m_llStartTime(0) { - CBaseAttributes<>::Initialize(0U); - InitializeCriticalSectionEx(&m_critSec, 3000, 0); - DebugPrintOut(L"MediaSink::MediaSink\n"); - } - - virtual ~MediaSink() { - DebugPrintOut(L"MediaSink::~MediaSink\n"); - DeleteCriticalSection(&m_critSec); - assert(m_IsShutdown); - } - HRESULT CheckShutdown() const - { - if (m_IsShutdown) - { - return MF_E_SHUTDOWN; - } - else - { - return S_OK; - } - } - //IMFMediaSink - HRESULT STDMETHODCALLTYPE GetCharacteristics( - /* [out] */ __RPC__out DWORD *pdwCharacteristics) { - HRESULT hr; - if (pdwCharacteristics == NULL) return E_INVALIDARG; - EnterCriticalSection(&m_critSec); - if (SUCCEEDED(hr = CheckShutdown())) { - //if had an activation object for the sink, shut down would be managed and MF_STREAM_SINK_SUPPORTS_ROTATION appears to be setable to TRUE - *pdwCharacteristics = MEDIASINK_FIXED_STREAMS;// | MEDIASINK_REQUIRE_REFERENCE_MEDIATYPE; - } - LeaveCriticalSection(&m_critSec); - DebugPrintOut(L"MediaSink::GetCharacteristics: HRESULT=%i\n", hr); - return hr; - } - - HRESULT STDMETHODCALLTYPE AddStreamSink( - DWORD dwStreamSinkIdentifier, IMFMediaType * /*pMediaType*/, IMFStreamSink **ppStreamSink) { - _ComPtr spMFStream; - _ComPtr pStream; - EnterCriticalSection(&m_critSec); - HRESULT hr = CheckShutdown(); - - if (SUCCEEDED(hr)) - { - hr = GetStreamSinkById(dwStreamSinkIdentifier, &spMFStream); - } - - if (SUCCEEDED(hr)) - { - hr = MF_E_STREAMSINK_EXISTS; - } - else - { - hr = S_OK; - } - - if (SUCCEEDED(hr)) - { - StreamSink* pSink = new StreamSink(); - if (pSink) { - hr = pSink->QueryInterface(IID_IMFStreamSink, (void**)spMFStream.GetAddressOf()); - if (SUCCEEDED(hr)) { - hr = spMFStream.As(&pStream); - } - if (FAILED(hr)) delete pSink; - } - } - - // Initialize the stream. - _ComPtr pAttr; - if (SUCCEEDED(hr)) { - hr = pStream.As(&pAttr); - } - if (SUCCEEDED(hr)) { - hr = pAttr->SetUINT32(MF_STREAMSINK_ID, dwStreamSinkIdentifier); - if (SUCCEEDED(hr)) { - hr = pAttr->SetUnknown(MF_STREAMSINK_MEDIASINKINTERFACE, (IMFMediaSink*)this); - } - } - if (SUCCEEDED(hr)) { - hr = pStream->Initialize(); - } - - if (SUCCEEDED(hr)) - { - ComPtrList::POSITION pos = m_streams.FrontPosition(); - ComPtrList::POSITION posEnd = m_streams.EndPosition(); - - // Insert in proper position - for (; pos != posEnd; pos = m_streams.Next(pos)) - { - DWORD dwCurrId; - _ComPtr spCurr; - hr = m_streams.GetItemPos(pos, &spCurr); - if (FAILED(hr)) - { - break; - } - hr = spCurr->GetIdentifier(&dwCurrId); - if (FAILED(hr)) - { - break; - } - - if (dwCurrId > dwStreamSinkIdentifier) - { - break; - } - } - - if (SUCCEEDED(hr)) - { - hr = m_streams.InsertPos(pos, spMFStream.Get()); - } - } - - if (SUCCEEDED(hr)) - { - *ppStreamSink = spMFStream.Detach(); - } - LeaveCriticalSection(&m_critSec); - DebugPrintOut(L"MediaSink::AddStreamSink: HRESULT=%i\n", hr); - return hr; - } - - HRESULT STDMETHODCALLTYPE RemoveStreamSink(DWORD dwStreamSinkIdentifier) { - EnterCriticalSection(&m_critSec); - HRESULT hr = CheckShutdown(); - ComPtrList::POSITION pos = m_streams.FrontPosition(); - ComPtrList::POSITION endPos = m_streams.EndPosition(); - _ComPtr spStream; - - if (SUCCEEDED(hr)) - { - for (; pos != endPos; pos = m_streams.Next(pos)) - { - hr = m_streams.GetItemPos(pos, &spStream); - DWORD dwId; - - if (FAILED(hr)) - { - break; - } - - hr = spStream->GetIdentifier(&dwId); - if (FAILED(hr) || dwId == dwStreamSinkIdentifier) - { - break; - } - } - - if (pos == endPos) - { - hr = MF_E_INVALIDSTREAMNUMBER; - } - } - - if (SUCCEEDED(hr)) - { - hr = m_streams.Remove(pos, nullptr); - _ComPtr spCustomSink; - hr = spStream.As(&spCustomSink); - if (SUCCEEDED(hr)) - hr = spCustomSink->Shutdown(); - } - LeaveCriticalSection(&m_critSec); - DebugPrintOut(L"MediaSink::RemoveStreamSink: HRESULT=%i\n", hr); - return hr; - } - - HRESULT STDMETHODCALLTYPE GetStreamSinkCount(DWORD *pStreamSinkCount) { - if (pStreamSinkCount == NULL) - { - return E_INVALIDARG; - } - - EnterCriticalSection(&m_critSec); - - HRESULT hr = CheckShutdown(); - - if (SUCCEEDED(hr)) - { - *pStreamSinkCount = m_streams.GetCount(); - } - - LeaveCriticalSection(&m_critSec); - DebugPrintOut(L"MediaSink::GetStreamSinkCount: HRESULT=%i\n", hr); - return hr; - } - - HRESULT STDMETHODCALLTYPE GetStreamSinkByIndex( - DWORD dwIndex, IMFStreamSink **ppStreamSink) { - if (ppStreamSink == NULL) - { - return E_INVALIDARG; - } - - _ComPtr spStream; - EnterCriticalSection(&m_critSec); - DWORD cStreams = m_streams.GetCount(); - - if (dwIndex >= cStreams) - { - return MF_E_INVALIDINDEX; - } - - HRESULT hr = CheckShutdown(); - - if (SUCCEEDED(hr)) - { - ComPtrList::POSITION pos = m_streams.FrontPosition(); - ComPtrList::POSITION endPos = m_streams.EndPosition(); - DWORD dwCurrent = 0; - - for (; pos != endPos && dwCurrent < dwIndex; pos = m_streams.Next(pos), ++dwCurrent) - { - // Just move to proper position - } - - if (pos == endPos) - { - hr = MF_E_UNEXPECTED; - } - else - { - hr = m_streams.GetItemPos(pos, &spStream); - } - } - - if (SUCCEEDED(hr)) - { - *ppStreamSink = spStream.Detach(); - } - LeaveCriticalSection(&m_critSec); - DebugPrintOut(L"MediaSink::GetStreamSinkByIndex: HRESULT=%i\n", hr); - return hr; - } - - HRESULT STDMETHODCALLTYPE GetStreamSinkById( - DWORD dwStreamSinkIdentifier, IMFStreamSink **ppStreamSink) { - if (ppStreamSink == NULL) - { - return E_INVALIDARG; - } - - EnterCriticalSection(&m_critSec); - HRESULT hr = CheckShutdown(); - _ComPtr spResult; - - if (SUCCEEDED(hr)) - { - ComPtrList::POSITION pos = m_streams.FrontPosition(); - ComPtrList::POSITION endPos = m_streams.EndPosition(); - - for (; pos != endPos; pos = m_streams.Next(pos)) - { - _ComPtr spStream; - hr = m_streams.GetItemPos(pos, &spStream); - DWORD dwId; - - if (FAILED(hr)) - { - break; - } - - hr = spStream->GetIdentifier(&dwId); - if (FAILED(hr)) - { - break; - } - else if (dwId == dwStreamSinkIdentifier) - { - spResult = spStream; - break; - } - } - - if (pos == endPos) - { - hr = MF_E_INVALIDSTREAMNUMBER; - } - } - - if (SUCCEEDED(hr)) - { - assert(spResult); - *ppStreamSink = spResult.Detach(); - } - LeaveCriticalSection(&m_critSec); - DebugPrintOut(L"MediaSink::GetStreamSinkById: HRESULT=%i\n", hr); - return hr; - } - - HRESULT STDMETHODCALLTYPE SetPresentationClock( - IMFPresentationClock *pPresentationClock) { - EnterCriticalSection(&m_critSec); - - HRESULT hr = CheckShutdown(); - - // If we already have a clock, remove ourselves from that clock's - // state notifications. - if (SUCCEEDED(hr)) { - if (m_spClock) { - hr = m_spClock->RemoveClockStateSink(this); - } - } - - // Register ourselves to get state notifications from the new clock. - if (SUCCEEDED(hr)) { - if (pPresentationClock) { - hr = pPresentationClock->AddClockStateSink(this); - } - } - - _ComPtr pSampleCallback; - if (SUCCEEDED(hr)) { - // Release the pointer to the old clock. - // Store the pointer to the new clock. - m_spClock = pPresentationClock; - hr = GetUnknown(MF_MEDIASINK_SAMPLEGRABBERCALLBACK, IID_IMFSampleGrabberSinkCallback, (LPVOID*)pSampleCallback.GetAddressOf()); - } - LeaveCriticalSection(&m_critSec); - if (SUCCEEDED(hr)) - hr = pSampleCallback->OnSetPresentationClock(pPresentationClock); - DebugPrintOut(L"MediaSink::SetPresentationClock: HRESULT=%i\n", hr); - return hr; - } - - HRESULT STDMETHODCALLTYPE GetPresentationClock( - IMFPresentationClock **ppPresentationClock) { - if (ppPresentationClock == NULL) { - return E_INVALIDARG; - } - - EnterCriticalSection(&m_critSec); - - HRESULT hr = CheckShutdown(); - - if (SUCCEEDED(hr)) { - if (!m_spClock) { - hr = MF_E_NO_CLOCK; // There is no presentation clock. - } else { - // Return the pointer to the caller. - hr = m_spClock.CopyTo(ppPresentationClock); - } - } - LeaveCriticalSection(&m_critSec); - DebugPrintOut(L"MediaSink::GetPresentationClock: HRESULT=%i\n", hr); - return hr; - } - - HRESULT STDMETHODCALLTYPE Shutdown(void) { - EnterCriticalSection(&m_critSec); - - HRESULT hr = CheckShutdown(); - - if (SUCCEEDED(hr)) { - ForEach(m_streams, ShutdownFunc()); - m_streams.Clear(); - m_spClock.ReleaseAndGetAddressOf(); - - _ComPtr pType; - hr = CBaseAttributes<>::GetUnknown(MF_MEDIASINK_PREFERREDTYPE, __uuidof(IMFMediaType), (LPVOID*)pType.GetAddressOf()); - if (SUCCEEDED(hr)) { - hr = DeleteItem(MF_MEDIASINK_PREFERREDTYPE); - } - m_IsShutdown = true; - } - - LeaveCriticalSection(&m_critSec); - DebugPrintOut(L"MediaSink::Shutdown: HRESULT=%i\n", hr); - return hr; - } - class ShutdownFunc - { - public: - HRESULT operator()(IMFStreamSink *pStream) const - { - _ComPtr spCustomSink; - HRESULT hr; - hr = pStream->QueryInterface(IID_PPV_ARGS(spCustomSink.GetAddressOf())); - if (FAILED(hr)) return hr; - hr = spCustomSink->Shutdown(); - return hr; - } - }; - - class StartFunc - { - public: - StartFunc(LONGLONG llStartTime) - : _llStartTime(llStartTime) - { - } - - HRESULT operator()(IMFStreamSink *pStream) const - { - _ComPtr spCustomSink; - HRESULT hr; - hr = pStream->QueryInterface(IID_PPV_ARGS(spCustomSink.GetAddressOf())); - if (FAILED(hr)) return hr; - hr = spCustomSink->Start(_llStartTime); - return hr; - } - - LONGLONG _llStartTime; - }; - - class StopFunc - { - public: - HRESULT operator()(IMFStreamSink *pStream) const - { - _ComPtr spCustomSink; - HRESULT hr; - hr = pStream->QueryInterface(IID_PPV_ARGS(spCustomSink.GetAddressOf())); - if (FAILED(hr)) return hr; - hr = spCustomSink->Stop(); - return hr; - } - }; - - template - HRESULT ForEach(ComPtrList &col, TFunc fn) - { - ComPtrList::POSITION pos = col.FrontPosition(); - ComPtrList::POSITION endPos = col.EndPosition(); - HRESULT hr = S_OK; - - for (; pos != endPos; pos = col.Next(pos)) - { - _ComPtr spStream; - - hr = col.GetItemPos(pos, &spStream); - if (FAILED(hr)) - { - break; - } - - hr = fn(spStream.Get()); - } - - return hr; - } - //IMFClockStateSink - HRESULT STDMETHODCALLTYPE OnClockStart( - MFTIME hnsSystemTime, - LONGLONG llClockStartOffset) { - EnterCriticalSection(&m_critSec); - HRESULT hr = CheckShutdown(); - - if (SUCCEEDED(hr)) - { - // Start each stream. - m_llStartTime = llClockStartOffset; - hr = ForEach(m_streams, StartFunc(llClockStartOffset)); - } - _ComPtr pSampleCallback; - if (SUCCEEDED(hr)) - hr = GetUnknown(MF_MEDIASINK_SAMPLEGRABBERCALLBACK, IID_IMFSampleGrabberSinkCallback, (LPVOID*)pSampleCallback.GetAddressOf()); - LeaveCriticalSection(&m_critSec); - if (SUCCEEDED(hr)) - hr = pSampleCallback->OnClockStart(hnsSystemTime, llClockStartOffset); - DebugPrintOut(L"MediaSink::OnClockStart: HRESULT=%i\n", hr); - return hr; - } - - HRESULT STDMETHODCALLTYPE OnClockStop( - MFTIME hnsSystemTime) { - EnterCriticalSection(&m_critSec); - HRESULT hr = CheckShutdown(); - - if (SUCCEEDED(hr)) - { - // Stop each stream - hr = ForEach(m_streams, StopFunc()); - } - _ComPtr pSampleCallback; - if (SUCCEEDED(hr)) - hr = GetUnknown(MF_MEDIASINK_SAMPLEGRABBERCALLBACK, IID_IMFSampleGrabberSinkCallback, (LPVOID*)pSampleCallback.GetAddressOf()); - LeaveCriticalSection(&m_critSec); - if (SUCCEEDED(hr)) - hr = pSampleCallback->OnClockStop(hnsSystemTime); - DebugPrintOut(L"MediaSink::OnClockStop: HRESULT=%i\n", hr); - return hr; - } - - HRESULT STDMETHODCALLTYPE OnClockPause( - MFTIME hnsSystemTime) { - HRESULT hr; - _ComPtr pSampleCallback; - hr = GetUnknown(MF_MEDIASINK_SAMPLEGRABBERCALLBACK, IID_IMFSampleGrabberSinkCallback, (LPVOID*)pSampleCallback.GetAddressOf()); - if (SUCCEEDED(hr)) - hr = pSampleCallback->OnClockPause(hnsSystemTime); - DebugPrintOut(L"MediaSink::OnClockPause: HRESULT=%i\n", hr); - return hr; - } - - HRESULT STDMETHODCALLTYPE OnClockRestart( - MFTIME hnsSystemTime) { - HRESULT hr; - _ComPtr pSampleCallback; - hr = GetUnknown(MF_MEDIASINK_SAMPLEGRABBERCALLBACK, IID_IMFSampleGrabberSinkCallback, (LPVOID*)pSampleCallback.GetAddressOf()); - if (SUCCEEDED(hr)) - hr = pSampleCallback->OnClockRestart(hnsSystemTime); - DebugPrintOut(L"MediaSink::OnClockRestart: HRESULT=%i\n", hr); - return hr; - } - - HRESULT STDMETHODCALLTYPE OnClockSetRate( - MFTIME hnsSystemTime, - float flRate) { - HRESULT hr; - _ComPtr pSampleCallback; - hr = GetUnknown(MF_MEDIASINK_SAMPLEGRABBERCALLBACK, IID_IMFSampleGrabberSinkCallback, (LPVOID*)pSampleCallback.GetAddressOf()); - if (SUCCEEDED(hr)) - hr = pSampleCallback->OnClockSetRate(hnsSystemTime, flRate); - DebugPrintOut(L"MediaSink::OnClockSetRate: HRESULT=%i\n", hr); - return hr; - } -private: - long m_cRef; - CRITICAL_SECTION m_critSec; - bool m_IsShutdown; - ComPtrList m_streams; - _ComPtr m_spClock; - LONGLONG m_llStartTime; -};