如果說一個人的力量有限,那麼網路的力量就是無窮的。研究H264的目的就是自己定製一個流媒體播放器,即時播放視頻。
好在網上牛人頗多,站在巨人的肩上,壓力會小很多。
播放器整體設計方案
一般播放器整體設計包括方案包括三個處理階段:
1)擷取媒體資料
2)解碼音視頻流媒體
3)將解碼後的媒體資料顯示給使用者
基於層次的播放器結構設計從上到下的層次:
1. 資料提取層
該層功能包括本地檔案、流媒體檔案的擷取
2. 資料預先處理層
對本地檔案按照媒體格式解鎖裝,擷取檔案的音視頻或文字字幕等資訊,並將其按幀放入相應的上層待解碼緩衝區;對流媒體檔案將去除RTP的包頭資訊,並將RTP中音視頻資訊組幀,將完整的資料幀傳給上層待解碼緩衝區
3. 音視頻解碼層
有解碼選擇組件,各種主流音視頻解碼器和多路媒體流之間同步的功能
4. 使用者介面
主要提供使用者和播放器之間的互動介面
FFmpeg:它提供了錄製、轉換以及流化音視頻的完整解決方案。
本篇來自:http://freewxy.iteye.com/blog/738790
基於Android平台的流媒體播放器的設計
1 引 言
隨著移動通訊技術和多媒體技術的迅速發展,融合手機、網路、多媒體技術為一體的視頻監控技 術也有了長足的進步,通過移動通訊網路提供流媒體服務已經成為可能。全球移動使用者數非常龐大,因此移動流媒體服務具有巨大的市場潛力,也正成為移動業務的 研究熱點之一。在這一背景下,針對移動網路和移動終端的特點,提出移動流媒體用戶端的解決方案很有現實意義。
本論文結合FFmpeg開原始碼中解碼流程,提出了移動終端流媒體播放器基於分層體系架構的設計方案。該設計的特點是在底層屏蔽不同類型檔案解碼時對媒體流處理的差異,並且提供了對外部網路攝影機裝置的控制功能,最終在Android平台[1]上實現該播放器。
2 播放器整體設計方案
播放器無論播放本地檔案或是網路流媒體檔案,都需要有擷取媒體資料,解碼音視頻媒體流,將解碼後媒體資料顯示給使用者三個處理階段,根據0檔案播放的流程中這三個明顯的處理階段,本文提出基於層次的播放器結構設計。
由於本地檔案和網路流媒體檔案的資料擷取方式是不相同的,若要保持上層解碼的一致性,需要對兩類檔案進行預先處理,形成相同格式的資料提供給上層解碼。根 據以上特性,結合檔案解碼流程本文中面向即時監控的播放器設計採用分層結構,每層獨立完成任務,使系統的耦合度降低,利於各層獨立擴充而不影響上下層的應 用。從下至上依次是資料提取層、資料預先處理層、音視頻解碼層和使用者介面。該流媒體播放器分層結構1所示。
使用者介面層主要提供使用者和播放器之間的互動介面,如播放本地檔案時可以實現暫停、快進、快退等功能,在觀看流媒體檔案時可以通過數字鍵、導航鍵或者播放器上方向按鈕控制網路攝影機的焦距、方向等資訊。
音視頻解碼層主要有解碼選擇組件、各種主流音視頻格式的解碼器和多路媒體流之間同步的功能。解碼選擇組件從本地檔案或者流媒體檔案頭中擷取到媒體的解碼 格式資訊,根據該格式資訊選擇相應的解碼器對壓縮後媒體流進行解碼。該部分是由FFmpeg修剪最佳化後作為播放器的解碼模組的。多路媒體之間同步包括視頻 流和音頻流的同步,在播放本地檔案時可能還需要字幕的同步。
資料預先處理層對本地檔案按照其媒體格式解鎖裝,擷取檔案的音視頻或字幕等資訊並將 其按幀放入相應上層待解碼緩衝區。對流媒體檔案將去除RTP的包頭資訊,並將RTP中音視頻資訊組幀,將完整的資料幀傳給上層待解碼緩衝區。而封裝控制信 息組件按照PELCO-D/P協議規定的文字格式設定封裝使用者的控制輸入,並將控制資訊傳遞給下層。
資料擷取層的功能包括本地檔案、流媒體檔案的 擷取和網路攝影機控制資訊的發送,前者只需讀取本地檔案即可,流媒體檔案的擷取需要從流媒體伺服器擷取媒體資料資訊。流媒體檔案擷取部分包括前期會話協商部 分、資料發送部分和資料緩衝部分。其中媒體資訊協商部分需要使用 RTSP協議[2]協商媒體流常規資訊,如媒體類型(視頻和音頻)、傳輸協議(RTP/UDP/IP…)和媒體格式(H263、mpeg…)和媒體傳輸端 口等資訊。
3 FFmpeg到Android平台的移植
FFmpeg是一個集錄製、轉換、音/視頻編碼解 碼功能為一體的完整的開源解決方案。但本文中播放器只需要FFmpeg中對檔案解鎖裝及音視頻解碼部分的功能,若將 FFmpeg整個解決方案全部移植到目標平台上會造成大量的代碼冗餘。並且FFmpeg代碼的開發時基於Linux作業系統的,並沒有考慮到手機平台的處 理能力小,能源不足等限制,因此針對手機上特定功能需求將FFmpeg代碼進行修剪及最佳化是十分重要的。
3.1 FFmpeg修剪及最佳化
從FFmpeg如此龐大並且代碼結構複雜的原始碼中找出本文需要的代碼確實是一項非常艱難的工作。在Linux下編譯運行FFmpeg代碼時需要經過 configure、make、make install三步才能將FFmpeg正確的編譯到Linux系統當中。其中configure階段會產生一個configure.h和make檔案,從 這兩個檔案中可以尋找出該次編譯都編譯了那些檔案。
經研究發現在configure原始碼的時候可以加入很多配置參數,其中參數分為基本選項 參數、進階選項參數還有專門提供的最佳化參數。最佳化參數主要負責配置在編譯時間需編譯的內容。對FFmpeg的修剪也恰是將本系統中不需要的檔案去除,因此本 文利用選擇適當的最佳化參數的方法找出播放器所需檔案。對這些參數仔細研究後,得出編譯時間設定的參數如下:
./configure --enable-version3 --disable-encoders --enable-encoder=h263 --enable-encoder= amr_nb --disable-parsers --disable-bsfs --enable-muxer=tgp --disable-protocols --enable-protocol =file。
以上面所示的參數配置編譯源檔案時,系統只將h263、amr_nb的編碼方法和3gp的檔案封裝格式及其所有的解碼格式、解鎖裝檔案的原始碼部分編譯到了連結庫。
此時被編譯到連結庫的原始碼集合即為本文所需的原始碼有效集,通過尋找configure.h和make檔案中的尾碼名為.o檔案,尾碼名為.o的檔案 是編譯.c代碼時產生的目標檔案,每一個被編譯的.c檔案都會產生.o檔案,所以通過查看所有的尾碼名為.o的檔案名稱,便可得知在該配置參數下被編譯源文 件有哪些,因此可以得出本文所需編譯的源檔案最小集合。
FFmpeg開原始碼雖然能夠跨平台編譯運行,但其代碼的設計都是針對於PC機而言的,PC機和手機從CPU處理能力、能源、記憶體等各方面的資源都具有很多大差異,本文中針對手機的特點主要從以下幾個方面最佳化代碼:
1. 去除冗餘代碼、規範程式結構、減少if-else 的判斷、調整局部和全域變數、使用寄存器變數代替局部變數,減少不必要的代碼冗餘,去除FFmpeg 調試過程中的列印語句;
2. 用邏輯移位元運算代替乘除操作,因為乘除運算指令的執行時間遠遠大於邏輯移位指令,尤其是除法指令,使用邏輯移位元運算可以減少指令的已耗用時間;
3. 注意迴圈函數的調用,盡量減少多重迴圈的使用,編寫代碼時盡量減弱上次迴圈與下次迴圈的相關性,減少不必要的代碼計算量;
4. 設定合理的緩衝。針對FFmpeg 移植的目標平台Android平台,設定適合此本台的緩衝大小;。
這裡對具體代碼的修改就不一一重複了。
3.2 FFmpeg移植
Google發布的NDK的makefile檔案即Android.mk檔案文法和普通的makefile檔案有很多不同之處,在跨平台編譯 FFmpeg原始碼時並不能使用原有的makefile檔案。所以移植的先決條件就是將FFmpeg裡的makefile檔案全部替換為NDK中的 Android.mk檔案。
通過分析FFmpeg的模組結構得知avutil是基礎模組,avcodec模組的編譯基於已經編譯好的 avutil模組,avformat基於前兩者,按照這種模組結構本文編譯移植的順序為avutil、avcoedec、avformat,編譯的步驟詳 細說明如下:
1. 關於config.h和config.mak
首先說明一下FFmpeg內建的 makefile的架構,FFmpeg在經過configure命令之後會產生一個config.h檔案和一個config.mak檔案,這兩個檔案加起 來共有 600-700個宏定義,用來描述編譯後代碼的各個方面參數設定,其中有關於體系架構、編譯器、連結庫、標頭檔、版本、轉碼器等等相關的宏定義。在這一 部分必須要修改關於平台差異方面的定義,比如必須把體系架構改成Android平台的ARMv5TE,這時檔案編譯的時候指令集就會選擇ARM的指令集而 不是X86的指令集。這兩個檔案很重要,以後很多檔案都要include
config.h這個檔案,編譯器會根據這個檔案而選擇性對代碼進行編譯。
2. 編譯libavutil.a
在libavutil建立一個Android.mk的檔案,libavutil裡的makefile檔案需要調用subdir.mak,這個其實就是真 正的編譯,但是書寫在Android.mk下,這個make檔案可以不要,但需要直接把對應的源檔案引入,標準的makefile是指定.o目標檔案,但 在Android.mk中需要直接指定.c源檔案,Android.mk檔案如下所示:
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := avutil LOCAL_SRC_FILES:=adler32.c \ …… \ include $(BUILD_STATIC_LIBRARY)
編譯時間可能會出現很多錯誤,但這些問題歸結起來大部分都是因為有些標頭檔沒有引入而產生的問題,只要引入相應的標頭檔後就可以了。比如不識別某些檔案的size_t關鍵字,在該檔案include stdio.h後就不報錯了,其他類似錯誤就不一一例舉了。
其它模組按照相同的方法書寫Android.mk檔案,移植到Android平台最為本文中播放器的解碼模組。
4 各層模組詳解
4.1資料擷取層
該層完成主要功能為與流媒體伺服器協商媒體資訊細節,並根據協商結果從伺服器端擷取流媒體資料,將流媒體資料存入緩衝區,按照本文中緩衝策略將資料包發送給資料預先處理層,其結構圖2所示:
本文中該層一共啟動五個線程,其中一個線程中啟動TCP串連,用於RTSP會話協商,並且在RTP資料轉送期間,該TCP串連必須一直保留。兩個線程分別為接收音頻和視頻RTP資料的線程,另外兩個線程分別為接收以及發送音頻和視頻的RTCP資料包。
4.2 資料預先處理層
本層對本地檔案的預先處理完全依賴於FFmpeg提供的功能檔案解鎖裝功能,而流媒體檔案的預先處理需將一個或多個RTP 資料包整合在一起,這部分技術已經相對成熟,本文將不再複述。
本文中流媒體播放器區別於其他普通流媒體播放器的最大特點即為能對外部帶有雲台的網路攝影機進行控制,例如焦距、上、下、左、右等方面的設定。所以本文中使用PELCO-D協議作為雲台控制協議。
中第一位元組為同步字也稱起始符號,通常都是0xFF。該符號位元組用來檢測所採用的收發方式正確與否。第二位元組填寫為目標裝置的地址,在命令字1位元組中為 對網路攝影機光圈及焦距的控制。在命令字2位元組為焦距及變倍控制,其中Bit4, Bit3, Bit2, Bitl為上下左右控制位,最後一個Bit0位總是0。資料1位元組中,水平方向速度(00-3F)。資料2位元組,垂直方向速度,其數值同資料位元組1。校正 碼位元組為前六個位元組之和。
本文設計的PELCO-D協議文本,最初預設情況下位命令字1、命令字2全部為0,資料字1和資料字2值為20H。通過上層發送的按鍵訊息修改相應命令字1、命令字2的相應位。
目前本文中流媒體播放器只提供以上六種控制功能,該模組根據上層出發的按鍵資訊設定相應位為1,計算位元組的值,形成七個位元組文本發送至外部裝置,當接收 到上層按鍵停止的訊息後,統一發送 {0xff,0x01,0x00,0x00,0x00,0x00,0x01,}停止命令。
4.3 解碼及顯示層
解碼層主要應用 FFmpeg移植到Android平台的代碼作為播放器的解碼模組,該部分代碼支援包括avi、3gp、MPEG-4等90多種解碼格式及檔案格式,並且經過修剪最佳化後的FFmpeg代碼效率和效能都得到了很大的提高。
顯示層本文主要應用開源的SDL函數庫實現,SDL(Simple DirectMedia Layer)是一個跨平台的,免費的開源軟體。該軟體應用C語言開發,對外提供多種平台像、聲音和其它輸入裝置的簡單介面。經常用於遊戲和其他多媒體 應用的開發,該開源軟體可以運行於多種作業系統上,其中包括Linux、PSP、Windows、Mac OS X等。同時SDL還具有視頻,音頻,線程,定時器,事件等功能。
5 總結
本文介紹了基於Android平台的流媒體播放器的分層設計結構及其各層的詳細設計,該播放器的解碼庫源自經過剪下最佳化的FFmpeg原始碼,並且本文中的播放器提供了對外部網路攝影機的控制功能,是其應用範圍更為廣泛。
本文雖然完成了帶有控制功能的流媒體播放器的原型功能實現,但還有很多例如 QoS、代碼最佳化的問題需要進一步的研究。
本篇來自:http://yangguangfu.iteye.com/blog/712227
基於rtsp的手機ApsaraVideo for VOD實現和研究
前言: 隨著3G的到來,頻寬大了流量費便宜了,手機電視等多媒體應用必將有很大發展, 本人總結以往經驗,跟大家討論一下如何建立一個手機ApsaraVideo for VOD的方案,最後給出了一個初步的用戶端實現效果。歡迎大家討論。
先說架構,出於便於管理和擴充,頻寬節流設定和多使用者並發的考慮,商用方案都會採用流媒體伺服器+WEB伺服器+代理服務器+手機用戶端的方案,其中流媒體伺服器(streaming server)負責採集視頻源並壓縮編碼並隨時等待來自用戶端的rtsp串連請求;
WEB伺服器(web server)便於發布和管理視頻資訊;
代理服務器(transmission server)是可選的,用於把來自client的RTSP請求轉寄給server,並把伺服器端的即時資料流轉給client,這樣的好處是在相同頻寬下支援更多的使用者同時觀看;
手機用戶端(client)可以用手機內建的播放器(如nokia上的realplayer)或者自己開發的獨立播放器,前者的好處是降低使用者使用門檻,便於大規模應用;後者方便擴充和定製,滿足更多的功能。
streaming server是整個方案的核心,目前主流的流媒體伺服器解決方案如下:
helix server :藉助Real公司的強大實力,這是目前最流行的方案, 可以支援所有音視頻格式,效能穩定,是唯一可以橫跨 Windows Mac 及 Linux, Solaris ,HP/UX 使用者流媒體服務的平台,支援在手機內建播放器播放。helix server免費的版本只支援1M流量,企業版很貴。當然你要破解就是另外一回事了:)
darwin server: 這是apple公司推出的開源的流媒體解決方案,支援格式沒helix那麼多,但由於是開源的免費的,對於開發人員有很大的開發空間。
live555 media server:效能穩定,但支援格式比較少(只有mp3,amr,aac,mpeg4 es等幾種流),很少獨立使用而一般作為系統的一部分。
Windows Media Server:僅限微軟平台,就不考慮了。
手機端架構流程如下:
手機用戶端與伺服器端的傳輸協議目前有HTTP,RTSP兩種,早期的手機電視多用的HTTP,HTTP的優點有不用特殊的伺服器軟體,有IIS即可,不 用考慮防火牆NAT,但HTTP不支援即時資料流,也會浪費頻寬; RTSP則是當前流媒體傳輸的主流標準,連微軟都拋棄了MMS而轉而支援RTSP, RTSP可以支援用戶端暫停回放停止等操作,基本不用考慮音視頻同步問題(因為音頻視頻分別從不同RTP PORT讀入緩衝)。值得說明的是,RTSP成功後,就開始RTP傳輸,分為RTP OVER TCP和RTP OVER UDP,前者保證每個資料包都能收到,如果沒收到就重傳,而且不用考慮防火牆NAT;後者只保證盡最大努力的傳輸,不會重傳丟幀,即時性好,要解決防火牆
NAT問題。如果對幀率要求比較高的手機電視,推薦採用UDP傳輸,因為延遲較大的重傳資料對使用者是沒有意義的,寧可丟棄。
我在網路部分採用強大的開源庫live555實現RTSP/RTP協議,其效能穩定而且支援大多數音視頻格式的傳輸。(當然ffmpeg也實現了網路傳輸 部分,經過改動後也能用)對live555經過裁剪後移植到symbian和windows mobile,這部分工作在symbian真機調試比較費時。
視頻解碼部分當然還是採用ffmpeg,移植了mpeg4 sp/h.264解碼器,在沒有任何最佳化的情況下可支援32K,CIF,5-10fps的效果,對於一般的流媒體應用足夠了。以後還要經過演算法和彙編優 化。解碼後還需要經過yuv2rgb和scale,需要注意的是ffmpeg的解碼有消隱區的說法,即qcif的映像其linesize不是176而是 192,如果你發現解碼後映像呈綠色,需用img_convert()轉一下(目的格式也是PIX_FMT_YUV420P)。symbian上用DSA 直接寫屏就行。windows
mobile上可以用sdl.
音頻解碼主要包括AAC,AMRNB,AMRWB。AAC和AMRNB是gprs和edge頻寬支援的音頻(aac效果比amrnb 好),AMRWB是3G後的音頻格式。在ffmpeg 0.5 release中已經支援amrnb/wb的fixed point解碼,很強大。
在symbian和windows mobile真機均測試通過,6122c真機和Windows mobile5.0模擬器上效果如下:
示範視頻地址為rtsp://v.starv.tv/later.3gp,視頻為mpeg4 sp,音頻為amrwb。目前只能看到映像,音頻還沒加。
注意做流媒體應用存取點一般是cmnet,cmwap只用來瀏覽網頁之類的低資料量應用。
本篇來自:http://yueguc.iteye.com/blog/832953
推薦一個:http://www.pandastream.com/,The powerful video encoding web service!