基于Qt的嵌入式媒體播放器系統(tǒng)的設計
2)獲取文件信息函數(shù) const QString fileInfo();
用于獲得文件的各種信息并將結果保存在一個常量字符串中,便于其他函數(shù)調(diào)用。這些信息包括:播放時間、音頻格式、音頻比特率、音頻通道、音頻頻率、視頻格式、視頻比特率、視頻高度、視頻寬度等。
3)讀取音頻采樣函數(shù)
bool audioReadSamples(short* output , int channels, long samples, long samplesRead, int);
調(diào)用解碼器對音頻采樣數(shù)據(jù)進行讀取,是音頻數(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)用解碼器對視頻幀進行讀取,是視頻數(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為當前正在播放的視頻文件的幀頭中提取的時間, auIndex指出當前的音頻幀計數(shù),即當前播放到了第幾幀。通過這些參數(shù)就可以計算出希望跳到的幀數(shù)和當前幀數(shù)的差值,然后根據(jù)這個差值將音頻流向前(滯后)或向后(超前)跳即可。同時Sync函數(shù)還會將此差值int反饋給音頻解碼器,讓音頻解碼器修正數(shù)據(jù)流的時間戳,如此循環(huán),從而達到較好的音視頻同步效果。此函數(shù)的總體思想是在播放視頻數(shù)據(jù)流的同時啟動另一線程,打開對應的音頻數(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)等,不再做詳細介紹。
3.2解碼庫模塊
解碼庫模塊的主要作用是為插件接口模塊提供解碼器,考慮到播放器的可移植性和可擴展性,本系統(tǒng)采用了ffmpeg解碼庫。FFmpeg解碼庫是Linux下的一個開源解碼器集合,它支持多種音頻和視頻編解碼標準,還支持轉(zhuǎn)文件格式、制作avi等,功能十分強大。可以在windows下使用的ffshow插件,linux下的mplayer播放器都是使用的ffmpeg解碼庫。
解碼庫又包含解碼器和分離器。解碼器就是對音視頻數(shù)據(jù)流進行解碼的組件,分離器就是把文件流中的數(shù)據(jù)分離為音頻數(shù)據(jù)流和視頻數(shù)據(jù)流的組件,音頻數(shù)據(jù)和視頻數(shù)據(jù)是分開解碼的,所以二者缺一不可。
3.1 數(shù)據(jù)流程總體設計
圖2為系統(tǒng)數(shù)據(jù)流程:首先輸入模塊從數(shù)據(jù)源(多媒體文件)讀入數(shù)據(jù),此時它將讀入文件頭,做一些基本的處理,如讀出文件長度,獲取此文件的編碼類型、比特率,判斷能否播放等;然后插件接口模塊會調(diào)用分離器插件將多媒體數(shù)據(jù)切分為視頻數(shù)據(jù)流和音頻數(shù)據(jù)流;再經(jīng)過視頻FIFO和音頻FIFO,排序處理;最后送入視、音頻解碼器調(diào)用相應的解碼器進行解碼,對于音頻數(shù)據(jù)就會進行重采樣,對于視頻數(shù)據(jù)就會讀取相應的幀,逐幀解碼;之后經(jīng)過采樣的音頻數(shù)據(jù)和經(jīng)過渲染覆蓋的視頻數(shù)據(jù)先進行音視頻同步,再分別通過視、音頻輸出模塊輸出。這其中,數(shù)據(jù)的讀入、分離、解碼、輸出都是通過Qt提供的類庫以多線程同時進行的,在解碼得同時程序也在不斷將數(shù)據(jù)讀入緩沖區(qū)并排序等待處理,以提高效率。
輸入模塊的主要功能是將用戶指定的多媒體文件讀入。由于不同格式的多媒體文件需要調(diào)用不同的解碼器才能正常打開,因此考慮到程序的模塊化將實際的文件打開工作交給插件接口模塊調(diào)用相應的解碼器進行,輸入模塊只對文件進行一些基本的處理并對文件內(nèi)容進行緩存,然后為插件接口模塊輸送原始數(shù)據(jù)流。用戶首先通過圖形用戶界面選定待播放文件發(fā)出打開指令,這將會使輸入模塊接收到一個信號并通過用戶界面?zhèn)骰氐男畔@得待播放文件的文件路徑和文件名。接下來輸入模塊會檢查文件路徑是否合法、文件是否為空,之后會向插件接口模塊發(fā)出信號,通知插件接口模塊查找可用的解碼器,為文件解碼做好準備。下一步就是進行調(diào)用播放初始化函數(shù)init(),其具體過程下面會詳細介紹,最后就是將工作移交給插件接口模塊,讓它調(diào)用對應文件格式的解碼器的open()函數(shù)。
輸出模塊的主要功能是將通過解碼器解碼之后的音頻、視頻數(shù)據(jù)送到輸出設備(如LCD顯示屏、揚聲器)輸出。根據(jù)輸出內(nèi)容的不同可以將輸出模塊劃分為音頻輸出和視頻輸出兩個子部分。這兩個部分基本上是相互獨立輸出的,通過插件接口模塊的同步控制讓它們在輸出時保持同步。視頻輸出和音頻輸出稍有不同,它利用Qt/Embedded可以直接控制FrameBuffer的特性來輸出視頻數(shù)據(jù)。幀緩沖區(qū)是顯卡上的內(nèi)存,使用幀緩沖區(qū)可以提高繪圖的速度和整體性能,與幀緩沖區(qū)有關的設備是/dev/fb0(主設備號29,次設備號0)。
linux操作系統(tǒng)文章專題:linux操作系統(tǒng)詳解(linux不再難懂)
評論