林海東,余 強(qiáng)
(西華大學(xué)數(shù)學(xué)與計(jì)算機(jī)學(xué)院,四川 成都 610039)
隨著計(jì)算機(jī)信息技術(shù)的發(fā)展和人們安全意識(shí)的增強(qiáng),視頻監(jiān)控以其直觀、準(zhǔn)確、及時(shí)和信息內(nèi)容豐富而廣泛應(yīng)用于許多場(chǎng)合,成為社會(huì)安全防范系統(tǒng)的重要組成部分。同時(shí),對(duì)視頻監(jiān)控的清晰度、網(wǎng)絡(luò)化、智能化、功耗節(jié)能以及傳輸設(shè)備的體積大小等方面提出了更高的要求。本文根據(jù)視頻監(jiān)控的發(fā)展現(xiàn)狀,設(shè)計(jì)了一種采用新一代H.264視頻編碼標(biāo)準(zhǔn)的嵌入式Linux的遠(yuǎn)程視頻監(jiān)控系統(tǒng)。該系統(tǒng)采用模塊化思想設(shè)計(jì),模塊之間高內(nèi)聚低耦合,便于維護(hù)和升級(jí) 。
本文提出的視頻監(jiān)控系統(tǒng)整體采用客戶機(jī)/服務(wù)器架構(gòu),其設(shè)計(jì)主要包括2方面。1)服務(wù)器設(shè)計(jì)。服務(wù)器端的硬件平臺(tái)建立在ARMS3C6410為主控芯片的開發(fā)板上,主要包括視頻采集模塊、視頻壓縮模塊、視頻傳輸模塊。采集模塊通過USB攝像頭采集視頻圖像。視頻壓縮模塊采用新一代H.264視頻壓縮算法,通過6410內(nèi)部的MFC(multi format codec)專用編碼芯片把視頻圖像壓縮成H264 NALU視頻流。H264實(shí)時(shí)視頻的傳輸協(xié)議采用的是RTP/RTCP協(xié)議模式。RTP模塊主要負(fù)責(zé)按照RFC 3984協(xié)議把NALU封裝成RTP數(shù)據(jù)包發(fā)送到客戶端,保證流媒體傳輸?shù)膶?shí)時(shí)性。RTCP 模塊主要用于數(shù)據(jù)分發(fā)質(zhì)量反饋信息,提供流量控制和擁塞控制[1-5]。2)客戶端設(shè)計(jì)。其主要包括視頻接收模塊、視頻解壓模塊和視頻顯示模塊。視頻解壓模塊主要用FFMPEG實(shí)現(xiàn),顯示模塊用SDL實(shí)現(xiàn)[6-7]。
視頻采集程序是基于Video4Linux模塊提供的API函數(shù)。Video4Linux是Linux內(nèi)核中提供給用戶視頻采集的API接口。它支持絕大多數(shù)的USB攝像頭,對(duì)設(shè)備的操作簡(jiǎn)單直觀,基本遵循打開視頻設(shè)備、設(shè)置設(shè)備屬性、設(shè)置視頻數(shù)據(jù)格式、設(shè)置設(shè)備輸出方法、循環(huán)輸出視頻信息、關(guān)閉設(shè)備的順序。其中,大多數(shù)操作都是通過調(diào)用ioctl函數(shù)實(shí)現(xiàn)的。圖1是視頻采集的流程圖。
圖1 視頻采集流程
1)打開設(shè)備。調(diào)用open(device_name, flags)函數(shù)打開設(shè)備,打開模式分為阻塞模式和分阻塞模式。
2)獲取設(shè)備屬性。調(diào)用ioctl(fd, VIDIOC_QUERYCAP, struct v4l2_capability *argp)函數(shù)將設(shè)備性能參數(shù)放到v4l2_capability結(jié)構(gòu)體中,獲取設(shè)備是否具有視頻捕獲和流式IO性能。
3)設(shè)置圖片格式。調(diào)用ioctl( fd, VIDIOC_S_FMT, struct v4l2_format *argp)設(shè)置圖像的存儲(chǔ)格式、帶寬大小、像素等信息。
4)初始化內(nèi)存映射。調(diào)用ioctl(fd, VIDIOC_REQBUFS, struct v4l2_requestbuffers *argp)申請(qǐng)緩存,并通過mmap函數(shù)映射到用戶地址空間。
5)開始采集視頻。調(diào)用ioctl(fd, VIDIOC_QBUF, struct v4l2_buffer *argp)函數(shù),將申請(qǐng)到的幀緩沖全部放入V4L2數(shù)據(jù)緩沖隊(duì)列,以便存放采集到的數(shù)據(jù),并用ioctl(fd, VIDIOC_STREAMON, int *argp)使攝像頭開始捕獲視頻。
6)獲取1幀數(shù)據(jù)。調(diào)用ioctl(fd, VIDIOC_DQBUF, struct v4l2_buffer *argp) 從視頻緩沖區(qū)的輸出隊(duì)列中取得一個(gè)已經(jīng)保存有1幀視頻數(shù)據(jù)的視頻緩沖區(qū),從而獲得視頻信息。
7)停止采集視頻。調(diào)用ioctl(fd, VIDIOC_STREAMOFF, int *argp)使攝像頭停止捕獲視頻。
8)關(guān)閉設(shè)備。調(diào)用close關(guān)閉設(shè)備。
視頻壓縮通過S3C6410內(nèi)部的MFC模塊完成。MFC是一個(gè)高能的視頻編解碼器 IP,由嵌入式位處理器和視頻編解碼器核心模塊組成, 支持H.263P3、MPEG-4 SP、H.264和VC-1的編解碼。在Linux內(nèi)核中加載MFC驅(qū)動(dòng)模塊,就可以/dev/s3c-mfc設(shè)備文件對(duì)其訪問,用ioctl函數(shù)來實(shí)現(xiàn)相應(yīng)的指令操作。MFC模塊的H264編碼流程如圖2所示,主要用到的函數(shù)如下。
1)fd=open(MFC_DEV_NAME, O_RDWR|O_NDELAY)。此函數(shù)打開MFC設(shè)備,如果打開設(shè)備成功,則返回該設(shè)備的文件描述符。
2)ioctl(fd, IOCTL_MFC_H264_ENC_INIT, &mfc_args)。此函數(shù)初始化MFC,設(shè)置視頻壓縮圖像的大小、比特率、幀率等。
3)ioctl(fd n, IOCTL_MFC_GET_FRAM_BUF_ADDR, &mfc_args)。此函數(shù)獲得MFC設(shè)備中用于存放原始YUV420幀格式的FRAM_BUF的存儲(chǔ)區(qū)的地址,用memcpy函數(shù)把原始視頻幀放入以這個(gè)首地址開始的存儲(chǔ)區(qū)中就可以對(duì)幀進(jìn)行壓縮。
4)ioctl(fd, IOCTL_MFC_H264_ENC_EXE, &mfc_args)。 此函數(shù)對(duì)放入FRAM_BUF中的視頻幀進(jìn)行壓縮。MFC按照H264編碼標(biāo)準(zhǔn)的基本檔次,把原始視頻幀壓縮并封裝到NALU中,然后把壓縮數(shù)據(jù)存放STRM_BUF的存儲(chǔ)區(qū)。為減少無用碼率,MFC只對(duì)第1幀H264碼流上添加序列參數(shù)集SPS(sequence parameter set)和圖像參數(shù)集PPS(picture parameter set),這里面包含了如圖像的大小、可采用的可選編碼模式、宏塊到片組的映射等信息,對(duì)客戶端的解碼至關(guān)重要。對(duì)壓縮數(shù)據(jù)進(jìn)行發(fā)送時(shí),應(yīng)首先發(fā)送第1幀編碼的NALU。
5)ioctl(fd, IOCTL_MFC_GET_LINE_BUF_ADDR, &mfc_args)。此函數(shù)獲得存放MFC壓縮視頻幀的STRM_BUF的存儲(chǔ)區(qū)的地址,用memcpy函數(shù)獲取壓縮后的視頻數(shù)據(jù)。MFC首次編碼存儲(chǔ)區(qū)中存儲(chǔ)著編碼圖像NALU 、SPS和PPS 3個(gè)NALU ,之后的編碼過程中緩沖區(qū)只包含一個(gè)完整的NALU。
6)close(fd)。關(guān)閉設(shè)備。
圖2 MFC模塊的H264編碼流程
為保證視頻傳輸?shù)膶?shí)時(shí)性,在視頻的傳輸中采用實(shí)時(shí)傳輸協(xié)議RTP(real-time transport protocol)。RTP 提供了端到端的網(wǎng)絡(luò)傳輸功能,適合于通過多播或單播網(wǎng)絡(luò)視頻服務(wù)的實(shí)時(shí)數(shù)據(jù)傳輸應(yīng)用。RTP的典型應(yīng)用建立在UDP協(xié)議上,本身只保證實(shí)時(shí)數(shù)據(jù)的傳輸,并不能為數(shù)據(jù)傳輸提供可靠的傳送機(jī)制,也不提供流量控制或擁塞控制。它依靠RTCP(RTP control protocol)提供這些服務(wù)。RTCP負(fù)責(zé)管理傳輸質(zhì)量在應(yīng)用進(jìn)程之間交換控制信息。在RTP會(huì)話期間,各參與者周期性地傳送RTCP包,包中含有已發(fā)送的數(shù)據(jù)包的數(shù)量、丟失的數(shù)據(jù)包的數(shù)量等統(tǒng)計(jì)資料,發(fā)送端可以利用這些信息動(dòng)態(tài)地改變傳輸速率。RTP和RTCP配合使用,能以有效的反饋和最小的開銷使傳輸效率最佳化,故特別適合視頻數(shù)據(jù)的實(shí)時(shí)性傳輸。RFC3550協(xié)議詳細(xì)描述了RTP和RTCP協(xié)議。
本文的視頻傳輸由ORTP提供實(shí)現(xiàn)。ORTP是一個(gè)支持RFC3550協(xié)議的開源庫,完全由C語言實(shí)現(xiàn),除了能保證傳輸?shù)膶?shí)時(shí)性外,還具有跨平臺(tái)可移植的特點(diǎn)。在ORTP的實(shí)現(xiàn)中提供了一個(gè)表示RTP會(huì)話的結(jié)構(gòu)RtpSession。它定義了RTP會(huì)話中所用到的所有信息,所有操作都是圍繞它展開的。
發(fā)送視頻的實(shí)現(xiàn)步驟如下。
1)在進(jìn)行RTP傳輸前,首先要對(duì)ORTP庫進(jìn)行初始化。初始化函數(shù)如下:
ortp_init():初始化ORTP庫。
ortp_scheduler_init():初始化任務(wù)調(diào)度。
2)對(duì)RTP收發(fā)進(jìn)行初始化。首先通過rtp_session_new創(chuàng)建一個(gè)RTP會(huì)話實(shí)例,并用一個(gè)RtpSession結(jié)構(gòu)session表示這個(gè)會(huì)話;然后通過返回的結(jié)構(gòu)設(shè)置任務(wù)調(diào)度模式、發(fā)送模式、目標(biāo)地址和端口號(hào)、負(fù)載類型等,如下所示:
rtp_session_set_scheduling_mode(session,1);設(shè)置任務(wù)調(diào)度支持阻塞
rtp_session_set_blocking_mode(session,1);設(shè)置發(fā)送接收為阻塞模式
rtp_session_set_connected_mode(session,TRUE);設(shè)置連接模式
rtp_session_set_remote_addr(session,argv[2],atoi(argv[3]));設(shè)置發(fā)送地址
rtp_session_set_payload_type(session,0);設(shè)置負(fù)載類型
3)發(fā)送壓縮數(shù)據(jù)。數(shù)據(jù)的發(fā)送主要用到rtp_session_send_with_ts (session, buffer, len, userts)。buf是要發(fā)送RTP包的負(fù)載部分,在本應(yīng)用中負(fù)載就是NALU的數(shù)據(jù)部分。len是負(fù)載的長(zhǎng)度。userts是發(fā)送RTP包的時(shí)間戳。S3C6410的MFC在對(duì)原始幀進(jìn)行H264編碼后,在每一個(gè)NAL單元前添加起始碼0X00000001,可根據(jù)這個(gè)找到NALU的起始頭部。如果NALU的長(zhǎng)度大于1 400,則要按照RFC3984對(duì)其分割后再發(fā)送,以避免IP層對(duì)大分組的分割。由于在ORTP中要自己管理時(shí)間戳,因此在對(duì)一個(gè)NALU分割發(fā)送的RTP包應(yīng)使用相同的時(shí)間戳。
4)終止RTP會(huì)話。程序如下:
rtp_session_destroy(session);
ortp_exit();
接收視頻的實(shí)現(xiàn)如下。
初始化和終止的步驟和發(fā)送端一樣,只是在初始化時(shí)要把接收IP設(shè)置為“0.0.0.0”,端口和發(fā)送端口保持一致。數(shù)據(jù)的接收使用rtp_session_recv_with_ts(session, buffer,len, ts, have_more)。這個(gè)函數(shù)將根據(jù)時(shí)間戳ts接收發(fā)送端發(fā)送的具有相同時(shí)間戳的RTP包,并把負(fù)載數(shù)據(jù)放到buferr里面,如果提供的buferr太小不足以存下所有的數(shù)據(jù),have_more將被設(shè)置為1。把同一時(shí)間戳內(nèi)接收的數(shù)據(jù)封裝在一起就是發(fā)送的NALU單元。特定的時(shí)間戳的數(shù)據(jù)包接收完后,應(yīng)根據(jù)時(shí)間戳增量增加時(shí)間戳,然后接收下一個(gè)NALU。
客戶端的任務(wù)主要是把接收到的H264視頻幀解碼成YUV420的圖像格式,并把圖像轉(zhuǎn)化為需要的格式,并在播放器的窗口里播放。本系統(tǒng)采用的基于開源的FFmpeg進(jìn)行H264的解碼和SDL用于解碼后視頻的播放。
FFmpeg在Linux平臺(tái)下開發(fā),是一套可以用來記錄、轉(zhuǎn)換數(shù)字音頻、視頻,并能將其轉(zhuǎn)化為流的開源計(jì)算機(jī)程序。它包括了目前領(lǐng)先的音/視頻編碼庫libavcodec。用FFmepeg解碼時(shí)首先用av_register_all()函數(shù)注冊(cè)所有的編解碼器,通過avcodec_find_decoder(AV_CODEC_ID_H264)找到程序所用的H264解碼器,并返回H264解碼器的句柄pcodec,然后調(diào)用avcodec_alloc_context3(pcodec),初始化編碼器的一些固定參數(shù),并返回編碼上下文句柄pcodecctx。利用上面得到的pcodec和pcodecctx,通過avcodec_open2(pcodecctx, pcodec, NULL)打開H264解碼器就可以進(jìn)行H264解碼了。解碼時(shí),定義一個(gè)AVPacket結(jié)構(gòu),把接收到的NALU存儲(chǔ)的地址和長(zhǎng)度傳遞給AVPacket,利用avcodec_decode_video2(pcodecctx, pFrame, &frameFinished, &avpkt)函數(shù)對(duì)NALU進(jìn)行解碼,解碼得到的YUV420格式的圖像數(shù)據(jù)將會(huì)存儲(chǔ)在pFrame中。
SDL是一套開放源代碼的跨平臺(tái)多媒體開發(fā)庫,使用C語言寫成。它提供了數(shù)種控制圖像、聲音、輸出入的函數(shù),多用于媒體播放器、開發(fā)游戲模擬器等多媒體應(yīng)用領(lǐng)域。SDL的播放流程如圖3所示。
圖3 SDL播放
本文提出了一套基于H264的遠(yuǎn)程視頻監(jiān)控系統(tǒng)方案。系統(tǒng)采用Linux2.6.28作為操作系統(tǒng),以S3C6410作為主控處理器實(shí)現(xiàn)了對(duì)視頻數(shù)據(jù)的采集、壓縮和傳輸。由于采用了新一代的H.264視頻編碼標(biāo)準(zhǔn),因此,在同等質(zhì)量圖像下,其壓縮比是傳統(tǒng)壓縮標(biāo)準(zhǔn)MPEG-2的2倍以上,是MPEG-4的1.5~2倍,提高了系統(tǒng)的數(shù)據(jù)壓縮比。H.264在具有高壓縮比的同時(shí)還擁有高質(zhì)量流暢的圖像,因此在網(wǎng)絡(luò)傳輸過程中所需的帶寬更小,極大地提高了數(shù)據(jù)的處理與傳輸效率,使整個(gè)系統(tǒng)具有良好的實(shí)時(shí)性。在客戶端將圖像幀率設(shè)置為25(f/s),用局域網(wǎng)模擬公網(wǎng),前端設(shè)備與用戶終端設(shè)備間的信息延遲大約為2 s。使用openRTSP工具觀測(cè)系統(tǒng)性能,系統(tǒng)運(yùn)行2 h,傳輸速率為156 kb/s,平均丟包率為2.3%,滿足國(guó)家視頻監(jiān)控的標(biāo)準(zhǔn)。在客戶端看到的監(jiān)控視頻畫面滿足視頻監(jiān)控系統(tǒng)的實(shí)時(shí)性、流暢性和畫面清晰的要求。采集圖像,如圖4所示。實(shí)驗(yàn)結(jié)果表明,本系統(tǒng)成本低、功耗小、功能可擴(kuò)展、運(yùn)行穩(wěn)定可靠,可適用于各個(gè)領(lǐng)域的視頻監(jiān)控。
圖4 遠(yuǎn)程視頻采集圖像
[1]李珊珊.王旭國(guó).基于V4l2的遠(yuǎn)程視頻采集系統(tǒng)設(shè)計(jì)與實(shí)現(xiàn)[EB/OL].(2011-11-24).http://www.paper.edu.cn/download/downPaper/201103-1124.
[2]白立朋.李秋林,程磊,等.嵌入式ARM下的USB攝像頭監(jiān)控系統(tǒng)[J] .計(jì)算機(jī)系統(tǒng)應(yīng)用,2011,20(6):122-125.
[3]劉健敏.楊斌.嵌入式Linux下基于FFmpeg的視頻硬件編解碼[J] .單片機(jī)與嵌入式系統(tǒng)應(yīng)用,2011,11(6):28-31.
[4]畢厚杰.新一代視頻壓縮編碼標(biāo)準(zhǔn):H.264/AVC[M].北京:人民郵電出版社,2009:189-213.
[5]S3C6400/6410 HW Multimedia Codec (MFC) User’s Guide [M]. [S.l.]:Samsung Electronics,2008:2-24.
[6]RFC 1889-RTP A Transport Protocol for Real-Time Applications [EB/OL].(1996-01-25).http://www.packetizer.com/rfc/rfc1889/.
[7]Doxygen,ORTP APT Documentation Rev0.14.2[EB/OL].(2008-02-02).http://www.antisip.com/doc/ortp.