我建议将您的任务分为五个步骤:
1. 编写播放一个视频文件的代码。在 MSDN 上有示例代码:How to Play Media Files with Media Foundation。
2. WORKABLE player for point的研究代码,从视频文件路径(URL)创建MediaSource。
3. 从两个视频文件路径(URL)创建两个 MediaSource。
4.通过函数MFCreateAggregateSource从两个MediaSource-一个MediaSource创建并从方法播放器HRESULT CreateMediaSource(PCWSTR sURL, IMFMediaSource **ppSource)返回MediaSource
5. 调用'hr = AddOutputNode(pTopology, pSinkActivate, 0, &pOutputNode);'两次:'hr = AddOutputNode(pTopology, pSinkActivate, 0, &pOutputNode);'用于第一个视频流,hr = AddOutputNode(pTopology, pSinkActivate, 1, &pOutputNode); 用于第二个视频流。
问候。
附:如果您将使用两个带有音频流的视频,那么您将在 Aggregate MediaSource 中有四个流 - 它可能需要 FIND 视频流的流 ID。
P.S.S 仅查看演示代码并不容易推荐,但在CreateMediaSinkActivate 中您会找到代码hr = MFCreateVideoRendererActivate(hVideoWindow, &pActivate);。在您的代码中,您必须先创建此Activate:
// For each stream, create the topology nodes and add them to the topology.
for (DWORD i = 0; i < cSourceStreams; i++)
{
hr = AddBranchToPartialTopology(pTopology, pSource, pPD, i, hVideoWnd);
if (FAILED(hr))
{
goto done;
}
}
然后将这个 crated Activate 设置为 AddBranchToPartialTopology 的参数
例如:
hr = MFCreateVideoRendererActivate(hVideoWindow, &pVideoRendererActivate);
// For each stream, create the topology nodes and add them to the topology.
for (DWORD i = 0; i < cSourceStreams; i++)
{
hr = AddBranchToPartialTopology(pTopology, pSource, pPD, i, pVideoRendererActivate);
if (FAILED(hr))
{
goto done;
}
}
在AddBranchToPartialTopology你必须这样写:
HRESULT AddBranchToPartialTopology(
IMFTopology *pTopology, // Topology.
IMFMediaSource *pSource, // Media source.
IMFPresentationDescriptor *pPD, // Presentation descriptor.
DWORD iStream, // Stream index.
IMFActivate* aVideoRendererActivate) // VideoRenderer for video playback.
{
IMFStreamDescriptor *pSD = NULL;
IMFActivate *pSinkActivate = NULL;
IMFTopologyNode *pSourceNode = NULL;
IMFTopologyNode *pOutputNode = NULL;
BOOL fSelected = FALSE;
HRESULT hr = pPD->GetStreamDescriptorByIndex(iStream, &fSelected, &pSD);
if (FAILED(hr))
{
goto done;
}
DWORD iStreamID = 0;
if (fSelected)
{
// Create the media sink activation object.
hr = CreateMediaSinkActivate(pSD, iStreamID, aVideoRendererActivate, &pSinkActivate);
在 'CreateMediaSinkActivate' 中你必须这样写:
DWORD globalVideoIndex = 0;
HRESULT CreateMediaSinkActivate(
IMFStreamDescriptor *pSourceSD, // Pointer to the stream descriptor.
DWORD& iStreamID, // ctream index
IMFActivate *pVideoRendererActivate, // Handle to the video renderer activate.
IMFActivate **ppActivate
)
{
IMFMediaTypeHandler *pHandler = NULL;
IMFActivate *pActivate = NULL;
// Get the media type handler for the stream.
HRESULT hr = pSourceSD->GetMediaTypeHandler(&pHandler);
if (FAILED(hr))
{
goto done;
}
// Get the major media type.
GUID guidMajorType;
hr = pHandler->GetMajorType(&guidMajorType);
if (FAILED(hr))
{
goto done;
}
// Create an IMFActivate object for the renderer, based on the media type.
if (MFMediaType_Audio == guidMajorType)
{
// Create the audio renderer.
hr = MFCreateAudioRendererActivate(&pActivate);
}
else if (MFMediaType_Video == guidMajorType)
{
// Share the video renderer.
hr = pVideoRendererActivate->QueryInterface(IID_PPV_ARG(pActivate))
iStreamID = globalVideoIndex++;
}
else
{
// Unknown stream type.
hr = E_FAIL;
// Optionally, you could deselect this stream instead of failing.
}
if (FAILED(hr))
{
goto done;
}
// Return IMFActivate pointer to caller.
*ppActivate = pActivate;
(*ppActivate)->AddRef();
done:
SafeRelease(&pHandler);
SafeRelease(&pActivate);
return hr;
}
在AddBranchToPartialTopology你必须写:
// Create the output node for the renderer.
hr = AddOutputNode(pTopology, pSinkActivate, iStreamID, &pOutputNode);
if (FAILED(hr))
{
goto done;
}
对于音频流iStreamID 将为零,但对于视频流它将从全局变量globalVideoIndex 递增。
想法是在创建 Topology 之前为视频渲染器创建 Activate 的代码 - 没关系。然后这个 ONE 视频渲染器通过检查条件 if (MFMediaType_Video == guidMajorType) 在 MediaSource 中的所有视频流之间通过引用指针激活共享。每个 VIDEO 流都通过递增全局变量 globalVideoIndex++ 从 0 获得唯一 id - 此 id 在方法 hr = AddOutputNode(pTopology, pSinkActivate, iStreamID, &pOutputNode); 中设置。这样一来,所有的视频流都会被ONE视频渲染器绘制出来,iStreamID为0的视频流将reference background,而其他视频流将额外添加。