IMFStreamSink::ProcessSample() 未在自定义媒体接收器上调用
IMFStreamSink::ProcessSample() not being called on a custom media sink
我正在尝试实现自定义 Windows Media Foundation 媒体接收器,以便在将通过 MediaCapture::PrepareLowLagRecordToCustomSinkAsync()
使用它的 UWP 应用程序中使用。
但是,我目前 运行 遇到一个问题,即我的 IMFStreamSink
的 ProcessSample()
函数从未被调用,即使我在 IMFMediaSink::OnClockStart()
中排队事件.
我已经阅读了此处的文档 (https://docs.microsoft.com/en-us/windows/win32/medfound/media-sinks),还查看了“简单通信”示例。
这是我得到的输出,我已经记录了每个函数调用和我的接收器执行的每个调用的 HRESULT:
MyCaptureMediaSink::SetPresentationClock
OK: Clock->AddClockStateSink(this)
MyCaptureStreamSink::BeginGetEvent
OK: MediaEventQueue->BeginGetEvent(pCallback, punkState)
MyCaptureMediaSink::OnClockStart
MyCaptureStreamSink::QueueEvent
OK: MediaEventQueue->QueueEventParamVar(met, guidExtendedType, hrStatus, pvValue)
OK: Sink->QueueEvent(MEStreamSinkStarted, GUID_NULL, S_OK, nullptr)
MyCaptureStreamSink::QueueEvent
OK: MediaEventQueue->QueueEventParamVar(met, guidExtendedType, hrStatus, pvValue)
OK: Sink->QueueEvent(MEStreamSinkRequestSample, GUID_NULL, S_OK, nullptr)
我认为在最后一行之后我应该看到的是对 MyCaptureStreamSink::EndGetEvent()
的调用,因为收到了 MEStreamSinkStarted
,然后是另一个 BeginGetEvent()
和 EndGetEvent()
对并调用 ProcessSample()
因为下一个事件将是 MEStreamSinkRequestSample
事件。
我是否遗漏了一些我仍然需要调用的函数以便 MediaCapture 系统调用这些函数?
我找到了解决问题的方法:
我在没有使用 winrt::implements
的情况下重新实现了我的流接收器,这似乎按预期工作。我假设(虽然我仍然不是 100% 确定)正在发生的是,由于 IMFStreamSink
派生自 IMFMediaGenerator
,winrt::implemnets
不会正确生成 QueryInterface
基本类型。在我自己的实现中,我需要明确地处理它。
这是旧的 class 声明,它不起作用:
class MyStreamSink : public winrt::implements<MyStreamSink, IMFStreamSink>
{
// ...
};
这是有效的 class:
class MyStreamSink: public IMFStreamSink
{
virtual HRESULT QueryInterface(const IID& riid, void** ppvObject) override
{
if (riid == __uuidof(IMFMediaEventGenerator))
{
*ppvObject = static_cast<IMFMediaEventGenerator*>(this);
}
//...
}
}
更好的方法是覆盖 winrt::is_guid_of。通过这种方法,您将获得一个共享的 v-table 而不是两个单独的 v-table。更多信息:How do I use C++/WinRT to implement a classic COM interface that derives from another classic COM interface
template<>
inline bool winrt::is_guid_of<IMFStreamSink>(guid const& id) noexcept
{
return winrt::is_guid_of<IMFStreamSink, IMFMediaEventGenerator>(id);
}
class MyStreamSink : public winrt::implements<MyStreamSink, IMFStreamSink>
{
//...
};
我正在尝试实现自定义 Windows Media Foundation 媒体接收器,以便在将通过 MediaCapture::PrepareLowLagRecordToCustomSinkAsync()
使用它的 UWP 应用程序中使用。
但是,我目前 运行 遇到一个问题,即我的 IMFStreamSink
的 ProcessSample()
函数从未被调用,即使我在 IMFMediaSink::OnClockStart()
中排队事件.
我已经阅读了此处的文档 (https://docs.microsoft.com/en-us/windows/win32/medfound/media-sinks),还查看了“简单通信”示例。
这是我得到的输出,我已经记录了每个函数调用和我的接收器执行的每个调用的 HRESULT:
MyCaptureMediaSink::SetPresentationClock
OK: Clock->AddClockStateSink(this)
MyCaptureStreamSink::BeginGetEvent
OK: MediaEventQueue->BeginGetEvent(pCallback, punkState)
MyCaptureMediaSink::OnClockStart
MyCaptureStreamSink::QueueEvent
OK: MediaEventQueue->QueueEventParamVar(met, guidExtendedType, hrStatus, pvValue)
OK: Sink->QueueEvent(MEStreamSinkStarted, GUID_NULL, S_OK, nullptr)
MyCaptureStreamSink::QueueEvent
OK: MediaEventQueue->QueueEventParamVar(met, guidExtendedType, hrStatus, pvValue)
OK: Sink->QueueEvent(MEStreamSinkRequestSample, GUID_NULL, S_OK, nullptr)
我认为在最后一行之后我应该看到的是对 MyCaptureStreamSink::EndGetEvent()
的调用,因为收到了 MEStreamSinkStarted
,然后是另一个 BeginGetEvent()
和 EndGetEvent()
对并调用 ProcessSample()
因为下一个事件将是 MEStreamSinkRequestSample
事件。
我是否遗漏了一些我仍然需要调用的函数以便 MediaCapture 系统调用这些函数?
我找到了解决问题的方法:
我在没有使用 winrt::implements
的情况下重新实现了我的流接收器,这似乎按预期工作。我假设(虽然我仍然不是 100% 确定)正在发生的是,由于 IMFStreamSink
派生自 IMFMediaGenerator
,winrt::implemnets
不会正确生成 QueryInterface
基本类型。在我自己的实现中,我需要明确地处理它。
这是旧的 class 声明,它不起作用:
class MyStreamSink : public winrt::implements<MyStreamSink, IMFStreamSink>
{
// ...
};
这是有效的 class:
class MyStreamSink: public IMFStreamSink
{
virtual HRESULT QueryInterface(const IID& riid, void** ppvObject) override
{
if (riid == __uuidof(IMFMediaEventGenerator))
{
*ppvObject = static_cast<IMFMediaEventGenerator*>(this);
}
//...
}
}
更好的方法是覆盖 winrt::is_guid_of。通过这种方法,您将获得一个共享的 v-table 而不是两个单独的 v-table。更多信息:How do I use C++/WinRT to implement a classic COM interface that derives from another classic COM interface
template<>
inline bool winrt::is_guid_of<IMFStreamSink>(guid const& id) noexcept
{
return winrt::is_guid_of<IMFStreamSink, IMFMediaEventGenerator>(id);
}
class MyStreamSink : public winrt::implements<MyStreamSink, IMFStreamSink>
{
//...
};