目录
[Algorithm 基类生命周期接口详解](#Algorithm 基类生命周期接口详解)
[1. init()](#1. init())
[2. configure()](#2. configure())
[3. queueRequest()](#3. queueRequest())
[4. prepare()](#4. prepare())
[5. process()](#5. process())
[Factory 工厂与注册机制](#Factory 工厂与注册机制)
[REGISTER_IPA_ALGORITHM 宏](#REGISTER_IPA_ALGORITHM 宏)
整体架构概述
libcamera IPA 框架采用抽象接口 + 对象工厂自动注册模式,将 AE/AWB/AGC 等 ISP 算法做成可插拔组件。 一套统一虚函数接口定义算法完整生命周期;新增算法不需要修改框架主代码,继承基类 + 注册宏即可接入 IPA 模块。
类总览
| 类 | 模板参数 | 作用 |
|---|---|---|
Algorithm<_Module> |
_Module IPA 模块类型 |
所有 IPA 算法的基类模板,定义算法生命周期接口,全部虚函数提供默认空实现 |
AlgorithmFactoryBase<_Module> |
_Module IPA 模块类型 |
工厂抽象基类;保存算法名称;构造时自动向 IPA 模块注册自身;声明纯虚create()接口用于创建算法实例 |
AlgorithmFactory<_Algorithm> |
_Algorithm 具体算法子类 |
工厂实现类;继承AlgorithmFactoryBase<typename _Algorithm::Module>;实现create(),构造对应算法对象 |
REGISTER_IPA_ALGORITHM宏 |
算法类名、算法名字 | 定义 static 工厂实例;库加载时触发工厂构造完成自动注册 |
_Module模块类型契约
当实现一套 IPA 模块时,使用者必须自定义_Module类型,内部包含下面内嵌类型:
cpp
_Module::Context // IPA会话全局共享上下文
_Module::FrameContext // 单帧上下文,保存该帧相关算法状态
_Module::Config // IPA配置信息,来自pipeline handler
_Module::Params // 输出结构体,下发给ISP硬件的参数
_Module::Stats // ISP硬件输出统计数据
Algorithm 模板依靠上述内嵌类型完成接口参数绑定,实现一套接口适配不同 ISP 硬件的 IPA 模块。
Algorithm 基类生命周期接口详解
cpp
template<typename _Module>
class Algorithm
{
public:
using Module = _Module;
virtual ~Algorithm() {}
virtual int init(Context &context, const ValueNode &tuningData);
virtual int configure(Context &context, const Config &configInfo);
virtual void queueRequest(Context &context, uint32_t frame,
FrameContext &frameContext, const ControlList &controls);
virtual void prepare(Context &context, uint32_t frame,
FrameContext &frameContext, Params *params);
virtual void process(Context &context, uint32_t frame,
FrameContext &frameContext, const Stats *stats,
ControlList &metadata);
};
1. init()
cpp
virtual int init(Context &context, const ValueNode &tuningData)
- 调用时机 :IPA 模块初始化阶段,整个生命周期仅执行一次
- 输入:全局共享上下文;
tuningData调参配置树 (ValueNode) - 职责:读取调优参数,初始化算法内部状态
- 返回:0 成功;非 0 代表错误码。
2. configure()
cpp
virtual int configure(Context &context, const Config &configInfo)
- 调用时机:相机流启动之前,拿到 PipelineHandler 下发配置信息
- 输入:全局上下文、IPA 配置信息(分辨率、模式等)
- 职责:基于当前相机配置预计算参数;配置状态保存到
Context会话配置结构。 - 返回:0 成功;非 0 错误码。
3. queueRequest()
cpp
virtual void queueRequest(Context &context, uint32_t frame,
FrameContext &frameContext, const ControlList &controls)
- 调用时机:上层每向相机提交一个 Request 时调用
frame:Request 序列号,标识该批控制希望生效的目标帧- 输入:
controls来自应用层用户控制参数(曝光、增益等) - 职责:提取用户控制值,保存到对应
FrameContext;此时还没有 ISP 统计数据。
4. prepare()
cpp
virtual void prepare(Context &context, uint32_t frame,
FrameContext &frameContext, Params *params)
- 调用时机 :ISP 处理对应帧图像之前
- 输出:
paramsISP 硬件参数结构体 - 职责:填充 ISP 寄存器 / 处理块参数、使能对应 ISP 模块;硬件使用 params 完成图像处理。
5. process()
cpp
virtual void process(Context &context, uint32_t frame,
FrameContext &frameContext, const Stats *stats,
ControlList &metadata)
- 调用时机 :ISP 完成一帧图像处理后,拿到 ISP 统计结果
stats - 输入:ISP 统计数据;
- 输出:
metadata帧元数据,回填给上层应用; - 职责:运行算法闭环计算(AE/AWB 迭代),更新帧上下文状态;
- ⚠️关键约束:
- 该函数运行在关键路径,禁止耗时计算;重运算必须丢到异步线程。
- 算法状态存放于
FrameContext;可访问其他算法保存的帧上下文状态。 - 存在硬件帧延迟:Request 序列号和 ISP 返回统计帧不一定一一对应;早期框架对历史帧上下文访问能力有限,容易造成控制环路震荡。
- 需要仔细维护上下文访问顺序,保证拿到有效最新状态。
算法整体时序
IPA初始化
↓
init() 【仅一次】
↓
configure() 【流开启前】
↓
[流式循环]
上层提交Request → queueRequest() 接收用户控制
↓
prepare() 填充ISP参数交给硬件执行
↓
ISP硬件执行图像处理
↓
process() 读取ISP统计,执行算法计算,输出metadata
注意:因为硬件流水线延迟,
process()处理的统计帧,对应较早之前的 Request,不是刚刚 queueRequest 那一帧,存在帧偏移。
Factory 工厂与注册机制
AlgorithmFactoryBase<_Module>
cpp
template<typename _Module>
class AlgorithmFactoryBase
{
public:
AlgorithmFactoryBase(const char *name)
{
_Module::registerAlgorithm(this);
}
virtual std::unique_ptr<Algorithm<_Module>> create() const = 0;
private:
std::string name_;
};
- 构造函数:接收算法名字,立刻调用
_Module::registerAlgorithm(this),把工厂基类指针注册进 IPA 模块; create()纯虚接口:产出算法实例的抽象接口。
AlgorithmFactory<_Algorithm>
cpp
template<typename _Algorithm>
class AlgorithmFactory
: public AlgorithmFactoryBase<typename _Algorithm::Module>
{
public:
std::unique_ptr<Algorithm<typename _Algorithm::Module>> create() const override
{
return std::make_unique<_Algorithm>();
}
};
- 模板参数是具体算法子类 ,通过
_Algorithm::Module推导所属 IPA 模块类型; create()实现:使用std::make_unique构造对应算法子类对象并返回。
REGISTER_IPA_ALGORITHM 宏
cpp
#define REGISTER_IPA_ALGORITHM(algorithm, name) \
static AlgorithmFactory<algorithm> global_##algorithm##Factory(name);
- 定义static 静态工厂对象;当 IPA 插件库被加载时,静态变量构造函数执行,自动完成工厂注册;
name算法名字必须在同一个 IPA 模块内全局唯一;- 使用示例:
cpp
// AWB为自定义算法,继承 Algorithm<MyModule>
REGISTER_IPA_ALGORITHM(AWB, "awb");
工厂使用流程
- 插件库加载:宏生成 static 工厂,构造函数调用
registerAlgorithm注册到 IPA 模块; - IPA 内部通过算法名字查找匹配的
AlgorithmFactoryBase; - 调用工厂
create()生成算法实例(基类指针,不需要依赖具体子类头文件); - 拿到
std::unique_ptr<Algorithm<_Module>>后依次调用init/configure/queueRequest/prepare/process接口。
核心设计要点总结
- 模板泛型设计 不硬编码 Context/Stats/Params 结构体;不同硬件 IPA 模块自定义一套类型,复用同一套算法框架。
- 插件化,低耦合 IPA 主逻辑只依赖
Algorithm抽象基类;新增算法只需要继承基类 + 注册宏,不需要修改框架代码。 - 两级状态隔离
Module::Context:全局会话状态;Module::FrameContext:每帧独立状态存储;算法把状态保存在帧上下文,应对多帧流水线;历史帧上下文访问能力早期有限是框架待改进点。
- 职责分离
queueRequest:接收上层用户控制;prepare:输出参数给 ISP 硬件;process:基于 ISP 统计数据运行算法闭环;
- 性能约束
process()运行在图像处理关键路径,阻塞会直接降低帧率;复杂计算必须异步处理。
调用链路完整梳理
- 库加载阶段
REGISTER_IPA_ALGORITHM定义 static 工厂实例 → 工厂构造函数执行 →_Module::registerAlgorithm(this),工厂注册进 IPA 模块。 - IPA 初始化
- IPA 模块根据配置的算法名字检索对应的
AlgorithmFactoryBase; - 调用
factory->create()得到算法基类对象; - 调用
algorithm->init(context, tuningData)初始化算法。
- 相机配置 相机准备开启流,调用
algorithm->configure(context, configInfo)。 - 相机运行流式阶段
- App 提交 Request 触发
algorithm->queueRequest(...)保存用户控制; - ISP 处理帧前调用
algorithm->prepare(...)填充硬件参数; - ISP 完成图像处理输出统计;
- 调用
algorithm->process(...),执行算法逻辑、回填 metadata 返回上层。