1. V4L2

1)简介

在Linux中,摄像头方面的标准化程度比较高,这个标准就是V4L2驱动程序,这也是业界比较公认的方式。

V4L全称是Video for Linux,是Linux内核中标准的关于视频驱动程序,目前使用比较多的版本是Video for Linux 2,简称V4L2。它为Linux下的视频驱动提供了统一的接口,使得应用程序可以使用统一的API操作不同的视频设备。从内核空间到用户空间,主要的数据流和控制类均由V4L2驱动程序的框架来定义。

V4L2驱动程序一般只提供Video数据的获得,而如何实现视频预览,如何向上层发送数据,如何把纯视频流和取景器、视频录制等实际业务组织起来,都是camera的硬件抽象层需要负责的工作。

V4L2驱动核心实现为如下文件:drivers/media/video/v4l2-dev.c。

V4l2-dev.h中定义的video_device是V4L2驱动程序的核心数据结构,它为具体的摄像头sensor驱动提供了接口调用。

V4l2的采集过程(应用程序):

1)     打开设备,获得文件描述符;

2)     设置图片格式;

3)     分配缓冲区;

4)     启动采集过程,读取数据;

5)     停止采集,关闭设备。

2)数据结构

V4L2的主要数据结构是video_device,定义在v4l2_dev.h中:

  1. struct video_device
  2. {
  3. /* device ops */
  4. const struct v4l2_file_operations *fops;  /*接口函数指针*/
  5. /* sysfs */
  6. struct device dev;      /* v4l 设备结构 */
  7. struct cdev *cdev;      /* 字符设备结构*/
  8. /* Set either parent or v4l2_dev if your driver uses v4l2_device */
  9. struct device *parent;      /* 设备父指针 */
  10. struct v4l2_device *v4l2_dev;   /* v4l2设备指针*/
  11. /* device info */
  12. char name[32];  /*设备名称*/
  13. int vfl_type;
  14. /* 'minor' is set to -1 if the registration failed */
  15. int minor;    /*次设备号*/
  16. u16 num;
  17. /* use bitops to set/clear/test flags */
  18. unsigned long flags;
  19. /* attribute to differentiate multiple indices on one physical device */
  20. int index;
  21. /* V4L2 file handles */
  22. spinlock_t      fh_lock; /* Lock for all v4l2_fhs */
  23. struct list_head    fh_list; /* List of struct v4l2_fh */
  24. int debug;          /* debug 级别*/
  25. /* Video 标准变量 */
  26. v4l2_std_id tvnorms;        /* Supported tv norms */
  27. v4l2_std_id current_norm;   /* Current tvnorm */
  28. /* 回调函数 */
  29. void (*release)(struct video_device *vdev);
  30. /* ioctl 回调函数 */
  31. const struct v4l2_ioctl_ops *ioctl_ops;
  32. };

主要接口函数有:

intvideo_register_device(struct video_device *vdev, int type, int nr);

static intv4l2_ioctl(struct inode *inode, struct file *filp,       unsigned int cmd, unsigned long arg);

2.  FIMC                     

1)简介

FIMC这个模块不仅仅是一个摄像头的控制接口,它还承担着V4L2的output功能和overlay的功能。

FIMC的驱动在内核中的位置:drivers/media/video/samsung/fimc

它包含下边的文件:

fimc_regs.c
        fimc_capture.c
        fimc_dev.c
        fimc_output.c
        fimc_overlay.c
        fimc_v4l2.c

它们的组织关系如下:

可以看到,FIMC的驱动实现了v4l2所有的接口,可以分为v4l2-input设备接口,v4l2-output设备接口以及v4l2-overlay设备接口。这里我们主要关注v4l2-input设备接口,因为摄像头属于视频输入设备。

fimc_v4l2.c里面注册了很多的回调函数,都是用于实现v4l2的标准接口的,但是这些回调函数基本上都不是在fimc_v4l2.c里面实现的,而是有相应的.c分别去实现。比如:

v4l2-input设备的操作实现:fimc_capture.c
        v4l2-output设备的操作实现: fimc_output.c
        v4l2-overlay设备的操作实现: fimc_overlay.c

这些代码其实都是和具体硬件操作无关的,这个驱动把所有操作硬件寄存器的代码都写到一个文件里面了,就是fimc40_regs.c。这样把硬件相关的代码和硬件无关的代码分开来实现是非常好的方式,可以最大限度的实现代码复用。

 2) 数据结构 

FIMC的主要数据结构fimc_control,定义在fimc.h中:

  1. struct fimc_control {
  2. int             id;     /* 控制器 id */
  3. char                name[16];
  4. atomic_t            in_use;
  5. void __iomem            *regs;      /* 寄存器 i/o */
  6. struct clk          *clk;       /* interface clock */
  7. struct regulator    *regulator;     /* pd regulator */
  8. struct fimc_meminfo     mem;        /* for reserved mem */
  9. /* kernel helpers */
  10. struct mutex            lock;       /* controller lock */
  11. struct mutex            alloc_lock;
  12. struct mutex            v4l2_lock;
  13. wait_queue_head_t       wq;
  14. struct device           *dev;
  15. int             irq;
  16. /* v4l2 related */
  17. struct video_device     *vd;
  18. struct v4l2_device      v4l2_dev;
  19. /* fimc specific */
  20. struct fimc_limit       *limit;     /* H/W limitation */
  21. struct s3c_platform_camera  *cam;       /* activated camera */
  22. struct fimc_capinfo     *cap;       /* capture dev info */
  23. struct fimc_outinfo     *out;       /* output dev info */
  24. struct fimc_fbinfo      fb;     /* fimd info */
  25. struct fimc_scaler      sc;     /* scaler info */
  26. struct fimc_effect      fe;     /* fimc effect info */
  27. enum fimc_status        status;
  28. enum fimc_log           log;
  29. u32             ctx_busy[FIMC_MAX_CTXS];
  30. };

因为FIMC一共有三套一样的控制器(fimc0, fimc1, fimc2),所以驱动里使用了一个数组来描述:

  1. struct video_device fimc_video_device[FIMC_DEVICES] = {
  2. [0] = {
  3. .fops = &fimc_fops,
  4. .ioctl_ops = &fimc_v4l2_ops,
  5. .release = fimc_vdev_release,
  6. },
  7. [1] = {
  8. .fops = &fimc_fops,
  9. .ioctl_ops = &fimc_v4l2_ops,
  10. .release = fimc_vdev_release,
  11. },
  12. [2] = {
  13. .fops = &fimc_fops,
  14. .ioctl_ops = &fimc_v4l2_ops,
  15. .release = fimc_vdev_release,
  16. },
  17. };

fb_ops结构体是针对v4l2设备的基本操作,定义如下:

  1. static const struct v4l2_file_operations fimc_fops = {
  2. .owner      = THIS_MODULE,
  3. .open       = fimc_open,
  4. .release    = fimc_release,
  5. .ioctl      = video_ioctl2,
  6. .read       = fimc_read,
  7. .write      = fimc_write,
  8. .mmap       = fimc_mmap,
  9. .poll       = fimc_poll,
  10. };

3)FIMC初始设置

在S5PV210中,FIMC初始设置代码在 /drivers/ arch/arm/mach-s5pv210/mach-smdkv310.c中:

  1. static struct s3c_platform_fimc fimc_plat = {
  2. .srclk_name = "mout_mpll",
  3. .clk_name   = "sclk_fimc",
  4. .lclk_name  = "sclk_fimc_lclk",
  5. .clk_rate   = 166750000,
  6. .default_cam    = CAMERA_CSI_C,
  7. .camera        = {
  8. &mt9p111,//5M back cam
  9. &s5k6aafx,///1.3M front cam
  10. },
  11. .hw_ver     = 0x43,
  12. };

对于GPIO的配置代码在 /drivers/ arch/arm/mach-s5pv210/setup-fimc0.c中:

  1. oid s3c_fimc0_cfg_gpio(struct platform_device *pdev)
  2. {
  3. int i = 0;
  4. /* CAM A port(b0010) : PCLK, VSYNC, HREF, DATA[0-4] */
  5. for (i = 0; i < 8; i++) {
  6. s3c_gpio_cfgpin(S5PV210_GPE0(i), S3C_GPIO_SFN(2));
  7. s3c_gpio_setpull(S5PV210_GPE0(i), S3C_GPIO_PULL_NONE);
  8. }
  9. /* CAM A port(b0010) : DATA[5-7], CLKOUT(MIPI CAM also), FIELD */
  10. for (i = 0; i < 5; i++) {
  11. s3c_gpio_cfgpin(S5PV210_GPE1(i), S3C_GPIO_SFN(2));
  12. s3c_gpio_setpull(S5PV210_GPE1(i), S3C_GPIO_PULL_NONE);
  13. }
  14. /* CAM B port(b0011) : DATA[0-7] */
  15. for (i = 0; i < 8; i++) {
  16. s3c_gpio_cfgpin(S5PV210_GPJ0(i), S3C_GPIO_SFN(3));
  17. s3c_gpio_setpull(S5PV210_GPJ0(i), S3C_GPIO_PULL_NONE);
  18. }
  19. /* CAM B port(b0011) : PCLK, VSYNC, HREF, FIELD, CLCKOUT */
  20. for (i = 0; i < 5; i++) {
  21. s3c_gpio_cfgpin(S5PV210_GPJ1(i), S3C_GPIO_SFN(3));
  22. s3c_gpio_setpull(S5PV210_GPJ1(i), S3C_GPIO_PULL_NONE);
  23. }
  24. }

4)接口函数

FIMC的主要回调函数如下,实现在fimc_v4l2.c中:

  1. onst struct v4l2_ioctl_ops fimc_v4l2_ops = {
  2. .vidioc_querycap        = fimc_querycap,
  3. .vidioc_reqbufs         = fimc_reqbufs,
  4. .vidioc_querybuf        = fimc_querybuf,
  5. .vidioc_g_ctrl          = fimc_g_ctrl,
  6. .vidioc_s_ctrl          = fimc_s_ctrl,
  7. .vidioc_s_ext_ctrls     = fimc_s_ext_ctrls,
  8. .vidioc_cropcap         = fimc_cropcap,
  9. .vidioc_g_crop          = fimc_g_crop,
  10. .vidioc_s_crop          = fimc_s_crop,
  11. .vidioc_streamon        = fimc_streamon,
  12. .vidioc_streamoff       = fimc_streamoff,
  13. .vidioc_qbuf            = fimc_qbuf,
  14. .vidioc_dqbuf           = fimc_dqbuf,
  15. .vidioc_enum_fmt_vid_cap    = fimc_enum_fmt_vid_capture,
  16. .vidioc_g_fmt_vid_cap       = fimc_g_fmt_vid_capture,
  17. .vidioc_s_fmt_vid_cap       = fimc_s_fmt_vid_capture,
  18. .vidioc_try_fmt_vid_cap     = fimc_try_fmt_vid_capture,
  19. .vidioc_enum_input      = fimc_enum_input,
  20. .vidioc_g_input         = fimc_g_input,
  21. .vidioc_s_input         = fimc_s_input,
  22. .vidioc_g_parm          = fimc_g_parm,
  23. .vidioc_s_parm          = fimc_s_parm,
  24. .vidioc_queryctrl       = fimc_queryctrl,
  25. .vidioc_querymenu       = fimc_querymenu,
  26. .vidioc_g_fmt_vid_out       = fimc_g_fmt_vid_out,
  27. .vidioc_s_fmt_vid_out       = fimc_s_fmt_vid_out,
  28. .vidioc_try_fmt_vid_out     = fimc_try_fmt_vid_out,
  29. .vidioc_g_fbuf          = fimc_g_fbuf,
  30. .vidioc_s_fbuf          = fimc_s_fbuf,
  31. .vidioc_try_fmt_vid_overlay = fimc_try_fmt_overlay,
  32. .vidioc_g_fmt_vid_overlay   = fimc_g_fmt_vid_overlay,
  33. .vidioc_s_fmt_vid_overlay   = fimc_s_fmt_vid_overlay,
  34. };

对于寄存器的操作,实现都在fimc_regs.c文件中,如

    1. int fimc_hwset_camera_source(struct fimc_control *ctrl)
    2. {
    3. struct s3c_platform_camera *cam = ctrl->cam;
    4. u32 cfg = 0;
    5. cfg |= S3C_CISRCFMT_ITU601_8BIT;
    6. cfg |= cam->order422;
    7. if (cam->type == CAM_TYPE_ITU)
    8. cfg |= cam->fmt;
    9. cfg |= S3C_CISRCFMT_SOURCEHSIZE(cam->width);
    10. cfg |= S3C_CISRCFMT_SOURCEVSIZE(cam->height);
    11. writel(cfg, ctrl->regs + S3C_CISRCFMT);
    12. return 0;
    13. }
    14. int fimc_hwset_enable_irq(struct fimc_control *ctrl, int overflow, int level)
    15. {
    16. u32 cfg = readl(ctrl->regs + S3C_CIGCTRL);
    17. cfg &= ~(S3C_CIGCTRL_IRQ_OVFEN | S3C_CIGCTRL_IRQ_LEVEL);
    18. cfg |= S3C_CIGCTRL_IRQ_ENABLE;
    19. if (overflow)
    20. cfg |= S3C_CIGCTRL_IRQ_OVFEN;
    21. if (level)
    22. cfg |= S3C_CIGCTRL_IRQ_LEVEL;
    23. writel(cfg, ctrl->regs + S3C_CIGCTRL);
    24. return 0;
    25. }

android camera(三):camera V4L2 FIMC的更多相关文章

  1. 【转】android camera(三):camera V4L2 FIMC

    关键词:android  camera CMM 模组 camera参数  CAMIF   V4L2  平台信息:内核:linux系统:android 平台:S5PV310(samsung exynos ...

  2. sc7731 Android 5.1 Camera 学习之一Camera 两个对象

    众所周知,在Android中Camera采用了C/S架构,其中Camera server 与 Camera client之间通过Android Binder IPC机制进行通信.在Camera实现的框 ...

  3. 【转】[Android编程心得] Camera(OpenCV)自动对焦和触摸对焦的实现

    参考http://stackoverflow.com/questions/18460647/android-setfocusarea-and-auto-focus http://blog.csdn.n ...

  4. Android 自带 camera 详解

    在本文中 需要考虑的问题 概述 Manifest声明 使用内置的摄像头应用程序 捕获图像的intent 捕获视频的intent 接收摄像头intent的结果 创建摄像头应用程序 检测摄像头硬件 访问摄 ...

  5. Android中利用Camera与Matrix实现3D效果详解

    本文行文目录: 一.Camera与Matrix初步认识 二.Camera与Matrix旋转效果拆分介绍 三.Camera与Matrix实现立体3D切换效果 [csdn地址:http://blog.cs ...

  6. [Android编程心得] Camera(OpenCV)自动对焦和触摸对焦的实现

    写在前面 最近在从零开始写一个移动端的AR系统,坑实在是太多了!!!整个项目使用了OpenCV第三方库,但对于摄像机来说,和原生Camera的方法基本相同. 实现 以OpenCV的JavaCamera ...

  7. Android 5.1 Camera 架构学习之Camera初始化

    Android Camera 采用C/S架构,client 与server两个独立的线程之间(CameraService)使用Binder通信. 一 CameraService的注册. 1.手机开机后 ...

  8. Android开发技巧——Camera拍照功能

    本篇是我对开发项目的拍照功能过程中,对Camera拍照使用的总结.由于camera2是在api level 21(5.0.1)才引入的,而Camera到6.0仍可使用,所以暂未考虑camera2. 文 ...

  9. Android 自定义属性动画&Camera动画

      摘要: Android 自定义属性动画&Camera动画 1.相关知识点 对于Androi的帧动画,可以制作gif图片,有时为了能够动态的生成帧动画,就得需要使用代码构建了 Animati ...

  10. Cesium案例解析(三)——Camera相机

    目录 1. 概述 2. 实例 2.1. Camera.html 2.2. Camera.js 2.2.1. 飞行至某一点 2.2.2. 飞行至某区域 2.2.3. 两地之间飞行 2.2.4. 设置视图 ...

随机推荐

  1. ASP.NET前端语法应用

    字符拼接 <%# "abc" + Eval("列名").ToString() %> <%# Eval("列名"," ...

  2. Spark-Cassandra-Connector 插入数据函数saveToCassandra

    在spark-shell中将数据保存到cassandra: var data = normalfill.map(line => line.split("\u0005")) d ...

  3. apache基本安装配置

    1.安装apache 1.安装 wget http://mirrors.cnnic.cn/apache//httpd/httpd-2.2.31.tar.gz 2.安装zlib yum install ...

  4. Ubuntu 之旅—— 调整扩展屏分辨率

    打开终端输入 xrandr 得到如下信息 Screen 0: minimum 320 x 200, current 2390 x 768, maximum 8192 x 8192 LVDS conne ...

  5. Jquery操作单选按钮(Radio)的取值赋值实现代码

    1.获取选中值,三种方法都可以: $('input:radio:checked').val(); $("input[type='radio']:checked").val(); $ ...

  6. Cassandra1.2文档学习(1)——Cassandra基本说明

    参考文档:http://www.datastax.com/documentation/cassandra/1.2/webhelp/index.html#cassandra/architecture/a ...

  7. php文件锁解决少量并发问题

    阻塞(等待)模式: <?php $fp = fopen("lock.txt", "r"); if(flock($fp,LOCK_EX)) { //..处理 ...

  8. JVM 找出最耗 cpu的线程 并打印线程栈

    监控JVM中最占cpu的线程 top -Hp pid JVM中最占cpu的线程ID -o THREAD,tid,time | awk 'BEGIN {count=0; } { if($2>0.3 ...

  9. Http 状态码详解

    状态码 含义 100 客户端应当继续发送请求.这个临时响应是用来通知客户端它的部分请求已经被服务器接收,且仍未被拒绝.客户端应当继续发送请求的剩余部分,或者如果请求已经完成,忽略这个响应.服务器必须在 ...

  10. 预处理命令#define #undef #if #endif 的基本用法

    C#的预处理命令其实还是蛮有用的,但是真正使用过得人不多,这个介绍一下平时用的比较多的预处理命令中的几个:#define,#undef ,#if,#endif.除此之外还有一些预处理命令#warnin ...