|
( {4 X( ]" i4 K( u, Z图1 ' |( \5 g8 n# t- k$ T4 @# U
1. Camera拍照相关概念 1.1 ISP
2 u. G' F; ^4 d% Hisp——(Image Signal Processor)——影视处理 8 I& n; l& z+ l1 M8 u2 A" F: o* t
无论数码相机、摄像机或者摄像手机,其影像数据从前端感应后,皆须经过ASP(Analog Signal Processing)、ADC(Analog-Digital Converter)、前期影像处理(Pre-ISP)与后端影像处理(Post-ISP)四个阶段后,影像数据才能最终呈现于终端设备上
, m3 e& y7 A& }# p. s1.2 720p 720P是美国电影电视工程师协会(SMPTE)制定的高等级高清数字电视的格式标准,有效显示格式为:1280×720.SMPTE(美国电影电视工程协会)将数字高清信号数字电视扫描线的不同分为1080P、1080I、720P(i是interlace,隔行的意思,p是Progressive,逐行的意思)。720P是一种在逐行扫描下达到1280×720的分辨率的显示格式。是数字电影成像技术和计算机技术的融合。
5 x1 D9 C, h' ~) R' y, I分辨率为1280×720p/60Hz,行频为45kHz % a5 w* m, E2 [
# G1 z H# d! ^/ l2. 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)这些特征,用于图像处理。
# H3 r: t' }8 I1 m& e# d$ P _2.2 camera特征
% q# R8 z1 } W0 U. y& G: {$ {MT6577内部集成的ISP,包含了一个功能强大的图像信号处理器,用于连接各种各样的图像传感器模组,这个处理器由时序产生单元(timing generated unit: TG)、镜头/传感器补偿(lens/sensor compensation)单元和图像处理单元。 . C6 Q! t) u6 o h: J
支持的特征如下: (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)。 . i' w1 W5 k0 l' U' ]6 p$ |) j3 k2 N
(6) 3A统计和校正(statistics and correction) (7) 闪烁检测(flicker detection)。
- H1 k- Q o$ ]+ K2.3 camera框图
- J: I% U; P9 @ X) U+ ]图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)单元。
( U: D, p( y" e" ]在Bayer原始数据输入模式,镜头/传感器补偿(lens/sensor compensation)单元产生补偿的原始数据给色彩处理单元(color process unit);在YUV422/RGB565 输入模式,这步被忽略。
" E d" B9 N4 K. h0 V$ Q色彩处理单元接受来之镜头/传感器补偿(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读取出来。
P3 Y2 T3 h/ P5 O1 {' u6 X: x下面给出一些性能参数:
$ S: N* M9 O( d( z7 z5 n图3 1 U+ c6 ]$ a' I/ X* {! Z
3. 原理图设计
' o% L3 ~" L, c$ o9 N+ tMT6577支持两路camera接口,一路是MIPI接口,一路是并行接口,这里我们采用的是并行接口,下面给出MT6577 CAM并行接口定义:
& {/ Q( c: e5 W; O; L% e; ?$ [/ w
图4 Camera sensor连接座如下:
G2 B+ f4 \: i: z7 J9 f+ @图5 ; R3 _5 Q& u+ Y
(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位。如下图:
, ^) u" S1 j2 ]9 K1 g/ U图6
0 E/ o' R5 y5 E% N
- [ m$ a7 N2 O7 v(2) OV5640IIC地址
* h: N. t+ t* h5 H5 ?6 o* |, Z: PIIC 8bit写地址为0x78,读地址为0x79,查询Sensor规格书可以看到:
# f. t; Y* d: V) R3 M' u+ R
图7 IIC 8bit地址最后一位为0时是写地址,为1时是读地址。这属于IIC通讯规则
3 C6 Q" ?, G6 p, H f
. h5 \8 a. @$ u# I" P3 }7 {% {
4. 驱动实现 , n3 Z2 ], u& _! K
( x# W6 P8 n) W1 | F4.1 相关代码 (1) CameraSensor驱动相关文件 \mediatek\custom\common\kernel\imgsensor\ov5642_yuv : M; g8 b. W' |+ I) Y
(2) SensorID和一些枚举类型的定义 \mediatek\custom\common\kernel\imgsensor\inc kd_imgsensor.h---------SensorID kd_imgsensor_define.h--------------一些枚举类型的定义
|( ?* a. R. `(3) Sensor供电 \mediatek\custom\common\kernel\camera\camera kd_camera_hw.c和kd_camera_hw.h
: O/ C" ]& U x( N9 Q& ^(4) KernelSpace的SensorList,imgsensor模块注册 \mediatek\custom\common\kernel\imgsensor\src kd_sensorlist.c和kd_sensorlist.h-----------camera模块加载
8 l8 b z4 h5 C8 V% e8 t) ~' }# E7 p(5) UserSpace的SensorList,向用户空间提供支持的SensorList \mediatek\custom\common\hal\imgsensor\src\sensorlist.cpp 提供给用户空间的SensorList
, |6 V+ e2 Y2 D6 x0 ]; _4 {' g
$ N- K, T$ x7 }% B2 F( p9 j(6) Sensor效果调整的接口 \mediatek\custom\common\hal\imgsensor\ov5642_yuv 0 J4 J# q0 H+ @9 `; j# \2 B
' `/ z( M' N$ g. n
4.2 针对OV5640的修改
- S+ v/ f( K# x" ~% ]4.2.1 mediatek\config\hsimobile77_ics2\ProjectConfig.mk 2 M5 b3 D- d! e% C: m! P
CUSTOM_KERNEL_IMGSENSOR=mt9p017_rawgc0329_yuv mt9p017_raw表示后置摄像头(也就是主摄像头),mt9p017是摄像头sensor驱动IC,raw是sensor一种输出的数据格式,是CCD或CMOS在将光信号转换为电信号时的电平高低的原始记录,单纯地没有将没有进行任何处理的图像数据,即摄像元件直接得到的电信号进行数字化处理而得到的。
$ m* M* v1 p+ C+ s. l& @& p) h( w: \gc0329_yuv是前置摄像头,yuvsensor一种输出的数据格式,支持YUV/RGB格式的模组,一般会带有ISP(image single processor),经过A/D转换过的原始数据经过ISP处理生成YUV标准格式传到BB。 8 e- l' g. n+ v1 ~8 E7 K, L
我们采用的OV5640就带有ISP,输出YUV格式 0 H1 m2 I; v/ S; B! {
(1) 把mt9p017_raw 改为ov5640_yuv,去掉gc0329_yuv因为我们的产品没有后置摄像头 (2) 去掉类似CUSTOM_KERNEL_LENS后面的dummy_lens因为没有后置摄像头 7 Y- J" ^% \. \1 X9 z9 V! }
修改之后的HAL层的配置:
# R0 J8 p% m8 c7 O5 f* x& z* J: G- 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
2 n7 ~( Z8 t+ \5 _( t& s, _) ? " e# f" e* _* h
. \* e0 u& X- P8 j* c" l: L
; G! l; K" c# P修改之后的kernel层的配置:
' ^: f3 X0 W, P( l' }7 c% ]: s- 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 ; e' |) @) O, p
3 N. U D1 T) E9 z2 O
* L3 h! D: z. a+ E5 m& v
& s+ O! ^% f( G+ d" F2 R1 C& [% V, s, N$ ~5 b
虽然我们没有后置摄像头,但不能去掉dummy_lens,我尝试过去掉之后用./mk r dr编译会提示下面的错误: $ d1 w5 s/ n! r- S1 x* M. C
. Z" Z3 z6 M/ \% b
- 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 + P) V) ?1 ~6 x6 b$ n
+ ?1 k7 |( c2 t. ?+ [( M& y$ @
* ?/ }7 ~: i8 _: Z/ U
0 A0 _" ], b2 I$ }* Y. Q' Q+ S4 R# \7 ^9 w4 v
4.2.2 mediatek\custom\common\kernel\imgsensor----------kernel层 0 h) ^$ Y% _8 o
(1) 创建ov5640_yuv并建立需要的文件 9 {' C4 ^8 c7 d& c8 l# b/ a- ?( P1 s
创建文件夹ov5640_yuv,把sensor IC厂家提供的ov5640yuv_Sensor.c放到此目录下。另外拷贝ov5642yuv_Sensor.h、ov5642yuv_Camera_Sensor_para.h、ov5642yuv_CameraCustomized.h拷贝过来改为ov5640yuv_Sensor.h等。
. h$ _" x6 M3 H: S. n编译发现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是没有这几个宏定义,我暂时定义如下: + J: ~* K0 s+ r7 ?
Y) r1 q/ F7 N9 X( _0 x, E
- //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 & ?( L, O, t6 w0 f2 V, @2 j
5 X, J" H: N) o! I8 `! }1 y8 ]
+ P2 ^2 o3 i6 f* N; C
7 H& |' t6 F+ n. x. ]5 H5 O这是参考ov5642的相关定义来定义的。
9 h* x: g. c# N5 Z" j1 J(2) 在支持的sensor列表中增加目标sensor
' A' g4 \, P4 M% P) R/ }mediatek\custom\common\kernel\imgsensor\src\kd_sensorlist.h 在数组增加OV5640的内容,如下: 6 S' k8 V) t% K C8 O3 z
1 `. w2 ^& E' S$ O& H* Q$ F4 o- 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
- …………….
- }
/ Y- M* h- D! g8 q; v6 u" f# C! Z4 ~
7 B, r8 R u) a1 o ; y! z0 ^8 p0 ~- k- @ p/ e6 y
9 c3 E3 u9 A; N; ?# k; |
2 U1 j$ ?# k; I4 _/ @* _4 f; M4 P4 `
也增加UINT32 OV5640_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT*pfFunc); mediatek\custom\common\kernel\imgsensor\inc\kd_imgsensor.h (3) 增加sensor ID和字符串的定义
5 A9 T0 I8 L1 Q" b0 Z" ^& v) R# n1 t; I( r( Y
- #defineOV5640_SENSOR_ID 0x5640
- #defineSENSOR_DRVNAME_OV5640_YUV "ov5640yuv" / n( ^7 ^! G) f9 P
+ U- e" l: t& n% J/ k( o* m
# T3 P) L3 F0 ^" d) B4 I$ p. p
4 P7 o# P7 m( M; p, W4.2.3 mediatek\custom\common\hal\imgsensor---------------HAL层
6 A8 W* O6 W- D3 W5 I/ i. G+ w(1) 创建ov5640_yuv文件夹 但这些文件夹下该有哪些文件,有需要哪些内容了,首先我对比了 ov3640_yuv和ov5642_yuv文件夹,只有cfg_ftbl_ov5642_yuv.h有差别:
图8
& _4 z# t5 g! f4 M6 X1 P0 H这里主要是不同驱动IC支持的分辨率不同,以及设置默认的分辨率。
图9 9 }! O2 s6 G: W y w
此文件下有两个这样的地方不同,这里是指自动对焦模式。
! @, r, S% q( I/ U: S: ]因为我们的OV5640和OV5642非常接近,所以就直接把OV5642的目录复制过来修改为OV5640即可。
# I9 x: {$ R* c' E* Z: J所以把mediatek\custom\common\kernel\imgsensor\ov5642_yuv拷贝到imgsensor目录下,改为ov5640_yuv / }! s+ ]8 q2 j: a# O
(2) 在支持的sensor列表中增加目标sensor + v) q$ u# \! ?; ^) w! |, H" q
\src\ sensorlist.cpp 8 i) P" r' v3 k. |3 f9 c$ S9 v. B
" g- `8 S+ K( r% |
- MSDK_SENSOR_INIT_FUNCTION_STRUCTSensorList[] =
- {
- ………..
- #ifdefined(OV5640_YUV)
- YUV_INFO(OV5640_SENSOR_ID,SENSOR_DRVNAME_OV5640_YUV, NULL),
- #endif
- …………
- }
. _3 |' V0 z! v5 `- o5 i1 x) ~2 @) e
& v% x( g0 @6 S F4 k# l S: f3 o: q9 n( @: J4 Q X
1 j: Y* [! G7 E4 S注意:在 kd_SensorList.h 和 SensorList.cpp 里面添加驱动的时候要注意,Sensor 添加的位置要一样。否则驱动会跑乱,轻则 ISP 参数不对,重则 Sensor 无法启动。 ' _& X7 p8 y& ~. y" I x- G3 E+ n
) m) A+ y1 j% f' {& t4.3 拍照图片尺寸设置 ' Q9 @$ d) G- a
mediatek\custom\common\hal\imgsensor\ov5640_yuv\cfg_ftbl_ov5640_yuv.h
9 k8 Z7 H. V3 y- C5 g x& P a8 h Y- j7 w" {# m
+ Z1 |1 g7 I7 p: f- // 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
- )
4 N1 }' o4 X8 B6 a+ I6 q+ u! a
6 f9 {) ~) b R* o$ y* F 9 i2 g" d' {& u+ P0 b# b4 }
" t3 a% L; h3 r/ h) y4.4 Camera物理角度旋转 Cfg_setting_imgsensor.h ( y) A2 Y! Q' L$ ^
6 |# [5 Y7 `( g4 u
- /*******************************************************************************
- * 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;
- }
j1 o! m, Y; t% l) `0 I Q/ y
6 k. L0 C7 `3 S4 Q
1 ^6 K- A4 h# d$ _! [8 o; t/ v- Q( d3 C, G, X
' A; M7 o$ o' C0 ~/ B 这几种都试过了,但都不行,预览和实际的都是成某种镜像关系。这是平台是提供旋转的功能。这个配置好了之后,如果方向不正确,可以通过驱动中的方向调整函数进行调整,如下: static void XXXXXSetMirror(kal_uint16ImageMirror) 参考:http://blog.csdn.net/loongembedded/article/details/41679977
6 q) ^2 n* B2 m! V, T" z1 i, |2 S* O$ e
& ^' R' T! `: R. x z4 Q& Y 看了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)却问题依旧,很奇怪。
- k5 ?0 s# N: B2 Jmediatek\custom\common\hal\imgsensor\ov5640_yuv\cfg_ftbl_ov5640_yuv.h " ?: A! ~. L% b% y$ a$ l7 Z# M
- /*
- // 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
- ) 3 J- S' X) l9 s: K* X: h
0 g5 [5 V7 u& U8 t6 j' k9 Z2 Z r8 _1 r2 _! ?
我试过做上面的修改,但打开摄像头的时候,提示”Unfortunately, Camera has stopped” 本文作者:LoongEmbedded
/ o# r5 t, ]# X$ C+ X, p/ L2 b
9 u9 A) {) c- E7 e. {, n |