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。
相关推荐
AI+程序员在路上3 小时前
瑞芯微 RV1126B ADB 调试命令完全指南
linux·adb
小茗的嵌入式学习日记4 小时前
基于IMX6ULL的车载中控系统
linux·c语言·qt
sc_爬坑之路4 小时前
Linux 部署 Redis:一主一从 + Sentinel 完整实战
linux·redis·sentinel
MIXLLRED4 小时前
随笔——Ubuntu固定IP方法
ubuntu·网络ip
从入门到放弃-咖啡豆4 小时前
Alibaba Cloud Linux 部署.NET 8 环境 项目运行
linux·服务器·.net·.net core
wongHome4 小时前
Ubuntu的Anaconda环境如何安装安装rasterio
linux·ubuntu
骆驼10244 小时前
Linux PAM(Pluggable Authentication Modules)完整指南——从入门原理到进阶机制,再到实战配置
linux·安全·pam
圥忈&&丅佽&&扗虖4 小时前
ubuntu 安装git
linux·git·ubuntu
Mr_sun.4 小时前
Mac中通过PD安装Rockly、Centos版本的linux并设置静态ip与安装Docker
linux·macos·centos
爱装代码的小瓶子4 小时前
【c++与Linux进阶】线程篇 -互斥锁
linux·c++·算法