, , ,
(1.江南大學(xué) 物聯(lián)網(wǎng)工程學(xué)院,江蘇 無錫 214122; 2.沈陽航空航天大學(xué) 自動化學(xué)院,沈陽 110000;3.江蘇聯(lián)合職業(yè)技術(shù)學(xué)院 無錫機電分院,江蘇 無錫 214000)
由于視頻原始數(shù)據(jù)中存在著各種冗余信息,如時間冗余、空間冗余等,故對視頻原始數(shù)據(jù)進行壓縮編碼十分重要[1]。當(dāng)前,市場上的嵌入式采集方案大多采用ASIC、FPGA等專用方案,雖然這種方案有高可靠性,高效率的優(yōu)點,但其靈活性較差,整體設(shè)計周期較長,系統(tǒng)開發(fā)成本高[2-3];目前,市場上也有采用雙核DSP處理器或者是ARM和DSP雙處理器的方案,這兩種方案都使用了DSP,系統(tǒng)編解碼速度快,但系統(tǒng)功耗較大,成本也比較高[4-5]。
采用包含多媒體硬件編解碼器的高性能單片嵌入式處理器來進行硬件編解碼和智能控制,則既降低了系統(tǒng)的功耗和成本,同時也使得系統(tǒng)具有更易維護和升級的優(yōu)點,若根據(jù)系統(tǒng)的硬件體系結(jié)構(gòu)對軟件作進一步地優(yōu)化,便可實現(xiàn)高效運算[6]。通過對嵌入式技術(shù)的深入學(xué)習(xí)和研究,本文提出了一種基于S3C6410單核嵌入式處理器的視頻傳輸系統(tǒng)解決方案。
本視頻傳輸系統(tǒng)主要由流媒體服務(wù)器、網(wǎng)絡(luò)傳輸模塊和PC機三部分組成。流媒體服務(wù)器采用以S3C6410為處理器的Tiny6410開發(fā)板。首先Tiny6410開發(fā)板上需要移植Linux操作系統(tǒng),然后在操作系統(tǒng)上部署live555流媒體服務(wù)器,采用最新一代編解碼方式H.264對采集的視頻數(shù)據(jù)進行硬編碼,使用RTP對數(shù)據(jù)包進行封裝,然后發(fā)送給live555流媒體服務(wù)器等待傳輸;使用RTP/RTCP協(xié)議將視頻流傳輸給PC,PC端對視頻流解碼后可進行視頻的回放。系統(tǒng)總體結(jié)構(gòu)如圖1所示。
圖1 系統(tǒng)總體結(jié)構(gòu)圖
系統(tǒng)使用的Tiny6410開發(fā)板采用Samsung公司生產(chǎn)的S3C6410處理器,S3C6410是基于ARM1176JZF-S核的高性能處理器,主頻667 Mhz,其內(nèi)部總線結(jié)構(gòu)由APB、AHB和AXI組成,外圍模塊通過這些總線與處理器相連[7]。S3C6410中包含內(nèi)存管理器MMU、LCD控制器、攝像頭控制器、4路UART和1路IIC等豐富資源,內(nèi)部集成的多媒體編解碼器MFC支持H.264等多種音視頻格式的編解碼,在視頻監(jiān)控、可視電話等開發(fā)應(yīng)用中使用十分廣泛,具有體積小、功耗低、處理能力強、速度快等優(yōu)點。系統(tǒng)硬件框圖如圖2所示。
圖2 系統(tǒng)硬件框圖
系統(tǒng)軟件設(shè)計主要由視頻采集、視頻編碼、視頻網(wǎng)絡(luò)傳輸以及流媒體服務(wù)器四個模塊組成,四個模塊的設(shè)計如下。
設(shè)備驅(qū)動程序是Linux內(nèi)核中的重要組成部分,它主要負責(zé)協(xié)調(diào)操作系統(tǒng)和硬件設(shè)備的關(guān)系,并提供由操作系統(tǒng)到硬件設(shè)備的接口。設(shè)備驅(qū)動程序為處于用戶態(tài)的程序屏蔽了硬件的細節(jié),從用戶態(tài)程序的角度來看,通過類似于系統(tǒng)調(diào)用的方式即可實現(xiàn)對設(shè)備進行訪問和操作。V4L2(Video For Linux two)是內(nèi)核下編寫視頻設(shè)備驅(qū)動程序的規(guī)范。通過將視頻應(yīng)用函數(shù)封裝,V4L2簡化了視頻采集程序的開發(fā),提高了系統(tǒng)開發(fā)與維護的效率[8]。
圖3 視頻采集流程圖
V4L2視頻采集的流程如上圖3所示。視頻采集中的關(guān)鍵步驟代碼如下:
(1)打開設(shè)備文件并查看設(shè)備功能
intfd=open("/dev/video0,O_RDWR);
{mathop{ m ret} olimits} = ioctl(fd, VIDIOC—QUERYSTD,& std);
(2)設(shè)置視頻幀格式及制式
{mathop{ m if} olimits}(ioctl(fd, VIDIOC—S—FMT,& fmt) < 0){
{mathop{ m return} olimits} 0;
}
(3)向驅(qū)動申請幀緩沖
{mathop{ m struct} olimits} v4l2—requestbuffers req;
{mathop{ m memset} olimits} (& req, 0, sizeof (req));
{mathop{ m ioctl} olimits} (fd,VIDIOC—REQBUFS,& req)
(4)幀緩沖映射并采集數(shù)據(jù)
{mathop{ m buffers} olimits} = calloc( req.count, sizeof(Video Buffer));{mathop{ m buffers} olimits} [numBufs].start = mmap(NULL,buf.length,PROT—{mathop{ m READ} olimits} |PROT\_WRITE,MAP\_SHARED,fd,buf.m.offset);{mathop{ m enum} olimits} v4l2\_buf\_type type;
{mathop{ m type} olimits} = V4L2\_BUF\_TYPE\_VIDEO\_CAPTURE;
{mathop{ m f} olimits} (ioctl(fd, VIDIOC\_STREAMON, & type) < 0){
{mathop{ m return} olimits} - 1;
}
(5)采集結(jié)束,關(guān)閉攝像頭
{mathop{ m ret} olimits} = ioctl(fd, VIDIOC\_STREAMOFF,& std);
{mathop{ m close} olimits} (fd);
視頻編碼主要是將攝像頭采集的圖像經(jīng)過壓縮編碼,形成特定的文件格式或視頻數(shù)據(jù)流。通過對視頻數(shù)據(jù)進行H.264編碼,既提高了編碼效率,同時也增強了網(wǎng)絡(luò)傳輸?shù)聂敯粜訹9]。
3.2.1 視頻編碼模型
MFC主要對存放在緩存中的攝像頭數(shù)據(jù)進行編碼。MFC硬件部分分為BIT processor模塊和視頻編解碼核心模塊,BIT processor模塊主要負責(zé)接硬件加速、編解碼速率控制以及接收處理器信號;視頻編解碼核心模塊主要負責(zé)運動估算、幀間預(yù)測以及幀內(nèi)預(yù)測,并通過BIT processor將數(shù)據(jù)存放到MFC的輸出緩存中。通過模塊的共享,MFC既能支持多種格式的編解碼,又大大降低了硬件的冗余。
MFC library、MFC driver和用戶程序共同組成了視頻編碼的軟件部分。其中,MFC driver通過在內(nèi)核中注冊一個misc設(shè)備,在文件系統(tǒng)中生成/dev目錄下的s3c-mfc設(shè)備文件,進而可以對該設(shè)備文件進行iotcl操作。MFC driver在初始化時先后完成:進行設(shè)備注冊、打開系統(tǒng)時鐘、進行寄存器物理地址映射、注冊中斷interrupt、獲取顯存framebuffer、設(shè)置位處理器緩存、對MFC硬件進行初始化。MFC硬編解碼模型框圖4所示。
圖4 MFC硬編解碼模型框圖
3.2.2 視頻編碼程序設(shè)計
使用MFC進行視頻的編解碼可以通過調(diào)用MFC library中的函數(shù)實現(xiàn),使得開發(fā)人員更多地專注于多媒體應(yīng)用開發(fā)。使用MFC進行視頻編碼的簡要步驟如下:
(1)打開輸入設(shè)備video
defineCODEC_NODE"/dev/video0"
{mathop{ m dev} olimits} \_fp = open(CODEC\_NODE, O\_RDWR);
(2)獲取設(shè)備的capability屬性
{mathop{ m ret} olimits} = ioctl(cam\_c\_fp , VIDIOC\_QUERYCAP, & cap);
(3)設(shè)置設(shè)備參數(shù)
{mathop{ m codec} olimits} \_fmt.type = V4L2\_BUF\_TYPE\_VIDEO\_CAPTURE;{mathop{ m codec} olimits} \_fmt.fmt.pix.width = LCD\_WIDTH;
{mathop{ m codec} olimits} \_fmt.fmt.pix.height = LCD\_HEIGHT;
{mathop{ m codec} olimits} \_fmt.fmt.pix.pixelformat = V4L2\_PIX\_FMT\_YUV420; {mathop{ m ret} olimits} = ioctl(cam\_c\_fp , VIDIOC\_S\_FMT, & codec\_fmt);
(4)MFC初始化
{mathop{ m handle} olimits} = mfc\_encoder\_init(LCD\_WIDTH,LCD\_HEIG{mathop{ m HT} olimits} , framerate, 1000, 30); /* Codec start */
(5)設(shè)置MFC的狀態(tài)
{mathop{ m start} olimits} = 1;
{mathop{ m ret} olimits} = ioctl(cam\_c\_fp, VIDIOC\_STREAMON, & start);
(6)循環(huán)讀取數(shù)據(jù)
{mathop{ m while} olimits} (1){
{mathop{ m read} olimits} (cam\_c\_fp,g\_yuv,YUV\_FRAME\_BUFFER\_SIZE);{mathop{ m f} olimits} (frame\_count = = 1) {
{mathop{ m encoded} olimits} \_buf = (unsignedchar*)mfc\_encoder\_exe(handl{mathop{ m e} olimits} ,g\_yuv,YUV\_FRAME\_BUFFER\_SIZE,1,& encoded\_size);}else
{mathop{ m encoded} olimits} \_buf = (unsignedchar*)mfc\_encoder\_exe(h
{mathop{ m andle} olimits} ,g\_yuv, YUV\_FRAME\_BUFFER\_SIZE, 0,
&encoded_size);
}
其中,MFC編碼初始化函數(shù)mfc_encoder_init通過調(diào)用SsbSipH264EncodeInit函數(shù)對MFC進行初始化;mfc_encoder_exe則調(diào)用MFClibrary中的SsbSipH264EncodeGetInBuf函數(shù)將要編碼的數(shù)據(jù)放入MFC的輸入緩存,再通過SsbSipH264EncodeExe函數(shù)對幀數(shù)據(jù)進行編碼,最后通過SsbSipH264EncodeGetOutBuf函數(shù)獲得編碼后幀的地址。
3.3.1 H.264的RTP封裝
NALU(NAL unit)數(shù)據(jù)流是由網(wǎng)絡(luò)適配層對H.264的原始數(shù)據(jù)進行處理后形成的。下面對H.264視頻流三種RTP負載格式進行介紹:當(dāng)一個RTP包能放置一個NALU而不能放置兩個NALU的時候,采用單個NAL單元包封裝方式;聚合包主要是在RTP負載包能夠放置兩個或兩個以上的NALU的時候,為了提高網(wǎng)絡(luò)的傳輸效率,將多個NALU打包到一個RTP包中。當(dāng)RTP負載包無法裝載一個NALU時,則需要對NALU進行分片。H.264數(shù)據(jù)包分片步驟可見于圖5,其分片規(guī)則如下:
圖5 H.264數(shù)據(jù)包的分片步驟框圖
1) 聚合包無法分片,只有單個NALU可進行分片。
2) NALU字節(jié)是連續(xù)的,且整數(shù)個NALU字節(jié)構(gòu)成一個NALU。
3) 發(fā)送時,NALU不同分片的RTP序列號是遞增有序排列的;接收時,則必須按照與發(fā)送時相同的序列號排列合并。
3.3.2 JRTPLIB庫的移植與使用
JRTPLIB內(nèi)部用C++實現(xiàn)了RTCP機制,為視頻的網(wǎng)絡(luò)傳輸提供了一個可靠的RTP協(xié)議庫[11]。JRTPLIB 庫的移植步驟如下:
1)下載并解壓jthread、jrtplib 的源代碼
2)配置編譯環(huán)境,對jthread進行編譯
./configure-host=arm-linuxCC=arm-linux-gccCX{mathop{ m X} olimits} = arm - linux - g + +
make
makeinstall
3)對JRTPLIB進行編譯
./configure-host=arm-linuxCC=arm-linux-gcc{mathop{ m CXX} olimits} = {mathop{ m arm} olimits} - {mathop{ m linux} olimits} - {mathop{ m g} olimits} + + - {mathop{ m with} olimits} - {mathop{ m jthread} olimits} - {mathop{ m includes} olimits} = /usr/local/{mathop{ m include} olimits} /jthread CPPFLAGS = - I/usr/local/include/jth{mathop{ m read} olimits} LDFLAGS = - L/usr/local/lib - ljthread
make
makeinstall
4)在庫目錄中添加編譯生成的.a文件和.so文件,完成JRTPLIB的移植。
在使用JRTPLIB庫之前,先要對一些參數(shù)進行相應(yīng)的設(shè)置。初始化RTP會話中的一個重要工作是設(shè)置合適的時間戳,通過調(diào)用RTPSession類中的SetTimestampUnit()函數(shù)可實現(xiàn)以秒為單元的時戳單元的設(shè)置;RTP 會話的實例可通過RTPSession類中的Create()函數(shù)來實現(xiàn)初始化;會話的通信端口和通信地址則可通過AddDestination()函數(shù)實現(xiàn)。最后,應(yīng)用程序在傳輸RTP數(shù)據(jù)包時可通過調(diào)用SendPacket函數(shù)實現(xiàn)。
本文在嵌入式Linux操作系統(tǒng)上部署live555服務(wù)器,完成了流媒體服務(wù)器的構(gòu)建。live555是一個針對流媒體服務(wù)而提出的C++解決方案,它支持多種多媒體傳輸協(xié)議。該服務(wù)器框架中主要包含四個模塊:UsageEnvironment模塊包含抽象類TaskScheduler,主要是對系統(tǒng)環(huán)境進行抽象;BasicUsageEnvironment模塊主要完成對輸入輸出信號響應(yīng)的實現(xiàn);而GroupSock模塊則主要用于數(shù)據(jù)包的接收和發(fā)送;最重要的是GroupSock模塊,其包含了RTCPInstance、RTSPClient、Sink、MediaSession和 Source眾多派生類。
該流媒體服務(wù)器工作在阻塞模式,服務(wù)器初始化時,首先需要進行RTSP端口的綁定,然后進行RTSP監(jiān)聽,當(dāng)有用戶連接時,服務(wù)器會先通知RTP打包模塊對數(shù)據(jù)進行打包,接著服務(wù)器再將RTP打包好的數(shù)據(jù)包轉(zhuǎn)發(fā)。live555服務(wù)器運行流程如圖6所示。
圖6 live555服務(wù)器運行流程圖
在PC上安裝支持多種流協(xié)議的VLC播放器,在VLC播放器中打開流文件并選擇RTP協(xié)議,即可接受解碼并播放tiny6410開發(fā)板通過局域網(wǎng)傳送過來的RTP流。設(shè)置流媒體服務(wù)器IP為192.168.1.230,端口為8000。在PC端進行如下測試:
先運行tiny6410上的流媒體服務(wù)器,SecureCRT顯示“The server is running”,在PC端運行VLC播放器,輸入URL:RTSP://192.168.1.230:8000/,點擊播放。視頻傳輸實時性良好,系統(tǒng)實物測試和VLC端顯示如圖7所示。
圖7 系統(tǒng)實物測試和VLC端顯示圖
由于時間及條件等方面的限制,該視頻傳輸系統(tǒng)存在一定的時延問題。根據(jù)系統(tǒng)測試環(huán)境,預(yù)先在系統(tǒng)接收端設(shè)置500 ms的緩沖區(qū)域,但系統(tǒng)播放的實際時延高于500 ms,在1~1.5 s之間。VLC視頻播放統(tǒng)計信息如圖8所示。系統(tǒng)運行2小時,平均傳輸速率為165 kb/s,平均丟包率為2.2%,滿足國家視頻監(jiān)控的標準。由于視頻數(shù)據(jù)是經(jīng)壓縮編碼后再進行傳輸?shù)模@極大地提高了數(shù)據(jù)傳輸?shù)男?,同時也降低了網(wǎng)絡(luò)的壓力。
圖8 VLC統(tǒng)計信息
本文分別從硬件和軟件兩個角度出發(fā),闡述了基于ARM11的H.264硬編解碼視頻傳輸系統(tǒng)的設(shè)計與實現(xiàn)。本系統(tǒng)采用以ARM11為核心的S3C6410作為處理器,使用外設(shè)攝像頭獲取實時視頻數(shù)據(jù);在Tiny6410上移植Linux操作系統(tǒng)并構(gòu)建live555流媒體服務(wù)器,監(jiān)聽用戶請求;采用處理器內(nèi)置的多媒體硬編解碼器MFC對視頻數(shù)據(jù)進行H.264編碼,使編碼效率得到了有效的提高;使用RTP對數(shù)據(jù)包進行封裝,然后經(jīng)由live555流媒體服務(wù)器轉(zhuǎn)發(fā)至PC機;經(jīng)測試,視頻還原流暢,傳輸實時性良好,滿足實際應(yīng)用需求。
參考文獻:
[1] 高 敏. 視頻圖像壓縮中熵編碼技術(shù)研究[D].哈爾濱:哈爾濱工業(yè)大學(xué),2016.
[2] 郭誠欣,陳 紅,孫 輝,等. 基于現(xiàn)代硬件的并行內(nèi)存排序方法綜述[J]. 計算機學(xué)報,2016(1):24.
[3] 杜曉婧,李樹國. SHA-1算法的高速ASIC實現(xiàn)[J]. 微電子學(xué)與計機,2016(10):19-23.
[4] 任志玲,朱光澤.基于嵌入式和運動檢測的井下視頻監(jiān)控系統(tǒng)[J].計算機測量與控制, 2014,22(5):1398-1400.
[5] 何登平,黃凌云,何 策. 基于DM3730的高清智能視頻采集處理系統(tǒng)的設(shè)計與應(yīng)用[J]. 光電子技術(shù),2015(4):283-288.
[6] Xia T, Prevotet J C, Nouvel F. Mini-NOVA: A Lightweight ARM-based Virtualization Microkernel Supporting Dynamic Partial Reconfiguration[A].Parallel and Distributed Processing Symposium Workshop[C]. IEEE, 2015:71-80.
[7] Yin Q, Zhang J. Development of remote video monitoring system based on TCP/IP[A]. International Conference on Computer Science & Education[C]. IEEE, 2015:596-600.
[8] 田時舜,章明朝,周 躍,等. 基于DM8148的嵌入式網(wǎng)絡(luò)視頻服務(wù)器設(shè)計[J]. 計算機工程與設(shè)計,2015(5):1192-1196.
[9] Zeng B, Yeung S K A, Zhu S, et al. Perceptual Encryption of H.264 Videos: Embedding Sign-Flips Into the Integer-Based Transforms[J]. IEEE Transactions on Information Forensics & Security, 2014, 9(2):309-320.
[10] 張紀寬,彭 力,陳志勇.動態(tài)復(fù)雜背景下的智能視頻監(jiān)控系統(tǒng)設(shè)計與實現(xiàn)[J].計算機測量與控制,2016,24(7):100-104.
[11] Belyaev E, Vinel A, Surak A, et al. Robust Vehicle-to-Infrastructure Video Transmission for Road Surveillance Applications[J]. IEEE Transactions on Vehicular Technology, 2015, 64(7):2991-3003.