### 1.媒體播放器概述
Android的MediaPlayer包含了Audio和video的播放功能,在Android的界面上,Music和Video兩個應用程序都是調用MediaPlayer實現的。
MediaPlayer在底層是基于OpenCore(PacketVideo)的庫實現的,為了構建一個MediaPlayer程序,上層還包含了進程間通訊等內容,這種進程間通訊的基礎是Android基本庫中的Binder機制。

以開源的Android為例MediaPlayer的代碼主要在以下的目錄中:
**JAVA程序的路徑:**
packages/apps/Music/src/com/android/music/
**JAVA類的路徑:**
frameworks/base/media/java/android/media/MediaPlayer.java
JAVA本地調用部分(JNI):
frameworks/base/media/jni/android_media_MediaPlayer.cpp? 這部分內容編譯成為目標是libmedia_jni.so。
主要的頭文件在以下的目錄中:
frameworks/base/include/media/
多媒體底層庫在以下的目錄中:
frameworks/base/media/libmedia/
這部分的內容被編譯成庫libmedia.so。
多媒體服務部分:
frameworks/base/media/libmediaplayerservice/
文件為mediaplayerservice.h和mediaplayerservice.cpp
這部分內容被編譯成庫libmediaplayerservice.so。
基于OpenCore的多媒體播放器部分
external/opencore/
這部分內容被編譯成庫libopencoreplayer.so。
從程序規模上來看,libopencoreplayer.so是主要的實現部分,而其他的庫基本上都是在其上建立的封裝和為建立進程間通訊的機制。
### 2.媒體播放器的各個層次

**1.JAVA程序部分**
?在packages/apps/Music/src/com/android/music/目錄的MediaPlaybackService.java文件中,包含了對MediaPlayer的調用。? 在MediaPlaybackService.java中包含對包的引用:import?android.media.MediaPlayer;
在MediaPlaybackService類的內部,定義了MultiPlayer類:
~~~
private class MultiPlayer {
private MediaPlayer mMediaPlayer = new MediaPlayer();
}
~~~
**2.頭文件**
MediaPlayer部分的頭文件在frameworks/base/include/media/目錄中,這個目錄是和libmedia.so庫源文件的目錄frameworks/base/media/libmedia/相對應的。主要的頭文件有以下幾個:
IMediaPlayerClient.h????????? 用于描述一個MediaPlayer客戶端的接口?????????????????????????????????????????????? ?
mediaplayer.h????????????????????? 對外的接口類,定義了一個MediaPlayer類
?IMediaPlayer.h??????????????????? 實現MediaPlayer功能的接口?????????????????????????????????????????????????????????????????????????????????????????? ?
IMediaPlayerService.h?????? 描述一個MediaPlayer的服務
在這些頭文件mediaplayer.h提供了對上層的接口,而其他的幾個頭文件都是提供一些接口類(即包含了純虛函數的類),這些接口類必須被實現類繼承才能夠使用。
**2. MediaPlayer的JAVA本地調用部分**
MediaPlayer的JAVA本地調用部分在目錄frameworks/base/media/jni/的android_media_MediaPlayer.cpp中的文件中實現。
android_media_MediaPlayer.cpp之中定義了一個JNINativeMethod(JAVA本地調用方法)類型的數組gMethods,如下所示:
~~~
static JNINativeMethod gMethods[] = {
{"setDataSource", "(Ljava/lang/String;)V", (void *)android_media_MediaPlayer_setDataSource},
{"setDataSource", "(Ljava/io/FileDescriptor;JJ)V", (void *)android_media_MediaPlayer_setDataSourceFD},
{"prepare", "()V", (void *)android_media_MediaPlayer_prepare},
{"prepareAsync", "()V", (void *)android_media_MediaPlayer_prepareAsync},
{"_start", "()V", (void *)android_media_MediaPlayer_start},
{"_stop", "()V", (void *)android_media_MediaPlayer_stop},
{"getVideoWidth", "()I", (void *)android_media_MediaPlayer_getVideoWidth},
{"getVideoHeight", "()I", (void *)android_media_MediaPlayer_getVideoHeight},
{"seekTo", "(I)V", (void *)android_media_MediaPlayer_seekTo},
{"_pause", "()V", (void *)android_media_MediaPlayer_pause},
{"isPlaying", "()Z", (void *)android_media_MediaPlayer_isPlaying},
{"getCurrentPosition", "()I", (void *)android_media_MediaPlayer_getCurrentPosition},
{"getDuration", "()I", (void *)android_media_MediaPlayer_getDuration},
{"_release", "()V", (void *)android_media_MediaPlayer_release},
{"_reset", "()V", (void *)android_media_MediaPlayer_reset},
{"setAudioStreamType", "(I)V", (void *)android_media_MediaPlayer_setAudioStreamType},
{"setLooping", "(Z)V", (void *)android_media_MediaPlayer_setLooping},
{"setVolume", "(FF)V", (void *)android_media_MediaPlayer_setVolume},
{"getFrameAt", "(I)Landroid/graphics/Bitmap;", (void *)android_media_MediaPlayer_getFrameAt},
{"native_setup", "(Ljava/lang/Object;)V", (void *)android_media_MediaPlayer_native_setup},
{"native_finalize", "()V", (void *)android_media_MediaPlayer_native_finalize},
}
~~~
JNINativeMethod的第一個成員是一個字符串,表示了JAVA本地調用方法的名稱,這個名稱是在JAVA程序中調用的名稱;第二個成員也是一個字符串,表示JAVA本地調用方法的參數和返回值;第三個成員是JAVA本地調用方法對應的C語言函數。
其中android_media_MediaPlayer_start函數的實現如下所示:
~~~
static void
android_media_MediaPlayer_start(JNIEnv *env, jobject thiz)
{
LOGV("start");
sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
if (mp == NULL ) {
jniThrowException(env, "java/lang/IllegalStateException", NULL);
return;
}
process_media_player_call( env, thiz, mp->start(), NULL, NULL );
}
~~~
在android_media_MediaPlayer_start的調用中,得到一個MediaPlayer指針,通過對它的調用實現實際的功能。
register_android_media_MediaPlayer用于將gMethods注冊為的類"android/media/MediaPlayer",其實現如下所示:
~~~
// This function only registers the native methods
static int register_android_media_MediaPlayer(JNIEnv *env)
{
return AndroidRuntime::registerNativeMethods(env,
"android/media/MediaPlayer", gMethods, NELEM(gMethods));
}
~~~
- 前言
- Camera源碼分析(android2.2)
- Android開機啟動流程說明
- android應用程序管理機制
- MediaPlayer框架概述(一)
- MediaPlayer框架概述(二)
- Android MediaPlayer+Stagefright框架(音頻)圖解
- Stagefright框架解讀(—)音視頻Playback流程
- Android mediaRecorder框架簡述(一)
- Android mediaRecorder框架簡述(二)
- Android IntentService淺談以及源碼分析
- Android多線程(二)AsyncTask源碼分析
- Android View體系(五)從源碼解析View的事件分發機制
- Android View體系(六)從源碼解析Activity的構成