1. 程式人生 > >OpenCV攝像頭視訊資料採集與RTSP和RTMP直播

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直播。