凌家良,卓桂成,陳中魁,謝朝德
(惠州學(xué)院 電子科學(xué)系,廣東 惠州 516015)
系統(tǒng)硬件方面由以三星公司的S3C2440微處理器[1]為核心的主控制板、攝像頭采集模塊、無(wú)線WIFI網(wǎng)卡模塊、PC終端監(jiān)控接收模塊組成.軟件方面由Linux內(nèi)核、攝像頭與無(wú)線網(wǎng)卡驅(qū)動(dòng)、無(wú)線WIFI網(wǎng)卡控制管理程序、視頻接發(fā)送處理程序等組成. 系統(tǒng)整體結(jié)構(gòu)如圖1所示.
圖1 系統(tǒng)整體框圖
主控制板上圖像采集程序模塊啟動(dòng)后,攝像頭對(duì)圖像進(jìn)行采集,并通過攝像頭中的特定芯片對(duì)圖片進(jìn)行JPEG壓縮和處理,采集到的數(shù)據(jù)通過USB接口發(fā)送到主控制板上,主控制板上運(yùn)行的特定程序?qū)邮盏降臄?shù)據(jù)進(jìn)行處理,當(dāng)用戶需要進(jìn)行視頻監(jiān)控時(shí),主控制板執(zhí)行圖像的發(fā)送程序,通過無(wú)線網(wǎng)卡將圖像發(fā)送出去,最后我們可以在局域網(wǎng)內(nèi)或互聯(lián)網(wǎng)終端上的瀏覽器上輸入主控制板上視頻服務(wù)器的地址,即可以顯示實(shí)時(shí)的監(jiān)控畫面.
圖2 主控制板電路
Linux 操作系統(tǒng)平臺(tái)的應(yīng)用開發(fā)環(huán)境一般由目標(biāo)機(jī)(開發(fā)板)和宿主機(jī)(PC 機(jī))構(gòu)成.目標(biāo)板上用到的操作系統(tǒng)內(nèi)核、根文件系統(tǒng)、應(yīng)用軟件等都需要通過宿主機(jī)(PC 機(jī))來(lái)完成.
(1)引導(dǎo)裝載程序 Bootloader 的移植.
Bootloader是嵌入式操作系統(tǒng)上電后最先執(zhí)行的一小段程序,主要完成對(duì)整個(gè)系統(tǒng)硬件初始化設(shè)置,完成內(nèi)存空間映射表的建立,微調(diào)用操作系統(tǒng)內(nèi)核設(shè)置正確的環(huán)境等操作后,實(shí)現(xiàn)對(duì)操作系統(tǒng)的加載,具體步驟如下.將supervivi.bin拷貝至/tftpboot/
在終端SecureCRT中依次輸入:
tftp 0x30008000 supervivi.bin
nand erase 0 0x60000
nand write 0x30008000 0 0x60000
將程序燒寫到地址02x30008000后,再擦除nand flash 0~0x60000地址的數(shù)據(jù),最后將0x30008000后的數(shù)據(jù)寫在地址0~0x60000內(nèi).
(2)Linux 內(nèi)核的移植.
對(duì)內(nèi)核的移植工作主要是修改與硬件平臺(tái)相關(guān)的代碼[2].本系統(tǒng)使用的 Linux 內(nèi)核版本為 2.6.32的zImage,步驟如下:
將 zImage_x35拷貝至/tftpboot/
在終端SecureCRT中依次輸入:
tftp 0x30008000 zImage_x35
nand erase 60000 500000
nand write 0x30008000 0x60000 0x500000
將內(nèi)核程序燒寫到地址02x30008000后,再擦除nand flash 0x60000~0x500000地址的數(shù)據(jù),最后將0x30008000后的數(shù)據(jù)寫在地址0x60000~0x500000內(nèi).
根文件系統(tǒng)掛載地方的不同,可以分為NFS根文件系統(tǒng)和YAFFS根文件系統(tǒng),前者是文件系統(tǒng)之上的一個(gè)網(wǎng)絡(luò)抽象,用來(lái)允許遠(yuǎn)程客戶端與本地文件系統(tǒng)通過網(wǎng)絡(luò)進(jìn)行訪問.后者是專門為NAND Flash存儲(chǔ)器設(shè)計(jì)的,適用于大容量的存儲(chǔ)設(shè)備的嵌入式文件系統(tǒng).YAFFS讓嵌入式設(shè)備有能力脫離主機(jī)獨(dú)立運(yùn)行.將內(nèi)核與根文件系統(tǒng)所生成的映像文件下載到主控制板后,啟動(dòng)系統(tǒng).
(3)提供數(shù)據(jù)壓縮用的函數(shù)庫(kù)zlib的移植.
解壓zlib-1.2.5.tar.gz
#tar -xzvf zlib-1.2.5.tar.gz
進(jìn)入源文件目錄
#cd zlib-1.2.5
運(yùn)行configure配置makefile
#./configure --prefix=/mnt/video/ffmpeg
#make
#make install
(4)H264編碼器x264的移植.
因?yàn)榫幾gFFMPEG時(shí)需要添加對(duì)x264的支持[3-4],所以要先編譯好x264,以便讓編譯ffmpeg時(shí)能夠找到它.
解壓last_x264.tar.bz2
#tar -xvzf last_x264.tar.bz2(先用bzip解壓,而后tar)
#cd x264-snapshot-20120316-2245
#./configure --host=arm-linux --prefix=/mnt/video/ffmpeg --enable-shared --disable-asm
#make
#make install
(5)視頻和音頻流方案FFmpeg的移植.
解壓ffmpeg-1.0.tar.gz
#tar -xzvf ffmpeg-1.0.tar.gz
#cd ffmpeg-1.0
#./configure --enable-cross-compile --target-os=linux --cross-prefix=arm-linux- --cc=arm-linux-gcc --enable-shared --arch=armv6 --enable-gpl --enable-libx264 --prefix=/opt/webcam/ffmpeg --extra-cflags=-I/mnt/video/x264/include --extra-ldflags=-L/mnt/video/x264/lib/
#make
#make install
視頻監(jiān)控系統(tǒng)服務(wù)器端的主要功能是利用 Linux 系統(tǒng)中的 V4L2 視頻設(shè)備編程接口來(lái)實(shí)現(xiàn)對(duì)視頻數(shù)據(jù)的采集,利用FFMPEG開源軟件轉(zhuǎn)換視頻數(shù)據(jù)幀為YUV格式,使得x264可以進(jìn)行H.264壓縮編碼,再利用基于UDP協(xié)議的 SOCKET套接字進(jìn)行傳輸發(fā)送至客戶端,客戶端接收數(shù)據(jù)進(jìn)行解碼并利用X Windows位圖顯示的視窗系統(tǒng)實(shí)現(xiàn)本地回放顯示[5].
(1) 視頻數(shù)據(jù)的采集技術(shù).視頻采集都是圍繞 V4L2定義的幾種重要數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)的,完成基于V4L2 的USB視頻采集,就要獲得相關(guān)的視頻采集設(shè)備的信息和圖像信息,并對(duì)采集窗口、幀狀態(tài)初始化,然后才能進(jìn)行視頻的采集工作.
在視頻采集中,應(yīng)用程序首先通過int fd=open(/dev/video0 ,O_RDWR)函數(shù),打開視頻采集設(shè)備并返回一個(gè)文件描述符號(hào) fd,而這個(gè)文件描述符就代表被打開的視頻采集設(shè)備.在打開設(shè)備后,通過ioctl()函數(shù),獲取視頻采集設(shè)備的相關(guān)信息,然后將獲取的視頻采集設(shè)備的信息放到結(jié)構(gòu)體struct v4l2_capability中.最后,可以通過 close()函數(shù),實(shí)現(xiàn)視頻采集設(shè)備的關(guān)閉.
(2) 視頻數(shù)據(jù)的轉(zhuǎn)換技術(shù).本設(shè)計(jì)的USB攝像頭采集的數(shù)據(jù)幀的格式為YUYV(4:2:2),而要進(jìn)行H264壓縮編碼,輸入格式必須為YUV(4:2:0),所以要對(duì)數(shù)據(jù)幀進(jìn)行格式轉(zhuǎn)換.其中我們要運(yùn)用到FFMPEG軟件中swscale函數(shù)庫(kù)的三個(gè)函數(shù)sws_getContext()、sws_scale()、sws_freeContext().
三個(gè)函數(shù)在轉(zhuǎn)換過程中起到主要作用,sws_getContext()函數(shù)進(jìn)行初始化確立原始的數(shù)據(jù)幀格式、圖像高度和寬度,還有要轉(zhuǎn)換成的數(shù)據(jù)格式、圖像高度和寬度,sws_scale() 函數(shù)起到數(shù)據(jù)幀轉(zhuǎn)換的主要作用,通過這個(gè)函數(shù)可以獲得目標(biāo)的數(shù)據(jù)幀格式,sws_freeContext() 函數(shù)是在結(jié)束數(shù)據(jù)采集時(shí)用來(lái)結(jié)束格式轉(zhuǎn)換.
(3)視頻數(shù)據(jù)的壓縮技術(shù).x264是一個(gè)開源代碼視頻編碼器,在壓縮之前,需要對(duì)編碼器設(shè)置必要的參數(shù), 比如param_default_preset(&ctx->param, "fast", "zerolatency"),接下來(lái)函數(shù)x264_encoder_open{}會(huì)檢查編碼參數(shù)是否合法,通過x264_encoder_encode (h,&nal,&i_nal,pic,&pic_out)對(duì)視頻幀進(jìn)行編碼,最后,x264_encoder_close()結(jié)束編碼,釋放內(nèi)存.
(4) 視頻數(shù)據(jù)的傳輸技術(shù).經(jīng)過壓縮編碼后,要完成 UDP/IP 的封裝.通過創(chuàng)建數(shù)據(jù)報(bào)套接字類型.
int socket = socket(AF_INET, SOCK_DGRAM, 0),設(shè)置為基于UDP的數(shù)據(jù)傳輸,通過struct sockaddr_in設(shè)置服務(wù)端.
sockaddr_in_family=AF_INET; // 協(xié)議類型是INET
sockaddr_in.s_addr=htonl(INADDR_ANY); // 本機(jī)
sockaddr_in.sin_port=htons(PORT); // 綁定端口
最后一步是 Sendto()函數(shù)的調(diào)用.視頻監(jiān)控前端通過調(diào)用Sendto()函數(shù)發(fā)送目標(biāo)視頻圖像數(shù)據(jù),通過網(wǎng)絡(luò)信道,傳輸數(shù)據(jù)到視頻監(jiān)控終端,視頻監(jiān)控終端通過接收函數(shù) recvfrom()接收視頻圖像數(shù)據(jù).
(1) 視頻數(shù)據(jù)的接收.通過創(chuàng)建套接字int socket = socket(AF_INET, SOCK_DGRAM, 0)設(shè)置為基于UDP的數(shù)據(jù)傳輸,通過struct sockaddr_in設(shè)置客戶端.
sin.sin_family = AF_INET; // 協(xié)議類型是INET
sin.sin_port = htons(RECV_PORT);// 服務(wù)器端口
sin.sin_addr.s_addr = inet_addr("127.0.0.1");
調(diào)用bind的函數(shù)bind(sock, (sockaddr*)&sin, sizeof(sin)之后,該套接字sock與一個(gè)相應(yīng)的地址關(guān)聯(lián),發(fā)送到這個(gè)地址的數(shù)據(jù)可以通過這個(gè)套接字來(lái)讀取與使用.最后,視頻監(jiān)控終端就可以調(diào)用數(shù)據(jù)接收函數(shù) recvfrom 接收視頻數(shù)據(jù).
(2) 視頻數(shù)據(jù)的實(shí)時(shí)顯示.利用針對(duì)X圖像處理開發(fā)的擴(kuò)展庫(kù)MIT-SHM,可以使用共享的內(nèi)存來(lái)存儲(chǔ)XImage結(jié)構(gòu),一幅存儲(chǔ)在共享內(nèi)存中的圖像文件可被多個(gè)任務(wù)同時(shí)訪問[6-7].圖像數(shù)據(jù)在傳遞或被其他進(jìn)程訪問時(shí),不需作拷貝操作,只需要傳遞這個(gè)XImage的數(shù)據(jù)指針.
建立并使用一個(gè)基于共享內(nèi)存的XImage分為以下幾個(gè)步驟.
建立一個(gè)共享內(nèi)存段:
用XShmCreateImage()建立一個(gè)shared Image結(jié)構(gòu). XShmCreateImage(Display display, visual*visual, unsigned int depth, unsigned int width, unsigned int height, int format, char*data, XShmSegmentInfo*shminfo).
Shminfo指向一個(gè)XShmSegmentInfo結(jié)構(gòu),用來(lái)通知該內(nèi)存段的信息.
調(diào)用XShmPutImage()在X Windows顯示圖像,調(diào)用的接口如下:
XShmPutImage(Display*display,Drawable d,GC gc,XImage *image,int src_x,int src_y,int width,int height,int dest x,int dest y,bool send event).
最后調(diào)用XShmDestroyImage()釋放圖像資源.
本系統(tǒng)實(shí)現(xiàn)了對(duì)攝像頭圖像數(shù)據(jù)的采集,通過H264的壓縮編碼,減小數(shù)據(jù)的大小,通過無(wú)線WIFI網(wǎng)絡(luò)實(shí)現(xiàn)了無(wú)線數(shù)據(jù)的傳輸,最后在監(jiān)控端成功地播放攝像頭采集的視頻數(shù)據(jù),如圖3所示.
圖3 客戶端顯示無(wú)線視頻數(shù)據(jù)
但是,系統(tǒng)還存在著一些問題,比如圖像傳輸速率不足,視頻播放存在延時(shí).另外,后續(xù)改進(jìn)將增加相關(guān)傳感器,如人體紅外傳感器和煙霧傳感器等,提供外部傳感器信號(hào)觸發(fā)攝像頭自動(dòng)開啟工作,以實(shí)現(xiàn)真正意義的家用實(shí)時(shí)無(wú)線視頻監(jiān)控.
參考文獻(xiàn):
[1]吳君欽,宋健,劉昊.基于S3C6410和ADV7180的嵌入式視頻采集系統(tǒng)設(shè)計(jì)與實(shí)現(xiàn)[J].計(jì)算機(jī)工程與科學(xué),2012(12).
[2]孫天澤.嵌入式設(shè)計(jì)及Linux驅(qū)動(dòng)開發(fā)指南[M].北京:電子工業(yè)出版社,2007.
[3]毛劍飛,張杰,蔣莉.基于改進(jìn)的H.264的視頻監(jiān)控系統(tǒng)[J].計(jì)算機(jī)系統(tǒng)應(yīng)用,2014(04).
[4]江俊杰,王志明.基于X264的嵌入式視頻監(jiān)控系統(tǒng)設(shè)計(jì)[J].計(jì)算機(jī)工程與設(shè)計(jì),2013(12).
[5]周若谷,丁峰,魯力.視頻監(jiān)控系統(tǒng)中嵌入式Web服務(wù)器的設(shè)計(jì)與實(shí)現(xiàn)[J].計(jì)算機(jī)科學(xué),2011(05).
[6]顏珂斐.嵌入式智能視頻監(jiān)控報(bào)警系統(tǒng)設(shè)計(jì)[J].實(shí)驗(yàn)技術(shù)與管理,2014(02).
[7]李威,田聯(lián)房,李向陽(yáng).嵌入式網(wǎng)絡(luò)視頻監(jiān)控系統(tǒng)的硬件設(shè)計(jì)與實(shí)現(xiàn)[J].微計(jì)算機(jī)信息,2010(08).