高通5Mcamera在BMP10平台上总结.docx
《高通5Mcamera在BMP10平台上总结.docx》由会员分享,可在线阅读,更多相关《高通5Mcamera在BMP10平台上总结.docx(20页珍藏版)》请在冰豆网上搜索。
高通5Mcamera在BMP10平台上总结
高通BMP1.0平台调试5MCMOScamera总结
摘要:
本文着重解决BMP1.0平台上的RAWdata输出数据的500万camerasensor的调试。
包括驱动层,应用层代码和camera镜头的色彩校准。
我们按照调试的先后顺序进行步骤说明:
我们先说OEM层。
OEM层继承了ICAMERA的所有功能,ICAMERA只是一个壳,实现会转到OEMCAMERA。
AEE层介于两者之间,公开的代码只是让我们参考,修改无效。
在我们需要使用camera时候,调用CreateCamera,在CreateInstance获得句柄后,我们得到一个应用的壳,然后得到具体的与camera应用相关的函数注册。
然后通过OEMCamera_SetParm开始启动ACM相关资源,ACM简单的理解,就是图片和相关分支调用函数。
详情看OEMCamera_ACMTransaction()相关函数,这里不是重点,因此点到即止。
因为高通在双camera的资源应用上还没有完善,日后和应用在ACM上可能遇上问题,因此才在这里顺带说一下。
各位有兴趣可以和应用的多交流。
现在,我们可以从OEMCamera_New()开始,对驱动设计工程师而言,可以理解为camera代码应用的开始。
OEMCamera_New()中,camera_get_sensors所用到的变量,在代码启动的时候已经赋值,因此,并不是为空,这点需要注意,另外,这里还没有开始分配camera提供显示的内存空间,主要是对camera硬件相关进行初始化(想深入了解,看graph_task中的camera_init,这是在service层注册过的函数,再往下说,我怕会开始跑火车,就在这里点到即止,很多东西我们可以从代码中看到更多。
我这里提点一下就好)
经常,我们需要trace看sensorInfo里面的信息。
我们最关心的是sensor_width和sensor_height,这个是从底层获取的camera输出图像的尺寸。
从代码的设计上看,AEECLSID_CAMERA1固定的表示主摄像头,AEECLSID_CAMERA2表示从摄像头(现在手机一般都是双camera,因此单camera的流程就不说了)
现在我们非常关心sevice层的camera应用,在这里涵盖了camera绝大多数的基础代码(指公共服务的接口,)这个文件里的函数,需要认真研究。
首先,我们研究preview的部分:
camera_malloc_preview_buffers(),可以看到camera_preview_buffers.buffers[current_buffer].buf_ptr表示preview的buffer的指针,共5块,前3块是给VFE用的,后2块是显示overlay用的。
VFE处理video数据流,图像效果处理,raw数据解析(包括rolloff,gamma,ASF,AWB相关),YCBCR格式拍照解析
显示overlay用途,包括录像buffer的缓冲,屏幕显示的重载。
在rawdatabuffer中,会带上buffer头标志"QCAMRAW",只有带这个标志的rawbuffer,才是合法的,可以参看qcamrawIsHeader()这个函数判断,具体头里面有多少内容,看qcamrawSetHeader()这个函数,很直观的就能解析,这里就不在赘述。
想看preview关于buffer的指针定义,有一个函数camera_set_preview_buffers()很方便,这里面还包括recoding部分的buffer指针定义。
这里提供一个函数camera_calculate_output1_framerate(),可以看到如何用软件的方式看camerapreview的帧率,我用过,和实际用示波器查看的结果非常接近,考虑帧率的动态变化,实际用软件的方式比示波器更好。
如果我们想对camera的数据进行一些深入的修改,建议从两个函数入手去追溯:
camera_process_qdsp_output1_msg和camera_process_qdsp_output2_msg,这里面有很多图像处理。
Output1进行preview;output2进行snapshot。
Snapshot的thumbnail放在output1处理。
图像的旋转,camera_svcs_blt_ex(0这个函数是需要的,注意Y和CbCr是分开存放的。
若是还想向上追溯,可以参看camera_svcs_process_func(),这里是camera一些主要公共功能的消息派发点。
具体看函数内部就明白,我就不多说了。
constcamera_bestshot_config_typecamera_bestshot_table[]={#include"camera_bestshot_config.h"};这个是场景模式的入口,从camera_svcs_bestshot_get_config这里开始,将场景的索引赋值给cam3a_awb_state.bestshot_config,从这个关键词,我们能搜索到后面所有的功能。
关于ZOOM的相关流程,这里说明一下:
camera_svcs_set_dimensions()可以看到zoom的放大倍率的计算。
ui_picture_width=FLOOR16(camsensor_static_params[camera_asi].full_size_width-pad_pixels);
ui_picture_height=FLOOR16(camsensor_static_params[camera_asi].full_size_height-pad_lines);
如果是rawdata格式的数据:
pad_pixels=12;
pad_lines=8;
这是预留的边框,防止后面计算出错,然后我们看到处理了ui_picture_width和ui_picture_height后,其值一定是偶数。
resize_factor=(camsensor_static_params[camera_asi].full_size_height*Q12/max_crop_height(或者max_crop_width,哪个数小取哪个,这样保证放大能填充整个屏幕));这里计算能够放大的倍率因子
if(camera_min_decimationfound_min){camera_parm_zoom_table.minimum_value=(int32)i;found_min=TRUE;}if(resize_factor{camera_parm_zoom_table.maximum_value=(int32)i;break;}通过camera_min_decimation和camera_zoom_table[]的比较,确定最小的ZOOM起始位置,这个位置其实是zoom的最大值,一般我们得到的是0值,告诉VFE按照camera的原始尺寸处理图像。而camera_parm_zoom_table.maximum_value所表示的是zoom缩小的最大比例。从上边的解释,我们看到,ZOOM所能放大,缩小的比率,和我们camerasensor能输出的最大尺寸,UI能设定的最大尺寸,还有屏幕能表现的尺寸有关系,通过改变这些值,我们能够按照需要放大,缩小图像。通过上面的计算,我们得到camera_parm_zoom.minimum_value和camera_parm_zoom.maximum_value和camera_parm_zoom.step_value,这是我们最后能利用的zoom范围和每一步zoom的步长。接下来如何zoom,就不多说了,因为出错的可能性很小。以上属于部分camera的应用,后面在色彩校准部分还会介绍3a方面的应用。下面我们来讨论一下camerasensor驱动代码我们按照函数调用顺序进行说明:1.camsensor_xxx_init():顾名思义,其代表的功能定义就不用再说了,这里只需要解释一下里面的一个变量camsensor_preview_resolution,它可以赋值CAMSENSOR_QTR_SIZE和CAMSENSOR_FULL_SIZE,QTR是预览尺寸,FULL是拍照尺寸。我们在调试的时候,要是怀疑拍照相关参数问题,可以在预览流程中看拍照的图片进行debug。发布出来给客户的,就只需要QTR的设置。2.camsensor_xxx_start():这个函数太太太太太太重要了(我有点蛋疼了),这个函数是驱动的灵魂,因为可以说的问题太多,一时之间都不知道怎么说(这话说的有点招臭鸡蛋)。这样,望文生义的地方我就不说了,讲讲容易犯错的地方。camif_config相关配置,其实已经没有用了,但是我们还是保留其设置(谁知道以后会不会又需要用上)。camsensor_params->chromatix_parms=&camsensor_chromatix_xxx_struct;这是tuning图像的所有参数的集合文件头。Tuning后面我们会说.camsensor_params->raw_output_option=CAMSENSOR_8_BIT_DIRECT;虽然还有CAMSENSOR_10_BIT_DIRECT这个参数可以选择,但由于后端数据的存储都是按照8Bit来处理,因此这个参数没有什么太大的意义(这个最终解释权在我这里,以后高通会不会将其区别开来,这要用发展的眼光来看).在这个函数里,有判断camsensor_preview_resolution变量,这是为了调试全尺寸的需要而设置的,在正常流程中使用,我们只需要CAMSENSOR_QTR_SIZE这个分支,在实际的调试中,我发现,利用好CAMSENSOR_FULL_SIZE这个参数能方便解决拍照相关的很多问题。至于怎么利用,说起来头疼,简单的说,在第一点使用camsensor_preview_resolution=CAMSENSOR_FULL_SIZE即可,至于这样做会有什么问题,就要看驱动代码的健壮否了。这里无法做太多预测。preview_dx_decimation:这个是VFE处理bayer格式数据给显示屏用的,这个是太太太重要了(我真无聊)。有一个边界计算的问题(边界的意思,就是在数学计算的时候,我们要保证图像处理时候,作为分母的数据不能取为0,否则有严重的后果,嘿嘿,为什么会取为0呢?因为图片边界外面就是0了),其要求在尺寸上,宽度预留12pixel,高度预留8pixel(VFE实际只需要高度裁边6pixel,但是为了整齐,我们裁剪了5+3=8pixel),然后剩下的宽和高的尺寸各自还要能被4整除。有人说不这样做行吗?太麻烦啦,我说可以,但是准备后面的色彩调整时候,屏幕显示总偏色的代价。在6平台上特别是偏绿。接下来是AF参数设置,这个放到AF中再说。AF对焦,只取屏幕的1/4尺寸给VFE计算,可以减少计算量,提高对焦速度。camsensor_params->pixel_clock和pixel_clock_per_line这个参数是如此的重要,怎么说都是重点,这个重点中的重点,我只能用这种方式表达我对这个参数的尊重之情。它是用来计算flicker,也可以叫banding,一个意思。这参数属于tuning范畴,因此如何确定这些参数,归在后面tuning进行解释,这里先提点一下。pclk_invert:不同的厂家,pclk有效的极性可能不一样,因此我们需要判断,设TRUE表示上升沿有效,FALSE表示下降沿有效,如何判断呢?规格书中看看一目了然,下面这张就是上升沿有效的示意图camif_config.HsyncEdge和camif_config.VsyncEdge:有CAMIF_High和CAMIF_Low两种选择,表示行场同步信号的有效电平,高或低有效,只要用示波器看看camera的数据线输出是在行场低还是在高的时候有,就能直观的判断。当然,规格书中也会提及,下面这张就是行场高有效的典型示意图。3.camsensor_xxx_snapshot_config():这个是拍照时候调用的设置函数。简单说一下里面的一些参数好了:discardFirstFrame=TRUE,表示在将来需要切换到预览模式时,会将预览的第一帧数据抛弃,这么做是为了防止第一帧数据残缺造成切换时候显示错乱的现象。但是仅仅这么做还不够(从中可以看到,高通虽然想到这个问题,但是其仅仅停留在实验室阶段),这样做,仅仅将数据传输的错误解决,但是分配显示buffer时候的随机数(malloc并不清空Buffer内容)没有处理,这样将会在切换到预览模式的时候显示花屏。我们在service层,找到camera_malloc_preview_buffers(),需要在其中添加如下代码:if(camera_preview_buffers.buffers[current_buffer].buf_ptr){memset(camera_preview_buffers.buffers[current_buffer].buf_ptr,0x7f,camera_preview_buffer_size);camera_set_preview_headers();}camif_window_width_config.firstPixel,camif_window_height_config.firstLine这是用来调整显示像素顺序不对,而bayer的format无法调整的时候,这里提供一个变相的调整format的机会,让显示的色彩正确,至于是减多少,需要实际调试判断,原理就不说了,找资料看去。epoch_line,这是纠错处理,当一帧数据的行超出这个设定的最大行时候,会有出错中断,提示帧错误。将这个值设置的很大,将永远不会发生这个事件,相当于disable。我建议最好disable,因为有一些变态的sensor,会输出很大的dummyline,看起来很变态,但是必须。4.camsensor_xxx_raw_snapshot_config();这个函数是在后续tuning的时候,拍rawdata照片的时候需要,设置同上。5.camsensor_xxx_video_config():预览配置函数。其实没什么好说的,要说的前面都说了,要是这里还有什么不明白的,可以打114问。我就不在这里骗稿费了。6.camsensor_xxx_power_up();其实我不想说,这个函数真的很雷人,要是你相信在这里进行powerup的话,我相信你的camera永远都别正常工作。7.camsensor_xxx_power_down():这个函数还算正常一些,但是不需要在这里closemclk的操作。在退出camera模块的时候,系统会有流程关闭工作时钟。8.camsensor_xxx_register():这个函数写这里,但是我不想说了(我看起来很欠揍)。9.camsensor_xxx_real_to_register_gain()和camsensor_xxx_register_to_real_gain():这两个函数才是重点。说起来有点意思:这两函数,是浮点数和寄存器表示的整数之间的转化关系。举个具体的例子比较容易说明。OV5647:gain寄存器最大0x3FF,小数占用4bit,因此形象的表示浮点数为3F.F,整数0x3F,小数一个F。从曝光表中抽取一个数值{912,600},/*Gain=3.563ExposureIndex=259*/下面的计算是real_to_register:reg_gain=(uint16)real_gain;//real_gain=3.563reg_temp=reg_gain<<4;//只取整数部分gain=reg_temp|(((uint16)((real_gain-(float)reg_gain)*16.0))&0x0f);//整数和小数部分合并下面是register_to_real的计算部分:real_gain=(float)((float)(reg_gain>>4)+(((float)(reg_gain&0x0f))/16.0));//reg_gain是寄存器整数表示的3.563.10.camsensor_ov5647_truly_sensor_setting():这个是sensor的参数集合的函数,用来对sensor初始化,预览和拍照参数的设定。具体的意义这里就不详细解说,一般由sensor厂家完成。11.camsensor_xxx_get_snapshot_fps():将预览/拍照的图片尺寸比较,默认预览30fps,得到拍照的速率,这个,用在ISO,计算曝光行,去除拍照的第一帧数据,防抖动处理。12.camsensor_xxx_get_preview_lines_per_frame():计算ISO曝光时间用的,公式如下:preview_exposuretime=(forced_input.forced_line_count)/(preview_exposuretime*preview_linesPerFrame);13.camsensor_xxx_get_preview_pixels_per_line():用来计算flicker,公式计算如下:if(camctrl_tbl.get_preview_pixels_per_line){cam3a_aec_state.band_60hz_gap=(float)(((float)1/120)*(((float)(camsensorParamsPtr->pixel_clock))/((float)(camctrl_tbl.get_preview_pixels_per_line()))));}else{cam3a_aec_state.band_60hz_gap=(float)(((float)1/120)*(((float)(camsensorParamsPtr->pixel_clock))/((float)(camsensorParamsPtr->pixel_clock_per_line))));}14.camsensor_xxx_get_snapshot_lines_per_frame()::用来计算拍照的曝光行:output.snapshot_linecount=(uint32)(((snapshot_exposuretime*snapshot_linesPerFrame*snapshot_fps)/Q8)+0.5);15.camsensor_xxx_get_snapshot_pixels_per_line():目前没有用处。16.camsensor_xxx_get_snapshot_max_exposure_line_count():设定拍照的最大曝光行,可以用来限制允许拍照的曝光行边界,这个边界是可以动态变化的,这样拍照的曝光时间就可以控制:限定代码如下:output.snapshot_linecount=(uint32)(((snapshot_exposuretime*snapshot_linesPerFrame*snapshot_fps)/(Q8*snapshot_fps_divider))+0.5);17.camsensor_xxx_set_snapshot_frame_rate():没啥用,返回设为TRUE即可。18.camsensor_xxx_set_snapshot_exposure_gain():这个函数是用来对拍照的gain和line进行写入sensor操作,我们为了防止拍照的时候噪声,一般会将gain/2,而line*2.19.camsensor_xxx_setup_camctrl_tbl():几个标志要说明一下:awb_low_light_CC_is_supported=TRUE;CC是colorcorrection的缩写,为色彩校正的意思,对bayer格式的数据而言,那是一定要设置的。fast_convergence_is_supported:是对AEC进行是否快速计算的意思,如果luma计算的进度在实际测试中发现偏差过大(超过2个点,2个点是默认设置,我们可以更改,这在后面的tuning中说明),就需要禁止这个标记。enable_sensor_rolloff_correction:和set_lens_correction标记是一个意思,这个标记要小心设置,当确定不用VFE进行后端rolloff计算,才可以使能这个设置,否则一定要关闭,要不tuning的时候,色彩无法校准。enable_rolloff_correction:这个标记正好和上面的相反,需要VFE进行rolloff设置的时候,我们需要使能它。至于rolloff是啥东西,后面tuning再解释。af_is_supported,af_use_isp,cam3a_af_state.is_enabled,这三个标记,是用来激活Af功能的,要用isp的AF功能,上面三个标记都要设TRUE,要是用VCM通过i2c来激活af功能,af_use_isp设为FALSE,另外两设为TRUE.20.aec_digital_gain_is_supported:这是用在CC的校验中,可以在WB中增强RGB色彩矩阵的变化,另外在拍照ISO设置中,必须配合ISO使能iso_is_supported标志才能起作用,好了,到此driver的说明告一段落。下面我们来说AF的调试。先说VCM的调试。1.camsensor_xxx_set_default_focus:我们一般将镜头设置在无穷远的位置。这样启动camera的时候,看远处会比较清晰。2.camsensor_xxx_move_focus:参数step_direction代表的是每一步对焦的步长,理论上这个值越小,对焦越精确,当然,我们调试是不能完全按照理论来的。一般我们会设置15~20。AF对焦调整,有两种模式,下面介绍一下各个参数的意义其一为通过VCM马达驱动camsensor_params->af_enable使能此功能num_steps_near_to_far步长总数num_steps_near_to_closest_infinity默认值num_gross_steps_between_stat_points粗调步长num_fine_st
found_min)
{
camera_parm_zoom_table.minimum_value=(int32)i;
found_min=TRUE;
}
if(resize_factor{camera_parm_zoom_table.maximum_value=(int32)i;break;}通过camera_min_decimation和camera_zoom_table[]的比较,确定最小的ZOOM起始位置,这个位置其实是zoom的最大值,一般我们得到的是0值,告诉VFE按照camera的原始尺寸处理图像。而camera_parm_zoom_table.maximum_value所表示的是zoom缩小的最大比例。从上边的解释,我们看到,ZOOM所能放大,缩小的比率,和我们camerasensor能输出的最大尺寸,UI能设定的最大尺寸,还有屏幕能表现的尺寸有关系,通过改变这些值,我们能够按照需要放大,缩小图像。通过上面的计算,我们得到camera_parm_zoom.minimum_value和camera_parm_zoom.maximum_value和camera_parm_zoom.step_value,这是我们最后能利用的zoom范围和每一步zoom的步长。接下来如何zoom,就不多说了,因为出错的可能性很小。以上属于部分camera的应用,后面在色彩校准部分还会介绍3a方面的应用。下面我们来讨论一下camerasensor驱动代码我们按照函数调用顺序进行说明:1.camsensor_xxx_init():顾名思义,其代表的功能定义就不用再说了,这里只需要解释一下里面的一个变量camsensor_preview_resolution,它可以赋值CAMSENSOR_QTR_SIZE和CAMSENSOR_FULL_SIZE,QTR是预览尺寸,FULL是拍照尺寸。我们在调试的时候,要是怀疑拍照相关参数问题,可以在预览流程中看拍照的图片进行debug。发布出来给客户的,就只需要QTR的设置。2.camsensor_xxx_start():这个函数太太太太太太重要了(我有点蛋疼了),这个函数是驱动的灵魂,因为可以说的问题太多,一时之间都不知道怎么说(这话说的有点招臭鸡蛋)。这样,望文生义的地方我就不说了,讲讲容易犯错的地方。camif_config相关配置,其实已经没有用了,但是我们还是保留其设置(谁知道以后会不会又需要用上)。camsensor_params->chromatix_parms=&camsensor_chromatix_xxx_struct;这是tuning图像的所有参数的集合文件头。Tuning后面我们会说.camsensor_params->raw_output_option=CAMSENSOR_8_BIT_DIRECT;虽然还有CAMSENSOR_10_BIT_DIRECT这个参数可以选择,但由于后端数据的存储都是按照8Bit来处理,因此这个参数没有什么太大的意义(这个最终解释权在我这里,以后高通会不会将其区别开来,这要用发展的眼光来看).在这个函数里,有判断camsensor_preview_resolution变量,这是为了调试全尺寸的需要而设置的,在正常流程中使用,我们只需要CAMSENSOR_QTR_SIZE这个分支,在实际的调试中,我发现,利用好CAMSENSOR_FULL_SIZE这个参数能方便解决拍照相关的很多问题。至于怎么利用,说起来头疼,简单的说,在第一点使用camsensor_preview_resolution=CAMSENSOR_FULL_SIZE即可,至于这样做会有什么问题,就要看驱动代码的健壮否了。这里无法做太多预测。preview_dx_decimation:这个是VFE处理bayer格式数据给显示屏用的,这个是太太太重要了(我真无聊)。有一个边界计算的问题(边界的意思,就是在数学计算的时候,我们要保证图像处理时候,作为分母的数据不能取为0,否则有严重的后果,嘿嘿,为什么会取为0呢?因为图片边界外面就是0了),其要求在尺寸上,宽度预留12pixel,高度预留8pixel(VFE实际只需要高度裁边6pixel,但是为了整齐,我们裁剪了5+3=8pixel),然后剩下的宽和高的尺寸各自还要能被4整除。有人说不这样做行吗?太麻烦啦,我说可以,但是准备后面的色彩调整时候,屏幕显示总偏色的代价。在6平台上特别是偏绿。接下来是AF参数设置,这个放到AF中再说。AF对焦,只取屏幕的1/4尺寸给VFE计算,可以减少计算量,提高对焦速度。camsensor_params->pixel_clock和pixel_clock_per_line这个参数是如此的重要,怎么说都是重点,这个重点中的重点,我只能用这种方式表达我对这个参数的尊重之情。它是用来计算flicker,也可以叫banding,一个意思。这参数属于tuning范畴,因此如何确定这些参数,归在后面tuning进行解释,这里先提点一下。pclk_invert:不同的厂家,pclk有效的极性可能不一样,因此我们需要判断,设TRUE表示上升沿有效,FALSE表示下降沿有效,如何判断呢?规格书中看看一目了然,下面这张就是上升沿有效的示意图camif_config.HsyncEdge和camif_config.VsyncEdge:有CAMIF_High和CAMIF_Low两种选择,表示行场同步信号的有效电平,高或低有效,只要用示波器看看camera的数据线输出是在行场低还是在高的时候有,就能直观的判断。当然,规格书中也会提及,下面这张就是行场高有效的典型示意图。3.camsensor_xxx_snapshot_config():这个是拍照时候调用的设置函数。简单说一下里面的一些参数好了:discardFirstFrame=TRUE,表示在将来需要切换到预览模式时,会将预览的第一帧数据抛弃,这么做是为了防止第一帧数据残缺造成切换时候显示错乱的现象。但是仅仅这么做还不够(从中可以看到,高通虽然想到这个问题,但是其仅仅停留在实验室阶段),这样做,仅仅将数据传输的错误解决,但是分配显示buffer时候的随机数(malloc并不清空Buffer内容)没有处理,这样将会在切换到预览模式的时候显示花屏。我们在service层,找到camera_malloc_preview_buffers(),需要在其中添加如下代码:if(camera_preview_buffers.buffers[current_buffer].buf_ptr){memset(camera_preview_buffers.buffers[current_buffer].buf_ptr,0x7f,camera_preview_buffer_size);camera_set_preview_headers();}camif_window_width_config.firstPixel,camif_window_height_config.firstLine这是用来调整显示像素顺序不对,而bayer的format无法调整的时候,这里提供一个变相的调整format的机会,让显示的色彩正确,至于是减多少,需要实际调试判断,原理就不说了,找资料看去。epoch_line,这是纠错处理,当一帧数据的行超出这个设定的最大行时候,会有出错中断,提示帧错误。将这个值设置的很大,将永远不会发生这个事件,相当于disable。我建议最好disable,因为有一些变态的sensor,会输出很大的dummyline,看起来很变态,但是必须。4.camsensor_xxx_raw_snapshot_config();这个函数是在后续tuning的时候,拍rawdata照片的时候需要,设置同上。5.camsensor_xxx_video_config():预览配置函数。其实没什么好说的,要说的前面都说了,要是这里还有什么不明白的,可以打114问。我就不在这里骗稿费了。6.camsensor_xxx_power_up();其实我不想说,这个函数真的很雷人,要是你相信在这里进行powerup的话,我相信你的camera永远都别正常工作。7.camsensor_xxx_power_down():这个函数还算正常一些,但是不需要在这里closemclk的操作。在退出camera模块的时候,系统会有流程关闭工作时钟。8.camsensor_xxx_register():这个函数写这里,但是我不想说了(我看起来很欠揍)。9.camsensor_xxx_real_to_register_gain()和camsensor_xxx_register_to_real_gain():这两个函数才是重点。说起来有点意思:这两函数,是浮点数和寄存器表示的整数之间的转化关系。举个具体的例子比较容易说明。OV5647:gain寄存器最大0x3FF,小数占用4bit,因此形象的表示浮点数为3F.F,整数0x3F,小数一个F。从曝光表中抽取一个数值{912,600},/*Gain=3.563ExposureIndex=259*/下面的计算是real_to_register:reg_gain=(uint16)real_gain;//real_gain=3.563reg_temp=reg_gain<<4;//只取整数部分gain=reg_temp|(((uint16)((real_gain-(float)reg_gain)*16.0))&0x0f);//整数和小数部分合并下面是register_to_real的计算部分:real_gain=(float)((float)(reg_gain>>4)+(((float)(reg_gain&0x0f))/16.0));//reg_gain是寄存器整数表示的3.563.10.camsensor_ov5647_truly_sensor_setting():这个是sensor的参数集合的函数,用来对sensor初始化,预览和拍照参数的设定。具体的意义这里就不详细解说,一般由sensor厂家完成。11.camsensor_xxx_get_snapshot_fps():将预览/拍照的图片尺寸比较,默认预览30fps,得到拍照的速率,这个,用在ISO,计算曝光行,去除拍照的第一帧数据,防抖动处理。12.camsensor_xxx_get_preview_lines_per_frame():计算ISO曝光时间用的,公式如下:preview_exposuretime=(forced_input.forced_line_count)/(preview_exposuretime*preview_linesPerFrame);13.camsensor_xxx_get_preview_pixels_per_line():用来计算flicker,公式计算如下:if(camctrl_tbl.get_preview_pixels_per_line){cam3a_aec_state.band_60hz_gap=(float)(((float)1/120)*(((float)(camsensorParamsPtr->pixel_clock))/((float)(camctrl_tbl.get_preview_pixels_per_line()))));}else{cam3a_aec_state.band_60hz_gap=(float)(((float)1/120)*(((float)(camsensorParamsPtr->pixel_clock))/((float)(camsensorParamsPtr->pixel_clock_per_line))));}14.camsensor_xxx_get_snapshot_lines_per_frame()::用来计算拍照的曝光行:output.snapshot_linecount=(uint32)(((snapshot_exposuretime*snapshot_linesPerFrame*snapshot_fps)/Q8)+0.5);15.camsensor_xxx_get_snapshot_pixels_per_line():目前没有用处。16.camsensor_xxx_get_snapshot_max_exposure_line_count():设定拍照的最大曝光行,可以用来限制允许拍照的曝光行边界,这个边界是可以动态变化的,这样拍照的曝光时间就可以控制:限定代码如下:output.snapshot_linecount=(uint32)(((snapshot_exposuretime*snapshot_linesPerFrame*snapshot_fps)/(Q8*snapshot_fps_divider))+0.5);17.camsensor_xxx_set_snapshot_frame_rate():没啥用,返回设为TRUE即可。18.camsensor_xxx_set_snapshot_exposure_gain():这个函数是用来对拍照的gain和line进行写入sensor操作,我们为了防止拍照的时候噪声,一般会将gain/2,而line*2.19.camsensor_xxx_setup_camctrl_tbl():几个标志要说明一下:awb_low_light_CC_is_supported=TRUE;CC是colorcorrection的缩写,为色彩校正的意思,对bayer格式的数据而言,那是一定要设置的。fast_convergence_is_supported:是对AEC进行是否快速计算的意思,如果luma计算的进度在实际测试中发现偏差过大(超过2个点,2个点是默认设置,我们可以更改,这在后面的tuning中说明),就需要禁止这个标记。enable_sensor_rolloff_correction:和set_lens_correction标记是一个意思,这个标记要小心设置,当确定不用VFE进行后端rolloff计算,才可以使能这个设置,否则一定要关闭,要不tuning的时候,色彩无法校准。enable_rolloff_correction:这个标记正好和上面的相反,需要VFE进行rolloff设置的时候,我们需要使能它。至于rolloff是啥东西,后面tuning再解释。af_is_supported,af_use_isp,cam3a_af_state.is_enabled,这三个标记,是用来激活Af功能的,要用isp的AF功能,上面三个标记都要设TRUE,要是用VCM通过i2c来激活af功能,af_use_isp设为FALSE,另外两设为TRUE.20.aec_digital_gain_is_supported:这是用在CC的校验中,可以在WB中增强RGB色彩矩阵的变化,另外在拍照ISO设置中,必须配合ISO使能iso_is_supported标志才能起作用,好了,到此driver的说明告一段落。下面我们来说AF的调试。先说VCM的调试。1.camsensor_xxx_set_default_focus:我们一般将镜头设置在无穷远的位置。这样启动camera的时候,看远处会比较清晰。2.camsensor_xxx_move_focus:参数step_direction代表的是每一步对焦的步长,理论上这个值越小,对焦越精确,当然,我们调试是不能完全按照理论来的。一般我们会设置15~20。AF对焦调整,有两种模式,下面介绍一下各个参数的意义其一为通过VCM马达驱动camsensor_params->af_enable使能此功能num_steps_near_to_far步长总数num_steps_near_to_closest_infinity默认值num_gross_steps_between_stat_points粗调步长num_fine_st
camera_parm_zoom_table.maximum_value=(int32)i;
break;
通过camera_min_decimation和camera_zoom_table[]的比较,确定最小的ZOOM起始位置,这个位置其实是zoom的最大值,一般我们得到的是0值,告诉VFE按照camera的原始尺寸处理图像。
而camera_parm_zoom_table.maximum_value所表示的是zoom缩小的最大比例。
从上边的解释,我们看到,ZOOM所能放大,缩小的比率,和我们camerasensor能输出的最大尺寸,UI能设定的最大尺寸,还有屏幕能表现的尺寸有关系,通过改变这些值,我们能够按照需要放大,缩小图像。
通过上面的计算,我们得到camera_parm_zoom.minimum_value和camera_parm_zoom.maximum_value和camera_parm_zoom.step_value,这是我们最后能利用的zoom范围和每一步zoom的步长。
接下来如何zoom,就不多说了,因为出错的可能性很小。
以上属于部分camera的应用,后面在色彩校准部分还会介绍3a方面的应用。
下面我们来讨论一下camerasensor驱动代码
我们按照函数调用顺序进行说明:
1.camsensor_xxx_init():
顾名思义,其代表的功能定义就不用再说了,这里只需要解释一下里面的一个变量camsensor_preview_resolution,它可以赋值CAMSENSOR_QTR_SIZE和CAMSENSOR_FULL_SIZE,QTR是预览尺寸,FULL是拍照尺寸。
我们在调试的时候,要是怀疑拍照相关参数问题,可以在预览流程中看拍照的图片进行debug。
发布出来给客户的,就只需要QTR的设置。
2.camsensor_xxx_start():
这个函数太太太太太太重要了(我有点蛋疼了),这个函数是驱动的灵魂,因为可以说的问题太多,一时之间都不知道怎么说(这话说的有点招臭鸡蛋)。
这样,望文生义的地方我就不说了,讲讲容易犯错的地方。
camif_config相关配置,其实已经没有用了,但是我们还是保留其设置(谁知道以后会不会又需要用上)。
camsensor_params->chromatix_parms=&camsensor_chromatix_xxx_struct;这是tuning图像的所有参数的集合文件头。
Tuning后面我们会说.
camsensor_params->raw_output_option=CAMSENSOR_8_BIT_DIRECT;虽然还有CAMSENSOR_10_BIT_DIRECT这个参数可以选择,但由于后端数据的存储都是按照8Bit来处理,因此这个参数没有什么太大的意义(这个最终解释权在我这里,以后高通会不会将其区别开来,这要用发展的眼光来看).
在这个函数里,有判断camsensor_preview_resolution变量,这是为了调试全尺寸的需要而设置的,在正常流程中使用,我们只需要CAMSENSOR_QTR_SIZE这个分支,在实际的调试中,我发现,利用好CAMSENSOR_FULL_SIZE这个参数能方便解决拍照相关的很多问题。
至于怎么利用,说起来头疼,简单的说,在第一点使用camsensor_preview_resolution=CAMSENSOR_FULL_SIZE即可,至于这样做会有什么问题,就要看驱动代码的健壮否了。
这里无法做太多预测。
preview_dx_decimation:
这个是VFE处理bayer格式数据给显示屏用的,这个是太太太重要了(我真无聊)。
有一个边界计算的问题(边界的意思,就是在数学计算的时候,我们要保证图像处理时候,作为分母的数据不能取为0,否则有严重的后果,嘿嘿,为什么会取为0呢?
因为图片边界外面就是0了),其要求在尺寸上,宽度预留12pixel,高度预留8pixel(VFE实际只需要高度裁边6pixel,但是为了整齐,我们裁剪了5+3=8pixel),然后剩下的宽和高的尺寸各自还要能被4整除。
有人说不这样做行吗?
太麻烦啦,我说可以,但是准备后面的色彩调整时候,屏幕显示总偏色的代价。
在6平台上特别是偏绿。
接下来是AF参数设置,这个放到AF中再说。
AF对焦,只取屏幕的1/4尺寸给VFE计算,可以减少计算量,提高对焦速度。
camsensor_params->pixel_clock和pixel_clock_per_line这个参数是如此的重要,怎么说都是重点,这个重点中的重点,我只能用这种方式表达我对这个参数的尊重之情。
它是用来计算flicker,也可以叫banding,一个意思。
这参数属于tuning范畴,因此如何确定这些参数,归在后面tuning进行解释,这里先提点一下。
pclk_invert:
不同的厂家,pclk有效的极性可能不一样,因此我们需要判断,设TRUE表示上升沿有效,FALSE表示下降沿有效,如何判断呢?
规格书中看看一目了然,下面这张就是上升沿有效的示意图
camif_config.HsyncEdge和camif_config.VsyncEdge:
有CAMIF_High和CAMIF_Low两种选择,表示行场同步信号的有效电平,高或低有效,只要用示波器看看camera的数据线输出是在行场低还是在高的时候有,就能直观的判断。
当然,规格书中也会提及,下面这张就是行场高有效的典型示意图。
3.camsensor_xxx_snapshot_config():
这个是拍照时候调用的设置函数。
简单说一下里面的一些参数好了:
discardFirstFrame=TRUE,表示在将来需要切换到预览模式时,会将预览的第一帧数据抛弃,这么做是为了防止第一帧数据残缺造成切换时候显示错乱的现象。
但是仅仅这么做还不够(从中可以看到,高通虽然想到这个问题,但是其仅仅停留在实验室阶段),这样做,仅仅将数据传输的错误解决,但是分配显示buffer时候的随机数(malloc并不清空Buffer内容)没有处理,这样将会在切换到预览模式的时候显示花屏。
我们在service层,找到camera_malloc_preview_buffers(),需要在其中添加如下代码:
if(camera_preview_buffers.buffers[current_buffer].buf_ptr)
memset(camera_preview_buffers.buffers[current_buffer].buf_ptr,
0x7f,
camera_preview_buffer_size);
camera_set_preview_headers();
camif_window_width_config.firstPixel,camif_window_height_config.firstLine这是用来调整显示像素顺序不对,而bayer的format无法调整的时候,这里提供一个变相的调整format的机会,让显示的色彩正确,至于是减多少,需要实际调试判断,原理就不说了,找资料看去。
epoch_line,这是纠错处理,当一帧数据的行超出这个设定的最大行时候,会有出错中断,提示帧错误。
将这个值设置的很大,将永远不会发生这个事件,相当于disable。
我建议最好disable,因为有一些变态的sensor,会输出很大的dummyline,看起来很变态,但是必须。
4.camsensor_xxx_raw_snapshot_config();这个函数是在后续tuning的时候,拍rawdata照片的时候需要,设置同上。
5.camsensor_xxx_video_config():
预览配置函数。
其实没什么好说的,要说的前面都说了,要是这里还有什么不明白的,可以打114问。
我就不在这里骗稿费了。
6.camsensor_xxx_power_up();其实我不想说,这个函数真的很雷人,要是你相信在这里进行powerup的话,我相信你的camera永远都别正常工作。
7.camsensor_xxx_power_down():
这个函数还算正常一些,但是不需要在这里closemclk的操作。
在退出camera模块的时候,系统会有流程关闭工作时钟。
8.camsensor_xxx_register():
这个函数写这里,但是我不想说了(我看起来很欠揍)。
9.camsensor_xxx_real_to_register_gain()和camsensor_xxx_register_to_real_gain():
这两个函数才是重点。
说起来有点意思:
这两函数,是浮点数和寄存器表示的整数之间的转化关系。
举个具体的例子比较容易说明。
OV5647:
gain寄存器最大0x3FF,小数占用4bit,因此形象的表示浮点数为3F.F,整数0x3F,小数一个F。
从曝光表中抽取一个数值{912,600},/*Gain=3.563ExposureIndex=259*/下面的计算是real_to_register:
reg_gain=(uint16)real_gain;//real_gain=3.563reg_temp=reg_gain<<4;//只取整数部分gain=reg_temp|(((uint16)((real_gain-(float)reg_gain)*16.0))&0x0f);//整数和小数部分合并下面是register_to_real的计算部分:
real_gain=(float)((float)(reg_gain>>4)+(((float)(reg_gain&0x0f))/16.0));//reg_gain是寄存器整数表示的3.563.
10.camsensor_ov5647_truly_sensor_setting():
这个是sensor的参数集合的函数,用来对sensor初始化,预览和拍照参数的设定。
具体的意义这里就不详细解说,一般由sensor厂家完成。
11.camsensor_xxx_get_snapshot_fps():
将预览/拍照的图片尺寸比较,默认预览30fps,得到拍照的速率,这个,用在ISO,计算曝光行,去除拍照的第一帧数据,防抖动处理。
12.camsensor_xxx_get_preview_lines_per_frame():
计算ISO曝光时间用的,公式如下:
preview_exposuretime=(forced_input.forced_line_count)/(preview_exposuretime*preview_linesPerFrame);
13.camsensor_xxx_get_preview_pixels_per_line():
用来计算flicker,公式计算如下:
if(camctrl_tbl.get_preview_pixels_per_line){cam3a_aec_state.band_60hz_gap=(float)(((float)1/120)*(((float)(camsensorParamsPtr->pixel_clock))/((float)(camctrl_tbl.get_preview_pixels_per_line()))));}else{cam3a_aec_state.band_60hz_gap=(float)(((float)1/120)*(((float)(camsensorParamsPtr->pixel_clock))/((float)(camsensorParamsPtr->pixel_clock_per_line))));}
14.camsensor_xxx_get_snapshot_lines_per_frame():
:
用来计算拍照的曝光行:
output.snapshot_linecount=(uint32)(((snapshot_exposuretime*snapshot_linesPerFrame*snapshot_fps)/Q8)+0.5);
15.camsensor_xxx_get_snapshot_pixels_per_line():
目前没有用处。
16.camsensor_xxx_get_snapshot_max_exposure_line_count():
设定拍照的最大曝光行,可以用来限制允许拍照的曝光行边界,这个边界是可以动态变化的,这样拍照的曝光时间就可以控制:
限定代码如下:
output.snapshot_linecount=(uint32)(((snapshot_exposuretime*snapshot_linesPerFrame*snapshot_fps)/(Q8*snapshot_fps_divider))+0.5);
17.camsensor_xxx_set_snapshot_frame_rate():
没啥用,返回设为TRUE即可。
18.camsensor_xxx_set_snapshot_exposure_gain():
这个函数是用来对拍照的gain和line进行写入sensor操作,我们为了防止拍照的时候噪声,一般会将gain/2,而line*2.
19.camsensor_xxx_setup_camctrl_tbl():
几个标志要说明一下:
awb_low_light_CC_is_supported=TRUE;CC是colorcorrection的缩写,为色彩校正的意思,对bayer格式的数据而言,那是一定要设置的。
fast_convergence_is_supported:
是对AEC进行是否快速计算的意思,如果luma计算的进度在实际测试中发现偏差过大(超过2个点,2个点是默认设置,我们可以更改,这在后面的tuning中说明),就需要禁止这个标记。
enable_sensor_rolloff_correction:
和set_lens_correction标记是一个意思,这个标记要小心设置,当确定不用VFE进行后端rolloff计算,才可以使能这个设置,否则一定要关闭,要不tuning的时候,色彩无法校准。
enable_rolloff_correction:
这个标记正好和上面的相反,需要VFE进行rolloff设置的时候,我们需要使能它。
至于rolloff是啥东西,后面tuning再解释。
af_is_supported,af_use_isp,cam3a_af_state.is_enabled,这三个标记,是用来激活Af功能的,要用isp的AF功能,上面三个标记都要设TRUE,要是用VCM通过i2c来激活af功能,af_use_isp设为FALSE,另外两设为TRUE.
20.aec_digital_gain_is_supported:
这是用在CC的校验中,可以在WB中增强RGB色彩矩阵的变化,另外在拍照ISO设置中,必须配合ISO使能iso_is_supported标志才能起作用,
好了,到此driver的说明告一段落。
下面我们来说AF的调试。
先说VCM的调试。
1.camsensor_xxx_set_default_focus:
我们一般将镜头设置在无穷远的位置。
这样启动camera的时候,看远处会比较清晰。
2.camsensor_xxx_move_focus:
参数step_direction代表的是每一步对焦的步长,理论上这个值越小,对焦越精确,当然,我们调试是不能完全按照理论来的。
一般我们会设置15~20。
AF对焦调整,有两种模式,下面介绍一下各个参数的意义
其一为通过VCM马达驱动
camsensor_params->
af_enable使能此功能
num_steps_near_to_far步长总数
num_steps_near_to_closest_infinity默认值
num_gross_steps_between_stat_points粗调步长
num_fine_st
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1