媒体类型是描述数字媒体格式的通用和可扩展的方式。 当两个Filter连接时,它们就媒体类型达成一致。 媒体类型标识上游Filter 将传递给下游Filter的数据类型以及数据的物理布局。 如果两个Filter无法就媒体类型达成一致,则它们将无法连接。对于某些应用程序,您不必担心媒体类型。 例如,在文件播放中,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结构。视频使用各种结构,包括VIDEOINFOHEADER和VIDEOINFOHEADER2。 AM_MEDIA_TYPE结构的formattype成员是一个GUID,它指定格式块中包含的结构。每个格式结构都分配了一个GUID。 cbFormat成员指定格式块的大小。在取消引用pbFormat指针之前,始终检查这些值。
如果填充格式块,则主要类型和子类型包含冗余信息。 然而,主要类型和子类型提供了一种方便的方式来识别没有完整格式块的格式。 例如,您可以指定一个通用的24位RGB格式(MEDIASUBTYPE_RGB24),而无需知道VIDEOINFOHEADER结构所需的全部信息,例如图像大小和帧速率。
例如,Filter可能使用如下代码来检查媒体类型:
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结构体还包含一些可选字段。这些字段可以用来提供额外的信息,但Filter不需要使用它们:
·ISampleSize:如果该字段不为零,则它定义每个样本的大小。如果它为零,则表示样本大小可能随着样本而变化;
·bFixedSizeSamples:如果此布尔标志为TRUE,则表示ISampleSize中的有效,否则,你应该忽略ISampleSize;
·bTemporalCompression:如果此布尔标志为FALSE,则表示所有帧都是关键帧。
参考:
https://www.yuque.com/docs/share/60aa5ed9-b68a-472a-b2ec-69415a86e6fd