爲了督促自己對於android MediaPlayer部分的學習與理解,簡單的貼出自己逐步學習的過程歡迎大家一起探討,以及大牛的指導
第一天20170410:
看源碼的方法是通過點擊studio的MediaPlayer進入。
public class MediaPlayer implements SubtitleController.Listener
簡單的點進入SubtitleController 看了下,感覺是實現了對於MediaPlayer中的視圖部分的控制(個人猜想)
在看具體的代碼前,看一下MediaPlayer的功能流程
這個是mediaPlayer的功能過程,從直觀上理解我們可以從一個播放器的使用流程來考慮問題
最初一個播放器是處於空閒狀態的(將這個播放器理解爲一個容器),這時候我們需要加載一部影片我們需要
像這個容器中加入視頻的數據(視頻數據的格式不同,且有各種加入方式,因爲是播放和加載的同步進行如何
控制視頻數據的正確加入是一個坑,此處後續要看看)。
當一個容器獲取到足夠的資源時,我們要對這個狀態進行確認。
這個準備的過程可以是一個異步的操作(據瞭解這塊有的android版本會有坑點)。
資源就緒了,這時候就要研究一下播放的功能,正常播放對於視頻流操作的方法主要是,開始,暫停,快進,停止。這些功能實現了
視頻播放流程,但是具體的實現每個方法有很多細節(此處需看一下mediaPlayer中具體的實現的原理)。
簡單的順了一下media的使用流程,第一步我們先看下對於加入數據這一步,mediaPlayer是如何的實現的。
常規思路,一個視頻第一步加載時的數據有很多,包括視頻數據和音頻數據,視頻數據要想展示在畫面上也需要
畫在屏幕上。
開始我的小白琢磨代碼的旅程。
因爲還不確定,setDateSource這一過程中所做的工作,計劃從create開始看起control+f12看一下包含
oncreate的方法。
有三種方法,所傳入的參數不同,逐個查看實現的過程,
//第一個create中傳入的參數只有context,和一個整數型數據,(因爲開始需要有表面的視圖變換,以及
內在的數據傳入 ,姑且在此時認爲是某個控件的Id)
public static MediaPlayer create(Context context, int resid) {
try {
//認爲這裏是讓context獲取資源信息的過程
AssetFileDescriptor afd = context.getResources().openRawResourceFd(resid);
if (afd == null) return null;
//創建了mediaPlayer對象
MediaPlayer mp = new MediaPlayer();
mediaPlayer設置了數據
mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
//afd這個東西爲什麼在這一步close?這時候說明之前的判斷不太正確。
afd.close();
//走到這一步mediaplayer已經到了prepare的狀態
mp.prepare();
return mp;
} catch (IOException ex) {
Log.d(TAG, "create failed:", ex);
// fall through
} catch (IllegalArgumentException ex) {
Log.d(TAG, "create failed:", ex);
// fall through
} catch (SecurityException ex) {
Log.d(TAG, "create failed:", ex);
// fall through
}
return null;
}
簡單看了第一個再看下第二個
public static MediaPlayer create(Context context, Uri uri) {
//這個的區別是第二個參數不同,第二種以url定位控件的情景還沒有想出來,返回值多了一個參數
return create (context, uri, null);
}
public static MediaPlayer create(Context context, Uri uri, SurfaceHolder holder) {
//這個地方多了一個SurfaceHolder,介紹說這個是用來顯示視頻的
try {
MediaPlayer mp = new MediaPlayer();
mp.setDataSource(context, uri);
這個地方進行了判空操作,猜想這個地方是沒有釋放播放器時候開始播放
if (holder != null) {
mp.setDisplay(holder);
}
mp.prepare();
return mp;
} catch (IOException ex) {
Log.d(TAG, "create failed:", ex);
// fall through
} catch (IllegalArgumentException ex) {
Log.d(TAG, "create failed:", ex);
// fall through
} catch (SecurityException ex) {
Log.d(TAG, "create failed:", ex);
// fall through
}
return null;
}
今天暫時就先看這些
20170415今天終於偷得浮生半日閒繼續咱的計劃 沒偷成,忙了一下午。
總體上不看細節大致就是創建播放器然後set資源,看一下創建播放器的過程。
public MediaPlayer() {
Looper looper;
//在線程中執行,會優先判斷子線程
if ((looper = Looper.myLooper()) != null) {
mEventHandler = new EventHandler(this, looper);
} else if ((looper = Looper.getMainLooper()) != null) {
mEventHandler = new EventHandler(this, looper);
} else {
mEventHandler = null;
}
//推測:時間控制,標題控制
mTimeProvider = new TimeProvider(this);
mOutOfBandSubtitleTracks = new Vector<SubtitleTrack>();
mOpenSubtitleSources = new Vector<InputStream>();
mInbandSubtitleTracks = new SubtitleTrack[0];
/* Native setup requires a weak reference to our object.
* It's easier to create it here than in C++.
*/
//從註釋中看這裏要實現更底層c++的實現
native_setup(new WeakReference<MediaPlayer>(this));
}
看一下在線程做的事情,可以判斷爲對操作事件的判斷響應(這個後續研究對視頻的操作的時候研究)