首先编写一个媒体播放器 public class main extends Activity { private static final int OPENLOCAL = 1; private VideoView video; /** Called when the activity is first created. */ private void initComponents() { public boolean onCreateOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { 上面是一个完整的媒体播放器源码,其中我使用了VideoView作为播放的框架。现在分析android是如何一步一步调用MediaPlayer来打开视频的。 在上诉代码中,与媒体播放有关的代码是: video.setVideoPath("sdcard/Wildlife.3gp"); //设置媒体文件信息 注:VideoVIew是android封装了MediaPlayer的一个类,因此这个类里面对MediaPlayer的调用方式以及顺序从另一个方面说也是最符合android标准的。 在VideoView中调用setVideoPath(String path)会自动将path作Uri转换,然后调用setVideoURI,然后初始化一些状态变量 然后调用openVideo,在openVideo中可以看到很多关于MediaPlayer的初始化动作,包括注册各种与MediaPlayer相关的事件监听函数。但这不是我所关心的,在MediaPlayer的API文档中,我们可以知道setDataSource才是跟打开视频文件有关的调用。果然,在设置完一系列的监听事件后,VideoView调用了MediaPlayer的setDataSource,将刚刚Uri化的文件路径作为参数传入。 在MediaPlayer中setDataSource(Context context, Uri uri, Map<String, String> headers)会将传入的Uri做一次解析,判断它的scheme信息,之后调用到setDataSource(String path) 这是一个native函数,这就表明它的实现是在一个jni中实现的,根据android JNI的命名规则 我们找到了 android_media_MediaPlayer 在android_media_MediaPlayer 发现setDataSource的jni调用为android_media_MediaPlayer_setDataSource(JNIEnv *env, jobject thiz, jstring path)(这里说明一下在android 2.3代码中这里会调用android_media_MediaPlayer_setDataSourceAndHeaders函数,但是在1.5中没有这个调用,1.5中调用到setDataSource就直接开始操作了,其实2者的差别并不大,所以不影响整个流程),在setDataSource中android首先调用getMediaPlayer来获取一个MediaPlayer的对象 static sp<MediaPlayer> getMediaPlayer(JNIEnv* env, jobject thiz) 其中Mutex 是一个封装过的线程类,它的定义在frameworks/base/include/utils/threads.h 而sp<T>则是一个模板,它的定义在frameworks/base/include/utils/RefBase.h 这里不对这2个做说明。 获得MediaPlayer的对象后android对传入的path做了一系列的合法性判断,然后将string转为C语言中的char* 指针,当然其它的参数也做类似的处理。然后将处理后的数据以参数的形式传给mp->setDataSource。 mediaplayer.cpp是对MediaPlay的实现,所以这里的mp其实就是mediaplayer,在被调用setDataSource后,mediaplayer首先调用getMediaPlayerService来获取MediaPlayer系统服务 sp<IMediaPlayerService>& if (sDeathNotifier == NULL) { 在获得这个对象后,mediaplayer,调用create创建出一个IMediaPlayer接口的player对象,并记录下来。 到这里android就根据上层传入的视频文件地址创建出了一个指向这个地址的IMediaPlayer对象。 然后我们回到VideoView继续跟踪其它跟播放视频有关的流程。 除了setDataSource之外,VideoView还调用了MediaPlayer的setDisplay,setAudioStreamType,setScreenOnWhilePlaying以及prepareAsync,这些操作这里就不描述了,直接看跟播放有关的。 现在我已经将视频文件设置好了,那么可以开始播放了,在VideoView中播放视频是用MediaPlayerControlœ来控制,而播放则是调用MediaPlayer的start函数。 回到MediaPlayer中,发现start函数最终同样是调用到了jni接口上面,根据上面的经验,我们直接到android_media_MediaPlayer中找到android_media_MediaPlayer_start的调用。同样在这里面首先获得一个MediaPlayer的对象,然后调用这个对象的start()函数。 记得上面我们在mediaplay中创建的IMediaPlayer对象吗?这里就用到了这个对象,在设置完looping以及volume后,mediaplay 调用IMediaPlayer的start进行真正的播放 status_t start() 至此播放视频文件的基本流程就是如上所述。 |
MediaPlayer 流程分析
最新推荐文章于 2024-08-03 10:55:05 发布