0

I'm developing a multimedia player app with Directshow recently, and I can successfully build the filter graph to capture video stream from a webcam.

I read the Directshow document on MSDN and found that WDM video capture filter exposes IAMAnalogVideoDecoder interface and I can set the analog video format listed in AnalogVideoStandard enum, but this enum does not contain some new HD standard such as 720p, 1080i, 1080p:

typedef /* [v1_enum] */ 
enum tagAnalogVideoStandard
    {
        AnalogVideo_None    = 0,
        AnalogVideo_NTSC_M  = 0x1,
        AnalogVideo_NTSC_M_J    = 0x2,
        AnalogVideo_NTSC_433    = 0x4,
        AnalogVideo_PAL_B   = 0x10,
        AnalogVideo_PAL_D   = 0x20,
        AnalogVideo_PAL_G   = 0x40,
        AnalogVideo_PAL_H   = 0x80,
        AnalogVideo_PAL_I   = 0x100,
        AnalogVideo_PAL_M   = 0x200,
        AnalogVideo_PAL_N   = 0x400,
        AnalogVideo_PAL_60  = 0x800,
        AnalogVideo_SECAM_B = 0x1000,
        AnalogVideo_SECAM_D = 0x2000,
        AnalogVideo_SECAM_G = 0x4000,
        AnalogVideo_SECAM_H = 0x8000,
        AnalogVideo_SECAM_K = 0x10000,
        AnalogVideo_SECAM_K1    = 0x20000,
        AnalogVideo_SECAM_L = 0x40000,
        AnalogVideo_SECAM_L1    = 0x80000,
        AnalogVideo_PAL_N_COMBO = 0x100000,
        AnalogVideoMask_MCE_NTSC    = ( ( ( ( ( ( AnalogVideo_NTSC_M | AnalogVideo_NTSC_M_J )  | AnalogVideo_NTSC_433 )  | AnalogVideo_PAL_M )  | AnalogVideo_PAL_N )  | AnalogVideo_PAL_60 )  | AnalogVideo_PAL_N_COMBO ) ,
        AnalogVideoMask_MCE_PAL = ( ( ( ( AnalogVideo_PAL_B | AnalogVideo_PAL_D )  | AnalogVideo_PAL_G )  | AnalogVideo_PAL_H )  | AnalogVideo_PAL_I ) ,
        AnalogVideoMask_MCE_SECAM   = ( ( ( ( ( ( ( AnalogVideo_SECAM_B | AnalogVideo_SECAM_D )  | AnalogVideo_SECAM_G )  | AnalogVideo_SECAM_H )  | AnalogVideo_SECAM_K )  | AnalogVideo_SECAM_K1 )  | AnalogVideo_SECAM_L )  | AnalogVideo_SECAM_L1 ) 
    }   AnalogVideoStandard;

What's more, when a capture card has more than one physical input, a crossbar filter will be added automatically and I can route which input I want using the PhysicalConnectorType enum, but some new input such as HDMI is not included:

typedef 
enum tagPhysicalConnectorType
    {
        PhysConn_Video_Tuner    = 1,
        PhysConn_Video_Composite    = ( PhysConn_Video_Tuner + 1 ) ,
        PhysConn_Video_SVideo   = ( PhysConn_Video_Composite + 1 ) ,
        PhysConn_Video_RGB  = ( PhysConn_Video_SVideo + 1 ) ,
        PhysConn_Video_YRYBY    = ( PhysConn_Video_RGB + 1 ) ,
        PhysConn_Video_SerialDigital    = ( PhysConn_Video_YRYBY + 1 ) ,
        PhysConn_Video_ParallelDigital  = ( PhysConn_Video_SerialDigital + 1 ) ,
        PhysConn_Video_SCSI = ( PhysConn_Video_ParallelDigital + 1 ) ,
        PhysConn_Video_AUX  = ( PhysConn_Video_SCSI + 1 ) ,
        PhysConn_Video_1394 = ( PhysConn_Video_AUX + 1 ) ,
        PhysConn_Video_USB  = ( PhysConn_Video_1394 + 1 ) ,
        PhysConn_Video_VideoDecoder = ( PhysConn_Video_USB + 1 ) ,
        PhysConn_Video_VideoEncoder = ( PhysConn_Video_VideoDecoder + 1 ) ,
        PhysConn_Video_SCART    = ( PhysConn_Video_VideoEncoder + 1 ) ,
        PhysConn_Video_Black    = ( PhysConn_Video_SCART + 1 ) ,
        PhysConn_Audio_Tuner    = 0x1000,
        PhysConn_Audio_Line = ( PhysConn_Audio_Tuner + 1 ) ,
        PhysConn_Audio_Mic  = ( PhysConn_Audio_Line + 1 ) ,
        PhysConn_Audio_AESDigital   = ( PhysConn_Audio_Mic + 1 ) ,
        PhysConn_Audio_SPDIFDigital = ( PhysConn_Audio_AESDigital + 1 ) ,
        PhysConn_Audio_SCSI = ( PhysConn_Audio_SPDIFDigital + 1 ) ,
        PhysConn_Audio_AUX  = ( PhysConn_Audio_SCSI + 1 ) ,
        PhysConn_Audio_1394 = ( PhysConn_Audio_AUX + 1 ) ,
        PhysConn_Audio_USB  = ( PhysConn_Audio_1394 + 1 ) ,
        PhysConn_Audio_AudioDecoder = ( PhysConn_Audio_USB + 1 ) 
    }   PhysicalConnectorType;

I know that Directshow is an old multimedia framework and the header may be out of time. So is there any way to apply some new standard to Directshow? Is there some other redistribution of Directshow? Or I should just give up using Directshow and use Media Foundation instead?

Roman R.
  • 68,205
  • 6
  • 94
  • 158
YQ.Mei
  • 41
  • 1
  • 5

1 Answers1

0

So, you correct wrote that Microsoft stopped supporting of DirectShow. DirectShow does not support HD standard such as 720p, 1080i, 1080p by default. For resolving of such problem vendor of the video capture device develops private direct show filter with supporting of the such new device and include it into the driver for devices - this filter is installed while installing of drives - it means that you must research OS system for finding of DirectShow Source Filters - one of them will your's needed filter, of course if you installed drivers. About Media Foundation - at the present moment it supports only USB Video Class driver Audio/Video Capture in Media Foundation for capture of video - such driver supports only USB web cameras.

Regards.

P.S. for getting of output pin you can use the next code:`

                CComPtrCustom<ICaptureGraphBuilder2> lCaptureGraph;

                LOG_INVOKE_FUNCTION(lCaptureGraph.CoCreateInstance, __uuidof(CLSID_CaptureGraphBuilder2Proxy));

                LOG_CHECK_PTR_MEMORY(lCaptureGraph);

                CComPtrCustom<IGraphBuilder> lGraphBuilder;

                LOG_INVOKE_FUNCTION(lGraphBuilder.CoCreateInstance, __uuidof(CLSID_FilterGraphProxy));

                LOG_CHECK_PTR_MEMORY(lGraphBuilder);

                LOG_INVOKE_POINTER_METHOD(lCaptureGraph, SetFiltergraph,
                    lGraphBuilder);                             

                CComPtrCustom<IBaseFilter> lVideoCaptureFilter;

                CComPtrCustom<IBindCtx> pbc;

                LOG_INVOKE_FUNCTION(CreateBindCtx, NULL, &pbc);

                LOG_INVOKE_POINTER_METHOD(mMoniker, BindToObject,
                    pbc,
                    nullptr, 
                    IID_PPV_ARGS(&lVideoCaptureFilter));

                LOG_CHECK_PTR_MEMORY(lVideoCaptureFilter);

                LOG_INVOKE_POINTER_METHOD(lGraphBuilder, AddFilter,
                    lVideoCaptureFilter,
                    L"Video Capture");

                std::vector<CComPtrCustom<IMFMediaType>> lMediaTypes;

                do
                {
                    CComPtrCustom<IPin> lPin;

                    LOG_INVOKE_POINTER_METHOD(lCaptureGraph, FindPin,
                        lVideoCaptureFilter,
                        PINDIR_OUTPUT,
                        &PIN_CATEGORY_CAPTURE,
                        &__uuidof(MEDIATYPE_VideoProxy),
                        FALSE,
                        aStreamIndex,
                        &lPin);

                    if (lPin != nullptr)
                    {
                        PIN_INFO lPIN_INFO;

                        ZeroMemory(&lPIN_INFO, sizeof(lPIN_INFO));

                        HRESULT lr = lPin->QueryPinInfo(&lPIN_INFO);

                        if (SUCCEEDED(lr) && lPIN_INFO.achName[0] != L'\0')
                        {
                            if (aPtrStreamNameString != nullptr)
                            {
                                *aPtrStreamNameString = SysAllocString(lPIN_INFO.achName);
                            }
                        }

                        getMediaTypes(
                            lPin,
                            lMediaTypes);
                    }

                } while (false);

`

Some vendors define own interface for extension of DS filter - for example AJA DS Filters:

EXTERN_C const IID IID_IAJACaptureFilter;

MIDL_INTERFACE("D941E04F-3B38-4F27-82DD-943FBEA7E755")
IAJACaptureFilter : public IUnknown
{
public:
    virtual HRESULT STDMETHODCALLTYPE SetBoardNumber( 
        /* [in] */ WORD value) = 0;

    virtual HRESULT STDMETHODCALLTYPE GetBoardNumber( 
        /* [out] */ WORD *value) = 0;

    virtual HRESULT STDMETHODCALLTYPE GetNumBoards( 
        /* [out] */ WORD *value) = 0;

    virtual HRESULT STDMETHODCALLTYPE ReserveBoard( 
        /* [in] */ WORD value) = 0;

    virtual HRESULT STDMETHODCALLTYPE SetVideoFormat( 
        /* [in] */ WORD value) = 0;

    virtual HRESULT STDMETHODCALLTYPE GetVideoFormat( 
        /* [out] */ WORD *value) = 0;

    virtual HRESULT STDMETHODCALLTYPE SetReferenceSource( 
        /* [in] */ WORD value) = 0;

    virtual HRESULT STDMETHODCALLTYPE GetReferenceSource( 
        /* [out] */ WORD *value) = 0;

    virtual HRESULT STDMETHODCALLTYPE SetVideoSource( 
        /* [in] */ WORD value) = 0;

    virtual HRESULT STDMETHODCALLTYPE GetVideoSource( 
        /* [out] */ WORD *value) = 0;

    virtual HRESULT STDMETHODCALLTYPE SetAnalogVideoFormat( 
        /* [in] */ WORD value) = 0;

    virtual HRESULT STDMETHODCALLTYPE GetAnalogVideoFormat( 
        /* [out] */ WORD *value) = 0;

    virtual HRESULT STDMETHODCALLTYPE GetSourceVideoFormat( 
        /* [out] */ WORD *value) = 0;

    virtual HRESULT STDMETHODCALLTYPE GetInput1VideoFormat( 
        /* [out] */ WORD *value) = 0;

    virtual HRESULT STDMETHODCALLTYPE GetInput2VideoFormat( 
        /* [out] */ WORD *value) = 0;

    virtual HRESULT STDMETHODCALLTYPE GetHDMIInVideoFormat( 
        /* [out] */ WORD *value) = 0;

    virtual HRESULT STDMETHODCALLTYPE GetReferenceVideoFormat( 
        /* [out] */ WORD *value) = 0;

    virtual HRESULT STDMETHODCALLTYPE SetFourCC( 
        /* [in] */ DWORD value) = 0;

    virtual HRESULT STDMETHODCALLTYPE GetFourCC( 
        /* [out] */ DWORD *value) = 0;

    virtual HRESULT STDMETHODCALLTYPE SetEnableEtoE( 
        /* [in] */ BOOL value) = 0;

    virtual HRESULT STDMETHODCALLTYPE GetEnableEtoE( 
        /* [out] */ BOOL *value) = 0;

    virtual HRESULT STDMETHODCALLTYPE SetEnableVANCMode( 
        /* [in] */ BOOL value) = 0;

    virtual HRESULT STDMETHODCALLTYPE GetEnableVANCMode( 
        /* [out] */ BOOL *value) = 0;

    virtual HRESULT STDMETHODCALLTYPE SetScaleMode( 
        /* [in] */ WORD value) = 0;

    virtual HRESULT STDMETHODCALLTYPE GetScaleMode( 
        /* [out] */ WORD *value) = 0;

    virtual HRESULT STDMETHODCALLTYPE SetAudioSource( 
        /* [in] */ WORD value) = 0;

    virtual HRESULT STDMETHODCALLTYPE GetAudioSource( 
        /* [out] */ WORD *value) = 0;

    virtual HRESULT STDMETHODCALLTYPE SetInputAlarm( 
        /* [in] */ BOOL value) = 0;

    virtual HRESULT STDMETHODCALLTYPE GetInputAlarm( 
        /* [out] */ BOOL *value) = 0;

    virtual HRESULT STDMETHODCALLTYPE GetCurrentFrame( 
        /* [out] */ DWORD *value) = 0;

    virtual HRESULT STDMETHODCALLTYPE GetDroppedFrames( 
        /* [out] */ DWORD *value) = 0;

    virtual HRESULT STDMETHODCALLTYPE GetBufferLevel( 
        /* [out] */ DWORD *value) = 0;

    virtual HRESULT STDMETHODCALLTYPE GetBoardID( 
        /* [out] */ DWORD *value) = 0;

    virtual HRESULT STDMETHODCALLTYPE GetSerialNumber( 
        /* [retval][out] */ BSTR *value) = 0;

    virtual HRESULT STDMETHODCALLTYPE GetDebug( 
        /* [out] */ int *pnDebug1,
        /* [out] */ int *pnDebug2,
        /* [out] */ int *pnDebug3) = 0;

};

Filter of AJA company can be used for setting format of output filter.

Evgeny Pereguda
  • 553
  • 1
  • 4
  • 9
  • Yes I can enum system devices and the call BindToObject() to get the source filter registered by driver. So does it mean that if I want to customize the source filter property such as video standard, I should use the IKsPropertySet instead of a specific Directshow interface? – YQ.Mei Nov 10 '17 at 11:30
  • You can find video output pin, and enums supported output AM_MEDIA_TYPE - some devices support many pins with different output formats and resolution. But it depends from device. Some vendors use own interfaces for selecting output pin formats and resolutions. – Evgeny Pereguda Nov 10 '17 at 12:58