跟着卷卷龙一起学 Camera-- 低延迟
转载至跟着卷卷龙一起学Camera--低延迟01原文链接 https://xie.infoq.cn/article/93d0ef671a17d0be57bcb65f4延迟的构成目前主流的 camera 大多都遵循以下工作原理使用集成的 MIPI CSI/LVDS 等视频输入接口捕获 CMOS sensor 输出的 RAW 数据这个过程产生的延 迟称为 video capture latency使用集成的 ISP 硬件对 RAW 数据进行流水线处理生成 YUV 图像这个过程产生的延迟称 ISP pipeline latency使用集成的 H.264/265 硬件编码器对 YUV 图像进行编码生成编码码流这个过程产生的延迟称为 video encoding latency步骤 123 的延迟主要取决于芯片硬件性能而三者之间还存在软件调度的延迟硬件延迟和软件 延迟的总和统称为 camera latency使用 RTSP/RTMP/HLS/SIP 等流传输协议将编码码流传送到网络客户端这个过程受网络拥堵和丢包情 况影响较大产生的延迟称为 network latency客户端使用 FFMPEG 等解码软件对收到的码流进行解码得到 YUV 图像这个过程产生的延迟称为 video decoding latency。当客户端需要处理多路码流时每个码流都需要在内存中排队等待 CPU 处理所 以 decoding latency 里还包含了软件调度的延迟。目前较新版本的 FFMPEG 已经默认支持使用 GPU 进行解 码可以显著降低 CPU 占用率、降低 decoding latency客户端使用 OpenGLDirectX 等 3D 加速引擎对 YUV 图像进行 2D 和 3D 处理包括像素格式转换、 图像增强、图形层叠加、PIP 贴图、3D 投影变换、添加场景光源、计算阴影等处理任务这个过程称为渲 染rendering产生的延迟称为 rendering latency渲染之后的图像被保存在显卡上的帧缓存FrameBuffer中显卡的视频控制器Video Controller 会读取帧缓存中的信息经过数模转换后送给显示器进行显示这个过程称为 video display产生的延迟 称为 screen latency。camera latency 是一个系统指标包含了硬件和软件的贡献硬件架构决定了系统能够做到的最小延迟而软件架构也会对延迟产生重 大的影响合理高效的软件设计可以使系统总延迟接近硬件极限而低效的软件设计则会引入不必要的延 迟降低产品性能。延迟的根因 俗话说不怕慢就怕站。Camera 延迟的根本原因就是像素没有时刻跟随硬件时钟的节拍在流转而 是花了很多时间静静地呆在某个地方等待硬件处理。那么事情为什么会是这个样子呢个中原因就一言难 尽了客官需要听我细细道来。先从 ISP 讲起。ISP pipeline 一般是由一个个独立的处理模块组成很多模块都需要使用滤波器对图像进 行滤波典型的滤波窗口尺寸有 3x35x57x79x9更大的还有 17x17 等等。以 5x5 滤波器为例它会要求至少 5 行图像数据全部到齐以后才能开始滤波处理在此之前先到的数据就只能在某个缓存里边静 静地等待不许说话也不许乱动。以典型的 1080p 分辨率为例sensor 输出一行图像需要大约 2000 个 PCLK cycle此处 PCLK 为 sensor 主频则 ISP 需要等待 5 行 sensor 数据的时间引入的延迟约为 10,000 个 PCLK cycle当 PCLK 频率为 76MHz 时绝对延迟时间为 132us。这是 ISP 等待数据到齐的延迟之后就开始了 ISP 内部处理此时需要使用 ISP 主频计算处理延迟不妨命名为 ICLK。根据 ISP pipeline 的复杂度一般 需要几千个 ICLK cycle 之后数据开始流出 ISP这个延迟称为 pipeline 延迟。接下来是 video encoder。以 JPEG 编码器为例JPEG 的核心算法是 8x8 大小的离散余弦变换即 DCT 运算该运算要求至少 8 行图像数据全部到齐以后才能开始处理。类似地H.264 要求 16 行而 H.265 则 要求 64 行。套用前面的公式H.265 缓存 64 行数据需要 128,000 个 PCLK cycle绝对延迟时间约为 1684us。 在这个延迟之后encoder 就可以开始处理数据了此时需要使用 encoder 主频计算处理延迟不妨命名 为 ECLK。根据 encoder 的复杂度一般需要几千个 ECLK cycle 之后编码数据开始流出 encoder。笔者曾经 参与过一个简化版 H.264 encoder 设计该设计中一个像素从开始处理到离开 encoder 只需要 530 个 ECLK cycle每个 ECLK 时值 18ns所以硬件 pipeline 延迟为 9.5us。从以上分析可以知道典型的硬件延迟其实是非常小的ISP 和 encoder 的延迟之和可以做到 2ms 以内 如果只考虑算法 pipeline 本身的延迟则更小与动辄 100ms 以上的端到端延迟相比几乎可以忽略不计。 接下来的问题就很显然了剩下的这么多延迟都是怎么来的呢其实问题的根因很简单就四个字“离线 模式”。离线与在线模式所谓离线模式就是说从 CMOS sensor 捕获到的数据不是立即马上 right away 送给 ISP 去处理而是先 输出到内存中的帧缓存frame buffer中等到一帧完整的数据捕获完毕后 ISP 才择机开始处理。以 30fps 帧率为例等到一帧图像捕获完成后图像的第一个像素数据已经在内存中白白等待接近 30ms 的时间了。 在此基础上“择机”二字的具体含义是ISP 其实不一定什么时候才能开始处理有的时候可能要再等上一 两帧之后 ISP 才有空等 ISP 终于有空的时候它读取的图像可能已经是两三帧之前的历史图像了仍以 30fps 帧率为例这就意味着刚才那个像素已经等了 60ms 以上。在 camera 系统中这种由 buffer 缓冲引 起的延迟是最主要的延迟来源。 那么 ISP 为什么会这么忙以至于要等一两帧之后才有机会处理 sensor 图像呢显然这样设计是故 意的并且有着非常合理的原因。按照当前的主流 IP 的技术水平ISP 和 video encoder 的主频很容易做到 800MHz有些芯片甚至可以做到 1GHz 以上。前面提到过 CMOS sensor 在输出 1080p30fps 时典型主频 在 76MHz 左右所以 IP 的实际处理能力是 sensor 输出能力的 10 倍以上。这么强大的处理能力如果只为 一个 sensor 服务显然是太奢侈了所以现实情况是一个 ISP 最少需要同时支持两个 sensor有些产品则需 要支持 4 个甚至 8 个 sensor。比如笔者手里价格高达 1000 余元的红米 Note8 手机就装有 5 个摄像头同 时 ISP 还有惊人的图像处理能力。显然ISP 需要以分时复用的方式一个个处理来自各个 sensor 的图像 这就需要软件逻辑介入对多个 sensor 的处理任务进行合理的调度。如果软件设计的不尽合理或者 CPU 处理能力不够当所有 sensor 一起跑实时流时就很容易出现某些 sensor 处理不及时的情况。看到这里很多观众可以长出一口气了原来 camera latency 的主要原因在于离线模式。如果我的产品没 有支持多 sensor 的需求那是不是就可以让 ISP 专心处理一个 sensor 的图像就可以做到更好的实时性了。 Bingo! 当一个 ISP 只需要支持一个 sensor 时sensor 出来的数据不需要经过 DDR 排队的过程而是通过 一个专用的硬件通路VIP Path直接送给 ISP 进行处理这种工作方式叫做在线模式。前面已经计算过ISP 等待 5 行数据到达引入的延迟约为 10,000 个 PCLK cycle而内部处理的延迟一般 不超过 5000 个 ICLK为计算方便不妨假设 ICLK 频率是 PCLK 的 5 倍则 ISP 处理的总延迟约为 11000 个 PCLK折合绝对时间约为 145us。这里需要注意的是由于在线模式 ISP 只能为一个 sensor 服务所以它并不需要满负荷工作。如果 ISP 系统的硬件设计支持动态调整时钟频率则应该把 ISP 的主频调低到 100MHz 以下与 sensor 主频适配 此时既能满足业务处理的要求也能降低硬件功耗。对于电池供电的产品来说这个特性是至关重要。低延迟 Encoder 常规的 video encoder IP 都是以帧为单位进行编码的典型的流畅是从 ISP 出来的一帧 YUV 图像先进 入内存队列排队encoder 空闲时会从队列中取出一帧进行编码。H.264 标准支持对图像进行分片slice 每个 slice 包含一定数量的宏块macroblock多个 slice 构成一帧。尽管有些 encoder IP 支持以 slice 为 单位输出编码码流但实践中多数产品还是以帧为单位输出编码码流这时一帧就是一个 slice。在对 encoder 进行低延时设计时使用 slice 并不是一个终极解决方案因为 slice 机制的主要设计意图 并不是支持低延迟而是控制码流错误的传播范围在一个 slice 中发生的误码不可能传播到其它 slice 中 去。在实践中很多 encoder IP 只支持 1 个 slice也有些 IP 支持最多 4 个 slice对于 1080p 图像平均 每个 slice 包含 270 行像素。在前文中我们已经分析过H.264 只需要缓冲 16 行数据就可以开始编码了 如果每隔 270 行输出一次虽然离硬件极限接近了一些但总是感觉还不够好。显然最理想的 encoder 设计是以 16 行为单位进行编码每完成 16 行就输出一次这样的输出效率 就最大限度地逼近了硬件极限可以实现很低的延迟了。可能有热心观众会问这个方案虽然挺好了但还能再继续压缩码其实也不是完全不可能因为 H.264 标准还支持 8x8、4x4 等宏块如果我们决定牺牲一点编码效率固定使用 8x8 这一种编码形式则延迟还 有可能进一步压缩。如果让市场部门负责给这个技术起个名字保不齐会就会出现“零延迟编码”这类存在 夸大嫌疑的广告语。到目前位置我们理想中的梦幻 encoder 已经能够以 16 行为单位输出编码码流了所以接下来的任务 就是用最快的速度把这些比特流送到网络上去。我看到有些热心观众已经开始跃跃欲试地举手了它们一 定是想说先把这些数据送到内存里然后 encoder 给 CPU 一个中断CPU 立刻使用 socket 把数据传出 去这样延迟就很低了。对于持有这些想法的热心观众我只能说其实想象力很重要不要被思维定势画地为牢了。在一个真 正的低延迟 camera 里我们其实不需要 socket 这类技术因为该技术会涉及多次内存拷贝效率还不够 高。我们的终极做法是在 encoder 后面设计一个硬件 DMA当 encoder 的输出攒够一定数量时比如 1460 个字节DMA 直接把比特流写入网卡芯片内置缓冲区的 data payload 位置然后 CPU 介入给 payload 补齐 54 个字节的 header这就构成了一个完整的网络数据包这笔数据就 ready to go 了。 根据以太网协议CPU 需要填补的 packet header 包含 14 个字节的 Datalink header、20 个字节的 IP Header、20 个字节的 TCP Header。需要补充的是上述方案是以 TCP 协议为码流载体的由于没有使用标准的 socket 服务方案的设计 者需要自行解决 TCP 协议栈的问题这多多少少还是有些技术难度的对于已经聪明绝顶的工程师来说 可能还要再牺牲几根头发。实际上在低延迟应用中更多场合会倾向于使用简单快捷的 UDP 协议工程师 能够保住头发客户也非常满意。总结 通过本文的分析我们知道了camera latency 的主要来源不是硬件处理而是因为各种原因导致的等待 软件或或硬件出于算法和调度的需要必须先将像素数据凑齐成一个基本单位才能启动处理。如果这个单 位是帧则会引入非常显著的延迟所以理想的低延迟方案需要摒弃以帧为单位对像素数据进行处理而 是尽可能以行为单位只要积累的像素行数满足了硬件的最低要求就立刻开始硬件处理。如果每个处理 环节都遵循这样的原则就一定能够得到性能接近硬件极限的低延迟 camera 方案。