福州瑞芯微电子有限公司时间讲师Camera常用知识及流程分析-----让凌鹏内容提要四、camerahal代码分析三、kernel相关代码分析二、上电识别camera流程一、基本概念五、3288和3188及以前的代码差异六、出错时log打印一、基本概念1.1常用camera分类SOCSensor:自带ISP,输出yuv数据,使用cif接口,因为cif接口不带isp,不对camera效果做处理。RAWSensor:不带isp,输出sensor采集原始灰度数据。目前发布的mid_sdk中仅3288支持这种sensor,这种就需要我们调试效果,使用mipi接口。1.3MIPI接口DOVDD,DVDD,AVDDPWDN,MIPI_RSTMCLK:24MHzMIPIData,CLK一、基本概念1.3CIF接口(socsensor,yuv)XCLK(MCLK),PCLKVSYNC一、基本概念二、上电识别camera流程启动mediaservice的时候,main_mediaserver.cpp中intmain(intargc,char**argv){AudioFlinger::instantiate();MediaPlayerService::instantiate();CameraService::instantiate();//cameraservice的启动AudioPolicyService::instantiate();二、上电识别camera流程();ProcessState::self()-startThreadPool();IPCThreadState::self()-joinThreadPool();}启动cameraservice的时候非常重要的一步:camera_get_number_of_cameras这是获取camera个数及camera相关参数的。#defineCAMERAS_SUPPORT_MAX2rk_cam_info_tgCamInfos[CAMERAS_SUPPORT_MAX];staticsignedintgCamerasNumber其实这个时候是获取camera参数到gCamInfos中,从这里也最多看到最多支持2个camera。注意:这里容易识别不到设备,后续摄像头打不开。三、kernel相关代码分析它需要和它的子设备进行通信,如果说camerahost是一个v4l2_device设备,那么就可以将camera模组称为一个v4l2_subdev设备,它们之间的通信可以采取多种方式常见的是I2C。camera的驱动文件比较简单,它和v4l2_device都是在kernel\drivers\media\video下面,以各型号命名,如ov5640.cgc0308.c里面代码较简单,是一些寄存器数组和简单寄存器逻辑判断组成(如af),数组包括初始化,预览分辨率,最大分辨率,还有如各种效果如曝光,白平衡等需要设置的寄存器组,以及设置他们的函数三、kernel相关代码分析如上所说,camerahost是一个v4l2_device设备,即我们的cif相关驱动,cif驱动较sub_dev复杂一点。在上面说的目录下面有rk30_camera_oneframe.crk30_camera_pingpong.c两个文件,目前默认的为前一种模式,即单帧模式,后一种为乒乓模式。那host驱动就涉及到裁剪,格式,制式,videobuf的初始化与设置。当全部设置好,会设置寄存器设置开始接收stream流,当buf接受满后会产生中断,进入rk_camera_irq函数,会将camera数据存入队列,并将vb-state=VIDEOBUF_DONE;四、camerahal代码分析的初始化当一打开摄像头的时候,从framework下来第一次执行的反函数是CameraHal::CameraHal(intcameraId),里面会创建很多进程,displayThreadCommandQ(displayCmdQ),displayThreadAckQ(displayAckQ),previewThreadCommandQ(previewCmdQ),previewThreadAckQ(previewAckQ),commandThreadCommandQ(commandCmdQ),commandThreadAckQ(commandAckQ),snapshotThreadCommandQ(snapshotCmdQ),snapshotThreadAckQ(snapshotAckQ),之后执行的两个比较重要的函数,intCameraHal::cameraCreate(intcameraId)四、camerahal代码分析前一个函数,通过获取底层支持的数据格式和上层匹配,设置格式,以及申请必要的内存(ion).后一个初始化camera各种参数,获取支持的预览和拍照分辨率,获取底层支持的各种效果的控件,以及当前效果的默认值。初始化完这些,调用函数mDisplayThread-run(CameraDispThread,ANDROID_PRIORITY_URGENT_DISPLAY);mPreviewThread-run(CameraPreviewThread,ANDROID_PRIORITY_DISPLAY);mCommandThread-run(CameraCmdThread,ANDROID_PRIORITY_URGENT_DISPLAY);mAutoFocusThread-run(CameraAutoFocusThread,ANDROID_PRIORITY_DISPLAY);mSnapshotThread-run(CameraSnapshotThread,ANDROID_PRIORITY_NORMAL);那么整个hal层的进程循环全部开始。四、camerahal代码分析()先是在preview进程中通过ioctl命令抓取buf数据if(ioctl(iCamFd,VIDIOC_DQBUF,&cfilledbuffer1)0)抓取的数据放到显示进程来显示在caseCMD_DISPLAY_FRAME:下面if(CAMERA_IS_RKSOC_CAMERA())(经常我们可以在此处抓下yuv数据分析)这个将传送过来的数据,转成指定的显示格式数去显示,然后发送CMD_PREVIEW_QBUF命令到commandThread进程去将buf将重新入队列尾,这样可以循环采集。hal层的一些命令•VIDIOC_REQBUFS:分配内存•VIDIOC_QUERYBUF:把VIDIOC_REQBUFS中分配的数据缓存转换成物理地址•VIDIOC_QUERYCAP:查询驱动功能四、camerahal代码分析•VIDIOC_ENUM_FMT:获取当前驱动支持的视频格式•VIDIOC_S_FMT:设置当前驱动的频捕获格式•VIDIOC_G_FMT:读取当前驱动的频捕获格式•VIDIOC_TRY_FMT:验证当前驱动的显示格式•VIDIOC_CROPCAP:查询驱动的修剪能力•VIDIOC_S_CROP:设置视频信号的边框•VIDIOC_G_CROP:读取视频信号的边框•VIDIOC_QBUF:把数据从缓存中读取出来•VIDIOC_DQBUF:把数据放回缓存队列•VIDIOC_STREAMON:开始视频显示函数•VIDIOC_STREAMOFF:结束视频显示函数•VIDIOC_QUERYSTD:检查当前视频设备支持的标准,例如PAL或NTSC。四、camerahal代码分析4.3拍照流程caseCMD_PREVIEW_CAPTURE:mPictureThread-runmPictureThread-runcapturePictureerr=hw_jpeg_encode(&JpegInInfo,&JpegOutInfo);copyAndSendRawImagecopyAndSendCompressedImage先是command进程接收拍照命令,在case下启动拍照进程,先申请拍照的buf,然后打开数据流,抓一帧数据存放,经过硬件编码成jpeg格式,通过copyAndSendCompressedImage返回给上层,当然在编码之前可以发送copyAndSendRawImage函数,直接发送原始数据。五、3288和3188及以前的代码差异做的。3288的驱动文件放在hardware\rk29\camera\SiliconImage\isi\drv,这里面只是简单camera芯片数组集合,以及一些函数结构体的赋值,部分操作代码放在库里面。3288比其他芯片多了isp(ImageSignalProcessing),当然对图像的处理代码也放在相应的isp库里面。camera定义的地方也有所不一样hardware\rk29\camera\Config\cam_board.xml具体的定义的说明可以看相关文档六、出错时log打印:可以输入setpropsys_graphic.cam_trace1打开更多调试信息4.2.3288以前log打印echo1/sys/module/rk30_camera_oneframe/parameters/debugQ&A福州瑞芯微电子有限公司时间讲师