MFCreateFMPEG4MediaSink不生成与MSE兼容的MP4

问题描述 投票:2回答:3

我正在尝试将H.264视频源流式传输到网络浏览器。 Media Foundation用于编码碎片化的MPEG4流(MFCreateFMPEG4MediaSink启用了MFTranscodeContainerType_FMPEG4MF_LOW_LATENCYMF_READWRITE_ENABLE_HARDWARE_TRANSFORMS)。然后通过IMFByteStream将流连接到Web服务器。

当H.264视频被<video src=".."/>标签使用时,它的流媒体工作正常。但是,产生的延迟约为2秒,这对于所讨论的应用来说太多了。我怀疑客户端缓冲会导致大部分延迟。因此,我正在尝试使用Media Source Extensions(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参数(将流大小减少8bytes) 设置default-base-is-moof标志
  • 添加缺少的轨道片段解码时间(tfdt)(将流大小增加20字节) 设置baseMediaDecodeTime参数
  • 修改轨道片段运行框(trun): 调整data_offset参数

字段描述记录在https://www.iso.org/standard/68960.html(免费下载)中。

切换到基于MSE的视频流将延迟从大约2.0降低到0.7秒。不幸的是,这对我的需求来说仍然太多了。剩余延迟的主要来源似乎是由每个MP4片段中8个帧/样本的捆绑引起的。我不知道如何解决这个问题。

https://github.com/forderud/AppWebStream上有一个示例实现

mp4 h.264 ms-media-foundation mse
3个回答
1
投票

提到的0.7秒延迟(在您的状态更新中)是由Media Foundation的MFTranscodeContainerType_FMPEG4封装器引起的,该封装器在一个MP4 moof / mdat盒对中收集和输出每个大约1/3秒(来自未知原因)的帧。这意味着您需要等待19帧才能从MFTranscodeContainerType_FMPEG4以60 FPS获得任何输出。

要为每帧输出单个MP4 moof / mdat,只需说谎MF_MT_FRAME_RATE为1 FPS(或高于1/3秒的任何值)。要以正确的速度播放视频,请使用Media Source Extensions的<video>.playbackRate,或者在MP4流拦截器中更新timescalemvhd框的mdhd(即乘以实际FPS),以获得正确定时的MP4流。

这样做,延迟可以缩短到20毫秒以下。当您在localhost上看到输出并排在Unity(研究) - > NvEnc - > MFTranscodeContainerType_FMPEG4 - > WebSocket - > Chrome Media Source Extensions显示时,几乎无法识别。

请注意,MFTranscodeContainerType_FMPEG4仍然会引入1帧延迟(第1帧输入,无输出,第2帧输入,第1帧输出,......),因此60 FPS时的20 ms延迟。对此的唯一解决方案似乎是编写自己的FMPEG4容器。但这比拦截媒体基金会的MP4流程要复杂得多。


0
投票

通过遵循roman-r的建议并修改生成的MPEG4流来解决问题。见上面的答案。


0
投票

另一种方法是再次使用@Fredrik提到的相同代码但我编写自己的IMFByteStream并检查写入IMFByteStream的块。 FFMpeg几乎每次写入一次原子。所以你可以检查原子名称并进行修改。这是一回事。我希望有一个符合MSE标准的Windows沉降片。

有没有可以为HLS生成.ts文件的?

© www.soinside.com 2019 - 2024. All rights reserved.