【发布时间】:2018-03-22 13:28:43
【问题描述】:
我正在尝试将 H.264 视频源流式传输到网络浏览器。媒体基础用于编码分段的 MPEG4 流(MFCreateFMPEG4MediaSink 启用了MFTranscodeContainerType_FMPEG4、MF_LOW_LATENCY 和MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS)。然后流通过IMFByteStream 连接到网络服务器。
当 H.264 视频被 <video src=".."/> 标签使用时,它的流式传输工作正常。然而,由此产生的延迟约为 2 秒,这对于相关应用程序来说太长了。我怀疑客户端缓冲会导致大部分延迟。因此,我正在尝试使用媒体源扩展 (MSE) 对浏览器内的流进行编程控制。但是,当通过 MSE 使用相同的 MPEG4 流时,Chrome 会失败并出现以下错误:
解析 MP4 失败:MSE 不允许 TFHD 基础数据偏移。看 https://www.w3.org/TR/mse-byte-stream-format-isobmff/#movie-fragment-relative-addressing
MPEG4 流中 moof/mdat 片段的 mp4dump。这清楚地表明 TFHD 包含“非法”base data offset 参数:
[moof] size=8+200
[mfhd] size=12+4
sequence number = 3
[traf] size=8+176
[tfhd] size=12+16, flags=1
track ID = 1
base data offset = 36690
[trun] size=12+136, version=1, flags=f01
sample count = 8
data offset = 0
[mdat] size=8+1624
我使用的是 Chrome 65.0.3325.181(官方版本)(32 位),在 Win10 版本 1709 (16299.309) 上运行。
是否有任何方法可以使用 Media Foundation 生成与 MSE 兼容的 H.264/MPEG4 视频流?
状态更新:
根据roman-r的建议,我设法通过拦截生成的MPEG4流并执行以下修改自己解决了这个问题:
- 修改Track Fragment Header Box (tfhd):
- 删除
base_data_offset参数(将流大小减少8字节)- 设置
default-base-is-moof标志- 添加缺少的跟踪片段解码时间 (tfdt)(将流大小增加 20 字节)
- 设置
baseMediaDecodeTime参数- 修改Track fragment Run框(trun):
- 调整
data_offset参数
字段描述记录在https://www.iso.org/standard/68960.html(免费下载)中。
切换到基于 MSE 的视频流式传输将延迟从约 2.0 秒减少到 0.7 秒。通过在每次 IMFSinkWriter::WriteSample 调用后调用 IMFSinkWriter::NotifyEndOfSegment,延迟进一步减少到 0-1 帧。
【问题讨论】:
-
我不知道改变行为的方法,但是我过去曾通过对生成的字节流进行后处理和创建备用媒体接收器来解决此问题。尽管这不是您要确切询问的内容,但两条(两者中的任何一条)路径都会导致来自 Media Foundation 管道的 MSE 友好输出。
-
遗憾的是,后处理不是一个选项,因为流式传输的是“实时”视频源。但是,另一种媒体接收器可能值得研究。您能否提供更多详细信息和/或指出一些示例代码的方向?
-
我没有任何可以分享的代码,很抱歉。后处理(是的,我这样做是为了实时低延迟提要)正在拦截字节流,将其解析为原子并重新组合回来。一般来说,这是可行的。自定义媒体接收器是一种直接的开发,它取代了库存接收器。 MF 因样本不多而臭名昭著,但也许您可以找到一些媒体接收器样本作为起点。 Win SDK 7.x 中的 Wavsink 示例可能是一个很好的例子。
标签: mp4 h.264 ms-media-foundation mse