基于ARM11的無線視頻
發(fā)送端主要過程如下:
(1)創(chuàng)建RTP 會話并設(shè)置目標(biāo)地址。調(diào)用Create方法得到RTP 會話實例,然后調(diào)用AddDestination 方法設(shè)置目標(biāo)IP 以及目標(biāo)端口號。
(2)獲得數(shù)據(jù),調(diào)用Get_Data()函數(shù)得到。
(3)發(fā)送數(shù)據(jù),通過SendPacket()方法實現(xiàn)。
接收端主要過程如下:
(1)創(chuàng)建RTP 會話。調(diào)用Create 方法來創(chuàng)建一個會話實例,并且在創(chuàng)建會話的同時設(shè)置端口號,要與發(fā)送端的端口號保持一致。
(2)接受RTP 數(shù)據(jù)。調(diào)用RTPSession 類的PollData()方法接收數(shù)據(jù)。
(3)保存RTP 數(shù)據(jù)報。通過創(chuàng)建了一個指針數(shù)組,里面存放的是RTP 數(shù)據(jù)報的指針,只要將剛接收到RTP 數(shù)據(jù)報的指針賦給這個指針數(shù)組即可,這樣可以節(jié)省數(shù)據(jù)拷貝的時間。
(4)判斷是否接收完成,如果沒有,則跳轉(zhuǎn)到第b 步,否則接收端程序退出。
4.2 視頻數(shù)據(jù)的解碼和顯示
由于接收到的數(shù)據(jù)是經(jīng)H264 編碼的數(shù)據(jù),因此,先要對該數(shù)據(jù)進行解碼,然后才能顯示。而在服務(wù)器端,對視頻數(shù)據(jù)解碼用到FFmpeg.FFmpeg 是一個開源免費跨平臺的視頻和音頻流方案,屬于自由軟件。
解碼時主要涉及FFmpeg 下的libavcodec 庫、libswscale庫和libavformat 庫,其中第一個庫是一個包含了所有FFmpeg 音視頻編解碼器的庫,第二個庫是格式轉(zhuǎn)化庫,因為解碼后的數(shù)據(jù)是YUV420 格式,而要在計算機上顯示該數(shù)據(jù),則需要的是RGB 格式的,該庫功能就是把YUV420 格式轉(zhuǎn)化成RGB 格式,第三個庫是一個包含了所有的普通音視格式的解析器和產(chǎn)生器的庫。
4.2.1 初始化解碼線程
(1) 注冊全部的文件格式和編解碼器,調(diào)用av_register_all()函數(shù)完成注冊。
(2) 設(shè)置AVFormatContext 結(jié)構(gòu)體。該結(jié)構(gòu)體是FFmpeg 格式轉(zhuǎn)換過程中實現(xiàn)輸入和輸出功能,保存相關(guān)數(shù)據(jù)的主要結(jié)構(gòu),通過av_open_input_file 函數(shù)設(shè)置該結(jié)構(gòu)體。
(3) 檢查視頻流的信息,通過調(diào)用av_find_stream_info(pFormatCtx)函數(shù),pFormatCtx->streams 就填充了正確的視頻流信息,pFormatCtx 類型是AVFormatContext.
(4) 得到編解碼器上下文,pCodecCtx= pFormatCtx -> streams[videoStream]->codec,pCodecCtx 指針指向了流中所使用的關(guān)于編解碼器的所有信息。
(5) 打開解碼器,先通過avcodec_find_decoder 函數(shù)找到相應(yīng)解碼器,然后調(diào)用avcodec_open 函數(shù)打開解碼器。
(6) 申請內(nèi)存用來存放解碼數(shù)據(jù), 通過調(diào)用avcodec_alloc_frame 函數(shù)實現(xiàn),由于解碼的數(shù)據(jù)是YUV420 格式的,因此還需要將該數(shù)據(jù)轉(zhuǎn)換成RGB 格式,因此,再次調(diào)用avcodec_alloc_frame 申請內(nèi)存用來存放RGB 格式數(shù)據(jù)。
(7) 申請內(nèi)存用來存放原始數(shù)據(jù),因為H264 解碼時,對于P 幀需要參考前面一個關(guān)鍵幀或P 幀,而B幀需要參考前后幀,因此需要存放原始數(shù)據(jù),首先,用avpicture_get_size 來獲得需要的大小,然后調(diào)用av_malloc 函數(shù)申請內(nèi)存空間。
(8) 通過調(diào)用avpicture_fill 函數(shù)將幀和新申請的內(nèi)存結(jié)合起來。
(9) 創(chuàng)建格式轉(zhuǎn)換上下文,通過img_convert_ctx=sws _getContext(src_w, src_h,src_pix_fmt, dst_w, dst_h,PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL,NULL)方法實現(xiàn)。其中,src_w 表示源圖像的寬度,src_h 表示源圖像的高度,src_pix_fmt 表示源圖像的格式,dst_w 表示目標(biāo)圖像的寬度,dst_h 表示目標(biāo)圖像的高度,PIX_FMT_RGB24 表示目標(biāo)圖像的格式。
4.2.2 對數(shù)據(jù)進行H264 解碼
(1) 獲得需要解碼的一幀數(shù)據(jù),由于前面接收端線程已經(jīng)把接收到的數(shù)據(jù)存放在一個指針數(shù)組中,因此,解碼線程只需要從指針數(shù)據(jù)中獲取數(shù)據(jù)即可。
(2) 解碼數(shù)據(jù)。調(diào)用解碼函數(shù)avcodec_ decode_video(pCodecCtx , pFrame , finished , encodedData,size)來解碼視頻文件。其中,參數(shù)pCodecCtx是前面得到視頻流編碼上下文的指針;參數(shù)pFrame存儲解碼后的圖片的位置,參數(shù)finished 用來記錄已完成的幀數(shù);參數(shù)encodedData 是輸入緩沖區(qū)指針,指向要解碼的原始數(shù)據(jù);參數(shù)size 是輸入緩沖區(qū)的大小。
(3) 將已解碼的視頻數(shù)據(jù)YUV420 格式轉(zhuǎn)換成RGB 格式,通過調(diào)用sws_scale()函數(shù)實現(xiàn)格式轉(zhuǎn)換。
4.2.3 視頻數(shù)據(jù)的顯示
本系統(tǒng)使用QT 下的QImage 顯示視頻數(shù)據(jù),由于QImage 能夠存取單個像素,這樣在顯示前一幀圖像的時候,將該圖像保存下來,當(dāng)顯示后一幀圖像的時候,如果該像素值與前一幀相同,則不必修改該值,從而節(jié)省了大量的時間,即哪里變修改哪里,顯示過程的具體步驟如下:
(1) 取得已解碼的視頻數(shù)據(jù),且該數(shù)據(jù)是RGB 格式的。
(2) 循環(huán)取得視頻數(shù)據(jù)的R 分量、G 分量、B 分量。
(3) 判斷該點的像素值是否與前一幀對應(yīng)位置的像素值相同,若相同,跳轉(zhuǎn)到第2 步,否則,保存該像素值。
(4) 對取得的RGB 各自分量,構(gòu)造該像素點的顏色值,通過調(diào)用qRGB(R,G,B)構(gòu)造方法實現(xiàn)。
(5) 設(shè)置相應(yīng)點的像素值,首先生成QImage 類的對象,然后調(diào)用該類的setPixel(x,y,rgb)。其中,x 是圖像的x 坐標(biāo)值,y 是圖像的y 坐標(biāo)值,rgb 是該點的顏色值。
(6) 顯示圖像,通過調(diào)用update()方法,該方法會觸發(fā)繪畫事件,因此,在繪畫事件里,寫入顯示圖像代碼,即可顯示剛生成的QImage 對象,通過調(diào)用drawImage()方法繪制圖像。
5 結(jié)論
本系統(tǒng)在視頻圖像采集時,為了降低數(shù)據(jù)量,采用YUV420 的采樣格式。視頻數(shù)據(jù)編碼采用H264 硬編碼方式,極大地提高了編碼速度。而在無線網(wǎng)絡(luò)傳輸時,考慮到丟包問題,將編碼數(shù)據(jù)進行拆包然后發(fā)送,降低了丟包率。經(jīng)測試,本系統(tǒng)采集一幅OV9650攝像頭拍攝的且分辨率為320X240 的圖像,經(jīng)H264硬編碼,編碼后的圖像數(shù)據(jù)大致為5KB 左右,降低了數(shù)據(jù)傳輸量,并且硬編碼每秒可編碼25 幀圖像數(shù)據(jù),達到實時視頻數(shù)據(jù)編碼的要求。對于WI-FI 無線網(wǎng)絡(luò)的傳輸率一般在11-54Mbps 左右,因此,該無線網(wǎng)絡(luò)可以滿足實時傳輸視頻的需求。本系統(tǒng)構(gòu)建了高實時性,低成本,低功耗的數(shù)字化無線視頻監(jiān)控平臺,在該平臺基礎(chǔ)上,可以搭建各種各樣的應(yīng)用,比如,路況實時監(jiān)控,人臉識別,倉庫報警等應(yīng)用,該系統(tǒng)具有一定的實用價值。
評論