凌家良,卓桂成,陳中魁,謝朝德
(惠州學院 電子科學系,廣東 惠州 516015)
系統硬件方面由以三星公司的S3C2440微處理器[1]為核心的主控制板、攝像頭采集模塊、無線WIFI網卡模塊、PC終端監控接收模塊組成.軟件方面由Linux內核、攝像頭與無線網卡驅動、無線WIFI網卡控制管理程序、視頻接發送處理程序等組成. 系統整體結構如圖1所示.

圖1 系統整體框圖
主控制板上圖像采集程序模塊啟動后,攝像頭對圖像進行采集,并通過攝像頭中的特定芯片對圖片進行JPEG壓縮和處理,采集到的數據通過USB接口發送到主控制板上,主控制板上運行的特定程序對接收到的數據進行處理,當用戶需要進行視頻監控時,主控制板執行圖像的發送程序,通過無線網卡將圖像發送出去,最后我們可以在局域網內或互聯網終端上的瀏覽器上輸入主控制板上視頻服務器的地址,即可以顯示實時的監控畫面.

圖2 主控制板電路
Linux 操作系統平臺的應用開發環境一般由目標機(開發板)和宿主機(PC 機)構成.目標板上用到的操作系統內核、根文件系統、應用軟件等都需要通過宿主機(PC 機)來完成.
(1)引導裝載程序 Bootloader 的移植.
Bootloader是嵌入式操作系統上電后最先執行的一小段程序,主要完成對整個系統硬件初始化設置,完成內存空間映射表的建立,微調用操作系統內核設置正確的環境等操作后,實現對操作系統的加載,具體步驟如下.將supervivi.bin拷貝至/tftpboot/
在終端SecureCRT中依次輸入:
tftp 0x30008000 supervivi.bin
nand erase 0 0x60000
nand write 0x30008000 0 0x60000
將程序燒寫到地址02x30008000后,再擦除nand flash 0~0x60000地址的數據,最后將0x30008000后的數據寫在地址0~0x60000內.
(2)Linux 內核的移植.
對內核的移植工作主要是修改與硬件平臺相關的代碼[2].本系統使用的 Linux 內核版本為 2.6.32的zImage,步驟如下:
將 zImage_x35拷貝至/tftpboot/
在終端SecureCRT中依次輸入:
tftp 0x30008000 zImage_x35
nand erase 60000 500000
nand write 0x30008000 0x60000 0x500000
將內核程序燒寫到地址02x30008000后,再擦除nand flash 0x60000~0x500000地址的數據,最后將0x30008000后的數據寫在地址0x60000~0x500000內.
根文件系統掛載地方的不同,可以分為NFS根文件系統和YAFFS根文件系統,前者是文件系統之上的一個網絡抽象,用來允許遠程客戶端與本地文件系統通過網絡進行訪問.后者是專門為NAND Flash存儲器設計的,適用于大容量的存儲設備的嵌入式文件系統.YAFFS讓嵌入式設備有能力脫離主機獨立運行.將內核與根文件系統所生成的映像文件下載到主控制板后,啟動系統.
(3)提供數據壓縮用的函數庫zlib的移植.
解壓zlib-1.2.5.tar.gz
#tar -xzvf zlib-1.2.5.tar.gz
進入源文件目錄
#cd zlib-1.2.5
運行configure配置makefile
#./configure --prefix=/mnt/video/ffmpeg
#make
#make install
(4)H264編碼器x264的移植.
因為編譯FFMPEG時需要添加對x264的支持[3-4],所以要先編譯好x264,以便讓編譯ffmpeg時能夠找到它.
解壓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
視頻監控系統服務器端的主要功能是利用 Linux 系統中的 V4L2 視頻設備編程接口來實現對視頻數據的采集,利用FFMPEG開源軟件轉換視頻數據幀為YUV格式,使得x264可以進行H.264壓縮編碼,再利用基于UDP協議的 SOCKET套接字進行傳輸發送至客戶端,客戶端接收數據進行解碼并利用X Windows位圖顯示的視窗系統實現本地回放顯示[5].
(1) 視頻數據的采集技術.視頻采集都是圍繞 V4L2定義的幾種重要數據結構實現的,完成基于V4L2 的USB視頻采集,就要獲得相關的視頻采集設備的信息和圖像信息,并對采集窗口、幀狀態初始化,然后才能進行視頻的采集工作.
在視頻采集中,應用程序首先通過int fd=open(/dev/video0 ,O_RDWR)函數,打開視頻采集設備并返回一個文件描述符號 fd,而這個文件描述符就代表被打開的視頻采集設備.在打開設備后,通過ioctl()函數,獲取視頻采集設備的相關信息,然后將獲取的視頻采集設備的信息放到結構體struct v4l2_capability中.最后,可以通過 close()函數,實現視頻采集設備的關閉.
(2) 視頻數據的轉換技術.本設計的USB攝像頭采集的數據幀的格式為YUYV(4:2:2),而要進行H264壓縮編碼,輸入格式必須為YUV(4:2:0),所以要對數據幀進行格式轉換.其中我們要運用到FFMPEG軟件中swscale函數庫的三個函數sws_getContext()、sws_scale()、sws_freeContext().
三個函數在轉換過程中起到主要作用,sws_getContext()函數進行初始化確立原始的數據幀格式、圖像高度和寬度,還有要轉換成的數據格式、圖像高度和寬度,sws_scale() 函數起到數據幀轉換的主要作用,通過這個函數可以獲得目標的數據幀格式,sws_freeContext() 函數是在結束數據采集時用來結束格式轉換.
(3)視頻數據的壓縮技術.x264是一個開源代碼視頻編碼器,在壓縮之前,需要對編碼器設置必要的參數, 比如param_default_preset(&ctx->param, "fast", "zerolatency"),接下來函數x264_encoder_open{}會檢查編碼參數是否合法,通過x264_encoder_encode (h,&nal,&i_nal,pic,&pic_out)對視頻幀進行編碼,最后,x264_encoder_close()結束編碼,釋放內存.
(4) 視頻數據的傳輸技術.經過壓縮編碼后,要完成 UDP/IP 的封裝.通過創建數據報套接字類型.
int socket = socket(AF_INET, SOCK_DGRAM, 0),設置為基于UDP的數據傳輸,通過struct sockaddr_in設置服務端.
sockaddr_in_family=AF_INET; // 協議類型是INET
sockaddr_in.s_addr=htonl(INADDR_ANY); // 本機
sockaddr_in.sin_port=htons(PORT); // 綁定端口
最后一步是 Sendto()函數的調用.視頻監控前端通過調用Sendto()函數發送目標視頻圖像數據,通過網絡信道,傳輸數據到視頻監控終端,視頻監控終端通過接收函數 recvfrom()接收視頻圖像數據.
(1) 視頻數據的接收.通過創建套接字int socket = socket(AF_INET, SOCK_DGRAM, 0)設置為基于UDP的數據傳輸,通過struct sockaddr_in設置客戶端.
sin.sin_family = AF_INET; // 協議類型是INET
sin.sin_port = htons(RECV_PORT);// 服務器端口
sin.sin_addr.s_addr = inet_addr("127.0.0.1");
調用bind的函數bind(sock, (sockaddr*)&sin, sizeof(sin)之后,該套接字sock與一個相應的地址關聯,發送到這個地址的數據可以通過這個套接字來讀取與使用.最后,視頻監控終端就可以調用數據接收函數 recvfrom 接收視頻數據.
(2) 視頻數據的實時顯示.利用針對X圖像處理開發的擴展庫MIT-SHM,可以使用共享的內存來存儲XImage結構,一幅存儲在共享內存中的圖像文件可被多個任務同時訪問[6-7].圖像數據在傳遞或被其他進程訪問時,不需作拷貝操作,只需要傳遞這個XImage的數據指針.
建立并使用一個基于共享內存的XImage分為以下幾個步驟.
建立一個共享內存段:
用XShmCreateImage()建立一個shared Image結構. XShmCreateImage(Display display, visual*visual, unsigned int depth, unsigned int width, unsigned int height, int format, char*data, XShmSegmentInfo*shminfo).
Shminfo指向一個XShmSegmentInfo結構,用來通知該內存段的信息.
調用XShmPutImage()在X Windows顯示圖像,調用的接口如下:
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).
最后調用XShmDestroyImage()釋放圖像資源.
本系統實現了對攝像頭圖像數據的采集,通過H264的壓縮編碼,減小數據的大小,通過無線WIFI網絡實現了無線數據的傳輸,最后在監控端成功地播放攝像頭采集的視頻數據,如圖3所示.

圖3 客戶端顯示無線視頻數據
但是,系統還存在著一些問題,比如圖像傳輸速率不足,視頻播放存在延時.另外,后續改進將增加相關傳感器,如人體紅外傳感器和煙霧傳感器等,提供外部傳感器信號觸發攝像頭自動開啟工作,以實現真正意義的家用實時無線視頻監控.
參考文獻:
[1]吳君欽,宋健,劉昊.基于S3C6410和ADV7180的嵌入式視頻采集系統設計與實現[J].計算機工程與科學,2012(12).
[2]孫天澤.嵌入式設計及Linux驅動開發指南[M].北京:電子工業出版社,2007.
[3]毛劍飛,張杰,蔣莉.基于改進的H.264的視頻監控系統[J].計算機系統應用,2014(04).
[4]江俊杰,王志明.基于X264的嵌入式視頻監控系統設計[J].計算機工程與設計,2013(12).
[5]周若谷,丁峰,魯力.視頻監控系統中嵌入式Web服務器的設計與實現[J].計算機科學,2011(05).
[6]顏珂斐.嵌入式智能視頻監控報警系統設計[J].實驗技術與管理,2014(02).
[7]李威,田聯房,李向陽.嵌入式網絡視頻監控系統的硬件設計與實現[J].微計算機信息,2010(08).