🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
### 1.媒体播放器概述 Android的MediaPlayer包含了Audio和video的播放功能,在Android的界面上,Music和Video两个应用程序都是调用MediaPlayer实现的。 MediaPlayer在底层是基于OpenCore(PacketVideo)的库实现的,为了构建一个MediaPlayer程序,上层还包含了进程间通讯等内容,这种进程间通讯的基础是Android基本库中的Binder机制。 ![](https://box.kancloud.cn/2016-03-18_56eba993995db.gif) 以开源的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.媒体播放器的各个层次 ![](https://box.kancloud.cn/2016-03-18_56eba993be813.gif) **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)); } ~~~