張緒紅,黃 睿
(1. 廣東技術(shù)師范大學(xué) 自動化學(xué)院, 廣州 510665; 2. 廣東第二師范學(xué)院 計(jì)算機(jī)科學(xué)系, 廣州 510303)
隨著科技的發(fā)展,人工智能與物聯(lián)網(wǎng)技術(shù)已廣泛應(yīng)用于各個領(lǐng)域,人臉識別、車聯(lián)網(wǎng)等技術(shù)趨于成熟,對視頻采集、監(jiān)控的技術(shù)要求越來越高。然而,這些實(shí)時應(yīng)用場景往往由于網(wǎng)絡(luò)傳輸?shù)臅r延而影響云端的計(jì)算效率。在此背景下,邊緣計(jì)算的架構(gòu)得到了越來越多的關(guān)注。邊緣計(jì)算將計(jì)算部署在離終端更近的邊緣平臺,可以避免集中式云計(jì)算中心的網(wǎng)絡(luò)延遲,提供更具實(shí)時性和短周期的計(jì)算,更好地滿足物聯(lián)網(wǎng)推動下爆發(fā)式的計(jì)算需求。本文特別針對大數(shù)據(jù)量的視頻采集、視頻監(jiān)控等實(shí)時傳輸場景,研究高效穩(wěn)定的嵌入式視頻傳輸方案,實(shí)現(xiàn)邊緣平臺的實(shí)時視頻數(shù)據(jù)采集操作。
具體而言,影響邊緣平臺服務(wù)器性能的有處理器、硬盤、內(nèi)存等硬件因素和服務(wù)器架構(gòu)、網(wǎng)絡(luò)傳輸協(xié)議等軟件因素,而服務(wù)器架構(gòu)是主要的軟件影響因素。目前基于Linux內(nèi)核的模型架構(gòu)一般有傳統(tǒng)I/O模型、SELECT模型、POLL模型和EPOLL模型等[1-4]。傳統(tǒng)I/O模型包括阻塞I/O和非阻塞I/O,該模型主要用于短連接和即時信息交互等場景。SELECT模型通過一組有限的文件描述符集合和時間值(Timeval)結(jié)構(gòu)來等待并處理I/O事件,并通過遍歷監(jiān)聽池來判斷事件源,從而完成事件下行操作[5]。POLL模型是在SELECT模型的基礎(chǔ)上,對最大監(jiān)聽數(shù)和響應(yīng)方法進(jìn)行優(yōu)化,事件上報(bào)后不需要進(jìn)行遍歷操作,直接調(diào)用事件注冊時綁定的處理函數(shù)。
本文設(shè)計(jì)的傳輸方案首先在嵌入式終端實(shí)現(xiàn)攝像頭驅(qū)動,進(jìn)行圖像采集,然后進(jìn)行Socket網(wǎng)絡(luò)服務(wù)器搭建,建立圖像傳輸協(xié)議,最后對客戶端接收到的圖像進(jìn)行實(shí)時顯示。在數(shù)據(jù)量小且連接數(shù)單一的情況下,上述各模型均能滿足需求。隨著連接數(shù)和圖像數(shù)據(jù)量的增大,服務(wù)器系統(tǒng)調(diào)度頻繁,前兩類模型效率較低,將難以滿足工程所需。POLL模型處理相對較好,但資源占用帶寬高,所以,需要在POLL模型的基礎(chǔ)上進(jìn)行模型優(yōu)化,以提高系統(tǒng)性能的效果。
基于Linux內(nèi)核的嵌入式產(chǎn)品中,通常會掛載多種外部設(shè)備,為確保各個設(shè)備的穩(wěn)定運(yùn)行,系統(tǒng)需要實(shí)時監(jiān)測各設(shè)備的運(yùn)行狀態(tài)。傳統(tǒng)的阻塞I/O主要采用忙等的方式來獲取事件的狀態(tài),實(shí)現(xiàn)簡單但占用系統(tǒng)資源多。而SELECT在事件發(fā)生后不能直接判斷上報(bào)的事件是由哪一個文件產(chǎn)生,需要耗費(fèi)時間和資源對監(jiān)聽池的所有事件進(jìn)行遍歷來判斷事件源。EPOLL模型是在POLL模型基礎(chǔ)上進(jìn)行優(yōu)化,使監(jiān)控的文件數(shù)量為無窮大,且事件發(fā)生后就直接調(diào)用該事件綁定的回調(diào)函數(shù),從而直接進(jìn)行下行操作。
為了使設(shè)計(jì)的視頻監(jiān)控系統(tǒng)更高效地運(yùn)行,本文基于EPOLL架構(gòu),分別建立圖像采集、圖像傳輸、視頻通訊、播放顯示等4個子系統(tǒng),各個子系統(tǒng)之間相互通信,從而達(dá)到實(shí)時視頻監(jiān)控的效果,并最終基于Intel、ARM平臺下完成圖像傳輸。
EPOLL機(jī)制是基于傳統(tǒng)的SELECT、POLL機(jī)制產(chǎn)生的,并在Linux2.6內(nèi)核以后的版本進(jìn)行了實(shí)現(xiàn)。EPOLL支持對管道、先進(jìn)先出(FIFO)、套接字、可移植操作系統(tǒng)(POSIX)消息隊(duì)列、終端、設(shè)備等監(jiān)聽處理,其主要優(yōu)點(diǎn)如下:
(1) 進(jìn)程進(jìn)行文件監(jiān)控的數(shù)量沒有上限。該機(jī)制所支持的最大文件描述符上限,主要依賴于運(yùn)行設(shè)備的內(nèi)存容量,呈正相關(guān),遠(yuǎn)大于SELECT的1 024條。
(2) 事件響應(yīng)快速。當(dāng)事件發(fā)生時,不需要再重新遍歷監(jiān)聽池里所有注冊的事件,而是直接找到上報(bào)事件的回調(diào)函數(shù),及時進(jìn)行事件處理。
(3) 快速訪問內(nèi)核空間。通過內(nèi)存映射(mmap)機(jī)制將內(nèi)核空間映射到用戶空間,應(yīng)用程序直接對內(nèi)存進(jìn)行讀寫操作,可以及時對設(shè)備進(jìn)行數(shù)據(jù)交互。
傳統(tǒng)EPOLL模型使用比較簡單,主要分為3個步驟:創(chuàng)建EPOLL監(jiān)聽池、添加要監(jiān)聽的事件、等待事件上報(bào)。EPOLL模型如圖1所示,實(shí)現(xiàn)步驟如下:
步驟1創(chuàng)建EPOLL監(jiān)聽池。epoll_create()函數(shù)用于創(chuàng)建EPOLL監(jiān)聽池,該函數(shù)創(chuàng)建的監(jiān)聽數(shù)量不限,返回值是一個文件描述符。
步驟2添加要監(jiān)聽的事件。epoll_ctl()函數(shù)可以對監(jiān)聽文件屬性進(jìn)行設(shè)置。部分參數(shù)說明如下[6]:
EPOLL_CTL_ADD,注冊新事件到監(jiān)聽池中。
EPOLL_CTL_MOD,修改已注冊的監(jiān)聽事件。
EPOLL_CTL_DEL,從監(jiān)聽池中刪除事件。
EPOLLLT,水平觸發(fā)模式。當(dāng)監(jiān)聽池事件處于就緒態(tài)時,EPOLL將一直上報(bào)該事件。
EPOLLET,邊緣觸發(fā)模式,包括上升沿觸發(fā)和下降沿觸發(fā)。
步驟3等待事件上報(bào)。epoll_wait()函數(shù)用于等待事件上報(bào),當(dāng)發(fā)生事件上報(bào)時,EPOLL機(jī)制會調(diào)用注冊事件時的處理函數(shù)。
圖1 EPOLL模型
傳統(tǒng)EPOLL模型是通過epoll_ctl()函數(shù)對事件進(jìn)行注冊,該函數(shù)主要依賴struct epoll_event結(jié)構(gòu)體進(jìn)行事件描述,該結(jié)構(gòu)體內(nèi)容如圖2所示。
圖2 Epoll_event結(jié)構(gòu)體關(guān)系圖
從圖可以得知,epoll_event結(jié)構(gòu)體成員data是一個union聯(lián)合體。雖然使用*ptr可以指向用戶定義的處理函數(shù)(*為指針結(jié)構(gòu)),fd可以保存事件的文件描述符,但是union聯(lián)合體只能選擇一種成員方式進(jìn)行使用,因此,需要對EPOLL模型進(jìn)行優(yōu)化,如圖3所示。
首先,實(shí)現(xiàn)自定義結(jié)構(gòu)體struct event_ext,包含事件描述符fd;事件狀態(tài)epolled;事件類型events;事件上報(bào)時對應(yīng)的處理函數(shù)*handler;附加參數(shù)*arg。
其次,通過union聯(lián)合體成員*pt指向自定義結(jié)構(gòu)體struct event_ext,完成EPOLL監(jiān)聽池事件注冊。當(dāng)發(fā)生事件上報(bào)時,可以根據(jù)*pt指向的自定義結(jié)構(gòu)體,找到對應(yīng)的處理函數(shù),從而實(shí)現(xiàn)事件下行操作。
圖3 Epoll_event結(jié)構(gòu)體優(yōu)化
本文基于EPOLL機(jī)制分別建立圖像采集、圖像傳輸、視頻通信、顯示等子系統(tǒng),該系統(tǒng)功能結(jié)構(gòu)圖如圖4所示。
圖4 系統(tǒng)功能結(jié)構(gòu)圖
圖像采集子系統(tǒng)主要功能是對圖像進(jìn)行采集,包括初始化攝像頭、設(shè)置圖像采集格式、圖像的保存等功能。
圖像傳輸子系統(tǒng)用于建立圖像傳輸協(xié)議,使服務(wù)端和客戶端按照既定的協(xié)議完成通信,確保圖像數(shù)據(jù)傳輸完整。
視頻通信子系統(tǒng)用于建立客戶端與服務(wù)器的網(wǎng)絡(luò)連接,對接收到的數(shù)據(jù)進(jìn)行解析,提供圖像數(shù)據(jù)接口給顯示子系統(tǒng)。
顯示子系統(tǒng)用于實(shí)時顯示攝像頭采集到的圖像,同時也顯示圖像幀格式、圖像尺寸、傳輸速率等基本內(nèi)容。
視頻監(jiān)控是嵌入式Linux的一個重要應(yīng)用場合,合理高效的進(jìn)行圖像采集是廣大學(xué)者研究的重點(diǎn)[7]。目前基于Linux操作系統(tǒng)下,比較流行的攝像頭軟件架構(gòu)是V4L2(video for linux 2)架構(gòu),該架構(gòu)通過一系列的回調(diào)函數(shù)來使應(yīng)用程序具有發(fā)現(xiàn)設(shè)備和操作設(shè)備的功能,譬如設(shè)置攝像頭的頻率、視頻壓縮格式等圖像基本參數(shù),其軟件架構(gòu)如圖5所示。
圖5 V4L2軟件架構(gòu)
圖5詳細(xì)界紹了基于V4L2攝像頭軟件架構(gòu),該架構(gòu)下圖像采集步驟如下:
步驟1初始化攝像頭。
步驟2獲取驅(qū)動信息;通過文件接口的調(diào)用,使用VIDIOC_QUERYCAP參數(shù)可以查看驅(qū)動信息。
步驟3設(shè)置圖像格式;v4l2_format結(jié)構(gòu)體用于設(shè)置攝像頭的視頻捕捉格式和幀格式等信息。
步驟4申請圖像緩沖區(qū);v4l2_requestbuffers結(jié)構(gòu)體用于設(shè)置緩沖區(qū)數(shù)據(jù)格式和映射關(guān)系。
步驟5將內(nèi)核空間中的圖像緩沖區(qū)映射到用戶空間;結(jié)構(gòu)體v4l2_buffer設(shè)置緩沖區(qū)的存儲類型,使用mmap建立映射關(guān)系。
步驟6圖像緩沖入隊(duì)列;映射好的緩沖區(qū)通過使用VIDIOC_QBUF參數(shù),進(jìn)行緩沖入隊(duì)列操作。
步驟7注冊事件到EPOLL。當(dāng)采集事件發(fā)生后,EPOLL會自動調(diào)用事件處理函數(shù),從而完成采集事件的下行操作。
通過圖像采集子系統(tǒng)完成攝像頭的采集,下一步就需要將圖像進(jìn)行傳輸。傳輸層采用面向連接的TCP協(xié)議,注冊事件到EPOLL后,收到客戶端的網(wǎng)絡(luò)包請求時會作出相應(yīng)的事件處理。Socket編程主要進(jìn)行以下幾步: 創(chuàng)建套接字; 初始化要綁定的地址,并使用bind進(jìn)行綁定; 進(jìn)行端口監(jiān)聽; 等待連接; 數(shù)據(jù)交互。
建立網(wǎng)絡(luò)連接后,需要定義服務(wù)端與客戶端的通信協(xié)議,傳輸?shù)幕緝?nèi)容包含幀的格式和圖像內(nèi)容。一條完整的通訊協(xié)議分別由協(xié)議頭、協(xié)議長度和數(shù)據(jù)內(nèi)容3部分組成,如圖6所示。
圖6 網(wǎng)絡(luò)傳輸協(xié)議
圖6表明,協(xié)議頭由3個字節(jié)組成,分別包含請求ID(8bit)、數(shù)據(jù)類型type(3bit)、數(shù)據(jù)格式subs(5bit)和數(shù)據(jù)長度len(8bit)。協(xié)議幀長度由4個字節(jié)組成。剩下為圖像數(shù)據(jù)。協(xié)議數(shù)據(jù)頭定義見表1。
表1 協(xié)議頭定義
當(dāng)監(jiān)聽到客戶端的請求幀時,首先,事件處理函數(shù)對該請求幀協(xié)議頭進(jìn)行解析,從而獲取請求幀ID,然后將需要返回的內(nèi)容按照傳輸協(xié)議進(jìn)行封裝,最后發(fā)送給客戶端完成了視頻的傳輸。
通過上述步驟完成了采集子系統(tǒng)和傳輸子系統(tǒng),為了讓客戶端與服務(wù)器進(jìn)行穩(wěn)定的數(shù)據(jù)傳輸,需要設(shè)計(jì)面向連接的通信子系統(tǒng),該系統(tǒng)工作流程設(shè)計(jì)如下。
(1) 初始化網(wǎng)絡(luò)協(xié)議,采用面向連接的TCP協(xié)議。
(2) 創(chuàng)建工作線程,主要用于圖像請求及數(shù)據(jù)解析。
(3) 圖像獲取,根據(jù)傳輸子系統(tǒng)的通信協(xié)議,對服務(wù)器返回一幀的數(shù)據(jù)進(jìn)行解析,從而獲取一幀的圖像數(shù)據(jù)。
(4) 創(chuàng)建顯示接口,該接口用于將解析的一幀圖像數(shù)據(jù),傳遞給圖像顯示子系統(tǒng)。
該系統(tǒng)通過線程來發(fā)送構(gòu)造的圖像請求,并對接收到的數(shù)據(jù)幀進(jìn)行解析,將解析出來的圖像提交給圖像顯示子系統(tǒng)。
嵌入式Linux支持多種圖形界面(GUI),常用的有Qt[8]、GTK+[9]、miniGUI等[10-11]。Qt是面向?qū)ο蟮目缙脚_C++圖形開發(fā)框架,模塊化程度高。GTK+是嵌入式Linux下主流的圖形界面開發(fā)工具,支持LGPL開發(fā)協(xié)議,主要采用C語言進(jìn)行編程。miniGUI是面向嵌入式系統(tǒng)圖形界面開發(fā)工具,1.6.10版本后重定義為商用嵌入式GUI系統(tǒng)[12-13]。
顯示子系統(tǒng)主要完成的是圖像顯示功能,相比上述3種程序框架,GTK+開發(fā)相對簡單,可以顯著節(jié)省開發(fā)時間,讓編程人員可以將更多精力集中在項(xiàng)目的核心部分上,故顯示子系統(tǒng)采用GTK+框架進(jìn)行開發(fā)。顯示子系統(tǒng)主要包括以下兩個窗體:
(1) 網(wǎng)絡(luò)連接窗體。通過獲取用戶輸入的IP地址和端口號來進(jìn)行TCP連接,如連接成功,則跳轉(zhuǎn)到圖像顯示窗體界面[14]。窗體設(shè)計(jì)如下:
① 創(chuàng)建垂直布局容器,用于定義窗體的整體布局方式,存放后續(xù)所有的控件。
② 創(chuàng)建水平布局容器,并繪制登錄圖片。
③ 創(chuàng)建水平布局容器,分別繪制服務(wù)器IP地址和端口標(biāo)簽,以及對應(yīng)的編輯框。
④ 創(chuàng)建水平布局容器,創(chuàng)建“確定”“取消”按鈕,并分別聯(lián)按鈕點(diǎn)擊事件connect_handler和gtk_main_quit。該窗體最終效果如圖7所示。
圖7 網(wǎng)絡(luò)連接窗體
(2) 圖像顯示窗體。跳轉(zhuǎn)到圖像顯示窗體后,通過調(diào)用通信子系統(tǒng)來獲取圖像接口,并將圖像、幀格式、尺寸、速率等信息進(jìn)行實(shí)時顯示。窗體設(shè)計(jì)流程如下:
① 判斷是否連接上服務(wù)器,如連接上則獲取服務(wù)器IP地址和端口地址,否則報(bào)錯。
② 創(chuàng)建圖像顯示區(qū)域和功能顯示區(qū)域,功能顯示區(qū)主要包含圖像幀格式、圖像尺寸、傳輸速率等信息[15]。
③ 將解析的圖像在圖像顯示區(qū)域進(jìn)行實(shí)時顯示,并在功能區(qū)顯示相應(yīng)的信息。
基于EPOLL機(jī)制進(jìn)行視頻監(jiān)控系統(tǒng)的設(shè)計(jì)和實(shí)現(xiàn),實(shí)驗(yàn)采用2臺Intel-i5和2臺分別ARM9、ARM11架構(gòu)的設(shè)備。首先分析阻塞I/O、SELECT、POLL、EPOLL等架構(gòu)處理能力,其次分別在Intel、ARM平臺下實(shí)現(xiàn)視頻監(jiān)控系統(tǒng),最后對基于EPOLL機(jī)制視頻監(jiān)控系統(tǒng)進(jìn)行分析。
多線程、多進(jìn)程雖然可以改進(jìn)模型的處理效率,但是并沒有對網(wǎng)絡(luò)編程模型進(jìn)行實(shí)質(zhì)性改善。故服務(wù)端實(shí)驗(yàn)環(huán)境采用單線程處理模式,分別在阻塞I/O、SELECT、POLL、EPOLL等架構(gòu)下進(jìn)行單Byte傳輸,客戶端成功完成讀寫操作的連接請求數(shù)如圖8所示。
圖8 網(wǎng)絡(luò)連接窗體
4種模型函數(shù)調(diào)用所占用時間見表2。
表2 I/O、SELECT、POLL、EPOLL函數(shù)占時比 %
由圖8可見,模型處理能力由高到低的排序是阻塞I/O、EPOLL、POLL、SELECT。由于實(shí)驗(yàn)采用一次性交互的短連接,該場景是捕獲一個請求后即刻進(jìn)行讀寫操作,傳統(tǒng)的阻塞I/O效率最高,EPOLL模型效率要優(yōu)于POLL模型和SELECT模型。
主函數(shù)進(jìn)行Socket網(wǎng)絡(luò)編程,結(jié)合表2數(shù)據(jù),SELECT模型在主函數(shù)占用時間更多,是因?yàn)槊看芜M(jìn)行SELCET都需要對監(jiān)聽池里的事件進(jìn)行遍歷,這也導(dǎo)致相比其他模型,SELECT模型連接性能最差。
視頻監(jiān)控系統(tǒng)基于高并發(fā)處理服務(wù)器,阻塞I/O模型、SELECT只能通過引入多線程提高傳輸效率,而不能達(dá)到高并發(fā)的狀態(tài)。故只考慮POLL和EPOLL模型面對長連接時的性能比較。對服務(wù)器連接數(shù)分別為3 000和20 000時,POLL和EPOLL模型性能見表3。
表3 POLL、EPOLL函數(shù)占時比 %
通過表3 POLL和EPOLL模型對比可看出,當(dāng)最大連接數(shù)為3 000時,POLL模型的傳輸效率高于EPOLL模型。隨著連接數(shù)的增加,最大連接數(shù)達(dá)到20 000時,EPOLL模型主函數(shù)所耗時間低于POLL模型,說明傳輸效率高于POLL模型。EPOLL模型函數(shù)調(diào)用率基本保存不變,而POLL模型主函數(shù)調(diào)用率由12.11%上升至64.65%,讀寫操作分別由36.93%、48.15%降低至3.73%、4.87%,說明EPOLL傳輸穩(wěn)定性更強(qiáng)。由于視頻監(jiān)控系統(tǒng)的傳輸數(shù)據(jù)大,且面向多用戶連接的網(wǎng)絡(luò)通信,所以EPOLL架構(gòu)來實(shí)現(xiàn)視頻監(jiān)控系統(tǒng)是合理的,相對于其他模型,該模型傳輸效率更高,穩(wěn)定性更好。
本文客戶端使用Intel-i5處理器,采用通信子系統(tǒng)和顯示子系統(tǒng)設(shè)計(jì)方法進(jìn)行搭建。服務(wù)端分別使用Intel-i5、ARM9、ARM11設(shè)備,采用圖像采集子系統(tǒng)和傳輸子系統(tǒng)設(shè)計(jì)方法進(jìn)行搭建。通信效果如圖9所示。
圖9 EPOLL架構(gòu)視頻監(jiān)控系統(tǒng)
本文針對大數(shù)據(jù)量的視頻采集傳輸研究高效的實(shí)時傳輸方案。通過對傳統(tǒng)EPOLL模型進(jìn)行優(yōu)化,實(shí)現(xiàn)在Intel、ARM架構(gòu)下的攝像頭數(shù)據(jù)采集,并通過網(wǎng)絡(luò)進(jìn)行圖像的顯示。
實(shí)驗(yàn)表明,采用單線程網(wǎng)絡(luò)服務(wù)器進(jìn)行單Byte數(shù)據(jù)交互時,阻塞I/O對單線程短連接傳輸效率高。采用大數(shù)據(jù)長連接交互時,EPOLL模型函數(shù)調(diào)用率基本保持不變,POLL模型主函數(shù)調(diào)用率上升52.54%,讀寫操作分別降低33.2%、43.28%。說明EPOLL模型架構(gòu)傳輸效率優(yōu)于POLL模型,該機(jī)制制作視頻監(jiān)控系統(tǒng)的傳輸效率更高,穩(wěn)定性更好,適用性強(qiáng)。
本文提出的基于EPOLL機(jī)制應(yīng)用通過實(shí)驗(yàn)數(shù)據(jù)得出,EPOLL模型傳輸效率相比POLL、SELECT和阻塞I/O傳輸效率都要好,傳輸質(zhì)量高,可應(yīng)用于實(shí)時視頻采集、視頻監(jiān)控等場景。