配置视频输出格式

[与此页面关联的功能 DirectShow 是旧版功能。 它已被 MediaPlayerIMFMediaEngineMedia Foundation 中的音频/视频捕获所取代。 这些功能已针对Windows 10和Windows 11进行了优化。 Microsoft 强烈建议新代码尽可能在 Media Foundation 中使用 MediaPlayerIMFMediaEngine音频/视频捕获 ,而不是 DirectShow。 如果可能,Microsoft 建议重写使用旧 API 的现有代码以使用新 API。]

注意

本主题中所述的功能已弃用。 若要配置捕获设备的输出格式,应用程序应在 pmt 参数中使用 IAMStreamConfig::GetFormat 返回的AM_MEDIA_TYPE结构。

 

捕获设备可以支持一系列输出格式。 例如,设备可能支持 16 位 RGB、32 位 RGB 和 YUYV。 在上述每种格式中,设备可以支持一系列帧大小。

在 WDM 设备中, IAMStreamConfig 接口用于报告设备支持的格式并设置格式。 (对于旧版 VFW 设备,请使用“视频格式 VFW”对话框,如 显示 VFW 捕获对话框中所述。) IAMStreamConfig 接口在捕获筛选器的捕获引脚和/或预览引脚上公开。 使用 ICaptureGraphBuilder2::FindInterface 方法获取接口指针:

IAMStreamConfig *pConfig = NULL;
hr = pBuild->FindInterface(
    &PIN_CATEGORY_PREVIEW, // Preview pin.
    0,    // Any media type.
    pCap, // Pointer to the capture filter.
    IID_IAMStreamConfig, (void**)&pConfig);

设备具有它支持的媒体类型的列表。 对于每种媒体类型,设备还提供一组功能。 其中包括可用于该格式的帧大小范围、设备拉伸或收缩图像的大小以及帧速率范围。

若要获取媒体类型的数量,请调用 IAMStreamConfig::GetNumberOfCapabilities 方法。 方法返回两个值:

  • 媒体类型的数量。
  • 保存功能信息的结构的大小。

大小值是必需的,因为 IAMStreamConfig 接口用于音频和视频 (,并且可以扩展到其他媒体类型) 。 对于视频,这些功能是使用 VIDEO_STREAM_CONFIG_CAPS 结构描述的,而音频使用 AUDIO_STREAM_CONFIG_CAPS 结构。

若要枚举媒体类型,请使用从零开始的索引调用 IAMStreamConfig::GetStreamCaps 方法。 GetStreamCaps 方法返回媒体类型和相应的功能结构:

int iCount = 0, iSize = 0;
hr = pConfig->GetNumberOfCapabilities(&iCount, &iSize);

// Check the size to make sure we pass in the correct structure.
if (iSize == sizeof(VIDEO_STREAM_CONFIG_CAPS))
{
    // Use the video capabilities structure.

    for (int iFormat = 0; iFormat < iCount; iFormat++)
    {
        VIDEO_STREAM_CONFIG_CAPS scc;
        AM_MEDIA_TYPE *pmtConfig;
        hr = pConfig->GetStreamCaps(iFormat, &pmtConfig, (BYTE*)&scc);
        if (SUCCEEDED(hr))
        {
            /* Examine the format, and possibly use it. */

            // Delete the media type when you are done.
            DeleteMediaType(pmtConfig);
        }
}

请注意如何为 GetStreamCaps 方法分配结构。 方法分配媒体类型结构,而调用方分配功能结构。 将功能结构强制转换为字节数组指针。 使用完媒体类型后,删除 AM_MEDIA_TYPE 结构以及媒体类型的格式块。

可以将设备配置为使用 GetStreamCaps 方法中返回的格式。 只需使用媒体类型调用 IAMStreamConfig::SetFormat

hr = pConfig->SetFormat(pmtConfig);

如果引脚未连接,则会尝试在连接时使用此格式。 如果引脚已连接,它将尝试使用新格式重新连接。 在任一情况下,下游筛选器都可能会拒绝格式。

还可以在将媒体类型传递给 SetFormat 方法之前对其进行修改。 这是 VIDEO_STREAM_CONFIG_CAPS 结构的来源。 它介绍了更改媒体类型的所有有效方法。 若要使用此信息,必须了解该特定媒体类型的详细信息。

例如,假设 GetStreamCaps 返回 24 位 RGB 格式,其帧大小为 320 x 240 像素。 可以通过检查媒体类型的主要类型、子类型和格式块来获取此信息:

if ((pmtConfig.majortype == MEDIATYPE_Video) &&
    (pmtConfig.subtype == MEDIASUBTYPE_RGB24) &&
    (pmtConfig.formattype == FORMAT_VideoInfo) &&
    (pmtConfig.cbFormat >= sizeof (VIDEOINFOHEADER)) &&
    (pmtConfig.pbFormat != NULL))
{
    VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)pmtConfig.pbFormat;
    // pVih contains the detailed format information.
    LONG lWidth = pVih->bmiHeader.biWidth;
    LONG lHeight = pVih->bmiHeader.biHeight;
}

VIDEO_STREAM_CONFIG_CAPS结构提供可用于此媒体类型的最小和最大宽度和高度。 它还提供“步长”大小,用于定义调整宽度或高度的增量。 例如,设备可能会返回以下内容:

  • MinOutputSize:160 x 120
  • MaxOutputSize:320 x 240
  • OutputGranularityX:8 像素 (水平步长)
  • OutputGranularityY:8 像素 (垂直步长)

给定这些数字,可以将宽度设置为 (160、168、176...304、312、320) 和高度 (在 120、128、136...104、112、120) 。 下图演示了此过程。

视频格式大小

若要设置新的帧大小,请直接修改 GetStreamCaps 中返回的AM_MEDIA_TYPE结构:

pVih->bmiHeader.biWidth = 160;
pVih->bmiHeader.biHeight = 120;
pVih->bmiHeader.biSizeImage = DIBSIZE(pVih->bmiHeader);

然后,将媒体类型传递给 SetFormat 方法,如前所述。

VIDEO_STREAM_CONFIG_CAPSMinFrameIntervalMaxFrameInterval 成员是每个视频帧的最小和最大长度,可将其转换为帧速率,如下所示:

frames per second = 10,000,000 / frame duration

若要请求特定的帧速率,请修改媒体类型中 VIDEOINFOHEADERVIDEOINFOHEADER2 结构中的 AvgTimePerFrame 的值。 设备可能不支持最小值和最大值之间的每个可能值,因此驱动程序将使用最接近的值。 若要查看驱动程序实际使用的值,请在调用 SetFormat 后调用 IAMStreamConfig::GetFormat

某些驱动程序可能会报告 MaxFrameInterval 值的 MAXLONGLONG (0x7FFFFFFFFFFFFFFF) ,这实际上意味着没有最长持续时间。 但是,你可能希望在应用程序中强制实施最小帧速率,例如 1 fps。

关于媒体类型

配置视频捕获设备