在Activity 的OnSurfaceCreate回调后,表示Surface已经创建成功,可以将surface传到native层player
frameworks/base/media/java/android/media/MediaPlayer.java
代码语言:javascript复制 public void setDisplay(SurfaceHolder sh) {
mSurfaceHolder = sh;
Surface surface;
if (sh != null) {
surface = sh.getSurface();
} else {
surface = null;
}
_setVideoSurface(surface); //将surface传给 native层
updateSurfaceScreenOn(); //设置屏幕是否保持打开状态
}
参数是SurfaceHolder 通过SurfaceHolder去获取Surface,将Surface传给jni
frameworks/base/media/jni/android_media_MediaPlayer.cpp
代码语言:javascript复制static void
setVideoSurface(JNIEnv *env, jobject thiz, jobject jsurface, jboolean mediaPlayerMustBeAlive)
{
sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
if (mp == NULL) {
if (mediaPlayerMustBeAlive) {
jniThrowException(env, "java/lang/IllegalStateException", NULL);
}
return;
}
decVideoSurfaceRef(env, thiz);
sp<IGraphicBufferProducer> new_st;
if (jsurface) {
sp<Surface> surface(android_view_Surface_getSurface(env, jsurface));
if (surface != NULL) {
new_st = surface->getIGraphicBufferProducer();
if (new_st == NULL) {
jniThrowException(env, "java/lang/IllegalArgumentException",
"The surface does not have a binding SurfaceTexture!");
return;
}
new_st->incStrong((void*)decVideoSurfaceRef);
} else {
jniThrowException(env, "java/lang/IllegalArgumentException",
"The surface has been released");
return;
}
}
//将GraphicBufferProducer 的对象new_st 设置给java层的mNativeSurfaceTexture
//在java的反射中,通过字段获取对象,是通过 public Object get(Object obj) 获取的
//new_st.get() 获取到new_st的对象,而且对象是static的,如果不是static。如果字段不是静态字段的话,要传入反射类的对象
env->SetLongField(thiz, fields.surface_texture, (jlong)new_st.get());
// This will fail if the media player has not been initialized yet. This
// can be the case if setDisplay() on MediaPlayer.java has been called
// before setDataSource(). The redundant call to setVideoSurfaceTexture()
// in prepare/prepareAsync covers for this case.
mp->setVideoSurfaceTexture(new_st);
}
首先通过surface获取到GraphicBufferProducer, 接着将GraphicBufferProducer设置到MediaPlayer.java 中的mNativeSurfaceTexture,最后调用C 层播放器的setVideoSurfaceTexture方法
frameworks/av/media/libmedia/mediaplayer.cpp
代码语言:javascript复制status_t MediaPlayer::setVideoSurfaceTexture(
const sp<IGraphicBufferProducer>& bufferProducer)
{
ALOGV("setVideoSurfaceTexture");
Mutex::Autolock _l(mLock);
if (mPlayer == 0) return NO_INIT;
return mPlayer->setVideoSurfaceTexture(bufferProducer);
}
mPlayer 是通过binder调用到了MediaPlayerService.cpp中 client内部类的方法
代码语言:javascript复制status_t MediaPlayerService::Client::setVideoSurfaceTexture(
const sp<IGraphicBufferProducer>& bufferProducer)
{
ALOGV("[%d] setVideoSurfaceTexture(%p)", mConnId, bufferProducer.get());
sp<MediaPlayerBase> p = getPlayer();
if (p == 0) return UNKNOWN_ERROR;
sp<IBinder> binder(IInterface::asBinder(bufferProducer));
if (mConnectedWindowBinder == binder) {
return OK;
}
sp<ANativeWindow> anw;
if (bufferProducer != NULL) {
anw = new Surface(bufferProducer, true /* controlledByApp */);
status_t err = nativeWindowConnect(anw.get(), "setVideoSurfaceTexture");
if (err != OK) {
ALOGE("setVideoSurfaceTexture failed: %d", err);
// Note that we must do the reset before disconnecting from the ANW.
// Otherwise queue/dequeue calls could be made on the disconnected
// ANW, which may result in errors.
reset();
Mutex::Autolock lock(mLock);
disconnectNativeWindow_l();
return err;
}
}
// Note that we must set the player's new GraphicBufferProducer before
// disconnecting the old one. Otherwise queue/dequeue calls could be made
// on the disconnected ANW, which may result in errors.
status_t err = p->setVideoSurfaceTexture(bufferProducer);
mLock.lock();
disconnectNativeWindow_l();
if (err == OK) {
mConnectedWindow = anw;
mConnectedWindowBinder = binder;
mLock.unlock();
} else {
mLock.unlock();
status_t err = nativeWindowDisconnect(
anw.get(), "disconnectNativeWindow");
if (err != OK) {
ALOGW("nativeWindowDisconnect returned an error: %s (%d)",
strerror(-err), err);
}
}
return err;
}
主要是将bufferProducer 设置给了NuPlayer,NuPlayer的内容暂时不跟。