IMFSinkWriter::BeginWriting 未初始化,因为 IMFMediaEventGenerator 有未决事件

Posted

技术标签:

【中文标题】IMFSinkWriter::BeginWriting 未初始化,因为 IMFMediaEventGenerator 有未决事件【英文标题】:IMFSinkWriter::BeginWriting does not initialize because the IMFMediaEventGenerator has pending events 【发布时间】:2019-07-03 21:42:56 【问题描述】:

我正在尝试使用 IMFSinkWriter 来呈现音频样本 (IMFSample),但在调用 IMFSinkWriter::BeginWriting 方法时遇到问题,因为它返回代码:MF_E_MULTIPLE_SUBSCRIBERS。这是因为我打电话给IMFStreamSink::BeginGetEvent(Callback, null)

我尝试在没有先调用 (BeginGetEvent) 的情况下调用该方法 (BeginWriting),令人惊讶的是,该方法工作正常,我可以成功处理音频样本。

问题是在创建 SinkWriter 后我无法调用 (BeginGetEvent)。

用于创建 SAR(流音频渲染)的代码:

HRESULT Hr = E_FAIL;
IMFMediaSink *pAudioRender = NULL;
IMFStreamSink *pStreamSink = NULL;
IMFMediaTypeHandler *pMediaHandler = NULL;
IMFPresentationClock *pPresentClock = NULL;
IMFPresentationTimeSource* pTimeSource = NULL;
IMFSinkWriter *pSinkWriter = NULL;

Hr = MFCreateAudioRenderer(NULL, &pAudioRender);

我为 Collector 创建了 IMFPresenetationClock:

Hr = MFCreateSystemTimeSource(&pTimeSource);
Hr = MFCreatePresentationClock(&pPresentClock);
pPresentClock ->SetTimeSource(pTimeSource);
IMFMediaSink->SetPresentationClock(pPresentClock );

这部分我配置Stream Sink:

pAudioRender->GetStreamSinkByIndex(0, &pStreamSink);
pStreamSink->GetMediaTypeHandler(&pMediaHandler);
pMediaHandler->SetCurrentMediaType(DecodePCM);

如果我在这里调用 BeginGetEvent,将不会创建 SinkWriter。如果我在创建 SinkWriter 后调用,我会成功,但我不能再次使用 BeginGetEvent,因为它会返回:MF_E_MULTIPLE_SUBSCRIBERS。

我使用这段代码创建了 SinkWriter,创建过程很顺利,但是在第三行,如果我在 IMFStreamSink 中调用 (BeginGetEvent),则会收到错误代码。

Hr = MFCreateSinkWriterFromMediaSink(pAudioRender, NULL, &pSinkWriter);
pSinkWriter->SetInputMediaType(DecodePCM);
pSinkWriter->BeginWriting(); //HR -> MF_E_MULTIPLE_SUBSCRIBERS

我想使用IMFStreamSink接口的IMFMediaEventGenerator接收事件(MEStreamSinkRequestSample)调用IMFSourceReader::ReadSample方法。

为了让我接收这些事件,我需要了解为什么IMFSinkWriter::BeginWritingIMFStreamSink 获取事件生成器。

【问题讨论】:

【参考方案1】:

在这种情况下,您不应该调用 IMFMediaEventGenerator 方法。

通过使用 Sink Writer API,您可以将 Media Foundation 原语 (SAR) 的管理和独占控制委托给 Sink Writer 实例。它是事件的订阅者,并且只能有一个。

也就是说,如果你想自己处理MEStreamSinkRequestSample,你不能使用Sink Writer API。

MSDN论坛上有类似的问题,例如

Why IMFMediaEventGenerator::GetEvent() always returns MF_E_MULTIPLE_SUBSCRIBERS?

【讨论】:

感谢您回答我。但我有点困惑。那么我将如何使用 IMFStreamSink :: ProcessSample 呢?这个过程只适用于视频,对于音频,我需要 SinkWriter 来处理。我将不得不访问低级 API 来呈现音频,那么在这种情况下是 CoreAudio?但是SAR会怎么做呢?还是我在这里错了,我是否应该创建一个媒体源,无论是否自定义,并使用媒体基础框架中出现的高级 API MediaSession? ProcessSample 只能有一个用户,在您的情况下是 Sink Writer。您不能与另一个更高级别的消费者同时使用媒体/流接收器。如果您对此不满意,则必须停止使用 Sink Writer:管理媒体接收器您自己处理它的操作,在这种情况下,您的部分工作将与样本处理有关,您将根据需要对其进行自定义方式。如果 Sink Writer 拥有媒体接收器,则您不能干预。

以上是关于IMFSinkWriter::BeginWriting 未初始化,因为 IMFMediaEventGenerator 有未决事件的主要内容,如果未能解决你的问题,请参考以下文章