Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android Multimedia框架總結(三)MediaPlayer中創建到setDataSource過程

Android Multimedia框架總結(三)MediaPlayer中創建到setDataSource過程

編輯:關於Android編程

前言:前一篇的mediaPlayer框架,對於各個模塊的關系,得先從核心類MediaPlayer鋪開,同樣看下今天的Agenda:

MediaPlayer從create到setDisplay時序圖 MediaPlayer的create過程 MediaPlayer的setDataSource過程 MediaPlayer的setDisplay過程

今天分析的是從MediaPlayer創建到MediaPlayer調用setDataSource過程
以往總是把時序圖放在最後總結,有些人覺得一上來沒有個大概,無從下手,所以,先把時序圖附上,一步一步對著時序圖看看每個階段經歷的過程

MediaPlayer從創建到setDisplay時序圖

MediaPlayer時序圖一(create->setDataSource, 後面文章還有,暫且這麼命名):

這裡寫圖片描述

MediaPlayer的創建過程

當外部調用MediaPlayer.create(this,”http://www.xxx.mp4“)時,進入我們MediaPlayer的創建過程:

這裡寫圖片描述

以上代碼可以總結為:當MediaPlayer通過Create方式創建播放器時,內部new出MediaPlayer對象 ,並setDataSource,並做好prepare的動作。這時外面只須調用下start方法,音視頻資源將能播放起來。<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwPs2os6PO0sPH08PNqLn9ubnU7E1lZGlhUGxheWVyo6zIu7rz19S8unNldERhdGFTb3VyY2WjrHByZXBhcmW1yLLZ1/eho87ewtvExNbWtrzSqs/Ivq25/W5ldyBNZWRpYVBsYXllcigpLM7Sw8e/tM/CubnU7NbQ1/bBy8qyw7Sy2df3o7o8L3A+DQo8cD48aW1nIGFsdD0="這裡寫圖片描述" src="/uploadfile/Collfiles/20160901/20160901092553362.png" title="\" />

注意這裡有個EventHandler,雖然今天不是重點要說的,我們可以先了解下它:

這裡寫圖片描述

接下來看native層如何創建一個mediaplayer,在說native_up之前,我們注意,一般加載so都是在靜態代碼塊中, 在MediaPlayer中有一段靜態代碼塊,用於初始jni相關,早於構造方法,在加載類時就執行。一般是全局性的數據,變量,可以放在這。這裡是加載media_jni.so文件。

這裡寫圖片描述

開始進入android_media_MediaPlayer.cpp分析,第一個方法,就是在java靜態代碼塊調入的native_init:

這裡寫圖片描述

被native層調用,就是反向調用,僅被使用EventHandler post事件回到主線程中,很多用post開頭,基本都是post到主線程,用軟引用指向原生的MediaPlayer,以便native代碼是安全的,當MediaPlayer可在native釋放,調到java中的實現部分如下:

這裡寫圖片描述

以上就是native_init方法,可以看到,就是做了一些准備工作,獲取一些方法,一些要用的成員變量。接著回到之前說的,create中MediaPlayer構造函數,有一個native_setup,在android_media_MediaPlayer.cpp找到對應方法:

這裡寫圖片描述

可以看到會設置一些回調用的listener及創建c++中的MediaPlayer對象。

MediaPlayer的setDataSource過程

上面就是MediaPlayer的構造過程:構造後接下來要設置數據源,進而到了setDataSource操作,我們看下setDataSource做了什麼操作:

這裡寫圖片描述
這裡寫圖片描述

先看看如果送的setDataSource中的uri是文件類型:

這裡寫圖片描述

開始進入jni層,發現找不到android_media_MediaPlayer_setDataSource方法,可以發現有一個方法名對應映射方法聲明:

這裡寫圖片描述

以上這個方法名字映射,如果看過JNIEnv * 源碼的話,對上面這些並不陌生,無非也是映射,不影響我們分析,在這裡我們接下來要去找android_media_MediaPlayer_setDataSourceFD這個函數看看:

這裡寫圖片描述

接著看process_media_player_call方法:

這裡寫圖片描述

以上代碼總結為:當 mp->setDataSource(fd, offset, length)方法後得到status後,對各種狀態進行notify。有異常的直接拋出,這樣也就不會影響mediaplayer後面的執行過程。
接下來看下以http/rtsp傳入到jni中,在java層對應的nativeSetDataSource方法:

這裡寫圖片描述

在jni中通過映射表,可對應到android_media_MediaPlayer_setDataSourceAndHeaders:

這裡寫圖片描述

到此,setDataSource的過程就完成了。這裡要注意兩個點,一個是從Java->jni->c++正向調用過程(前面從java到native都是正向過程),一種是c++ -> jni -> java層過程(如 mp->setDataSource( httpService, pathStr, headersVector.size() > 0? &headersVector : NULL),那有人肯定會問了?這樣來回調的好處是什麼?

安全性,封裝在native層的代碼以so形式,破環性風險小 效率快,在運行速度上c++執行時間快,且底層也是c++寫的。可以對復雜的渲染及對時間要求高的,放在native是最好不過的選擇了。 連通性,正向調用將值進行傳入,反向調用把處理過值通知回去。相當於一根管道一樣。

MediaPlayer的setDisplay過程

接下來看下在setDataSource之後,開始進行mp.setDisplay(holder)
MediaPLayer.java -> setDisplay

這裡寫圖片描述

對於2,同樣在android_media_MediaPlayer.cpp找到其對應方法:

這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述Android3.0(API 11)加入的一個新類。這個類跟SurfaceView很像,可以從video decode裡面獲取圖像流(image stream)。但是,和SurfaceView不同的是,SurfaceTexture在接收圖像流之後,不需要顯示出來。SurfaceTexture不需要顯示到屏幕上,因此我們可以用SurfaceTexture接收來自decode出來的圖像流,然後從SurfaceTexture中取得圖像幀的拷貝進行處理,處理完畢後再送給另一個SurfaceView用於顯示即可。

Surface: 處理被屏幕排序的原生的buffer,Android中的Surface就是一個用來畫圖形(graphics)或圖像(image)的地方,對於View及其子類,都是畫在Surface上,各Surface對象通過Surfaceflinger合成到frameBuffer,每個Surface都是雙緩沖(實際上就是兩個線程,一個渲染線程,一個UI更新線程),它有一個backBuffer和一個frontBuffer,Surface中創建了Canvas對象,用來管理Surface繪圖操作,Canvas對應Bitmap,存儲Surface中的內容。 SurfaceView: 這個可能經常被說起,在Camera,MediaRecorder,MediaPlayer中用來顯示圖像的。

SurfaceView是View的子類,且實現了Parcelable接口且實現了Parcelable接口,其中內嵌了一個專門用於繪制的Surface,SurfaceView可以控制這個Surface的格式和尺寸,以及Surface的繪制位置。可以理解為Surface就是管理數據的地方,SurfaceView就是展示數據的地方。 SurfaceHolder:顧名思義,一個管理SurfaceHolder的容器。SurfaceHolder是一個接口,可理解為一個Surface的監聽器。

通過回調方法addCallback(SurfaceHolder.Callback callback )監聽Surface的創建

通過獲取Surface中的Canvas對象,並鎖定之。所得到的Canvas對象

通過當修改Surface中的數據完成後,釋放同步鎖,並提交改變Surface的狀態及圖像,將新的圖像數據進行展示。 而最後綜合:SurfaceView中調用getHolder方法,可以獲得當前SurfaceView中的Surface對應的SurfaceHolder,SurfaceHolder開始對Surface進行管理操作。這裡其實按MVC模式理解的話,可以更好理解。M:Surface(圖像數據),V:SurfaceView(圖像展示),C:SurfaceHolder(圖像數據管理)。MediaPlayer.java中setDisPlay的操作就是對將要顯示的視頻設預設置。

以上就是setDisPlay過程,java中setDisPlay最後一行,就是通過jni返回的Surface,時時做好更新准備。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved