IMFStreamSink::ProcessSample() 未在自定义媒体接收器上调用

IMFStreamSink::ProcessSample() not being called on a custom media sink

我正在尝试实现自定义 Windows Media Foundation 媒体接收器,以便在将通过 MediaCapture::PrepareLowLagRecordToCustomSinkAsync() 使用它的 UWP 应用程序中使用。

但是,我目前 运行 遇到一个问题,即我的 IMFStreamSinkProcessSample() 函数从未被调用,即使我在 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 派生自 IMFMediaGeneratorwinrt::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>
{
    //...
};