步骤 3A。 实现 CheckInputType 方法

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

这是 编写转换筛选器教程的步骤 3A。

当上游筛选器向转换筛选器推荐媒体类型时,将调用 CTransformFilter::CheckInputType 方法。 此方法采用指向 CMediaType 对象的指针,CMediaType 对象是 AM_MEDIA_TYPE 结构的精简包装器。 在此方法中,应检查 AM_MEDIA_TYPE 结构的每个相关字段,包括格式块中的字段。 可以使用 CMediaType 中定义的访问器方法,也可以直接引用结构成员。 如果任何字段无效,则返回VFW_E_TYPE_NOT_ACCEPTED。 如果整个媒体类型有效,则返回S_OK。

例如,在 RLE 编码器筛选器中,输入类型必须是 8 位或 4 位未压缩的 RGB 视频。 没有理由支持其他输入格式(如 16 位或 24 位 RGB),因为筛选器必须将其转换为较低的位深度,并且 DirectShow 已为此提供 颜色空间转换器 筛选器。 以下示例假定编码器支持 8 位视频,但不支持 4 位视频:

HRESULT CRleFilter::CheckInputType(const CMediaType *mtIn)
{
    if ((mtIn->majortype != MEDIATYPE_Video) ||
        (mtIn->subtype != MEDIASUBTYPE_RGB8) ||
        (mtIn->formattype != FORMAT_VideoInfo) || 
        (mtIn->cbFormat < sizeof(VIDEOINFOHEADER)))
    {
        return VFW_E_TYPE_NOT_ACCEPTED;
    }

    VIDEOINFOHEADER *pVih = 
        reinterpret_cast<VIDEOINFOHEADER*>(mtIn->pbFormat);
    if ((pVih->bmiHeader.biBitCount != 8) ||
        (pVih->bmiHeader.biCompression != BI_RGB))
    {
        return VFW_E_TYPE_NOT_ACCEPTED;
    }

    // Check the palette table.
    if (pVih->bmiHeader.biClrUsed > PALETTE_ENTRIES(pVih))
    {
        return VFW_E_TYPE_NOT_ACCEPTED;
    }
    DWORD cbPalette = pVih->bmiHeader.biClrUsed * sizeof(RGBQUAD);
    if (mtIn->cbFormat < sizeof(VIDEOINFOHEADER) + cbPalette)
    {
        return VFW_E_TYPE_NOT_ACCEPTED;
    }

    // Everything is good.
    return S_OK;
}

在此示例中,方法首先检查主类型和子类型。 然后,它会检查格式类型,以确保格式块是 VIDEOINFOHEADER 结构。 筛选器还可以支持 VIDEOINFOHEADER2,但在这种情况下没有实际的好处。 VIDEOINFOHEADER2 结构添加了对交错和非方形像素的支持,这些像素在 8 位视频中不太可能相关。

如果格式类型正确,则本示例将检查 VIDEOINFOHEADER 结构的 biBitCountbiCompression 成员,以验证格式是否为 8 位未压缩 RGB。 如以下示例所示,必须强制

pbFormat

指向基于格式类型的正确结构的指针。 在强制转换指针之前,始终检查格式类型 GUID (formattype) ,以及 cbFormat) (格式块的大小。

该示例还验证调色板条目的数量是否与位深度兼容,并且格式块的大小足以容纳调色板条目。 如果所有这些信息都正确,该方法将返回S_OK。

下一步: 步骤 3B.实现 GetMediaType 方法

编写 DirectShow 筛选器