王超 王昊京
(中國(guó)科學(xué)院長(zhǎng)春光學(xué)精密機(jī)械與物理研究所 吉林省長(zhǎng)春市 130033)
在傳統(tǒng)的望遠(yuǎn)鏡觀測(cè)系統(tǒng)中,圖像數(shù)據(jù)通過JPEG 格式進(jìn)行傳送。由于壓縮技術(shù)的限制,圖像的壓縮比例低,占用的存儲(chǔ)空間和帶寬都比較大。隨著望遠(yuǎn)鏡觀測(cè)系統(tǒng)獲取圖像數(shù)量的增加和實(shí)時(shí)性傳輸需求的增強(qiáng),使用JPEG 壓縮技術(shù)已經(jīng)無(wú)法滿足系統(tǒng)需求,因此將流媒體實(shí)時(shí)傳輸技術(shù)應(yīng)用到望遠(yuǎn)鏡的圖像傳輸系統(tǒng)中具有很好的實(shí)用性。
本文設(shè)計(jì)了一種用于實(shí)時(shí)觀測(cè)相機(jī)圖像的流媒體數(shù)據(jù)傳輸系統(tǒng)。系統(tǒng)利用OpenCV 進(jìn)行視頻采集,將采集到的數(shù)據(jù)進(jìn)行Н.264壓縮編碼,最后將編碼數(shù)據(jù)通過RTSP 服務(wù)器進(jìn)行實(shí)時(shí)流媒體推送。
實(shí)時(shí)流媒體協(xié)議RTSP(real time stream protocol)是一種應(yīng)用廣泛的實(shí)時(shí)流媒體傳輸協(xié)議,主要負(fù)責(zé)處理服務(wù)器和客戶端之間的數(shù)據(jù)通信,能夠建立和控制媒體的時(shí)間同步流。RTSP 協(xié)議主要由兩部分構(gòu)成,分別是RTP和RTCP。其中RTP協(xié)議用來(lái)傳輸媒體數(shù)據(jù),RTCP 則是負(fù)責(zé)在RTP 傳輸過程中提供傳輸控制信息[1]。RTSP 協(xié)議本身不具有流媒體推送的能力,主要依靠其中的RTP 和RTCP 來(lái)進(jìn)行數(shù)據(jù)的傳輸。在網(wǎng)絡(luò)結(jié)構(gòu)中,RTSP 屬于應(yīng)用層協(xié)議,需要相應(yīng)的鏈路層協(xié)議配合才能進(jìn)行數(shù)據(jù)的推送。
Н.264 編碼技術(shù)是一種高效視頻壓縮編碼技術(shù),能夠支持流媒體數(shù)據(jù)進(jìn)行分組傳輸[2]。Н.264 技術(shù)具有較高的編碼壓縮率,在相同帶寬下,用其進(jìn)行壓縮編碼能夠傳輸更多的數(shù)據(jù)。同時(shí)Н.264 技術(shù)具有較強(qiáng)的抗干擾性,能夠適應(yīng)不同的網(wǎng)絡(luò)環(huán)境,常用于數(shù)據(jù)流的傳輸過程,尤為適合圖像的傳輸。經(jīng)壓縮編碼后,圖像的幀結(jié)構(gòu)由NALU 組成。每個(gè)NALU 中都分為兩部分,一部分是NAL 頭文件信息,用以儲(chǔ)存數(shù)據(jù)傳輸?shù)南嚓P(guān)信息。另一部分是原始圖像編碼后的數(shù)據(jù)信息。
流媒體實(shí)時(shí)傳輸系統(tǒng)采用客戶端-服務(wù)器工作模式。系統(tǒng)中的Н.264 編碼模塊選用FFmpeg 中的Н.264 編碼庫(kù)。網(wǎng)絡(luò)傳輸協(xié)議選用TCP 協(xié)議。流媒體傳輸系統(tǒng)的整體結(jié)構(gòu)如圖1 所示,主要包括三部分:視頻采集編碼模塊、流媒體服務(wù)器模塊和流媒體客戶端模塊。
前端模塊主要負(fù)責(zé)圖像的獲取和處理,在功能上分為兩部分,分別是圖像采集和Н.264 編碼器。兩部分各占用一個(gè)線程單獨(dú)進(jìn)行處理,這樣可以保證在獲得圖像信息后,能夠?qū)崟r(shí)的進(jìn)行Н.264 編碼。圖像獲取過程使用OpenCV 對(duì)相機(jī)的原始圖像信息進(jìn)行采集,采集到的每一幀圖像都會(huì)被轉(zhuǎn)存為cv::Mat 格式,便于接下來(lái)編碼器的編碼操作。幀數(shù)據(jù)在進(jìn)入編碼器之前會(huì)經(jīng)過數(shù)據(jù)格式轉(zhuǎn)換,該過程將每一幀的圖像信息提取出來(lái),通過色度空間轉(zhuǎn)換轉(zhuǎn)變?yōu)閅UV420 格式,之后再進(jìn)入編碼器進(jìn)行Н.264 編碼。編碼器通過調(diào)用編碼函數(shù),對(duì)圖像進(jìn)行壓縮編碼,然后將數(shù)據(jù)存儲(chǔ)到內(nèi)存中等待RTSP 服務(wù)器調(diào)用。
圖1:流媒體傳輸系統(tǒng)整體架構(gòu)
RTSP 服務(wù)器通過指針調(diào)用內(nèi)存中的編碼數(shù)據(jù)。在接收到數(shù)據(jù)后,RTSP 服務(wù)器首先對(duì)數(shù)據(jù)格式進(jìn)行判別處理,然后將Н.264 數(shù)據(jù)進(jìn)行轉(zhuǎn)換操作,再將圖像數(shù)據(jù)封裝成RTP 數(shù)據(jù)包、將控制信息封裝成RTCP 協(xié)議支持的數(shù)據(jù)包,最后使用RTSP 服務(wù)器對(duì)外推流。
如圖2 所示為RTSP 客戶端和服務(wù)器的交互過程??蛻舳耸紫认蚍?wù)器發(fā)送Options 請(qǐng)求報(bào)文,等待服務(wù)器響應(yīng)。待服務(wù)器對(duì)此進(jìn)行響應(yīng)后,客戶端會(huì)向服務(wù)器端發(fā)送Describe 請(qǐng)求報(bào)文、Setup請(qǐng)求報(bào)文,服務(wù)器通過接收這些報(bào)文,逐步建立與客戶端的連接[3]。在客戶端與服務(wù)器建立連接的過程中,客戶端會(huì)向服務(wù)器端發(fā)送Play 請(qǐng)求,即請(qǐng)求服務(wù)器進(jìn)行RTSP 數(shù)據(jù)推送。在對(duì)該請(qǐng)求進(jìn)行響應(yīng)后,RTSP 服務(wù)器便會(huì)進(jìn)行RTP 和RTCP 的推送。推送完成后,客戶端和服務(wù)器通過Turndown 報(bào)文結(jié)束連接[4]。
為了保障數(shù)據(jù)傳輸?shù)目煽啃?,本系統(tǒng)在數(shù)據(jù)鏈路層使用TCP協(xié)議進(jìn)行數(shù)據(jù)發(fā)送??蛻舳撕头?wù)器在SETUP 過程中確定了使用TCP 協(xié)議進(jìn)行后續(xù)的RTSP 數(shù)據(jù)推送工作。當(dāng)流媒體數(shù)據(jù)進(jìn)行傳輸時(shí),服務(wù)器不會(huì)構(gòu)建新的TCP 連接,而是直接使用此前通信過程中的TCP 通道。服務(wù)器會(huì)對(duì)RTP 數(shù)據(jù)包進(jìn)行封裝處理,在原RTP包的基礎(chǔ)上添加辨識(shí)符、通道號(hào)和RTP 包的大小等信息,然后經(jīng)由TCP 通道發(fā)送給客戶端,發(fā)送示意圖詳見圖3。
本系統(tǒng)的編碼器主要以FFmpeg 中提供的libx264 為基礎(chǔ)進(jìn)行圖像信息的Н.264 壓縮編碼。前端視頻采集裝置在獲得圖像信息后,經(jīng)過色度空間轉(zhuǎn)換,再通過指針傳入到Н.264 編碼器中。Н.264 編碼器對(duì)接收到的圖像數(shù)據(jù)進(jìn)行判別和預(yù)處理,并將圖像數(shù)據(jù)存儲(chǔ)在AVFrame 結(jié)構(gòu)體中,然后通過調(diào)用avcodec_encode_video()函數(shù)進(jìn)行Н.264 編碼[5]。編碼后的數(shù)據(jù)存放在AVPacket 結(jié)構(gòu)中,待RTSP服務(wù)器進(jìn)行推送。
RTSP 服務(wù)器是流媒體實(shí)時(shí)傳輸系統(tǒng)的核心部分,其主要職能是對(duì)圖像數(shù)據(jù)進(jìn)行RTSP 封裝處理及推流。RTSP 服務(wù)器的主要功能為客戶端和服務(wù)器之間的通信、構(gòu)建流媒體數(shù)據(jù)、發(fā)送RTSP 流媒體數(shù)據(jù)。RTSP 服務(wù)器的基本設(shè)計(jì)流程如圖4 所示。
RTSP 服務(wù)器在運(yùn)行時(shí),首先會(huì)監(jiān)聽當(dāng)前狀態(tài)下的TCP 連接情況,當(dāng)監(jiān)聽到來(lái)自客戶端的連接請(qǐng)求時(shí),服務(wù)器會(huì)建立新的socket,并綁定相應(yīng)端口號(hào)。然后服務(wù)器進(jìn)入RTSP 的事件循環(huán)中,待接收到客戶端發(fā)送的connection 信息后,與客戶端進(jìn)行連接[6]。
在等待連接的同時(shí),RTSP 服務(wù)器會(huì)開辟新的線程來(lái)構(gòu)建流媒體傳輸數(shù)據(jù)。RTSP 服務(wù)器在接收到來(lái)自編碼器的數(shù)據(jù)后,自身會(huì)構(gòu)造一個(gè)AVFrame 類型的幀結(jié)構(gòu),用來(lái)進(jìn)行后續(xù)的流媒體推送。該幀結(jié)構(gòu)主要包括圖像編碼數(shù)據(jù)、編碼器的頭文件信息、P 幀、I 幀、時(shí)間戳等。
在與客戶端連接成功后,RTSP 服務(wù)器通過解析接收到的信息,獲取流媒體ID,建立流媒體會(huì)話,通過會(huì)話傳遞流媒體數(shù)據(jù)。在會(huì)話建立后,系統(tǒng)會(huì)創(chuàng)建數(shù)據(jù)推送地址,建立TCP 連接,并構(gòu)建動(dòng)態(tài)監(jiān)聽器,監(jiān)聽來(lái)自客戶端的返回值。若返回值正確,便開始進(jìn)行圖像數(shù)據(jù)的RTSP 推送。待推送結(jié)束后,服務(wù)器關(guān)閉RTSP 數(shù)據(jù)推送,移除流媒體會(huì)話。
實(shí)時(shí)性對(duì)于望遠(yuǎn)鏡流媒體傳輸系統(tǒng)來(lái)說至關(guān)重要,其主要體現(xiàn)在編碼和推送兩方面。本系統(tǒng)通過使用多線程、環(huán)形緩存和時(shí)間同步等技術(shù),使前端模塊和RTSP 服務(wù)器模塊的實(shí)時(shí)性都得到了提升,以達(dá)到減少傳輸時(shí)延的目的。
開源編碼庫(kù)中的Н.264 編碼程序是基于視頻文件進(jìn)行編碼,這種編碼方式只能對(duì)內(nèi)存中已有的圖像信息進(jìn)行壓縮編碼,無(wú)法對(duì)從相機(jī)處實(shí)時(shí)獲取的原始數(shù)據(jù)進(jìn)行軟編碼?;谶@種情況,我們改進(jìn)了Н.264 編碼器數(shù)據(jù)輸入部分的程序結(jié)構(gòu),以適應(yīng)系統(tǒng)實(shí)時(shí)性的需求。
通過對(duì)Parse 函數(shù)的內(nèi)部結(jié)構(gòu)進(jìn)行修改,使其不再將讀取文件信息作為獲取待編碼數(shù)據(jù)的來(lái)源,而是通過直接讀取系統(tǒng)內(nèi)存中的數(shù)據(jù)流進(jìn)行編碼。相機(jī)將采集的圖像信息直接存儲(chǔ)在共享內(nèi)存中,Н.264 編碼器會(huì)從共享內(nèi)存中逐幀讀取數(shù)據(jù),將內(nèi)存中的數(shù)據(jù)進(jìn)行壓縮編碼,并在每一幀圖像的編碼數(shù)據(jù)前添加相應(yīng)的關(guān)鍵幀、SPS和PPS 等前綴[7],使得編碼后的數(shù)據(jù)流具備完整的Н.264 格式。
為使系統(tǒng)在編碼后能夠直接進(jìn)行RTSP 推流,編碼器對(duì)輸出的數(shù)據(jù)不再保存成Н.264 的文件格式,而是直接將其存儲(chǔ)在緩存中。RTSP 服務(wù)器從該緩存中讀取編碼信息后,直接進(jìn)行下一步的推流操作。這樣不僅能減少處理過程的時(shí)延,還可以節(jié)約內(nèi)存空間,減少系統(tǒng)產(chǎn)生不必要的輸出。
本系統(tǒng)設(shè)計(jì)并實(shí)現(xiàn)了一個(gè)RTSP 類,用來(lái)完成從初始化參數(shù)配置到數(shù)據(jù)實(shí)時(shí)推送的完整過程。RTSP 推送類主要包括Н.264 數(shù)據(jù)調(diào)用、RTSP 服務(wù)器構(gòu)建和圖像推送等操作。通過構(gòu)建RTSP 對(duì)象,進(jìn)而建立一個(gè)完整的RTSP 實(shí)時(shí)推流過程。
RTSP 推流過程依靠多線程處理來(lái)實(shí)現(xiàn)實(shí)時(shí)性推送。主線程中構(gòu)建了一個(gè)RTSP 對(duì)象,用于初始化RTSP 推送類、Н.264 編碼器函數(shù)、推送函數(shù)、圖像參數(shù)以及存儲(chǔ)空間。推送函數(shù)中定義了一個(gè)子線程,用來(lái)進(jìn)行數(shù)據(jù)的處理和推送。主線程中打開RTSPServer函數(shù),完成服務(wù)器的構(gòu)建。然后主線程進(jìn)入獲取圖像數(shù)據(jù)的循環(huán)中,不斷的將獲取到的圖像數(shù)據(jù)存放到推送類的指針成員中。最后主線程中加入推送對(duì)象的停止和退出操作。這樣便完成了主線程中實(shí)時(shí)推送環(huán)境的搭建。
圖2:RTSP 服務(wù)器與客戶端之間的通信過程
圖3:基于TCP 協(xié)議的RTSP 數(shù)據(jù)推流
在推送函數(shù)中定義的子線程主要負(fù)責(zé)構(gòu)造RTSP 推送的數(shù)據(jù)。子線程調(diào)用主線程中前端相機(jī)獲取的原始圖像數(shù)據(jù),將圖像數(shù)據(jù)轉(zhuǎn)換成YUV420 格式,并進(jìn)行Н.264 編碼。再將編碼后的數(shù)據(jù)通過主線程中的RTSP 服務(wù)器進(jìn)行推送,使用TCP 協(xié)議傳輸?shù)娇蛻舳恕?/p>
圖4:RTSP 服務(wù)器的基本設(shè)計(jì)流程
在對(duì)原始圖像數(shù)據(jù)進(jìn)行Н.264 編碼時(shí),由于前端模塊獲取圖像數(shù)據(jù)的速度和Н.264 編碼器的讀入速度并不相同,兩者數(shù)據(jù)直連會(huì)造成時(shí)延。因此圖像數(shù)據(jù)需要經(jīng)過緩存區(qū)再進(jìn)入到編碼器中。線性緩存區(qū)不能同時(shí)進(jìn)行讀寫兩種操作,數(shù)據(jù)需寫滿緩沖區(qū)后,再進(jìn)行讀出,這會(huì)造成在編碼器讀取數(shù)據(jù)時(shí),圖像數(shù)據(jù)因等待寫入而丟失,無(wú)法保證系統(tǒng)的實(shí)時(shí)性。為此系統(tǒng)在前端輸入設(shè)備和編碼器之間設(shè)置一個(gè)環(huán)形緩沖區(qū)。環(huán)形緩沖區(qū)能夠同時(shí)進(jìn)行讀寫操作,實(shí)現(xiàn)圖像數(shù)據(jù)的先入先出,這樣便解決了兩個(gè)線程同時(shí)處理的問題。并且緩沖區(qū)不需要再拷貝內(nèi)存,對(duì)數(shù)據(jù)的解析率高。但環(huán)形緩沖區(qū)的大小也是有限的,如果讀寫數(shù)據(jù)的速率相差很大,可能會(huì)導(dǎo)致數(shù)據(jù)溢出,這時(shí)便需要分別計(jì)算圖像獲取操作和Н.264 編碼操作的耗時(shí),通過主動(dòng)延遲某一方面的單次耗時(shí),配合系統(tǒng)的環(huán)形緩沖區(qū)來(lái)確保數(shù)據(jù)不會(huì)丟失。
流媒體實(shí)時(shí)傳輸系統(tǒng)使用Visual Studio 2015 作為開發(fā)工具,在Windows 平臺(tái)下進(jìn)行運(yùn)行。采用高清魚眼相機(jī)作為前端采集與編碼模塊的視頻輸入設(shè)備,使用VLC 播放器作為客戶端。
運(yùn)行流媒體實(shí)時(shí)傳輸系統(tǒng)后,終端界面會(huì)顯示出當(dāng)前流媒體系統(tǒng)的RTSP 推流地址和如圖5 所示的前端實(shí)時(shí)圖像窗口。使用VLC中的網(wǎng)絡(luò)串流功能,輸入實(shí)時(shí)傳輸系統(tǒng)的推送地址和預(yù)先設(shè)定好的端口號(hào),即可完成視頻的實(shí)時(shí)播放。實(shí)驗(yàn)結(jié)果如圖6 所示,VLC播放器的顯示畫面與前端輸入圖像一致,證明基于RTSP 服務(wù)器的流媒體實(shí)時(shí)傳輸系統(tǒng)中的數(shù)據(jù)采集、編碼、推送、播放等各個(gè)功能皆能正常運(yùn)行,系統(tǒng)整體達(dá)到實(shí)時(shí)傳輸效果。
系統(tǒng)在使用的過程中,支持多個(gè)接收端并行觀看,使用不同的網(wǎng)絡(luò)串流客戶端,通過訪問相同的RTSP 播放地址,便能同時(shí)觀看前端流媒體實(shí)時(shí)數(shù)據(jù)。
本文討論了使用RTSP 技術(shù)實(shí)現(xiàn)流媒體數(shù)據(jù)實(shí)時(shí)傳輸?shù)娜^程,設(shè)計(jì)并實(shí)現(xiàn)了一種基于RTSP 服務(wù)器的流媒體實(shí)時(shí)傳輸系統(tǒng)。系統(tǒng)能夠?qū)D像數(shù)據(jù)進(jìn)行Н.264 實(shí)時(shí)編碼和RTSP 實(shí)時(shí)推送。在兼顧傳輸實(shí)時(shí)性的同時(shí),系統(tǒng)采用了TCP 協(xié)議對(duì)RTSP 數(shù)據(jù)進(jìn)行傳輸,保證了數(shù)據(jù)傳輸?shù)目煽啃?。因此本系統(tǒng)能夠?yàn)橥h(yuǎn)鏡的觀測(cè)圖像提供實(shí)時(shí)、可靠的傳輸服務(wù)。
圖5:前端實(shí)時(shí)圖像窗口
圖6:流媒體實(shí)時(shí)傳輸系統(tǒng)客戶端測(cè)試結(jié)果