MediaPlayer视频播放流程(基于Android8.0)
-
1. MediaPlayer源码分析
-
1.0
public class MediaPlayer extends PlayerBase implements SubtitleController.Listener, VolumeAutomation, AudioRouting
MediaPayer继承自PlayerBase类,分别实现了SubtitleController VolumeAutomation AudioRouting接口
-
frameworks/base/media/java/android/media/PlayerBase.java
PlayeBase是一个抽象类,封装了常规的播放器操作,如start pause stop release
baseRegisterPlayer(),获取AppOpsService对象,并通过startWatchingMode对播放音乐的权限OP_PLAY_AUDIO进行监听
protected void baseRegisterPlayer() { int newPiid = AudioPlaybackConfiguration.PLAYER_PIID_INVALID; //获取AppOpsService对象 IBinder b = ServiceManager.getService(Context.APP_OPS_SERVICE); mAppOps = IAppOpsService.Stub.asInterface(b); // initialize mHasAppOpsPlayAudio //检查权限 updateAppOpsPlayAudio(); // register a callback to monitor whether the OP_PLAY_AUDIO is still allowed mAppOpsCallback = new IAppOpsCallbackWrapper(this); try { //注册了权限的监听 mAppOps.startWatchingMode(AppOpsManager.OP_PLAY_AUDIO, ActivityThread.currentPackageName(), mAppOpsCallback); } catch (RemoteException e) { Log.e(TAG, "Error registering appOps callback", e); mHasAppOpsPlayAudio = false; } try { //调用了AudioService的 trackPlayer,主要将mediaplayer统一管理起来,已方便提供 duck,mediaplayer的状态监听啊,以及外部对mediaplayer控制等功能 newPiid = getService().trackPlayer( new PlayerIdCard(mImplType, mAttributes, new IPlayerWrapper(this))); } catch (RemoteException e) { Log.e(TAG, "Error talking to audio service, player will not be tracked", e); } mPlayerIId = newPiid; }
在MediaPlayer()构造函数中调用
public MediaPlayer() { //通过super在playerBase创建一个默认的AudioAttributes,以及player类 //PLAYER_TYPE_JAM_MEDIAPLAYER 表示MediaPlayer super(new AudioAttributes.Builder().build(), AudioPlaybackConfiguration.PLAYER_TYPE_JAM_MEDIAPLAYER); //获取当前线程的looper,如果当前线程没有lopper那么就获取主线程的looper Looper looper; if ((looper = Looper.myLooper()) != null) { //创建一个handler主要用于控制mediaplayer的播放 mEventHandler = new EventHandler(this, looper); } else if ((looper = Looper.getMainLooper()) != null) { mEventHandler = new EventHandler(this, looper); } else { mEventHandler = null; } //控制播放时间和播放进度的相关 mTimeProvider = new TimeProvider(this); //创建了一个InputStream向量集合 mOpenSubtitleSources = new Vector<InputStream>(); //通过jni向下调用,初始化 native_setup(new WeakReference<MediaPlayer>(this)); baseRegisterPlayer(); }
-
frameworks/base/media/java/android/media/SubtitleController.java
frameworks/base/media/java/android/media/SubtitleTrack.java
frameworks/base/media/java/android/media/SubtitleData.java用于为用户显示字幕,允许指定要显示的轨迹、定位点,还允许添加外部带外字幕曲目
-
frameworks/base/media/java/android/media/VolumeAutomation.java
frameworks/base/media/java/android/media/VolumeShaper.java
frameworks/base/media/jni/android_media_VolumeShaper.h等主要用于音频应用的淡入,淡出,淡入淡出,淡入淡出以及其他短暂的自动音量转换,音量控制通过VolumeShaper.Configuration实现,必须要在8.0及以后才能使用。
-
-
2.0
加载so库
static { System.loadLibrary("media_jni"); native_init(); }
-
3.0
初始化
public MediaPlayer() { ...... //通过jni向下调用,初始化 native_setup(new WeakReference<MediaPlayer>(this)); ...... }
-
frameworks/base/media/jni/android_media_MediaPlayer.cpp
static void android_media_MediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this) { ALOGV("native_setup"); // 创建一个MediaPlayer对象(frameworks/av/media/libmedia/mediaplayer.cpp) sp<MediaPlayer> mp = new MediaPlayer(); if (mp == NULL) { jniThrowException(env, "java/lang/RuntimeException", "Out of memory"); return; } // 为MediaPlayer设置listener,目的就是通过callback的方式将player的事件上传至 java层,以便用户做出对应的处理 // create new listener and give it to MediaPlayer sp<JNIMediaPlayerListener> listener = new JNIMediaPlayerListener(env, thiz, weak_this); mp->setListener(listener); // Stow our new C++ MediaPlayer in an opaque field in the Java object. setMediaPlayer(env, thiz, mp); }
//JNIMediaPlayerListener类 class JNIMediaPlayerListener: public MediaPlayerListener { public: JNIMediaPlayerListener(JNIEnv* env, jobject thiz, jobject weak_thiz); ~JNIMediaPlayerListener(); virtual void notify(int msg, int ext1, int ext2, const Parcel *obj = NULL); private: JNIMediaPlayerListener(); jclass mClass; // Reference to MediaPlayer class jobject mObject; // Weak ref to MediaPlayer Java object to call on }; ...... //callback事件的传递 void JNIMediaPlayerListener::notify(int msg, int ext1, int ext2, const Parcel *obj) { JNIEnv *env = AndroidRuntime::getJNIEnv(); if (obj && obj->dataSize() > 0) { // 创建java层Parcel对象对应的JNI类型对象(JNI本地引用对象) jobject jParcel = createJavaParcelObject(env); if (jParcel != NULL) { // 然后获取该Java层Parcel对象对应的native层Parcel对象指针(值) // 然后缓存当前obj额外参数值及其大小 Parcel* nativeParcel = parcelForJavaObject(env, jParcel); nativeParcel->setData(obj->data(), obj->dataSize()); // 最后调用java层事件回调静态方法【fields.post_event】通知java层 // fields.post_event对应于MediaPlayer的java方法 postEventFromNative env->CallStaticVoidMethod(mClass, fields.post_event, mObject, msg, ext1, ext2, jParcel); // 释放创建的java层Parcel对象的JNI本地引用对象 env->DeleteLocalRef(jParcel); } } else { // 若无额外参数,则直接调用通知java层 env->CallStaticVoidMethod(mClass, fields.post_event, mObject, msg, ext1, ext2, NULL); } // 检查【post_event】方法调用是否有异常,若异常则需要清空该异常等处理 // 备注:当一个JNI函数返回一个明确的错误码时,仍可用ExceptionCheck来检查是否有异常发生。 // 但是,用返回的错误码来判断比较高效。一旦JNI函数的返回值是一个错误码, // 那么接下来调用ExceptionCheck肯定会返回JNI_TRUE。 if (env->ExceptionCheck()) { ALOGW("An exception occurred while notifying an event."); LOGW_EX(env); env->ExceptionClear(); } } ...... static void android_media_MediaPlayer_native_init(JNIEnv *env) { jclass clazz; clazz = env->FindClass("android/media/MediaPlayer"); if (clazz == NULL) { return; } fields.context = env->GetFieldID(clazz, "mNativeContext", "J"); if (fields.context == NULL) { return; } // 获取静态方法postEventFromNative fields.post_event = env->GetStaticMethodID(clazz, "postEventFromNative", "(Ljava/lang/Object;IIILjava/lang/Object;)V"); if (fields.post_event == NULL) { return; } ...... } ..... static sp<MediaPlayer> setMediaPlayer(JNIEnv* env, jobject thiz, const sp<MediaPlayer>& player) { Mutex::Autolock l(sLock); sp<MediaPlayer> old = (MediaPlayer*)env->GetLongField(thiz, fields.context); if (player.get()) { player->incStrong((void*)setMediaPlayer); } if (old != 0) { old->decStrong((void*)setMediaPlayer); } // 将mediaplayer对象指针给与了java层的mediaplayer的mNativeContext字段 env->SetLongField(thiz, fields.context, (jlong)player.get()); return old; }
-
frameworks/av/media/libmedia/include/media/mediaplayer.h
// ref-counted object for callbacks class MediaPlayerListener: virtual public RefBase { public: virtual void notify(int msg, int ext1, int ext2, const Parcel *obj) = 0; };
-
framework/av/media/libmedia/mediaplayer.cpp
status_t MediaPlayer::setListener(const sp<MediaPlayerListener>& listener) { ALOGV("setListener"); Mutex::Autolock _l(mLock); mListener = listener; return NO_ERROR; } ...... void MediaPlayer::notify(int msg, int ext1, int ext2, const Parcel *obj) { ALOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2); bool send = true; bool locked = false; ...... case MEDIA_ERROR: // Always log errors. // ext1: Media framework error code. // ext2: Implementation dependant error code. ALOGE("error (%d, %d)", ext1, ext2); mCurrentState = MEDIA_PLAYER_STATE_ERROR; // 错误发生时,【mPrepareSync】该标识为true时, // 表示当前执行的是同步prepare准备流程,非异步执行prepareAsync流程 if (mPrepareSync) { ALOGV("signal application thread"); mPrepareSync = false; mPrepareStatus = ext1; mSignal.signal(); // prepare同步执行功能失败时,置为false send = false; } ...... ALOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2); sp<MediaPlayerListener> listener = mListener; if (locked) mLock.unlock(); // this prevents re-entrant calls into client code if ((listener != 0) && send) { // 此处根据上面的分析可知,listener不为空并且send为true(即当prepare同步执行过程中无错误发生)时, // 进行加锁调用通知java层该事件 Mutex::Autolock _l(mNotifyLock); ALOGV("callback application"); listener->notify(msg, ext1, ext2, obj); ALOGV("back from callback"); } }
-
-
4.0
setDataSource(文件类型)
public void setDataSource(FileDescriptor fd, long offset, long length) throws IOException, IllegalArgumentException, IllegalStateException { _setDataSource(fd, offset, length); } private native void _setDataSource(FileDescriptor fd, long offset, long length) throws IOException, IllegalArgumentException, IllegalStateException;
-
frameworks/base/media/jni/android_media_MediaPlayer.cpp
{"_setDataSource", "(Ljava/io/FileDescriptor;JJ)V", (void *) android_media_MediaPlayer_setDataSourceFD}, ...... static void android_media_MediaPlayer_setDataSourceFD(JNIEnv *env, jobject thiz, jobject fileDescriptor, jlong offset, jlong length) { // 获取mediaplayer指针对象 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); if (mp == NULL ) { jniThrowException(env, "java/lang/IllegalStateException", NULL); return; } if (fileDescriptor == NULL) { jniThrowException(env, "java/lang/IllegalArgumentException", NULL); return; } // 在jni中获取文件描述符 int fd = jniGetFDFromFileDescriptor(env, fileDescriptor); ALOGV("setDataSourceFD: fd %d", fd); // 处理mediaplayer指针对象对于setDataSource的结果 process_media_player_call( env, thiz, mp->setDataSource(fd, offset, length), "java/io/IOException", "setDataSourceFD failed." ); } ...... // 获取java层MediaPlayer对象的mNativeContext字段,转为native层mediaplayer对象 static sp<MediaPlayer> getMediaPlayer(JNIEnv* env, jobject thiz) { Mutex::Autolock l(sLock); MediaPlayer* const p = (MediaPlayer*)env->GetLongField(thiz, fields.context); return sp<MediaPlayer>(p); } ...... // 对setDataSource的结果进行处理 static void process_media_player_call(JNIEnv *env, jobject thiz, status_t opStatus, const char* exception, const char *message) { // 不抛出异常,直接向上层反馈错误事件 if (exception == NULL) { // Don't throw exception. Instead, send an event. if (opStatus != (status_t) OK) { sp<MediaPlayer> mp = getMediaPlayer(env, thiz); if (mp != 0) mp->notify(MEDIA_ERROR, opStatus, 0); } } else { // Throw exception! if ( opStatus == (status_t) INVALID_OPERATION ) { jniThrowException(env, "java/lang/IllegalStateException", NULL); } else if ( opStatus == (status_t) BAD_VALUE ) { jniThrowException(env, "java/lang/IllegalArgumentException", NULL); } else if ( opStatus == (status_t) PERMISSION_DENIED ) { jniThrowException(env, "java/lang/SecurityException", NULL); } else if ( opStatus != (status_t) OK ) { if (strlen(message) > 230) { // if the message is too long, don't bother displaying the status code jniThrowException( env, exception, message); } else { char msg[256]; // append the status code to the message sprintf(msg, "%s: status=0x%X", message, opStatus); jniThrowException( env, exception, msg); } } } }
-
frameworks/av/media/libmedia/mediaplayer.cpp
status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length) { // //用于记录framework APIs返回成功与否 ALOGV("setDataSource(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length); status_t err = UNKNOWN_ERROR; //getMediaPlayerService()函数定义域framework/av/media/libmedia/ IMediaDeathNotifier.cpp中 //getMediaPlayerService()返回的是MediaPlayerService服务在客户端的代理对象BpMediaPlayerService const sp<IMediaPlayerService> service(getMediaPlayerService()); if (service != 0) { //调用IMediaPlayerService中的create()函数查询服务 //并返回一个调用IMediaPlayer对象 sp<IMediaPlayer> player(service->create(this, mAudioSessionId)); //调用服务端的setDataSource(int fd, int64_t offset, int64_t length)方法 if ((NO_ERROR != doSetRetransmitEndpoint(player)) || (NO_ERROR != player->setDataSource(fd, offset, length))) { player.clear(); } //重置一些变量,更新MediaPlayer对象 err = attachNewPlayer(player); } return err; }
-
frameworks/av/media/libmedia/IMediaDeathNotifier.cpp
/*static*/const sp<IMediaPlayerService> IMediaDeathNotifier::getMediaPlayerService() { ALOGV("getMediaPlayerServic
-
-