Android平台下多媒体设计.docx
- 文档编号:6423583
- 上传时间:2023-01-06
- 格式:DOCX
- 页数:36
- 大小:1.06MB
Android平台下多媒体设计.docx
《Android平台下多媒体设计.docx》由会员分享,可在线阅读,更多相关《Android平台下多媒体设计.docx(36页珍藏版)》请在冰豆网上搜索。
Android平台下多媒体设计
智能平台开发部
Android平台多媒体设计
版本号
V0.1
修订内容
修订日期
拟制
文件性质
密级
审核
文件编号
批准
生效日期
发放号
发
放
至
修改记录
1>V0.1
完成时间:
2009-7-8
修改人:
修改内容:
初始版本
11、编写目的
本文档描述在Android平台中多媒体的框架设计。
在Android中,多媒体部分包括MediaPlayerr应用、mediarecorder应用(videorecorder/voicerecorder),imagecenter(imagecapture/view)、opencore等。
此文档仅仅包含MediaPlayer与opencore的架构。
12、编写背景
总结前段时间的学习,为后续工作开展打下基础
13、参考资料
N/A
14、Android总体架构图
15、Android多媒体的架构
5.1、多媒体架构概览
多媒体应用基于Android的多媒体架构。
MediaPlayer包含了Audio和Video的播放功能,在Android的界面上,Music和Video两个应用程序都是调用MediaPlayer实现的。
MediaPlayer在底层是基于Opencore(PacketVideo)的库实现的,为了构建一个MediaPlayer程序,上层还包含了进程间通讯等内容,这种进程间通讯的基础是Android基本库中的Binder机制。
5.2、多媒体总体架构图
5.3、MediaPlayer的各个库之间的结构如下图的表示:
在各个库中,libmedia.so与libmediaplayerservice.so位于核心的位置。
libmedia.so对上层的提供的接口主要是MediaPlayer类,类libmedia_jni.so通过调用MediaPlayer类提供对JAVA的接口,并且实现了android.media.MediaPlayer类。
libmediaplayerservice.so是Media的服务器,它通过继承libmedia.so的类实现服务器的功能,而libmedia.so中的另外一部分内容则通过进程间通讯和libmediaplayerservice.so进行通讯。
libmediaplayerservice.so的真正功能通过调用OpenCorePlayer(库libopencoreplayer.so)来完成。
5.4、整个MediaPlayer库和调用的关系图
从框架结构上来看,IMediaPlayerService.h、IMediaPlayerClient.h和MediaPlayer.h三个类定义了MeidaPlayer的接口和架构,MediaPlayerService.cpp和mediaplayer.coo两个文件用于MeidaPlayer架构的实现,MeidaPlayer的具体功能在PVPlayer(库libopencoreplayer.so)中的实现。
6、应用层架构分析
6.1、JAVA程序部分
在packages/apps/Music/src/com/android/music/目录的MediaPlaybackService.java文件中,包含了对MediaPlayer的调用。
在MediaPlaybackService.java中包含对包的引用:
importandroid.media.MediaPlayer;
在MediaPlaybackService类的内部,定义了MultiPlayer类:
privateclassMultiPlayer{
privateMediaPlayermMediaPlayer=newMediaPlayer();
}
MultiPlayer类中使用了MediaPlayer类,其中有一些对这个MediaPlayer的调用,调用的过程如下所示:
mMediaPlayer.reset();
mMediaPlayer.setDataSource(path);
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
reset、setDataSource和setAudioStreamType等接口就是通过JAVA本地调用(JNI)来实现的。
6.2、MediaPlayer的JAVA本地调用部分
MediaPlayer的JAVA本地调用部分在目录frameworks/base/media/jni/的android_media_MediaPlayer.cpp中的文件中实现。
android_media_MediaPlayer.cpp之中定义了一个JNINativeMethod(JAVA本地调用方法)类型的数组gMethods,如下所示:
staticJNINativeMethodgMethods[]={
{"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语言函数。
其中android_media_MediaPlayer_reset函数的实现如下所示:
staticvoid
android_media_MediaPlayer_reset(JNIEnv*env,jobjectthiz)
{
sp
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指针,通过对它的调用实现实际的功能。
register_android_media_MediaPlayer用于将gMethods注册为的类"android/media/MediaPlayer",其实现如下所示。
staticintregister_android_media_MediaPlayer(JNIEnv*env)
{
jclassclazz;
clazz=env->FindClass("android/media/MediaPlayer");
//......
returnAndroidRuntime:
:
registerNativeMethods(env,"android/media/MediaPlayer",gMethods,NELEM(gMethods));
}
"android/media/MediaPlayer"对应JAVA的类android.media.MediaPlayer
6.3、mediaplayer本地库libmedia.so
libs/media/mediaplayer.cpp文件用于实现mediaplayer.h提供的接口,其中一个重要的片段如下所示:
constsp
:
getMediaPlayerService()
{
Mutex:
:
Autolock_l(mServiceLock);
if(mMediaPlayerService.get()==0){
sp
sp
do{
binder=sm->getService(String16("media.player"));
if(binder!
=0)
break;
LOGW("MediaPlayerServicenotpublished,waiting...");
usleep(500000);//0.5s
}while(true);
if(mDeathNotifier==NULL){
mDeathNotifier=newDeathNotifier();
}
binder->linkToDeath(mDeathNotifier);
mMediaPlayerService=interface_cast
}
LOGE_IF(mMediaPlayerService==0,"noMediaPlayerService!
?
");
returnmMediaPlayerService;
}
其中最重要的一点是binder=sm->getService(String16("media.player"));这个调用用来得到一个名称为"media.player"的服务,这个调用返回值的类型为IBinder,根据实现将其转换成类型IMediaPlayerService使用。
一个具体的函数setDataSource如下所示:
status_tMediaPlayer:
:
setDataSource(constchar*url)
{
LOGV("setDataSource(%s)",url);
status_terr=UNKNOWN_ERROR;
if(url!
=NULL){
constsp
if(service!
=0){
sp
err=setDataSource(player);
}
}
returnerr;
}
在函数setDataSource函数中,调用getMediaPlayerService得到了一个IMediaPlayerService,又从IMediaPlayerService中得到了IMediaPlayer类型的指针,通过这个指针进行着具体的操作。
其他一些函数的实现也与setDataSource类似。
libmedia.so中的其他一些文件与头文件的名称相同,它们是:
libs/media/IMediaPlayerClient.cpp
libs/media/IMediaPlayer.cpp
libs/media/IMediaPlayerService.cpp
为了实现Binder的具体功能,在这些类中还需要实现一个BpXXX的类,例如IMediaPlayerClient.cpp的实现如下所示:
l
classBpMediaPlayerClient:
publicBpInterface
{
public:
BpMediaPlayerClient(constsp
:
BpInterface
{
}
virtualvoidnotify(intmsg,intext1,intext2)
{
Parceldata,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,这个宏将被展开,生成几个函数:
IMPLEMENT_META_INTERFACE(MediaPlayerClient,"android.hardware.IMediaPlayerClient");
以上的实现都是基于Binder框架的实现方式,只需要按照模版实现即可。
其中BpXXX的类为代理类(proxy),BnXXX的类为本地类(native)。
代理类的transact函数和本地类的onTransact函数实现对应的通讯。
6.4、media服务libmediaservice.so
frameworks/base/media\libmediaplayerservice目录中的MediaPlayerService.h和MediaPlayerService.cpp用于实现一个
servers/media/的服务,MediaPlayerService是继承BnMediaPlayerService的实现,在这个类的内部又定义了类Client,MediaPlayerService:
:
Client继承了BnMediaPlayer。
classMediaPlayerService:
publicBnMediaPlayerService
{
classClient:
publicBnMediaPlayer
}
在MediaPlayerService中具有如下一个静态函数instantiate:
voidMediaPlayerService:
:
instantiate(){
defaultServiceManager()->addService(
String16("media.player"),newMediaPlayerService());
}
在instantiate函数中,调用IServiceManager的一个函数addService,向其中增加了一个名为"media.player"的服务。
这个名为"media.player"的服务和mediaplayer.cpp中调用getService中得到的使用一样名称。
因此,在这里调用addService增加服务在mediaplayer.cpp中可以按照名称"media.player"来使用。
这就是使用Binder实现进程间通讯的(IPC)的作用,事实上这个MediaPlayerService类是在服务中运行的,而mediaplayer.cpp调用的功能在应用中运行,二者并不是一个进程。
但是在mediaplayer.cpp却像一个进程的调用一样调用MediaPlayerService的功能。
在MediaPlayerService.cpp中的createPlayer函数如下所示:
staticsp
notify_callback_fnotifyFunc)
{
sp
switch(playerType){
casePV_PLAYER:
LOGV("createPVPlayer");
p=newPVPlayer();
break;
caseSONIVOX_PLAYER:
LOGV("createMidiFile");
p=newMidiFile();
break;
caseVORBIS_PLAYER:
LOGV("createVorbisPlayer");
p=newVorbisPlayer();
break;
}
//……
returnp;
}
在这里根据playerType的类型建立不同的播放器:
对于大多数情况,类型将是PV_PLAYER,这时会调用了newPVPlayer()建立一个PVPlayer,然后将其指针转换成MediaPlayerBase来使用;对于Mini文件的情况,类型为SONIVOX_PLAYER,将会建立一个MidiFile;对于OggVorbis格式的情况,将会建立一个VorbisPlayer。
值得注意的是PVPlayer、MidiFile和VorbisPlayer三个类都是继承MediaPlayerInterface得到的,而MediaPlayerInterface又是继承MediaPlayerBase得到的,因此三者具有相同接口类型。
只有建立的时候会调用各自的构造函数,在建立之后,将只通过MediaPlayerBase接口来MediaPlayerBase控制它们。
在frameworks/base/media/libmediaplayerservice目录中,MidiFile.h和MidiFile.cpp的实现
MidiFile,VorbisPlayer.h和VorbisPlayer.cpp实现一个VorbisPlayer
6.5、头文件IMediaPlayerClient.h
IMediaPlayerClient.h用于描述一个MediaPlayer客户端的接口,描述如下所示:
classIMediaPlayerClient:
publicIInterface
{
public:
DECLARE_META_INTERFACE(MediaPlayerClient);
virtualvoidnotify(intmsg,intext1,intext2)=0;
};
classBnMediaPlayerClient:
publicBnInterface
{
public:
virtualstatus_tonTransact(uint32_tcode,
constParcel&data,
Parcel*reply,
uint32_tflags=0);
};
在定义中,IMediaPlayerClient类继承IInterface,并定义了一个MediaPlayer客户端的接口,BnMediaPlayerClient继承了BnInterface
事实上,根据BnInterface类模版的定义BnInterface
这是Android一种常用的定义方式
6.6、头文件mediaplayer.h
mediaplayer.h是对外的接口类,它最主要是定义了一个MediaPlayer类:
classMediaPlayer:
publicBnMediaPlayerClient
{
public:
MediaPlayer();
~MediaPlayer();
voidonFirstRef()
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Android 平台 多媒体 设计