应用系统中设计到网络视频流相关的功能时,经常会有在浏览器端WEB界面实现视频实时预览的需求。
在以前通常有会考虑有四种方案实现:使用开源播放器插件,开发浏览器控件,使用Flash插件配合FLV转码使用,苹果的HLS(HTTP Live Streaming)。
有过经验的朋友相信一定有过痛苦的记忆,插件崩溃,矩阵显示卡顿,分辨率下降等体验欠佳的问题。
HTML5经过10多的发展终于成型,同时各大厂商浏览器也对HTML5进行了大力支持。在这里介绍一种通过浏览器间接或直接获取网络视频流,并使用HTML5 canvas控件进行播放的方法。
使用中间实时视频流转码服务,将远端的RTSP视频流获取,转码为RGB格式,通过websocket将RGB数据发送到浏览器客户端。客户端使用解析RGB数据并显示在HTML5的Canvas控件上进行绘制。
使用的开源及三方工具:ffmpeg,websocketpp,boost1.69,SDL2,Pthread。
开发环境:WINDOWS 10,VSTS 2017。
目标架构:x86_32。
进入目录,双击bootstrap.bat后,打开VS 2017 develop command命令窗口,执行如下编译命令:
bjam address-model=32 architecture=x86 stage --without-python --stagedir="X:\boost\vc141" link=static runtime-link=shared threading=multi debug release
编译成功后会在X:\boost\vc141下生成静态库。
因为比较简单,这里略过。
业务流程
//scale context
pSwsCtx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_RGBA, SWS_BILINEAR, NULL, NULL, NULL);
//to RGBA frame
sws_scale(pSwsCtx, (const uint8_t * const *)avFrame->data,avFrame->linesize,0,pCodecCtx->height, pFrameRGBA->data, pFrameRGBA->linesize);
//rgba data struct
typedef struct rgba_data {
uint8_t* data;
size_t len;
}rgba_data;
//rgba data
rgba_data _rgba_data;
_rgba_data.data = pFrameRGBA->data[0];
_rgba_data.len = av_image_get_buffer_size(AV_PIX_FMT_RGBA, width, height, 1);
//根据canvas 上线问获取图像对象
var imgData = cxt.createImageData(canvas.width, canvas.height);
var pxData = imgData.data;
//ws接收rgba数据
ws.onmessage = function(evt) {
var rgba = new Uint8Array(evt.data);
for(var i = 0; i < canvas.height; i++){
for(var j = 0; j < canvas.width; j++){
var p = canvas.width*i+j;
pxData[4*p+0] = rgba[4*p+0];
pxData[4*p+1] = rgba[4*p+1];
pxData[4*p+2] = rgba[4*p+2];
pxData[4*p+3] = rgba[4*p+3];
}
}
//绘制图像
cxt.putImageData(imgData, 0,0,0,0,canvas.width,canvas.height);
};
效果图,支持多客户端。