前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >30,000 fps nginx

30,000 fps nginx

作者头像
用户1324186
发布2022-04-11 19:35:41
4750
发布2022-04-11 19:35:41
举报
文章被收录于专栏:媒矿工厂媒矿工厂

来源:Demuxed 2021 主讲人:Tracey Jaquith 内容整理:冯冬辉 服务器端的 MP4 无损精确时间寻址是很难的,大多数时候只能在关键帧之间跳跃。Tracey 最初的想法是,在寻址点之前加快视频帧的播放。这在 2013 年成为 mod_h264_streaming 的早期定制补丁。2021 年,该功能需要迁移到 nginx 的 mp4 模块。Tracey 展示了如何成为 nginx 的第 56 号贡献者和其中有趣的经历。

目录

  • 服务端 MP4 精确切片
  • Hacking
  • Swimming upstream

服务端 MP4 精确切片

服务端 MP4 切片功能在于按需无损地提供视频的小切片。具体实现上,首先解析和重写 mp4 的头信息(moov atom),包括改变表大小,以及更新音视频包的偏移。之后将这些 mp4 片段发送到浏览器。

那么为什么需要服务端 MP4 切片功能呢?对于一小时的 2Mbps 码率的 HD 电视节目,头信息中就有 4MB 的 moov atom。如果只想播放两小时节目的一帧,则需要先下载 8MB 的头信息。而对于两分钟的服务端切片,则只需要 150K 的头信息。

其中关键帧是需要面对的主要问题。在视频的编码中,所有帧分为 I 帧(关键帧),P 帧(单向预测帧),B 帧(双向预测帧)。Tracey 以吃豆人游戏示例说明了这一机制。

视频编码的IPB帧

实际场景中,关键帧大概 3-5 秒出现一次,而典型的关键帧间隔最多有 10 秒,浏览器需要从某个关键帧开始播放视频,这意味着最多可能要等待 9.9 秒才能播放到你想跳转的位置。

Tracey 给出了一个示例,对于这个视频片段,前 3 个关键帧的 PTS 时间分别在 0.00s,6.04s,10.71s。对于 nginx mod_h264_streaming 模块,当请求第 8 秒的视频(?start=8)时,视频却是从 6.04s 的关键帧开始的。对于 nginx mp4 模块,当请求第 8 秒的视频(?start=8)时,视频会画面冻结直到第一个关键帧,而音频却是正常的。

这个示例说明,服务器端的 MP4 无损精确时间寻址是很难的,大多数时候,都是在关键帧间跳转。对此,Tracey 最初的想法是,在关键帧处开始,然后加速播放,直到想要播放的帧。在之后的示例中,多余的前两秒以 30,000fps 的速度播放。

Hacking

为实现这个功能,需要修改一些 STTS 和 STSS moov atom 。Tracey 先介绍了 nginx 与播放插件的开发历史。其中在 2013 年 10 月,Tracey 在 mod_h264_streaming 插件上提交了这一精准播放功能的补丁。对于音频采样,重置到想要的开始时间;对于视频采样,修改不想要的帧的 PTS 时间戳。

在 nginx 2021/5/11 更新后的 7 天,这一功能出现了很多段错误。其中 98% 的段错误都可以通过 mod_h264_streaming 的内存管理解决,但是剩下的却没办法。因此 Tracey 把目光转向了 nginx 的 mp4 模块。

虽然该模块有 3500 行 C 代码,但却很容易理解,Tracey 花了两天时间就搞定了这一补丁,并为自己所在的 archive.org 上线了该补丁。

Swimming upstream

ATOMS 是头信息的子件,它被包裹在更大的 moov atom 里面。其中, STTS 是采样时间,给出了每帧的间隔;STSS 是同步采样,给出了每个关键帧的采样数。还有其他各种元数据属性。

ATOMS 属性

STTS 是一个 8byte 的表,每行记录包括 4Byte 的采样计数和 4Byte 的采样区间。单个 mp4 文件通常是一个只有一行的表,包含 4Byte 的视频中所有帧数,以及 4Byte 的 1001 采样区间大小。这是因为 US TV 标准的 29.97 ps 就是 30,000 的时间刻度除以 1001。

STSS 是关键帧的列表。在切片中,首先从第一个关键帧开始,直到目标帧结束,如果目标帧不是关键帧,则保存之前关键帧的位置。在加速的部分,将需要跳过的 [count] 帧,从 30fps, duration 10001,改为 ~30000fps, duration 1,即在 STTS 表中添加 [count] [1] 的记录。

还有其他需要解决的问题,包括需要使用 hg 做版本控制,以及发送 patchbomb 邮件给开发列表,以讨论是否接受修订。

作者于 2021/6/3 提交了补丁,给 mp4 请求添加了&exact=1 选项。在与开发列表中的贡献者们交流时,收到了更多建议,最终这成为了 nginx mp4 模块中的 mp4_seek_key_frame 开关选项,甚至之后讨论过是否默认开启。

下面几张图详细地解释了这个功能的实现原理。

修改前的包

修改后的包

修改后的包-说明

附上演讲视频:

http://mpvideo.qpic.cn/0bc3yaaamaaarqahdckn7rrfbqgda3aaabqa.f10002.mp4?dis_k=c9c3290ca717179b18be37482afa0bb6&dis_t=1649676908&vid=wxv_2342966900605157377&format_id=10002&support_redirect=0&mmversion=false

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-04-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 媒矿工厂 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 服务端 MP4 精确切片
  • Hacking
  • Swimming upstream
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档