我的任务是创建一个应用程序,该应用程序接收音频/视频捕获输入(使用Elgato Cam Link)并将其输出回用户。 根据Microsoft的Audio/Video Capture in Media Foundation文档,建议“ 如果要将音频捕获与视频捕获结合使用,请使用聚合媒体源。”
我从topoedit的源代码中删除了我需要的大部分代码,但是topoedit并未在任何地方使用聚合源,因此在正确使用它们方面我有些盲目。
使用聚合媒体源时遇到两个不同的问题。
帧频
我有一个捕获设备(Elgato Cam Link),当我使用聚合媒体源时可以成功播放音频和视频,但是由于某些原因,帧速率比我只运行两种完全独立的拓扑(一种用于视频,一种用于音频)更糟糕。
调用IMFTopoloader :: Load()时出现错误MF_E_TOPO_CODEC_NOT_FOUND(0xC00D5212)
当我尝试在两台不同的笔记本电脑上使用聚合媒体源时(使用任何内置的网络摄像头) /麦克风组合),我遇到此错误。这个错误使我感到困惑,因为如果我使用两种完全独立的拓扑(一种用于视频,一种用于音频),它运行得很好。
主要设置:
只是提前排除一些建议...
只需使用DirectShow!
我希望我能。我受此困扰的唯一原因是因为我们的DirectShow解决方案在Elgato Cam Link设备上出现严重帧速率问题。我们无法弄清楚为什么,所以Media Foundation似乎是我们最好的选择。
使用两个单独的拓扑!
这就是我目前正在使用的方式。这只是感觉错误,您知道吗?该文档说要使用汇总源,因此我想尽职调查。最后,如果我没有得到这个问题的答案,我至少可以轻松自在地知道我具有 something 功能,但是我主要是在问这个问题,以防万一更好的东西。 Skype必须做这样的事情吗? (再三考虑,Skype不会将音频输出回自己的扬声器,所以也许不会)。肯定有人在那里知道如何使用聚合源。
鉴于我的程序可以在Elgato设备上成功运行,我怀疑我没有做任何可怕的错误。如果有问题,可能是我没有使用的代码,而不是我可以显示的任何内容。
话虽如此,我在这里创建聚合源(不包括为简洁起见进行错误检查)。
HRESULT GenerateAggregateSource(IMFMediaSource*& pAggSource, IMFMediaSource* pSource1, IMFMediaSource* pSource2)
{
pAggSource = NULL;
HRESULT hr = S_OK;
IMFCollection* pSourceCollection = NULL;
hr = ::MFCreateCollection(&pSourceCollection);
hr = pSourceCollection->AddElement(pSource1);
hr = pSourceCollection->AddElement(pSource2);
hr = ::MFCreateAggregateSource(pSourceCollection, &pAggSource);
pSourceCollection->Release(); // Done with this
return hr;
}
然后我将EVR连接到流描述符0,将SAR连接到流描述符1。
如果您更想解决第2个问题(同样,不包括为简便起见而进行的错误检查),那么这里就是我称之为IMFTopoloader :: Load()的地方。
HRESULT ResolveTopology(IMFTopology*& pTopology, IMFMediaSession* pMediaSession)
{
HRESULT hr = S_OK;
IMFTopoLoader* pTopoLoader = NULL;
hr = ::MFCreateTopoLoader(&pTopoLoader);
IMFTopology* pFullTopology = NULL;
hr = pTopoLoader->Load(pTopology, &pFullTopology, NULL);
// Laptop webcams seem to encounter this error here
//MF_E_TOPO_CODEC_NOT_FOUND
hr = pMediaSession->SetTopology(MFSESSION_SETTOPOLOGY_IMMEDIATE, pFullTopology);
// Swap the topology we're holding
pTopology->Release();
pTopology = pFullTopology;
// Done with this
pTopoLoader->Release();
return hr;
}
使用请求的拓扑更新:
这是我的局部拓扑的粗略示例。这可能是您所期望的,因为我不想做任何花哨的事情。
⇗ EVR
Agg. Source (A/V)
⇘ SAR
一旦我解析了拓扑,还会注入什么额外的东西?我不知道该如何走链并查询拓扑中的所有内容。如果您相信topoedit分别处理音频和视频源的功能,那么它看起来像这样。
⇗ {CF862982-23B0-4E3D-8C76-D03FEF084AF8} ⇒ EVR
Agg. Source (A/V)
⇘ SAR
什么是{CF862982-23B0-4E3D-8C76-D03FEF084AF8}
?我不确定,也不确定如何找出答案。
当我再次访问Elgato时,我将更新上述拓扑。我目前没有它。
更新2 所写的客户似乎不太关心向我提供任何反馈(好坏),因此我不太在意对此进行跟进奇怪的问题。