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. mysql query insert中文乱码

    mysql新建的表的charset都是utf8的. 在phpmyadmin里直接敲sql,中文可以insert进去的,但是在php代码里mysql_query同样的sql语句就是不行,保存到表里是乱码 ...

  2. linux指令大全(完整篇)(转)

       http://blog.chinaunix.net/uid-9681606-id-1998590.html  linux指令大全(完整篇)(转) 2009-03-17 01:21:46 分类:  ...

  3. MVC中Razor视图基本语法(1)

    Razor前面,必须要跟前面的有空隙,即空格(多谢一楼提醒,url里面确实不用空格,如果要在url里面只需要@(ViewBag.),加上括号就好了),之后的必须要连贯,否则加小括号 1,在页面中输出单 ...

  4. 『奇葩问题集锦』Fedora ubuntu 下使用gulp 报错 Error: watch ENOSPC 解决方案

    用gulp启动,错误如下 Error: watch ENOSPC at exports._errnoException (util.js:746:11) at FSWatcher.start (fs. ...

  5. Python 命令行参数解析

    方法1: Python有一个类可以专门处理命令行参数,先看代码: #!/usr/bin/env python # encoding: utf-8 from optparse import Option ...

  6. 树莓派上搭建基于Python+web.py+fastcgi+lighttpd的网站

    最近在网上淘了一个树莓派,什么是树莓派?这里是他的官方网站你可以去看看. 简单的说就是一块使用了ARM11的CPU,具有256MB或512MB内存的具有两个USB接口,一个RJ45接口,HDMI输出和 ...

  7. bzoj2427: [HAOI2010]软件安装

    Description 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和 ...

  8. 基础canvas应用-钟表绘制

    首先,canvas语法基础薄弱的小伙伴请点这里,剩下的小伙伴们可以接着往下看了. 一个表,需要画什么出来呢:3条线(时分秒针),1个圆(表盘),以及60条短线/点(刻度). 嗯,没毛病. 那接下来让我 ...

  9. 【Python网络爬虫三】 爬去网页新闻

    学弟又一个自然语言处理的项目,需要在网上爬一些文章,然后进行分词,刚好牛客这周的是从一个html中找到正文,就实践了一下.写了一个爬门户网站新闻的程序 需求: 从门户网站爬取新闻,将新闻标题,作者,时 ...

  10. 【转载】C# HttpWebRequest 发送SOAP XML

    调用webservice的几种方法: 方法一:添加web引用(简单/方便 局限客户端是.net) 方法二:Post xml(本文重点讲述) 方法三:使用微软MSXML2组件(好像在window ser ...