web无插件解码播放H264/H265(js解码HTML5播放)

项目意义:

长久以来,安防领域的网络摄像机(IPC)的WEB视频直播都依赖于浏览器插件,IE浏览器使用ActiveX插件,Chrome和Firefox浏览器使用NPAPI插件。
之所以开发浏览器插件来收流、解码、播放IPC的实时视频,是因为早期HTML的发展过于缓慢,在纯web代码无法实现的情况下开发者只能使用插件来辅助。
此方法的弊端显而易见,比如用户使用不方便,打开web之后需要点击下载并安装插件才可以播放IPC的实时视频,而且很多用户会担心第三方插件的安全性。
原本出于安全考虑,浏览器把web代码的运行限制于沙箱之中,并限制web代码很多本地接口的权限,营造出比较安全的网络环境。
浏览器插件的设计违背了这个初衷,因为插件可以获得和桌面应用程序几乎一样的权限,安装完插件之后打开web时,web代码可以调用插件肆意的读写电脑本地数据。
这几年微软、谷歌、苹果、Mozilla等各大浏览器厂商也意识到了浏览器插件的安全问题,开始在新发布的浏览器中限制第三方插件的使用。
现在Edge、Chrome、Safari、Firefox等浏览器已经不支持NPAPI插件,只剩下IE浏览器还在支持ActiveX插件,导致IPC的web页面只能在IE内核的浏览器播放实时视频。
所以实现web无插件实时播放IPC的H264/H265视频十分重要。

项目描述:

视频传输使用websocket协议,ipc后端推流使用C语言编程,web前端收流使用js语言。
web的视频解码库使用js语言,通过emscripten工具把C语言解码库代码编译成js。
解码后的YUV数据转换为RGB后推到HTML5的canvas播放。

解码器选择:

由于找不到合适的开源js解码器代码,所以选用C语言的解码器,通过emscripten工具把C语言解码库编译成js库。
先后尝试过libde265、openhevc、ffmpeg,最后选择了ffmpeg。ffmpeg源码的下载与api使用参考之前发布的文章。

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

libffmpeg.js的编译

emconfigure ./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-swresample –disable-postproc –disable-avfilter \
–disable-programs –disable-logging –disable-everything –enable-decoder=hevc –enable-decoder=h264 \
–disable-ffplay –disable-ffprobe –disable-ffserver –disable-asm –disable-doc –disable-devices –disable-network \
–disable-hwaccels –disable-parsers –disable-bsfs –disable-debug –disable-protocols –disable-indevs –disable-outdevs
make
make install

export TOTAL_MEMORY=268435456
export EXPORTED_FUNCTIONS=”[ \
‘_avcodec_register_all’, \
‘_avcodec_find_decoder’, \
‘_avcodec_alloc_context3’, \
‘_avcodec_open2’, \
‘_av_free’, \
‘_av_frame_alloc’, \
‘_avcodec_close’, \
‘_avcodec_decode_video2_js’, \
‘_avcodec_get_image_width_js’, \
‘_avcodec_get_image_height_js’, \
‘_avcodec_get_chroma_format_js’, \
‘_avcodec_get_image_plane_js’, \
‘_avcodec_get_image_pitch_js’, \
‘_avcodec_get_image_bit_depth_js’, \
‘_avcodec_close_AVCodecContext_js’, \
‘_avcodec_flush_buffers’
]”
emcc dist/lib/libavcodec.a dist/lib/libavutil.a \
-s OUTLINING_LIMIT=100000 \
-s TOTAL_MEMORY=${TOTAL_MEMORY} \
-s EXPORTED_FUNCTIONS=”${EXPORTED_FUNCTIONS}” \
-O2 \
–pre-js libffmpeg_pre.js \
–post-js libffmpeg_post.js \
-o libffmpeg.js

测试效果:

使用最新的Firefox浏览器
解码H264的1080P分辨率时,延时可以控制在几百毫秒以内,测试的最大分辨率是2592X1944,也比较实时。
解码H265的1080P分辨率时,比较负荷比较大,会有卡顿现象。

还有更高性能的解决方案,使用WebAssembly解码H264/H265,可参考我的另一篇文章:

《web无插件解码播放H264/H265(WebAssembly解码HTML5播放)》

http://blog.csdn.net/Jacob_job/article/details/79436639

《JS如何调用WebAssembly的api》

http://blog.csdn.net/Jacob_job/article/details/79434207