問題
應用系統中設計到網絡視頻流相關的功能時,經常會有在瀏覽器端WEB界面實現視頻實時預覽的需求。
在以前通常有會考慮有四種方案實現:使用開源播放器插件,開發瀏覽器控件,使用Flash插件配合FLV轉碼使用,蘋果的HLS(HTTP Live Streaming)。
有過經驗的朋友相信一定有過痛苦的記憶,插件崩潰,矩陣顯示卡頓,分辨率下降等體驗欠佳的問題。
變通的方案
HTML5經過10多的發展終於成型,同時各大廠商瀏覽器也對HTML5進行了大力支持。在這裏介紹一種通過瀏覽器間接或直接獲取網絡視頻流,並使用HTML5 canvas控件進行播放的方法。
使用Canvas間接播放視頻流
使用中間實時視頻流轉碼服務,將遠端的RTSP視頻流獲取,轉碼爲RGB格式,通過websocket將RGB數據發送到瀏覽器客戶端。客戶端使用解析RGB數據並顯示在HTML5的Canvas控件上進行繪製。
實時視頻流轉碼
使用的開源及三方工具:ffmpeg,websocketpp,boost1.69,SDL2,Pthread。
開發環境:WINDOWS 10,VSTS 2017。
目標架構:x86_32。
boost1.69編譯
進入目錄,雙擊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下生成靜態庫。
Pthread編譯
因爲比較簡單,這裏略過。
代碼摘要
視頻流轉RGBA
//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);
H5圖像繪製
//根據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);
};
效果圖,支持多客戶端。