在输出引脚上忽略设置介质类型

时间:2013-12-21 02:23:03

标签: c++ winapi video directshow

我正在构建一个DirectShow图。 我有视频捕获滤波器,将其输出引脚连接到SampleGrabber的输入引脚。 在连接两个引脚之前,我配置输出引脚如下:

HRESULT GraphBuilder::applyVideoFormat()
{
    if( !pVideoCaptureFilter_ )
        return E_FAIL;

    CComPtr<IPin> pPin;
    pPin.Attach( findCategoryPin( pVideoCaptureFilter_, PINDIR_OUTPUT, PIN_CATEGORY_CAPTURE ) );

    if( !pPin )
        return E_FAIL;

    CComQIPtr<IAMStreamConfig> pConfig( pPin );

    if( !pConfig )
        return E_FAIL;

    AM_MEDIA_TYPE   mt = { 0 };
    VIDEOINFOHEADER vih = { 0 };

    if( videoStandard_ == AnalogVideo_NTSC_M )
        vih.AvgTimePerFrame         = 333667;
    else
        vih.AvgTimePerFrame         = 400000;

    vih.bmiHeader.biSize            = sizeof( BITMAPINFOHEADER );
    vih.bmiHeader.biWidth           = captureResolution_.cx;
    vih.bmiHeader.biHeight          = captureResolution_.cy;
    vih.bmiHeader.biPlanes          = 1;
    vih.bmiHeader.biBitCount        = 16;
    vih.bmiHeader.biCompression     = mmioFOURCC('Y','U','Y','2');
    vih.bmiHeader.biSizeImage       = vih.bmiHeader.biWidth * vih.bmiHeader.biHeight * 2;

    mt.majortype                    = MEDIATYPE_Video;
    mt.subtype                      = MEDIASUBTYPE_YUY2;
    mt.bFixedSizeSamples            = TRUE;
    mt.bTemporalCompression         = FALSE;
    mt.lSampleSize                  = vih.bmiHeader.biSizeImage;
    mt.formattype                   = FORMAT_VideoInfo;
    mt.cbFormat                     = sizeof( VIDEOINFOHEADER );
    mt.pbFormat                     = (BYTE*)&vih;
    mt.pUnk                         = NULL;

    return pConfig->SetFormat( &mt ); // SUCCESS - always
}

我也配置了样本采集器,虽然我知道它只考虑主要类型和子类型。它并不关心其余部分。

HRESULT GraphBuilder::configureVideoSampleGrabber( ISampleGrabber * const pSampleGrabber )
{
    AM_MEDIA_TYPE mt = { 0 };
    VIDEOINFOHEADER vih = { 0 };

    if( videoStandard_ == AnalogVideo_NTSC_M )
        vih.AvgTimePerFrame         = 333667;
    else
        vih.AvgTimePerFrame         = 400000;

    vih.bmiHeader.biSize            = sizeof( BITMAPINFOHEADER );
    vih.bmiHeader.biWidth           = captureResolution_.cx;
    vih.bmiHeader.biHeight          = captureResolution_.cy;
    vih.bmiHeader.biPlanes          = 1;
    vih.bmiHeader.biBitCount        = 16;
    vih.bmiHeader.biCompression     = mmioFOURCC('Y','U','Y','2');
    vih.bmiHeader.biSizeImage       = vih.bmiHeader.biWidth * vih.bmiHeader.biHeight * 2;

    mt.majortype                    = MEDIATYPE_Video;
    mt.subtype                      = MEDIASUBTYPE_YUY2;
    mt.bFixedSizeSamples            = TRUE;
    mt.bTemporalCompression         = FALSE;
    mt.lSampleSize                  = vih.bmiHeader.biSizeImage;
    mt.formattype                   = FORMAT_VideoInfo;
    mt.cbFormat                     = sizeof( VIDEOINFOHEADER );
    mt.pbFormat                     = (BYTE*)&vih;
    mt.pUnk                         = NULL;

    return pSampleGrabber->SetMediaType( &mt ); // SUCCESS - always
}

一旦过滤器在图中,但在连接之前调用此代码。所有返回值均为0。 在此示例中,captureResolution_.cx = 352和captureResolution_.cy = 240。

现在,问题是:为什么我总是通过SampleGrabber而不是352x240获得默认的720x480?我将捕获引脚配置为提供352x240。

1 个答案:

答案 0 :(得分:1)

你在做什么是正确的,但是你想要改变一些事情。

您肯定想要查看Sample Grabber初始化。您不需要在其上设置完全指定的媒体类型。相反,你想要一个只有主要类型的部分媒体类型,一个子类型被初始化(其余的是NULL'ed)。理由如下。

Sample Grabber只是一个插件,您可以将其配置为坚持特定的媒体类型。特别是,它无法以任何其他方式在上游连接上计算出连接类型,而不是直接将尝试与其内部引用类型进行比较,并根据此比较的结果接受或拒绝。话虽如此,您的Sample Grabber无法帮助设置分辨率,但如果某些不重要的字段中的介质类型不同,它可以拒绝连接。在Sample Grabber上需要视频YUY2就足够了,其余的格式是视频源的责任。

要确保此媒体类型适用于视频源,您始终可以在不使用Sample Grabber的情况下以交互方式连接它,并查看有效连接媒体类型的所有字段。