摘 要: 針對傳統(tǒng)監(jiān)控系統(tǒng)的不足已不能滿足現代人對監(jiān)控視頻內容的要求,提出了一種解決方案并對其進行闡述,說明如何在Linux系統(tǒng)下,以IP網絡攝像頭為數據源,結合開源Live555庫實現流媒體服務器的方法,其中涉及了視頻數據的獲取、編碼、流化以及傳輸等模塊。流媒體服務器的實現解決了多路客戶訪問攝像頭的負載問題,同時若與圖像處理算法結合可提供特殊的視頻監(jiān)控內容以滿足應用需求。
關鍵詞: RTSP;流媒體服務器;Live555;網絡監(jiān)控
0 引言
隨著圖像處理的發(fā)展,構建一個良好的視頻圖像處理應用平臺越來越重要。目前的攝像頭對多路訪問的負載能力非常有限,并且現在人們對監(jiān)控內容的要求已不僅僅停留在原始視頻上,而大多更希望能夠實時監(jiān)控經過特殊處理的視頻數據。為了滿足這一需求,以IP攝像頭作為數據源,PC端搭建流媒體服務器供多路客戶進行實時監(jiān)控的模式是一個很好的解決方案,這樣既能減少攝像頭負載能力的限制,同時又能滿足圖像處理后的監(jiān)控需求。本文設計的流媒體服務器[1]架設在Linux操作系統(tǒng)的PC上,采用RTSP協(xié)議[2]進行實時傳輸以供客戶訪問。
服務器首先登錄訪問IP攝像頭,匹配通過后IP攝像頭返回捕捉的視頻數據給服務器,當客戶端通過鏈接向服務器發(fā)送訪問請求后,服務器開始向客戶端傳送實時視頻數據,供客戶進行實時監(jiān)控。
1 IPC數據獲取及存儲
網絡攝像機對于人們來說較為重要的是如何獲取其視頻源數據,而海康威視的網絡攝像機為人們提供了二次開發(fā)的接口以方便對IPC的功能應用進行擴展。下面對IPC視頻數據獲取流程進行介紹。
由于在IPC端已經有設定好的賬戶與密碼,因此用戶在訪問此IPC時就需要通過NET_DVR_Login_V30函數來進行注冊:NET_DVR_Login_V30(IP地址,端口,賬號,密碼,&struDeviceInfo),IP攝像頭匹配正確后才有訪問權限。
該流程中,啟動數據流的接收是通過調用NET_DVR_RealPlay_V30來實現的。該函數中有一項參數可用來設置數據回調函數,每當有碼流數據到達時,便會跳轉到這個已設置的數據回調函數中,在數據回調函數中需要對接收到的數據流進行判斷,若為系統(tǒng)頭則進行一些設置,若為碼流數據則可將其存入緩沖區(qū)內。其流程示意圖如圖1所示。
在圖1中,判斷流數據為系統(tǒng)頭時需要進行一些設置,其中就包括了解碼回調函數的設置。解碼回調函數的作用是當碼流數據存入緩沖區(qū)達一幀時會跳轉到該函數中,此時在解碼回調函數內部便可對完整的一幀數據進行操作。
在解碼回調函數內獲取到的是YV12格式幀數據,而由于所選擇的是x264編碼器,其輸入源規(guī)范為YUV格式,因此必須在解碼回調函數內將其轉為YUV格式后才可供x264進行編碼,之后就可以將其儲入緩沖區(qū)內。本次開發(fā)過程中以循環(huán)緩沖區(qū)和鏈表的方式存取數據。
2 圖像編碼模塊
前面提到,H264編碼使用的是x264編碼器,x264提供了一些開發(fā)接口,但仍需進一步封裝,其設計流程如下:
?。?)初始化EncoderInit函數:在其內部設置初始化結構體,調用x264_param_default及x264_encoder_open進行編碼器初始化,并開辟存放編碼前后圖像存儲空間。
?。?)編碼實現Encode_frame函數:將原始YUV420P格式數據傳給x264_encoder_encode函數進行編碼得到nal數組,其后循環(huán)調用x264_nal_encode函數逐一將編碼后nal封裝成NAL單元并寫入輸出緩存區(qū)中,完成一幀圖像數據的編碼。
3 流媒體服務器模塊
服務器結合開源Live555庫進行設計,提供對外實時播放。Live555是一個為流媒體提供解決方案的跨平臺的C++開源項目,它包括了四個基本庫,分別是:UsageEnvironment、BasicUsageEnvironment、Groupsock和LiveMedia[4]。其中LiveMedia庫是最為核心的,它包含了對應各種不同流媒體類型的數據源類Source、數據接收類Sink、會話類Session及RTSPServe等。
TaskScheduler實例是整個程序的任務調度器[5],它通過doEventLoop()方法實現程序的循環(huán)結構,并在循環(huán)中進行任務調度。
3.1 服務器的建立及響應
程序流程如下:
?。?)建立任務調度器
TaskScheduler*scheduler=BasicTaskScheduler::createNew()
(2)建立程序運行環(huán)境
_env=BasicUsageEnvironment::createNew(*scheduler)
?。?)創(chuàng)建RTSP服務器綁定端口號
RTSPServer*rtspServer=RTSPServer::createNew(*_env,9554)
(4)創(chuàng)建服務器媒體對象:創(chuàng)建ServerMediaSession實例。
(5)進入事件循環(huán)
_env->taskScheduler().doEventLoop()
服務器采用的是事件驅動機制,在這個循環(huán)中,doEventLoop()主要負責三件事:監(jiān)聽客戶端請求并進行響應、對事件發(fā)生進行處理、對延時任務進行調度。
RTSP協(xié)議應用于C/S模式,它本身并不傳輸數據,而只負責實現連接、播放、停止等操作,數據的傳輸則交由RTP協(xié)議來進行[6]。服務器與客戶端建立連接時是通過響應客戶端發(fā)送的OPTION、DESCRIBE、SETUP、PLAY、TERADOWN等請求來進行交互連接的[7]。常用的交互方法作用如下:
OPTION:C向S端獲取可提供的交互方法
DESCRIBE:要求得到S端提供的媒體初始化信息(SDP)
SETUP:確定傳輸模式并提醒S端建立會話
PLAY:C向S發(fā)送播放請求
TERADOWN:C向S發(fā)送關閉請求
服務器對客戶端的具體響應情況如下:
?。?)服務器端在收到客戶端發(fā)送的DESCRIBE請求時,相應的處理函數根據流媒體名查找或創(chuàng)建ServerMediaSession,生成SDP信息作為返回響應此請求。
?。?)服務器端收到SETUP請求時,相應處理函數會對SETUP請求的傳輸頭解析,獲取流媒體發(fā)送傳輸參數,將這些參數組裝成響應消息返回給客戶端。期間subsession調用CreatNew()生成Source數據源實例及RTPSink數據接收實例。
?。?)服務器端收到PLAY請求時,RTPSink數據接收實例會開始向Source數據源索取圖像數據,并將索取到的數據打包成RTP包發(fā)送出去。此時,當RTPSink開始索取數據時,就啟動了對一幀圖像數據的流化。
3.2 流化過程
當Sink向Source索取數據時服務器內便啟動了流化,數據由Source流向Sink,最終再發(fā)送出去。但這一過程中經過了多個節(jié)點傳遞才到達Sink端,這是因為最初的Source視頻數據如果直接傳給Sink端,便無法直接進行流式傳輸,因此需要經過中間多個節(jié)點對視頻數據進行“加工”才能滿足流式傳輸的要求。下面是一個示例:
′source1′->′source2′(a filter)->′source3′(a filter)->′sink′
filters接收到數據后也作為后者的source。對于本文H264格式的流媒體來說,圖像數據經各節(jié)點傳遞過程如下:
WebcamFrameSource(自定義節(jié)點)->H264VideoStreamParser->H264VideoStreamFramer->H264FUAFragmenter->H264 VideoRTPSink
WebcamFrameSource中H264編碼的視頻數據傳給H264VideoStreamParser,并由它分解為多個NAL單元,然后經H264VideoStreamFramer處理后由H264FUAFragmenter進行RTP封包,最后H264VideoRTPSink負責形成RTP包頭并發(fā)送數據。
在這個過程中,WebcamFrameSource類是創(chuàng)建的,后面的H264VideoStreamFramer類、H264FUAFragmenter類、H264VideoRTPSink類都是由Live555庫定義好了的,所創(chuàng)建的WebcamFrameSource類負責將前期的YUV幀數據從緩沖區(qū)取出進行H264編碼,然后將編碼好的視頻數據傳給下一個節(jié)點即可。
3.3 服務器內數據獲取與打包發(fā)送
在Live555中MediaSource類是所有Source的基類,對各種流媒體格式類型及編碼的支持都是通過這個類的派生類來實現的,FrameSource派生自MediaSource,并且內部定義了一個虛函數doGetNextFrame(),用來讓其子類實現各自媒體格式的幀獲取。若要自定義Source的來源,則可以通過自定義一個派生自FrameSource的類來實現。前面提到的WebcamFrameSource就是繼承自FrameSource類用來實現數據源獲取的。
doGetNextFrame()是FrameSource的虛函數,Sink實例在向Source實例索取數據時,會重復循環(huán)層層調用doGetNextFrame()來獲取實時數據源,獲取過程就是將前期的YUV幀數據從緩沖區(qū)取出進行H264編碼,并將編碼完成的數據間接地傳遞給Sink的緩沖區(qū),最后再調用FramedSource::afterGetting()函數來通知Sink端作處理。具體流程如圖2所示。
數據獲取后交由PackFrame()等函數進行打包,最后進行發(fā)送。若無數據,則繼續(xù)向Source數據源進行索取,循環(huán)之前的步驟。
4 實驗結果
實驗結果如圖3所示,左側PC為基于Linux的RTSP服務器,負責將IPC拍攝到的視頻實時傳送;右側PC以及手機都作為客戶端,通過RTSP服務器提供的URL進行鏈接,進而實時播放。
5 結論
本文對IPC數據源的獲取方法、編碼流程、服務器內部數據流化及數據源類WebcamFrameSource的設計進行了說明。使用IPC通過路由器將數據傳送至服務器,服務器端進行實時傳送并提供相應的URL鏈接供客戶端使用??蛻舳丝墒褂肰LC等支持RTSP協(xié)議的視頻軟件進行實時監(jiān)控。
參考文獻
[1] 杜嘩.流媒體技術的原理和應用[J].光盤技術,2008(7):9-11.
[2] SCHULZRINNE A, RAO R, Columbia University, et al. RFC2326-Real time streaming protocol(RTSP)[S].1998.
[3] 樊珊.基于RTP的H264視頻傳輸技術的研究[D].濟南:山東大學,2008.
[4] 樊承澤,陳蜀宇,楊新華.基于網絡計算機的流媒體播放器的研究與實現[J].計算機技術與發(fā)展,2010,20(4):195-198.
[5] 茅炎菲,忠東.基于RTSP協(xié)議網絡監(jiān)控系統(tǒng)的研究與實現[J].計算機工程與設計,2011,32(7):2523-2530.
[6] 王彥麗,陳明,陳華,等.基于RTP/RTCP的數字視頻監(jiān)控系統(tǒng)的設計與實現[J].計算機工程與科學,2009,31(3):58-60.
[7] 王路幫.RTSP協(xié)議及其分布式應用框架[J].安徽職業(yè)技術學院學報,2006,5(1):4-6.