当前位置: 首页 > news >正文

音视频 四 看书的笔记 MediaPlayerService

Binder机制看这里 Binde机智 这是一个分割符 Binder机智+ 分割(goutou) Binder机制++

MediaPlayerService多媒体框架中一个非常重要的服务。MediaPlayerService 我原称之为链接之王

[图片来自 Android音视频开发 何俊林 著 书的拍照]  真的是看书笔记啊!ฅʕ•̫͡•ʔฅ
图片来源

  • MediaPlayer 是客户端 C/S 中的C
  • MediaPlayerService MediaPlayerService::Client 是服务端 C/S中的S
  • MediaPlayerService 实现 IMediaPlayerService 定义的业务逻辑,主要功能就是MediaPlayer::setDataSource 调用create创建对应的player
  • MediaPlayerService::Client 实现IMediaPlayer 定义业务逻辑 start stop pause…; 是通过MediaPlayerService create的player中对应的方法 实现具体功能。
  • 通过Transact 函数 向 IBinder 发出调用, 通过 onTransact 函数 使远程对象 相应接收到的调用

Binder通信时,需要通过IBinder接口转化具体的实体对象,就会产生可多可多类。

  • 看上图Bp/Bn开头的类。他们都派生自两个类
    · Bp??? : I??? : BpRefBase
    · Bn??? : I??? : BBinder
    · 都派生自 I??? 有嘛不同?

    -  Bp 把对应的 binder_transaction_data 打包,通过BpRefBase的mRemote(BpBinder)发送出去,等待结果
    -  Bn 实现对应的业务逻辑,通过调用Bn派生类中的方法来实现,例如:MediaPlayerService::Client.继承了 BnMediaPlayer。
    

    在这里插入图片描述

  • BpRefBase 中 remote函数用来与Binder驱动交互

  • Binder是用来从Binder驱动中接收相关请求并进行相关处理的

  • BpBinder 和 BinderDriver进行互通

    -   BBinder与BpBinder这两者容易混淆。其实这两者是很好区分
    -  对于service来说继承了BBinder(BnInterface)因为BBinder有onTransact消息处理函数
    -  对于与service通信的client来说需要继承BpBinder(BpInterface),因为BpBinder有消息传递函数transcat。
    以cameraService的client为例
    Camera.cpp中getCameraService函数取得远程CameraService的IBinder对象
    然后通过 mCameraService = interface_cast<ICameraService>(binder);
    进行重构得到了BpCameraService对象。而BpCameraService继承了BpInterface。
    cameraService:
        defaultServiceManager()->addService(String16("media.camera"), new CameraService()); 传入了BBinder。
       IPC传递的过程中IBinder指针不可缺少,这个指针对一个进程来说就像是socket的ID一样,唯一的。
       所以不管这个IBinder是BBinder还是BpBinder, 他们的都是在重构BpBinder或者BBinder的时候把IBinder作为参数传入。
    此段文字来自https://blog.csdn.net/RationalGo/article/details/23845085
    

看MediaPlayerService 先看 MediaPlayerService.cpp

class IMediaPlayerService : public IInterface
{
    public:
    DECLARE_META_INTERFACE(MediaPlayerService);
    virtual sp < IMediaPlayer > create (pid_t pid, const sp<IMediaPlayerClient>& client, const char* url) = 0;
    virtual sp < IMediaPlayer > create (pid_t pid, const sp<IMediaPlayerClient>& client, int fd, int64_t offset, int64_t length) = 0;
    virtual sp < IMemory > decode (const char * url, uint32_t *pSampleRate, int* pNumChannels) = 0;
    virtual sp < IMemory > decode (int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels) = 0;
};
class BnMediaPlayerService : public BnInterface<IMediaPlayerService>
{
    public:
    virtual status_tonTransact (uint32_t code,
    const Parcel & data,
    Parcel * reply,
    uint32_t flags = 0);
};

可以看到这里定义了一些常规播放控制接口。
找到入口

int main(int argc __unused, char** argv)
{
    signal(SIGPIPE, SIG_IGN);
    char value[PROPERTY_VALUE_MAX];
    //...
    sp<ProcessState> proc(ProcessState::self());
    sp<IServiceManager> sm = defaultServiceManager();
    //...
    AudioFlinger::instantiate();//AudioFlinger
    MediaPlayerService::instantiate();
    CameraService::instantiate();
    AudioPolicyService::instantiate();//AudioPolicyService
    SoundTriggerHwService::instantiate();
    registerExtensions();
    ProcessState::self()->startThreadPool();
    IPCThreadState::self()->joinThreadPool();
	//...
}

找 defaultServiceManager()
defaultServiceManager返回的实际是一个BpServiceManger类实例,并调用add函数;
B p MediaPlayService 作为服务代理端,那么 B n MediaPlayerService 一定是实现端; (注意一个Bp 一个 Bn)
MediaPlayerService 继承自 BnMediaPlayerService,实现了真正的业务函数。
此处省略一堆
最终BpServiceManager 的 addService 的 结果就是 MediaPlayerService的服务器端 已经再ServiceManager注册了。

BinderDriver和MediaPlayer通信的过程

客户端如何获得服务的代理并和服务器端通信?
MediaPlayer为例:
MediaPlayer::decode 方法中:getMediaPlayerService(),客户端向ServiceManager 查询服务并获得代理BpServiceManager,然后调用getService向ServiceManager 查询名叫 String16(”media.palyer“)的服务;
getService方法内,先将请求打包成Parcel,然后调用remote -> transact函数,最终调用的是IPCThreadStae的transact函数。
每个线程都有一个IPCThreadState ,IPCThreadState实例登记在Linux线程的上下文附属数据中,主要负责Binder的读写,请求处理框架。
IPCThreadState再构造的时候获取进程的ProcessState并记录再自己的成员变量中。
最终调用ProcessState::getStrongProxyForHandle函数。
这里的handle就是ServiceManager内维护的MediaPlayerService对应的Binder句柄,这个ProcessState根据这个句柄新建了一个BpBinder,并将其保存起来,下次需要ServiceManager请求获取相同句柄的时候就可以直接返回了。
根据返回的BpBinder 获得 MediaPlayerService的代理。
效用IMediaPlayerService的asInterface宏函数,这样就获得了一个代理BpMediaPlayerService对象,它的remote为BpBinder(handle),这个handle就是向ServiceManager查询到的MediaPlayerService对应的Binder句柄。

总结:

  • MediaPlayer::setDataSource 会创建一个 MediaPlayerService::Client对应的BpMediaPlayer,用于获取MediaPlayerService::Client的各项功能。
  • 只有MediaPlayerService向ServiceManager进行注册,MediaPlayer才能找到MediaPlayerService::Client; SO MediaPlayer必须先获取BpMediaPlayerService,然后通过BpMediaPlayerService 创建一个MediaPlayerService::Client。

可以去这里看书 Android 音视频开发
我看的书是 《Android 音视频开发》何俊林 著 公司被别人垫显示器的,不知道放了几年没人看的旧书,也是新书(木有人翻看过),😈

相关文章:

  • 《非暴力沟通》第四章 “体会和表达感受” 总结
  • 快速了解ES6Module模块化
  • CLion的坑:CMake File API : no reply dir found clion
  • 【强化学习】DAPO 论文解读
  • 什么是索引下推和索引覆盖?
  • 06-SpringBoot3入门-常见注解(简介)
  • 《破局摩尔定律:AI驱动、异构集成与工具革新重构芯片效能新范式》
  • Redis数据迁移同步
  • 乳腺超声图像结节分割
  • LeetCode算法题(Go语言实现)_15
  • 煤矿油田光伏管理新突破:安科瑞分布式监控系统如何破解高耗能行业转型难题
  • 深度学习框架PyTorch——从入门到精通(9)PyTorch简介
  • 机试题——村落基站建设
  • Java 集合中ArrayList与LinkedList的性能比较
  • Visual Studio 2022中打开其他项目的步骤
  • 虚拟货币和 Token
  • 剑指Offer26 -- 树
  • ‘无法定位程序输入点kernel32.dll’详细的修复方法,一键快速修复kernel32.dll
  • 瑞芯微RK356X主板复用接口配置方法,触觉智能嵌入式方案商
  • 使用ModbusRTU读取松下测高仪的高度
  • 天津医疗行业网站建设/项目推广渠道有哪些
  • 动态网页实训报告总结/seo关键词优化费用
  • asp能不能作为网页开发语言/网络营销优化
  • 高端网站建设苏州/seo商学院
  • 湖南长沙现在能去吗/西安关键词优化服务
  • wordpress搭建问题/seo刷词