首先从MediaPlayer的setDisplay方法开始:
//frameworks/base/media/java/android/media/MediaPlayer.java
public class MediaPlayer extends PlayerBase implements SubtitleController.Listener, VolumeAutomation, AudioRouting
{
public void setDisplay(SurfaceHolder sh) {
mSurfaceHolder = sh; //给Surface设置一个控制器,用于展示视频图像
Surface surface;
if (sh != null) {
surface = sh.getSurface(); //取得surface
} else {
surface = null;
}
_setVideoSurface(surface); //给视频设置Surface,带_的函数是native函数
updateSurfaceScreenOn(); //更新Surface到屏幕上
}
}
上面方法主要处理如下:
调用_setVideoSurface方法,设置Video Surface。
调用updateSurfaceScreenOn方法,更新Surface到屏幕上。
下面分别分析:
_setVideoSurface
_setVideoSurface是一个native方法,经过查询调用的是android_media_MediaPlayer_setVideoSurface方法:
//frameworks/base/media/jni/android_media_MediaPlayer.cpp
static void android_media_MediaPlayer_setVideoSurface(JNIEnv *env, jobject thiz, jobject jsurface)
{
setVideoSurface(env, thiz, jsurface, true /* mediaPlayerMustBeAlive */);
}
调用setVideoSurface方法:
//frameworks/base/media/jni/android_media_MediaPlayer.cpp
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)); //调用android_view_Surface_getSurface方法,得到Java层的Surface
if (surface != NULL) {
new_st = surface->getIGraphicBufferProducer(); //调用surface的getIGraphicBufferProducer方法,获取IGraphicBufferProducer
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;
}
}
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);
}
调用MediaPlayer的setVideoSurfaceTexture方法,设置VideoSurface纹理:
sp<IMediaPlayer> mPlayer;
//frameworks/av/media/libmedia/MediaPlayer.cpp
status_t MediaPlayer::setVideoSurfaceTexture(
const sp<IGraphicBufferProducer>& bufferProducer)
{
ALOGV("setVideoSurfaceTexture");
Mutex::Autolock _l(mLock);
if (mPlayer == 0) return NO_INIT;
return mPlayer->setVideoSurfaceTexture(bufferProducer);
}
调用IMediaPlayer的setVideoSurfaceTexture方法:
//frameworks/av/media/libmedia/IMediaPlayer.cpp
class BpMediaPlayer: public BpInterface<IMediaPlayer>
{
status_t setVideoSurfaceTexture(const sp<IGraphicBufferProducer>& bufferProducer)
{
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
sp<IBinder> b(IInterface::asBinder(bufferProducer));
data.writeStrongBinder(b);
remote()->transact(SET_VIDEO_SURFACETEXTURE, data, &reply); //发送SET_VIDEO_SURFACETEXTURE消息
return reply.readInt32();
}
}
发送SET_VIDEO_SURFACETEXTURE消息,发送的消息会在BnMediaPlayer的onTransact方法中进行处理:
//frameworks/av/media/libmedia/IMediaPlayer.cpp
status_t BnMediaPlayer::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch (code) {
case SET_VIDEO_SURFACETEXTURE: {
CHECK_INTERFACE(IMediaPlayer, data, reply);
sp<IGraphicBufferProducer> bufferProducer =
interface_cast<IGraphicBufferProducer>(data.readStrongBinder());
reply->writeInt32(setVideoSurfaceTexture(bufferProducer)); //调用MediaPlayerService的setVideoSurfaceTexture方法
return NO_ERROR;
} break;
}
}
调用MediaPlayerService的setVideoSurfaceTexture方法:
//frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp
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;
}
updateSurfaceScreenOn
待更新