如何设置视频捕获格式

视频捕获设备可能支持多种捕获格式。 格式通常因压缩类型、颜色空间 (YUV 或 RGB) 、帧大小或帧速率而异。

支持的格式列表包含在 演示文稿描述符中。 有关详细信息,请参阅 演示文稿描述符

枚举支持的格式:

  1. 为捕获设备创建媒体源。 请参阅 枚举视频捕获设备
  2. 调用媒体源上的 IMFMediaSource::CreatePresentationDescriptor 以获取演示文稿描述符。
  3. 调用 IMFPresentationDescriptor::GetStreamDescriptorByIndex 获取视频流的流描述符。
  4. 在流描述符上调用 IMFStreamDescriptor::GetMediaTypeHandler
  5. 调用 IMFMediaTypeHandler::GetMediaTypeCount 以获取支持的格式数。
  6. 在循环中,调用 IMFMediaTypeHandler::GetMediaTypeByIndex 以获取每种格式。 格式由 媒体类型表示。 有关详细信息,请参阅 视频媒体类型

以下示例枚举设备的捕获格式:

HRESULT EnumerateCaptureFormats(IMFMediaSource *pSource)
{
    IMFPresentationDescriptor *pPD = NULL;
    IMFStreamDescriptor *pSD = NULL;
    IMFMediaTypeHandler *pHandler = NULL;
    IMFMediaType *pType = NULL;

    HRESULT hr = pSource->CreatePresentationDescriptor(&pPD);
    if (FAILED(hr))
    {
        goto done;
    }

    BOOL fSelected;
    hr = pPD->GetStreamDescriptorByIndex(0, &fSelected, &pSD);
    if (FAILED(hr))
    {
        goto done;
    }

    hr = pSD->GetMediaTypeHandler(&pHandler);
    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);
        if (FAILED(hr))
        {
            goto done;
        }

        LogMediaType(pType);
        OutputDebugString(L"\n");

        SafeRelease(&pType);
    }

done:
    SafeRelease(&pPD);
    SafeRelease(&pSD);
    SafeRelease(&pHandler);
    SafeRelease(&pType);
    return hr;
}

LogMediaType本主题媒体类型调试代码中列出了此示例中使用的函数。

设置捕获格式:

  1. 获取指向 IMFMediaTypeHandler 接口的指针,如上一示例所示。
  2. 调用 IMFMediaTypeHandler::GetMediaTypeByIndex 以获取由 index 指定的所需格式。
  3. 调用 IMFMediaTypeHandler::SetCurrentMediaType 以设置格式。

如果未设置捕获格式,设备将使用其默认格式。

以下示例设置捕获格式:

HRESULT SetDeviceFormat(IMFMediaSource *pSource, DWORD dwFormatIndex)
{
    IMFPresentationDescriptor *pPD = NULL;
    IMFStreamDescriptor *pSD = NULL;
    IMFMediaTypeHandler *pHandler = NULL;
    IMFMediaType *pType = NULL;

    HRESULT hr = pSource->CreatePresentationDescriptor(&pPD);
    if (FAILED(hr))
    {
        goto done;
    }

    BOOL fSelected;
    hr = pPD->GetStreamDescriptorByIndex(0, &fSelected, &pSD);
    if (FAILED(hr))
    {
        goto done;
    }

    hr = pSD->GetMediaTypeHandler(&pHandler);
    if (FAILED(hr))
    {
        goto done;
    }

    hr = pHandler->GetMediaTypeByIndex(dwFormatIndex, &pType);
    if (FAILED(hr))
    {
        goto done;
    }

    hr = pHandler->SetCurrentMediaType(pType);

done:
    SafeRelease(&pPD);
    SafeRelease(&pSD);
    SafeRelease(&pHandler);
    SafeRelease(&pType);
    return hr;
}

格式的返回顺序取决于设备。 通常,它们首先按压缩类型或颜色空间进行分组;然后从最小帧大小到每个组中的最大帧大小。

帧速率的处理方式与其他格式属性略有不同。 有关详细信息,请参阅 如何设置视频捕获帧速率

注意

在某些设备中,格式列表将包含每种格式的重复条目。 例如,如果设备支持 15 种不同的捕获格式,则列表将包含 30 个条目。 在每个对中,其中一个媒体类型的属性 MF_MT_AM_FORMAT_TYPE 等于 FORMAT_VideoInfo,另一个媒体类型的 属性MF_MT_AM_FORMAT_TYPE 等于 FORMAT_VideoInfo2。 (这两个值在头文件 uuids.h.) 第二种类型还可能包含其他颜色信息 (扩展颜色信息) 或显示用于交错 (MF_MT_INTERLACE_MODE) 的不同值。 存在这些重复类型以支持较旧的 DirectShow 应用程序。 在 Media Foundation 应用程序中,每当列出重复 FORMAT_VideoInfo2 类型时,都应忽略 FORMAT_VideoInfo 类型。

 

视频捕获