MediaPlayer框架概述(二)

最后更新于:2022-04-01 14:45:52

### 3 mediaplayer的核心库libmedia.so libs/media/mediaplayer.cpp文件用于实现mediaplayer.h提供的接口,其中一个重要的片段如下所示: ~~~ const sp<IMediaPlayerService>& MediaPlayer::getMediaPlayerService() { Mutex::Autolock _l(mServiceLock); if (mMediaPlayerService.get() == 0) { sp<IServiceManager> sm = defaultServiceManager(); sp<IBinder> 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<IMediaPlayerService>(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<IMediaPlayerService>& service(getMediaPlayerService()); if (service != 0) { sp<IMediaPlayer> player(service->create(getpid(), this, url)); err = setDataSource(player); } } return err; } ~~~ 在函数setDataSource函数中,调用getMediaPlayerService得到了一个IMediaPlayerService,又从IMediaPlayerService中得到了IMediaPlayer类型的指针,通过这个指针进行着具体的操作。 其他一些函数的实现也与setDataSource类似。 为了实现Binder的具体功能,在这些类中还需要实现一个BpXXX的类,例如IMediaPlayerClient.cpp的实现如下所示:l ~~~ class BpMediaPlayerClient: public BpInterface<IMediaPlayerClient> { public: BpMediaPlayerClient(const sp<IBinder>& impl) : BpInterface<IMediaPlayerClient>(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); } }; ~~~ 以上的实现都是基于Binder框架的实现方式,只需要按照模版实现即可。其中BpXXX的类为代理类(proxy),BnXXX的类为本地类(native)。代理类的transact函数和本地类的onTransact函数实现对应的通讯。 ### 4 media服务libmediaservice.so 多媒体服务的守护进程的代码:frameworks/base/media/mediaserver/其中只有一个源文件main_mediaserver.cpp,将被编译成为一个可执行程序mediaserver。它负责启 动了多媒体服务、照相机服务,音频服务这三个服务 ~~~ int main(int argc, char** argv) { sp<ProcessState> proc(ProcessState::self()); sp<IServiceManager> sm = defaultServiceManager(); LOGI("ServiceManager: %p", sm.get()); AudioFlinger::instantiate(); MediaPlayerService::instantiate(); CameraService::instantiate(); AudioPolicyService::instantiate(); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); } ~~~ frameworks/base/media\libmediaplayerservice目录中的MediaPlayerService.h和MediaPlayerService.cpp用于实现一个 servers/media/的服务,MediaPlayerService是继承BnMediaPlayerService的实现,在这个类的内部又定义了类Client,MediaPlayerService::Client继承了BnMediaPlayer。 ~~~ 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"的服务。 这个名为"media.player"的服务和mediaplayer.cpp中调用getService中得到的使用一样名称。因此,在这里调用addService增加服务在mediaplayer.cpp中可以按照名称"media.player"来使用。这就是使用Binder实现进程间通讯的(IPC)的作用,事实上这个MediaPlayerService类是在服务中运行的,而mediaplayer.cpp调用的功能在应用中运行,二者并不是一个进程。但是在mediaplayer.cpp却像一个进程的调用一样调用MediaPlayerService的功能。  在MediaPlayerService.cpp中的createPlayer函数如下所示: ~~~ static sp<MediaPlayerBase> createPlayer(player_type playerType, void* cookie, notify_callback_f notifyFunc) { sp<MediaPlayerBase> p; switch (playerType) { #ifndef NO_OPENCORE case PV_PLAYER: LOGV(" create PVPlayer"); p = new PVPlayer(); break; #endif case SONIVOX_PLAYER: LOGV(" create MidiFile"); p = new MidiFile(); break; case VORBIS_PLAYER: LOGV(" create VorbisPlayer"); p = new VorbisPlayer(); break; #if BUILD_WITH_FULL_STAGEFRIGHT case STAGEFRIGHT_PLAYER: LOGV(" create StagefrightPlayer"); p = new StagefrightPlayer; break; #endif case TEST_PLAYER: LOGV("Create Test Player stub"); p = new TestPlayerStub(); break; } if (p != NULL) { if (p->initCheck() == NO_ERROR) { p->setNotifyCallback(cookie, notifyFunc); } else { p.clear(); } } if (p == NULL) { LOGE("Failed to create player object"); } return p; } ~~~ 在这里根据playerType的类型建立不同的播放器:对于大多数情况,类型将是PV_PLAYER,这时会调用了new PVPlayer()建立一个PVPlayer,然后将其指针转换成MediaPlayerBase来使用;对于Mini文件的情况,类型为SONIVOX_PLAYER,将会建立一个MidiFile;对于Ogg Vorbis格式的情况,将会建立一个VorbisPlayer。 (OGG Vobis是一种音频压缩格式,与[MP3](http://digital.it168.com/files/music.asp)等的音乐格式类似,它具有完全免费、开放和没有专利限制的特点。) 值得注意的是PVPlayer、MidiFile和VorbisPlayer三个类都是继承MediaPlayerInterface得到的,而MediaPlayerInterface又是继承MediaPlayerBase得到的,因此三者具有相同接口类型。只有建立的时候会调用各自的构造函数,在建立之后,将只通过MediaPlayerBase接口来MediaPlayerBase控制它们。    在frameworks/base/media/libmediaplayerservice目录中,MidiFile.h和MidiFile.cpp的实现MidiFile,VorbisPlayer.h和VorbisPlayer.cpp实现一个VorbisPlayer。
';