SurfaceView
先來介紹一下大部分軟體如何解析一段視訊流。首先它需要先确定視訊的格式,這個和解碼相關,不同的格式視訊編碼不同,不是這裡的重點。知道了視訊的編碼格式後,再通過編碼格式進行解碼,最後得到一幀一幀的圖像,并把這些圖像快速的顯示在界面上,即為播放一段視訊。SurfaceView在Android中就是完成這個功能的。
既然SurfaceView是配合MediaPlayer使用的,MediaPlayer也提供了相應的方法設定SurfaceView顯示圖檔,隻需要為MediaPlayer指定SurfaceView顯示圖像即可。它的完整簽名如下:
void setDisplay(SurfaceHolder sh)
它需要傳遞一個SurfaceHolder對象,SurfaceHolder可以了解為SurfaceView裝載需要顯示的一幀幀圖像的容器,它可以通過SurfaceHolder.getHolder()方法獲得。
使用MediaPlayer配合SurfaceView播放視訊的步驟與播放使用MediaPlayer播放MP3大體一緻,隻需要額外設定顯示的SurfaceView即可。
上面有提到,SurfaceView和大部分視訊應用一樣,把視訊流解析成一幀幀的圖像進行顯示,但是如果把這個解析的過程放到一個線程中完成,可能在上一幀圖像已經顯示過後,下一幀圖像還沒有來得及解析,這樣會導緻畫面的不流暢或者聲音和視訊不同步的問題。是以SurfaceView和大部分視訊應用一樣,通過雙緩沖的機制來顯示幀圖像。那麼什麼是雙緩沖呢?雙緩沖可以了解為有兩個線程輪番去解析視訊流的幀圖像,當一個線程解析完幀圖像後,把圖像渲染到界面中,同時另一線程開始解析下一幀圖像,使得兩個線程輪番配合去解析視訊流,以達到流暢播放的效果。
下圖為示範了雙緩沖的過程,線程A和線程B配合解析渲染視訊流的幀圖像:
SurfaceView内部實作了雙緩沖的機制,但是實作這個功能是非常消耗系統記憶體的。因為移動裝置的局限性,Android在設計的時候規定,SurfaceView如果為使用者可見的時候,建立SurfaceView的SurfaceHolder用于顯示視訊流解析的幀圖檔,如果發現SurfaceView變為使用者不可見的時候,則立即銷毀SurfaceView的SurfaceHolder,以達到節約系統資源的目的。
如果開發人員不對SurfaceHolder進行維護,會出現最小化程式後,再打開應用的時候,視訊的聲音在繼續播放,但是不顯示畫面了的情況,這就是因為當SurfaceView不被使用者可見的時候,之前的SurfaceHolder已經被銷毀了,再次進入的時候,界面上的SurfaceHolder已經是新的SurfaceHolder了。是以SurfaceHolder需要我們開發人員去編碼維護,維護SurfaceHolder需要用到它的一個回調,SurfaceHolder.Callback(),它需要實作三個如下三個方法:
void surfaceDestroyed(SurfaceHolder holder):當SurfaceHolder被銷毀的時候回調。
void surfaceCreated(SurfaceHolder holder):當SurfaceHolder被建立的時候回調。
void surfaceChange(SurfaceHolder holder):當SurfaceHolder的尺寸發生變化的時候被回調。
以下是這三個方法的調用的過程,在應用中分别為SurfaceHolder實作了這三個方法,先進入應用,SurfaceHolder被建立,建立好之後會改變SurfaceHolder的大小,然後按Home鍵回退到桌面銷毀SurfaceHolder,最後再進入應用,重新SurfaceHolder并改變其大小。
對于Android4.0以下的裝置,在使用SurfaceView播放視訊的時候,需要為其設定一個額外的屬性。之前提到過,SurfaceView維護了一個雙緩沖的機制,它會自己維護緩沖區,無需我們手動維護,但是對于低版本(4.0以下)的裝置,需要為其制定它緩沖區的維護類型,讓其不自己維護緩沖區,而是等待界面渲染引擎将内容渲染到界面上。這裡僅僅是使用SurfaceView播放一個視訊,如果使用SurfaceView開發遊戲應用,就需要我們自己維護這個緩沖區了。
上面講了那麼多關于SurfaceView的内容,下面通過一個Demo簡單示範一下SurfaceView如何播放視訊,加了一個滾動條,用于顯示進度,還可以拖動滾動條選擇播放位置,Demo的注釋比較完整,這裡不再累述,視訊是在網上随便找的,朋友們運作的時候保證/sdcard/ykzzldx.mp4,這個目錄下有這個檔案。
布局檔案:activity_main.xml
activity_main.xml
實作代碼:
<a></a>
效果展示:
本文轉自承香墨影部落格園部落格,原文連結:http://www.cnblogs.com/plokmju/p/android_SurfaceView.html,如需轉載請自行聯系原作者