背景:
当下web端流媒体并没有权威的标准方案,在html5之前只能采用flash、vlc等插件方式实现,而此类插件面临跨平台的问题,且出于安全性方面考虑目前各浏览器逐渐放弃对此类插件的支持,html5引入了video标签使浏览器在一定程度上对视频实现原生的支持,但是目前该标签具体支持的媒体类型依赖于浏览器的实现,并且对流媒体的支持只有渐进式下载的hls方式,延迟高。

解决方案:
本方案基本思想是自己一套简单的实时流机制。
流程:
Camera—>gstreamer—>h264—>websocket—>web-javascript(ffmpeg)—>canvas
本方案的关键在于web端js解码h264,利用Emscripten工具把ffmpeg交叉编译为webassemly模块。

具体实现:

1.Websocket server(通过gstreamer实现camera采集并编码h264,通过qt实现websocket服务功能)
Gstreamer 管道:
rkcamsrc device=/dev/video1 ! video/x-raw,format=NV12,width=1920,height=1080, \ framerate=20/1 ! videorate ! mpph264enc ! video/x-h264,stream-format=byte-stream, \ alignment=au ! appsink name=appsink sync=true
QT WebsocketServer:
 QT为支持websocket提供了QWebsocketServer和QWebsocket两个类,其使用方法跟QTcpServer/QTcpSocket完全一致,由server类侦听,并使用连接得到的socket类与客户端通信。
 具体代码见videoStreamer.tar2.ffmpeg编译webassembly:
1. 安装emscripten :
 wget https://s3.amazonaws.com/mozilla-games/emscripten/releases/emsdk-portable.tar.gz tar -xvf emsdk-portable.tar.gz
 cd emsdk-portable./emsdk update
 ./emsdk install latest以下两步每次新进入终端都需要执行:
 ./emsdk activate latest
 source ./emsdk_env.sh可以通过emcc –v查看是否安装成功。
2)下载最新ffmpeg源码,并通过以下方式编译:
 修改configure第5872行 增加以下两行:
 disable gethrtime
 disable sched_getaffinity./configure --cc=“emcc” --cxx=“em++” --ar=“emar” --prefix=$(pwd)/…/dist --enable-cross-compile --target-os=none --arch=x86_32 --cpu=generic 
 –enable-gpl --enable-version3 --disable-avdevice --disable-avformat --disable-postproc --disable-avfilter 
 –disable-programs --disable-everything --enable-decoder=h264 
 –disable-ffplay --disable-ffprobe --disable-doc --disable-devices --disable-network 
 –disable-hwaccels --disable-bsfs --disable-debug --disable-protocols --disable-indevs --disable-outdevs --enable-parser=h264make
 make install另外可以编译一套pc的版本,以便于在pc端做逻辑验证:
 ./configure --prefix=$(pwd)/install --disable-x86asm 
 –enable-gpl --enable-version3 --disable-avdevice --disable-avformat --disable-postproc --disable-avfilter 
 –disable-programs --enable-decoder=hevc --enable-decoder=h264 \make
 make install以上ffmpeg库可参见ffmpeg-4.1.tar,其中包含了分别编译成x86和Emscripten的脚本build_xx.sh
编译并生成wasm模块及胶着代码。
 emcc ffmpegdecoder.c -o ffmpegdecoder.o -I…/dist/include/ -L…/dist/lib -lavcodec -lswscale -lavutil -lswresample -lm -lpthread
 emar rcs libffmpegdecoder.a ffmpegdecoder.o其中ffmpegdecoder.c是为了方便js调用而包装的一个解码接口,接收h264字节数组,返回rgba字节数组
具体文件见web_ffmpeg.tar,其中包括一个ffmepg_test项目,采用与web一致的方案处理websocket+解码逻辑并绘制qt窗口,可用来验证方案逻辑。
补充: 该压缩包内另含ffmpegutils.c文件用于实现从一张大幅rgba图像中切割并缩放任意矩形rgba数据,可编译成单独的webassebly模块。
目录结构及作用说明:
 web_ffmpeg
 –ffmpegdecoder.c ffmpeg针对h264的解码封装,包含了yuv转rgb步骤。
 –ffmpegutils.c 实现rgba的图像切割+缩放功能。
 –build_env.sh 建立emcc环境脚本,需要修改以指定实际的工具路径
 –build_ffmpegdecoder.sh 构建ffmpegdecoder.c及ffmpegutils.c的emcc静态库,需要修改指定实际emcc版本的ffmpeg静态库路径。
 – build_js.sh 使用ffmpegdecoder.c及ffmpegutils.c的静态库构建相应的wasm及辅助js文件,其中可通过修改-s WASM=1为-s WASM=0控制生成纯js文件。
 3.前端
 前端封装一个ffmpeg.js接收html的canvas对象,内部对接websocket接收h264流,调用ffmpeg的webassembly模块实现解码,并把解码结果画在canvas上。另有test_zx.html 演示如果使用该ffmpeg.js
具体文件在web_ffmpeg.tar的static/video、目录下。
附件清单:
 web_ffmpeg.tar
 ffmpeg-4.1.tar
 videoStreamer.tar

方案缺陷:
1.Js软解码h264终究面临性能问题,解码效果与浏览器所在设备性能有直接关系。
2.目前在windows版chrome浏览器发现在vue框架下的两个界面间跳转会有大块内存泄漏风险,在linux版火狐浏览器下暂未发现,但可能由于虚拟机性能原因,在linux版火狐下画面不流畅。(h264流为20帧)。