表示描述符
一个Presentation是一组相关的共享一个共同的演示时间的媒体流。例如,一个演示可以是来自电影的视频流和音频流。一个表示描述符(Presentation Descriptors)是一个包含一个特定的演示描述的对象。演示描述符用于配置媒体源和一些媒体接收器。
每个演示文稿描述符(Presentation Descriptors)包含一个或多个流描述符的列表。这些用于描述存在presentation中的流。这些流可以被选中或取消选择。只有被选中的流才会产生数据。没有被选中的流不会被激活而且也不会有任何数据产生。每一个流描述符都有一个媒体类型处理程序,用于改变或者获取流媒体的类型。
下表显示了这些对象中的每一个公开的主要接口。
对象 | 接口 |
---|---|
Presentation descriptor | IMFPresentationDescriptor |
Stream descriptor | IMFStreamDescriptor |
Media type handler | IMFMediaTypeHandler |
媒体来源介绍(Media Source Presentations)
每一个媒体源提供了一个表示描述符(Presentation Descriptors),用于描述源的默认配置。在默认配置中,至少有一条流被选中,每一个被选中的流都有媒体类型。调用 IMFMediaSource::CreatePresentationDescriptor 可获得媒体描述符(Presentation Descriptors)。返回值是一个IMFPresentationDescriptor指针。
可以修改源的表示描述符(Presentation Descriptors)来选择不同设定的流。不要修改演示文稿描述符,除非媒体源已经停止。调用IMFMediaSource::Start 来开始源的时候,所有修改的表示描述符(Presentation Descriptors)将生效。
调用 IMFPresentationDescriptor::GetStreamDescriptorCount可以获取流的数量。调用IMFPresentationDescriptor::GetStreamDescriptorByIndex 通过流的索引可以获得一条流的描述。流的索引值是从0开始的。函数返回的是一个指向IMFStreamDescriptor 的指针。它还返回一个布尔标志,表示是否选择了流。如果流被选中,则媒体源为该流产生数据。否则,源不产生该流的任何数据。通过流的索引值来调用IMFPresentationDescriptor::SelectStream可以选中一条流。调用 IMFPresentationDescriptor::DeselectStream.可以不选中流。
下面的代码演示了如何从一个媒体源获得演示文稿描述符并枚举流。
HRESULT hr = S_OK;
DWORD cStreams = 0;
BOOL fSelected = FALSE;
IMFPresentationDescriptor *pPresentation = NULL;
IMFStreamDescriptor *pStreamDesc = NULL;
hr = pSource->CreatePresentationDescriptor(&pPresentation);
if (SUCCEEDED(hr))
{
hr = pPresentation->GetStreamDescriptorCount(&cStreams);
}
if (SUCCEEDED(hr))
{
for (DWORD iStream = 0; iStream < cStreams; iStream++)
{
hr = pPresentation->GetStreamDescriptorByIndex(
iStream, &fSelected, &pStreamDesc);
if (FAILED(hr))
{
break;
}
/* Use the stream descriptor. (Not shown.) */
SAFE_RELEASE(pStreamDesc);
}
}
SAFE_RELEASE(pPresentation);
SAFE_RELEASE(pStreamDesc);
媒体类型处理程序(Media Type Handlers)
要改变流媒体类型,或要获得流的当前媒体类型,使用流描述符的媒体类型处理程序(Media Type Handlers)。调用IMFStreamDescriptor::GetMediaTypeHandler 可以得到媒体类型处理程序(Media Type Handlers),返回值是一个IMFMediaTypeHandler 指针。
如果你只是想简单的知道流中是什么样的数据,如:音频或视频。可以调用 IMFMediaTypeHandler::GetMajorType。此方法返回的主要媒体类型的GUID。例如,一个应用程序播放音频流通常连接到音频输出和一个视频流的视频渲染器。如果你使用的媒体会话(Media Session)或拓扑装载( topology loader)机建立一个拓扑结构、主要类型GUID可能是你唯一需要的格式信息。
如果您的应用程序需要当前格式的更详细的信息,调用 IMFMediaTypeHandler::GetCurrentMediaType。这个方法返回一个指向IMFMediaType 接口的指针。使用这个接口可以得到格式的细节。
媒体类型处理程序还包含一个流支持的媒体类型列表。为了获得列表的大小,调用IMFMediaTypeHandler::GetMediaTypeCount。获得列表的类型,通过索引值调用IMFMediaTypeHandler::GetMediaTypeByIndex。得列表媒体类型以近似顺序返回例如,对于音频格式,较高的采样率是较低的采样率的首选。然而,没有明确的规则,管理的顺序,所以你应该把它作为一个指导原则。
支持的类型列表可能不包含流所支持的所有媒体类型。要测试是否支持特定的媒体类型,调用IMFMediaTypeHandler::IsMediaTypeSupported.。设置媒体类型,调用 IMFMediaTypeHandler::SetCurrentMediaType。如果设置成功,流将包含符合指定格式的数据。SetCurrentMediaType方法不改变优先类型列表。
下面的代码演示了如何获取媒体类型处理程序,枚举首选媒体类型,并设置媒体类型。这个例子假定应用程序有一些算法,在这里没有显示,用于选择媒体类型。具体情况将大大取决于您的应用程序。
HRESULT hr = S_OK;
DWORD cTypes = 0;
BOOL bTypeOK = FALSE;
IMFMediaTypeHandler *pHandler = NULL;
IMFMediaType *pMediaType = NULL;
hr = pStreamDesc->GetMediaTypeHandler(&pHandler);
if (SUCCEEDED(hr))
{
hr = pHandler->GetMediaTypeCount(&cTypes);
}
if (SUCCEEDED(hr))
{
for (DWORD iType = 0; iType < cTypes; iType++)
{
hr = pHandler->GetMediaTypeByIndex(iType, &pMediaType);
if (FAILED(hr))
{
break;
}
/* Examine the media type. (Not shown.) */
/* If this media type is acceptable, set the media type. */
if (bTypeOK)
{
hr = pHandler->SetCurrentMediaType(pMediaType);
break;
}
SAFE_RELEASE(pMediaType);
}
}
SAFE_RELEASE(pMediaType);
SAFE_RELEASE(pHandler);