大多数浏览器和
Developer App 均支持流媒体播放。
-
探索使用 VideoToolbox 的低延迟视频编码
支持低延迟编码器已成为视频应用开发过程的重要部分。探究 VideoToolbox 如何支持低延迟 H.264 硬件编码,以最小化端到端延迟,达到新的性能水平,实现极佳的实时通信和高质量的视频播放。
资源
相关视频
WWDC21
WWDC20
-
下载
♪ ♪ 嗨 我是培康 来自视频编码团队 欢迎观看“使用Video Toolbox 进行低延迟视频编码”
低延迟的编码非常重要 对许多视频运用皆是如此 尤其是实时视频的通讯运用程序 在这个视频中 我会介绍 Video Toolbox的一种新编码模式 能达成低延迟的编码效果 这个新模式的目标就是优化 现有编码器管道架构 在实时视频中的处理功能 那么实时视频运用有哪些需求呢?
我们必须尽可能减少端对端延迟 在通讯应用时产生 交谈时才不会有音讯重叠的问题
我们还要强化其兼容性 让视频应用程序 能和更多设备进行通讯 编码器管道化应能有效率地执行 当通话者多于一人时
此程序也要能让视频 呈现其最佳质量
我们需要稳定的机制 来复原因网络中断造成的通讯错误
低延迟视频编码 在我今天所谈的内容 能够优化上述所谈的各个面向 使用这个模式 实时应用程序 能达到更高效能的表现
这部视频中 我会先概述 低延迟视频编码为何 我们就会有基本概念 了解如何在管道架构中降低延迟 接着我会介绍如何使用 VTCompressionSession APIs 来建置管道架构 并用低延迟的模式编码 最后 我会谈谈 在低延迟模式下引入的多项功能 让我先为各位简介 低延迟视频编码为何 画面上是Apple平台的简易流程图 呈现视频编码器的管道化 Video Toolbox将CVImagebuffer 作为输入图像 要求视频解码器 执行压缩算法 如H.264 来缩减原始数据的大小
输出的压缩数据 封装在CMSamplebuffer中 可经由网络传输 以进行视频通讯 从图表中我们可以发现 影响端到端延迟 有两个因素:处理时间 和网络传输时间
要减少传输时间 低延迟模式消除了帧重新排序 遵循一进一出的编码模式 而且 此模式的速率控制器 有更快的调节能力 来因应网络变化 所以网络壅挤造成的延迟 也因此大幅降低 这两大优化功能让我们见识到 与默认模式相比性能大幅提升 低延迟编码 在720p 30fps的视频中 能减少高达100毫秒的延迟 这样的改变对视频会议来说至关重要
随着延迟减少 我们就能将 更有效率的编码器管道架构 提供给实时通讯功能服务 像是视频会议和网络直播
此外 低延迟编码模式固定使用 硬件加速视频编码器 以节省电量 请注意 支持的视频编解码器类型 在此模式为H.264 这项功能将同时支持 iOS及macOS系统
接着 我想谈谈低延迟编码模式 如何在Video Toolbox中使用 我会先回顾VTCompressionSession的 使用方式 接着为大家说明 低延迟编码所需的步骤 使用VTCompressionSession时 首先要用 VTCompressionSessionCreate API 来创建会话
我们可选择性地配置会话 例如目标比特率 在VTSessionSetProperty API完成 假如未提供配置 编码器就会依默认行为运作
创建会话且正确配置之后 我们能通过 VTCompressionSessionEncodeFrame 将CVImagebuffer传递给会话 编码结果 可从会话创建过程中提供的 输出处理程序检索
低延迟编码 在压缩会话中启用很容易 只需在会话创建过程做修改
用以下的代码片段来示范 首先我们需要一个 CFMutableDictionary 以符合编码器规格 编码器规格是用来指定 会话必须使用的特定视频编码器 接着我们要在编码器规格中 设置 EnableLowLatencyRateControl标志
最后 将编码器规格赋予 VTCompressionSessionCreate 压缩会话就会在低延迟模式下运作
配置步骤跟往常相同 例如 以AverageBitRate属性 来设置目标比特率
好的 我们已经介绍Video Toolbox 低延迟模式的基本功能 接下来我想介绍此模式新的功能 进一步协助你 开发实时视频程序 目前我们谈了许多 低延迟模式带来的优点 还有其他的优点 由我接下来介绍的功能就能做到
首先是配置档案的功能 我们在管道架构中增加两项新配置 来强化其兼容性
还有令人振奋的时间可调性功能 这个功能对视频会议非常有用
现在你可以更加精准控制 影像质量 使用最大帧量化参数就可以做到 最后 我们添加长期参考的支持 来改善错误恢复的功能
接着来谈新的配置支持 配置内容定义一组解码器 能支持的编码算法 来和接收方通讯 经编码的比特流应符合 解码器支持的特定配置文件
在Video Toolbox我们支持 一系列的配置文件 例如Baseline Profile Main Profile和High Profile
今天我们为该系列添加两个配置 Constrained Baseline Profile (CBP) 和Constrained High Profile (CHP)
CBP主要用于低成本应用程序 而CHP则有更先进的算法 能获得更好的压缩比 你可以确认解码器功能 来判断该使用哪种配置
如要使用CHP 只需将ProfileLevel的会话属性 设为ContrainedBaseLine_AutoLevel
同样地 可以将配置级别 设置为ContrainedHigh_AutoLevel 来使用CHP
现在 来谈谈时间可调性 我们能通过时间可调性的功能 提升多方视频通话的效率
假设现在有一个 三方视频通话的场景 此模型中 接受器A的带宽较低 为600kbps 而接受器B的带宽较高 为1000kbps
通常发送方需要对两组比特流编码 以符合每个接收端的下行带宽 这可能不是最好的做法
该模型可以有更高效的表现 通过时间可调性 发送方仅需对一组比特流编码 但之后输出时可分为两层
我们来看看这是怎么运作的
画面上是经编码的视频帧序列 每帧都将前一帧 作为预测参考
我们把一半的帧拉到另一层 接着更改参考内容 如此一来 仅有原始图层中的帧被作为预测使用
此原始图层称为基础层 而新建构的图层称为增强层
增强层可作为基础层的补充 来提高帧率
对接受器A可以发送基础层的帧 因为基础层本身已可解码 更重要的是 因为基础层 只有一半的帧 所以数据传输率会很低
而接受器B可以享有更流畅的视频 因为它有足够的带宽 来接收基础层的帧和增强层的帧
我们来看看 使用时间可调性编码的影像画面 接下来播放两个视频 一个来自基础层 另一个则为基础层 加上增强层
基础层本身可以正常播放 但同时我们会注意到 视频不太流畅
播放第二个视频 我们就能立刻看出差异 比起左边的视频 右边的视频有更高的帧率 这是因为同时包含基础层 和增强层
左边视频有50%的输入帧率 并使用60%的目标比特率 这两个视频只需要编码器 一次编码一个比特流 进行多方视频会议时 这个做法将会更加节能
时间可调性的另一个优点 是错误恢复的功能 我们可以看到 因为增强层中的帧 不作为预测使用 所以对于这些帧就没有相依性
意思是假如增强层中一个或多个帧 在网络传输的过程中遗失 其他帧也不会受到影响 这个特性强固了整个会话过程
启用时间可调性的方法 相当直观简单 我们创建一个新的会话属性 在称作BaseLayerFrameRateFraction 的低延迟模式中 将属性设为0.5 意思是只有一半的输入帧 被指派给基础层 而其余的帧被指派 给增强层
你可以从示例缓冲区附件中 检查一下图层信息 对基础层帧 CMSampleAttachmentKey_ IsDependedOnByOthers将为真 否则为假
我们还可以选择为每一层 设置目标比特率 请记得 我们使用会话属性 AverageBitRate来配置目标比特率
目标比特率配置完成后 我们可设置新的 BaseLayerBitRateFraction属性 来控制基础层所需的 目标比特率百分比
如果没有设定这个属性 默认值0.6就会被启用 我们建议基础层比特率分数 应该在0.6到0.8的范围内
现在让我们来看最大帧量化参数 也就是最大帧QP
帧QP用来调节图像质量和数据速率
我们可以使用低帧QP 来产生高质量的图像 这种情况下 图像尺寸会很大
另一方面 我们可以使用高帧QP 来产生低质量 但尺寸较小的图像
在低延迟模式中 编码器会调整帧QP 使用像是图像复杂度 输入帧率、视频动作等因素来调整 以在当前的目标比特率 产出最佳视觉质量 所以我们鼓励 靠着编码器的默认行为 来调整帧QP
但某些客户端 对视频质量有特定要求 我们可控制 编码器能用的最大帧QP
使用最大帧QP时 编码器会选择 小于此限制的帧QP 因此客户端可以对视频质量 进行更精细的调控
值得一提的是 即使设定了最大帧QP 常规控制速率依然有效 如果编码器达到最大帧QP上限 但比特率预算已经用完 编码器就会开始丢弃帧 来保持目标比特率
使用此功能的一个例子 是通过较差的网络传输屏幕内容视频
可以通过牺牲帧率来换取 发送清晰的屏幕内容影像 通过设置最大帧QP即可做到
来看看界面吧 我们可以用新的会话属性 MaxAllowedFrameQP 来传递最大帧QP
请记得 最大帧QP的值 根据标准 必须介于1到51之间
来谈谈我们开发的最后一个 低延迟模式的功能 长期参考帧
长期参考帧 或称LTR 可用于错误恢复 看一下这张图 图中是管道内的 编码器、发送方客户端 以及接收方客户端
假设视频通讯 通过连接不良的网络进行 帧丢失可能会发生 在传输错误的情况中
当接收方客户端侦测到帧丢失 可以请求重新整理帧以重置会话
如果解码器收到请求 通常它会编码一个关键帧 以作为重新整理用途 但关键帧通常相当大
大的关键帧需要更长的时间 才能到达接收器 既然网络条件已经不佳 大的关键帧可能会加剧 网络壅挤的问题
那么 我们能用预测帧 而不是关键帧来重新整理吗? 答案是肯定的 只要有帧确认就可以 来看看这要如何运作
首先 我们选定要求确认的帧 我们称这些帧为长期参考帧或LTR 这是由编码器来决定 当发送方客户端传输LTR帧时 还需要向接收方客户端 请求确认
如果成功接收到LTR帧 需要将确认回传
一但发送方客户端收到确认 并将该信息传给编码器 编码器就会知道 对方收到了哪些LTR帧
再看一次网络不良的情况
当编码器收到重新整理的请求 但因为这次 编码器有一串已确认的LTR 就能够对这些已确认的LTR中 的一个预测帧进行编码
以这种方式编码的帧称作LTR-P
以编码帧的尺寸来说 通常LTR-P比关键帧小得多 因此更容易传输 现在 我们来谈谈LTR的API 请注意 帧确认需要由应用层处理 可以通过RTP控制通讯协议 中的RPSI信息等机制来完成
这里我们只聚焦在 编码器和发送方客户端的沟通过程
启用低延迟编码后 就能通过设置EnableLTR的会话属性 来启用这个功能
LTR帧被编码时 编码器会在示例附件 RequireLTRAcknowledgementToken 发送一个帧令牌
发送方客户端负责通过 AcknowledgedLTRTokens帧属性 将确认的LTR帧报告给编辑器 因为可能一次收到多个确认 我们需要一个数组 来储存这些帧令牌
我们可以随时通过 ForceLTRRefresh帧属性 请求重新整理帧 一旦编码器收到这个请求 一个LTR-P就会被编码 如果没有已确认的LTR可使用 编码器就会产生一个关键帧
好的 我们已经说明了低延迟模式中 新功能的内容 接着来谈谈如何将这些功能搭配运用
举例来说 我们可将时间可调性 和最大帧量化参数 使用在屏幕分享应用程序 时间可调性的功能 可以更高效地产生输出视频 到每个接收端 我们也能降低最大帧QP 以获得更清晰的UI 及屏幕上的文字内容
假如通讯是经由不良的网络 必须使用重新整理帧恢复错误 这时长期参考帧就能派上用场 如果接收端只能解码限制配置文件 我们也能以CBP 或CHP来进行编码
好的 我们在视频中介绍了几个重点 关于Video Toolbox引入 低延迟编码模式的功能
以及如何使用 VTCompressionSession APIs 在低延迟模式中编码视频
除了低延迟的优点 我们还开发了一系列的新功能 以满足实时视频应用程序的需求 有了这些改良功能 希望低延迟模式 能让你的视频应用程序更加出色 谢谢收看 祝你度过愉快的WWDC 2021 [轻快的音乐]
-
-
5:03 - VTCompressionSession creation
CFMutableDictionaryRef encoderSpecification = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, NULL); CFDictionarySetValue(encoderSpecification, kVTVideoEncoderSpecification_EnableLowLatencyRateControl, kCFBooleanTrue) VTCompressionSessionRef compressionSession; OSStatus err = VTCompressionSessionCreate(kCFAllocatorDefault, width, height, kCMVideoCodecType_H264, encoderSpecification, NULL, NULL, outputHandler, NULL, &compressionSession);
-
7:35 - New profiles
// Request CBP VTSessionSetProperty(compressionSession, kVTCompressionPropertyKey_ProfileLevel, kVTProfileLevel_H264_ConstrainedBaseline_AutoLevel); // Request CHP VTSessionSetProperty(compressionSession, kVTCompressionPropertyKey_ProfileLevel, kVTProfileLevel_H264_ConstrainedHigh_AutoLevel);
-
-
正在查找特定内容?在上方输入一个主题,就能直接跳转到相应的精彩内容。
提交你查询的内容时出现错误。请检查互联网连接,然后再试一次。