常见画面亮度闪烁,AE层面排查思路

常见画面亮度闪烁,AE层面排查思路

Q:摄像头画面出现规律性的亮暗闪烁,自动曝光反复调节、稳定不下来,怎么快速定位?

A:按 「先定性 → 查配置 → 看现成信息 → 再改源码」 四级递进。前三步用调试工具、串口和现成节点就能完成,都不用改代码。

AE 闪烁排查流程

第 0 步:先确认是不是 AE 引起的

用调试工具把 AE 切到 Manual 模式,固定曝光时间、模拟增益、数字增益:

结果判断
闪烁消失是 AE 在反复调节,继续往下查
仍然闪烁大概率与 AE 无关,转查 3DNR 调试开关、ISP 其他模块或显示端

这一步只点几下工具,不用改代码,先排除误判。

第 1 步:查配置类原因(工具、串口可见)

按现场现象直接查,多数问题在这一步就能定位:

现象检查点(怎么查)处理方向
开了曝光表但效果不对 / 曝光不生效工具看 AE 模式;切 Manual 或普通模式对比修正曝光表;曝光表模式不支持半行曝光,确认 sensor 是整行曝光
抗频闪(flicker)不生效、滚动水波纹串口读 sensor 实际 FPS、VTS(命令见下方)修正驱动传入的 VTS/FPS,两者要匹配
again/dgain 在两组值之间来回变、不收敛gain 表精度:小值达不到目标亮度、大值又超提高 gain 表精度,或增大进入稳定状态的阈值
收敛越冲越亮、亮暗来回摆收敛步长 / 收敛速度上限参数/强光抑制过大限制收敛速度上限,避免步长过大或为负,降强光抑制强度
双摄主/次摄闪烁隔帧生效参数、expo_fsexpo_fs 设为 0;隔帧生效按双摄配置
高增益段亮度突跳驱动 again 上限是否等于 gain 表档位值again 上限改为 gain 表档位值
30 fps 高分辨率下闪,降帧率后消失带宽 / 帧率降帧率复测确认,说明问题不在 AE 参数
经验:先看 FPS/VTS 是否传对、曝光表模式是否配错、隔帧生效参数这三项,能覆盖相当一部分现场问题。

读 sensor 实际 FPS / VTS(T33 实测可用):

echo "w dbgmode 0 items 0x2 interval 0 vinum 0" > /proc/jz/isp/isp-m0 cat /proc/jz/isp/isp-m0 | grep -E "FPS|HTS|VTS"

实测输出(T33 + SC4336P):

Sensor OUTPUT FPS : 20 / 1 Sensor HTS : 2800 Sensor VTS : 2250

第 2 步:先看现成的 AE 信息(不用改代码)

T33 的 AE 算法核心在库文件(fast_ae_472.a / fast_ae_540.a)里,客户一般拿不到驱动源码。但 AE 实时信息有两个现成口子,一行代码都不用改。

2.1 方式一:proc 节点(零改动,优先)

核心 ISP 节点:/proc/jz/isp/isp-m0(T33 板端实测确认,ls /proc/jz/isp/ 可见 isp-m0 / isp-m1 等)

# items 的 bit9(0x200)选中 AE 信息,vinum 0 = 主摄 echo "w dbgmode 0 items 0x200 interval 0 vinum 0" > /proc/jz/isp/isp-m0 cat /proc/jz/isp/isp-m0

串口上全量输出太长,建议只取关键几行(注意 AeAGain : 带空格,否则会匹配到 AeAGainManualMode):

cat /proc/jz/isp/isp-m0 | grep -E "AeLuma|AeAGain :|AeDGain :|AeIspDGain :|AeIntegrationTime :|AeStable"

连续采样看是否跳变:

for i in 1 2 3 4 5; do cat /proc/jz/isp/isp-m0 | grep -E "AeLuma|AeStable" | tr "\n" " "; echo; sleep 1; done

实测输出片段:

********* Ae Info ********* AeIntegrationTime : 1415 AeAGain : 1024 AeDGain : 0 AeIspDGain : 1024 ExposureValue : 1415 AeStable : 0 AeTarget : 62 AeMean : 55 AeLuma : 56

输出里直接看这些字段是否来回跳:

字段含义
AeLuma当前统计亮度
AeAGain / AeDGain / AeIspDGain模拟 / 数字 / ISP 数字增益
AeIntegrationTime曝光时间
AeTarget / AeMean / AeStable目标亮度 / 加权亮度 / 稳定标志
ExposureValue / EVLog2曝光量

2.2 方式二:应用层调 API(SDK 带库就能用)

节点被裁剪时,在客户应用层直接调接口打印:

tisp_ae_exprinfo_t info; tisp_g_ae_exprinfo_attr(0, &info); printf("it=%d ag=%d dg=%d ispdg=%d EV=%d\n",        info.AeIntegrationTime, info.AeAGain,        info.AeDGain, info.AeIspDGain, info.ExposureValue); tisp_ae_scence_attr_t sc; tisp_g_ae_scence_attr(0, &sc); printf("luma=%d\n", sc.luma);

接口声明在 lib_tisp_api.h。注意实现包在 #ifdef TISP_AE_API_CTRL 里,没开这个宏时函数不填数据,先确认客户 SDK 的配置。

2.3 判断:luma / 增益是否跳变

观察结果下一步
luma 或增益有跳变定位跳变位置,用 Manual 固定该组参数,确认画面效果
没有跳变,但画面仍闪AE 算得没问题,是驱动没正确执行 → 进第 3 步对比

第 3 步:还定位不了,再改驱动加打印

3.1 / 3.2 需要 T33 内部 AE 固件源码(客户 SDK 一般没有,找原厂支持);3.3 改的是 sensor 驱动,客户 SDK 自带,可以自己加。只有前两步都看不出问题时才需要。

3.1 打印 luma

luma 存在 AE 结果结构体 ae_context->results[index] 里:

  • nLuma:原始统计亮度

  • nLumaFinal:加权 / ROI 后的亮度

打印点:opensource/internal/t33/t33_tiziano/src/tiziano_ae.c 的 tisp_ae_calc_process(约 413 行)——在库函数 normal_ae_calc_process / fast_ae_calc_process 调用之后、tisp_ae_set_algo_index 之前,此时 results[index] 已被本次统计填充。normal AE 和 fast AE 两种模式都覆盖。

3.2 打印 it / ag / dg

在同一位置打印 results[index] 的 nExpt / nAGain / nAGainReg / nDGain / nIspDGain。

两个注意点:

  • tiziano_ae.c 约 343 行有一段现成注释 printk(ag_index / again / ispd),取消注释可用,但它在 fast AE 分支,normal 模式在 306 行就提前 return 了;

  • tisp_ae_interrupt_sync_result(约 356–409 行)整段被 #if 0 禁用,不要在那里打点。

实测可用的打印代码(T33 + SC4336P 验证通过,EV 变化时逐条打印、稳定后每 50 帧心跳,避免刷屏):

{     static uint64_t dbg_last_ev = ~0ULL;     static uint32_t dbg_cnt = 0;     uint64_t cur_ev = ae_context->results[index].nEV;     if (cur_ev != dbg_last_ev || (dbg_cnt++ % 50) == 0) {         dbg_last_ev = cur_ev;         printk("JZ_AE: v%d it=%u ag=%u ispdg=%u luma=%u ev=%llu\n",                vinum,                ae_context->results[index].nExpt,                ae_context->results[index].nAGain,                ae_context->results[index].nIspDGain,                ae_context->results[index].nLuma,                (unsigned long long)cur_ev);     } }
为什么打 ispdg 而不打 dg:nDGain(sensor 数字增益)多数场景不用、恒为 0,AE 的实际增益调节落在 ISP 数字增益 nIspDGain 上(实测在 1024~1054 之间变化)。打 dg 会看不到调节过程。

实测稳定段:

JZ_AE: v0 it=896 ag=1024 ispdg=1024 luma=55 ev=917504 JZ_AE: v0 it=896 ag=1024 ispdg=1024 luma=55 ev=917504

对照关系:

JZ_AEm0 节点说明
itAeIntegrationTime曝光行数(AeIntegrationTimeUnit : 0 时两者相等)
agAeAGain模拟增益,1024 = 1x
ispdgAeIspDGainISP 数字增益,1024 = 1x
lumaAeLuma统计亮度
evExposureValueev 是 10bit 精度,ExposureValue = ev >> 10

上电前几帧 luma 会剧烈波动(如 101→1),属出图瞬态,不要拿启动那几帧当判断依据,看稳定后的值。

看 luma 和 ev 是否在相邻帧之间来回跳、it/ag/ispdg 是否成对反向变化,就能判断是 AE 侧振荡还是下游执行问题。

3.3 对比 sensor 驱动侧输入值

在 sensor 驱动里打印——这个源码客户 SDK 自带,路径 opensource/drivers/sensors/<sensor>/,不用改内部固件。

以 T33 + SC4336P 为例,走的是 SENSOR_EXPO 模式(sc4336p.c 头部 #define SENSOR_EXPO),it 和 again 打包在一个 int 里传给 sc4336p_set_expo(约 2008 行):

static int sc4336p_set_expo(struct tx_isp_subdev *sd, int value) {     int it = value & 0xffff;              /* 曝光行数 */     int again = (value >> 16) & 0xffff;   /* again 寄存器值 */     printk("JZ_SENSOR: it=%d again=0x%x\n", it, again);   /* again 用十六进制,和 gain 表对照 */     /* 原有写寄存器代码不动 */ }

如果 sensor 驱动没开 SENSOR_EXPO(头文件里没有 #define SENSOR_EXPO),打点改在这两个函数:

  • sc4336p_set_integration_time(约 2044 行)

  • sc4336p_set_analog_gain(约 2076 行)

WDR 短帧对应 sc4336p_set_expo_short(约 2243 行),要一起打。

与第 2 步 proc 节点 / API 拿到的 AeIntegrationTime / AeAGain 对比(这条链路客户自己就能走完,不依赖内部固件源码):

实测(T33 + SC4336P,收敛过程中同时抓):

# sensor 驱动打印 JZ_SENSOR: it=598 again=0x80 JZ_SENSOR: it=600 again=0x80 JZ_SENSOR: it=602 again=0x80 # 同刻 proc 节点 AeIntegrationTime : 595 AeAGain : 1024
对比项能否直接比说明
it ↔ AeIntegrationTime✅ 直接比都是曝光行数。上例 598 vs 595 的差值是抓取时刻不同(AE 正在收敛),取同一帧或稳定态应相等
again ↔ AeAGain⚠️ 需查表AeAGain 是倍数(1024 = 1x),经 sc4336p_alloc_again 查 again_lut 表得到寄存器值。上例 1024 → 0x80(表首项 {0x0080, 0},即增益下限档);增益升高时按表逐档递增,只看趋势是否跟得上,不要比数值
对比结果结论
一致(it 相等、again 按 AE 分配同步变化)闪烁与 AE 算法无关,查 sensor 驱动:增益表(again_lut)、增益上限、隔帧生效、寄存器写入时机
不一致(sensor 收到值和 AE 分配不符)问题在 AE 算法侧或参数传递,向上排查分配逻辑

避免误判

  1. 先切 Manual 定性,快速定位模块;

  2. FPS/VTS 必须核对,flicker 相关几乎都和它有关;

  3. 注意隔帧生效:双摄和单摄配置不同,参数照搬单摄会错;

  4. 曝光表和驱动限制要对齐:表里设的值超过驱动能力时,串口会有提示,不要只看工具显示;

结论

先切 Manual 确认是不是 AE;再用工具和串口查模式、帧率、曝光表、隔帧生效;然后 cat proc 节点或调 API 看 AeLuma 和增益是否跳变;都不行才改驱动加打印,与 sensor 驱动输入值对比——一致查驱动,不一致查算法。
评论交流 (共 0 条)