, j$ h' d1 r( [% b图1 # \2 C: F8 T E) r/ ?$ x, E
1. Camera拍照相关概念 1.1 ISP ; m3 T8 u P- K- H2 `/ @3 \7 |
isp——(Image Signal Processor)——影视处理 * F7 X+ T9 X0 I# t
无论数码相机、摄像机或者摄像手机,其影像数据从前端感应后,皆须经过ASP(Analog Signal Processing)、ADC(Analog-Digital Converter)、前期影像处理(Pre-ISP)与后端影像处理(Post-ISP)四个阶段后,影像数据才能最终呈现于终端设备上 : ?6 ^& [- \, V! F
1.2 720p 720P是美国电影电视工程师协会(SMPTE)制定的高等级高清数字电视的格式标准,有效显示格式为:1280×720.SMPTE(美国电影电视工程协会)将数字高清信号数字电视扫描线的不同分为1080P、1080I、720P(i是interlace,隔行的意思,p是Progressive,逐行的意思)。720P是一种在逐行扫描下达到1280×720的分辨率的显示格式。是数字电影成像技术和计算机技术的融合。
; c; C1 K1 C3 R) i; S3 X1 J分辨率为1280×720p/60Hz,行频为45kHz " B/ ?9 i6 g; r7 y. ]. y. n
+ X! r: g% n7 G- Y/ c
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)这些特征,用于图像处理。 g1 \3 {4 o: N& Z
2.2 camera特征 4 J: U9 `) ^, X/ y, I
MT6577内部集成的ISP,包含了一个功能强大的图像信号处理器,用于连接各种各样的图像传感器模组,这个处理器由时序产生单元(timing generated unit: TG)、镜头/传感器补偿(lens/sensor compensation)单元和图像处理单元。
$ O: i. ]1 f, O: E1 H5 N2 k支持的特征如下: (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 t1 L/ n8 L! \* b2 H( Y0 M3 J
(6) 3A统计和校正(statistics and correction) (7) 闪烁检测(flicker detection)。 ) L1 ^* x4 q7 `. W6 Q& [. S" A. Z
2.3 camera框图
- b2 L9 o: n' O* r- Z) H" D# C
图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)单元。 1 I8 G# N$ B3 z! l" f$ G
在Bayer原始数据输入模式,镜头/传感器补偿(lens/sensor compensation)单元产生补偿的原始数据给色彩处理单元(color process unit);在YUV422/RGB565 输入模式,这步被忽略。 , u# G8 P( e3 {4 l
色彩处理单元接受来之镜头/传感器补偿(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读取出来。
$ @5 S# t0 M Q8 v下面给出一些性能参数:
6 u( ?3 a( f7 ^6 h) y
图3 , r) `7 c2 n) s% T; b
3. 原理图设计 . n: b0 y; H+ y' i3 k, x# Y' [
MT6577支持两路camera接口,一路是MIPI接口,一路是并行接口,这里我们采用的是并行接口,下面给出MT6577 CAM并行接口定义:
- g+ A! S3 Z+ e5 d图4 Camera sensor连接座如下:
5 {0 p1 c D3 s5 T9 f3 o) f* l H图5 4 [7 t2 a. l9 {
(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位。如下图:
; [& C( e% c2 I. w图6
. h0 h/ W! ~# c: B9 D7 E) g/ m" G0 K. O$ \; Z/ D0 s6 @( t0 a
(2) OV5640IIC地址 / @, B* e9 E( a
IIC 8bit写地址为0x78,读地址为0x79,查询Sensor规格书可以看到:
. d# _" m8 \9 V8 |" I图7 IIC 8bit地址最后一位为0时是写地址,为1时是读地址。这属于IIC通讯规则 * N1 X. Y% f% b) x; J
8 D N6 H p7 j) k+ a I% ^; E7 s( L7 E0 [
4. 驱动实现 6 W, r' w) b$ I
1 o$ Y' U$ V% A2 O# J3 g* \* f8 E
4.1 相关代码 (1) CameraSensor驱动相关文件 \mediatek\custom\common\kernel\imgsensor\ov5642_yuv
- N: q7 P7 Q: Q: m) m1 P(2) SensorID和一些枚举类型的定义 \mediatek\custom\common\kernel\imgsensor\inc kd_imgsensor.h---------SensorID kd_imgsensor_define.h--------------一些枚举类型的定义 ) i4 \1 `9 J) E2 J* S9 a
(3) Sensor供电 \mediatek\custom\common\kernel\camera\camera kd_camera_hw.c和kd_camera_hw.h " h5 | \2 I) V, B9 }
(4) KernelSpace的SensorList,imgsensor模块注册 \mediatek\custom\common\kernel\imgsensor\src kd_sensorlist.c和kd_sensorlist.h-----------camera模块加载
3 X# }' ?9 I1 e(5) UserSpace的SensorList,向用户空间提供支持的SensorList \mediatek\custom\common\hal\imgsensor\src\sensorlist.cpp 提供给用户空间的SensorList 6 _5 a7 t9 l3 |+ l p/ P+ r
) ^' p. v D6 F: p4 T(6) Sensor效果调整的接口 \mediatek\custom\common\hal\imgsensor\ov5642_yuv $ h4 {5 F k2 D' g" X
( [1 `" L t' P7 L3 c7 D& a8 C3 I9 A4 J0 z4.2 针对OV5640的修改 / C2 m/ @7 s# ^
4.2.1 mediatek\config\hsimobile77_ics2\ProjectConfig.mk
+ l8 b+ f4 O7 ~9 L; i+ e1 JCUSTOM_KERNEL_IMGSENSOR=mt9p017_rawgc0329_yuv mt9p017_raw表示后置摄像头(也就是主摄像头),mt9p017是摄像头sensor驱动IC,raw是sensor一种输出的数据格式,是CCD或CMOS在将光信号转换为电信号时的电平高低的原始记录,单纯地没有将没有进行任何处理的图像数据,即摄像元件直接得到的电信号进行数字化处理而得到的。 4 Q: A" }& \/ i* Y+ S4 M
gc0329_yuv是前置摄像头,yuvsensor一种输出的数据格式,支持YUV/RGB格式的模组,一般会带有ISP(image single processor),经过A/D转换过的原始数据经过ISP处理生成YUV标准格式传到BB。 " b" x2 c- c6 Z/ ~4 u- A
我们采用的OV5640就带有ISP,输出YUV格式
4 S6 Y( _' U& ?) r5 V" D: z(1) 把mt9p017_raw 改为ov5640_yuv,去掉gc0329_yuv因为我们的产品没有后置摄像头 (2) 去掉类似CUSTOM_KERNEL_LENS后面的dummy_lens因为没有后置摄像头 # f& ?6 M8 E$ T" [
修改之后的HAL层的配置:
. y4 u- [1 B; U2 E) F- 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
% V" @( Q( s! K; p0 l( j 1 w( G8 i: T1 l- ~9 e" i
6 g6 J" r% U8 W8 U( `; g2 Y
$ j3 w7 J- x' d4 k! g% {. B修改之后的kernel层的配置:
! ~: ^& _/ r( 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 - ]2 Q) z- A* p. N" i# U
5 m3 u0 t# E0 m( p/ _5 R2 Y* E8 j( Q7 x
$ Z# ?; h3 v# w- V1 W
: b) ]' s$ i" U! |虽然我们没有后置摄像头,但不能去掉dummy_lens,我尝试过去掉之后用./mk r dr编译会提示下面的错误: 5 h3 _2 [7 J7 B2 ]- Z! Y( v
7 E3 R u3 |; h L' c8 }7 g: ~3 k
- 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 - T1 ~# s5 O) g6 U- b! k" ~$ @
9 P6 B9 n3 v: H( h
& i8 g( [ F8 s3 _% B8 ?. B* G b8 \. _1 [$ x$ Z
% Z& O* w8 r( f/ Y
4.2.2 mediatek\custom\common\kernel\imgsensor----------kernel层
4 J9 z4 k: a# {# \' ~; ](1) 创建ov5640_yuv并建立需要的文件 1 o0 `. `: Q. Z2 W# I
创建文件夹ov5640_yuv,把sensor IC厂家提供的ov5640yuv_Sensor.c放到此目录下。另外拷贝ov5642yuv_Sensor.h、ov5642yuv_Camera_Sensor_para.h、ov5642yuv_CameraCustomized.h拷贝过来改为ov5640yuv_Sensor.h等。 : R1 |; [4 D& X7 `1 f/ {2 s
编译发现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是没有这几个宏定义,我暂时定义如下: ( G" @/ z* ]4 f5 `8 x7 l: G2 o
' K; o. ~0 r, U& t
- //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 m& y7 x) F' z4 X' n
$ ~, i( G% P; g$ k
1 B' Y$ J$ D" A# l0 Q: }& u% `
i) t' m+ |+ @. o9 n5 S) b这是参考ov5642的相关定义来定义的。
' N2 `/ P; K ?4 f(2) 在支持的sensor列表中增加目标sensor
/ }, n5 @6 T$ V. x6 T% Lmediatek\custom\common\kernel\imgsensor\src\kd_sensorlist.h 在数组增加OV5640的内容,如下: $ k5 Q) ]+ R* M/ k. V6 K
3 A4 A6 I5 }+ p( x! c9 Y
- 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
- …………….
- } 8 J4 ]3 a2 A" ?! ^
4 H5 r& f4 n! J- ^6 `& n2 Y' h v
% \5 G! S ?5 K. D6 ?. ~1 I2 W! D# \& t0 r7 ?$ A+ p+ k% e, I2 }/ C4 C
* x3 w$ X N4 c1 M" m也增加UINT32 OV5640_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT*pfFunc); mediatek\custom\common\kernel\imgsensor\inc\kd_imgsensor.h (3) 增加sensor ID和字符串的定义 ' ^# ~! ?* J, K5 F" D) \! `3 c
+ Q% q" e$ Z$ p5 Q1 x) a
- #defineOV5640_SENSOR_ID 0x5640
- #defineSENSOR_DRVNAME_OV5640_YUV "ov5640yuv" . ]1 R/ H6 z t
! j: D9 J" ^- d; ^0 J: a: F
6 N' p6 e4 O* T9 Z2 J+ O7 ?
5 r7 ?8 I M% @/ c) O* H6 a, P j+ x4.2.3 mediatek\custom\common\hal\imgsensor---------------HAL层 $ H8 @( y, N; x! z5 \
(1) 创建ov5640_yuv文件夹 但这些文件夹下该有哪些文件,有需要哪些内容了,首先我对比了 ov3640_yuv和ov5642_yuv文件夹,只有cfg_ftbl_ov5642_yuv.h有差别:
图8
6 m8 a. a; f$ `* i1 q这里主要是不同驱动IC支持的分辨率不同,以及设置默认的分辨率。
图9
+ W. G/ O4 C. L6 l/ A此文件下有两个这样的地方不同,这里是指自动对焦模式。 9 J7 X. Q0 y& Z: J u9 A
因为我们的OV5640和OV5642非常接近,所以就直接把OV5642的目录复制过来修改为OV5640即可。
( i/ y. V& R$ s, T8 [所以把mediatek\custom\common\kernel\imgsensor\ov5642_yuv拷贝到imgsensor目录下,改为ov5640_yuv
" @' h' _' v, h# |# n(2) 在支持的sensor列表中增加目标sensor
' Q- q9 M9 m* |2 ^; V0 a2 f9 @2 z\src\ sensorlist.cpp 7 V$ h& v- H. y
; H; _3 Z- y6 C$ z0 t
- MSDK_SENSOR_INIT_FUNCTION_STRUCTSensorList[] =
- {
- ………..
- #ifdefined(OV5640_YUV)
- YUV_INFO(OV5640_SENSOR_ID,SENSOR_DRVNAME_OV5640_YUV, NULL),
- #endif
- …………
- } * h- R* }5 U- S$ I6 k
6 i- r/ y4 V7 K3 p
1 ` S+ t$ s1 v1 Z5 w
6 v0 |" v, P% x0 X% X注意:在 kd_SensorList.h 和 SensorList.cpp 里面添加驱动的时候要注意,Sensor 添加的位置要一样。否则驱动会跑乱,轻则 ISP 参数不对,重则 Sensor 无法启动。
; ?9 S$ `& Q$ t9 q7 V9 A
8 e# T$ Z% p, }$ ] z* l4.3 拍照图片尺寸设置
$ h9 I- h. A6 S$ ]mediatek\custom\common\hal\imgsensor\ov5640_yuv\cfg_ftbl_ov5640_yuv.h
3 I) z! ]! Y2 T y! w
% k4 x5 d) r0 i! K6 i
& d2 ^8 C! I6 h$ Z- 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
- )
6 R* D$ J; @+ Z+ e% G2 `% a
9 s. l# b$ `8 j% p+ p
* T% x! u/ \8 ?! S
* K1 M8 j. {; L8 c' F) C: N, j4.4 Camera物理角度旋转 Cfg_setting_imgsensor.h r+ I) o9 A. @! [4 e
) K: P( y" J" M7 o$ |
- /*******************************************************************************
- * 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;
- }
4 K' [6 E! g! | `$ J
! U% K) G; E5 M M * [, V, C1 p" e9 j2 i
4 z' L- ?5 L5 i% }5 d- e3 a5 Z" E7 c8 I/ I% d( M
这几种都试过了,但都不行,预览和实际的都是成某种镜像关系。这是平台是提供旋转的功能。这个配置好了之后,如果方向不正确,可以通过驱动中的方向调整函数进行调整,如下: static void XXXXXSetMirror(kal_uint16ImageMirror) 参考:http://blog.csdn.net/loongembedded/article/details/41679977 " i, d1 E/ `* P# T$ a
: H1 X' K8 S. P; _; j* }+ G1 ^6 c
' R3 N& A5 l: N/ |. ?- }, 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)却问题依旧,很奇怪。
: B( x0 R: G- S4 x1 Tmediatek\custom\common\hal\imgsensor\ov5640_yuv\cfg_ftbl_ov5640_yuv.h
) s6 g8 l6 p* }+ |5 I' M8 e- /*
- // 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
- ) + J% S, G7 K) l. g
+ t3 A2 M. G9 }
9 K1 I3 J8 H! Z; V# z/ I我试过做上面的修改,但打开摄像头的时候,提示”Unfortunately, Camera has stopped” 本文作者:LoongEmbedded
& G, l( }* k* J+ G L) m3 j* M V" V9 K# T1 N
|