我正在尝试为 OpenGL 应用程序中的视频播放制作自定义媒体接收器(没有各种 WGL_NV_DX_INTEROP,因为我不确定我的所有目标设备是否都支持此功能)。
到目前为止,我所做的是编写一个自定义流接收器,它接受 RGB32 样本并通过媒体 session 设置播放,但是我在播放 mp4 文件的初始测试中遇到了问题:
- 生成的拓扑中的一个(或多个)MFT不断失败,并出现错误代码MF_E_TRANSFORM_NEED_MORE_INPUT,因此我的流接收器从未收到样本
- 请求一些示例后,媒体 session 收到事件 MF_E_ATTRIBUTENOTFOUND,但我仍然不知道它来自何处
但是,如果我将流接收器配置为接收 NV12 样本,则一切似乎都工作正常。
我最好的猜测是由 TopologyLoader 生成的颜色转换器 MFT 需要更多配置,但考虑到我需要使整个过程独立于原始文件类型,我不知道该怎么做。
最佳答案
我制作了一个最小的测试用例,演示了自定义视频渲染器与经典媒体 session 的使用。
我使用big_buck_bunny_720p_50mb.mp4,并且使用RGB32格式没有发现任何问题。
此处的示例代码:https://github.com/mofo7777/Stackoverflow在 MinimalSinkRenderer 下。
编辑
您的程序与 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;
关于windows - 如何让自定义视频媒体/流接收器在媒体基础中请求 RGB32 帧?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52198300/