1. MediaPlayer::setDisplay()
Frameworks/base/media/java/android/media/MediaPlayer.java
public void setDisplay(SurfaceHolder sh) {
mSurfaceHolder = sh;
Surface surface;
if (sh != null) {
surface = sh.getSurface();
} else {
surface = null;
}
_setVideoSurface(surface);
updateSurfaceScreenOn();
}
2. 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 */);
}
3. MediaPlayer:: setVideoSurface()
Frameworks/base/media/jni/Android_media_MediaPlayer.cpp
static void
setVideoSurface(JNIEnv *env, jobject thiz, jobjectjsurface, jboolean mediaPlayerMustBeAlive)
{
// 得到本地MediaPlayer对象
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) {
// 从java env中得到surface对象
sp<Surface>surface(android_view_Surface_getSurface(env, jsurface));
if (surface != NULL) {
// 得到surface对象的BufferProducer
new_st =surface->getIGraphicBufferProducer();
if (new_st == NULL) {
jniThrowException(env,"java/lang/IllegalArgumentException",
"The surface does nothave a binding SurfaceTexture!");
return;
}
new_st->incStrong((void*)decVideoSurfaceRef);
} else {
jniThrowException(env,"java/lang/IllegalArgumentException",
"The surface has beenreleased");
return;
}
}
// 将BufferProducer对象保存在java env中
env->SetIntField(thiz,fields.surface_texture, (int)new_st.get());
// This will fail if the media player hasnot been initialized yet. This
// can be the case if setDisplay() onMediaPlayer.java has been called
// before setDataSource(). The redundantcall to setVideoSurfaceTexture()
// in prepare/prepareAsync covers for thiscase.
mp->setVideoSurfaceTexture(new_st);
}
status_t MediaPlayer::setVideoSurfaceTexture(
constsp<IGraphicBufferProducer>& bufferProducer)
{
ALOGV("setVideoSurfaceTexture");
Mutex::Autolock _l(mLock);
if (mPlayer == 0) return NO_INIT;
// mPlayer是一个BpMediaPlayer(BpBinder)对象
returnmPlayer->setVideoSurfaceTexture(bufferProducer);
}
4. BpMediaPlayer:: setVideoSurfaceTexture()
Frameworks/av/media/libmedia/IMediaServer.cpp
class BpMediaPlayer: public BpInterface<IMediaPlayer>
{
// pass the buffered IGraphicBufferProducerto the media player service
status_t setVideoSurfaceTexture(constsp<IGraphicBufferProducer>& bufferProducer)
{
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
sp<IBinder>b(bufferProducer->asBinder());
data.writeStrongBinder(b);
// remote() 返回 BpMediaServer(BpBinder)中的BpBinder
remote()->transact(SET_VIDEO_SURFACETEXTURE,data, &reply);
return reply.readInt32();
}
}
5. BnMediaPlayer::onTransact ()
Frameworks/av/media/libmedia/IMediaServer.cpp
通过Biner机制调用BnMediaPlayer::onTransact()
status_tBnMediaPlayer::onTransact(
uint32_t code, const Parcel& data,Parcel* reply, uint32_t flags)
{
switch (code) {
case DISCONNECT: {
CHECK_INTERFACE(IMediaPlayer, data,reply);
disconnect();
return NO_ERROR;
} break;
case SET_DATA_SOURCE_URL: {
CHECK_INTERFACE(IMediaPlayer, data,reply);
const char* url =data.readCString();
KeyedVector<String8, String8>headers;
int32_t numHeaders =data.readInt32();
for (int i = 0; i < numHeaders;++i) {
String8 key =data.readString8();
String8 value =data.readString8();
headers.add(key, value);
}
reply->writeInt32(setDataSource(url, numHeaders > 0 ? &headers: NULL));
return NO_ERROR;
} break;
case SET_DATA_SOURCE_FD: {
CHECK_INTERFACE(IMediaPlayer, data,reply);
int fd = data.readFileDescriptor();
int64_t offset = data.readInt64();
int64_t length = data.readInt64();
reply->writeInt32(setDataSource(fd, offset, length));
return NO_ERROR;
}
case SET_DATA_SOURCE_STREAM: {
CHECK_INTERFACE(IMediaPlayer, data,reply);
sp<IStreamSource> source =
interface_cast<IStreamSource>(data.readStrongBinder());
reply->writeInt32(setDataSource(source));
return NO_ERROR;
}
caseSET_VIDEO_SURFACETEXTURE: {
CHECK_INTERFACE(IMediaPlayer, data, reply);
sp<IGraphicBufferProducer> bufferProducer =
interface_cast<IGraphicBufferProducer>(data.readStrongBinder());
reply->writeInt32(setVideoSurfaceTexture(bufferProducer));
returnNO_ERROR;
} break;
case SET_NEXT_PLAYER: {
CHECK_INTERFACE(IMediaPlayer, data,reply);
reply->writeInt32(setNextPlayer(interface_cast<IMediaPlayer>(data.readStrongBinder())));
return NO_ERROR;
}break;
default:
return BBinder::onTransact(code,data, reply, flags);
}
}
6. BnMediaPlayer::onTransact ()
Frameworks/av/media/libmediaplayerservice/MediaPlayerService.h
Frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp
classMediaPlayerService : public BnMediaPlayerService
{
class Client;
class Client : public BnMediaPlayer {
// IMediaPlayer interface
virtual void disconnect();
virtualstatus_t setVideoSurfaceTexture(
constsp<IGraphicBufferProducer>& bufferProducer);
virtual status_t prepareAsync();
…………………………………………………………………………………………….
}
7. MediaPlayerService::Client::setVideoSurfaceTexture()
Frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp
status_tMediaPlayerService::Client::setVideoSurfaceTexture(
constsp<IGraphicBufferProducer>& bufferProducer)
{
ALOGV("[%d]setVideoSurfaceTexture(%p)", mConnId, bufferProducer.get());
sp<MediaPlayerBase> p = getPlayer();
if (p == 0) return UNKNOWN_ERROR;
sp<IBinder> binder(bufferProducer ==NULL ? NULL :
bufferProducer->asBinder());
if (mConnectedWindowBinder == binder) {
return OK;
}
sp<ANativeWindow> anw;
if (bufferProducer != NULL) {
anw = new Surface(bufferProducer);
status_t err =native_window_api_connect(anw.get(),
NATIVE_WINDOW_API_MEDIA);
if (err != OK) {
ALOGE("setVideoSurfaceTexturefailed: %d", err);
// Note that we must do the resetbefore disconnecting from the ANW.
// Otherwise queue/dequeue callscould be made on the disconnected
// ANW, which may result in errors.
reset();
disconnectNativeWindow();
return err;
}
}
// Note that we must set the player's newGraphicBufferProducer before
// disconnecting the old one. Otherwise queue/dequeue calls could be made
// on the disconnected ANW, which mayresult in errors.
status_t err =p->setVideoSurfaceTexture(bufferProducer);
disconnectNativeWindow();
mConnectedWindow = anw;
if (err == OK) {
mConnectedWindowBinder = binder;
} else {
disconnectNativeWindow();
}
return err;
}
8. native_window_api_connect ()
system/core/include/system/window.h
staticinline int native_window_api_connect(
struct ANativeWindow* window, int api)
{
return window->perform(window,NATIVE_WINDOW_API_CONNECT, api);
}
9. Surface::perform
Frameworks/native/libs/gui/Surface.cpp
int Surface::perform(int operation, va_listargs)
{
int res = NO_ERROR;
switch (operation) {
case NATIVE_WINDOW_CONNECT:
// deprecated. must return NO_ERROR.
break;
case NATIVE_WINDOW_DISCONNECT:
// deprecated. must return NO_ERROR.
break;
case NATIVE_WINDOW_SET_USAGE:
res = dispatchSetUsage(args);
break;
case NATIVE_WINDOW_SET_CROP:
res = dispatchSetCrop(args);
break;
case NATIVE_WINDOW_SET_BUFFER_COUNT:
res = dispatchSetBufferCount(args);
break;
case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY:
res = dispatchSetBuffersGeometry(args);
break;
case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
res = dispatchSetBuffersTransform(args);
break;
case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
res = dispatchSetBuffersTimestamp(args);
break;
case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS:
res = dispatchSetBuffersDimensions(args);
break;
case NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS:
res = dispatchSetBuffersUserDimensions(args);
break;
case NATIVE_WINDOW_SET_BUFFERS_FORMAT:
res = dispatchSetBuffersFormat(args);
break;
case NATIVE_WINDOW_LOCK:
res = dispatchLock(args);
break;
case NATIVE_WINDOW_UNLOCK_AND_POST:
res = dispatchUnlockAndPost(args);
break;
case NATIVE_WINDOW_SET_SCALING_MODE:
res = dispatchSetScalingMode(args);
break;
case NATIVE_WINDOW_API_CONNECT:
res = dispatchConnect(args);
break;
case NATIVE_WINDOW_API_DISCONNECT:
res = dispatchDisconnect(args);
break;
default:
res = NAME_NOT_FOUND;
break;
}
return res;
}
int Surface::dispatchConnect(va_list args){
int api = va_arg(args, int);
return connect(api);
}
int Surface::connect(int api) {
ATRACE_CALL();
ALOGV("Surface::connect");
Mutex::Autolock lock(mMutex);
IGraphicBufferProducer::QueueBufferOutput output;
int err =mGraphicBufferProducer->connect(api, &output);
if (err == NO_ERROR) {
uint32_t numPendingBuffers = 0;
output.deflate(&mDefaultWidth,&mDefaultHeight, &mTransformHint,
&numPendingBuffers);
mConsumerRunningBehind = (numPendingBuffers >= 2);
}
if (!err && api == NATIVE_WINDOW_API_CPU) {
mConnectedToCpu = true;
}
return err;
}
10. BufferQueue::connect()
Frameworks/native/libs/gui/SurfaceQueue.cpp
status_t BufferQueue::connect(int api,QueueBufferOutput* output) {
ATRACE_CALL();
ST_LOGV("connect: api=%d", api);
Mutex::Autolock lock(mMutex);
if (mAbandoned) {
ST_LOGE("connect: BufferQueue has been abandoned!");
return NO_INIT;
}
if (mConsumerListener == NULL) {
ST_LOGE("connect: BufferQueue has no consumer!");
return NO_INIT;
}
int err = NO_ERROR;
switch (api) {
case NATIVE_WINDOW_API_EGL:
case NATIVE_WINDOW_API_CPU:
case NATIVE_WINDOW_API_MEDIA:
case NATIVE_WINDOW_API_CAMERA:
if (mConnectedApi != NO_CONNECTED_API) {
ST_LOGE("connect: alreadyconnected (cur=%d, req=%d)",
mConnectedApi, api);
err = -EINVAL;
} else {
mConnectedApi = api;
output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint,
mQueue.size());
}
break;
default:
err = -EINVAL;
break;
}
mBufferHasBeenQueued = false;
return err;
}