如何在媒体基础中有自定义视频媒体/流接收器请求 RGB32 帧?
Posted
技术标签:
【中文标题】如何在媒体基础中有自定义视频媒体/流接收器请求 RGB32 帧?【英文标题】:How to have custom video media/stream sink request RGB32 frames in media foundation? 【发布时间】:2018-09-06 07:06:15 【问题描述】:我正在尝试为 OpenGL 应用程序中的视频播放制作一个自定义媒体接收器(没有各种 WGL_NV_DX_INTEROP,因为我不确定我的所有目标设备是否都支持这个)。
到目前为止,我所做的是编写一个自定义流接收器,它接受 RGB32 样本并使用媒体会话设置播放,但是我在播放 mp4 文件的初始测试时遇到了问题:
生成的拓扑中的一个(或多个)MFT不断失败,并出现错误代码MF_E_TRANSFORM_NEED_MORE_INPUT,因此我的流接收器从不接收样本 请求了几个样本后,媒体会话收到事件 MF_E_ATTRIBUTENOTFOUND,但我仍然不知道它来自哪里但是,如果我将流接收器配置为接收 NV12 样本,那么一切似乎都可以正常工作。
我的最佳猜测是 TopologyLoader 生成的颜色转换器 MFT 需要更多配置,但考虑到我需要保持整个过程与原始文件类型无关,我不知道该怎么做。
【问题讨论】:
可以提供mp4文件吗?你能解释一下 TopologyLoader 是如何设置的吗? 对各种 mp4 文件有同样的效果。通过将 MediaSource 连接到 MediaSink 来设置拓扑,然后通过默认拓扑加载器进行解析 好的,你能用这个文件测试一下吗:big_buck_bunny_720p_50mb.mp4,所以我也可以测试一下吗? 我开始使用 SourceReader,因此无法再进行测试。但是我仍然有代码,我将在明天或后天测试。感谢您的回复! 【参考方案1】:我制作了一个最小的测试用例,演示了自定义视频渲染器与经典媒体会话的使用。
我使用 big_buck_bunny_720p_50mb.mp4,使用 RGB32 格式没有发现任何问题。
此处的示例代码:https://github.com/mofo7777/*** 在 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;
【讨论】:
嗨,很抱歉回复晚了,但我一直很忙。我一直在快速查看您的代码,并且在逻辑上似乎没有任何区别(我使用的是 C#)。我会尝试用你的作为 bse 重新实现我的 我尝试在 C# 中重现您的示例,但失败了。运行 MFTrace 我得到了我上次得到的确切错误 (MF_E_TRANSFORM_NEED_MORE_INPUT)。存储库可用here 您好,再次感谢您的帮助!我已经实现了你建议的 chagnes(除了示例中的那些,因为我只需要得到一个然后做一些详细说明),我没有任何运气。不幸的是,出于版权原因,我无法将文件发送给您,但我在各种视频上都注意到了同样的问题。我开始认为这可能与我的系统有关。我也没有你的 Big Buck Bunny 视频,你能分享一下吗,我可以用我的系统测试它吗? 很奇怪!使用该视频,它可以正常工作。我会尝试获取有关我要播放的视频的格式和编解码器的更准确信息,然后再与您联系。 我运行了 ffprobe,发现视频编解码器格式有一些非常细微的差异。仍然不知道为什么它可以与 SourceReader 一起正常工作...您可以检查 ffprobe 输出 here以上是关于如何在媒体基础中有自定义视频媒体/流接收器请求 RGB32 帧?的主要内容,如果未能解决你的问题,请参考以下文章
在 Javascript 中监控 WebRTC 视频(媒体)流质量
切换音轨时是不是可以阻止 Chromecast 自定义媒体接收器发出许可请求?