浅析云控平台画面传输的视频流方案

2020 年 11 月 10 日

浅析云控平台画面传输的视频流方案

背景


ARC(高德车机云控平台)是一个基于车载设备业务深度定制的云控平台,通过该平台我们能够实现远程使用不同类型的车载设备。为了让远程使用者像在本地一样使用车载设备,需要将车载设备的画面及时的传回给使用者。因此,画面传输能力是 ARC 平台的一个核心组件。


起初我们采用行业内普遍在用的画面传输开源方案(minicap)。该方案获取到屏幕数据后压缩生成 JPG 图像,逐帧传输到 Web 端进行展示。由于车机性能比手机差很多,压缩图片消耗 CPU 性能大,在部分低端车机设备上压缩图片能消耗 80%左右的 CPU,容易使设备使用出现卡顿。同时图像压缩率不算很高,传输消耗带宽大,在低带宽下造成用户看到的画面过度延迟。


因此,我们需要一个解决方案能够平衡传回的画面质量和车机端的 CPU 资源消耗。本文将小结本次云控平台画面传输的视频流方案。



思路方法



基于图像数据的基本传输链路,为了能够不消耗设备端 CPU 资源,首先想到了图像不进行压缩,先传输到服务端进行处理。但是经过调研,车机的 USB 带宽传输根本无法满足高清图像不压缩进行传输,高清原始数据非常大,基本 1 秒只能传输三帧左右的数据。


另一个思路是采用设备端的硬件编码器减少 CPU 资源的消耗。经过调研 Android 4.1 开始基本都自带了 H264 视频编码器。因此,决定尝试采用视频流的方案,在设备端通过硬件编码器编码成视频流,通过服务端转发到 Web 端进行解码展示。


实现方案



整个实现方案可以分为以下三个部分:


  • 设备端 :负责画面的获取和编码。

  • 服务端 :处理视频流的传输和控制。

  • Web端 :视频流的解码和展示。


画面的获取和编码


图像画面的获取直接采用的是 Android 的 Virtual Display。编码方式有多种实现方法:



由于 Java 方案只能支持 Android 5.0 以上机器, 而目前车载市场 Android 4.x 的占比还比较大,无法忽略。因此只能使用 cpp 的方案,最低可兼容 Android 4.3 版本。


视频流的传输和控制


Web 端最常见的直播方案是 rtmp/hls/flvjs 等。但是这些方案最低都有 1-3s 的延迟。对于一般直播平台没有影响,但是对于有实时交互场景的云控平台,要求达到毫秒级延迟。所以,最终决定采用 H264 裸流通过 Socket 传输的方案,设备端编码 H264 视频流直接传输到 Web 端进行播放。


同时,为了提高使用体验,对视频流的传输增加了弹性控制。通过在服务端加入缓存队列用来监控前端带宽负载情况,根据带宽状况自动调节帧率和码率,优先保证使用者的流畅感。


Web 端展示和解码


Web 端展示使用 media source extensiton(MSE) + fragment mp4 的方案, 把 H264 裸流封装成 fragment mp4 后,通过 MSE api 进行解码播放, 具体实现是参考了开源的 Jmuxer 方案。


丢帧和补帧


默认情况下 Android Virtual Display 产生的最大帧率是 60fps,而我们肉眼 30fps 就能感觉流畅。为了能够节省带宽,我们定义了视频流最大输出帧率是 30fps。在网络带宽较差的情况下,我们还能够降低帧率来最大限度的避免延迟。同时,Android MediaCodec 不支持控制帧率,帧率是由每秒送入的帧数量决定的。因此,我们需要通过实现丢帧来进行帧率控制。


Win7 硬件解码器没有低延迟模式,需要大概 10 帧左右数据才能开始播放,而 VirtualDisplay 是画面有变化才会产生图像帧,因此需要实现补帧来消除解码延迟。



我们通过创建一个 EglSurface 对丢帧补帧进行处理,通过时间间隔控制 eglTexture 绘入 EglSurface 的频度进行丢帧,通过重复绘入最后一帧数据进行补帧。


总结


该方案在 ARC 平台上的使用,在保证传输质量的同时,有效的提升了使用者操作的流畅感。该方案理论上也可以应用于其他类似的云控平台上,如果不需要支持 Android 4.x 设备,采用 Java 层 API 来获取视频流数据,则可以降低开发和适配成本。


本文转载自公众号高德技术(ID:amap_tech)。


原文链接


浅析云控平台画面传输的视频流方案


2020 年 11 月 10 日 14:07902

评论

发布
暂无评论
发现更多内容

CAP原理

幸福小子

分布式 CAP原理

学习总结之分布式数据库

幸福小子

模块分解

wing

极客大学架构师训练营

9 性能优化(三)课后练习

ABS

第十周学习总结

熊桂平

极客大学架构师训练营

架构第十周作业

Geek_Gu

极客大学架构师训练营

架构第十周总结

Geek_Gu

极客大学架构师训练营

第六周作业总结

hunk

极客大学架构师训练营

CAP原理

皮蛋

CAP CAP原理

架构师训练营2期 第六周总结

月下独酌

极客大学架构师训练营

第十周 模块分解作业

钟杰

极客大学架构师训练营

架构师训练营第 10 周课后练习

叶纪想

极客大学架构师训练营

架构师训练营 - week10 - 作业

lucian

极客大学架构师训练营

【架构师训练营 1 期】第十周学习总结

诺乐

git 在未保存,add,commit,push下撤销的方法?收藏后再也不用找了

小松漫步

第十周 模块分解总结

钟杰

极客大学架构师训练营

第十周作业

熊桂平

极客大学架构师训练营

CAP 原理简述

jorden wang

【架构师训练营 1 期】第十周作业

诺乐

架构师训练营第六周作业

xiaomao

10 模块分解课后练习

ABS

第十周作业 (作业二)

Geek_83908e

架构师一期

架构2期-第六周作业(1)

浮生一梦

极客大学架构师训练营 2组 第六周作业

架构师训练营第2期 第六周课后练习

月下独酌

极客大学架构师训练营

与前端训练营的日子 --Week05

SamGe

学习

模块分解-微服务,组件设计原则,领域驱动开发

garlic

极客大学架构师训练营

面试被问Mybatis底层实现:你连这个知识点都说不明白?

小Q

Java 编程 程序员 架构 mybatis

架构师训练营第六周总结:

xiaomao

week6 技术选型(二) 作业和学习总结

杨斌

第 6 周作业

Steven

极客大学架构师训练营

Week_10 总结

golangboy

极客大学架构师训练营

浅析云控平台画面传输的视频流方案-InfoQ