音视频 四 看书的笔记 MediaPlayerService
Binder机制看这里 Binde机智 这是一个分割符 Binder机智+ 分割(goutou) Binder机制++
MediaPlayerService多媒体框架中一个非常重要的服务。MediaPlayerService 我原称之为链接之王
![[图片来自 Android音视频开发 何俊林 著 书的拍照] 真的是看书笔记啊!ฅʕ•̫͡•ʔฅ](https://i-blog.csdnimg.cn/direct/b5a5e8c92cba4010a66da05ca02e5cd3.png)
图片来源
- 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 音视频开发》何俊林 著 公司被别人垫显示器的,不知道放了几年没人看的旧书,也是新书(木有人翻看过),😈
相关文章:
音视频 四 看书的笔记 MediaPlayerService
Binder机制看这里 Binde机智 这是一个分割符 Binder机智 分割(goutou) Binder机制 MediaPlayerService多媒体框架中一个非常重要的服务。MediaPlayerService 我原称之为链接之王 图片来源 MediaPlayer 是客户端 C/S 中的CMediaPlayerService MediaPlayerService::Client 是服…...
vmware 创建win10 系统,虚拟机NAT网络设置
虚拟机设置: 物理机本机创建桥接: 如何创建桥接,请自行脑补~...
Python CSV 数据分析:问题排查与解决全记录
Python CSV 数据分析:问题排查与解决全记录 前段时间,我接到一个任务,需要对公司的销售数据进行分析。这些数据存储在 CSV 文件里,本想着用 Python 处理起来会很轻松,结果却状况百出。下面,就跟大家讲讲我…...
RabbitMQ高级特性--发送方确认
目录 1. confirm确认模式 1.配置RabbitMQ 2.设置确认回调逻辑并发送消息 2.Return退回模式 1.配置RabbitMQ 2.设置返回回调逻辑并发送消息 在使用RabbitMQ的时候, 可以通过消息持久化来解决因为服务器的异常崩溃而导致的消息丢失, 但是还有⼀个问题, 当消息的生产者将消息发送出…...
【初阶数据结构】线性表之双链表
文章目录 目录 一、双链表的概念 二、双链表的实现 1.初始化 2.尾插 3.头插 4.打印 5.判断双链表是否为空 6.尾删 7.头删 8.查找 9.在指定的位置之后插入数据 10.删除指定位置的数据 11.销毁 三、完整源码 总结 一、双链表的概念 链表的结构非常多样࿰…...
java网盘项目 目前 文件有分享表 文件夹也要创建分享表吗
java网盘项目 目前 文件有分享表 文件夹也要创建分享表吗 根据网盘系统的典型设计模式及搜索结果中的最佳实践,建议为文件夹创建独立的分享表。以下是具体分析及实施建议: 一、需要独立文件夹分享表的核心原因 权限控制差异 文件分享:通常基…...
智能路由系统-信息泄露漏洞挖掘
1.漏洞描述: Secnet-智能路由系统 actpt_5g.data 信息泄露,攻击者可利用此漏洞收集敏感信息,从而为下一步攻击做准备。 2.fofa搜索语句 title"安网-智能路由系统" || title"智能路由系统" || title"安网科技-智能…...
表格图表切换,图表无法展示问题复盘
项目背景 103项目CPC卡使用模块在原有的表格展示数据的基础之上,增加环状饼图图表展示,采用tab切换的方式实现 问题描述 图表无法设置宽高,导致饼图无法渲染 具体代码 // 入口页<el-tabs type"card" class"cts_flex_t…...
css 实现闪烁光标
要实现闪烁光标(比如文本输入框内常见的闪烁效果),可以使用 CSS 动画。下面是一个简单的方法: 代码示例 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta n…...
AI赋能python数据处理、分析与预测操作流程
以数据集预测鱼类种类(Species)开展以下研究。数据格式如下: 以下是一个系统的分析思路及推荐的机器学习算法: 1. 数据预处理与探索性分析 缺失值与异常值处理: 检查数据完整性(如Roach类中Weight=0的记录需修正或删除)。 通过箱线图或Z-Score检测异常值,判断是否需…...
基于74LS192的十进制两位数正向计时器(proteus仿真)
在数字电路设计中,计时器是一个非常常见的应用。今天,我将分享一个基于 74LS192 双向计数器 的十进制两位数正向计时器电路设计。这个电路可以实现从 00 到 99 的十进制正向计数,并通过两个七段数码管显示结果。 最终效果如图: 各…...
#C8# UVM中的factory机制 #S8.5# 对factory机制的重载进一步思考(二)
今天我们反思,然后总结。 一 先看代码 `timescale 1ns/1ps module tb_top;class Base;function void print(int a);$display("Base: int = %0d", a);endfunction endclassclass Sub extends Base;function void print(string s);$display("Sub: string = %s&…...
算法-前缀和与差分
一、前缀和(Prefix Sum) 1. 核心思想 前缀和是一种预处理数组的方法,通过预先计算并存储数组的前缀和,使得后续的区间和查询可以在**O(1)**时间内完成。 2. 定义 给定数组 nums,前缀和数组 prefixSum 的每个元素 p…...
React(六)React过渡动画-CSS编写方式
React过渡动画 react-transition-group介绍 在开发中,我们想要给一个组件的显示和消失添加某种过渡动画,提高用户体验→可通过react-transition-group实现。React曾为开发者提供过动画插件 react-addons-css-transition-group,后由社区维护…...
第十五章:Python的Pandas库详解及常见用法
在数据分析领域,Python的Pandas库是一个不可或缺的工具。它提供了高效的数据结构和数据分析工具,使得数据处理变得简单而直观。本文将详细介绍Pandas库的基本功能、常见用法,并通过示例代码演示如何使用Pandas进行数据处理。最后,…...
Python自动化模块:开启高效编程新时代
一、写在前面 在数字化时代,自动化技术已成为提高效率、降低成本的关键手段。Python 作为一种简洁、高效且功能强大的编程语言,凭借其丰富的库和框架,在自动化领域占据了举足轻重的地位,成为众多开发者的首选工具之一。从简单的文…...
【蓝桥杯速成】| 15.完全背包
题目:携带研究材料 问题描述 52. 携带研究材料(第七期模拟笔试) 小明是一位科学家,他需要参加一场重要的国际科学大会,以展示自己的最新研究成果。他需要带一些研究材料,但是他的行李箱空间有限。这些研…...
C++:allocator类(动态数组续)
1.为什么需要 allocator? 在 C 中,动态内存管理通常通过 new 和 delete 完成: int* p new int; // 分配内存 构造对象 delete p; // 析构对象 释放内存 但 new 和 delete 有两个问题: 耦合性:将内…...
libva基础
Libva(Lib Video Acceleration)是一个开源的库,实现了 **VA-API**(Video Acceleration API),旨在为视频处理提供跨平台的硬件加速支持。 1、核心功能与作用 硬件加速抽象层:Libva 作为中间层&…...
【C++20】format格式化输出
C20 format格式化输出 在C20之前,格式化能力都依赖于三方格式化库FMT, 而C20 标准委员会终于在C标准库引入了格式化功能,从使用方式和风格来看其实就是FMT库转正了 直接使用 包含<format.h>头文件既可以直接使用,类似pyt…...
c++游戏开发第一期
以后我将要发c游戏开发的教程,可能更得比较慢。(目测几个星期一更)。 今天先讲个配置编译器。 我用的是Visual studio 2022和EasyX。 安装studio: 首先找到下载链接(点我)下拉找到下面图片的东西。 下完…...
Elasticsearch:人工智能时代的公共部门数据治理
作者:来自 Elastic Darren Meiss 人工智能(AI)和生成式人工智能(GenAI)正在迅速改变公共部门,从理论探讨走向实际应用。正确的数据准备、管理和治理将在 GenAI 的成功实施中发挥关键作用。 我们最近举办了…...
Web开发:数据的加密和解密
一、常见通用术语解析 加盐:在密码中加入随机数据,提高安全性。摘要:固定长度的输出,用于数据完整性验证。加密:将数据转换为不可读形式,确保安全。撞库:通过暴力破解比对常见密码的攻击方式。…...
低功耗LPWAN模块开发指南:远距离无线通信与边缘计算融合实战
在远程资产追踪、野外环境监测等场景中,稳定可靠的长距离通信与超低功耗是系统设计的核心挑战。eFish-SBC-RK3576通过 原生双UART接口 USB OTG扩展能力 ,可无缝集成主流LPWAN模组(LoRa/NB-IoT),实现“数据采集-边…...
RHCA核心课程技术解析5:红帽高可用性集群架构与深度实践
一、红帽高可用集群架构全景 1.1 核心组件交互逻辑 graph TD A[节点1] -->|Corosync 心跳| B[节点2] A -->|Pacemaker 资源管理| C[共享存储] B --> C D[Fencing设备] -->|STONITH| A D -->|STONITH| B C -->|GFS2锁管理| A C -->|GFS2锁管理| B 1.2 集…...
Python切片中的步长秘密
Python切片中的步长秘密 大家好!今天我们来聊聊Python切片中一个有趣的话题 - 步长(step)。 基本格式回顾 Python切片的完整格式是: [起点:终点:步长] 但你是否注意到,很多代码里的切片都只写了起点和终点?没错,步长是可以省略的! 步长的默认…...
Spring Boot事务管理详解(附银行转账案例)
一、事务基础概念 事务的ACID特性: 原子性(Atomicity):操作要么全部成功,要么全部失败一致性(Consistency):数据在事务前后保持合法状态隔离性(Isolation)&…...
【超详细教程】2025年3月最新Pytorch安装教程(同时讲解安装CPU和GPU版本)
目录 一、前言二、pytorch简介三、安装准备工作3.1、下载Anaconda 四、判断是否有NVIDIA显卡五、安装pytorch-CPU版本六、安装pytorch-GPU版本6.1、查看CUDA显卡驱动版本6.2、安装CUDA6.3、安装CuDNN(加速器)6.4、安装pytorch-GPU6.5 其他方法安装注意 七…...
Unity光线传播体积(LPV)技术实现详解
一、LPV技术概述 光线传播体积(Light Propagation Volumes)是一种实时全局光照技术,通过将场景中的间接光信息存储在3D网格中,实现动态物体的间接光照效果。 核心优势: 实时性能:相比传统光照贴图,支持动态场景 硬件…...
Git和GitCode使用(从Git安装到上传项目一条龙)
第一步 菜鸟教程-Git教程 点击上方链接,完成Git的安装,并了解Git 工作流程,知道Git 工作区、暂存区和版本库的区别 第二步 GitCode官方帮助文档-SSH 公钥管理 点击上方链接,完成SSH公钥设置 第三步(GitCode的官方引…...
