camera_cameralink - CSDN
camera 订阅
camera,英语单词,名词,意为“照相机;摄影机”。 展开全文
camera,英语单词,名词,意为“照相机;摄影机”。
信息
外文名
camera
词    性
名词
camera单词发音
英[ˈkæmrə]美[ˈkæmrə] [1] 
收起全文
  • Camera专题】-从零开始的Camera学习之路——启动篇

    千次阅读 热门讨论 2019-09-03 14:19:26
    如今工作也一年多了,在现在的公司是啥都调试,从EMMC,TP,LCD,CAMERA等等,对于底层驱动也有了一定的认识,现在的状态就是啥都会一些,啥都不精通。 于是,寻寻觅觅一年多,终于确定下来职业发展方向-Camera驱动...

    1.吐槽

    如今工作也一年多了,在现在的公司是啥都调试,从EMMC,TP,LCD,CAMERA等等,对于底层驱动也有了一定的认识,现在的状态就是啥都会一些,啥都不精通。
    于是,寻寻觅觅一年多,终于确定下来职业发展方向-Camera驱动开发


    2019.1.26更新吐槽:
    之前在大学开的博客,没能坚持写技术文章,后来工作后开始坚持写技术文档!
    但是觉得csdn在使用MarkDown语法时,上传图片特别麻烦,于是转战简书写了!
    不过现在感觉,还是csdn做技术氛围较强,简书感觉变了!
    现在就同步更新吧!


    一方面,这一块的薪资诱人,
    在这里插入图片描述

    另一方面,比较感兴趣,而且恰好公司有老前辈搞这个,可以少走弯路!
    但是不确定我们这个老前辈什么水平,我能跟他学的东西或许真的不多,主要还是靠自己静下心来自学吧。

    正如乔布斯所说的——stay hungry,stay foolish!要不停地去寻找自己想学习的东西,想从事的工作!!!从来都不晚!

    2.学习

    camera的方向

    • 1.camera 驱动调试(kernel层)——c语言

    • 2.camera hal层调试开发——c++(涉及到JNI)

    • 3.camera效果调试(tuning)——图像原理,光学,c/c++(涉及面广)

    • 4.camera应用层开发——java

    我现在的想法就是未来3-5年,把1-2搞通搞明白!

    camera的学习方法

    如标题所言,既然是从0开始,那么就是老老实实打基础,掌握必备的技能。

    智者千虑必有一失,愚者千虑亦有一得。

    我自诩是个愚人,傻人用傻方法。

    怎么去学习呢?


    1.看学习文档,边看边记录边思考(好记性不如烂笔头)。

    这些文档来源于网上,MTK官方资料,规格书等。

    2.看源码

    Read the fucking soucecode,这个过程必定是艰辛、枯燥、难熬的。我想唯有坚持可破。

    3.跟着项目解决实际问题。

    解决实际问题,把学到的知识学以致用,积累经验!


    Stay hungry,Stay foolish!

    展开全文
  • camera 基本常识

    千次阅读 2016-08-22 14:22:28
    一、Camera 工作原理介绍 1. 结构 . 一般来说,camera 主要是由 lens 和 sensor IC 两部分组成,其中有的 sensor IC 集成 了 DSP,有的没有集成,但也需要外部 DSP 处理。细分的来讲,camera 设备由下边几部 分...
    
    一、Camera 工作原理介绍
    1. 结构 .

    一般来说,camera 主要是由 lens 和 sensor IC 两部分组成,其中有的 sensor IC 集成 了 DSP,有的没有集成,但也需要外部 DSP 处理。细分的来讲,camera 设备由下边几部 分构成:

     1) lens(镜头) 一般 camera 的镜头结构是有几片透镜组成,分有塑胶透镜(Plastic)和玻璃透 镜(Glass) ,通常镜头结构有:1P,2P,1G1P,1G3P,2G2P,4G 等。

     2) sensor(图像传感器) Senor 是一种半导体芯片,有两种类型:CCD 和 CMOS。Sensor 将从 lens 上传导过来的光线转换为电信号, 再通过内部的 AD 转换为数字信号。 由于 Sensor 的每个 pixel 只能感光 R 光或者 B 光或者 G 光, 因此每个像素此时存贮的是单色的, 我们称之为 RAW DATA 数据。 要想将每个像素的 RAW DATA 数据还原成三基色,就需要 ISP 来处理。 

    3)ISP(图像信号处理) 主要完成数字图像的处理工作,把 sensor 采集到的原始数据转换为显示支持 的格式。 

    4)CAMIF(camera 控制器) 芯片上的 camera 接口电路,对设备进行控制,接收 sensor 采集的数据交给 CPU,并送入 LCD 进行显示。


    2. 工作原理 .
    外部光线穿过 lens 后, 经过 color filter 滤波后照射到 Sensor 面上, Sensor 将从 lens 上传导过来的光线转换为电信号,再通过内部的 AD 转换为数字信号。如果 Sensor 没有集 成 DSP,则通过 DVP 的方式传输到 baseband,此时的数据格式是 RAW DATA。如果集成 了 DSP, RAW DATA 数据经过 AWB、 则 color matrix、 lens shading、 gamma、 sharpness、 AE 和 de-noise 处理,后输出 YUV 或者 RGB 格式的数据。
    最后会由 CPU 送到 framebuffer 中进行显示,这样我们就看到 camera 拍摄到的景象 了。

    3. YUV 与 YCbCr .
    YUV 和 RGB 一样,是色彩空间中常用的色彩模型之一,两者可以相互转换。YUV 中 得 Y 表示亮度,U 和 V 表示色度。与 RGB 相比,它的优点在于占用更少的空间。 YCbCr 则是在世界数字组织视频标准研制过程中作为 ITU - R BT601 建议的一部分, 其实是 YUV 经过缩放和偏移的翻版。 其中 Y 与 YUV 中的 Y 含义一致, Cb , Cr 同样都指色 彩, 只是在表示方法上不同而已。在 YUV 家族中, YCbCr 是在计算机系统中应用最多的成 员, 其应用领域很广泛,JPEG、 MPEG 均采用此格式。 一般人们所讲的 YUV 大多是指 YCbCr。 YCbCr 有许多取样格式, 如 4∶4∶4 , 4∶2∶2 , 4∶1∶1 和 4∶2∶0。

    二、Camera 硬件
    1. CAMIF .

    如下是 S5PV210 的 camera 系统的结构图:



    S5PV210 的 camera 接口控制器叫 FIMC4.3,它支持 ITU R BT-601/656、AXI 和 MIPI(CSI)三种接口方式,最大输入像素是 8192*8192。S5PV210 有三组 camera 接口。

    主要特性: 支持多种输入接口类型:



    ITU-R BT 601/656 模式 DMA(AXI 64 位)模式 MIPI(CSI)模式 Direct FIFO 模式 支持多种输出接口:DMA 模式/Direct FIFO 模式 支持数码调焦(DZI) 最大输入像素 8192*8192 支持图像翻转、旋转等处理效果 生成多种图片格式 支持采集帧控制

    2. 接口信号 .

    FIMC 信号定义如下所示(YCbCr 模式)

    Signal

    VSYNC HREF PCLK DATA[7:0] FIELD CAM_MCLK I I I I


    I/O
    帧同步信号 行同步信号 像素时钟 像素数据 FIELD 信号

    Description

    Type

    Muxed

    O O

    系统时钟信号



    通过 CAM_MCLK 给摄像头提供时钟,RST 是复位线,PWDN 在摄像头工作时应该始终 为低。HREF 是行参考信号,PCLK 是像素时钟,VSYNC 是场同步信号。一旦给摄像头提供了 时钟,并且复位摄像头,摄像头就开始工作了,通过 HREF,PCLK 和 VSYNC 同步传输数字图 像信号。数据是通过 DATA0~DATA7 这八根数据线并行送出的。

    3. 工作时序 .
    FIMC43 支持如下两种视频数据:

    ITU-R BT 601 输入时序图 这种方式下行和帧同步信号独立于视频数据,因此需要同步信号。



    ITU-R BT 656 输入时序图



    这种方式下同步信号已经内嵌到视频数据中了,因此不需要额外的行和帧同步信号。

    (ITU-R BT 601: 16 位数据传输;21 芯;Y、U、V 信号同时传输。 ITU-R BT 656: 9 芯,不需要同步信号;8 位数据传输;串行视频传输;传输速率是 601 的 2 倍;先传 Y, 后传 UV。 )

    同步信号的时延参数 t1:表示 VSYNC 前、后插入周期 t2:表示 HREF 前插入周期 t3:表示 HREF 宽度 t4:表示 HREF 后插入周期



    4. 外部接口 . 外部接口
    硬件原理图的 CAM A 部分:

    CAM B 部分

    5. Camera 内部结构图 .
    下图是 camera 内部结构框图,以 OV sensor 为例:

    三、Camera 驱动
    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 中:

    struct video_device { 

    /* device ops */ 

    const struct v4l2_file_operations *fops; /*接口函数指针*/


    /* sysfs */

     struct device dev; struct cdev *cdev; /* v4l 设备结构 */ 

    /* 字符设备结构*/


    /* Set either parent or v4l2_dev if your driver uses v4l2_device */ 

    struct device *parent; struct v4l2_device *v4l2_dev; /* 设备父指针 */

    /* v4l2 设备指针*/


    /* device info */ 

    char name[32]; 

    int vfl_type; /* 'minor' is set to -1 if the registration failed */ 

    int minor; u16 num; /* use bitops to set/clear/test flags */ 

    unsigned long flags; /* attribute to differentiate multiple indices on one physical device */ 

    int index; /*次设备号*/ 

    /*设备名称*/


    /* V4L2 file handles */ 

    spinlock_t fh_lock; /* Lock for all v4l2_fhs */


    struct list_head fh_list; /* List of struct v4l2_fh */

    int debug;

    /* debug 级别*/

    /* Video 标准变量 */ 

    v4l2_std_id tvnorms; /* Supported tv norms */


    v4l2_std_id current_norm; /* Current tvnorm */

    /* 回调函数 */ 

    void (*release)(struct video_device *vdev);


    /* ioctl 回调函数 */ 

    const struct v4l2_ioctl_ops *ioctl_ops; 

    };


    主要接口函数有: int video_register_device(struct video_device *vdev, int type, int nr);

    static int v4l2_ioctl(struct inode *inode, struct file *filp, long arg);

    unsigned int cmd, unsigned

    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 中:


    struct fimc_control {
            int                             id;             /* controller id */
            char                            name[16];
            atomic_t                        in_use;
            void __iomem                    *regs;          /* register i/o */
            struct clk                      *clk;           /* interface clock */
            struct regulator        *regulator;             /* pd regulator */
            struct fimc_meminfo             mem;            /* for reserved mem */


            /* kernel helpers */
            struct mutex                    lock;           /* controller lock */
            struct mutex                    alloc_lock;
            struct mutex                    v4l2_lock;
            wait_queue_head_t               wq;
            struct device                   *dev;
            int                             irq;


            /* v4l2 related */
            struct video_device             *vd;
            struct v4l2_device              v4l2_dev;


            /* fimc specific */
            struct fimc_limit               *limit;         /* H/W limitation */
            struct s3c_platform_camera      *cam;           /* activated camera */
            struct fimc_capinfo             *cap;           /* capture dev info */
            struct fimc_outinfo             *out;           /* output dev info */
            struct fimc_fbinfo              fb;             /* fimd info */
            struct fimc_scaler              sc;             /* scaler info */
            struct fimc_effect              fe;             /* fimc effect info */


            enum fimc_status                status;
            enum fimc_log                   log;


            u32                             ctx_busy[FIMC_MAX_CTXS];
    };


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

    struct video_device fimc_video_device[FIMC_DEVICES] = { 

    [0] = { .fops = &fimc_fops, .ioctl_ops = &fimc_v4l2_ops, .release = fimc_vdev_release, }, 

    [1] = { .fops = &fimc_fops, .ioctl_ops = &fimc_v4l2_ops, .release = fimc_vdev_release, }, 

    [2] = { .fops = &fimc_fops, .ioctl_ops = &fimc_v4l2_ops, .release = fimc_vdev_release, }, 

    };


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

    static const struct v4l2_file_operations fimc_fops = { 

                .owner  = THIS_MODULE,

                 .open = fimc_open, 

                 .release  = fimc_release,

                 .ioctl = video_ioctl2,

                 .read = fimc_read,

                 .write = fimc_write,

                 .mmap = fimc_mmap,

                 .poll = fimc_poll,

    }; 

    3)FIMC 初始设置 

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

    static struct s3c_platform_fimc fimc_plat_lsi = {
            .srclk_name     = "mout_mpll",
            .clk_name       = "sclk_fimc",
            .lclk_name      = "sclk_fimc_lclk",
            .clk_rate       = 166750000,
    #if defined(CONFIG_VIDEO_S5K4EA)
            .default_cam    = CAMERA_CSI_C,
    #else
    #ifdef CAM_ITU_CH_A
            .default_cam    = CAMERA_PAR_A,
    #else
            .default_cam    = CAMERA_PAR_B,
    #endif
    #endif
            .camera         = {
    #ifdef CONFIG_VIDEO_S5K4ECGX
                            &s5k4ecgx,
    #endif
    #ifdef CONFIG_VIDEO_S5KA3DFX
                            &s5ka3dfx,
    #endif
    #ifdef CONFIG_VIDEO_S5K4BA
                            &s5k4ba,
    #endif
    #ifdef CONFIG_VIDEO_S5K4EA
                            &s5k4ea,
    #endif
    #ifdef CONFIG_VIDEO_HM2055
                            &hm2055,
    #endif
    #ifdef CONFIG_VIDEO_GC0308
                            &gc0308,
    #endif
    #ifdef CONFIG_VIDEO_HIMAX2055
                            &himax2055,
    #endif
    #ifdef CONFIG_VIDEO_ADV7181
                            &adv7181,
    #endif
            },
            .hw_ver         = 0x43,
    };



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

    void s3c_fimc0_cfg_gpio(struct platform_device *pdev) { 

    int i = 0;


    /* CAM A port(b0010) : PCLK, VSYNC, HREF, DATA[0-4] */ 

    for (i = 0; i < 8; i++) { 

    s3c_gpio_cfgpin(S5PV210_GPE0(i), S3C_GPIO_SFN(2)); 

    s3c_gpio_setpull(S5PV210_GPE0(i), S3C_GPIO_PULL_NONE);

     } 

    /* CAM A port(b0010) : DATA[5-7], CLKOUT(MIPI CAM also), FIELD */ 


    for (i = 0; i < 5; i++) { 

    s3c_gpio_cfgpin(S5PV210_GPE1(i), S3C_GPIO_SFN(2)); 

    s3c_gpio_setpull(S5PV210_GPE1(i), S3C_GPIO_PULL_NONE); 

    } /* CAM B port(b0011) : DATA[0-7] */ 


    for (i = 0; i < 8; i++) { 

    s3c_gpio_cfgpin(S5PV210_GPJ0(i), S3C_GPIO_SFN(3));

     s3c_gpio_setpull(S5PV210_GPJ0(i), S3C_GPIO_PULL_NONE); 

    } /* CAM B port(b0011) : PCLK, VSYNC, HREF, FIELD, CLCKOUT */ 


    for (i = 0; i < 5; i++) { 

    s3c_gpio_cfgpin(S5PV210_GPJ1(i), S3C_GPIO_SFN(3)); 

    s3c_gpio_setpull(S5PV210_GPJ1(i), S3C_GPIO_PULL_NONE); 

    }


    4)接口函数 ) 

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


    const struct v4l2_ioctl_ops fimc_v4l2_ops = {
            .vidioc_querycap                = fimc_querycap,
            .vidioc_reqbufs                 = fimc_reqbufs,
            .vidioc_querybuf                = fimc_querybuf,
            .vidioc_g_ctrl                  = fimc_g_ctrl,
            .vidioc_s_ctrl                  = fimc_s_ctrl,
            .vidioc_s_ext_ctrls             = fimc_s_ext_ctrls,
            .vidioc_cropcap                 = fimc_cropcap,
            .vidioc_g_crop                  = fimc_g_crop,
            .vidioc_s_crop                  = fimc_s_crop,
            .vidioc_streamon                = fimc_streamon,
            .vidioc_streamoff               = fimc_streamoff,
            .vidioc_qbuf                    = fimc_qbuf,
            .vidioc_dqbuf                   = fimc_dqbuf,
            .vidioc_enum_fmt_vid_cap        = fimc_enum_fmt_vid_capture,
            .vidioc_g_fmt_vid_cap           = fimc_g_fmt_vid_capture,
            .vidioc_s_fmt_vid_cap           = fimc_s_fmt_vid_capture,
            .vidioc_try_fmt_vid_cap         = fimc_try_fmt_vid_capture,
            .vidioc_enum_input              = fimc_enum_input,
            .vidioc_g_input                 = fimc_g_input,
            .vidioc_s_input                 = fimc_s_input,
            .vidioc_g_parm                  = fimc_g_parm,
            .vidioc_s_parm                  = fimc_s_parm,
            .vidioc_queryctrl               = fimc_queryctrl,
            .vidioc_querymenu               = fimc_querymenu,
            .vidioc_g_fmt_vid_out           = fimc_g_fmt_vid_out,
            .vidioc_s_fmt_vid_out           = fimc_s_fmt_vid_out,
            .vidioc_try_fmt_vid_out         = fimc_try_fmt_vid_out,
            .vidioc_g_fbuf                  = fimc_g_fbuf,
            .vidioc_s_fbuf                  = fimc_s_fbuf,
            .vidioc_try_fmt_vid_overlay     = fimc_try_fmt_overlay,
            .vidioc_g_fmt_vid_overlay       = fimc_g_fmt_vid_overlay,
            .vidioc_s_fmt_vid_overlay       = fimc_s_fmt_vid_overlay,
    };
                                                                  


    5)寄存器操作(fimc_regs.c) )寄存器操作( )

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

    int fimc_hwset_camera_source(struct fimc_control *ctrl) {


     struct s3c_platform_camera *cam = ctrl->cam; u32 cfg = 0;


    cfg |= S3C_CISRCFMT_ITU601_8BIT; cfg |= cam->order422;

    if (cam->type == CAM_TYPE_ITU)

    cfg |= cam->fmt;

    cfg |= S3C_CISRCFMT_SOURCEHSIZE(cam->width); 

    cfg |= S3C_CISRCFMT_SOURCEVSIZE(cam->height);


    writel(cfg, ctrl->regs + S3C_CISRCFMT);

    return 0; 

    }


    int fimc_hwset_enable_irq(struct fimc_control *ctrl, int overflow, int level) { 

    u32 cfg = readl(ctrl->regs + S3C_CIGCTRL);


    cfg &= ~(S3C_CIGCTRL_IRQ_OVFEN | S3C_CIGCTRL_IRQ_LEVEL); 

    cfg |= S3C_CIGCTRL_IRQ_ENABLE;


    if (overflow) cfg |= S3C_CIGCTRL_IRQ_OVFEN;

    if (level) cfg |= S3C_CIGCTRL_IRQ_LEVEL;

    writel(cfg, ctrl->regs + S3C_CIGCTRL);

    return 0; 

    }


    3. Sensor 驱动

    1)简介, 

    )简介 本方案中使用了两个摄像头模组: MT9P111 和 S5K6AAFX。 其中 MT9P111 是 APTINA 公司推出的 1/4 英寸光学格式 5M 单芯片传感器,用作后摄像头;S5K6AAFX 是三星出的 1.3M CMOS 高清图像传感器,用作前摄像头。 

    2)参数设置 

    )参数设置 MT9P111 的参数设置

    #ifdef MT9P111_ENABLED 

    static struct mt9p111_platform_data mt9p111_plat = { 

    .default_width = 1024, 

    .default_height = 600, 

    .pixelformat = V4L2_PIX_FMT_UYVY, 

    .freq = 24000000, 

    .is_mipi = 0, 

    }; 


    static struct i2c_board_info mt9p111_i2c_info = { 

    I2C_BOARD_INFO("MT9P111", 0x3D),//0x7a,0x7b .

    platform_data = &mt9p111_plat, 

    }; 


    static struct s3c_platform_camera mt9p111 = { 

    .id = CAMERA_PAR_A,

    .type= CAM_TYPE_ITU,

    .fmt =  = ITU_601_YCBCR422_8BIT,


    .order422 = CAM_ORDER422_8BIT_CBYCRY, 

    .i2c_busnum 

    .info = 7,


    = &mt9p111_i2c_info, = V4L2_PIX_FMT_UYVY, = "xusbxti",

    .pixelformat .srclk_name

    .clk_name = "sclk_cam0",

    .clk_rate = 24000000,

    .line_length 

    .width 

    .height

    .window 

    .left = 0, 

    .top = 0, 

    .width 

    .height 

    }, = 1024, = 600, = 1920, = 1024, = 600, ={


    /* Polarity */ .inv_pclk = 0, .inv_vsync .inv_href = 0, .inv_hsync = 0, = 0,

    .initialized = 0, .cam_power }; #endif = smdkv210_cam0_power,

    S5K6AAFX 的参数设置

    #ifdef S5K6AAFX_ENABLED 

    static struct s5k6aafx_platform_data s5k6aafx_plat = { 

    .default_width = 800, 

    .default_height = 600,

     .pixelformat = V4L2_PIX_FMT_YUYV, 

    .freq = 24000000,


    .is_mipi = 0, 

    }; 

    static struct i2c_board_info s5k6aafx_i2c_info = {


    I2C_BOARD_INFO("s5k6aafx", 0x3c), 

    .platform_data = &s5k6aafx_plat,

     }; 


    static struct s3c_platform_camera s5k6aafx = { 

    .id 

    .type 

    .fmt = CAMERA_PAR_B, = CAM_TYPE_ITU, = ITU_601_YCBCR422_8BIT,


    .order422 = CAM_ORDER422_8BIT_YCBYCR, .i2c_busnum .info = 4,

    = &s5k6aafx_i2c_info, = V4L2_PIX_FMT_YUYV, = "xusbxti",

    .pixelformat .srclk_name

    .clk_name = "sclk_cam1", .clk_rate = 24000000, .line_length = 1280,

    /* default resol for preview kind of thing */ 

    .width .height 

    .window .left = 0, 

    .top = 0, .width 

    .height }, /* Polarity */

     .inv_pclk = 0, 

    .inv_vsync = 0, = 800, = 600, = 800, = 600, ={


    .inv_href = 0, 

    .inv_hsync = 0,


    .initialized = 0, 

    .cam_power }; 

    #endif = smdkv210_cam1_power,


    3)数据结构 )

    (未注释)

    struct v4l2_subdev { 

    struct list_head list; 

    struct module *owner; 

    u32 flags; 

    struct v4l2_device *v4l2_dev; 

    const struct v4l2_subdev_ops *ops; /* name must be unique */ 

    char name[V4L2_SUBDEV_NAME_SIZE]; /* can be used to group similar subdevs, value is driver-specific */ 

    u32 grp_id; /* pointer to private data */ 

    void *priv;

     }; 

    #endif


    4)接口函数 )

    (未注释)

    static const struct v4l2_subdev_core_ops mt9p111_core_ops = { 

    .init = mt9p111_init, /* initializing API */


    .s_config = mt9p111_s_config, /* Fetch platform data */ 

    .queryctrl = mt9p111_queryctrl, 

    .querymenu = mt9p111_querymenu,

     .g_ctrl = mt9p111_g_ctrl, 

    .s_ctrl = mt9p111_s_ctrl,

     };


    static const struct v4l2_subdev_video_ops mt9p111_video_ops = { 

    // .s_crystal_freq = mt9p111_s_crystal_freq, 

    .g_fmt = mt9p111_g_fmt, 

    .s_fmt = mt9p111_s_fmt,

     .enum_framesizes = mt9p111_enum_framesizes, // //

     .enum_frameintervals = mt9p111_enum_frameintervals, 

    .enum_fmt = mt9p111_enum_fmt, 

    .try_fmt = mt9p111_try_fmt, 

    .g_parm = mt9p111_g_parm, 

    .s_parm = mt9p111_s_parm, 

    .s_stream = mt9p111_s_stream, };


    static const struct v4l2_subdev_ops mt9p111_ops = { 

    .core = &mt9p111_core_ops, 

    .video = &mt9p111_video_ops, 

    };

     #endif

    展开全文
  • Android8.0 Camera系统架构(一)

    万次阅读 2018-12-24 13:37:07
    随着Android系统的不断升级,相机子系统框架也在不断进化,由最初的API1...Android 的相机硬件抽象层 (HAL) 可将 Camera 2 中较高级别的相机框架 API 连接到底层的相机驱动程序和硬件。相机子系统包括相机管道组件的...

    随着Android系统的不断升级,相机子系统框架也在不断进化,由最初的API1和HAL1到现在的API2和HAL3,由最初简单的拍照,录制到现在的连拍,AI人像;可以说是架构上变动最大最频繁的子系统。很多设备仍然依赖相机 HAL1,因此 Android 7.0 继续支持该模块。此外,Android 相机服务还支持同时实现两种 HAL(1 和 3),如果您希望通过相机 HAL1 支持性能略低的前置摄像头,并通过相机 HAL3 支持更为高级的后置摄像头。Android 的相机硬件抽象层 (HAL) 可将 Camera 2 中较高级别的相机框架 API 连接到底层的相机驱动程序和硬件。相机子系统包括相机管道组件的实现,而相机 HAL 则可提供用于实现您的这些组件版本的接口。从 Android 8.0 开始,相机 HAL 接口是 Project Treble 的一部分,相应的 HIDL 接口在硬件/接口/相机中定义。该实现会封装仍在使用旧版 API 的旧 HAL。从 Android 8.0 开始,相机 HAL 实现必须使用 HIDL API;不支持使用旧版接口。Android8.0下最新的相机架构具有更高的灵活性。架构如下:

    这里写图片描述

    重新设计 Android Camera API 的目的在于大幅提高应用对于 Android 设备上的相机子系统的控制能力,同时重新组织 API,提高其效率和可维护性。借助额外的控制能力,您可以更轻松地在 Android 设备上构建高品质的相机应用,这些应用可在多种产品上稳定运行,同时仍会尽可能使用设备专用算法来最大限度地提升质量和性能。版本 3 相机子系统将多个运行模式整合为一个统一的视图,您可以使用这种视图实现之前的任何模式以及一些其他模式,例如连拍模式。这样一来,便可以提高用户对聚焦、曝光以及更多后期处理(例如降噪、对比度和锐化)效果的控制能力。此外,这种简化的视图还能够使应用开发者更轻松地使用相机的各种功能。架构图已经很清晰的描述了各层架构之间的关系,我们按图索骥从最新的架构开始,再看完整的架构,最后我们回到应用层来看Camera子系统的设计。

    1. CameraService

    CameraManager与CameraService通过Binder机制,形成推拉回调

    frameworks\base\core\java\android\hardware\camera2\CameraManager.java
    frameworks\av\camera\aidl\android\hardware\ICameraService.aidl
    frameworks\av\camera\aidl\android\hardware\ICameraServiceListener.aidl

    private static final class CameraManagerGlobal extends ICameraServiceListener.Stub {
             ......
    		 public ICameraService getCameraService() {
                synchronized(mLock) {
                    connectCameraServiceLocked(); //连接服务
                    if (mCameraService == null) {
                        Log.e(TAG, "Camera service is unavailable");
                    }
                    return mCameraService;
                }
            }
            ......
    }
    

    CameraManager通过CameraManagerGlobal访问CameraService服务,并注册监听,CamreaService持有CameraServiceListener列表,并回调结果给CameraManager

    private void connectCameraServiceLocked() {
            //查询服务引用
            IBinder cameraServiceBinder = ServiceManager.getService(CAMERA_SERVICE_BINDER_NAME);
            //转换服务接口
            ICameraService cameraService = ICameraService.Stub.asInterface(cameraServiceBinder);
            try {
               CameraStatus[] cameraStatuses = cameraService.addListener(this); //注册回调监听
               //存副本
               mCameraService = cameraService;
           }
    }
    

    frameworks\av\services\camera\libcameraservice\CameraService.h

    class CameraService :
        public BinderService<CameraService>,
        public virtual ::android::hardware::BnCameraService, //Bn端(服务端)
        public virtual IBinder::DeathRecipient {.....}
    

    注册CameraService回调监听

    Status CameraService::addListener(const sp<ICameraServiceListener>& listener,
            std::vector<hardware::CameraStatus> *cameraStatuses) {
        {
            Mutex::Autolock lock(mStatusListenerLock);
            for (auto& it : mListenerList) {
                if (IInterface::asBinder(it) == IInterface::asBinder(listener)) {
                    return STATUS_ERROR(ERROR_ALREADY_EXISTS, "Listener already registered");
                }
            }
            mListenerList.push_back(listener); //注册
        }
    
        return Status::ok();
    }
    

    CameraService初始化

    void CameraService::onFirstRef()
    {
        BnCameraService::onFirstRef();
        res = enumerateProviders(); //枚举Provider
        CameraService::pingCameraServiceProxy();
    }
    

    调用CameraProviderManager枚举设备

    status_t CameraService::enumerateProviders() {
       
        if (nullptr == mCameraProviderManager.get()) {
            mCameraProviderManager = new CameraProviderManager();
            res = mCameraProviderManager->initialize(this); //初始化
        }
    
        mNumberOfCameras = mCameraProviderManager->getCameraCount(); //相机数目
        mNumberOfNormalCameras =
                mCameraProviderManager->getAPI1CompatibleCameraCount(); //可用API
                
        mCameraProviderManager->setUpVendorTags(); //第三方厂商Tag
    
        if (nullptr == mFlashlight.get()) {
            mFlashlight = new CameraFlashlight(mCameraProviderManager, this); //闪光灯
        }
        res = mFlashlight->findFlashUnits();
        return OK;
    }
    

    2. CameraProviderManager

    frameworks\av\services\camera\libcameraservice\common\CameraProviderManager.cpp

    status_t CameraProviderManager::initialize(wp<CameraProviderManager::StatusListener> listener,
            ServiceInteractionProxy* proxy) {
        std::lock_guard<std::mutex> lock(mInterfaceMutex);
        mListener = listener;
        mServiceProxy = proxy;
    
        // Registering will trigger notifications for all already-known providers
        bool success = mServiceProxy->registerForNotifications( //注册代理通知
            /* instance name, empty means no filter */ "",
            this);
            return INVALID_OPERATION;
        }
    
        //添加提供者
        addProviderLocked(kLegacyProviderName, /*expected*/ false);
        return OK;
    }
    

    查找初始化并保存Provider; mServiceProxy是ServiceInteractionProxy*;

    status_t CameraProviderManager::addProviderLocked(const std::string& newProvider, bool expected) {
       
        sp<provider::V2_4::ICameraProvider> interface;
        interface = mServiceProxy->getService(newProvider); //获取服务
    
        sp<ProviderInfo> providerInfo =
                new ProviderInfo(newProvider, interface, this);
        status_t res = providerInfo->initialize(); //执行初始化
    
        mProviders.push_back(providerInfo); //备份
    
        return OK;
    }
    

    frameworks\av\services\camera\libcameraservice\common\CameraProviderManager.h

    struct ServiceInteractionProxy {
            virtual bool registerForNotifications(
                    const std::string &serviceName,
                    const sp<hidl::manager::V1_0::IServiceNotification>
                    &notification) = 0;
            virtual sp<hardware::camera::provider::V2_4::ICameraProvider> getService(
                    const std::string &serviceName) = 0;
            virtual ~ServiceInteractionProxy() {}
        };
    
        // Standard use case - call into the normal generated static methods which invoke
        // the real hardware service manager
        struct HardwareServiceInteractionProxy : public ServiceInteractionProxy {
            virtual bool registerForNotifications(
                    const std::string &serviceName,
                    const sp<hidl::manager::V1_0::IServiceNotification>
                    &notification) override {
                return hardware::camera::provider::V2_4::ICameraProvider::registerForNotifications(
                        serviceName, notification);
            }
            virtual sp<hardware::camera::provider::V2_4::ICameraProvider> getService(
                    const std::string &serviceName) override { //调用HAL
                return hardware::camera::provider::V2_4::ICameraProvider::getService(serviceName);
            }
        };
    

    3. Camera硬件抽象层

    hardware\interfaces\camera\provider\2.4\default\CameraProvider.h

    struct CameraProvider : public ICameraProvider, public camera_module_callbacks_t {......}
    

    执行初始化

    bool CameraProvider::initialize() {
        camera_module_t *rawModule;
        int err = hw_get_module(CAMERA_HARDWARE_MODULE_ID, //熟悉的配方,熟悉的操作
                (const hw_module_t **)&rawModule);
        mModule = new CameraModule(rawModule); //封装了一层
        err = mModule->init();
        // Setup callback now because we are going to try openLegacy next
        err = mModule->setCallbacks(this);
        mNumberOfLegacyCameras = mModule->getNumberOfCameras();
        for (int i = 0; i < mNumberOfLegacyCameras; i++) {
            struct camera_info info;
            auto rc = mModule->getCameraInfo(i, &info); //查相机信息
            char cameraId[kMaxCameraIdLen];
            snprintf(cameraId, sizeof(cameraId), "%d", i);
            std::string cameraIdStr(cameraId);
            mCameraStatusMap[cameraIdStr] = CAMERA_DEVICE_STATUS_PRESENT;
            mCameraIds.add(cameraIdStr);
            ......
        }
    
        return false; // mInitFailed
    }
    

    hardware\interfaces\camera\common\1.0\default\CameraModule.cpp

    CameraModule::CameraModule(camera_module_t *module) {
        mModule = module; //save this ref
    }
    

    做了一些版本相关处理

    int CameraModule::init() {
        ATRACE_CALL();
        int res = OK;
        if (getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_4 &&
                mModule->init != NULL) {
            ATRACE_BEGIN("camera_module->init");
            res = mModule->init(); //初始化
            ATRACE_END();
        }
        mCameraInfoMap.setCapacity(getNumberOfCameras());
        return res;
    }
    

    hardware\libhardware\include\hardware\camera_common.h
    最终通过HAL与相机设备驱动交互

    {
        ......
         */
        int (*init)();
    
        /* reserved for future use */
        void* reserved[5];
    } camera_module_t;
    

    让我们往回倒一下车,providerInfo->initialize();

    status_t CameraProviderManager::ProviderInfo::initialize() {
        status_t res = parseProviderName(mProviderName, &mType, &mId);
        hardware::Return<Status> status = mInterface->setCallback(this);
        hardware::Return<bool> linked = mInterface->linkToDeath(this, /*cookie*/ mId);
        //初始化相机设备
        // Get initial list of camera devices, if any
        std::vector<std::string> devices;
        hardware::Return<void> ret = mInterface->getCameraIdList([&status, &devices]( //获取device
                Status idStatus,
                const hardware::hidl_vec<hardware::hidl_string>& cameraDeviceNames) {
            status = idStatus;
    
        sp<StatusListener> listener = mManager->getStatusListener();
        for (auto& device : devices) {
            std::string id;
            status_t res = addDevice(device, //天加device
                    hardware::camera::common::V1_0::CameraDeviceStatus::PRESENT, &id);
        }
    
        for (auto& device : mDevices) {
            mUniqueCameraIds.insert(device->mId);
            if (device->isAPI1Compatible()) {
                mUniqueAPI1CompatibleCameraIds.insert(device->mId);
            }
        }
        mUniqueDeviceCount = mUniqueCameraIds.size();
        return OK;
    }
    
    status_t CameraProviderManager::ProviderInfo::addDevice(const std::string& name,
            CameraDeviceStatus initialStatus, /*out*/ std::string* parsedId) {
            
        uint16_t major, minor;
        std::string type, id;
    
        status_t res = parseDeviceName(name, &major, &minor, &type, &id); //解析设备名
        
        if (mManager->isValidDeviceLocked(id, major)) { //验证
            return BAD_VALUE;
        }
    
        std::unique_ptr<DeviceInfo> deviceInfo;
        switch (major) {
            case 1:
                deviceInfo = initializeDeviceInfo<DeviceInfo1>(name, mProviderTagid, //Device1
                        id, minor);
                break;
            case 3:
                deviceInfo = initializeDeviceInfo<DeviceInfo3>(name, mProviderTagid, //Device3
                        id, minor);
                break;
            default:
                return BAD_VALUE;
        }
        if (deviceInfo == nullptr) return BAD_VALUE;
        deviceInfo->mStatus = initialStatus; //回调设置
    
        mDevices.push_back(std::move(deviceInfo)); //存储引用
    
        if (parsedId != nullptr) {
            *parsedId = id;
        }
        return OK;
    }
    
    

    初始化设备信息

    template<class DeviceInfoT>
    std::unique_ptr<CameraProviderManager::ProviderInfo::DeviceInfo>
        CameraProviderManager::ProviderInfo::initializeDeviceInfo(
            const std::string &name, const metadata_vendor_id_t tagId,
            const std::string &id, uint16_t minorVersion) const {
        Status status;
    
        auto cameraInterface =
                getDeviceInterface<typename DeviceInfoT::InterfaceT>(name); //获取HAL设备远程接口
        if (cameraInterface == nullptr) return nullptr;
        return std::unique_ptr<DeviceInfo>( //返回设备信息
            new DeviceInfoT(name, tagId, id, minorVersion, resourceCost,
                    cameraInterface));
    }
    
    

    通过ICameraDevice关联硬件抽象层

    template<>
    sp<device::V1_0::ICameraDevice>
    CameraProviderManager::ProviderInfo::getDeviceInterface
            <device::V1_0::ICameraDevice>(const std::string &name) const {
        Status status;
        sp<device::V1_0::ICameraDevice> cameraInterface;
        hardware::Return<void> ret;
        ret = mInterface->getCameraDeviceInterface_V1_x(name, [&status, &cameraInterface](
            Status s, sp<device::V1_0::ICameraDevice> interface) {
                    status = s;
                    cameraInterface = interface;
                });
        return cameraInterface;
    }
    

    硬件抽象层调用接口(Treble架构)

    struct CameraDevice : public ICameraDevice {......}
    

    4. CameraDeviceClient与CameraDevice

    新的架构图中右边的分支已经跟踪完毕,我们回过头来看左边的分支
    frameworks/base/core/java/android/hardware/camera2/CameraManager.java

    private CameraDevice openCameraDeviceUserAsync(String cameraId,
                CameraDevice.StateCallback callback, Handler handler, final int uid)
                throws CameraAccessException {
            CameraCharacteristics characteristics = getCameraCharacteristics(cameraId);
            CameraDevice device = null;
    
            synchronized (mLock) {
    
                ICameraDeviceUser cameraUser = null;
                //CameraDeviceImpl 为 CameraDevice抽象类的自类
                android.hardware.camera2.impl.CameraDeviceImpl deviceImpl =
                        new android.hardware.camera2.impl.CameraDeviceImpl(
                            cameraId,
                            callback,
                            handler,
                            characteristics,
                            mContext.getApplicationInfo().targetSdkVersion);
    
                ICameraDeviceCallbacks callbacks = deviceImpl.getCallbacks();
    
                try {
                    if (supportsCamera2ApiLocked(cameraId)) {
                        // Use cameraservice's cameradeviceclient implementation for HAL3.2+ devices
                        ICameraService cameraService = CameraManagerGlobal.get().getCameraService();
                        //连接相机Device
                        cameraUser = cameraService.connectDevice(callbacks, cameraId,
                                mContext.getOpPackageName(), uid);
                    } else {
                        // Use legacy camera implementation for HAL1 devices
                        //使用旧版HAL1
                        cameraUser = CameraDeviceUserShim.connectBinderShim(callbacks, id);
                    }
                } catch (ServiceSpecificException e) {
                   ......
                }
    
                // TODO: factor out callback to be non-nested, then move setter to constructor
                // For now, calling setRemoteDevice will fire initial
                // onOpened/onUnconfigured callbacks.
                // This function call may post onDisconnected and throw CAMERA_DISCONNECTED if
                // cameraUser dies during setup.
                deviceImpl.setRemoteDevice(cameraUser); //设置
                device = deviceImpl;
            }
    
            return device;
        }
    

    frameworks/av/services/camera/libcameraservice/CameraService.cpp

    Status CameraService::connectDevice(
            const sp<hardware::camera2::ICameraDeviceCallbacks>& cameraCb,
            const String16& cameraId,
            const String16& clientPackageName,
            int clientUid,
            /*out*/
            sp<hardware::camera2::ICameraDeviceUser>* device) {
    
        ATRACE_CALL();
        Status ret = Status::ok();
        String8 id = String8(cameraId);
        sp<CameraDeviceClient> client = nullptr;
        //调用模板函数
        ret = connectHelper<hardware::camera2::ICameraDeviceCallbacks,CameraDeviceClient>(cameraCb, id,
                CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageName,
                clientUid, USE_CALLING_PID, API_2,
                /*legacyMode*/ false, /*shimUpdateOnly*/ false,
                /*out*/client);
    
        if(!ret.isOk()) {
            logRejected(id, getCallingPid(), String8(clientPackageName),
                    ret.toString8());
            return ret;
        }
    
        *device = client; //返回设备
        return ret;
    }
    

    模板函数

    template<class CALLBACK, class CLIENT>
    Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
            int halVersion, const String16& clientPackageName, int clientUid, int clientPid,
            apiLevel effectiveApiLevel, bool legacyMode, bool shimUpdateOnly,
            /*out*/sp<CLIENT>& device) {
        binder::Status ret = binder::Status::ok();
    
        String8 clientName8(clientPackageName);
    
        int originalClientPid = 0;
        sp<CLIENT> client = nullptr;
        {
            ......
            // Enforce client permissions and do basic sanity checks
            if(!(ret = validateConnectLocked(cameraId, clientName8, //连接验证
                    /*inout*/clientUid, /*inout*/clientPid, /*out*/originalClientPid)).isOk()) {
                return ret;
            }
    
            // Check the shim parameters after acquiring lock, if they have already been updated and
            // we were doing a shim update, return immediately
            if (shimUpdateOnly) {
                auto cameraState = getCameraState(cameraId);
                if (cameraState != nullptr) {
                    if (!cameraState->getShimParams().isEmpty()) return ret;
                }
            }
            
            ......
    
            sp<BasicClient> tmp = nullptr;
            if(!(ret = makeClient(this, cameraCb, clientPackageName, cameraId, facing, clientPid,
                    clientUid, getpid(), legacyMode, halVersion, deviceVersion, effectiveApiLevel,
                    /*out*/&tmp)).isOk()) {
                return ret;
            }
            client = static_cast<CLIENT*>(tmp.get());
            //初始化
            err = client->initialize(mCameraProviderManager);
    
            // Update shim paremeters for legacy clients
            if (effectiveApiLevel == API_1) { //系统旧版本API1
                // Assume we have always received a Client subclass for API1
                sp<Client> shimClient = reinterpret_cast<Client*>(client.get());
                String8 rawParams = shimClient->getParameters();
                CameraParameters params(rawParams);
    
                auto cameraState = getCameraState(cameraId);
                if (cameraState != nullptr) {
                    cameraState->setShimParams(params);
                }
            }
        } // lock is destroyed, allow further connect calls
        device = client;
        return ret;
    }
    

    创建不同HAL版本对应的相机Client

    Status CameraService::makeClient(const sp<CameraService>& cameraService,
            const sp<IInterface>& cameraCb, const String16& packageName, const String8& cameraId,
            int facing, int clientPid, uid_t clientUid, int servicePid, bool legacyMode,
            int halVersion, int deviceVersion, apiLevel effectiveApiLevel,
            /*out*/sp<BasicClient>* client) {
    
        if (halVersion < 0 || halVersion == deviceVersion) {
            // Default path: HAL version is unspecified by caller, create CameraClient
            // based on device version reported by the HAL.
            switch(deviceVersion) {
              //HAL1的架构
              case CAMERA_DEVICE_API_VERSION_1_0:
                if (effectiveApiLevel == API_1) {  // Camera1 API route
                    sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
                    *client = new CameraClient(cameraService, tmp, packageName, cameraIdToInt(cameraId),
                            facing, clientPid, clientUid, getpid(), legacyMode);
                } else { // Camera2 API route
                    ALOGW("Camera using old HAL version: %d", deviceVersion);
                    return STATUS_ERROR_FMT(ERROR_DEPRECATED_HAL,
                            "Camera device \"%s\" HAL version %d does not support camera2 API",
                            cameraId.string(), deviceVersion);
                }
                break;
              //HAL3的架构
              case CAMERA_DEVICE_API_VERSION_3_0:
              case CAMERA_DEVICE_API_VERSION_3_1:
              case CAMERA_DEVICE_API_VERSION_3_2:
              case CAMERA_DEVICE_API_VERSION_3_3:
              case CAMERA_DEVICE_API_VERSION_3_4:
                if (effectiveApiLevel == API_1) { // Camera1 API route
                    sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
                    *client = new Camera2Client(cameraService, tmp, packageName, cameraIdToInt(cameraId),
                            facing, clientPid, clientUid, servicePid, legacyMode);
                } else { // Camera2 API route
                    sp<hardware::camera2::ICameraDeviceCallbacks> tmp =
                            static_cast<hardware::camera2::ICameraDeviceCallbacks*>(cameraCb.get());
                    *client = new CameraDeviceClient(cameraService, tmp, packageName, cameraId,
                            facing, clientPid, clientUid, servicePid);
                }
                break;
              default:
                // Should not be reachable
                ALOGE("Unknown camera device HAL version: %d", deviceVersion);
                return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
                        "Camera device \"%s\" has unknown HAL version %d",
                        cameraId.string(), deviceVersion);
            }
        } else {
            // A particular HAL version is requested by caller. Create CameraClient
            // based on the requested HAL version.
            if (deviceVersion > CAMERA_DEVICE_API_VERSION_1_0 &&
                halVersion == CAMERA_DEVICE_API_VERSION_1_0) {
                // Only support higher HAL version device opened as HAL1.0 device.
                sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
                *client = new CameraClient(cameraService, tmp, packageName, cameraIdToInt(cameraId),
                        facing, clientPid, clientUid, servicePid, legacyMode);
            } else {
                // Other combinations (e.g. HAL3.x open as HAL2.x) are not supported yet.
                ALOGE("Invalid camera HAL version %x: HAL %x device can only be"
                        " opened as HAL %x device", halVersion, deviceVersion,
                        CAMERA_DEVICE_API_VERSION_1_0);
                return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT,
                        "Camera device \"%s\" (HAL version %d) cannot be opened as HAL version %d",
                        cameraId.string(), deviceVersion, halVersion);
            }
        }
        return Status::ok();
    }
    

    frameworks/av/services/camera/libcameraservice/api2/CameraDeviceClient.h

    struct CameraDeviceClientBase :
             public CameraService::BasicClient,
             public hardware::camera2::BnCameraDeviceUser //CameraDeviceUser的服务端
    {
        typedef hardware::camera2::ICameraDeviceCallbacks TCamCallbacks; //该回调在CameraDeviceImpl
    
        const sp<hardware::camera2::ICameraDeviceCallbacks>& getRemoteCallback() {
            return mRemoteCallback;
        }
        ......
    };
    

    HAL3对应的CameraDeviceClient

    class CameraDeviceClient :
            public Camera2ClientBase<CameraDeviceClientBase>,
            public camera2::FrameProcessorBase::FilteredListener
    {......}
    

    如此以来CameraDeviceClient就继承了CameraDeviceClientBase,间接继承了BnCameraDeviceUser

    template <typename TClientBase>
    class Camera2ClientBase :
            public TClientBase,
            public CameraDeviceBase::NotificationListener
    {
    

    持有远程mRemoteDevice的Binder对象

        public void setRemoteDevice(ICameraDeviceUser remoteDevice) throws CameraAccessException {
            synchronized(mInterfaceLock) {
                mRemoteDevice = new ICameraDeviceUserWrapper(remoteDevice); //包装
    
                IBinder remoteDeviceBinder = remoteDevice.asBinder();//远程Binder服务,HAL3架构下是CameraDeviceClient
                ......
    
                mDeviceHandler.post(mCallOnOpened);
                mDeviceHandler.post(mCallOnUnconfigured);
            }
        }
    

    通过此远程回调将CamreaDevice与CameraDeviceClient联系起来,处理来自CameraDeviceClient的消息

    public class CameraDeviceCallbacks extends ICameraDeviceCallbacks.Stub {......}
    

    5. CameraDeviceClient与Camera3Device

    回到刚才的err = client->initialize(mCameraProviderManager);

    status_t CameraDeviceClient::initialize(sp<CameraProviderManager> manager) {
        return initializeImpl(manager);
    }
    
    template<typename TProviderPtr>
    status_t CameraDeviceClient::initializeImpl(TProviderPtr providerPtr) {
        ATRACE_CALL();
        status_t res;
    
        res = Camera2ClientBase::initialize(providerPtr); //调用初始化
        if (res != OK) {
            return res;
        }
        ......
        return OK;
    }
    

    frameworks/av/services/camera/libcameraservice/common/Camera2ClientBase.cpp

    template <typename TClientBase>
    status_t Camera2ClientBase<TClientBase>::initialize(sp<CameraProviderManager> manager) {
        return initializeImpl(manager);
    }
    
    template <typename TClientBase>
    template <typename TProviderPtr>
    status_t Camera2ClientBase<TClientBase>::initializeImpl(TProviderPtr providerPtr) {
        ATRACE_CALL();
        ALOGV("%s: Initializing client for camera %s", __FUNCTION__,
              TClientBase::mCameraIdStr.string());
        status_t res;
    
        // Verify ops permissions
        res = TClientBase::startCameraOps();
        if (res != OK) {
            return res;
        }
    
        if (mDevice == NULL) {
            ALOGE("%s: Camera %s: No device connected",
                    __FUNCTION__, TClientBase::mCameraIdStr.string());
            return NO_INIT;
        }
    
        res = mDevice->initialize(providerPtr); //调用具体的设备初始化
        if (res != OK) {
            ALOGE("%s: Camera %s: unable to initialize device: %s (%d)",
                    __FUNCTION__, TClientBase::mCameraIdStr.string(), strerror(-res), res);
            return res;
        }
    
        wp<CameraDeviceBase::NotificationListener> weakThis(this);
        res = mDevice->setNotifyCallback(weakThis);
    
        return OK;
    }
    

    frameworks/av/services/camera/libcameraservice/common/Camera2ClientBase.h

     sp<CameraDeviceBase>  mDevice;
    

    rameworks/av/services/camera/libcameraservice/device3/Camera3Device.h

    class Camera3Device :
                public CameraDeviceBase, //继承了CameraDeviceBase
                virtual public hardware::camera::device::V3_2::ICameraDeviceCallback,
                private camera3_callback_ops {
    

    frameworks/av/services/camera/libcameraservice/device3/Camera3Device.cpp

    status_t Camera3Device::initialize(sp<CameraProviderManager> manager) {
        ......
        sp<ICameraDeviceSession> session;
        ATRACE_BEGIN("CameraHal::openSession");
        status_t res = manager->openSession(mId.string(), this, //通过session获取Device
                /*out*/ &session);
        res = manager->getCameraCharacteristics(mId.string(), &mDeviceInfo); //通过相机参数获取Device
        std::shared_ptr<RequestMetadataQueue> queue;
        auto requestQueueRet = session->getCaptureRequestMetadataQueue(//元数据捕获请求队列
            [&queue](const auto& descriptor) {
                queue = std::make_shared<RequestMetadataQueue>(descriptor);
                if (!queue->isValid() || queue->availableToWrite() <= 0) {
                    ALOGE("HAL returns empty request metadata fmq, not use it");
                    queue = nullptr;
                    // don't use the queue onwards.
                }
            });
    
        std::unique_ptr<ResultMetadataQueue>& resQueue = mResultMetadataQueue;
        auto resultQueueRet = session->getCaptureResultMetadataQueue(//元数据捕获结果队列
            [&resQueue](const auto& descriptor) {
                resQueue = std::make_unique<ResultMetadataQueue>(descriptor);
                if (!resQueue->isValid() || resQueue->availableToWrite() <= 0) {
                    ALOGE("HAL returns empty result metadata fmq, not use it");
                    resQueue = nullptr;
                    // Don't use the resQueue onwards.
                }
            });
        IF_ALOGV() {
            session->interfaceChain([](
                ::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) {
                    ALOGV("Session interface chain:");
                    for (auto iface : interfaceChain) {
                        ALOGV("  %s", iface.c_str());
                    }
                });
        }
    
        mInterface = new HalInterface(session, queue); //新建硬件抽象层接口实例
        std::string providerType;
        mVendorTagId = manager->getProviderTagIdLocked(mId.string());
    
        return initializeCommonLocked();
    }
    

    至此新Camera架构整个蓝图构建完成,我们只是按图索骥从Java层一直到HAL层,事实上Camera大部分重要的东西都在其驱动算法层,我们暂且不去深究。下一篇我们将从整个新旧架构的角度去分析Camera系统。

    展开全文
  • Camera tuning 基础知识点

    千次阅读 2018-03-09 15:15:40
    相关知识点总结:一、模组及工艺相关知识 ①模组的组成 1)模组的基本组成。(AF&amp;FF) 2)镜头----镜头的发展历史,镜头相关参数解析,镜头的选型依据,优劣判断。(MTF,DOF,Focus,AF,P&...
    相关知识点总结:
    一、模组及工艺相关知识
         ①模组的组成
              1)模组的基本组成。(AF&FF)
              2)镜头----镜头的发展历史,镜头相关参数解析,镜头的选型依据,优劣判断。(MTF,DOF,Focus,AF,P&G....)
              3)sensor----sensor的发展历史,技术演进,sensor本身特性参数解析,主流sensor厂工艺技术解析,分析各大sensor厂之间的差异,优缺点,同时能从某几颗sensor来分析。(了解带有PD的sensor)
                        1’sensor硬件电路设计部分要了解。
                        2’驱动相关部分,MIPI时序,sensor hts,vts,pclk,等的配置要了解。
              4)AF driver 了解,如何控制driver ic,如何设置dumping,ring时间等。
              5)了解模组硬件layout,走线,电子元器件,连机器等设计缺陷对于图像质量的影响。
         ②模组的组装工艺,优劣。了解模组设计上的其他工艺,OIS等。
         ③了解模组厂是如何测试最终的模组是否满足需要,测试方法,测试标准。
         ④学习模组厂对于模组差异性的控制,golden,limit,normal选择依据,otp写入参数等。
         ⑤综合考虑模组选型参考依据,以及模组最终确定选型之后,所能成像的影响质量和其他模组的对比。
    二、图像及色彩处理基本理论和算法
         ①色彩的基本理论。
         ②ISP流程分析。
         ③3A的基本算法原理。

         ④ISP各模块分模块讲解算法模型等。(CCM,去噪,锐化等)。

    三、图像质量评价方法,主客观测试方法
         ①客观测试方法
              基本测试标准,及测试方法,(imatest,DXO等主流厂商的测试方法)
         ②主观测试方法
              主观测试场景,以及对于测试场景的分析方法。
         ③综合从哪些参数评价图像质量。了解客户的关注点。

    以上为自己简单总结的知识点,欢迎大神吐槽。

    展开全文
  • Camera(一)

    2019-02-28 12:25:35
    一引言Camera做为android手机必备的一款硬件,不管是二维码识别,拍照都离不开Camera。那么我们怎么使用Camera呢?调用系统的相机自己定义一个相机二调用系统相机调用系统相机其本质是跨应用间调用,所以我们可以...
  • camera & DTU方案

    2019-09-03 16:47:07
    Camera & DTU是我司基于华为芯片技术以及互联网技术打造的一个视频与数据透传两大功能相结合的实现方案,致力于客户通过简单的二次开发,从而实现传统产品迭代为智能化产品的目标。 Camera&DTU方案简称为...
  • Android Camera2 API和拍照与录像过程

    万次阅读 多人点赞 2018-07-13 18:20:25
    Android 5.0开始出现了新的相机Camera 2 API,用来替代以前的camera api。 Camera2 API不仅提高了android系统的拍照性能,还支持RAW照片输出,还可以设置相机的对焦模式,曝光模式,快门等等。 Camera2 中主要...
  • Android Camera基本用法一

    万次阅读 2019-01-30 10:42:05
    1 Camera 简介 讲解编解码之前先对Camera进行简单的介绍,本篇介绍完之后只能保证小白会用Camera预览画面,其他的Camera知识会后续讲解。 考虑兼容性依然介绍Camera,目录为android.hardware.Camera,可以看到从...
  • camera基本原理

    2019-06-13 16:46:43
    http://blog.csdn.net/xubin341719/article/details/7723725 http://blog.csdn.net/pengwentao/article/details/7180115 http://blog.csdn.net/southcamel/article/details/8305873 ...
  • AndroidUSBCamera基于[saki4510t/UVCCamera](https://github.com/saki4510t/UVCCamera)开发,该项目对USB Camera(UVC设备)的使用和视频数据采集进行了高度封装,能够帮助开发者通过几个简单的API实现USB Camera设备...
  • Android Camera开发之基础知识篇

    万次阅读 多人点赞 2017-05-31 09:38:44
    概述Android框架支持设备的相机拍照和录像功能,你的应用可以直接调用系统的Camera应用来拍照或者录像(比如微信拍照),当然也可以利用Android系统提供的API开发一个Camera应用来实现相机拍照和录像功能(比如市面...
  • android.hardware.camera2详解

    万次阅读 热门讨论 2020-06-11 21:35:35
    看到有些读者对博客提出的疑问,在此真诚说一句实在抱歉,本人是一名在校非科班出身大学生... 前言:原有的android.hardware.camera已经被google废除,改用功能更强大的camera2,camera2的复杂度远远超过camera,所以写
  • camera基础知识——1、camera模组简介

    千次阅读 2019-01-26 23:43:24
     博主作为一个camera驱动码农,在刚接触camera知识的时候难免有点转变不过来,难以接受,博主也深有体会。看着厚厚的camera datasheet,不知道如何下手编写驱动代码。但是在编写代码之前,必须还是先要理解camera的...
  • Android Camera的使用(一)

    千次阅读 2016-08-25 09:03:59
    在Api21中Camera类被废弃,取而代之的是camera2包。相对来说,camera2比Camera使用起来看似复杂了好多,但是在灵活性方面增加了很多。不过出于兼容性的考虑,加上当前Android设备5.0以下的占比还是比较大的,所以在...
  • Camera Link相机接口

    万次阅读 2018-03-05 20:47:36
    关于FPGA采集卡实现的简要技术说明1介绍Camera Link是工业相机中使用的标准接口。它由多个使用差分信号的串行链路组成。根据要传输的数据量,每台摄像机可以使用一条或两条电缆。自动影像协会是Camera Link标准的...
  • GLSurfaceView是OpenGL中的一个类,也是可以预览Camera的,而且za
  • android 自定义相机Camera

    千次阅读 2017-04-28 09:53:48
    Camera仍旧可以使用,Camera2使用起来感觉比Camera要复杂些,Camera2功能要强于Camera,也是goole提倡使用的。Camera已经基本可以满足需求了,今天我们就要看一下Camera的使用,下一篇我们会讲到Camera2的使用
  • CameraLink传输协议

    千次阅读 2019-07-17 10:41:09
    一、CameraLink协议是一种专门针对机器视觉应用领域的串行通信协议,它使用低压差分信号(LVDS)进行数据的传输和通信。CameraLink标准是在ChannelLink标准的基础上多加了6对差分信号线,其中4对用于并行传输相机控制...
  • 上篇在做相机桌面的时候用的是5.0之前的Camera,但Camera在5.0之后已经被淘汰了,官方也是推荐使用Camera2,这两天也分别尝试了下CameraCamera2的使用。 因为新的API换了加购,让开发者用起来更麻烦了。虽然按照...
  • UVCCamera安卓驱动USB摄像头

    万次阅读 热门讨论 2017-05-03 09:51:54
    最近在做一个USB摄像头...现在搜了一个叫UVCCamera的开源程序,开源了8个例程,每个例程功能各不相同。经过配置终于能出preview了,也能拍照、录像了。1.下载开源程序下载地址:https://github.com/saki4510t/UVCCamera
1 2 3 4 5 ... 20
收藏数 171,906
精华内容 68,762
关键字:

camera