我建議分五步完成你的任務: 1.編寫播放ONE視頻文件的代碼。在MSDN上有示例代碼:How to Play Media Files with Media Foundation。 2. WORKABLE播放器的研究代碼點,從視頻文件路徑(URL)創建MediaSource。 3.從兩個視頻文件路徑(URL)創建TWO MediaSource。 4.按功能MFCreateAggregateSource從兩個MediaSource創建 - ONE MediaSource並從方法播放器重新指定MediaSource HRESULT CreateMediaSource(PCWSTR sURL, IMFMediaSource **ppSource)
5. call'hr = AddOutputNode(pTopology,pSinkActivate,0,& pOutputNode);'兩次:'hr = AddOutputNode(pTopology,pSinkActivate,0,& pOutputNode);'用於第一視頻流並且用於第二視頻流的hr = AddOutputNode(pTopology, pSinkActivate, 1, &pOutputNode);
。
問候。
P.S.如果您將兩個視頻與音頻流一起使用,那麼您將在Aggregate MediaSource中擁有四個流 - 它可能需要查找視頻流的流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;
}
}
然後設置此裝箱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
增加。
想法是代碼爲視頻渲染器創建Activate
之前創建Topology
- 它是確定的。然後,這一個視頻渲染器通過檢查條件if (MFMediaType_Video == guidMajorType)
來激活MediaSource中所有視頻流之間的ref指針共享。通過遞增全局變量globalVideoIndex++
,每個VIDEO流都得到了唯一的ID,這個ID在方法hr = AddOutputNode(pTopology, pSinkActivate, iStreamID, &pOutputNode);
中設置。其結果是,所有視頻流將由一個視頻渲染器被吸入,並與iStreamID
視頻流是0將reference background
,而其他視頻流將附加。
你如何添加實際的來源?你使用源解析器,聚合源還是序列源? – VuVirt
@VuVirt:我正在使用源聚合器從多個視頻源創建一個源。但現在正努力在使用EVR和顯示控件的一個渲染器中顯示兩個視頻。 – User7723337
我不確定標準IMFMediaSession支持EVR的多個視頻輸入。您可能需要實施自定義媒體會話。 – VuVirt