Linux内核V4L2架构

[复制链接]
发表于 2026-2-25 22:47:48 | 显示全部楼层 |阅读模式
一.V4L2简介

V4L2是Video for linux2的简称,为linux中关于视频装备的内核驱动。是linux使用体系下一套用于收罗图片、视频和音频数据的通用API接口,共同恰当的视频收罗装备和相应的驱动步伐,可以实现图片、视频、音频等的收罗。 ​ V4L2支持三种方式来收罗图像:内存映射方式(mmap)、直接读取方式(read)和用户指针;
二.V4L2框架

1.紧张结构体
  1. 该结构体描述了视频采集设备的driver信息
  2. 01 struct v4l2_capability
  3. 02 {
  4. 03     __u8 driver[16];       // 驱动名字
  5. 04     __u8 card[32];         // 设备名字
  6. 05     __u8 bus_info[32];     // 设备在系统中的位置
  7. 06     __u32 version;         // 驱动版本号
  8. 07     __u32 capabilities;    // 设备支持的操作
  9. 08     __u32 reserved[4];     // 保留字段
  10. 09 };
复制代码
  1. 该结构体描述当前camera(摄像机)支持的格式信息
  2. 01 struct v4l2_fmtdesc
  3. 02 {
  4. 03     __u32 index;               // 要查询的格式序号,应用程序设置
  5. 04     enum v4l2_buf_type type;   // 帧类型,应用程序设置
  6. 05     __u32 flags;               // 是否为压缩格式
  7. 06     __u8 description[32];      // 格式名称
  8. 07     __u32 pixelformat;         //所支持的格式
  9. 08     __u32 reserved[4];         // 保留
  10. 09 };
复制代码
  1. 该结构体描述每帧图像的具体格式,包括帧类型以及图像的长、宽等信息
  2. 01 struct v4l2_format
  3. 02 {
  4. 03     enum v4l2_buf_type type;          // 帧类型,应用程序设置
  5. 04     union fmt
  6. 05     {
  7. 06         struct v4l2_pix_format pix;   // 视频设备使用
  8. 07         struct v4l2_window win;
  9. 08         struct v4l2_vbi_format vbi;
  10. 09         struct v4l2_sliced_vbi_format sliced;
  11. 10         __u8 raw_data[200];
  12. 11     };
  13. 12 };
复制代码
  1. 该结构体描述申请的缓冲区的基本信息
  2. 01 struct v4l2_requestbuffers
  3. 02 {
  4. 03     __u32 count;                    // 缓冲区内缓冲帧的数目
  5. 04     enum v4l2_buf_type type;        // 缓冲帧数据格式
  6. 05     enum v4l2_memorymemory;         // 区别是内存映射还是用户指针方式
  7. 06     __u32 reserved[2];
  8. 07 };
复制代码
  1. 该结构体表示一帧图像数据的基本信息,包含序号、缓冲帧长度和缓冲帧地址等信息
  2. 01 struct v4l2_buffer
  3. 02 {
  4. 03     __u32 index;                    //buffer 序号
  5. 04     enum v4l2_buf_type type;        //buffer 类型
  6. 05     __u32 byteused;                 //buffer 中已使用的字节数
  7. 06     __u32 flags;                    // 区分是MMAP 还是USERPTR
  8. 07     enum v4l2_field field;
  9. 08     struct timeval timestamp;       // 获取第一个字节时的系统时间
  10. 09     struct v4l2_timecode timecode;
  11. 10     __u32 sequence;                 // 队列中的序号
  12. 11     enum v4l2_memory memory;        //IO 方式,被应用程序设置
  13. 12     union m
  14. 13     {
  15. 14         __u32 offset;               // 缓冲帧地址,只对MMAP 有效
  16. 15         unsigned long userptr;
  17. 16     };
  18. 17     __u32 length;                   // 缓冲帧长度
  19. 18     __u32 input;
  20. 19     __u32 reserved;
  21. 20 };
复制代码
2.v4l2的实现流程


 

1)Video装备又分为主装备和从装备对于Camera来说, 主装备: Camera Host控制器为主装备,负责图像数据的吸收和传输, 从装备: 从装备为Camera Sensor,一样平常为I2C接口,可通过从装备控制Camera收罗图像的活动,如图像的巨细、图像的FPS等。V4L2的主装备号是81,次装备号范围0~255
2)这些次装备号又分为多类装备:
视频装备(次装备号范围0-63)
Radio(收音机)装备(次装备号范围64-127)
Teletext装备(次装备号范围192-223)
VBI装备(次装备号范围224-255)。
V4L2装备对应的装备节点有/dev/videoX、/dev/vbiX、/dev/radioX。
本文只讨论视频装备,视频装备对应的装备节点是/dev/videoX,视频装备以高频摄像头或Camera为输入源,Linux内核驱动该类装备,吸收相应的视频信息并处理惩罚
2.0v4l2的分层

user space: 应用步伐紧张通过libv4l库来使用摄像头 也可以基于字符装备/dev/videoX自己编写应用步伐 guvcview:用于调试usb摄像头(尚有个软件cheese也可以) v4l2 utilities: v4l2 的工具集(参考前面第3篇文章)
kernel space: sensor、ISP、VIPP、CSI、CCI都为从装备向上,提供dev/videoX节点, 从dphy物理层获取视频数据册通过vb2子模块 CCI :紧张是通过GPIO(供电、片选)、I2C(下发设置下令给sensor)实现设置sensor EHCI/OHCI:USB范例摄像头
实用于收音机,视频编解码器,视频捕获器以及视频输出装备驱动;
hardware CSIC Controller:从dphy获取mipi协议帧 I2C Controller:与sensor的i2c block通讯 GPIO Controller:sensor通常须要供电大概片选
Video Control:视频处理惩罚下令(分辨率协商,数据格式处理惩罚,buffer管理)
Runtime Handle:运行时管理(Pipeline 管理,体系资源管理,制止调治)
Event Process:变乱管理(上层调用,制止等变乱的吸收和分发);
Config Handle:设置管理(硬件拓扑结构,模组自顺应列表);
external device sensror:摄像头的接口紧张有:USB,DVP.MIPI(CSI)
Camera Modules:模组驱动(图像传感器,对焦电机,闪光灯等)
Camera Interfac:接口驱动(MIPI, Sub-Lvds, HiSpi, Bt656, DC等)
Image Signal Processor:图像处理惩罚驱动(根本处理惩罚模块驱动,3A统计驱动)
Video Inout Post Processor:视频输入后处理惩罚(Scaler,OSD等)

 

2.1中紧张的结构体、


 

1)v4l2_device主装备
  1.    struct v4l2_device {
  2.        struct device *dev;  // 父设备指针
  3.    #if defined(CONFIG_MEDIA_CONTROLLER)  // 多媒体设备配置选项
  4.        // 用于运行时数据流的管理,
  5.        struct media_device *mdev;
  6.    #endif
  7.        // 注册的子设备的v4l2_subdev结构体都挂载此链表中
  8.        struct list_head subdevs;
  9.        // 同步用的自旋锁
  10.        spinlock_t lock;
  11.        // 独一无二的设备名称,默认使用driver name + bus ID
  12.        char name[V4L2_DEVICE_NAME_SIZE];
  13.        // 被一些子设备回调的通知函数,但这个设置与子设备相关。子设备支持的任何通知必须在
  14.        // include/media/<subdevice>.h 中定义一个消息头。
  15.        void (*notify)(struct v4l2_subdev *sd, unsigned int notification, void *arg);
  16.        // 提供子设备(主要是video和ISP设备)在用户空间的特效操作接口,
  17.        // 比如改变输出图像的亮度、对比度、饱和度等等
  18.        struct v4l2_ctrl_handler *ctrl_handler;
  19.        // 设备优先级状态
  20.        struct v4l2_prio_state prio;
  21.        /* BKL replacement mutex. Temporary solution only. */
  22.        struct mutex ioctl_lock;
  23.        // struct v4l2_device结构体的引用计数,等于0时才释放
  24.        struct kref ref;
  25.        // 引用计数ref为0时,调用release函数进行释放资源和清理工作
  26.        void (*release)(struct v4l2_device *v4l2_dev);
  27.    };
复制代码
由上图可以知道v4l2_device是v4l2子体系的入口,管理v4l2zi体系的主装备和从装备。简朴装备可以仅分配这个结构体,但在大多数情况下,都会将这个结构体嵌入到一个更大的结构体中以提供v4l2框架的功能,好比struct isp_device
2)video_device
  1. struct video_device
  2. {
  3.     const struct v4l2_file_operations *fops;
  4.     struct cdev *cdev;     //vdev->cdev->ops = &v4l2_fops;  字符设备描述符
  5.     struct v4l2_device *v4l2_dev;
  6.     struct v4l2_ctrl_handler *ctrl_handler;
  7. ​
  8.     struct vb2_queue *queue;  //q->ops = &dmarx_vb2_ops; buf操作真正驱动回调函数
  9.  …………
  10.     const struct v4l2_ioctl_ops *ioctl_ops;//vdev->ioctl_ops = &rkisp_dmarx_ioctl;
  11.  …………
  12. };
复制代码
V4L2子体系使用v4l2_device结构体管理装备,装备的具体使用方法根据装备范例决定,
前面说过管理的装备分为许多种,
假如视频装备,则须要注册video_device结构体,并提供相应的使用方法。
对于视频装备Camera而言,Camera控制器可以视为主装备,接在Camera控制器上的摄像头可以视为从装备。
3) v4l2_subdev从装备
  1. [include/media/v4l2-subdev.h]
  2.    #define V4L2_SUBDEV_FL_IS_I2C        (1U << 0)  // 从设备是I2C设备
  3.    #define V4L2_SUBDEV_FL_IS_SPI        (1U << 1)  // 从设备是SPI设备
  4.    #define V4L2_SUBDEV_FL_HAS_DEVNODE    (1U << 2)  // 从设备需要设备节点
  5.    #define V4L2_SUBDEV_FL_HAS_EVENTS    (1U << 3)  // 从设备会产生事件
  6. ​
  7.    struct v4l2_subdev {
  8.    #if defined(CONFIG_MEDIA_CONTROLLER)  // 多媒体配置选项
  9.        struct media_entity entity;
  10.    #endif
  11.        struct list_head list;  // 子设备串联链表
  12.        struct module *owner;  // 属于那个模块,一般指向i2c_lient驱动模块
  13.        bool owner_v4l2_dev;
  14.        // 标志位,确定该设备属于那种设备,由V4L2_SUBDEV_FL_IS_XX宏确定
  15.        u32 flags;
  16.        // 指向主设备的v4l2_device结构体
  17.        struct v4l2_device *v4l2_dev;
  18.        // v4l2子设备的操作函数集合
  19.        const struct v4l2_subdev_ops *ops;
  20.        // 提供给v4l2框架的操作函数,只有v4l2框架会调用,驱动不使用
  21.        const struct v4l2_subdev_internal_ops *internal_ops;
  22.        // 从设备的控制接口
  23.        struct v4l2_ctrl_handler *ctrl_handler;
  24.        // 从设备的名称,必须独一无二
  25.        char name[V4L2_SUBDEV_NAME_SIZE];
  26.        // 从设备组的ID,由驱动定义,相似的从设备可以编为一组,
  27.        u32 grp_id;
  28.        // 从设备私有数据指针,一般指向i2c_client的设备结构体dev
  29.        void *dev_priv;
  30.        // 主设备私有数据指针,一般指向v4l2_device嵌入的结构体
  31.        void *host_priv;
  32.        // 指向video设备结构体
  33.        struct video_device *devnode;
  34.        // 指向物理设备
  35.        struct device *dev;
  36.        // 将所有从设备连接到全局subdev_list链表或notifier->done链表
  37.        struct list_head async_list;
  38.        // 指向struct v4l2_async_subdev,用于异步事件
  39.        struct v4l2_async_subdev *asd;
  40.        // 指向管理的notifier,用于主设备和从设备的异步关联
  41.        struct v4l2_async_notifier *notifier;
  42.        /* common part of subdevice platform data */
  43.        struct v4l2_subdev_platform_data *pdata;
  44.    };
  45.    // 提供给v4l2框架的操作函数,只有v4l2框架会调用,驱动不使用
  46.    struct v4l2_subdev_internal_ops {
  47.        // v4l2_subdev注册时回调此函数,使v4l2_dev指向主设备的v4l2_device结构体
  48.        int (*registered)(struct v4l2_subdev *sd);
  49.        // v4l2_subdev卸载时回调此函数
  50.        void (*unregistered)(struct v4l2_subdev *sd);
  51.        // 应用调用open打开从设备节点时调用此函数
  52.        int (*open)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh);
  53.        // 应用调用close时调用此函数
  54.        int (*close)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh);
  55.    };
复制代码
V4L2从装备使用struct v4l2_subdev结构体体现,该结构体用于对子装备举行抽象。
险些全部的装备都有多个 IC 模块
它们大概是实体的(比方 USB 摄像头内里包罗 ISP、sensor 等) 也大概是抽象的(如 USB 装备内里的抽象拓扑结构) 它们在 /dev 目次下面天生了多个装备节点,而且这些 IC 模块还创建了一些非 v4l2 装备:DVB、ALSA、FB、I2C 和输入装备。 通常情况下,这些IC模块通过一个大概多个 I2C 总线毗连到主桥驱动上面,同时别的的总线仍旧可用,这些 IC 就称为 ‘sub-devices’。
一个V4L2主装备大概对应多个V4L2从装备,全部主装备对应的从装备都挂到v4l2_device结构体的subdevs链表中。
对于视频装备,从装备就是摄像头,通常情况下是I2C装备,主装备可通过I2C总线控制从装备
比方控制摄像头的焦距、闪光灯等,同时使用 MIPI 大概 LVDS 等接口举行图像数据传输。
struct v4l2_subdev中包罗的struct v4l2_subdev_ops是一个完备的使用函数集,用于对接各种差异的子装备,好比video、audio、sensor等;
4) v4l2_fh
文件访问控制
5)v4l2_ctrl_handler
控制模块,提供子装备(紧张是 video 和 ISP 装备)在用户空间的殊效使用接口
6)media_device
用于运行时数据流的管理,嵌入在 V4L2 device 内部
通过以上函数就完成了对摄像头v4l2框架的抽象
2.1V4L2子装备使用函数


 
 
 
 
 
 
 

 

三.装备树的修改

3.1根本知识

DCMI:DCMI是一个同步并行接口,可以大概从外部8bit、10bit、12bit或14bit的CMOS摄像头吸收高速数据流,支持差异的数据格式:YCbCr4:2:2/RGB565渐进式视频和压缩数据(JPEG)

 

数据吸收时序
在DCMI中数据和同步时钟信号都是由摄像头模块提供的,在PIXCLK的上升沿大概降落沿收罗数据, 时钟沿极性可以通过修改控制寄存器CR.PCKPOL位指定。而VSYNC称为帧同步信号,它指示了一帧数据的开始和竣事; HSYNC称为行同步信号,指示了一帧图像中每一行数据的开始和竣事,在JPEG模式下则用于指示可用数据。

 

上图2是一个吸收数据时序的表示图,图中在PIXCLK的降落沿获取数据,HSYNC和VSYNC的有效状态为1。 (按:看图中的状态应该是在HSYNC和VSYNC为低电平的时间有效,这里却说1是有效状态。查察DCMI的控制寄存器CR的位界说, 文档中对于这两个信号的极性做了如下图的形貌。以是,个人推测HSYNC和VSYNC指示的是无效的数据状态。)

 

在DCMI中支持8位、10位、12位、14位的数据总线,我们可以通过控制寄存器CR的EDM位具体声明。 这些数据线总是以最低位(LSB)的情势接入DCMI的,好比说8位的线宽, 接入DCMI的数据线是DCMI_DR[0:7],10位则是DCMI_DR[0:9]。在DCMI中总是将吸收到的数据拼接为一个32位的数据后,触发DMA哀求。
对于8位的数据线宽,捕获一个32位数据须要4个像素时钟周期(PIXCLK),第一个字节放在LSB的位置上,第四个字节放在MSB上。 对于10位及以上的数据线宽,只须要2个像素时钟周期就可以产生一个32位数据,第一个周期收罗的数据放在低16位的LSB上, 低16位的高位部门用0补齐;第二个周期则放在高16位的LSB上,高位用0补齐。
DCMI模块除了支持HSYNC和VSYNC如许的硬件时钟同步的方式外,还支持内嵌码的情势同步数据。 所谓的内嵌码是指在一帧图像中使用特定命字标着着一帧图像大概一行数据的开始和竣事。这些特定的数字则不可以大概作为图像的数据内容使用, 通常是0xFF和0x00。这种内嵌码的工作方式支持8位线宽的摄像头,在DCMI中接纳的0xFF0000XY的情势界说同步码的, XY的数据内容可以通过寄存器ESCR指定。具体拜见官方手册。

 

由此可知,我们应去找dcmi接口。
3.2装备树


  •         DCMI装备树节点
查找dcmi,内核中ST对STM32MP15x系列芯片的装备树资源了做了界说
  1. arch/arm/boot/dts/stm32mp151.dtsi
  2. dcmi: dcmi@4c006000 {
  3.                         compatible = "st,stm32-dcmi";
  4.                         reg = <0x4c006000 0x400>;
  5.                         interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
  6.                         resets = <&rcc CAMITF_R>;
  7.                         clocks = <&rcc DCMI>;
  8.                         clock-names = "mclk";
  9.                         dmas = <&dmamux1 75 0x400 0xe0000001>;
  10.                         dma-names = "tx";
  11.                         status = "disabled";
  12.                 };
复制代码
固然这是远远不敷的我们要自己添加一下dcmi节点以是我们到devicetree/bindings下搜索dcmi。
  1. STMicroelectronics STM32 Digital Camera Memory Interface (DCMI)
  2. Required properties:
  3. - compatible: "st,stm32-dcmi"
  4. - reg: physical base address and length of the registers set for the device
  5. - interrupts: should contain IRQ line for the DCMI
  6. - resets: reference to a reset controller,
  7.           see Documentation/devicetree/bindings/reset/st,stm32-rcc.txt
  8. - clocks: list of clock specifiers, corresponding to entries in
  9.           the clock-names property
  10. - clock-names: must contain "mclk", which is the DCMI peripherial clock
  11. - pinctrl: the pincontrol settings to configure muxing properly
  12.            for pins that connect to DCMI device.
  13.            See Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml.
  14. - dmas: phandle to DMA controller node,
  15.         see Documentation/devicetree/bindings/dma/stm32-dma.txt
  16. - dma-names: must contain "tx", which is the transmit channel from DCMI to DMA
  17. DCMI supports a single port node with parallel bus. It should contain one
  18. 'port' child node with child 'endpoint' node. Please refer to the bindings
  19. defined in Documentation/devicetree/bindings/media/video-interfaces.txt.
  20. Example:
  21.         dcmi: dcmi@50050000 {
  22.                 compatible = "st,stm32-dcmi";
  23.                 reg = <0x50050000 0x400>;
  24.                 interrupts = <78>;
  25.                 resets = <&rcc STM32F4_AHB2_RESET(DCMI)>;
  26.                 clocks = <&rcc 0 STM32F4_AHB2_CLOCK(DCMI)>;
  27.                 clock-names = "mclk";
  28.                 pinctrl-names = "default";
  29.                 pinctrl-0 = <&dcmi_pins>;
  30.                 dmas = <&dma2 1 1 0x414 0x3>;
  31.                 dma-names = "tx";
  32.                 port {
  33.                         dcmi_0: endpoint {
  34.                                 remote-endpoint = <...>;
  35.                                 bus-width = <8>;
  36.                                 hsync-active = <0>;
  37.                                 vsync-active = <0>;
  38.                                 pclk-sample = <1>;
  39.                         };
  40.                 };
  41.         };
复制代码
通过以上文件我们知道了要添加port和endpoint结点既然要添加节点我们就要去看一下,pinctrl文件里看一下引脚和我们所用是否同等,由于stm32mp15-pinctrl.dtsi中对于DCMI管脚的界说与FS-MP1A实际使用管脚同等,以是无需修改。我们只要添加一下节点即可。
  1. &dcmi {
  2.         status = "okay";
  3.         pinctrl-names = "default", "sleep";
  4.         pinctrl-0 = <&dcmi_pins_a>;
  5.         pinctrl-1 = <&dcmi_sleep_pins_a>;
  6.         port {
  7.                 dcmi_0: endpoint {
  8.                         remote-endpoint = <&ov5640_0>;
  9.                         bus-width = <8>;
  10.                         hsync-active = <0>;
  11.                         vsync-active = <0>;
  12.                         pclk-sample = <1>;
  13.                         pclk-max-frequency = <77000000>;
  14.                 };
  15.         };
  16. };
复制代码
CMOS Camera装备树节点
这里以0v5640举例子同样我们到devicetree/bindings下搜索ov5640。进到media/i2c/ov5640.txt去看
  1. * Omnivision OV5640 MIPI CSI-2 / parallel sensor
  2. Required Properties:
  3. - compatible: should be "ovti,ov5640"
  4. - clocks: reference to the xclk input clock.
  5. - clock-names: should be "xclk".
  6. - DOVDD-supply: Digital I/O voltage supply, 1.8 volts
  7. - AVDD-supply: Analog voltage supply, 2.8 volts
  8. - DVDD-supply: Digital core voltage supply, 1.5 volts
  9. Optional Properties:
  10. - reset-gpios: reference to the GPIO connected to the reset pin, if any.
  11.                This is an active low signal to the OV5640.
  12. - powerdown-gpios: reference to the GPIO connected to the powerdown pin,
  13.                    if any. This is an active high signal to the OV5640.
  14. - rotation: as defined in
  15.             Documentation/devicetree/bindings/media/video-interfaces.txt,
  16.             valid values are 0 (sensor mounted upright) and 180 (sensor
  17.             mounted upside down).
  18. The device node must contain one 'port' child node for its digital output
  19. video port, in accordance with the video interface bindings defined in
  20. Documentation/devicetree/bindings/media/video-interfaces.txt.
  21. OV5640 can be connected to a MIPI CSI-2 bus or a parallel bus endpoint.
  22. Endpoint node required properties for CSI-2 connection are:
  23. - remote-endpoint: a phandle to the bus receiver's endpoint node.
  24. - clock-lanes: should be set to <0> (clock lane on hardware lane 0)
  25. - data-lanes: should be set to <1> or <1 2> (one or two CSI-2 lanes supported)
  26. Endpoint node required properties for parallel connection are:
  27. - remote-endpoint: a phandle to the bus receiver's endpoint node.
  28. - bus-width: shall be set to <8> for 8 bits parallel bus
  29.              or <10> for 10 bits parallel bus
  30. - data-shift: shall be set to <2> for 8 bits parallel bus
  31.               (lines 9:2 are used) or <0> for 10 bits parallel bus
  32. - hsync-active: active state of the HSYNC signal, 0/1 for LOW/HIGH respectively.
  33. - vsync-active: active state of the VSYNC signal, 0/1 for LOW/HIGH respectively.
  34. - pclk-sample: sample data on rising (1) or falling (0) edge of the pixel clock
  35.                signal.
  36. Examples:
  37. &i2c1 {
  38.         ov5640: camera@3c {
  39.                 compatible = "ovti,ov5640";
  40.                 pinctrl-names = "default";
  41.                 pinctrl-0 = <&pinctrl_ov5640>;
  42.                 reg = <0x3c>;
  43.                 clocks = <&clks IMX6QDL_CLK_CKO>;
  44.                 clock-names = "xclk";
  45.                 DOVDD-supply = <&vgen4_reg>; /* 1.8v */
  46.                 AVDD-supply = <&vgen3_reg>;  /* 2.8v */
  47.                 DVDD-supply = <&vgen2_reg>;  /* 1.5v */
  48.                 powerdown-gpios = <&gpio1 19 GPIO_ACTIVE_HIGH>;
  49.                 reset-gpios = <&gpio1 20 GPIO_ACTIVE_LOW>;
  50.                 rotation = <180>;
  51.                 port {
  52.                         /* MIPI CSI-2 bus endpoint */
  53.                         ov5640_to_mipi_csi2: endpoint {
  54.                                 remote-endpoint = <&mipi_csi2_from_ov5640>;
  55.                                 clock-lanes = <0>;
  56.                                 data-lanes = <1 2>;
  57.                         };
  58.                 };
  59.         };
  60. };
  61. &i2c1 {
  62.         ov5640: camera@3c {
  63.                 compatible = "ovti,ov5640";
  64.                 pinctrl-names = "default";
  65.                 pinctrl-0 = <&pinctrl_ov5640>;
  66.                 reg = <0x3c>;
  67.                 clocks = <&clk_ext_camera>;
  68.                 clock-names = "xclk";
  69.                 port {
  70.                         /* Parallel bus endpoint */
  71.                         ov5640_to_parallel: endpoint {
  72.                                 remote-endpoint = <&parallel_from_ov5640>;
  73.                                 bus-width = <8>;
  74.                                 data-shift = <2>; /* lines 9:2 are used */
  75.                                 hsync-active = <0>;
  76.                                 vsync-active = <0>;
  77.                                 pclk-sample = <1>;
  78.                         };
  79.                 };
  80.         };
  81. };
复制代码
通过上文知道了我们要怎么添加装备树
  1. ov5640: camera@3c {
  2.     compatible = "ovti,ov5640";
  3.     reg = <0x3c>;
  4.     clocks = <&clk_ext_camera>;
  5.     clock-names = "xclk";
  6.     DOVDD-supply = <&v2v8>;
  7.     powerdown-gpios = <&gpioa 4 (GPIO_ACTIVE_HIGH | GPIO_PUSH_PULL)>;
  8.     reset-gpios = <&gpioa 3 (GPIO_ACTIVE_LOW | GPIO_PUSH_PULL)>;
  9.     rotation = <180>;
  10.     status = "okay";
  11.     port {
  12.         ov5640_0: endpoint {
  13.             remote-endpoint = <&dcmi_0>;
  14.             bus-width = <8>;
  15.             data-shift = <2>; /* lines 9:2 are used */
  16.             hsync-active = <0>;
  17.             vsync-active = <0>;
  18.             pclk-sample = <1>;
  19.             pclk-max-frequency = <77000000>;
  20.         };
  21.     };
  22. };
复制代码
由于我们这里用了2.8V电源和24M时钟以是我们去添加这两个
同样我们不知道怎么写去devicetree/bindings/regulator/st,stpmic1-regulator.txt文件下参考。之后增补
  1.     v2v8: regulator-2p8v {
  2.             compatible = "regulator-fixed";
  3.             regulator-name = "v2v8";
  4.             regulator-min-microvolt = <2800000>;
  5.             regulator-max-microvolt = <2800000>;
  6.             regulator-always-on;
  7.             regulator-boot-on;
  8.     };
复制代码
  1.     clocks {
  2.             clk_ext_camera: clk-ext-camera {
  3.                     #clock-cells = <0>;
  4.                     compatible = "fixed-clock";
  5.                     clock-frequency = <24000000>;
  6.             };
  7.     };
复制代码
3.3编译内核
  1. linux@ubuntu:$ make menuconfig
  2. Device Drivers --->
  3.   <*> Multimedia support --->
  4.       [*] V4L platform devices --->
  5.           <*> STM32 Digital Camera Memory Interface (DCMI) support
  6.       I2C Encoders, decoders, sensors and other helper chips --->
  7.           <*> OmniVision OV5640 sensor support
复制代码
四.用ffmpeg测试

4.1添加ffmpeg

使用buildroot-2021.02.1添加ffmpeg

 

选中alsa-utils和ffmpeg之后进入ffmpeg

 

选中自己须要用到的库。之后sudo make,考备至开发板。
4.2视频测试

实行以下下令测试录制视频
ffmpeg -f v4l2 -framerate 10 -i /dev/video1 -q 10 my.mp4
4.3搭建nginx-rtmp服务器举行推流拉流测试

安装以下依赖

 

创建文件夹存放nginx
  1. mkdir rtmp
  2. cd rtmp
  3. wget http://nginx.org/download/nginx-1.13.3.tar.gz
复制代码
去github下载nginx-rtmp模块
  1. git clone https://github.com/arut/nginx-rtmp-module.git
  2. tar -zxvf nginx-1.13.3.tar.gz
  3. cd nginx-1.13.3
  4. ./configure --add-module=../nginx-rtmp-module
  5. make
  6. make install
复制代码
由于版本nginx版本差异,这里不肯定能编译通过。
没报错的话,会有如下目次
/usr/local/nginx
  1. cd /usr/local/nginx
  2. cd sbin
复制代码
启动nginx ./nginx 启动niginx时也大概出现错误,如下:
  1. asdf@ubuntu:/usr/local/nginx/sbin$ ./nginx
  2. nginx: [alert] could not open error log file: open() "/usr/local/nginx/logs/error.log" failed (13: Permission denied)
  3. 2021/07/07 07:39:22 [emerg] 23751#0: mkdir() "/usr/local/nginx/client_body_temp" failed (13: Permission denied)
复制代码
此时须要修改权限
sudo chown root nginx sudo chmod u+s nginx
查察历程
ps -ef|grep nginx
ifconfig 查察ip,欣赏器访问ip,看到下图, 阐明nginx安装ok.

 

留意:这是动态ip, 每次开机启动都差异,假如推流失败大概是ip变更了。 设置rtmp服务 设置文件修改, cd到nginx的conf目次 vim nginx.conf 添加如下内容

 

重启nginx pkill nginx
重启./nginx
推当地流测试 ffmpeg -re -i 1.mp4 -f flv rtmp://192.168.126.132/live
及时推流测试
ffmpeg -f v4l2 -framerate 15 -i /dev/video0 -q 15 -f flv rtmp://192.168.126.132/live
下载VLC软件
VLC播放测试

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表