【学习】从零开始的Android音视频开发(6)——MediaPlayerService中BinderDriver、创建播放器过程、建立StageFright层交互

通过BinderDriver和MediaPlayer通信的过程

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

在这里插入图片描述

这里主要分析getMediaPlayerService,即客户端是如何向ServiceManager总管查询服务并获得代理的

在这里插入图片描述

上图先获得BpServiceManager的代理,然后调用getService函数向服务总管ServiceManager查询名叫String16("media.player")的服务,其处于frameworks/base/libs/binder/IServiceManager.cpp中(仅展示部分代码)

在这里插入图片描述

这里首先将请求打包成Parcel格式,然后调用remote->transact函数,前面我们分析过BpServiceManager::remote返回的就是new BpBinder(0),对应的句柄为ServiceManager,在frameworks/base/libs/binder/BpBinder.cpp中可以找到实现代码

在这里插入图片描述

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

与之相关的是IPCThreadState,每个线程都有一个IPCThreadState实例登记在Linux线程的上下文附属数据中主要负责Binder的读取、写入和请求处理框架。IPCThreadState在构造的时候获取进程的ProcessState并记录在自己的成员变量中

IPCThreadState::transact中(部分代码)

在这里插入图片描述
在这里插入图片描述

通过writeTransactionData函数来填充mOut结构体,mOut内容如下

在这里插入图片描述

tr内容如下
在这里插入图片描述

tr.data内容如下

在这里插入图片描述
在这里插入图片描述

waitForResponse函数是关键
在这里插入图片描述
在这里插入图片描述

返回的是reply.readStrongBinder().在waitForResponse方法中,收到消息以后这个reply不为空,此时进入reply的ipcSetDataReference方法中,这个reply是Parcel对象,调用了Parcel的ipcSetDataReference方法将ServiceManager返回过来的数据设置到parcel对象中。waitForResponse()执行完BR_REPLY之后,便返回到IPCThreadState::transact()中;然后返回,到退回到Java层的ServiceManagerProxy.getService方法时,调用reply的readStrongBinder方法
在这里插入图片描述
在这里插入图片描述

这里的flat->typeBINDER_TYPE_HANDLE,所以调用ProcessState::getStrongProxyForHandle函数

在这里插入图片描述

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

根据这个从getService中返回的BpBinder获得MediaPlayerService的代理
在这里插入图片描述

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

总结

1.在实际业务中,当MediaPlayer::setDataSource返回时,会创建一个与MediaPlayerService::Client对应的BpMediaPlayer,用于获取MediaPlayerService::Client的各项功能

2.MediaPlayer要想找到MediaPlayerService::Client必须MediaPlayerService向ServiceManager进行注册才可以,所以MediaPlayer必须先获取BpMediaPlayerService,然后通过BpMediaPlayerService的管理功能创建一个MediaPlayerService::Client

3.MediaPlayerService包含的功能不仅是Client,还有AudioOutput、AudioCache、MediaConfigClient功能。MediaPlayerService就是一个媒体服务的窗口(Driver类似一个场地,在场地内沟通好信息),MediaPlayerService把生意谈好,合同签回来,再根据合同上的要求安排不同的开发人员去做

创建播放器

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

通过StagefrightPlayerFactory创建一个StagefrightPlayer(高版本中已经没有该播放器了)

在这里插入图片描述

通过NuPlayerFactory可以创建一个NuPlayer
在这里插入图片描述

这里没有直接创建一个NuPlayer,而是创建了一个NuPlayerDriver,实际上是在NuPlayerDriver的构造函数中创建了一个NuPlayer

建立StageFright层交互

前面建立的NuPlayer要和StageFright层进行交互,下图是它们两个的关系

在这里插入图片描述

从上图可以看出StagefrightPlayer/StagefrightRecorder以及NuPlayer都属于MediaPlayerService层,源码libmediaplayerservice目录如下(没有StagefrightPlayer是因为版本问题)

在这里插入图片描述

上面的文件在编译后会生成libmediaplayerservice.so文件,当要继续处理从MediaPlayer传过来的事件时,就需要到达libstagefright.so中,如AwesomePlayer、MediaExtractor、MediaMuxer、MediaBuffer、MediaSource、MediaCodec等,可以看出这些都是多媒体框架的核心部分,用于数据解析、解码

一个数据源会先分离出音视频数据,如果是视频流,通过OMX组件解码,如果是音频流,通过音频解码器解码,如AACDecoder、AC3Decoder等。解码完成后做音视频同步,最终将视频渲染到屏幕上,音频通过音频系统进行播放

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值