1、Android平台下多媒体设计智能平台开发部Android平台多媒体设计 版本号V0.1修订内容修订日期拟 制 文件性质密 级审 核文件编号批 准生效日期发放号发放至修改记录1 V0.1 完成时间: 2009-7-8修改人: 修改内容:初始版本11、编写目的本文档描述在Android平台中多媒体的框架设计。在Android中,多媒体部分包括MediaPlayerr应用、media recorder应用(video recorder/voice recorder),image center(image capture/view)、opencore等。此文档仅仅包含MediaPlayer与open
2、core的架构。12、编写背景总结前段时间的学习,为后续工作开展打下基础13、参考资料N/A14、Android总体架构图15、Android多媒体的架构5.1、多媒体架构概览多媒体应用基于Android的多媒体架构。MediaPlayer包含了Audio和Video的播放功能,在Android的界面上,Music和Video两个应用程序都是调用MediaPlayer实现的。MediaPlayer在底层是基于Opencore(PacketVideo)的库实现的,为了构建一个MediaPlayer程序,上层还包含了进程间通讯等内容,这种进程间通讯的基础是Android基本库中的Binder机制。
3、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中的另外一部分内容则通过进程间通讯和lib
4、mediaplayerservice.so进行通讯。libmediaplayerservice.so的真正功能通过调用OpenCore Player(库libopencoreplayer.so)来完成。5.4、整个MediaPlayer库和调用的关系图从框架结构上来看,IMediaPlayerService.h、IMediaPlayerClient.h和MediaPlayer.h三个类定义了MeidaPlayer的接口和架构,MediaPlayerService.cpp和mediaplayer.coo两个文件用于MeidaPlayer架构的实现,MeidaPlayer的具体功能在PVPlaye
5、r(库libopencoreplayer.so)中的实现。6、应用层架构分析6.1、JAVA程序部分在packages/apps/Music/src/com/android/music/目录的MediaPlaybackService.java文件中,包含了对MediaPlayer的调用。 在MediaPlaybackService.java中包含对包的引用:import android.media.MediaPlayer; 在MediaPlaybackService类的内部,定义了MultiPlayer类:private class MultiPlayer private MediaPlaye
6、r mMediaPlayer = new MediaPlayer(); MultiPlayer类中使用了MediaPlayer类,其中有一些对这个MediaPlayer的调用,调用的过程如下所示: mMediaPlayer.reset(); mMediaPlayer.setDataSource(path); mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); reset、setDataSource和setAudioStreamType等接口就是通过JAVA本地调用(JNI)来实现的。6.2、MediaPlayer的JAVA本地
7、调用部分 MediaPlayer的JAVA本地调用部分在目录frameworks/base/media/jni/的android_media_MediaPlayer.cpp中的文件中实现。 android_media_MediaPlayer.cpp之中定义了一个JNINativeMethod(JAVA本地调用方法)类型的数组gMethods,如下所示:static JNINativeMethod gMethods = setDataSource, (Ljava/lang/String;)V, (void *)android_media_MediaPlayer_setDataSource, se
8、tDataSource, (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
9、_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 *)a
10、ndroid_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, setAudio
11、StreamType, (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,
12、 (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_rese
13、t函数的实现如下所示:static voidandroid_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的
14、调用中,得到一个MediaPlayer指针,通过对它的调用实现实际的功能。 register_android_media_MediaPlayer用于将gMethods注册为的类android/media/MediaPlayer,其实现如下所示。 static int register_android_media_MediaPlayer(JNIEnv *env) jclass clazz; clazz = env-FindClass(android/media/MediaPlayer);/ . return AndroidRuntime:registerNativeMethods(env, an
15、droid/media/MediaPlayer, gMethods, NELEM(gMethods); android/media/MediaPlayer对应JAVA的类android.media.MediaPlayer6.3、mediaplayer本地库libmedia.so libs/media/mediaplayer.cpp文件用于实现mediaplayer.h提供的接口,其中一个重要的片段如下所示:const sp& MediaPlayer:getMediaPlayerService() Mutex:Autolock _l(mServiceLock); if (mMediaPlayer
16、Service.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-link
17、ToDeath(mDeathNotifier); mMediaPlayerService = interface_cast(binder); LOGE_IF(mMediaPlayerService=0, no MediaPlayerService!?); return mMediaPlayerService; 其中最重要的一点是binder = sm-getService(String16(media.player);这个调用用来得到一个名称为media.player的服务,这个调用返回值的类型为IBinder,根据实现将其转换成类型IMediaPlayerService使用。 一个具体的函数
18、setDataSource如下所示: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; 在函数s
19、etDataSource函数中,调用getMediaPlayerService得到了一个IMediaPlayerService,又从IMediaPlayerService中得到了IMediaPlayer类型的指针,通过这个指针进行着具体的操作。 其他一些函数的实现也与setDataSource类似。 libmedia.so中的其他一些文件与头文件的名称相同,它们是:libs/media/IMediaPlayerClient.cpp libs/media/IMediaPlayer.cpp libs/media/IMediaPlayerService.cpp 为了实现Binder的具体功能,在这些
20、类中还需要实现一个BpXXX的类,例如IMediaPlayerClient.cpp的实现如下所示:lclass BpMediaPlayerClient: public BpInterfacepublic: BpMediaPlayerClient(const sp& impl) : BpInterface(impl) virtual void notify(int msg, int ext1, int ext2) Parcel data, reply; data.writeInterfaceToken(IMediaPlayerClient:getInterfaceDescriptor(); da
21、ta.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框架的实现方式,只需要按照模版实现即可。其中BpXX
22、X的类为代理类(proxy),BnXXX的类为本地类(native)。代理类的transact函数和本地类的onTransact函数实现对应的通讯。6.4、media服务libmediaservice.soframeworks/base/medialibmediaplayerservice目录中的MediaPlayerService.h和MediaPlayerService.cpp用于实现一个servers/media/的服务,MediaPlayerService是继承BnMediaPlayerService的实现,在这个类的内部又定义了类Client,MediaPlayerService:C
23、lient继承了BnMediaPlayer。class MediaPlayerService : public BnMediaPlayerService class Client : public BnMediaPlayer 在MediaPlayerService中具有如下一个静态函数instantiate:void MediaPlayerService:instantiate() defaultServiceManager()-addService( String16(media.player), new MediaPlayerService(); 在instantiate函数中,调用ISe
24、rviceManager的一个函数addService,向其中增加了一个名为media.player的服务。 这个名为media.player的服务和mediaplayer.cpp中调用getService中得到的使用一样名称。因此,在这里调用addService增加服务在mediaplayer.cpp中可以按照名称media.player来使用。这就是使用Binder实现进程间通讯的(IPC)的作用,事实上这个MediaPlayerService类是在服务中运行的,而mediaplayer.cpp调用的功能在应用中运行,二者并不是一个进程。但是在mediaplayer.cpp却像一个进程的调
25、用一样调用MediaPlayerService的功能。 在MediaPlayerService.cpp中的createPlayer函数如下所示: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);
26、 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格式的情况,将会建立一个Vo
27、rbisPlayer。 值得注意的是PVPlayer、MidiFile和VorbisPlayer三个类都是继承MediaPlayerInterface得到的,而MediaPlayerInterface又是继承MediaPlayerBase得到的,因此三者具有相同接口类型。只有建立的时候会调用各自的构造函数,在建立之后,将只通过MediaPlayerBase接口来MediaPlayerBase控制它们。 在frameworks/base/media/libmediaplayerservice目录中,MidiFile.h和MidiFile.cpp的实现MidiFile,VorbisPlayer.h
28、和VorbisPlayer.cpp实现一个VorbisPlayer6.5、头文件IMediaPlayerClient.hIMediaPlayerClient.h用于描述一个MediaPlayer客户端的接口,描述如下所示:class IMediaPlayerClient: public IInterfacepublic: DECLARE_META_INTERFACE(MediaPlayerClient); virtual void notify(int msg, int ext1, int ext2) = 0;class BnMediaPlayerClient: public BnInterf
29、acepublic: 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一种常用的定义方式6.6、头文件mediaplayer.hmediaplayer.h是对外的接口类,它最主要是定义了一个MediaPlayer类:class MediaPlayer : public BnMediaPlayerClientpublic: MediaPlayer(); MediaPlayer(); void onFirstRef()
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1