基于Qt的嵌入式媒體播放器系統(tǒng)的設(shè)計
1引言
隨著用戶要求的不斷提高,越來越多的嵌入式設(shè)備使用功能強(qiáng)大、價格低廉的嵌入式Linux作為操作系統(tǒng)并開始采用較為復(fù)雜的圖形用戶界面。Qt以其強(qiáng)大的功能、良好的可移植性逐漸成為一種被廣泛使用的GUI系統(tǒng)。正是由于嵌入式操作系統(tǒng)及其相應(yīng)圖形用戶界面的不斷發(fā)展,嵌入式軟件的開發(fā)顯得越來越重要。其中嵌入式媒體播放器由于能夠滿足人們的視聽享受已經(jīng)逐漸成為了系統(tǒng)中不可或缺的重要組成部分,在嵌入式系統(tǒng)上開發(fā)媒體播放器已經(jīng)成為了一個技術(shù)熱點,當(dāng)前許多嵌入式產(chǎn)品中都包含媒體播放器。因此在基于Qt的嵌入式系統(tǒng)中實現(xiàn)媒體播放器具有深刻的意義和實用價值。
2 嵌入式媒體播放器系統(tǒng)設(shè)計
2.1架構(gòu)設(shè)計
嵌入式媒體播放器架構(gòu)設(shè)計方案如圖1所示。通過使用純C++語言開發(fā)來支持嵌入式Linux系統(tǒng),采用Qt/Embedded作為GUI來提供強(qiáng)大的用戶界面,實現(xiàn)一個開放式的插件接口來增強(qiáng)擴(kuò)展性,利用內(nèi)核幀緩沖來輸出,消除對特定架構(gòu)的依賴,從而保證可移植性。媒體播放器屬于上層應(yīng)用程序,位于Linux用戶空間。這樣設(shè)計的目的是為了系統(tǒng)移植性。
圖形用戶界面窗口以Qt/Embedded為基礎(chǔ)開發(fā),通過調(diào)用Qt/Embedded提供的類庫根據(jù)需要設(shè)計可以管理多媒體文件的基本窗口,包括打開、刪除、顯示文件長度、顯示播放時間等窗口,以及為方便用戶設(shè)定的管理播放列表、進(jìn)行播放控制的窗口,這些都是直接和用戶打交道的。由于采用了Qt/Embedded作為GUI,移植性可以得到保證。
文件輸入主要是對用戶指定的文件進(jìn)行讀取和解析,將獲得的文件長度、播放時間、編碼格式、音視頻幀率、文件標(biāo)題等內(nèi)容,結(jié)合MIME的處理,顯示在預(yù)先設(shè)計的窗口中。
插件接口調(diào)用主要是把所有對解碼器的操作整合到一個統(tǒng)一的開放式接口當(dāng)中,根據(jù)上一部分解析出的文件信息去查找相應(yīng)的解碼器插件并調(diào)用,如果沒有找到可用的解碼器可以返回信息提醒用戶添加相應(yīng)的插件。通過實現(xiàn)這樣一個接口可以使播放器的擴(kuò)展性大大提高,因此本部分是媒體播放器的核心。
文件解碼和輸出主要負(fù)責(zé)通過調(diào)用解碼器對音視頻數(shù)據(jù)流進(jìn)行解碼,然后利用QT/Embedded可以直接操縱內(nèi)核幀緩沖FrameBuffer的特性,將解碼之后的數(shù)據(jù)通過FrameBuffer直接送到輸出設(shè)備輸出,避免對DirectShow、OpenGL等特定架構(gòu)的依賴,進(jìn)一步增強(qiáng)可移植性。
圖1 嵌入式媒體播放器的架構(gòu)
3 插件接口模塊和解碼庫模塊
3.1插件接口模塊設(shè)計
插件接口模塊是整個播放器的核心部分,它封裝了對具體解碼器的操作,從而在輸入和輸出模塊之間搭起一座橋梁,確保數(shù)據(jù)的正常流動。插件接口模塊主要提供了以下方法來控制解碼器:
1)文件支持性函數(shù) bool isFileSupported(const QString&filename);
通過檢查文件的擴(kuò)展名來確定待播放的文件是否被播放器支持,若是返回真,否則返回假??勺R別的擴(kuò)展名有asf、avi、dat、mp2、mp3、mpeg、mpg、ogg、wav等。如果添加了新的解碼器插件以后可以識別新的文件格式,只需要將其擴(kuò)展名添加到此函數(shù)的支持列表中[!--empirenews.page--]
2)獲取文件信息函數(shù) const QString& fileInfo();
用于獲得文件的各種信息并將結(jié)果保存在一個常量字符串中,便于其他函數(shù)調(diào)用。這些信息包括:播放時間、音頻格式、音頻比特率、音頻通道、音頻頻率、視頻格式、視頻比特率、視頻高度、視頻寬度等。
3)讀取音頻采樣函數(shù)
bool audioReadSamples(short* output , int channels, long samples, long& samplesRead, int);
調(diào)用解碼器對音頻采樣數(shù)據(jù)進(jìn)行讀取,是音頻數(shù)據(jù)處理的核心部分。output表示待輸出文件指針,channels表示通道數(shù),samples表示采樣數(shù),samplesRead表示待讀取采樣數(shù)
4)讀取視頻幀函數(shù)
bool videoReadScaledFrame(unsigned char** output_rows, int, int, int in_w, int in_h,int out_w,int out_h,ColorFormat fmt,int);
調(diào)用解碼器對視頻幀進(jìn)行讀取,是視頻數(shù)據(jù)處理的核心部分。參數(shù)output_rows表示輸出列地址的指針,in_w、in_h、out_w、out_h分別表示輸入和輸出幀數(shù)據(jù)的寬度和高度,fmt表示采用的色彩模式,返回值用來判斷執(zhí)行是否成功。
5)音視頻同步函數(shù)定義:int Sync(File*fp,int auIndex,struct timeval*vtime);
fp為打開的多媒體文件指針,vtime為當(dāng)前正在播放的視頻文件的幀頭中提取的時間, auIndex指出當(dāng)前的音頻幀計數(shù),即當(dāng)前播放到了第幾幀。通過這些參數(shù)就可以計算出希望跳到的幀數(shù)和當(dāng)前幀數(shù)的差值,然后根據(jù)這個差值將音頻流向前(滯后)或向后(超前)跳即可。同時Sync函數(shù)還會將此差值int反饋給音頻解碼器,讓音頻解碼器修正數(shù)據(jù)流的時間戳,如此循環(huán),從而達(dá)到較好的音視頻同步效果。此函數(shù)的總體思想是在播放視頻數(shù)據(jù)流的同時啟動另一線程,打開對應(yīng)的音頻數(shù)據(jù)流播放,然后在視頻線程中來同步音頻數(shù)據(jù)。
此外還有插件初始化和注冊函數(shù) void pluginInit()、文件初始化函數(shù) void fileInit()、查找函數(shù) bool seek(long pos)、清空視頻數(shù)據(jù)函數(shù)flushVideoPackets()和清空音頻數(shù)據(jù)函數(shù)flushAudioPackets()、獲取下一數(shù)據(jù)包函數(shù) MediaPacket*getAnotherPacket(int stream)等,不再做詳細(xì)介紹。
3.2解碼庫模塊
解碼庫模塊的主要作用是為插件接口模塊提供解碼器,考慮到播放器的可移植性和可擴(kuò)展性,本系統(tǒng)采用了ffmpeg解碼庫。FFmpeg解碼庫是Linux下的一個開源解碼器集合,它支持多種音頻和視頻編解碼標(biāo)準(zhǔn),還支持轉(zhuǎn)文件格式、制作avi等,功能十分強(qiáng)大??梢栽趙indows下使用的ffshow插件,linux下的mplayer播放器都是使用的ffmpeg解碼庫。
解碼庫又包含解碼器和分離器。解碼器就是對音視頻數(shù)據(jù)流進(jìn)行解碼的組件,分離器就是把文件流中的數(shù)據(jù)分離為音頻數(shù)據(jù)流和視頻數(shù)據(jù)流的組件,音頻數(shù)據(jù)和視頻數(shù)據(jù)是分開解碼的,所以二者缺一不可。
3 嵌入式媒體播放器系統(tǒng)實現(xiàn)
3.1 數(shù)據(jù)流程總體設(shè)計
圖2為系統(tǒng)數(shù)據(jù)流程:首先輸入模塊從數(shù)據(jù)源(多媒體文件)讀入數(shù)據(jù),此時它將讀入文件頭,做一些基本的處理,如讀出文件長度,獲取此文件的編碼類型、比特率,判斷能否播放等;然后插件接口模塊會調(diào)用分離器插件將多媒體數(shù)據(jù)切分為視頻數(shù)據(jù)流和音頻數(shù)據(jù)流;再經(jīng)過視頻FIFO和音頻FIFO,排序處理;最后送入視、音頻解碼器調(diào)用相應(yīng)的解碼器進(jìn)行解碼,對于音頻數(shù)據(jù)就會進(jìn)行重采樣,對于視頻數(shù)據(jù)就會讀取相應(yīng)的幀,逐幀解碼;之后經(jīng)過采樣的音頻數(shù)據(jù)和經(jīng)過渲染覆蓋的視頻數(shù)據(jù)先進(jìn)行音視頻同步,再分別通過視、音頻輸出模塊輸出。這其中,數(shù)據(jù)的讀入、分離、解碼、輸出都是通過Qt提供的類庫以多線程同時進(jìn)行的,在解碼得同時程序也在不斷將數(shù)據(jù)讀入緩沖區(qū)并排序等待處理,以提高效率。
輸入模塊的主要功能是將用戶指定的多媒體文件讀入。由于不同格式的多媒體文件需要調(diào)用不同的解碼器才能正常打開,因此考慮到程序的模塊化將實際的文件打開工作交給插件接口模塊調(diào)用相應(yīng)的解碼器進(jìn)行,輸入模塊只對文件進(jìn)行一些基本的處理并對文件內(nèi)容進(jìn)行緩存,然后為插件接口模塊輸送原始數(shù)據(jù)流。用戶首先通過圖形用戶界面選定待播放文件發(fā)出打開指令,這將會使輸入模塊接收到一個信號并通過用戶界面?zhèn)骰氐男畔@得待播放文件的文件路徑和文件名。接下來輸入模塊會檢查文件路徑是否合法、文件是否為空,之后會向插件接口模塊發(fā)出信號,通知插件接口模塊查找可用的解碼器,為文件解碼做好準(zhǔn)備。下一步就是進(jìn)行調(diào)用播放初始化函數(shù)init(),其具體過程下面會詳細(xì)介紹,最后就是將工作移交給插件接口模塊,讓它調(diào)用對應(yīng)文件格式的解碼器的open()函數(shù)。
輸出模塊的主要功能是將通過解碼器解碼之后的音頻、視頻數(shù)據(jù)送到輸出設(shè)備(如LCD顯示屏、揚聲器)輸出。根據(jù)輸出內(nèi)容的不同可以將輸出模塊劃分為音頻輸出和視頻輸出兩個子部分。這兩個部分基本上是相互獨立輸出的,通過插件接口模塊的同步控制讓它們在輸出時保持同步。視頻輸出和音頻輸出稍有不同,它利用Qt/Embedded可以直接控制FrameBuffer的特性來輸出視頻數(shù)據(jù)。幀緩沖區(qū)是顯卡上的內(nèi)存,使用幀緩沖區(qū)可以提高繪圖的速度和整體性能,與幀緩沖區(qū)有關(guān)的設(shè)備是/dev/fb0(主設(shè)備號29,次設(shè)備號0)。[!--empirenews.page--]
圖2 系統(tǒng)數(shù)據(jù)流程
4.2嵌入式音視頻同步設(shè)計
本方法的基本思想是以視頻流為主媒體流,音頻流為從媒體流,視頻的播放速率保持不變,根據(jù)本地系統(tǒng)時鐘確定的實際顯示時間,通過調(diào)整音頻播放速度來達(dá)到音視頻同步。整個系統(tǒng)的音視頻同步數(shù)據(jù)流程見圖3。首先選擇一個本地系統(tǒng)時鐘參考(LSCR),要求本地系統(tǒng)時鐘參考上的時間是線性遞增的。然后將LSCR分送到視頻解碼器和音頻解碼器,由這兩個解碼器根據(jù)各幀的PTS值對照本地系統(tǒng)時鐘參考產(chǎn)生各幀準(zhǔn)確的顯示或回放的時間。也就是說,生成輸出數(shù)據(jù)流時依據(jù)本地參考時鐘上的時間給每個數(shù)據(jù)塊都打上時間戳(一般包括開始時間和結(jié)束時間)。在播放時,讀取數(shù)據(jù)塊上的時間戳,同時根據(jù)本地系統(tǒng)時鐘參考上的時間來安排播放。
圖3 音視頻同步數(shù)據(jù)流程
基于時間戳的播放過程中,僅僅對早到的或晚到的數(shù)據(jù)塊進(jìn)行等待或快速處理,往往是不夠的。如果想要更加主動并且有效地調(diào)節(jié)播放性能,就需要引入反饋機(jī)制,也就是通過對比音視頻的時間戳將當(dāng)前數(shù)據(jù)流的播放狀態(tài)反饋給上層的“源”。如果音頻流滯后,就即時通知音頻解碼器加快音頻流輸出,但是如果滯后太多,則直接將當(dāng)前數(shù)據(jù)丟棄,直接跳到下一幀;如果視頻流滯后,就通知音頻解碼器減慢音頻輸出速度等待視頻流,如滯后太多也直接進(jìn)行跳幀。數(shù)據(jù)流首先通過分離器分解為視頻數(shù)據(jù)流和音頻數(shù)據(jù)流,然后經(jīng)過對應(yīng)的解碼器,同時由本地系統(tǒng)時鐘來進(jìn)行時間戳控制;獲得準(zhǔn)確顯示或回放時間以后進(jìn)行時間戳比較;若同步則直接輸出,不同步則進(jìn)行音頻跳幀或等待,直到同步后輸出。
5 總結(jié)
本文的創(chuàng)新點是系統(tǒng)具有很好的可移植性,它的實現(xiàn)過程以及核心的代碼對類似應(yīng)用具有很好的可重用性,只需通過較小的修改就能移植到不同的操作系統(tǒng)和平臺上,可以廣泛使用在各種嵌入式系統(tǒng)中,如PDA,智能手機(jī)等方面,具有較高的經(jīng)濟(jì)價值,同時也可以為開發(fā)其他嵌入式系統(tǒng)軟件提供參考意見;其次,本文圍繞用戶的基本需求,提出了一個基于嵌入式Linux操作系統(tǒng)和圖形用戶界面QT/Embedded的媒體播放器設(shè)計方案。該設(shè)計方案具有低耦合、高內(nèi)聚、可擴(kuò)展、可移植等良好特點,并在設(shè)計的基礎(chǔ)上將該方案實現(xiàn)。該媒體播放器支持編碼格式為MPEG-1、MPEG-2和MPEG-4的多媒體文件。同時具有存儲空間小,響應(yīng)速度快的性能特點,并支持播放控制、播放列表等功能,可自由切換中英文雙語界面,用戶可以選擇打開任意位置的文件。項目經(jīng)濟(jì)效益50萬元。