记录一次前端播放流媒体的调研过程

原创
04/29 14:43
阅读数 64

调查背景:公司目前项目用的方法是接口请求数据流地址,直接在img标签上播放的方法。但是根据业务要求,现在需要改为websorket通信传入RTSP协议或者YUV协议的数据流到前端播放。

调研开始,前期尝试在前端用JS调用C/C++语言编译后的wasm文件,这个没遇到什么困难,正确引入文件后就调用成功了(在前端JS中通过桥接JS文件调用C/C++编辑的wasm文件中的方法得到计算结果):

接着尝试引入WebChimera.js文件,处理RTSP格式的流媒体数据,WebChimera.js使libVLC直接绘制到JS端的原始数组(Uint8Array)中。然后它将这个数组放入一个纹理并在一个画布元素上绘制它在node.js/io.js/Node-Webkit/NW.js/Electron中使用。可以像普通js一样的使用。但是在测试中发现WebChimera.js中用到的技术版本太旧,不支持最新浏览器,也无法直接在前端的js中使用,且需要安装VLC插件等弊端。后面尝试过其他框架,均逃脱不了版本太旧和浏览器不支持的难题。

最后得出结论,RTSP这种协议的流数据在前端播放,没有特别好的解决方法,需要在本机装一个VLC插件,然后依靠插件让RTSP协议流数据在前端播放,但是目前高版本的Chrome浏览器不支持NPAPI插件,就是说46以上版本的Chrome浏览器还是不能播放。

后端得出的结论:

单纯的WebAssembly技术中,没有可以直接调用原生系统so库文件的方法。它适用于有一部分代码是C/C++编写的,通过emscripten来编译成wasm,可以直接在JS虚拟机里(沙箱化运行)或者其它非浏览器环境(比如node)中运行。

于是我们只能放弃RTSP协议,尝试传输YUV协议的数据。

摄像头输出格式为YUV422格式数据流,经后台处理为YUV420格式后传到前端,再转换为RGB格式,然后用webGL绘制出来实现播放。

YUV420转换为RGB格式的转换阵列为:

从网上找的一段代码,目前测试正常,可以显示监控画面:

但是测试中发现板子上的GPU使用量增加到10%左右,前端CPU占用达到60%左右

由于性能消耗太大,要求带宽过高,后台希望将YUV422数据直接传到前端,由前端转为RGB后绘制到界面显示。

因为没有深入理解转换原理,所有传输的数据变成YUV420后,还是用的原来的代码,结果输出的画面如下

测试结果显然是糟糕的,只能隐约看到确实有画面,但完全看不清,但有一点可以看得出来,那就是:虽然前端无法直接播放rtsp和YUV格式的数据,Chrome浏览器也不支持RTSP格式协议的数据流播放,但是实现在前端播放YUV422格式数据的想法是可行的。

=============================================================================

今天又研究了一天,终于在下班前有了突破,首先关于yuv格式的类型,这里要特别介绍一下。

yuv格式有两大类,planar(平面模式)和packed(打包模式)

planar的YUV格式,先连续存储所有像素点的Y,紧接着存储所有像素点的U,随后是所有像素点的V。
packed的YUV格式,每个像素点的Y,U,V是连续交*存储的。

其次根据采样方式的不同,分为yuv420,yuv422,yuv444等多种格式。

YUV 4:4:4采样,每一个Y对应一组UV分量。
YUV 4:2:2采样,每两个Y共用一组UV分量。 
YUV 4:2:0采样,每四个Y共用一组UV分量。

根据采样方式和存储顺序的不同划分出下面所有类型的排列:

yuv420-1(planar)

yuv420-2(planar)

yuv420-3(packed):

yuv420-4(packed):

yuv422-1(planar):

yuv422-2(planar):

yuv422-3(packed):

yuv422-4(packed):

yuv422-5(packed):

yuv422-6(packed):

yuv444-1:

yuv444-2:

以上排列是从网上整理出来的,如有错误,欢迎指出,谢谢!

我们在拿到yuv数据之后,先确定数据的排列方式,然后正确的提取出yuv值,最后转换为rgb格式渲染出来。

画面出来了,但是不知道为啥是黑白的,色彩去哪儿了呢?

只有灰色图像,但没有色彩,应该是UV值的渲染错误,于是我修改了下面这个参数

修改前:

修改后:

终于画面正常了!!!

需要注意的地方:

1. 传入的图像宽高一定要跟监控画面的分辨率保持一致。

2. 必须明确yuv数据的格式和存储方式。

3. Yuv422格式图像中UV分量的高度分布是分辨率的高度,宽度只有一半。

4. Yuv420格式图像中UV分量的宽高分别是分辨率宽高的一半。

以上是我研究是一个过程,本人并不是学图像处理的,只是一个纯粹的前端开发,弄这个一路上跌跌撞撞,有什么错误的地方请大佬指出!

全部代码:https://github.com/jianjiabailu/yuv2rgb_webGL_player

展开阅读全文
打赏
0
0 收藏
分享
加载中
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部