如何在媒体基础中让自定义视频媒体/流接收器请求RGB32帧?

时间:2018-09-06 07:06:16

标签: windows opengl rgb mp4 ms-media-foundation

我正在尝试为OpenGL应用程序中的视频播放创建自定义媒体接收器(没有各种WGL_NV_DX_INTEROP,因为我不确定我所有的目标设备是否都支持此功能)。

到目前为止,我所做的是编写一个接受 RGB32 样本的自定义流接收器,并设置了媒体会话的播放,但是我在播放mp4文件的初始测试中遇到了问题:

    生成的拓扑中的
  • 一个(或多个) MFT 不断失败,错误代码为 MF_E_TRANSFORM_NEED_MORE_INPUT ,因此我的流接收器从不接收样本
  • 在请求了一些样本之后,媒体会话收到了事件 MF_E_ATTRIBUTENOTFOUND ,但我仍然不知道它来自哪里

但是,如果我将流接收器配置为接收 NV12 样本,那么一切似乎都可以正常工作。

我的最佳猜测是TopologyLoader生成的色彩转换器MFT需要更多配置,但考虑到我需要使整个过程与原始文件类型保持独立,我不知道该怎么做。

1 个答案:

答案 0 :(得分:2)

我做了一个最小的测试用例,展示了自定义视频渲染器与经典媒体会话的结合使用。

我使用big_buck_bunny_720p_50mb.mp4,使用RGB32格式也看不到任何问题。

此处的示例代码:位于MinimalSinkRenderer下的https://github.com/mofo7777/Stackoverflow

编辑

您的程序与big_buck_bunny_720p_50mb.mp4一起使用时效果很好。我认为您的mp4文件是问题。共享它,如果可以的话。

我刚刚做了一些更改:

您在MESessionEnded上停止,然后在MESessionStopped关闭。

case MediaEventType.MESessionEnded:
    Debug.WriteLine("MediaSession:SesssionEndedEvent");
    hr = mediaSession.Stop();
    break;
case MediaEventType.MESessionClosed:
    Debug.WriteLine("MediaSession:SessionClosedEvent");
    receiveSessionEvent = false;
    break;
case MediaEventType.MESessionStopped:
    Debug.WriteLine("MediaSession:SesssionStoppedEvent");
    hr = mediaSession.Close();
    break;
default:
    Debug.WriteLine("MediaSession:Event: " + eventType);
    break;

添加它以等待声音并检查样本是可以的:

internal HResult ProcessSample(IMFSample s)
{
    //Debug.WriteLine("Received sample!");

    CurrentFrame++;

    if (s != null)
    {
        long llSampleTime = 0;
        HResult hr = s.GetSampleTime(out llSampleTime);

        if (hr == HResult.S_OK && ((CurrentFrame % 50) == 0))
        {
            TimeSpan ts = TimeSpan.FromMilliseconds(llSampleTime / (10000000 / 1000));
            Debug.WriteLine("Frame {0} : {1}", CurrentFrame.ToString(), ts.ToString());
        }

        // Do not call SafeRelease here, it is done by the caller, it is a parameter
        //SafeRelease(s);
    }

    System.Threading.Thread.Sleep(26);

    return HResult.S_OK;
}

public HResult SetPresentationClock(IMFPresentationClock pPresentationClock)

添加

SafeRelease(PresentationClock);

之前

if (pPresentationClock != null)
    PresentationClock = pPresentationClock;