Android MediaCodec 框架 基于codec2
系列文章的目的是什么?
粗略:
- 解码需要哪些基础的服务?
- 标准解码的调用流程?
- 各个流程的作用是什么?
- 解码框架的层次?
- 各个层次的作用?
细化:
- 解码参数的配置?
- 解码输入数据包的流转?
- 解码输出帧内存的申请和管理?
文章目录
- HIDL上游
- HIDL 下游
- HIDL接口
- 基础的codec2 服务
首先从MediaCodec 到具体的解码Component 梳理出一条路径,然后在具体理解里面的细节。 本文就从MediaCodec出发 理解Android 解码框架的各个层次, 总的来说可以分为三个部分
- HIDL 层之上,这一层主要是对外部的应用提供接口 并提供输入和输出buffer的管理,流程的控制等等。
- HIDL 层之下,提供创建具体的解码组件,解码组件的实现,对数据包解码 并返会解码后的图像。
- codec service,提供创建解码组件的服务,HIDL层之上通过这个服务调用到HIDL 之下。
HIDL上游
如图所示 上游主要包含了以下这些部分。
- MediaCodec
MediaCodec 首先会创建出ccodec,后续的操作都是通过ccodec 这个codecbase进行调用(这里是为了兼容ACodec 和 Codec2的情况)。同时也通过这个ccodec获取codec创建的CCodecBufferChannel。
- 创建codecbase 这里就是CCodec, 在MediaCodec 这一级是调用到CCodec。
- 将创建好的ccodec 注册到looper 中。这个looper是应用层设置到mediacodec中的。
- 注册CodecCallback到ccodec,注册BufferCallback到CCodecBufferChannel。
- CCodec
- 创建 CCodecBufferChannel 和 CCodecConfig。
- 通过codec2的service 获取componentStore, 并通过componentStore来创建解码器的component。这里面主要是通过codec2client 这个类来完成的。
- 将创建好的组件设置到CCodecBufferChannel,以便后续调用。
- 回调一些错误等信息到MediaCodec。
codec2client:
和下游HIDL进行交互 的客户端, 主要是调用IComponetStore 和IComponet的接口。
- 查看codec2client是如何创建出来的?
std::shared_ptr<Codec2Client> client = _CreateFromIndex(index);std::shared_ptr<Codec2Client> Codec2Client::_CreateFromIndex(size_t index) {std::string const& name = GetServiceNames()[index];LOG(WARNING) << "Creating a Codec2 client to service \"" << name << "\"";sp<Base> baseStore = Base::getService(name);CHECK(baseStore) << "Codec2 service \"" << name << "\""" inaccessible for unknown reasons.";LOG(WARNING) << "Client to Codec2 service \"" << name << "\" created";return std::make_shared<Codec2Client>(baseStore, index);
}
- GetServiceNames()。 通过Manifest来获取hal的名字
Manifest定义了HAL的名字”android.hardware.media.c2”, hidl传输方式”hwbinder”,interface的名字”IComponentStore”,instance的名字”default”。而GetServiceNames也是通过这些信息去定位到具体的HAL。
-
Base::getService(name): 其中Base是IComponentStore类型,也就是service 端。通过名字获取到service端的服务。 然后赋值到baseStore。
-
接着用这个baseStore初始化创建codec2client(也就是mBase 是baseStore)。
std::make_shared<Codec2Client>(baseStore, index)
-
所以说codecclinet 调用的接口会调用到service 端的ComponentStore。
CCodecBufferChannel:管理输入和输出buffer的地方,当时有输入和输出buffer的时候通过回调上报到MediaCodec ,随后MediaCodec上报到应用
HIDL 下游
下游包括两个方面 一个是componentStore 另一个是Componet
-
componetStore
调用关系以createComponent 为例。调用流程如下
codec2client----->(HIDL)compometStore(获取真正的store)------>C2PlatformComponentStore(或者vendor自己实现的componetstore) -----> C2SoftAvcDecFactory .
在HIDL 上层 codec2clinet 获取componetStore服务的时候 会调用下面的函数返回C2PlatformComponentStore。而后调用createCompoent就调用到这个类当中。
在这个类的创建componet中会根据具体的名字找到componet调用其的createComponent,比如avc的C2SoftAvcDecFactory 的 createComponent
c2store.cpp
std::shared_ptr<C2ComponentStore> GetCodec2PlatformComponentStore() {static std::mutex mutex;static std::weak_ptr<C2ComponentStore> platformStore;std::lock_guard<std::mutex> lock(mutex);std::shared_ptr<C2ComponentStore> store = platformStore.lock();if (store == nullptr) {store = std::make_shared<C2PlatformComponentStore>();platformStore = store;}return store;
}c2_status_t C2PlatformComponentStore::createComponent(C2String name, std::shared_ptr<C2Component> *const component) {// This method SHALL return within 100ms.component->reset();std::shared_ptr<ComponentModule> module;c2_status_t res = findComponent(name, &module);if (res == C2_OK) {// TODO: get a unique node IDres = module->createComponent(0, component);}return res;
}
-
component
compont的调用 也是通过HIDL的接口调用到 SimpleC2Component ,然后 SimpleC2Component 调用具体的avc、hevc等等的componet。 SimpleC2Component 是每个compont的基类。
以queue接口为例 HIDL上层的codec2bufferChannel 会调用具体解码组件的queue接口 将待解码的数据包放入的具体的component中 首先调用到Codec2Client 这个调用componet的queue,然后调用到SimpleC2Component的queue_nb, queue_nb发送消息, 在消息处理线程中调用子类的process函数。
c2_status_t Codec2Client::Component::queue(std::list<std::unique_ptr<C2Work>>* const items) {Return<Status> transStatus = mBase1_0->queue(workBundle); }// Methods from ::android::hardware::media::c2::V1_1::IComponent Return<Status> Component::queue(const WorkBundle& workBundle) {return static_cast<Status>(mComponent->queue_nb(&c2works)); }c2_status_t SimpleC2Component::queue_nb(std::list<std::unique_ptr<C2Work>> * const items) {{if (queueWasEmpty) {(new AMessage(WorkHandler::kWhatProcess, mHandler))->post();} }bool SimpleC2Component::processQueue() {}process(work, mOutputBlockPool); }
HIDL接口
-
IComponentStore
C2ComponentStore(这定义了各种接口, codec2client/C2PlatformComponentStore都继承他并实现里面的接口。)
有哪些接口 主要是
createComponent: 创建各种编解码器组件
createInterface:创建定义各种组件的配置
listComponents:列出所有的组件。 -
IComponent
主要定义了对组件的各种操作 实际可以分为数据流和控制流, 数据流包括配置编码输入surface,解码输出surface,输入解码包,清空编解码数据。控制流:启动组件、退出组件、释放组件等等操作
connectToInputSurface:使用surface启动组件
queue: 将work 放到组件中。
drain: 清空组件,不是堵塞运行的。setOutputSurface: 设置输出的surface。
start: 启动组件。
stop: stop组件。
基础的codec2 服务
frameworks\av\media\codec2\hidl\services\vendor.cpp
在这里面的rc 中会启动一个android.hardware.media.c2@1.2-default-service
这个main函数中实现的是一个componentStore。
store = new utils::ComponentStore(std::make_shared<StoreImpl>());constexpr char const* serviceName = "default";if (store->registerAsService(serviceName) != OK) {LOG(ERROR) << "Cannot register Codec2's IComponentStore service"" with instance name << \""<< serviceName << "\".";} else {LOG(DEBUG) << "Codec2's IComponentStore service registered. ""Instance name: \"" << serviceName << "\".";}
相关文章:
Android MediaCodec 框架 基于codec2
系列文章的目的是什么? 粗略: 解码需要哪些基础的服务?标准解码的调用流程?各个流程的作用是什么?解码框架的层次?各个层次的作用? 细化: 解码参数的配置?解码输入数…...
【RocketMQ 系列三】RocketMQ集群搭建(2m-2s-sync)
您好,我是码农飞哥(wei158556),感谢您阅读本文,欢迎一键三连哦。 💪🏻 1. Python基础专栏,基础知识一网打尽,9.9元买不了吃亏,买不了上当。 Python从入门到精…...
Go TLS服务端绑定证书的几种方式
随着互联网的发展,网站提供的服务类型和规模不断扩大,同时也对Web服务的安全性提出了更高的要求。TLS(Transport Layer Security)[1]已然成为Web服务最重要的安全基础设施之一。默认情况下,一个TLS服务器通常只绑定一个证书[2],但…...
【算法与数据结构】--高级算法和数据结构--排序和搜索
一、常见排序算法 以下是一些常见的排序算法,包括冒泡排序、选择排序、插入排序、快速排序和归并排序。每种排序算法的讲解以及附带C#和Java示例: 1.1 冒泡排序 (Bubble Sort) 讲解: 冒泡排序是一种简单的比较排序算法。它多次遍历待排序的…...
【Java】jvm 元空间、常量池(了解)
JDK1.8 以前的 HotSpot JVM 有方法区,也叫永久代(permanent generation)方法区用于存放已被虚拟机加载的类信息,常量、静态遍历,即编译器编译后的代码JDK1.7 开始了方法区的部分移除:符号引用(S…...
Spring Boot自动加载
问:自动装配如何实现的? 答:简单来说就是自动去把第三方组件的Bean装载到IOC容器中,不需要开发人员再去写Bean相关的配置,在springboot应用里面只需要在启动类上去加上SpringBootApplication注解,就可以去实…...
MPNN 模型:GNN 传递规则的实现
首先,假如我们定义一个极简的传递规则 A是邻接矩阵,X是特征矩阵, 其物理意义就是 通过矩阵乘法操作,批量把图中的相邻节点汇聚到当前节点。 但是由于A的对角线都是 0.因此自身的节点特征会被过滤掉。 图神经网络的核心是 吸周围…...
Flink kafka 数据汇不指定分区器导致的问题
背景 在flink中,我们经常使用kafka作为flink的数据汇,也就是目标数据的存储地,然而当我们使用FlinkKafkaProducer作为数据汇连接器时,我们需要注意一些注意事项,本文就来记录一下 使用kafka数据汇连接器 首先我们看…...
【软考】14.1 面向对象基本概念/分析设计测试
《面向对象开发》 对象 现实生活中实际存在的一个实体;构成系统的一个基本单位由对象名、属性和方法组成 类 实体的形式化描述;对象是类的实例,类是对象的模板可分为:实体类:现实世界中真实的实体接口类(边…...
MFC-对话框
目录 1、模态和非模态对话框: (1)、对话框的创建 (2)、更改默认的对话框名称 (3)、创建模态对话框 1)、创建按钮跳转的界面 2)、在跳转的窗口添加类 3࿰…...
Essential Steps in Natural Language Processing (NLP)
💗💗💗欢迎来到我的博客,你将找到有关如何使用技术解决问题的文章,也会找到某个技术的学习路线。无论你是何种职业,我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章,也欢…...
Flink中KeyBy、分区、分组的正确理解
1.Flink中的KeyBy 在Flink中,KeyBy作为我们常用的一个聚合类型算子,它可以按照相同的Key对数据进行重新分区,分区之后分配到对应的子任务当中去。 源码解析 keyBy 得到的结果将不再是 DataStream,而是会将 DataStream 转换为 Key…...
QT6集成CEF3--01 准备工作
QT6集成CEF3--01 准备工作 一、所有使用到的工具软件清单:二、准备工作三、cefclient示例程序四、特别注意 一、所有使用到的工具软件清单: CEF 二进制发行包 cef_binary_117.2.5gda4c36achromium-117.0.5938.152_windows64.tar.bz2 CMake 编译工具 cmake-3.22.6-windows-x86_…...
随机误差理论与测量
文章目录 第1节 随机误差的性质和特点第2节 随机误差的数字特性标准差的估计 第3节 单次测量结果的精度指标第4节 多次测量结果的精度指标算数平均值的分布特性与标准差算数平均值的置信度算数平均值的精度指标(常用的有4个) 第5节 非等精度测量 第1节 随机误差的性…...
树莓派4b配置通过smbus2使用LCD灯
出现报错: FileNotFoundError: [Errno 2] No such file or directory: ‘/dev/i2c-1’ 则说明没有打开I2C,可通过如下步骤进行设置 1、打开树莓派配置 sudo raspi-config2、进入Interface Options,配置I2C允许 目前很多python3版本已经不…...
UPS 原理和故障案例分享
摘要:不间断电源UPS (Uninterruptible Power System),主要是由整流器、 逆变器、静态旁路和储能装置等组成;具备高可靠性、高可用性和高质量的独立 电源。通过对收集的 UPS 故障案例进行分析,从施工,调试和运行三个方面筛选 出四个故障案例与…...
Stream流中的 max()和 sorted()方法
需求:某个公司的开发部门,分为开发 一部 和 二部 ,现在需要进行年中数据结算。分析: 员工信息至少包含了(名称、性别、工资、奖金、处罚记录)开发一部有 4 个员工、开发二部有 5 名员工分别筛选出 2 个部门…...
云上攻防-云原生篇Docker安全权限环境检测容器逃逸特权模式危险挂载
文章目录 前言1、Docker是干嘛的?2、Docker对于渗透测试影响?3、Docker渗透测试点有那些?4、前渗透-判断在Docker中方式一:查询cgroup信息方式二:检查/.dockerenv文件方式三:检查mount信息方式四࿱…...
PDE数值解中,为什么要引入弱解(weak solution)的概念?
See https://www.zhihu.com/question/24243246?utm_sourceqq&utm_mediumsocial&utm_oi1315073218793488384...
使用pdfjs实现在线预览pdf
在工作中可能会遇到前端展示pdf文件进行预览并提供下载的需求场景,例如操作指引,这个时候需要寻找一款实现该功能的插件,以pdjjs举例子 1. 安装pdf.js npm install pdfjs-dist2. 引入pdf.js import pdfjsLib from pdfjs-dist3.加载pdf文件流 这个地方区分是请求后端接口还是…...
汇编语言基础
引言 汇编语言是直接在硬件之上工作的编程语言,首先要了解硬件系统的结构,才能有效的应用汇编语言对其编程。汇编课程的研究重点放在如何利用硬件系统的编程结构和指令集有效灵活的控制系统进行工作。 基础知识 1.1机器语言 机器语言是机器指令的集合…...
格式工厂怎么把两个视频合并在一起
免费的工具谁不喜欢呢,今天为大家介绍的是格式工厂这款多功能视频转换软件,然而今天主要为大家介绍的是格式工厂的视频合并功能。 是的,你没有听错,格式工厂除了转换之外,还可以视频合适、视频剪辑、视频分割、去水印…...
2.MySQL表的操作
个人主页:Lei宝啊 愿所有美好如期而遇 表的操作 (1)表的创建 CREATE TABLE table_name ( field1 datatype, field2 datatype, field3 datatype ) character set 字符集 collate 校验规则 engine 存储引擎; 存储引擎的不同会导致创建表的文件不同。 换个引擎。 t…...
网络安全之应急流程
近期需要弄一个网络安全应急的流程,其实对于网络安全应急并不陌生,只是在一些特定的环境上会遇到一些难以解决的问题或者缺少某个岗位的技术人员,因为不同运营商的应急小队也是不同的岗位,如今有着安全设备的告警和预警࿰…...
[Python进阶] 操纵鼠标:pyuserinput
6.2 操纵鼠标:pyuserinput 6.2.1 说明 在安装pyuserinput库时会自动安装PyMouse和PyKeyboard库。前者主要用来操作鼠标,包括鼠标的点击、移动等。后者主要用来操作键盘,包括键盘按键的按下、弹起等。 这两个库还可以同时对鼠标和键盘的事件…...
【LeetCode】每日一题两数之和寻找正序数组的中位数找出字符串中第一个匹配项的下标在排序数组中查找元素的第一个和最后一个位置
主页点击直达:个人主页 我的小仓库:代码仓库 C语言偷着笑:C语言专栏 数据结构挨打小记:初阶数据结构专栏 Linux被操作记:Linux专栏 LeetCode刷题掉发记:LeetCode刷题 算法:算法专栏 C头…...
与HTTP相关的各种协议
TCP/IP TCP/IP协议是目前网络世界“事实上”的标准通信协议,实际上是一系列网络通信协议的统称,其中最核心的两个协议是 TCP和IP,其他的还有 UDP、ICMP、ARP 等等,共同构成了一个复杂但有层次的协议栈。 这个协议栈有四层&#x…...
常见的网络攻击手段
网络攻击对个人、组织和整个社会都带来了严重的威胁,因此必须采取有效的安全措施来保护网络系统和用户的信息安全。网站是攻击者经常瞄准的目标,以下是一些常见的攻击方式: 1. DDoS攻击(分布式拒绝服务攻击)࿱…...
学习笔记---超基础+详细+新手的顺序表~~
目录 1.顺序表的前言 1.1 顺序表--->通讯录📇 1.2 数据结构的相关概念🏇 1.2.1 什么是数据结构 1.2.1 为什么需要数据结构 2. 顺序表概念及分类 2.1 顺序表的概念🐙 2.2 顺序表的分类🐫 2.2.1 顺序表和数组的区别 2.…...
Java高级-CompletableFuture并发编程利器
CompletableFuture核心Api 1.概述2.Async2.a) supplyAsync2.b) runAsync 3.Then3.a) thenApply()3.b) thenApplyAsync() 1.概述 Future可以在并发编程中异步获取结果 CompletableFuture实现了Future接口,肯定也会有Future的功能,也相当于是Future的一个…...
酒店网站建设的重要性/营销方案推广
使用监听器:定时清除map缓存的key value . 配置web.xml:注意位置 <listener> <listener-class> com.my.common.listener.TimerListener </listener-class> </listener> 监听类: public class TimerListener implements Serv…...
如何用php做网站/郑州网站营销推广
1:把项目下载到本地: 下载地址:http://www.bootcss.com/p/bootstrap-datetimepicker/ 2:提取文件 把datetimepicker.min.css文件放到自己项目的css文件夹中 把datetimepicker.min.js文件放到自己项目的js文件夹中 3ÿ…...
z-blog wordpress/合肥最新消息今天
357 Lambda表达式练习1(抽象方法无参无返回值) 【练习1】 定义一个piano接口,里面定义一个抽象方法:void listen()定义一个PianoDemo测试类,里面提供个方法 main,调用listenPianolistenPiano【练习2】 定…...
济南网站设计公司富/网站关键词优化排名软件
自定义学习率代码可以加快训练的速度,下面是代码的内容和学习率的截图。 import matplotlib.pyplot as plt def lrfn(epoch):LR_START 0.00001LR_MAX 0.00005 *8#* strategy.num_replicas_in_syncLR_MIN 0.00001LR_RAMPUP_EPOCHS 5LR_SUSTAIN_EPOCHS 5LR_EXP_…...
网站制作中文版/百度关键词搜索次数
原题地址:http://oj.leetcode.com/problems/insertion-sort-list/ 题意:对链表进行插入排序。 解题思路:首先来对插入排序有一个直观的认识,来自维基百科。 代码循环部分图示: 代码: class Solution: # par…...
廊坊网站建设技术外包/百度推广登录平台官网
目录 一、安装mongoDB安装包 二、配置 三、启动服务端 四、启动客户端 五、关闭服务端 六、关闭客户端 一、安装mongoDB安装包 1. cd /usr/local 2. mkdir mongodb 3. cd mongodb 4. wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-4.0.7.tgz 5. tar…...