' @+ X/ J8 d6 R
图1 " ~# a% H# k( D5 N5 i
1. Camera拍照相关概念 1.1 ISP
0 I+ m, M6 }* j9 m' D) {$ q8 B( wisp——(Image Signal Processor)——影视处理
0 Q) v0 B: z& V0 m1 z$ m& P+ w# [; r* J无论数码相机、摄像机或者摄像手机,其影像数据从前端感应后,皆须经过ASP(Analog Signal Processing)、ADC(Analog-Digital Converter)、前期影像处理(Pre-ISP)与后端影像处理(Post-ISP)四个阶段后,影像数据才能最终呈现于终端设备上 6 j+ u/ f. @0 c9 _& s& A2 _
1.2 720p 720P是美国电影电视工程师协会(SMPTE)制定的高等级高清数字电视的格式标准,有效显示格式为:1280×720.SMPTE(美国电影电视工程协会)将数字高清信号数字电视扫描线的不同分为1080P、1080I、720P(i是interlace,隔行的意思,p是Progressive,逐行的意思)。720P是一种在逐行扫描下达到1280×720的分辨率的显示格式。是数字电影成像技术和计算机技术的融合。
& w& s) v4 o7 P3 ~3 ?- U1 K; }% T分辨率为1280×720p/60Hz,行频为45kHz
! a* L; [& _- M4 w( s
6 V" A9 i/ W' I8 G2. 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)这些特征,用于图像处理。 2 B) I8 s' F# q+ P! ]; H- _
2.2 camera特征
c% D& k% Z; A& c1 H7 |% HMT6577内部集成的ISP,包含了一个功能强大的图像信号处理器,用于连接各种各样的图像传感器模组,这个处理器由时序产生单元(timing generated unit: TG)、镜头/传感器补偿(lens/sensor compensation)单元和图像处理单元。
7 P# _# J2 d6 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)。 / y/ V" `! g7 g7 ]" ~' A u; X
(6) 3A统计和校正(statistics and correction) (7) 闪烁检测(flicker detection)。 , V& I: ]9 K) r0 ]8 ^( f
2.3 camera框图
' J0 R Q; f2 t) `7 {; ?
图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)单元。
; H4 H1 v5 R0 f3 g# r7 K2 u在Bayer原始数据输入模式,镜头/传感器补偿(lens/sensor compensation)单元产生补偿的原始数据给色彩处理单元(color process unit);在YUV422/RGB565 输入模式,这步被忽略。
/ W2 ?3 F' ^4 p- L+ s色彩处理单元接受来之镜头/传感器补偿(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读取出来。 2 H8 H# H" ~. A i/ @4 O. A" y
下面给出一些性能参数:
6 ~% |; \9 T; j- F7 L
图3
+ I8 P, u" B% s3 H* M7 z7 f j3. 原理图设计
- _% f0 x6 H; v4 G( Q0 q7 MMT6577支持两路camera接口,一路是MIPI接口,一路是并行接口,这里我们采用的是并行接口,下面给出MT6577 CAM并行接口定义:
# ]6 A- R* r3 n" v$ }图4 Camera sensor连接座如下:
' a7 d6 Q! J# ~4 U- Z8 q! x图5 0 r5 E. a2 w$ {! J/ R4 g
(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位。如下图:
4 ~9 B1 b j' d. V2 }9 J. S图6 + L. _1 S- S2 g& i) Y) R
7 @2 w) B) k$ w6 h- }6 e(2) OV5640IIC地址
& a0 F# E$ N3 j" o- o8 jIIC 8bit写地址为0x78,读地址为0x79,查询Sensor规格书可以看到:
. i; \( P) f; I3 t5 K2 c! M' i& V图7 IIC 8bit地址最后一位为0时是写地址,为1时是读地址。这属于IIC通讯规则 1 z. Y: I/ O+ s d# |/ c; m3 V
! t @- a" q# q. E0 y% |; z& X$ l
( r, Q/ J/ ]" v7 P, d
4. 驱动实现 t% t$ O/ v' d+ l4 w) k6 C
, I* E% S: i' ?
4.1 相关代码 (1) CameraSensor驱动相关文件 \mediatek\custom\common\kernel\imgsensor\ov5642_yuv
# ^7 o6 x% ~' t2 T6 B; L/ }/ [(2) SensorID和一些枚举类型的定义 \mediatek\custom\common\kernel\imgsensor\inc kd_imgsensor.h---------SensorID kd_imgsensor_define.h--------------一些枚举类型的定义
, B2 x' T$ Q1 n! g+ W9 i, h(3) Sensor供电 \mediatek\custom\common\kernel\camera\camera kd_camera_hw.c和kd_camera_hw.h
' s4 F3 ~6 a8 u- L(4) KernelSpace的SensorList,imgsensor模块注册 \mediatek\custom\common\kernel\imgsensor\src kd_sensorlist.c和kd_sensorlist.h-----------camera模块加载 - m4 I9 E2 A8 J0 q* |
(5) UserSpace的SensorList,向用户空间提供支持的SensorList \mediatek\custom\common\hal\imgsensor\src\sensorlist.cpp 提供给用户空间的SensorList
6 b8 `5 ~! J* s+ n# b. {* X6 R& H9 M" W2 g$ R4 y
(6) Sensor效果调整的接口 \mediatek\custom\common\hal\imgsensor\ov5642_yuv # I6 k3 v g% g! p. h% {( Z, p! W
8 j7 P8 a- ?1 e: `: _/ F4.2 针对OV5640的修改
' V; z* k, M' Z0 F* E4.2.1 mediatek\config\hsimobile77_ics2\ProjectConfig.mk ; A5 [2 [( J, k+ q; ?) a7 P
CUSTOM_KERNEL_IMGSENSOR=mt9p017_rawgc0329_yuv mt9p017_raw表示后置摄像头(也就是主摄像头),mt9p017是摄像头sensor驱动IC,raw是sensor一种输出的数据格式,是CCD或CMOS在将光信号转换为电信号时的电平高低的原始记录,单纯地没有将没有进行任何处理的图像数据,即摄像元件直接得到的电信号进行数字化处理而得到的。
$ x. A: p" `8 A/ L, dgc0329_yuv是前置摄像头,yuvsensor一种输出的数据格式,支持YUV/RGB格式的模组,一般会带有ISP(image single processor),经过A/D转换过的原始数据经过ISP处理生成YUV标准格式传到BB。
0 p" W! b G2 N8 i# s. X4 M/ _) z我们采用的OV5640就带有ISP,输出YUV格式
# h5 T5 f, u2 |4 Z( X9 B% h Y(1) 把mt9p017_raw 改为ov5640_yuv,去掉gc0329_yuv因为我们的产品没有后置摄像头 (2) 去掉类似CUSTOM_KERNEL_LENS后面的dummy_lens因为没有后置摄像头 ) y- }' @* U9 N( G: K# _# C
修改之后的HAL层的配置:
8 Y/ R' D i1 w& e! F1 F$ Z- 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
& U; U3 u' ^0 n7 T+ k1 D 4 l9 r- T4 _% Z1 z
g$ a! R, q; T7 K% X. t1 A1 V+ h8 |" z# E! T U9 c" ^# e. ~ v
修改之后的kernel层的配置: 9 p& P! Q9 [; T, ]% {* o5 v
- 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
- u) ]/ }. T+ F 2 n- a' i x* S
, j2 M' r5 W8 b
* l. H2 M; Y1 s; @
2 m6 p# R" d, P- R虽然我们没有后置摄像头,但不能去掉dummy_lens,我尝试过去掉之后用./mk r dr编译会提示下面的错误:
- U/ n; Y1 i3 `! o1 r- I! r" x, M, P- e( a4 x
- 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
0 B% ~2 E+ E9 E5 H# r 4 b* E) k% q" C7 W, D6 k( E5 a) J+ L
! O; G! l: @; s& \* h' b) `
1 M4 A6 U' D' g; y$ i: F# c
3 a. K% g! ~, ?# J7 O5 C
4.2.2 mediatek\custom\common\kernel\imgsensor----------kernel层 + G ~* p$ \( K
(1) 创建ov5640_yuv并建立需要的文件 % Q$ N, _/ ]# F$ Y3 W: S1 o1 d% ^
创建文件夹ov5640_yuv,把sensor IC厂家提供的ov5640yuv_Sensor.c放到此目录下。另外拷贝ov5642yuv_Sensor.h、ov5642yuv_Camera_Sensor_para.h、ov5642yuv_CameraCustomized.h拷贝过来改为ov5640yuv_Sensor.h等。
8 n3 t# ~* w5 S0 ?7 H( z l) g编译发现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是没有这几个宏定义,我暂时定义如下:
8 C( g9 }& R, V& H( o. D$ x. x q* c/ y
- //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 f/ g! c+ u" K" P7 s& F
: k) F- M- Y& `
5 e* x# J4 w5 O% V9 k# h1 C& W8 [
4 w9 u+ f; n4 J2 d" r3 ^; P+ a这是参考ov5642的相关定义来定义的。 8 f' f+ B* Y, U5 \7 ? X# B
(2) 在支持的sensor列表中增加目标sensor
' W" p9 q# A# L, ~( {4 tmediatek\custom\common\kernel\imgsensor\src\kd_sensorlist.h 在数组增加OV5640的内容,如下:
2 J7 B+ @! R/ Y) Z+ C
: y& l3 }, p4 f5 t2 \: y7 B) [- 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
- …………….
- }
6 B8 [8 E- [; y( D( e# ^& K
5 v" s8 {3 U/ Y8 ~( Z2 H, P
+ h6 w; a1 F3 ]! {3 P# b
" {1 v4 F7 S) [3 q! s" d! \$ b D8 n! Q& a1 `6 x2 ]# D# a" B
也增加UINT32 OV5640_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT*pfFunc); mediatek\custom\common\kernel\imgsensor\inc\kd_imgsensor.h (3) 增加sensor ID和字符串的定义 & w, c! m, e9 {- Q# m1 s( T; z
; W3 l( A1 u# T; X& D" E8 [- #defineOV5640_SENSOR_ID 0x5640
- #defineSENSOR_DRVNAME_OV5640_YUV "ov5640yuv"
- p- v8 C7 b9 n : u8 V' }) a. T# [7 Y
9 s' G" B4 @6 O0 v! b* G% O# @0 H
2 k$ d6 A U+ ~* {$ q4.2.3 mediatek\custom\common\hal\imgsensor---------------HAL层
1 K/ C/ z6 N4 m" x& [& i2 ~/ S(1) 创建ov5640_yuv文件夹 但这些文件夹下该有哪些文件,有需要哪些内容了,首先我对比了 ov3640_yuv和ov5642_yuv文件夹,只有cfg_ftbl_ov5642_yuv.h有差别:
图8 7 ~: R }. A2 S$ W" O( [
这里主要是不同驱动IC支持的分辨率不同,以及设置默认的分辨率。
图9 4 a+ i: g6 w+ e3 K% D
此文件下有两个这样的地方不同,这里是指自动对焦模式。
1 @: P' q2 K- ]+ c" K, d因为我们的OV5640和OV5642非常接近,所以就直接把OV5642的目录复制过来修改为OV5640即可。
3 s3 l$ Z" Y) }2 _所以把mediatek\custom\common\kernel\imgsensor\ov5642_yuv拷贝到imgsensor目录下,改为ov5640_yuv
7 m% w. `+ g% \. U(2) 在支持的sensor列表中增加目标sensor
8 O3 D6 p4 Q. T, m- q( t/ K8 z\src\ sensorlist.cpp 8 T o5 n8 f m3 S" e
, D; g( l& N6 V4 X& @
- MSDK_SENSOR_INIT_FUNCTION_STRUCTSensorList[] =
- {
- ………..
- #ifdefined(OV5640_YUV)
- YUV_INFO(OV5640_SENSOR_ID,SENSOR_DRVNAME_OV5640_YUV, NULL),
- #endif
- …………
- } |# A6 Z, I- `. X* H0 M
1 q! m' e7 A' X: a% v* ?
+ W0 U7 j! a' Q0 L
3 u7 W2 m- X, T/ g+ S' o注意:在 kd_SensorList.h 和 SensorList.cpp 里面添加驱动的时候要注意,Sensor 添加的位置要一样。否则驱动会跑乱,轻则 ISP 参数不对,重则 Sensor 无法启动。
* K0 O3 _% O& i* {9 T8 N8 X3 e* q+ \- u1 @3 L! \
4.3 拍照图片尺寸设置 8 A4 x9 A, h" |4 Z7 S
mediatek\custom\common\hal\imgsensor\ov5640_yuv\cfg_ftbl_ov5640_yuv.h
6 g. h7 h$ o& _6 E% o4 J$ d5 u* e2 y) m9 A. S( W( H0 H' Q
' }) I+ p) y: a* P
- // 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
- ) 6 \: C- n. O# Q6 G
0 G7 W5 V! v# b7 Q
& G( Z( ]" {) L( f: i; R
& u" `& ^* h& q/ F8 t4.4 Camera物理角度旋转 Cfg_setting_imgsensor.h : h5 | \% t3 K0 A* h
# }$ B6 @( E; s5 \8 W* Y
- /*******************************************************************************
- * 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;
- }
% e+ s }, l3 E# ^* @5 O) m: ^; E1 d( A9 Y) _! [/ N
" n- R0 K& `& o1 W
: w% }9 F0 V0 U, w" n0 m5 ~ n
4 w5 K4 d# y) T
这几种都试过了,但都不行,预览和实际的都是成某种镜像关系。这是平台是提供旋转的功能。这个配置好了之后,如果方向不正确,可以通过驱动中的方向调整函数进行调整,如下: static void XXXXXSetMirror(kal_uint16ImageMirror) 参考:http://blog.csdn.net/loongembedded/article/details/41679977
6 K" j* ~% X! ^, z/ H/ f U8 ? @ ]/ g9 R
9 C4 o- D! Q( n4 y5 E4 {
看了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)却问题依旧,很奇怪。
5 }1 T2 h2 ]/ Q& [3 D, d6 p6 smediatek\custom\common\hal\imgsensor\ov5640_yuv\cfg_ftbl_ov5640_yuv.h
: S, u, w' i' f% x; 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
- )
" P z6 \5 j) o ^+ S " ^, f3 q6 M! W0 \& _, V: S2 M# Y9 R
: g+ S7 S* x/ v P0 ]0 V我试过做上面的修改,但打开摄像头的时候,提示”Unfortunately, Camera has stopped” 本文作者:LoongEmbedded
9 m0 F% D7 J& O
( k; Q/ \& K- E3 h |