在处理视频捕获时,如何使用一些新的模拟视频格式或路由到一些新的物理连接器?

时间:2017-11-10 09:33:56

标签: windows directshow video-capture crossbar

我最近正在开发一个带有Directshow的多媒体播放器应用程序,我可以成功构建过滤器图形来捕获来自网络摄像头的视频流。

我在MSDN上阅读了Directshow文档,发现WDM视频捕获过滤器暴露了IAMAnalogVideoDecoder接口,我可以设置AnalogVideo标准枚举中列出的模拟视频格式,但这个枚举不包含一些新的HD标准,如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;

更重要的是,当捕获卡有多个物理输入时,会自动添加一个交叉开关过滤器,我可以使用PhysicalConnectorType枚举路由我想要的输入,但不包括一些新的输入,如HDMI:

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;

我知道Directshow是一个旧的多媒体框架,标题可能已经过时了。那么有什么方法可以为Directshow应用一些新标准吗? Directshow还有其他一些重新分配吗?或者我应该放弃使用Directshow并改为使用Media Foundation?

1 个答案:

答案 0 :(得分:0)

所以,你正确的写道,微软停止支持DirectShow。 DirectShow默认不支持720p,1080i,1080p等高清标准。为了解决这样的问题,视频捕获设备的供应商开发了支持这种新设备的私有直接显示过滤器并将其包含在设备的驱动程序中 - 在安装驱动器时安装此过滤器 - 这意味着您必须研究OS系统查找DirectShow源过滤器 - 其中一个将是您需要的过滤器,当然如果您安装了驱动程序。关于Media Foundation - 目前它仅支持USB视频类驱动程序Audio/Video Capture in Media Foundation以捕获视频 - 此类驱动程序仅支持USB网络摄像头。

问候。

P.S。要获得输出引脚,您可以使用下一个代码:`

                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);

`

某些供应商为DS过滤器的扩展定义了自己的界面 - 例如AJA DS过滤器:

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;

};

AJA公司的过滤器可用于设置输出过滤器的格式。