MediaPlayer的各个库之间的结构
在各个库中,libmedia.so位于核心的位置,它对上层的提供的接口主要是MediaPlayer类,类libmedia_jni.so通过调用 MediaPlayer类提供对JAVA的接口,并且实现了android.media.MediaPlayer类。
libmediaplayerservice.so 是Media的服务器,它通过继承libmedia.so的类实现服务器的功能,而 libmedia.so中的另外一部分内容则通过进程间通讯和libmediaplayerservice.so进行通讯。 libmediaplayerservice.so的真正功能通过调用OpenCore Player来完成。
MediaPlayer部分的头文件在frameworks/base/include/media/目录中,这个目录是和libmedia.so库源文件的目录frameworks/base/media/libmedia/相对应的。主要的头文件有以下几个:
IMediaPlayerClient.h
mediaplayer.h
IMediaPlayer.h
IMediaPlayerService.h
MediaPlayerInterface.h
在这些头文件mediaplayer.h提供了对上层的接口,而其他的几个头文件都是提供一些接口类(即包含了纯虚函数的类),这些接口类必须被实现类继承才能够使用。
整个MediaPlayer库和调用的关系
整 个MediaPlayer在运行的时候,可以大致上分成Client和Server两个部分,它们分别在两个进程中运行,它们之间使用Binder机制实 现IPC通讯。从框架结构上来看,IMediaPlayerService.h、IMediaPlayerClient.h和 MediaPlayer.h三个类定义了MeidaPlayer的接口和架构,MediaPlayerService.cpp和 mediaplayer.coo两个文件用于MeidaPlayer架构的实现,MeidaPlayer的具体功能在PVPlayer(库 libopencoreplayer.so)中的实现。
2.2 头文件IMediaPlayerClient.h
IMediaPlayerClient.h用于描述一个MediaPlayer客户端的接口,描述如下所示:
class IMediaPlayerClient: public IInterface
{
public:
DECLARE_META_INTERFACE(MediaPlayerClient);
virtual void notify(int msg, int ext1, int ext2) = 0;
};
class BnMediaPlayerClient: public BnInterface
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
在 定义中,IMediaPlayerClient类继承IInterface,并定义了一个MediaPlayer客户端的接 口,BnMediaPlayerClient继承了BnInterface,这是为基于Android的基础类Binder机制实现在进程通讯而构建的。 事实上,根据BnInterface类模版的定义BnInterface类相当于双继承了BnInterface和 ImediaPlayerClient。这是Android一种常用的定义方式。
class MediaPlayer : public BnMediaPlayerClient
{
public:
MediaPlayer();
~MediaPlayer();
void onFirstRef();
void disconnect();
status_t setDataSource(const char *url);
status_t setDataSource(int fd, int64_t offset, int64_t length);
status_t setVideoSurface(const sp& surface);
status_t setListener(const sp& listener);
status_t prepare();
status_t prepareAsync();
status_t start();
status_t stop();
status_t pause();
bool isPlaying();
status_t getVideoWidth(int *w);
status_t getVideoHeight(int *h);
status_t seekTo(int msec);
status_t getCurrentPosition(int *msec);
status_t getDuration(int *msec);
status_t reset();
status_t setAudioStreamType(int type);
status_t setLooping(int loop);
status_t setVolume(float leftVolume, float rightVolume);
void notify(int msg, int ext1, int ext2);
static sp decode(const char* url, uint32_t *pSampleRate, int* pNumChannels);
static sp decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels);
//……
}
从接口中可以看出MediaPlayer类刚好实现了一个MediaPlayer的基本操作,例如播放(start)、停止(stop)、暂停(pause)等。
class DeathNotifier: public IBinder:: DeathRecipient
{
public:
DeathNotifier() {}
virtual ~DeathNotifier();
virtual void binderDied(const wp& who);
};
事实上,MediaPlayer类正是间接地继承了IBinder,而MediaPlayer:: DeathNotifier类继承了IBinder:: DeathRecipient,这都是为了实现进程间通讯而构建的。
class IMediaPlayer: public IInterface
{
public:
DECLARE_META_INTERFACE(MediaPlayer);
virtual void disconnect() = 0;
virtual status_t setVideoSurface(const sp& surface) = 0;
virtual status_t prepareAsync() = 0;
virtual status_t start() = 0;
virtual status_t stop() = 0;
virtual status_t pause() = 0;
virtual status_t isPlaying(bool* state) = 0;
virtual status_t getVideoSize(int* w, int* h) = 0;
virtual status_t seekTo(int msec) = 0;
virtual status_t getCurrentPosition(int* msec) = 0;
virtual status_t getDuration(int* msec) = 0;
virtual status_t reset() = 0;
virtual status_t setAudioStreamType(int type) = 0;
virtual status_t setLooping(int loop) = 0;
virtual status_t setVolume(float leftVolume, float rightVolume) = 0;
};
class BnMediaPlayer: public BnInterface
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
在 IMediaPlayer类中,主要定义MediaPlayer的功能接口,这个类必须被继承才能够使用。值得注意的是,这些接口和 MediaPlayer类的接口有些类似,但是它们并没有直接的关系。事实上,在MediaPlayer类的各种实现中,一般都会通过调用 IMediaPlayer类的实现类来完成。
class IMediaPlayerService: public IInterface
{
public:
DECLARE_META_INTERFACE(MediaPlayerService);
virtual sp create(pid_t pid, const sp& client, const char* url) = 0;
virtual sp create(pid_t pid, const sp& client, int fd, int64_t offset, int64_t length) = 0;
virtual sp decode(const char* url, uint32_t *pSampleRate, int* pNumChannels) = 0;
virtual sp decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels) = 0;
};
class BnMediaPlayerService: public BnInterface
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
由 于具有纯虚函数,IMediaPlayerService 以及BnMediaPlayerService必须被继承实现才能够使用,在IMediaPlayerService定义的create和decode等 接口,事实上是必须被继承者实现的内容。注意,create的返回值的类型是sp,这个IMediaPlayer正是提供实现功能的接口。
private class MultiPlayer {
private MediaPlayer mMediaPlayer = new MediaPlayer();
}
MultiPlayer类中使用了MediaPlayer类,其中有一些对这个MediaPlayer的调用,调用的过程如下所示:
static JNINativeMethod gMethods[] = {
{"setDataSource", "(Ljava/lang/String;)V", (void *)android_media_MediaPlayer_setDataSource},
{"setDataSource", "(Ljava/io/FileDescriptor;JJ)V", (void *)android_media_MediaPlayer_setDataSourceFD},
{"prepare", "()V", (void *)android_media_MediaPlayer_prepare},
{"prepareAsync", "()V", (void *)android_media_MediaPlayer_prepareAsync},
{"_start", "()V", (void *)android_media_MediaPlayer_start},
{"_stop", "()V", (void *)android_media_MediaPlayer_stop},
{"getVideoWidth", "()I", (void *)android_media_MediaPlayer_getVideoWidth},
{"getVideoHeight", "()I", (void *)android_media_MediaPlayer_getVideoHeight},
{"seekTo", "(I)V", (void *)android_media_MediaPlayer_seekTo},
{"_pause", "()V", (void *)android_media_MediaPlayer_pause},
{"isPlaying", "()Z", (void *)android_media_MediaPlayer_isPlaying},
{"getCurrentPosition", "()I", (void *)android_media_MediaPlayer_getCurrentPosition},
{"getDuration", "()I", (void *)android_media_MediaPlayer_getDuration},
{"_release", "()V", (void *)android_media_MediaPlayer_release},
{"_reset", "()V", (void *)android_media_MediaPlayer_reset},
{"setAudioStreamType", "(I)V", (void *)android_media_MediaPlayer_setAudioStreamType},
{"setLooping", "(Z)V", (void *)android_media_MediaPlayer_setLooping},
{"setVolume", "(FF)V", (void *)android_media_MediaPlayer_setVolume},
{"getFrameAt", "(I)Landroid/graphics/Bitmap;", (void *)android_media_MediaPlayer_getFrameAt},
{"native_setup", "(Ljava/lang/Object;)V", (void *)android_media_MediaPlayer_native_setup},
{"native_finalize", "()V", (void *)android_media_MediaPlayer_native_finalize},
}
JNINativeMethod的第一个成员是一个字符串,表示了JAVA本地调用方法的名称,这个名称是在JAVA程序中调用的名称;第二个成员也是一个字符串,表示JAVA本地调用方法的参数和返回值;第三个成员是JAVA本地调用方法对应的C语言函数。
static void android_media_MediaPlayer_reset(JNIEnv *env, jobject thiz)
{
sp mp = getMediaPlayer(env, thiz);
if (mp == NULL ) {
jniThrowException(env, "java/lang/IllegalStateException", NULL);
return;
}
process_media_player_call( env, thiz, mp->reset(), NULL, NULL );
}
在android_media_MediaPlayer_reset的调用中,得到一个MediaPlayer指针,通过对它的调用实现实际的功能。
static int register_android_media_MediaPlayer(JNIEnv *env)
{
jclass clazz;
clazz = env->FindClass("android/media/MediaPlayer");
// ......
return AndroidRuntime::registerNativeMethods(env, "android/media/MediaPlayer", gMethods, NELEM(gMethods));
}
"android/media/MediaPlayer"对应JAVA的类android.media.MediaPlayer。
const sp& MediaPlayer::getMediaPlayerService()
{
Mutex::Autolock _l(mServiceLock);
if (mMediaPlayerService.get() == 0) {
sp sm = defaultServiceManager();
sp binder;
do {
binder = sm->getService(String16("media.player"));
if (binder != 0)
break;
LOGW("MediaPlayerService not published, waiting...");
usleep(500000); // 0.5 s
} while(true);
if (mDeathNotifier == NULL) {
mDeathNotifier = new DeathNotifier();
}
binder->linkToDeath(mDeathNotifier);
mMediaPlayerService = interface_cast(binder);
}
LOGE_IF(mMediaPlayerService==0, "no MediaPlayerService!?");
return mMediaPlayerService;
}
其 中最重要的一点是binder = sm->getService(String16("media.player"));这个调用用来得到一个名称为"media.player"的 服务,这个调用返回值的类型为IBinder,根据实现将其转换成类型IMediaPlayerService使用。
status_t MediaPlayer::setDataSource(const char *url)
{
LOGV("setDataSource(%s)", url);
status_t err = UNKNOWN_ERROR;
if (url != NULL) {
const sp& service(getMediaPlayerService());
if (service != 0) {
sp player(service->create(getpid(), this, url));
err = setDataSource(player);
}
}
return err;
}
在函数setDataSource函数中,调用getMediaPlayerService得到了一个IMediaPlayerService,又从 IMediaPlayerService中得到了IMediaPlayer类型的指针,通过这个指针进行着具体的操作。
class BpMediaPlayerClient: public BpInterface
{
public:
BpMediaPlayerClient(const sp& impl)
: BpInterface(impl){}
virtual void notify(int msg, int ext1, int ext2)
{
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayerClient::getInterfaceDescriptor());
data.writeInt32(msg);
data.writeInt32(ext1);
data.writeInt32(ext2);
remote()->transact(NOTIFY, data, &reply, IBinder::FLAG_ONEWAY);
}
};
还需要实现定义宏IMPLEMENT_META_INTERFACE,这个宏将被展开,生成几个函数:
class MediaPlayerService : public BnMediaPlayerService
{
class Client : public BnMediaPlayer
}
在MediaPlayerService中具有如下一个静态函数instantiate:
void MediaPlayerService::instantiate() {
defaultServiceManager()->addService(
String16("media.player"), new MediaPlayerService());
}
在instantiate函数中,调用IServiceManager的一个函数addService,向其中增加了一个名为"media.player"的服务。
static sp createPlayer(player_type playerType, void* cookie,
notify_callback_f notifyFunc)
{
sp p;
switch (playerType) {
case PV_PLAYER:
LOGV(" create PVPlayer");
p = new PVPlayer();
break;
case SONIVOX_PLAYER:
LOGV(" create MidiFile");
p = new MidiFile();
break;
case VORBIS_PLAYER:
LOGV(" create VorbisPlayer");
p = new VorbisPlayer();
break;
}
//……
return p;
}
在 这里根据playerType的类型建立不同的播放器:对于大多数情况,类型将是PV_PLAYER,这时会调用了new PVPlayer()建立一个PVPlayer,然后将其指针转换成MediaPlayerBase来使用;对于Mini文件的情况,类型为 SONIVOX_PLAYER,将会建立一个MidiFile;对于Ogg Vorbis格式的情况,将会建立一个VorbisPlayer。