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。
相关推荐
不学习何以强国2 小时前
宝塔Linux面板+进程守护管理器,部署.net8 core网站
linux·运维·服务器
cooldream20092 小时前
Vim 报错 E325:swap 文件冲突的原理、处理流程与彻底避免方案
linux·编辑器·vim
i建模2 小时前
在 Rocky Linux 上安装轻量级的 XFCE 桌面
linux·运维·服务器
若风的雨3 小时前
WC (Write-Combining) 内存类型优化原理
linux
YMWM_3 小时前
不同局域网下登录ubuntu主机
linux·运维·ubuntu
zmjjdank1ng3 小时前
restart与reload的区别
linux·运维
哼?~3 小时前
进程替换与自主Shell
linux
浩浩测试一下3 小时前
DDOS 应急响应Linux防火墙 Iptable 使用方式方法
linux·网络·安全·web安全·网络安全·系统安全·ddos
niceffking4 小时前
linux 信号内核模型
linux·运维·服务器