1 ~% a; j/ v% T& M. w$ A' `
图1 # V, Y" X" X& X; A7 G
1. Camera拍照相关概念 1.1 ISP
" d' o* h p4 H8 g0 qisp——(Image Signal Processor)——影视处理 5 Y7 X1 B1 K3 ?; `
无论数码相机、摄像机或者摄像手机,其影像数据从前端感应后,皆须经过ASP(Analog Signal Processing)、ADC(Analog-Digital Converter)、前期影像处理(Pre-ISP)与后端影像处理(Post-ISP)四个阶段后,影像数据才能最终呈现于终端设备上 + ~% y6 i8 X8 m. T n. p
1.2 720p 720P是美国电影电视工程师协会(SMPTE)制定的高等级高清数字电视的格式标准,有效显示格式为:1280×720.SMPTE(美国电影电视工程协会)将数字高清信号数字电视扫描线的不同分为1080P、1080I、720P(i是interlace,隔行的意思,p是Progressive,逐行的意思)。720P是一种在逐行扫描下达到1280×720的分辨率的显示格式。是数字电影成像技术和计算机技术的融合。 3 \ N3 n+ S) \) O( H6 `6 A
分辨率为1280×720p/60Hz,行频为45kHz ! ?' `& j! W7 G6 A: T/ }
$ u/ N8 n2 J, t/ N" K+ u
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)这些特征,用于图像处理。
& _& u( q" ~5 M) z) {2.2 camera特征
- m0 A1 w3 s$ y( @3 nMT6577内部集成的ISP,包含了一个功能强大的图像信号处理器,用于连接各种各样的图像传感器模组,这个处理器由时序产生单元(timing generated unit: TG)、镜头/传感器补偿(lens/sensor compensation)单元和图像处理单元。 ! d, S' `- U/ W4 I/ m8 Q. R
支持的特征如下: (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)。
& T, r4 A( ~+ ?4 L! k(6) 3A统计和校正(statistics and correction) (7) 闪烁检测(flicker detection)。
. x7 j+ y( ~ B' c2.3 camera框图
1 f2 x. N& s: t: f图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)单元。
- W4 D4 q* ?! q, C8 T在Bayer原始数据输入模式,镜头/传感器补偿(lens/sensor compensation)单元产生补偿的原始数据给色彩处理单元(color process unit);在YUV422/RGB565 输入模式,这步被忽略。
3 b, g4 |: L. V$ R0 Y: c色彩处理单元接受来之镜头/传感器补偿(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读取出来。
7 u- o+ G: F( M( @% M( g) }下面给出一些性能参数:
/ Y8 ?- q5 y6 Y, w" G6 _" r: h a图3 - L7 E+ |" z$ p ~( D- S9 R
3. 原理图设计
6 |5 Y- v6 l4 b% g UMT6577支持两路camera接口,一路是MIPI接口,一路是并行接口,这里我们采用的是并行接口,下面给出MT6577 CAM并行接口定义:
7 q( @# a# L5 d4 w( p; b" M2 h. \
图4 Camera sensor连接座如下:
8 P9 }. W; |% \; \- t( x! D/ k: j图5
3 S+ @7 H. Z9 r& H' E, H(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位。如下图:
. ~5 F2 ?; ?/ s图6 2 w' V$ e# Q4 Y8 r% O* u
y+ C' }% ~* |! l1 B' ~! q: O(2) OV5640IIC地址 & h% a' W( y8 F' V/ D: h8 f
IIC 8bit写地址为0x78,读地址为0x79,查询Sensor规格书可以看到:
; O# o4 S+ o" c图7 IIC 8bit地址最后一位为0时是写地址,为1时是读地址。这属于IIC通讯规则
% W U) u! e/ T3 M
+ j1 R4 |: l1 [ Z# I$ j4 M* y1 n9 d" m5 w" ^: F Z% n, P' _ g& x
4. 驱动实现 , E- P$ g4 U* O0 l3 ?( j2 ?' X9 X
* s+ e" L0 e$ D, g4.1 相关代码 (1) CameraSensor驱动相关文件 \mediatek\custom\common\kernel\imgsensor\ov5642_yuv % i2 b- O, a* W/ l9 n4 C4 O& M
(2) SensorID和一些枚举类型的定义 \mediatek\custom\common\kernel\imgsensor\inc kd_imgsensor.h---------SensorID kd_imgsensor_define.h--------------一些枚举类型的定义 # j, j. Z5 ?! \8 N3 L+ i6 ?
(3) Sensor供电 \mediatek\custom\common\kernel\camera\camera kd_camera_hw.c和kd_camera_hw.h
: |* r- f! \4 a3 ]' k$ o: F Y4 k(4) KernelSpace的SensorList,imgsensor模块注册 \mediatek\custom\common\kernel\imgsensor\src kd_sensorlist.c和kd_sensorlist.h-----------camera模块加载
3 W( [- V& i, l& L1 o/ u. a(5) UserSpace的SensorList,向用户空间提供支持的SensorList \mediatek\custom\common\hal\imgsensor\src\sensorlist.cpp 提供给用户空间的SensorList
; M) f4 k9 e' q; E a$ z
5 j- [+ _2 _7 W) ?(6) Sensor效果调整的接口 \mediatek\custom\common\hal\imgsensor\ov5642_yuv
. V3 _# r# l4 g- v6 H) A! g& }
4 `9 h4 f! q0 o' U4.2 针对OV5640的修改 6 a c* u3 L. k/ S
4.2.1 mediatek\config\hsimobile77_ics2\ProjectConfig.mk
# W4 i: b0 a+ D( e9 eCUSTOM_KERNEL_IMGSENSOR=mt9p017_rawgc0329_yuv mt9p017_raw表示后置摄像头(也就是主摄像头),mt9p017是摄像头sensor驱动IC,raw是sensor一种输出的数据格式,是CCD或CMOS在将光信号转换为电信号时的电平高低的原始记录,单纯地没有将没有进行任何处理的图像数据,即摄像元件直接得到的电信号进行数字化处理而得到的。
7 w6 k$ L: P! [# S mgc0329_yuv是前置摄像头,yuvsensor一种输出的数据格式,支持YUV/RGB格式的模组,一般会带有ISP(image single processor),经过A/D转换过的原始数据经过ISP处理生成YUV标准格式传到BB。 # ]' n+ E2 S, v
我们采用的OV5640就带有ISP,输出YUV格式
( J! J+ R4 Z5 o0 ?. L(1) 把mt9p017_raw 改为ov5640_yuv,去掉gc0329_yuv因为我们的产品没有后置摄像头 (2) 去掉类似CUSTOM_KERNEL_LENS后面的dummy_lens因为没有后置摄像头 3 s% b! e. S9 f1 ] ? E. l( d
修改之后的HAL层的配置: 6 S5 Z$ k9 l( q' m2 d, [, W
- 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
& f9 \$ L1 J' U% B+ J* e 2 J6 g% k/ d. ]9 t0 k7 R+ {4 {. D
* w, s" i* [* h: v6 E# f4 L1 B* d2 n# H
修改之后的kernel层的配置:
7 I8 j9 v5 s o8 N- 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 , N& E5 I# r" q% s. |1 [; F
# h2 l9 P1 Y0 b
/ Y. _; t* N C
k! t8 Y8 N" s7 T
* H4 ?/ k" W/ @, p9 m z虽然我们没有后置摄像头,但不能去掉dummy_lens,我尝试过去掉之后用./mk r dr编译会提示下面的错误: # z; r, X6 |& f* O3 e8 l( V
" A: E6 X; F8 W7 {6 H( Q- 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
* {3 V1 |5 b t1 k( T2 K
3 H. L G* V/ t/ E
8 X* u2 @/ ~( N
) h1 |& X# i0 B: h/ k9 w9 C! I3 B/ i) o
4.2.2 mediatek\custom\common\kernel\imgsensor----------kernel层 7 R, |3 O8 a; @ s8 N+ `
(1) 创建ov5640_yuv并建立需要的文件
0 N0 A. o! ~: k1 I' `. [8 {创建文件夹ov5640_yuv,把sensor IC厂家提供的ov5640yuv_Sensor.c放到此目录下。另外拷贝ov5642yuv_Sensor.h、ov5642yuv_Camera_Sensor_para.h、ov5642yuv_CameraCustomized.h拷贝过来改为ov5640yuv_Sensor.h等。 $ {( }# C/ C5 e& Y9 E C; z
编译发现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是没有这几个宏定义,我暂时定义如下: ; n+ _! Z1 f& |* c8 k; D3 {
. Y2 J. o8 Z7 h6 p; j+ g
- //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
" r. ^& o* k% K# T! c, a5 B
+ W- p1 g- p( F ]2 p9 u6 p. ?4 K( O- V* {2 _
- s3 C' ~" g# k% \7 Y! ^
这是参考ov5642的相关定义来定义的。 4 c. @, ~! `/ U0 P: N% }1 F
(2) 在支持的sensor列表中增加目标sensor : k& V$ b* Y6 ]
mediatek\custom\common\kernel\imgsensor\src\kd_sensorlist.h 在数组增加OV5640的内容,如下: - Z1 q4 i3 K0 k. z4 P7 P: d
6 S# U- ?1 e& G K7 E- 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
- …………….
- }
0 t) U6 l1 z* E ]0 r1 X; e# m, j1 B* s3 N
3 A, ^: U8 c+ B7 V2 Z7 @
/ j0 V2 L" ], l: Z
1 [* }* H& ]8 o( L) l3 _7 r, m也增加UINT32 OV5640_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT*pfFunc); mediatek\custom\common\kernel\imgsensor\inc\kd_imgsensor.h (3) 增加sensor ID和字符串的定义
/ B. ~) m( X2 I; d$ L, ^
' K5 L1 d+ `. k- #defineOV5640_SENSOR_ID 0x5640
- #defineSENSOR_DRVNAME_OV5640_YUV "ov5640yuv"
1 ]5 N8 z/ x0 {/ ~4 @
4 x& F3 v- X8 B4 W1 B% P
* R# o2 P+ S" Z6 E" Q
0 h; g5 \( }! @8 f4.2.3 mediatek\custom\common\hal\imgsensor---------------HAL层 " a4 Q8 |. i. B' z
(1) 创建ov5640_yuv文件夹 但这些文件夹下该有哪些文件,有需要哪些内容了,首先我对比了 ov3640_yuv和ov5642_yuv文件夹,只有cfg_ftbl_ov5642_yuv.h有差别:
图8
' k% y w6 q: R这里主要是不同驱动IC支持的分辨率不同,以及设置默认的分辨率。
图9
5 ?: |+ Z2 Q# |1 M$ N; k' x' n, c此文件下有两个这样的地方不同,这里是指自动对焦模式。 2 s- u6 Y! C' ]( I2 B( `' T
因为我们的OV5640和OV5642非常接近,所以就直接把OV5642的目录复制过来修改为OV5640即可。 ( S$ D/ B' h. G% r k. T
所以把mediatek\custom\common\kernel\imgsensor\ov5642_yuv拷贝到imgsensor目录下,改为ov5640_yuv ) ]3 d! e' K' ]) h1 p9 N. s, X
(2) 在支持的sensor列表中增加目标sensor
7 `; Q5 y. |/ U# j+ T8 g\src\ sensorlist.cpp
" T1 w4 }- b1 V$ i9 r. d/ I1 \" h( d8 b- W
- MSDK_SENSOR_INIT_FUNCTION_STRUCTSensorList[] =
- {
- ………..
- #ifdefined(OV5640_YUV)
- YUV_INFO(OV5640_SENSOR_ID,SENSOR_DRVNAME_OV5640_YUV, NULL),
- #endif
- …………
- } 2 F9 a* n0 J# M; j5 r4 G' W/ J
5 v6 }/ Z& _: C0 d1 C8 U
* p# \# `6 R" S9 V3 |" \% G/ C4 U" M0 Y( c- g- l+ Z
注意:在 kd_SensorList.h 和 SensorList.cpp 里面添加驱动的时候要注意,Sensor 添加的位置要一样。否则驱动会跑乱,轻则 ISP 参数不对,重则 Sensor 无法启动。 " e; M) A3 X1 Q& |' Y! R
; d% r, A+ M8 n4 ~1 n8 w7 _
4.3 拍照图片尺寸设置 # a0 Z2 A$ q- f0 J3 X; r8 t
mediatek\custom\common\hal\imgsensor\ov5640_yuv\cfg_ftbl_ov5640_yuv.h 1 q% l' ^5 e& e7 x5 n8 k, f3 M, v
! Q% r9 D& L8 |8 Y) e+ z# x
- P6 w* [/ K7 ^% K1 s
- // 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
- )
+ c9 q1 ~' S6 X+ `# N* U9 [" t. K3 {) A; I
. D+ d8 m% T" t. W2 ~5 C
3 L3 v0 m# g3 ~5 l0 p0 A4.4 Camera物理角度旋转 Cfg_setting_imgsensor.h
) A/ m I: J8 T/ w
& P$ b+ n1 P& S$ r- k2 k6 F- /*******************************************************************************
- * 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;
- } 9 ^+ ~* m4 Z1 A/ y* p) X8 c
9 |# P/ W, K1 [4 F1 U
6 H e% G& @' K$ p+ _+ `. B
6 J1 P% Z/ m; F) Y+ `
) V8 ]& D, h# a8 p( n- y1 k/ }
这几种都试过了,但都不行,预览和实际的都是成某种镜像关系。这是平台是提供旋转的功能。这个配置好了之后,如果方向不正确,可以通过驱动中的方向调整函数进行调整,如下: static void XXXXXSetMirror(kal_uint16ImageMirror) 参考:http://blog.csdn.net/loongembedded/article/details/41679977
# Z" w8 J. _7 K# Z: Q, m' s! S6 [8 F: q! O9 b9 f j2 }/ N. X; `. b
1 z9 Z" E& Y% G' [6 n 看了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)却问题依旧,很奇怪。 . q6 Y, @: F- d @
mediatek\custom\common\hal\imgsensor\ov5640_yuv\cfg_ftbl_ov5640_yuv.h
2 J- v; T9 e% D) ~2 a* \- /*
- // 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
- )
. }$ x1 T$ V; |$ D3 M
$ h- `6 K3 _. g5 T* s, D6 B; Z3 @: ^
我试过做上面的修改,但打开摄像头的时候,提示”Unfortunately, Camera has stopped” 本文作者:LoongEmbedded: Z) n0 | ^ I4 ]! i
2 k; z2 w% y/ H3 R( o8 z |