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. python 自动化之路 day 02

    本节内容: 列表.元组操作 字符串操作 1. 列表.元组操作 列表是我们最以后最常用的数据类型之一,通过列表可以对数据实现最方便的存储.修改等操作 定义列表 1 names = ['Alex',&qu ...

  2. python的一个表达式的计算(超简单)

    运行的过程如下: 输入计算表达式:3+5 计算结果:8 然后再次显示计算表达式,等待输入完成后,再次显示结果,依此循环.   作为初学者再适合不过,代码也简单,如下所示: #!/usr/bin/env ...

  3. zTree的getChangeCheckedNodes()使用

    zTree的getChangeCheckedNodes()方法用于获取输入框勾选状态被改变的节点集合.如果需要获取每次操作后全部被改变勾选状态的节点数据,请在每次勾选操作后,遍历所有被改变勾选状态的节 ...

  4. [C#]递归遍历文件夹

    /// <summary> /// 递归获取文件夹目录下文件 /// </summary> /// <param name="pathName"> ...

  5. setInterval和setTimeout定时器

    1,文本框自增(重零开始)每隔一秒递增1 <input type="text" name="name" value="0" id=&q ...

  6. 使用Fiddler提高前端工作效率 (实例篇)

    上篇中,我们对Fiddler Web Debugger有了简单的接触,也许你已经开始在用Fiddler进行HTTP相关的调试,在这一篇,我们将通过一个实例了解Fiddler的神奇魔法. 在我们前端开发 ...

  7. javascript进阶——测试和打包分发

    建立一个面向对象的好的代码基础后,为了达到代码重用的目的,通过调试使用适当的测试用例进行测试尤为必要,之后就是打包分发的主题. 一.调试与测试 1.调试 Firebug:包含了错误控制台.调试器.DO ...

  8. (转载).Net HttpPost的发送和接收示例代码

    HttpPost在不同系统进行数据交互的时候经常被使用.它的最大好处在于直接,不像Webservice或者WCF需要wsdl作为一个双方的"中介".在安全性上,往往通过IP限制的方 ...

  9. [简历] JAVA 软件工程师

    首先,一份好的简历不光说明事实,更通过FAB模式来增强其说服力. Feature:是什么 Advantage:比别人好在哪些地方 Benefit:如果雇佣你,招聘方会得到什么好处 其次,写简历和写议论 ...

  10. C++程序的编写和实现

    C++程序的编写和实现 一个程序从编写到最后得到运行结果要经历以下一些步骤. 1. 用C++语言编写程序 用高级语言编写的程序称为“源程序”(source program).C++的源程序是以.cpp ...