Android音视频开发入门(4)MediaPlayerService

网友投稿 265 2022-11-16

Android音视频开发入门(4)MediaPlayerService

​​MediaPlayerService​​是多媒体框架中一个非常重要的服务,从前面的内容我们可以知道在 MediaPlayer的C/S模式中

​​MediaPlayerService​​​和​​MediaPlayerService::Client​​​是服务器端。MediaPlayerServier实现了​​IMediaPlayerService​​​定义的业务逻辑。其主要功能是​​​MediaPlyaer::setDataSource​​​输入的url调用​​create()​​创建对应的player。​​MediaPlayer::Client​​​实现​​IMediaPlayer​​定义的业务逻辑,其主要功能包括 start、stop、pause、resume…

1. Client/server通过IPC的通信流程图

Android中的通信很多都是通过Binder机制来完成的,对于MediaPlayer和MediaPlayerService也不例外。 我们来看看下面的C/S Binder通信图:

从图中可以总结出下面几点:

MediaPlayer是客户端也就是 C/S中的 Client层MediaPlayerService和MediaPlayerService::Client是服务端,也就是我们说的 C/S模型中的S层MediaPlayerService实现 IMediaPlayerService 定义的业务逻辑MediaPlayerService::Client 实现 IMediaPlayer定义的业务逻辑通过​​Transact()​​​可以向远端的IBinder对象发出调用,通过​​onTransact()​​可以使你自己的远程对象能够响应接收到的调用。

2. 相关联类图

我们知道Binder通信时,需要通过 IBinder接口转化具体的实体对象,那么中间会有很多其它类,下面看看类关系图:

细品IPC通信图,可以得出下面的结论:

BnXXX 和 BpXXX都派生自两个类class BpXXX : public IMediaPlayerService, public BpRefBaseclass BnXXX : public IMediaPlayerService, public BBinderBpXXX和BnXXX都派生自 IMediaPlayerService,我们之前说过,IMediaPlayerService使用来定义一些功能的接口的,而派生出两个类,所以它们虽然使用了相同的接口,但是他们有不同的实现方式。BpXXX中:把对应的binder_transaction_data 打包之后,通过BpRefBase中的 mRemote(BpBinder)发送出去,并等待结果BnXXX中:实现对应的业务逻辑,通过调用 BnXXX 派生类中的方法来实现,如​​​MediaPlayerService::Client​​IBinder用于进程间通信BpRefBase中有一个​​​remote()​​​用来与Binder驱动交互Binder是用来从Binder驱动中接收相关请求并进行相关处理的BpBinder和BinderDriver进行互通

3. MediaPlayerService产生过程

我们从入口看,入口在 /frameworks/av/media/mediaserver/main_mediaserver.cpp:

int main(int argc __unused, char **argv __unused){ //信号 signal(SIGPIPE, SIG_IGN); //进程赋值处理 sp proc(ProcessState::self()); sp sm(defaultServiceManager()); ALOGI("ServiceManager: %p", sm.get()); InitializeIcuOrDie(); MediaPlayerService::instantiate(); ResourceManagerService::instantiate(); registerExtensions(); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool();}

从第一个有意义的函数 ​​defaultServiceManager()​​,它在/frameworks/native/libs/binder/IServiceManager.cpp:

p defaultServiceManager(){ //如果存在一个 BpServiceManager就返回它 if (gDefaultServiceManager != NULL) return gDefaultServiceManager; //单例模式 { AutoMutex _l(gDefaultServiceManagerLock); while (gDefaultServiceManager == NULL) { gDefaultServiceManager = interface_cast( ProcessState::self()->getContextObject(NULL)); if (gDefaultServiceManager == NULL) sleep(1); } } return gDefaultServiceManager;}

这种构建模式其实是我们熟悉的 单例模式。每个进程都只需要构建出一个 BpServiceManager代理,​​​ProcessState::self() -> getContextObject(NULL)​​,接下来看看 getContextObject(),它在 /frameworks/native/libs/binder/ProcessState.cpp中:

sp ProcessState::getContextObject(const sp& /*caller*/){ return getStrongProxyForHandle(0);}sp ProcessState::getStrongProxyForHandle(int32_t handle){ sp result; AutoMutex _l(mLock); //在数组 mHandleToObject里面根据handle索引查找handle_entry结构体 handle_entry* e = lookupHandleLocked(handle); if (e != NULL) { //指向结构体中的binder地址 IBinder* b = e->binder; if (b == NULL || !e->refs->attemptIncWeak(this)) { if (handle == 0) { Parcel data; status_t status = IPCThreadState::self()->transact( 0, IBinder::PING_TRANSACTION, data, NULL, 0); if (status == DEAD_OBJECT) return NULL; } //BpBinder新建一个IBinder BpBinder.create(0) b = BpBinder::create(handle); e->binder = b; if (b) e->refs = b->getWeakRefs(); result = b; } else { result.force_set(b); e->refs->decWeak(this); } } return result;}struct handle_entry{ IBinder* binder; RefBase::weakref_type* refs;}

总结代码: 传入的句柄handler的值为0,表示ServiceManager,构建一个BpBinder,所以现在相当于 ​​​gDefaultServiceManager = interface_cast(BpBinder.create(0))​​

接下来看看 ​​interface_cast()​​是什么:

inline sp interface_cast(const sp& obj){ return IServiceManager::asInterface(obj);}...asInteface(){ ... //这里构建了一个新的BoServiceManager对象 intr = new BpServiceManager(obj)}

其asInterface最终还是创建出一个 BpServiceManager对象。

所以​​defaultServiceManager()​​就是 句柄handle(0)创建一个 BpBinder(0),跟举这个BpBinder创建出一个 BpServiceManager代理。 下面来分析一下​​​BpServiceManager​​ 这个类是什么成分,代码如下:

class BpServiceManager : public BpInterface { public: explicit BpServiceManager(const sp& impl) : BpInterface(impl) {} };

这里的 它继承了 ​​BpInterface​​​,它是一个模板类,这里相当于它同时 继承了 ​​BpInterface​​​和 ​​IServiceManager​​​ 而 ​​BpInterface​​在用到它的构造函数时,就会 去添加服务内部。 在 MediaPlayerSrvice.cpp中有一个 ​​instantiate()​​,通过ServiceManager来添加MediaPlayerService服务:

void MediaPlayerService::instantiate() { defaultServiceManager()->addService( String16("media.player"), new MediaPlayerService());}

​​defaultServiceManager()​​​ 返回的是刚创建的BpServiceManager,并调用它的 addService() BpMediaPlayerService作为服务端代理,那么BnMediaPlayerService一定是实现端 MediaPlayerService继承自 BnMediaPlayerService,实现了真正的的业务函数。

4. 添加服务的过程

下面分析一下 BpServiceManager的 ​​addService()​​

virtual status_t addService(const String16& name, const sp& service, bool allowIsolated, int dumpsysPriority) { Parcel data, reply; data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor()); data.writeString16(name); //也就是MediaPlayerService data.writeStrongBinder(service); data.writeInt32(allowIsolated ? 1 : 0); data.writeInt32(dumpsysPriority); status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply); return err == NO_ERROR ? reply.readExceptionCode() : err; }

这里的 remote函数返回的就是 前面创建的 BpBinder(0)对象:

status_t BpBinder::transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { // Once a binder has died, it will never come back to life. if (mAlive) { status_t status = IPCThreadState::self()->transact( mHandle, code, data, reply, flags); if (status == DEAD_OBJECT) mAlive = 0; return status; } return DEAD_OBJECT; }status_t IPCThreadState::transact(int32_t handle, uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { ... //发送addTransactionData err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL); ... } else { //等待响应 err = waitForResponse(NULL, NULL); } return err; } status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags, int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer) { //cmd BC_TRANSACTION 应用程序向Binder发送的命令 binder_transaction_data tr; tr.target.handle = handle; tr.code = code; tr.flags = binderFlags; ... //把命令和数据一起发送到 Parcel mOut中 mOut.writeInt32(cmd); mOut.write(&tr, sizeof(tr)); return NO_ERROR; }status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult) { uint32_t cmd; while (1) { //和Driver进行沟通后获得结果 if ((err=talkWithDriver()) < NO_ERROR) break; cmd = (uint32_t)mIn.readInt32(); switch (cmd) { case BR_TRANSACTION_COMPLETE: ... break; } } return err; }status_t IPCThreadState::talkWithDriver(bool doReceive) { binder_write_read bwr; bwr.write_size = outAvail; //写入 mOut的数据 bwr.write_buffer = (uintptr_t) mOut.data(); bwr.read_size = mIn.dataCapacity(); bwr.read_buffer = (uintptr_t) mIn.data(); ... //把mOut写到Binder中,并读取mIn的数据 if (ioctl(mProcess -> mDriverFD, BINDER_WRITE_READ, & bwr) >=0) err = NO_ERROR; ... return err; }

joinThreadPool、startThreadPool 进入线程循环 talkWithDriver等待客户端Client请求,从Binder读取命令请求进行处理。到现在为止,MediaPlayerService的服务端已经向总管 ServiceManager注册了。

5. 通过BinderDriver和MediaPlayer通信的过程

下面看看客户端是如何获得服务的代理并和服务端通信的。 我们以 MediaPlayer的业务函数解码解析播放一个 网络视频的URL为例。

首先在 MediaPlayer ​​decode(url)​​​时,首先调用了 getMediaPlayerService() 我们来看看这个函数:

:: getMediaPlayerService() { //生成一个BpServiceManager代理对象 sp sm = defaultServiceManager(); sp binder; do { //获取String16("media.player")的服务对象 binder = sm -> getService(String16("media.player")); if (binder != 0) { break; } usleep(500000); // 0.5 s } while (true); ... sMediaPlayerService = interface_cast < IMediaPlayerService > (binder); return sMediaPlayerService; }

Client端的MediaPlayer先获取一个 BpServiceManager的代理,然后调用其 ​​getService()​​向服务总管 ServiceManager查询名叫 String16(“media.player”)的服务,这个getService的方法处于 /frameworks/native/libs/binder/ 的 IServiceManager.cpp:

class BpServiceManager :public BpInterface { public: virtual sp getService(const String16 & name) const { int n = 0; while (uptimeMillis() < timeout) { n++; //调用checkService函数 sp svc = checkService(name); if (svc != NULL) return svc; } return NULL; } virtual sp checkService( const String16 & name) const { Parcel data, reply; //首先调用writeInterfaceToken,然后写入 android.os.IServiceManager data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor ()); //写入media.player data.writeString16(name); //然后通过Binder把data及reply的数据通知出去,在onTransact函数中进行回调 remote()->transact(CHECK_SERVICE_TRANSACTION, data, & reply); return reply.readStrongBinder(); } }

这里首先将请求打包成Parcel格式,然后调用 ​​remote->transact​​​函数,前面我们分析过 BpServiceManager::remote返回的就是 ​​newBpBinder(0)​​,对应的句柄为 ServiceManager。继续在BpBinder中寻找实现代码:

status_t BpBinder::transact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){ IPCThreadState::self()->transact(mHandle, code, data, reply, flags);}

最后调用 ​​IPCThreadState​​的transact函数,在Android中 ProcessState是哭护短和服务端的公共部分,作为Binder通信的基础,ProcessState是一个singleton类, 每个进程只有一个对象,这个对象负责打开Binder驱动,建立线程池,让其进程里面的所有线程都能通过Binder通信。

与之相关的就是 ​​IPCThreadState​​,每个线程都有一个IPCThreadState实例登记在Linux线程的上下文附属数据中,主要负责Binder的读取、写入和请求处理框架。

IPCThreadState在构造的时候获取进程的ProcessState并记录在自己的成员变量中:

status_t IPCThreadState::transact(int32_t handle,uint32_t code, const Parcel&data,Parcel*reply, uint32_t flags) { status_t err; //填充 binder_transaction_data 结构体,写入mOut中 //这里就是把 "media.player"、"android.os.IServiceManager"等写进去 err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL); .. //然后等待返回 waitForResponse(reply); return err; } status_t IPCThreadState:: waitForResponse(Parcel *reply, status_t *acquireResult) { while (1) { talkWithDriver()) //输入mOut,输出mIn cmd = mIn.errorCheck(); switch (cmd) { case BR_REPLY: { binder_transaction_data tr; if ((tr.flags & TF_STATUS_CODE) == 0) { reply -> ipcSetDataReference( reinterpret_cast (tr.data.ptr.buffer), tr.data_size, reinterpret_cast (tr.data.ptr.offsets), tr.offsets_size / sizeof(binder_size_t), freeBuffer, this); } else { err = *reinterpret_cast (tr.data.ptr.buffer); freeBuffer(NULL, reinterpret_cast (tr.data.ptr.buffer), tr.data_size, reinterpret_cast (tr.data.ptr.offsets), tr.offsets_size / sizeof(binder_size_t), this); } } } } }

waitForResponse返回的是一个 ​​readStrongBinder()​​,进入Parcel的readStrongBinder()中:

unflatten_binder(const sp& proc, const Parcel& in, wp* out) { const flat_binder_object * flat = in.readObject(false); if (flat) { switch (flat->hdr.type) { case BINDER_TYPE_BINDER: *out = reinterpret_cast(flat->cookie); return finish_unflatten_binder(NULL, *flat, in); case BINDER_TYPE_HANDLE: *out = proc->getStrongProxyForHandle(flat->handle); return finish_unflatten_binder( static_cast(out->get()), *flat, in); } } }

这里的flat->type是BINDER_TYPE_HANDLE,所以调用 ​​ProcessState::getStrongProxyForHandle()​​:

sp ProcessState::getStrongProxyForHandle(int32_t handle) { sp result; handle_entry* e = lookupHandleLocked(handle); if (e != NULL) { IBinder* b = e->binder; if (b == NULL || !e->refs->attemptIncWeak(this)) { b = BpBinder::create(handle); e->binder = b; if (b) e->refs = b->getWeakRefs(); result = b; } else { result.force_set(b); e->refs->decWeak(this); } } return result; }

这里的handle就是ServiceManager内维护的MediaPlayerService对应的Binder句柄。 这个ProcessState根据这个句柄创建了一个 BpBinder,并将其保存了起来。这样下次需要的时候就从ServiceManager请求获取相同的句柄就可以直接返回了。

根据这个返回的BpBinder获得MediaPlayerService的代理:

sMediaPlayerService = interface_cast(binder);

和前面的ServiceManager一样,调用IMediaPlayerService的​​asInterface​​宏函数,就可以获得一个代理BpMediaPlayerService对象,它的remote为BpBinder(handle),这个handle就是向服务总管ServiceManager查询到的MediaPlayerService对应的Binder句柄。

最后总结一下:

在实际业务中,如当 MediaPlayer::setDataSource 返回时,会创建一个与​​MediaPlayerService::Client​​对应的BpMediaPlayer,用于获取 MediaPlayerService::Client的各项功能​​MediaPlayer​​​又是如何找到​​MediaPlayerService::Client​​​的呢?只有MediaPlayerService向ServiceManager进行了注册才可以,所以MediaPlayer必须先获取​​BpMediaPlayerService​​,然后通过BpMediaService的管理功能创建一个MediaPlayerService::Client为什么不直接定义一个MediaPlayer,让其向 ServiceManager注册呢?​​​MediaPlayerService​​​包含的功能不仅是 Client,还有 AudioOutput、AudioCache、MediaConfigClient等功能。MediaPlayerService就是一个 媒体服务的窗口

6. 创建播放器

在MediaPlayer的构造函数中,会预先注册一些播放器的Factory。很多ROM厂商如果要应用自己写的播放器,也需要有一个Factory,这里也是一样的:

MediaPlayerService::MediaPlayerService() { ALOGV("MediaPlayerService created"); mNextConnId = 1; //注册一些播放器的Factory MediaPlayerFactory::registerBuiltinFactories(); } void MediaPlayerFactory::registerBuiltinFactories() { Mutex::Autolock lock_(&sLock); IFactory* factory = new NuPlayerFactory(); //注册两个 Factory if (registerFactory_l(factory, NU_PLAYER) != OK) delete factory; factory = new TestPlayerFactory(); if (registerFactory_l(factory, TEST_PLAYER) != OK) delete factory; sInitComplete = true; }

通过 ​​registerFactory_l(factory, NU_PLAYER)​​​会创建一个 ​​NuPlayer​​​ 通过​​​registerFactory_l(factory, TEST_PLAYER)​​​会创建一个 ​​TestPlayer​​ 第一个NuPlayer比较重要,我们来看看它的工厂创建方法:

class NuPlayerFactory : public MediaPlayerFactory::IFactory { public: virtual float scoreFactory(const sp& /*client*/, const char* url, float curScore) { static const float kOurScore = 0.8; if (!strncasecmp("url, 7) || !strncasecmp("url, 8) || !strncasecmp("file://", url, 7)) { //如果是 size_t len = strlen(url); //后缀是 .m3u8 if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) { return kOurScore; } if (strstr(url,"m3u8")) { return kOurScore; } //如果是SDP协议 if ((len >= 4 && !strcasecmp(".sdp", &url[len - 4])) || strstr(url, ".sdp?")) { return kOurScore; } } //如果是 RTSP协议 if (!strncasecmp("rtsp://", url, 7)) { return kOurScore; } return 0.0; } ... virtual sp createPlayer(pid_t pid) { return new NuPlayerDriver(pid); } };

最后没有返回一个 NuPlayer,而是创建了NuPlayerDriver,实际上是在NuPlayerDriver的构造函数中,创建了 一个NuPlayer。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:详细聊聊Mybatis中万能的Map
下一篇:Android Gradle文件拆解
相关文章

 发表评论

暂时没有评论,来抢沙发吧~