一、概述:
声明:下面我们看的是Android 4.0版本下的Media播放器的框架,我们首先从一个简单的media播放器apk源码入手,从Java->JNI->C/C++一步步研究Android是如何通过Java一个MediaPlayer实现解码到屏幕的输出。
通常在Android中播放视频用到的是MediaPlayer类,展示视频使用的是SurfaceView控件。
二、apk实现:
我们首先在main.xml布局文件中添加用于视频画面绘制的SurfaceView控件:
<SurfaceView android:layout_width="fill_parent"android:layout_height="240dip"android:id="@+id/surfaceView"/>
例如我们编写一个简单的视频播放器调用的常用方法如下。
SurfaceView surfaceView = (SurfaceView)this.findViewById(R.id.surfaceView);
surfaceView.getHolder().setFixedSize(720, 576); //设置分辨率
/*下面设置Surface不维护自己的缓冲区,而是等待屏幕的渲染引擎将内容推送到用户面前*/
surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
/* new 一个播放器 mediaPlayer */
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.reset(); //重置为初始状态
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
/* 设置Video影片以SurfaceHolder播放 */
mediaPlayer.setDisplay(surfaceView.getHolder());
mediaPlayer.setDataSource("/mnt/sdcard/test.ts");
mediaPlayer.prepare(); //缓冲
mediaPlayer.start(); //播放
mediaPlayer.pause(); //暂停播放
mediaPlayer.start(); //恢复播放
mediaPlayer.stop(); //停止播放
mediaPlayer.release(); //释放资源
三、源码分析
我们首先来看MediaPlayer类,Java层的MediaPlayer.java位于frameworks/base/media/java/android/media/目录下:
public class MediaPlayer
{
...
static {
System.loadLibrary("media_jni");
native_init();
}
private int mNativeContext;
private int mNativeSurfaceTexture;
private int mListenerContext;
private SurfaceHolder mSurfaceHolder;
private EventHandler mEventHandler;
public MediaPlayer() {
Looper loop;
if((loop = Looper.myLooper()) != null) {
mEventHandler = new EventHandler(this, looper);
} else if((looper = Looper.getMainLooper()) != null) {
mEventHandler = new EventHandler(this. looper);
} else {
mEventHandler = null;
}
native_setup(new WeakReference<MediaPlayer>(this));
}
....
}
(一) static代码块
首先会加载libmedia_jni.so库,调用native_init()方法,对应JNI接口为
android_media_MediaPlayer_native_init(JNIEnv* env)
{
jclass clazz;
class = env->FindClass("android/media/MediaPlayer");
fields.context = env->GetFieldID(clazz, "mNativeContext"); // Java类中保存JNI层的mediaplayer对象
/* JNI 事件通知Java,static 函数 */
fields.post_event = env->GetStaticMethodID(clazz, "postEventFromNative", "(Ljava/lang/Object;IIILjava/lang/Object;)V");
fields.surface_texture = env->GetFieldID(clazz, "mNativeSurfaceTexture", "I");
jclass surface = env->FindClass("android/view/Surface");
fields.bitmapClazz = env->FindClass("android/graphics/Bitmap");
fields.bitmapContstructor = env->GetMethodID(fields.bitmapClazz, "<