关于媒体类型 (DirectShow)

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

由于 DirectShow 是模块化的,因此需要一种方法来描述筛选图中每个点的数据格式。 例如,请考虑 AVI 播放。 数据以 RIFF 区块流的形式进入图形。 这些内容将解析为视频和音频流。 视频流由可能压缩的视频帧组成。 解码后,视频流是一系列未压缩的位图。 音频流会经历类似的过程。

媒体类型:DirectShow 如何表示格式

媒体类型是描述数字媒体格式的通用且可扩展的方法。 当两个筛选器连接时,它们就媒体类型达成一致。 媒体类型标识上游筛选器将传送到下游筛选器的数据类型,以及数据的物理布局。 如果两个筛选器无法就媒体类型达成一致,它们将无法连接。

对于某些应用程序,你永远不必担心媒体类型。 例如,在文件播放中,DirectShow 处理所有详细信息。 其他类型的应用程序可能需要直接使用媒体类型。

媒体类型是使用 AM_MEDIA_TYPE 结构定义的。 此结构包含以下信息:

  • 主要类型:主类型是定义数据总体类别的 GUID。 主要类型包括视频、音频、未分析字节流、MIDI 数据等。

  • 子类型:子类型是另一个 GUID,用于进一步定义格式。 例如,在视频主类型中,有 RGB-24、RGB-32、UYVY 等的子类型。 在音频中,有 PCM 音频、MPEG-1 有效负载等。 子类型提供比主类型更多的信息,但它不定义有关格式的所有内容。 例如,视频子类型不定义图像大小或帧速率。 这些由格式块定义,如下所述。

  • 格式块:格式块是详细描述格式的数据块。 格式块与 AM_MEDIA_TYPE 结构分开分配。 AM_MEDIA_TYPE 结构的 pbFormat 成员指向格式块。

    pbFormat 成员的类型为 void*,因为格式块的布局根据媒体类型而变化。 例如,PCM 音频使用 WAVEFORMATEX 结构。 视频使用各种结构,包括 VIDEOINFOHEADERVIDEOINFOHEADER2AM_MEDIA_TYPE 结构的 formattype 成员是一个 GUID,用于指定格式块中包含的结构。 每个格式结构都分配有一个 GUID。 cbFormat 成员指定格式块的大小。 在取消引用 pbFormat 指针之前,始终检查这些值。

如果格式块已填充,则主要类型和子类型包含冗余信息。 但是,主类型和子类型提供了一种无需完整格式块即可识别格式的便捷方法。 例如,可以在 (MEDIASUBTYPE_RGB24) 指定通用 24 位 RGB 格式,而无需知道 VIDEOINFOHEADER 结构所需的所有信息,例如图像大小和帧速率。

例如,筛选器可能使用以下代码来检查媒体类型:

HRESULT CheckMediaType(AM_MEDIA_TYPE *pmt)
{
    if (pmt == NULL) return E_POINTER;

    // Check the major type. We're looking for video.
    if (pmt->majortype != MEDIATYPE_Video)
    {
        return VFW_E_INVALIDMEDIATYPE;
    }

    // Check the subtype. We're looking for 24-bit RGB.
    if (pmt->subtype != MEDIASUBTYPE_RGB24)
    {
        return VFW_E_INVALIDMEDIATYPE;
    }

    // Check the format type and the size of the format block.
    if ((pmt->formattype == FORMAT_VideoInfo) &&
         (pmt->cbFormat >= sizeof(VIDEOINFOHEADER) &&
         (pmt->pbFormat != NULL))
    {
        // Now it's safe to coerce the format block pointer to the
        // correct structure, as defined by the formattype GUID.
        VIDEOINFOHEADER *pVIH = (VIDEOINFOHEADER*)pmt->pbFormat;
    
        // Examine pVIH (not shown). If it looks OK, return S_OK.
        return S_OK;
    }

    return VFW_E_INVALIDMEDIATYPE;
}

AM_MEDIA_TYPE结构还包含一些可选字段。 这些可用于提供其他信息,但筛选器不需要使用这些信息:

  • lSampleSize。 如果此字段为非零,则定义每个样本的大小。 如果为零,则表示样本大小可能会因样本而变化。
  • bFixedSizeSamples。 如果此布尔标志为 TRUE,则表示 lSampleSize 中的值有效。 否则,应忽略 lSampleSize
  • bTemporalCompression。 如果此布尔标志为 FALSE,则表示所有帧都是关键帧。

筛选器图及其组件