欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 房产 > 建筑 > 音视频 四 看书的笔记 MediaPlayerService

音视频 四 看书的笔记 MediaPlayerService

2025/4/1 19:40:09 来源:https://blog.csdn.net/weixin_41648633/article/details/146560156  浏览:    关键词:音视频 四 看书的笔记 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();//AudioFlingerMediaPlayerService::instantiate();CameraService::instantiate();AudioPolicyService::instantiate();//AudioPolicyServiceSoundTriggerHwService::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 音视频开发》何俊林 著 公司被别人垫显示器的,不知道放了几年没人看的旧书,也是新书(木有人翻看过),😈

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词