OpenCV攝像頭視訊資料採集與RTSP和RTMP直播
最近比較閒,因此研究了一下通過OpenCV採集攝像頭資料,並同時將視訊流資料推送到RTSP和RTMP。
RTSP服務採用的事開源的LIVE555(需要自己修改和實現部分程式碼)。
RTMP服務採用的是開源的CRtmpServer。
具體的實現細節我就不說了,大概的步驟如下:
1. OpenCV採集攝像頭的一幀資料(cvQueryFrame函式)
2. FFmpeg編碼該幀為H264和FLV流資料
3. 推送H264到LIVE555(自己實現),同時通過推送FLV流到CRtmpServer(通過FFmpeg)
因為CRtmpServer和LIVE555都是開源的,網上有很多資料;並且FFmpeg的H264和FLV編碼、H264和FLV流推送這兩個功能之前已經在其他專案總已經實現過,而且OpenCV在網上也有很多關於攝像頭資料採集的資料,因此實現過程並不複雜。
但是在接收RTSP和RTMP流,並播放時總感覺比較卡,特別是RTMP感覺非常明顯。視訊老是在緩衝。
最後發現是OpenCV的cvQueryFrame非常耗時間:
while (pEncoder->m_bRunFlag) { LARGE_INTEGER freq; LARGE_INTEGER start; LARGE_INTEGER end; QueryPerformanceFrequency(&freq); QueryPerformanceCounter(&start); //獲取一幀資料 pFrame = cvQueryFrame(pCapture); QueryPerformanceCounter(&end); //傳送資料給H264編碼器 if (pFrame) { frame.nFrameHeight = pFrame->height; frame.nFrameWidth = pFrame->width; frame.nFrameSize = pFrame->imageSize; frame.nFrameType = AEC_VIDEO_DATA_RGB24; frame.pszFrameData = pFrame->imageData; g_pH264SendFrame(frame); } double fElapsedTime = double(end.QuadPart - start.QuadPart) / double(freq.QuadPart); TRACE("Elapsed time = %f ms\n", fElapsedTime * 1000); }
也就是說fps平均12左右,RTSP還比較流暢,但是RTMP播放一秒後就又開始緩衝。將H264和FLV編碼器的幀率從25降低到8,效果也一樣。
看來後續需要研究其他攝像頭視訊資料採集方案,特此筆記。
後記:
經過查詢資料發現,OpenCV底層採用的是微軟的VFW(Video for Window)。VFW(Video for Windows)是Microsoft推出的關於數字視訊的一個軟體開發包,VFW的核心是AVI檔案標準。AVI(Audio Video Interleave)檔案中的音、視訊資料幀交錯存放。
VFW的主要函式如下:
(1)capCreateCaptureWindow()::建立視訊窗體
(2)capDriverConnect(): 連線驅動
(3)capGetStatus():獲得視訊狀態
(4)capPreviewRate():設定預覽速率
(5)capFileSaveAs():將視訊轉換成AVI檔案
(6)capFileSaveDIB():將視訊轉換成BMP檔案
(7)capGetUserData():獲取使用者定義的資料
(8)capGetVideoFormat(): 獲取視訊格式
(9)capGrabFrame():獲取當前幀
(10)capDlgVideoDisplay():設定顯示的對話方塊
(11)capCaptureSetSetup():設定視訊捕獲
(12)capSetCallbackOnFrame():設定每幀的回撥函式
(13)capSetCallbackOnVideoStream():設定視訊流的回撥函式
(14)capSetCallbackOnWaveStream():設定聲音流的回撥函式
後續將嘗試DirectShow方式驅動攝像頭,實現RTSP和RTMP直播。