|
# J0 P7 J- e. x3 ^8 J
图1
2 g6 N0 B, ~# l' |. u1. Camera拍照相关概念 1.1 ISP 5 G% Q. ]! U, {+ R0 m$ {( E
isp——(Image Signal Processor)——影视处理
6 ?, r! P9 k/ O( N' W# \0 n无论数码相机、摄像机或者摄像手机,其影像数据从前端感应后,皆须经过ASP(Analog Signal Processing)、ADC(Analog-Digital Converter)、前期影像处理(Pre-ISP)与后端影像处理(Post-ISP)四个阶段后,影像数据才能最终呈现于终端设备上 ) Y) ^( `9 f' _1 @3 E
1.2 720p 720P是美国电影电视工程师协会(SMPTE)制定的高等级高清数字电视的格式标准,有效显示格式为:1280×720.SMPTE(美国电影电视工程协会)将数字高清信号数字电视扫描线的不同分为1080P、1080I、720P(i是interlace,隔行的意思,p是Progressive,逐行的意思)。720P是一种在逐行扫描下达到1280×720的分辨率的显示格式。是数字电影成像技术和计算机技术的融合。
5 _5 Q! |5 h# y分辨率为1280×720p/60Hz,行频为45kHz % h2 }3 T6 y8 R1 z( k
- m/ h1 s5 A- x. q: c" Z( [
2. MTK6577Camera控制器部分 2.1 camera控制器概述 MT6577 camera可接受RAM和SOC传感器处理之后的图像数据(sensor image data),并输出YUV数据给MDP(什么的简称)。Camera控制器可同时连接2个并行SOC传感器,它提供像素缺陷补偿(bad pixel compensation)、去马赛克(demosaic)、边缘曾强(edge enhancement)、标准色自适应(preference color adaptation)、空间和暂时噪声消除(spatial and temporal noise reduction)这些特征,用于图像处理。 1 b g( `7 M% G0 s: } ]
2.2 camera特征
* q# T% \- o; I' r% S" FMT6577内部集成的ISP,包含了一个功能强大的图像信号处理器,用于连接各种各样的图像传感器模组,这个处理器由时序产生单元(timing generated unit: TG)、镜头/传感器补偿(lens/sensor compensation)单元和图像处理单元。 7 |5 K; i5 l$ j3 W* R v: N0 \; G) m8 i! H
支持的特征如下: (1) 抓图分辨率达8M像素(image capture resolution)。 (2) 录像分辨率达720p(video recording resolution)。 (3) 原始图像数据转储帧率8M@15(raw dump frame rate)。 (4) 曝光抓图率8M@7(burst capture rate)。 (5) 图像处理 低像素补偿(poor pix compensation)、镜头阴影补偿(lens shading compensation)、去马赛克(demosaic)、色彩削波(color clipping)、局部对比度增强(local contrast enhancement)、伽玛校正(gamma correction)、边缘曾强(edge enhancement)、噪声消除(noise reduction)、标准色自适应(preference color adaptation)、空间和暂时噪声消除(spatial and temporal noise reduction)。 1 M. _4 \- N" x
(6) 3A统计和校正(statistics and correction) (7) 闪烁检测(flicker detection)。 2 @" ]! G+ R" A2 B, O$ Y6 J' \# C
2.3 camera框图
0 j. D! t/ e# z5 p* Z. m. t: s9 _
图2 TG只配合主图像传感器(master type image sensor),也就是说主图像传感器应发送垂直和水平信号给TG。TG通过内部自动同步 (internal auto synchronization)或外部像素时钟同步来提供传感器所需要的数据时钟和接收传感器Bayer模式原始数据(Bayer pattern raw data)。TG的主要目的是为主图像传感器创建数据时钟和接收垂直/水平同步信号与sensor数据,然后产生Bayer数据的捕获区域(grabbed area of Bayer data)或是YUV422/RGB565数据给镜头/传感器补偿(lens/sensor compensation)单元。 ) d/ A' L& J2 C& [
在Bayer原始数据输入模式,镜头/传感器补偿(lens/sensor compensation)单元产生补偿的原始数据给色彩处理单元(color process unit);在YUV422/RGB565 输入模式,这步被忽略。
' @. V4 e' P# B! V% b色彩处理单元接受来之镜头/传感器补偿(lens/sensor compensation)单元产生补偿的原始数据或是YUV422/RGB565数据。ISP的输出的是很容易被压缩引擎(compress engine,JPEG编码器和MPEG4编码器)编码的YCbCr888数据格式,它是其他数据格式转化的基本数据域(比如R/G/B domain)(it can be the basic data domain of otherdata format translation such as the R/G/B domain)。ISP是流水线式(pipelined),在处理阶段ISP硬件能够为后面的AE/AF/AWB计算提取有意义的信息,这些信息被临时保存在ISP寄存器或是内存中,并且能够被MCU读取出来。 % w. q. m% n5 \! t5 ?" ^3 F
下面给出一些性能参数:
1 y2 I G9 x* |5 q# J
图3
6 D) c8 U6 h& n7 @& X3. 原理图设计
* x' \: c' h, D& h* C9 X& l* ?MT6577支持两路camera接口,一路是MIPI接口,一路是并行接口,这里我们采用的是并行接口,下面给出MT6577 CAM并行接口定义:
2 U" h4 o" C2 s
图4 Camera sensor连接座如下:
$ @/ k( T% x6 h) {+ ^* h3 ^
图5 9 D6 ^% ~4 y) Z+ v3 o, t
(1) OV5640输出的数据格式 《Y1MT6577 design notice V0.1.pdf》文档给出这样的说明: Sensor outputformat is RAM8/YUV/JPEG,connect sensor output to CMDAT[0:7] or CMDAT[2:9] Sensor outputformat is RAM10,connect sensor output to CMDAT[0:9] 而我们采用摄像头模组的驱动IC为OV5640(500万像素: active array size: 2592 x 1944) Sensor :outputformats: 8-/10-bit RGB RAW output,这是由OV5640寄存器0x4745决定的。原则就是:首先看硬件上采用的是8根数据线还是10根数据线,然后初始化参数-也就是寄存器设定也可以设定是8位或10位。如下图:
7 S f4 q4 t4 i& \5 ]1 j图6
2 s, @7 M u: l' u
$ P) |8 g' J! |: ]( L# s(2) OV5640IIC地址
- g# Z/ X. J3 ?6 L( r# A9 X; u& t- BIIC 8bit写地址为0x78,读地址为0x79,查询Sensor规格书可以看到:
& N# J$ P1 k! t图7 IIC 8bit地址最后一位为0时是写地址,为1时是读地址。这属于IIC通讯规则 9 R1 S: E, `' [1 S' l
! q! D0 F0 l$ {# y7 L! p
4 O3 M5 Q# f- t5 g! } j
4. 驱动实现 # |3 X) N/ V7 Z- Q) c! ^& H5 `
: Q3 ?; `5 U5 N4.1 相关代码 (1) CameraSensor驱动相关文件 \mediatek\custom\common\kernel\imgsensor\ov5642_yuv
8 k u5 j7 d& ~, s(2) SensorID和一些枚举类型的定义 \mediatek\custom\common\kernel\imgsensor\inc kd_imgsensor.h---------SensorID kd_imgsensor_define.h--------------一些枚举类型的定义 6 F8 K; y" B: ]! j. L$ {
(3) Sensor供电 \mediatek\custom\common\kernel\camera\camera kd_camera_hw.c和kd_camera_hw.h 5 m7 _+ j- l' ~% }. t- h
(4) KernelSpace的SensorList,imgsensor模块注册 \mediatek\custom\common\kernel\imgsensor\src kd_sensorlist.c和kd_sensorlist.h-----------camera模块加载
% R9 {6 D' }4 p4 }(5) UserSpace的SensorList,向用户空间提供支持的SensorList \mediatek\custom\common\hal\imgsensor\src\sensorlist.cpp 提供给用户空间的SensorList , a& D' Z) I6 F
8 e, L5 a& V- q8 a/ \6 N(6) Sensor效果调整的接口 \mediatek\custom\common\hal\imgsensor\ov5642_yuv . }& |! v; I }7 ?8 g$ b g' J
: d* Y6 s# z# I2 o. Y! @* o$ r% C4.2 针对OV5640的修改 $ O4 j8 Q# C+ J" W9 ]5 I2 M
4.2.1 mediatek\config\hsimobile77_ics2\ProjectConfig.mk * y0 z" @0 }. j+ w/ R
CUSTOM_KERNEL_IMGSENSOR=mt9p017_rawgc0329_yuv mt9p017_raw表示后置摄像头(也就是主摄像头),mt9p017是摄像头sensor驱动IC,raw是sensor一种输出的数据格式,是CCD或CMOS在将光信号转换为电信号时的电平高低的原始记录,单纯地没有将没有进行任何处理的图像数据,即摄像元件直接得到的电信号进行数字化处理而得到的。
; n, M6 y0 S! T# }1 U8 K+ U. @gc0329_yuv是前置摄像头,yuvsensor一种输出的数据格式,支持YUV/RGB格式的模组,一般会带有ISP(image single processor),经过A/D转换过的原始数据经过ISP处理生成YUV标准格式传到BB。 $ L3 s- v3 V) I% T( l) x9 h
我们采用的OV5640就带有ISP,输出YUV格式 ; x# P$ q- v, r. X* b
(1) 把mt9p017_raw 改为ov5640_yuv,去掉gc0329_yuv因为我们的产品没有后置摄像头 (2) 去掉类似CUSTOM_KERNEL_LENS后面的dummy_lens因为没有后置摄像头
; R. Y& i% c* }$ d4 R修改之后的HAL层的配置:
7 O0 R+ E5 O7 n0 [; R7 ^- CUSTOM_HAL_IMGSENSOR=ov5640_yuv
- CUSTOM_HAL_LENS=fm50afdummy_lens
- CUSTOM_HAL_MAIN_BACKUP_IMGSENSOR=
- CUSTOM_HAL_MAIN_BACKUP_LENS=
- CUSTOM_HAL_MAIN_IMGSENSOR=ov5640_yuv
- CUSTOM_HAL_MAIN_LENS=fm50af
- CUSTOM_HAL_MATV=
- CUSTOM_HAL_MSENSORLIB=mmc328xakm8975 ami304 yamaha530 mag3110 akmd8963
- CUSTOM_HAL_SENSORS=sensor
- CUSTOM_HAL_SUB_BACKUP_IMGSENSOR=
- CUSTOM_HAL_SUB_BACKUP_LENS=
- CUSTOM_HAL_SUB_IMGSENSOR=
- CUSTOM_HAL_SUB_LENS=dummy_lens * k% A* A0 h3 [, k! K' l
8 J' l/ G k: S9 F
3 s# O- }& U s! n+ P
# F% E1 p- M- m( H. l修改之后的kernel层的配置: - j! z! I+ S/ h* I4 [" \
- CUSTOM_KERNEL_IMGSENSOR=ov5640_yuv
- CUSTOM_KERNEL_JOGBALL=
- CUSTOM_KERNEL_KPD=kpd
- CUSTOM_KERNEL_LCM=ili9806e
- CUSTOM_KERNEL_LEDS=mt65xx
- CUSTOM_KERNEL_LENS=fm50afdummy_lens
- CUSTOM_KERNEL_MAGNETOMETER=akm8975
- CUSTOM_KERNEL_MAIN_BACKUP_IMGSENSOR=
- CUSTOM_KERNEL_MAIN_BACKUP_LENS=
- CUSTOM_KERNEL_MAIN_IMGSENSOR=ov5640_yuv
- CUSTOM_KERNEL_MAIN_LENS=fm50af
- CUSTOM_KERNEL_MATV=
- CUSTOM_KERNEL_OFN=
- CUSTOM_KERNEL_RTC=rtc
- CUSTOM_KERNEL_SOUND=amp_6329pmic_2in1_spk
- CUSTOM_KERNEL_SUB_BACKUP_IMGSENSOR=
- CUSTOM_KERNEL_SUB_BACKUP_LENS=
- CUSTOM_KERNEL_SUB_IMGSENSOR=
- CUSTOM_KERNEL_SUB_LENS=dummy_lens
3 M' ?# [8 K- m3 p$ x; n: Y C0 v" l* j" U9 C2 k) v
3 t1 w, @$ x- m% P; h
8 ~& A! v" P* W9 o+ w0 J( K6 C4 g! ?1 m j$ `# V; s/ k
虽然我们没有后置摄像头,但不能去掉dummy_lens,我尝试过去掉之后用./mk r dr编译会提示下面的错误: 3 f% ~1 k3 p* J+ y
" a/ u/ n- C4 s$ M1 S; D1 o7 `
- prebuilt/linux-x86/toolchain/arm-linux-androideabi-4.4.x/bin/../lib/gcc/arm-linux-androideabi/4.4.3/../../../../arm-linux-androideabi/bin/ld:out/target/product/hsimobile77_ics2/obj/SHARED_LIBRARIES/libcameracustom_intermediates/common/hal/lens/lenslist.o:in function global constructors keyed tolenslist.cpp:mediatek/source/external/mhal/src/custom/common/hal/lens/lenslist.cpp:82:error: undefined reference to 'pDummy_getDefaultData'
- make[3]: ***[out/target/product/hsimobile77_ics2/obj/SHARED_LIBRARIES/libcameracustom_intermediates/LINKED/libcameracustom.so]Error 1 8 t y; a3 I& W" m1 P/ W3 |( t5 T
4 i! P2 v! Y. p; M0 Y
" d- a0 k% i4 b! I! c* p/ v' f9 X E& _9 m7 C: T O' B
9 c7 ^! _: O/ L5 v, n- I* O4.2.2 mediatek\custom\common\kernel\imgsensor----------kernel层
$ X. ^5 T% z: Z2 E( {(1) 创建ov5640_yuv并建立需要的文件 * l- N, u: T1 ]0 c# z/ [
创建文件夹ov5640_yuv,把sensor IC厂家提供的ov5640yuv_Sensor.c放到此目录下。另外拷贝ov5642yuv_Sensor.h、ov5642yuv_Camera_Sensor_para.h、ov5642yuv_CameraCustomized.h拷贝过来改为ov5640yuv_Sensor.h等。 - `1 [% J- L+ n6 _
编译发现mediatek\custom\common\kernel\imgsensor\ov5640_yuv\ov5640yuv_Sensor.c文件用到的OV5640_FULL_PERIOD_PIXEL_NUMS_HTS、OV5640_FULL_PERIOD_LINE_NUMS_VTS、OV5640_PV_PERIOD_PIXEL_NUMS_HTS和OV5640_PV_PERIOD_LINE_NUMS_VTS没有定义,但ov5642yuv_Sensor.c是没有这几个宏定义,我暂时定义如下: 1 G }/ B! w4 H8 s% _
) M: H- Z: }* L. o, k* j
- //kandi add startat 2014.11.29
- #defineOV5640_FULL_PERIOD_PIXEL_NUMS_HTS OV5640_FULL_PERIOD_PIXEL_NUMS
- #define OV5640_FULL_PERIOD_LINE_NUMS_VTS OV5640_FULL_PERIOD_LINE_NUMS
-
- #defineOV5640_PV_PERIOD_PIXEL_NUMS_HTS OV5640_PV_PERIOD_PIXEL_NUMS
- #define OV5640_PV_PERIOD_LINE_NUMS_VTS OV5640_PV_PERIOD_LINE_NUMS 1 V, |2 q+ t8 u; |
+ T2 T* M! c; n, H
. f* w. J% A% ?: o$ o0 s3 b8 |7 r% w, |3 V: }
这是参考ov5642的相关定义来定义的。 ) X R% O# {9 w7 v1 J
(2) 在支持的sensor列表中增加目标sensor 6 m5 \) [4 N; q
mediatek\custom\common\kernel\imgsensor\src\kd_sensorlist.h 在数组增加OV5640的内容,如下:
{- w% F$ i: N0 [: e; W# m
$ h7 R& N* i' p- ACDK_KD_SENSOR_INIT_FUNCTION_STRUCTkdSensorList[MAX_NUM_OF_SUPPORT_SENSOR+1] =
- {
- ………….
- #if defined(OV5640_YUV)
- {OV5640_SENSOR_ID,SENSOR_DRVNAME_OV5640_YUV, OV5640_YUV_SensorInit},
- #endif
- …………….
- } 7 B; \* h9 d7 C4 _& A: K& Q# Q$ i4 G9 M
! i" e1 A; \2 e2 y5 V 0 W3 V5 P1 \9 k# z* [
9 G" t8 d$ V& x6 i9 d+ e
4 }8 q# X! @( i. y1 W1 ^* P) I也增加UINT32 OV5640_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT*pfFunc); mediatek\custom\common\kernel\imgsensor\inc\kd_imgsensor.h (3) 增加sensor ID和字符串的定义 8 L& K' A) s& {. r2 V' y2 ~
9 x: y* r1 t- N8 h- #defineOV5640_SENSOR_ID 0x5640
- #defineSENSOR_DRVNAME_OV5640_YUV "ov5640yuv"
2 |3 y8 K! p3 ]4 R" o! p ) o. G& s H* R' _) ~& d
3 I" O" {$ O T, j' U
9 V. R( H2 T' w* O1 [( D* P, p0 u4.2.3 mediatek\custom\common\hal\imgsensor---------------HAL层 1 P- E. T6 c( s4 i4 u
(1) 创建ov5640_yuv文件夹 但这些文件夹下该有哪些文件,有需要哪些内容了,首先我对比了 ov3640_yuv和ov5642_yuv文件夹,只有cfg_ftbl_ov5642_yuv.h有差别:
图8 % s( x/ r+ J+ b; s
这里主要是不同驱动IC支持的分辨率不同,以及设置默认的分辨率。
图9
8 y6 t2 j H9 W, p N& z. { J此文件下有两个这样的地方不同,这里是指自动对焦模式。 2 {3 `) T. I2 L% R1 u
因为我们的OV5640和OV5642非常接近,所以就直接把OV5642的目录复制过来修改为OV5640即可。 " d0 @* L) M: j- o+ I6 m. S. Q$ V
所以把mediatek\custom\common\kernel\imgsensor\ov5642_yuv拷贝到imgsensor目录下,改为ov5640_yuv ! a/ D* N: B" s$ E: L' ~8 y5 z* w
(2) 在支持的sensor列表中增加目标sensor
$ t' {! q. T! E! `\src\ sensorlist.cpp " E3 z5 o- S. @: }4 _% ]/ q# V) _
1 B2 b% n' r* k8 `. ?
- MSDK_SENSOR_INIT_FUNCTION_STRUCTSensorList[] =
- {
- ………..
- #ifdefined(OV5640_YUV)
- YUV_INFO(OV5640_SENSOR_ID,SENSOR_DRVNAME_OV5640_YUV, NULL),
- #endif
- …………
- } , k# M7 B$ P3 K( l1 ]
9 }! k) A- N5 a& O( `: z- w
# M8 i. _2 ]: L! S: ]
2 {( I7 s2 k5 T4 i- c( k$ E
注意:在 kd_SensorList.h 和 SensorList.cpp 里面添加驱动的时候要注意,Sensor 添加的位置要一样。否则驱动会跑乱,轻则 ISP 参数不对,重则 Sensor 无法启动。
; m* {: A/ M" _3 d3 D1 f6 L
$ \$ S7 ?. s4 t! @- _# A4.3 拍照图片尺寸设置
% m5 X! |9 N: Omediatek\custom\common\hal\imgsensor\ov5640_yuv\cfg_ftbl_ov5640_yuv.h 7 t. Q+ y5 c9 v/ r' m, V. N* i; s. b
. M0 D5 g4 J2 x, g R Q, P
0 O( }) r( ^# c
- // Capture Size
- CONFIG_FEATURE_SI(FID_CAP_SIZE,
- BY_DEFAULT(CAPTURE_SIZE_2560_1920),
- CAPTURE_SIZE_1280_960, CAPTURE_SIZE_1600_1200,
- CAPTURE_SIZE_2048_1536,CAPTURE_SIZE_2560_1920
- )
) D3 |- _; @: `3 @, S9 P6 o' p5 C
5 z& z" X" }* w0 G8 p P6 G; O2 r- q8 C% K1 N
4.4 Camera物理角度旋转 Cfg_setting_imgsensor.h ' \- B/ M( x" D/ }7 ?* n
0 Z0 u! W6 r; o6 w9 ^4 {- /*******************************************************************************
- * Image SensorOrientation
- *******************************************************************************/
- SensorOrientation_Tconst&
- getSensorOrientation()
- {
- static SensorOrientation_T const inst = {
- u4Degree_0 : 0,//270,//180,//90, // main sensor in degree (0, 90, 180, 270),kandi change from 90 to 180
- u4Degree_1 : 0, // sub sensor in degree (0, 90, 180, 270)
- };
- return inst;
- } C3 T3 s. R; V* g1 W6 e4 F9 l
) |; B; n0 e- u) W
& [- k% D5 ^! K$ S0 d
0 T& f/ S" T* a5 }3 f7 ]0 R) j
6 ^6 D, h* I" z; E# q. d
这几种都试过了,但都不行,预览和实际的都是成某种镜像关系。这是平台是提供旋转的功能。这个配置好了之后,如果方向不正确,可以通过驱动中的方向调整函数进行调整,如下: static void XXXXXSetMirror(kal_uint16ImageMirror) 参考:http://blog.csdn.net/loongembedded/article/details/41679977 & O! o8 o& \: i: ]+ O
/ A0 J% ^8 C# m! [: w4 d$ o: m
* T/ y8 O7 x* U: }! z 看了OV5640的数据手册,寄存器0x3820和0x3821是用于控制图像发射(mirror)和翻转(flip)的,在u4Degree_0=270情况下,OV5640YUVPreview()调用OV5640YUV_Set_Mirror_Flip (IMAGE_V_MIRROR),预览和拍照后的预览都是OK,但拍好的照片在电脑上打开的时候发现是顺时针翻转了90度。 http://bbs.csdn.net/topics/390837150 可是我在OV5640YUV_Sensor_Init()调用OV5640YUV_Set_Mirror_Flip(IMAGE_V_MIRROR)却问题依旧,很奇怪。
/ i7 S* _1 s" ^6 S3 e# qmediatek\custom\common\hal\imgsensor\ov5640_yuv\cfg_ftbl_ov5640_yuv.h 4 x2 q, D0 ]! r& c1 Q/ [5 z8 T
- /*
- // Capture Size
- CONFIG_FEATURE_SI(FID_CAP_SIZE,
- BY_DEFAULT(CAPTURE_SIZE_2560_1920),
- CAPTURE_SIZE_1280_960, CAPTURE_SIZE_1600_1200,
- CAPTURE_SIZE_2048_1536,CAPTURE_SIZE_2560_1920
- )
- */
- // Capture Size
- CONFIG_FEATURE_SI(FID_CAP_SIZE,
- BY_DEFAULT(CAPTURE_SIZE_1920_2560),
- CAPTURE_SIZE_960_1280, CAPTURE_SIZE_1200_1600,
- CAPTURE_SIZE_1536_2048,CAPTURE_SIZE_1920_2560
- ) ; j7 z$ e$ \' z1 n3 S* k
/ C0 @: k$ j% b7 R" D) q
3 k9 e( E8 j/ m我试过做上面的修改,但打开摄像头的时候,提示”Unfortunately, Camera has stopped” 本文作者:LoongEmbedded; M _# V/ M) ^% ~# Q# Z* }1 F
/ r9 k6 D4 Y1 W. x
|