V4L2 框架下 `v4l2-ctl --list-frameintervals` 调用链解析

V4L2 框架下 v4l2-ctl --list-frameintervals 调用链解析

背景

在调试 Rockchip 平台的 CIF + Sensor 驱动时,使用命令:

bash 复制代码
v4l2-ctl -d /dev/video0 --list-frameintervals width=3864,height=2192

会看到既有 Sensor 驱动 (IMX415) 的打印,又有 CIF 驱动 (rkcif) 的打印。很多人会疑惑:为什么一个命令会触发两处打印?


调用链分析

1. 用户空间

  • 命令 v4l2-ctl --list-frameintervals 对 /dev/video0 发起 ioctl:
    VIDIOC_ENUM_FRAMEINTERVALS

2. 内核第一阶段:Subdev 层

  • 在处理 VIDIOC_ENUM_FRAMEINTERVALS 时,内核会先尝试调用 subdev 的 g_frame_interval。

  • 路径:

    复制代码
    drivers/media/v4l2-core/v4l2-subdev.c
    → call_g_frame_interval()
       → sd->ops->video->g_frame_interval()
  • 此时进入 IMX415 驱动 :

    c 复制代码
    static int imx415_g_frame_interval(struct v4l2_subdev *sd,
                                       struct v4l2_subdev_frame_interval *fi)
    {
        fi->interval.numerator = 1;
        fi->interval.denominator = 30;
        printk("zzz imx415_g_frame_interval: width=%d height=%d fps=%d/%d\n",
               mode->width, mode->height,
               fi->interval.denominator, fi->interval.numerator);
        return 0;
    }
  • 所以你先看到 IMX415 的打印。

3. 内核第二阶段:Capture 层

  • 真正的 ioctl 实现是在 CIF 驱动:

    复制代码
    drivers/media/platform/rockchip/cif/capture.c
    → rkcif_enum_frameintervals()
  • 它内部再次调用:

    c 复制代码
    ret = v4l2_subdev_call(sensor->sd, video, g_frame_interval, &fi);
  • 但此处的 sensor->sd 指向的是 rockchip-mipi-csi2 bridge,而不是 IMX415。

  • 因为 CSI2 bridge 没有实现 g_frame_interval,所以返回 -ENOIOCTLCMD,CIF fallback 到默认 30fps。

  • 所以你又看到 CIF 的打印 :

    复制代码
    rkcif_enum_frameintervals: sensor->sd name=rockchip-mipi-csi2 ...
    sensor not implements g_frame_interval, use default 30fps

为什么会有两次打印

  • 一次 ioctl → 用户空间只调用了 VIDIOC_ENUM_FRAMEINTERVALS。
  • 两次打印 → 内核处理时分成两个阶段:
    1. 先调用 subdev 的 g_frame_interval → 打印 IMX415。
    2. 再调用 capture 驱动的 enum_frameintervals → 打印 CIF。

问题根因

  • CIF 驱动的 active_sensor->sd 指向的是 CSI2 bridge,而不是 IMX415。
  • 所以 CIF 层拿不到 IMX415 的真实 fps,只能 fallback 到默认 30fps。

调试建议

  1. 在 rkcif_enum_frameintervals() 打印:

    c 复制代码
    v4l2_info(&dev->v4l2_dev,
        "zzz %s: sensor->sd name=%s ops=%p video_ops=%p g_frame_interval=%p\n",
        __func__,
        sensor->sd->name,
        sensor->sd->ops,
        sensor->sd->ops ? sensor->sd->ops->video : NULL,
        (sensor->sd->ops && sensor->sd->ops->video) ?
            sensor->sd->ops->video->g_frame_interval : NULL);

    确认 active_sensor->sd 是否真的是 IMX415。

  2. 检查 media graph link,确认 CIF 是否直接绑定到 sensor,而不是 CSI2 bridge。

  3. 如果需要 fps 信息,应当在 CIF 层透传到 sensor,而不是停在 bridge。


总结

  • v4l2-ctl --list-frameintervals 会触发 一次 ioctl,但在内核里分成两个阶段调用。
  • 所以你会看到 先打印 IMX415 (subdev) ,再打印 CIF (capture)。
  • 根因是 CIF 的 active_sensor 指向了 CSI2 bridge,没有实现 g_frame_interval,导致 fallback 到默认 30fps。
相关推荐
KING-WU51214 分钟前
Linux GDB 调试实战指南:从编译到断点调试
linux·运维·服务器
Lucis__17 分钟前
深入理解程序链接与加载—从动静态链接到库加载
linux·elf·链接·程序·动静态库
影视飓风TIM32 分钟前
Linux 进程信号原理与剖析
linux·运维·服务器
缘友一世1 小时前
开源 Linux截图工具闪构(SnapForge)
linux·运维·ubuntu·开源·截图
人工智能和FPGA AI技术1 小时前
wbuntu 极点五笔输入法安装记录(两种方法)
ubuntu·软件构建
朱包林2 小时前
iTerm2终端配置指南
linux·javascript·python·云原生·容器·kubernetes·云计算
祖力552 小时前
Linux系统移植、烧录与环境的搭建
linux·运维·服务器
张小姐的猫3 小时前
【Linux】网络编程 —— 多路转接:epoll
linux·运维·网络
宋明河3 小时前
五种 IO 模型与 select、poll、epoll 对比
linux
玄芯散人4 小时前
【金丹·81】性能分析:你的程序慢在哪
linux·性能优化·perf