編輯:關於Android編程
前言:在上篇中,分析了MediaPlayer的從創建到setDataSource過程,盡管看了代碼,但是沒有從MediaPlayer生態上認識各類庫之間依賴調用關系,在本篇中將作一個補充整體上的認識。看下今天的Agenda:
MediaPlayer各個so庫之間關系結構圖 MediaPlayer各個具體類之間依賴關系圖 prepare的執行過程 prepareAsync執行過程 prepare和prepareAsync區別 start執行過程 pause執行過程在各個so中,libmedia.so位於核心的位置,它對上層的提供的jni主要是Java中MediaPlayer類,類libmedia_jni.so通過調用MediaPlayer類提供對Java的接口,並且實現了Android.media.MediaPlayer類。
libmediaplayerservice.so是Media的服務器,它通過繼承libmedia.so的類實現服務器的功能,而libmedia.so中的另外一部分內容則通過IPC和libmediaplayerservice.so進行通信。libmediaplayerservice.so的真正功能通過調用OpenCore Player來完成解碼。OpenCore是一個多媒體的框架,從宏觀上來看,它主要包含了兩大方面的內容:
在這些頭文件mediaplayer.h提供了對上層的接口,而其他的幾個頭文件都是提供一些接口類(即包含了純虛函數的類),這些接口類必須被實現類繼承才能夠使用。
整個MediaPlayer在運行的時候,可以分成Client和Server兩個部分,它們分別在兩個進程中運行,它們之間使用Binder機制實現IPC通信。從框架結構上來看,IMediaPlayerService.h、IMediaPlayerClient.h和MediaPlayer.h三個類定義了MeidaPlayer的接口和架構,MediaPlayerService.cpp和mediaplayer.cpp兩個文件用於MeidaPlayer架構的實現,MeidaPlayer的具體功能在PVPlayer(庫libopencoreplayer.so)中的實現。
prepare播放器為playback,這是個同步方法,當setDataSource且展現了surface,你應當開始調用prepare或prepareAsync方法,對於文件類型,調用prepare方法將暫時block,直到MediaPlayer已經為playback准備好。接著調用native層android_media_MediaPlayer_prepare方法:
上述1,2,3 我們在上一篇中,曾結介紹過,1中getVideoSurfaceTexture是獲取一個IGraphicBufferProducer類型指針,2中是setVideoSurfaceTexture,這個xxx中最後的部分介紹過,這裡不再細說。3中是個判定並且notify的方法,這裡是送進mp->prepare的方法調用的狀態送入,如果不ok,就notify相關error或者拋出異常。我們知道還有一個prepareAsync方法,我們前面的思路都是順著MediaPlayer中create方法來的。
如果是下面這種場景,一個網絡url送過來,視頻非常大:這時就要用到異步prepare
看下MediaPlayer中prepareAsync方法: 准備好播放器為接下來playback,這是個異步方法,當setDataSource且展現了surface,你應當開始調用prepare或prepareAsync方法了,對於流類型,你應該調用prepareAsync方法能立馬返回,而不是在沒有足夠的流數據被緩沖時一直block
本文出自逆流的魚yuiop:http://blog.csdn.net/hejjunlin/article/details/52420803
這是個native方法,我們看android_media_MediaPlayer_prepareAsync方法:
從代碼上看,除了最後process_media_player_call中mp->prepareAsync()判斷狀態時,不一樣,其他和prepare都是一樣。它的操作結果經過回調通知給Java層。
看下media/mediaplayer.h中prepareAsync函數,c++代碼:
上面代碼總結為:首先判斷mFlags,此時不是preparing。接著啟動mQueue(類TimedEventQueue)。之後修改mFlags的狀態為PREPARING,表示現在正在准備處理文件的音視頻流。然後通過實例一個AwesomeEvent,然後放到之前啟動的mQueue中進行通知出去。
queue中處理的結果就是調用AwesomePlayer::onPrepareAsyncEvent函數。後面的過程就是初始化解碼器,將流解碼出來,也能知道視頻流的寬高等屬性,然後通知prepared.不再向下跟蹤。prepare的流程就完成了。
接下來,我們再回到java層中之前prepare方法中的scanInternalSubtitleTracks()方法
這個方法是掃描內嵌字幕並進行跟蹤.
接下來分析看下MediaPlayer中start過程:
以上代碼總結為:start方法用於start或者重新恢復播放,如果playback先前已暫停,playback將開始從paused狀態變成在start狀態,如果playback已經是stopped,或之前從來沒有started過,playback將會開始start。
3中執行stayAwake()中是對屏幕進行操作:
最後通過updateSurfaceScreenOn()進行,更新屏幕上的Surface.我們還是回到最上面start方法中。最後會調用_start方法到native jni中。
從中間的mp-start開始,就調到底層c++,在native中引入media/mediaplayer.h,我們進入這個頭文件看看:
從接口中可以看出MediaPlayer類實現了一個MediaPlayer的基本playback操作,播放(start)、停止(stop)、暫停(pause), 重置(reset)等。
另外的一個類DeathNotifier在MediaPlayer類中定義,它繼承了IBinder類中的DeathRecipient類,這些作用都是為了進程間通信准備:
以下過程就是和mediaplayerservice通過IPC進行通信,不再向下分析。
可以發現start後,底層來返回一個狀態,是ok還是不ok的。這就回到process_media_player_call中判定這個返回的狀態,然後notify java層中的回調函數。
接下來,再看下pause方法,
在對應的jni中找到android_media_MediaPlayer_pause方法
pause方法,可以看到和start的流程類似,也是通過 mp->pause()返回對應的狀態,然後notify上層去pause
還有一個stop方法也是類似,這裡不再分析。
ListView網上資料很多,我所知擴展性最好、最通用的代碼做個備忘。總體上來講:ListView+BaseAdapter+xml文件實現:話不多說,先貼個圖,預期效果如
本文主要介紹一個支持圖片自動預取、支持多種緩存算法、支持數據保存和恢復的圖片Sd卡緩存的使用、功能及網友反饋的常見問題解答。與AndroidLruCache相比主要特性:
1.在java代碼中(SplashActivity繼承AppCompatActivity時無效)2.在manifest.xml中改Theme3.先在style.xml中自
基礎介紹異步消息處理線程是指,線程在啟動後會進入一個無線循環體中,沒循環一次,從內部的消息隊列中取出一個一個消息,並回調相應的消息處理函數,執行完一個消息後則繼續循環。如