程偉倫,唐恒飛
(201600 上海市 上海工程技術(shù)大學(xué))
隨著汽車工業(yè)穩(wěn)步發(fā)展,汽車電子行業(yè)朝著信息化、媒體化方向轉(zhuǎn)變?;ヂ?lián)網(wǎng)技術(shù)的崛起、智能終端設(shè)備的良好應(yīng)用,人們對于車載多媒體設(shè)備的需求急劇增加,高性能的智能終端設(shè)備逐漸進入大眾視野。智能終端設(shè)備搭載流媒體技術(shù)可使音頻和視頻在網(wǎng)絡(luò)上快速傳播并且無需下載等待。在高性能嵌入式設(shè)備上搭載流媒體技術(shù),可以實現(xiàn)互聯(lián)網(wǎng)通訊技術(shù)在車載領(lǐng)域的完美應(yīng)用,研究和設(shè)計這樣一款集音視頻一體化車載媒體播放總成也因此具備了現(xiàn)實意義和科研價值。
在網(wǎng)絡(luò)流媒體的傳輸過程中,音頻流和視頻流常常混合在一起進行傳輸,這就要求在對流數(shù)據(jù)進行解封裝之后再進行解碼操作。本文主要基于開源多媒體處理工具FFmpeg 來實現(xiàn)音視頻的編解碼工作。FFmpeg 最早由Fabrice Bellard 發(fā)起,其支持的常見封裝格式有.mp4,.mp3,.flv,.avi 等,支持的常見傳輸協(xié)議有RTSP,RTMP,HTTP,RTP 等。FFmpeg 現(xiàn)如今幾乎包含了大部分音視頻編碼標(biāo)準(zhǔn),是音視頻開發(fā)工作者的重要工具。
用戶通過點擊已經(jīng)移植到嵌入式設(shè)備的Qt界面程序中的下拉按鈕,選擇想要觀看的電臺播放頻道,系統(tǒng)程序會自動加載rtmp 或rtsp 等網(wǎng)絡(luò)流媒體地址進行解析并向服務(wù)器發(fā)起請求,服務(wù)器接收到請求后將壓縮好的視頻文件下發(fā)給嵌入式客戶端。嵌入式客戶端接收到文件壓縮包后,音頻方面:由FFmpeg 完成一系列解封裝、解碼、音頻重采樣后,調(diào)用Qt 的QAudioOutput 類播放音頻;視頻方面:FFmpeg 完成一系列解封裝、解碼后,利用Qt 自帶的OpenGl 完成對視頻數(shù)據(jù)的著色與渲染,再調(diào)用自定義的MyVideoCall 完成對視頻畫面的不間斷更新。在音視頻同步處理方法方面,分析了3 種方案,選定以音頻時間戳為基準(zhǔn),視頻向音頻靠攏的方案。圖1 為整個車載終端音視頻功能的系統(tǒng)結(jié)構(gòu)框圖。
圖1 車載嵌入式流媒體終端的系統(tǒng)結(jié)構(gòu)框圖Fig.1 Block diagram of audio and video function system of vehicle terminal
由于嵌入式設(shè)備一般都小巧便攜,所以,其內(nèi)存資源往往有限。為了保證編碼質(zhì)量,本文在Windows 操作系統(tǒng)環(huán)境中完成軟件的編譯和運行,實現(xiàn)音視頻數(shù)據(jù)的讀取與轉(zhuǎn)換,然后將其移植到嵌入式設(shè)備中。圖2為媒體文件的解碼示意圖。FFmpeg 庫文件豐富,能夠完成解碼、編碼、轉(zhuǎn)碼、封裝、解封裝、濾波和播放等眾多功能。
根據(jù)圖2 的解碼流程圖,F(xiàn)Fmpeg 對流媒體文件的解碼過程可以通過以下幾步來詳細敘述:
圖2 媒體文件的解碼流程Fig.2 Decoding flow of media file
(1)初始化庫文件。首先通過函數(shù)av_register_all(),初始化libavformat 庫并注冊所有的編碼器、解碼器和協(xié)議。然后需要調(diào)用avformat_network_init()函數(shù),初始化網(wǎng)絡(luò)庫。注冊成功后,軟件就可以rtsp,rtmp,http 協(xié)議的流媒體視頻。
(2)文件讀取模塊。avformat_open_input 函數(shù)將探測傳入的流媒體地址或文件格式,并設(shè)置傳入?yún)?shù),打開數(shù)據(jù)流。
(3)獲取視頻流信息。avformat_find_stream_info 主要起到了讀入數(shù)據(jù)包(packets)的作用,然后從中提取出流的信息。這個函數(shù)不斷地更新流信息,而流信息主要是存放在AVStream這個結(jié)構(gòu)體中。而av_dump_format 函數(shù)將音視頻數(shù)據(jù)格式通過輸出到指定的文件或者控制臺,方便了解輸入的視音頻格式。
(4)查找解碼器。獲取流信息的過程中會找到解碼器的id。
(5)讀取數(shù)據(jù)幀。av_read_frame 函數(shù)用于讀取具體的音視頻幀數(shù)據(jù),在完成解碼操作之前,需調(diào)用av_read_frame()獲得視頻或音頻的壓縮數(shù)據(jù),對該函數(shù)的調(diào)用是多次的、頻繁的。
音頻數(shù)據(jù)解碼出來之后,它的格式一般是不能直接播放的。音頻重采樣就是將原始的音頻數(shù)據(jù)變換為新的樣本格式(sample format)、聲道格式(channel)、采樣頻率(sample rate)以適應(yīng)不同聲音播放的要求。首先,利用swr_alloc()函數(shù)創(chuàng)建一個名為SwrContext 的重采樣上下文結(jié)構(gòu)體,通過函數(shù)swr_alloc_set_opts()函數(shù)將所需要的參數(shù)填充進SwrContext 結(jié)構(gòu)體中。詳細代碼段如下并予以說明。
上述代碼段中,actx 即為實例化SwrContext結(jié)構(gòu)體,填充完必要的音頻參數(shù)后通過swr_init()初始化該結(jié)構(gòu)體。最后,利用swr_convert()函數(shù)完成每一幀的音頻重采樣工作。完成重采樣后,需釋放SwrContext 結(jié)構(gòu)體。完成音頻的解碼和重采樣步驟后,調(diào)用Qt 的QAudioOutput 類播放音頻即可。
由于FFmpeg 解碼的格式默認(rèn)是yuv 數(shù)據(jù),所以解碼后要將其轉(zhuǎn)換為RGB 數(shù)據(jù),此過程稱為轉(zhuǎn)碼。本文采用Qt 自帶的OpenGL 完成對yuv數(shù)據(jù)的轉(zhuǎn)碼與渲染。OpenGL 是可用于跨平臺的應(yīng)用程序API,其強大功能可繪制小到簡單圖形大到三維場景等一系列圖形界面。OpenGL 完成渲染工作依賴2 個重要的著色器(shader)即頂點著色器與紋理著色器。OpenGL 通過一個名為QGLShaderProgram 的對象來與著色器交互。著色器通過這個對象連接到OpenGL 應(yīng)用程序中。
OpenGL 視頻顯示的具體流程可簡述如下:使用initializeOpenGLFunctionst()函數(shù)初始化OpenGL 函數(shù)庫;使用QGLShaderProgram 類中的addShaderFromSourceCode 函數(shù)將創(chuàng)建的著色器添加進著色器程序中;再調(diào)用linkt()使著色器與著色器程序鏈接在一起;傳入已經(jīng)定義好的頂點坐標(biāo)與紋理坐標(biāo)并使之生效;使用glGenTexturest()為yuv 數(shù)據(jù)開辟紋理內(nèi)存;通過glBindTexturet()將開辟的紋理內(nèi)存指向的內(nèi)容與GL_TEXTURE_2D 綁定,即綁定成二維紋理;利用紋理過濾函數(shù)glTexParameterit(),將紋理像素映射成圖像像素,此處有多種過濾算法可以選擇,使用較多的是線性插值算法和鄰近插值算法。
流媒體數(shù)據(jù)經(jīng)過解碼后便得到了各自獨立的數(shù)據(jù),所以,音頻流和視頻流是獨自播放的。如何將音視頻流完美地流暢地輸送到用戶的聽覺感官與視覺感官,一直以來都是音視頻開發(fā)問題中的重點。諸如流媒體傳輸、可視對講、本地播放等眾多領(lǐng)域的廠商都對音視頻同步提出了嚴(yán)苛的要求。一旦解碼出的音頻流和視頻流播放同步有偏差,隨著時間的推移其異步性將越來越大。
常用的同步策略有:(1)視頻同步到音頻;(2)音頻同步到視頻;(3)設(shè)置參考時鐘,視頻和音頻以參考時鐘為標(biāo)準(zhǔn)。由于人耳對于聲音的辨別效果更為敏銳,所以,本文采用第一種同步策略將視頻同步到音頻上。音視頻同步流程如圖3 所示。
圖3 媒體文件的解碼流程Fig.3 Decoding flow of media file
具體軟件實現(xiàn)方法是將音頻時間戳設(shè)為同步時間的參考對象,如果當(dāng)前視頻播放快于同步時間,利用msleep()延遲刷新,反之則加快刷新速率。
軟件設(shè)計完成后在Win10 操作系統(tǒng)上測試,通過Visual Studio2017運行,運行畫面如圖4所示。流媒體地址以CCTV-7 軍事農(nóng)業(yè)rtmp 地址測試,測試地址為rtmp://58.200.131.2:1935/livetv/cctv7。經(jīng)過測試,視頻播放無花屏且?guī)瑪?shù)穩(wěn)定,無明顯的延遲或卡頓現(xiàn)象;音頻播放流暢,無音頻損壞現(xiàn)象;軟件啟動CPU 占用率低,無內(nèi)存泄漏現(xiàn)象;視音頻同步效果良好,基本符合用戶使用要求。
本文的目的在于研究并實現(xiàn)一款適用于車載的流媒體音視頻播放終端,為適應(yīng)相對便攜的嵌入式設(shè)備而采用FFmpeg 音視頻編解碼庫完成對流媒體數(shù)據(jù)的解碼播放。代碼復(fù)用性高,運行效果流暢,音頻播放完整,視頻渲染良好,對嵌入式系統(tǒng)的開發(fā)與應(yīng)用、音視頻編解碼的處理都有較好的導(dǎo)向與使用價值。