c语言sscanf函数的用法是什么
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::ClientIBinder用于进程间通信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
从第一个有意义的函数 defaultServiceManager(),它在/frameworks/native/libs/binder/IServiceManager.cpp:
p
这种构建模式其实是我们熟悉的 单例模式。每个进程都只需要构建出一个 BpServiceManager代理,ProcessState::self() -> getContextObject(NULL),接下来看看 getContextObject(),它在 /frameworks/native/libs/binder/ProcessState.cpp中:
sp
总结代码: 传入的句柄handler的值为0,表示ServiceManager,构建一个BpBinder,所以现在相当于 gDefaultServiceManager = interface_cast(BpBinder.create(0))
接下来看看 interface_cast()是什么:
inline sp
其asInterface最终还是创建出一个 BpServiceManager对象。
所以defaultServiceManager()就是 句柄handle(0)创建一个 BpBinder(0),跟举这个BpBinder创建出一个 BpServiceManager代理。 下面来分析一下BpServiceManager 这个类是什么成分,代码如下:
class BpServiceManager : public BpInterface
这里的 它继承了 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
这里的 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
Client端的MediaPlayer先获取一个 BpServiceManager的代理,然后调用其 getService()向服务总管 ServiceManager查询名叫 String16(“media.player”)的服务,这个getService的方法处于 /frameworks/native/libs/binder/ 的 IServiceManager.cpp:
class BpServiceManager :public BpInterface
这里首先将请求打包成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
waitForResponse返回的是一个 readStrongBinder(),进入Parcel的readStrongBinder()中:
unflatten_binder(const sp
这里的flat->type是BINDER_TYPE_HANDLE,所以调用 ProcessState::getStrongProxyForHandle():
sp
这里的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
最后没有返回一个 NuPlayer,而是创建了NuPlayerDriver,实际上是在NuPlayerDriver的构造函数中,创建了 一个NuPlayer。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~