查看: 12875|回复: 1
收起左侧

Camera手机工作格式流程

[复制链接]
发表于 2015-6-29 13:47:39 | 显示全部楼层 |阅读模式
一、 手机 Camera 的物理结构:, v& |& s, Y6 |: m& ^
      
' r8 M# P. `/ r" Z6 |* _+ f9 }+ v% i" f9 B8 L
二、 Camera 的成像原理:) E& ^& X1 n  v5 m  t/ }

( ?4 ~/ l" m+ q- C1 l% R       景物通过镜头(LENS)生成的光学图像投射到图像传感器(Sensor)表面上,然后转为模拟的电信号,经过 A/D(模数转换)转换后变为数字图像信号,再送到数字信号处理芯片(DSP)中加工处理,再通过 IO 接口传输到 CPU 中处理,通过 LCD 就可以看到图像了。
9 M( Z2 w& A# A- g  h' G
0 M% [$ m# B: l             
( V% k% R! Z1 G0 q7 |. |# ~       图像传感器(SENSOR)是一种半导体芯片,其表面包含有几十万到几百万的光电二极管。光电二极管受到光照射时,就会产生电荷。目前的 SENSOR 类型有两种:
0 P5 A2 _* y' d+ r       CCD(Charge Couple Device),电荷耦合器件,它是目前高像素类 sensor 中比较成熟的成像器件,是以一行为单位的电流信号。
) c$ n* _, [' n       CMOS(Complementary Metal Oxide Semiconductor),互补金属氧化物半导体。CMOS的信号是以点为单位的电荷信号,更为敏感,速度也更快,更为省电。  A, Q0 ?/ t; e; g
       ISP 的性能是决定影像流畅的关键,JPEG encoder 的性能也是关键指标之一。而 JPEG encoder 又分为硬件 JPEG 压缩方式,和软件 RGB 压缩方式。
  s$ w9 H& H3 }' @       DSP 控制芯片的作用是:将感光芯片获取的数据及时快速地传到 baseband 中并刷新感光芯片,因此控制芯片的好坏,直接决定画面品质(比如色彩饱和度、清晰度)与流畅度。' Z( H" c" }5 m' d: p  h" ~! t

& }3 u7 K- W/ v. C( J8 C: T: U三、 Camera 常见的数据输出格式:
5 d! |2 c- W; D) \9 H: |$ @1 X8 Z! l       常见的数据输出格式有:Rawdata 格式、YUV 格式、RGB 格式。
: A/ h/ H- c" `5 X       RGB 格式:采用这种编码方法,每种颜色都可用三个变量来表示红色、绿色以及蓝色的强度。每一个像素有三原色 R 红色、G 绿色、B 蓝色组成。
  m5 C- ~( d' s# u0 y       YUV 格式:其中“Y”表示明亮度(Luminance 或 Luma),就是灰阶值;而“U”和“V”表示色度(Chrominance 或 Chroma),是描述影像色彩及饱和度,用于指定像素的颜色。. h3 {) ]* f  z) E+ R
       RAW DATA 格式:是 CCD 或 CMOS 在将光信号转换为电信号时的电平高低的原始记录,单纯地将没有进行任何处理的图像数据,即摄像元件直接得到的电信号进行数字化处理而得到的。
' q1 Y6 p& r9 ~7 M$ Z       支持 YUV/RGB 格式的模组,一般会在模组上集成 ISP(Image Single Processor),经过A/D 转换过的原始数据经过 ISP 处理生成 YUV 标准格式传到 BB。一般来说,这种设计适用于低像素 Camera 的要求,会在主板上省去一个 DSP,可降低成本。在调试过程中,YUV/RGB 格式的摄像头,其所有参数都可在 kernel 层通过寄存器来控制。调试一般由 sensor的原厂支持。
* o6 a6 r9 T" c1 f$ S; J       支持 RawData 格式的模组,由于感光区域的需求,不会再模组内集成 ISP 以最大程度的增大感光区域的面积,提高照片质量。模组把原始的数字信号传给 BB 上的 DSP 进行处理,MTK 自带的 DSP 一般包含 ISP、JPEG encoder、和 DSP 控制芯片。在调试的时候图像的效果需要 MTK 在 HAL 层的参数进行支持。
) k3 d: {5 z0 s7 a5 |: i5 i) |
四、 阅读 Camera 的规格书(以 Truly 模组 OV5647_Raw 为例):: j; s/ _1 f4 f3 J4 q0 L- F
      
/ b* H7 ?1 d  f$ E" b9 K          4 `/ A$ e( |. F  v! L

* \+ z# m. _- Y% T. b. G7 I' ^4 @五、 Camera 的硬件原理图及引脚:5 J* P" t! v' G; s
         
5 c. N4 z3 T" x: O# V9 Z: v5 a       从上面可看出,连接 Camera 的 30 根 Pin 脚可大致分为以下几类:
# e+ i& a& t& n/ q2 w$ U9 e. c          1、电源部分:
, N$ |9 G2 H+ ?                   a)VCAMD 就是 DVDD 数字供电,主要给 ISP 供电,由于 RAWDATA格式的sensor其ISP是在 BB 端,所以将其引脚将其 NC。从上面的规格书上可以看出 DVDD 是内部 BB 端供电。模组已将其 NC 掉了;
0 T8 U2 z2 F) k0 {1 X                   b) VCAM_IO 就是 VDDIO 数字 IO 电源主要给 I2C 部分供电;
# K4 W- n* D; q" d4 _4 y                   c) VCAMA 就是 AVDD 模拟供电,主要给感光区和 ADC 部分供电;
: f+ n2 I- t7 y$ z7 w                   d) VCAM_AF 是对 Camera 自动对焦马达的供电。# A5 q7 c, T8 w1 |/ @' T
             2、Sensor Input 部分:2 k) ~8 b& a* O) `' K0 b
                   a) Reset 信号,用于复位、初始化。
8 \- @+ v2 }. f* g5 g( n9 l4 h                   b) Standby/PowerDown 信号,用于进入待机模式,降低功耗。
8 R1 K* ?9 N: z  d                   c) Mclk,即 MasterClock 信号,是由 BB 端提供。
" p0 @& a" H4 }; @0 `0 Y             3、Sensor OutPut 部分:( `. E, _7 F( H3 o8 l  b' N8 G
                   a)Pclk,即 PixelClock 信号,由 MCLK 分频得到,作为外部时钟控制图像传输帧率
, q3 V: J6 o- l7 g                   b) HSYNC,行同步信号,其上升沿表示新一列行图像数据的开始。
/ u  G0 q3 b# P5 _9 _7 i* j4 p$ r                   c) VSYNC,帧同步信号,其下降沿表示新的一帧图片的开始。7 T7 e* s& k/ B5 Q
                   d) D0-D9 一共 10 根数据线(8/10 根等);9 X9 g8 [; F5 L6 L7 m$ Y
             4、I2C 部分:SCL,I2C 时钟信号线和 SDA,I2C 数据信号线。
9 {0 h* ]! Q# e; F
% l: E3 k) ?9 [  U% ~0 t
- {, J2 W- F1 U& \' O4 d( [六、 MTK 平台 Camera 相关代码文件(以下代码均为 MTK6575 平台)
" |7 b; F1 ^9 Y! q) g/ f       1、 CameraSensor 驱动相关文件8 u0 C; X- @7 @! W$ F8 F
              ! p0 v2 y9 X5 ]0 B* p3 d
        2、 Sensor ID 和一些枚举类型的定义
- Z$ X/ }6 Q( E, m* |            
7 |% x5 r& t8 x. [0 Y$ M      3、 Sensor 供电' S& I1 N. @! [. V3 A/ ^
2 q* D4 R$ N# m: Z) j1 P
               P' X" w6 Z4 k/ O& E5 D! C
       4、 Kernel Space 的 SensorList,imgsensor 模块注册
; M' ]8 e4 k" r7 `. B                7 X6 P" S) H9 c7 }: }
      5、 User Space 的 SensorList,向用户空间提供支持的 SensorList* j. I1 {# i8 Q3 v) S3 \: }" \
                           
9 c- ]1 s( ?4 C9 c3 r
2 V( L: v# M! s; w! C7 o       6、 Sensor 效果调整的接口) |; a; {' H7 N! R$ k, Y5 T3 R; l
              , S% p1 Q0 C5 `5 W
              8 k4 E, E3 ]3 i! o  p- _/ ^% j
6 d. \0 {) |* ?1 Z1 |
七、 Camera 模块驱动、设备与总线结构:+ n- Q: X4 s" z$ A* H! ?1 n
           一般在 Linux 设备驱动模型中,我们只需要关心总线、设备、驱动这三个实体。总线会充当红娘对加载于其上的设备与驱动进行配对,对于 Camera 模块也不例外,下面从总线、设备、驱动的角度来分析 Camera 模块驱动的注册、匹配与加载过程。
+ Q/ U* x0 \2 m' ~4 [           a) 驱动的注册:! `, }. D2 v6 m  W1 a! f# ]* A" ~/ Y
               在(\custom\common\kernel\imgsensor\src\Kd_sensorlist.c)CAMERA_HW_i2C_init 这个函数里通过 Platform_driver_register(&g_stCAMERA_HW_Driver)把 Camera 模块驱动注册; h& V! s: d! [5 E
到 Platform 总线上。而 g_stCAMERA_HW_Driver 是对结构体 Platform_driver 这个结构体的填充。0 d9 `/ [0 Y0 v% J3 f: \4 m' K
           & O$ t5 e$ @( t8 D! D
          (Kernel\include\linux\Platform_device.h)1 J1 G9 k- Q+ D( }
            Z5 F( P% ]4 T* R8 W' j% e
         b) 设备的注册:
7 k2 f# y0 |$ b$ F( E              对 platform_device 的定义通常在 BSP 的板级文件:
' m7 @& |4 x$ ?& [# r) s              (kernel\arch\sh\boards\mach-ap325rxa\Setup.c)中实现,在板级文件中,将 platform_device归纳为一个数组,最终通过 platform_add_device()函数统一注册:- h) x9 l. c/ A' \& q( _; M
            
% f0 P% q; E& D! R$ p( o/ B            
, U+ N% p/ C4 D! o8 ^6 C             9 X* ?/ y* a& i4 t2 L& s( G
            c) 总线的匹配:: @2 _8 k" T6 w/ P8 L& s
                既 然 是 驱 动 Platform_device 那 对 应 的 设 备 必 然 是 挂 载 Platform 总 线 上 的Platform_device,Platform 总线是 Linux 系统提供的一种机制,不同于 I2C、I2S 等总线,它9 `5 \0 P' K$ v/ f1 e* h+ G
是一种虚拟的总线。Linux 系统为 Platform 总线定义了一个 bus_type 的实例 Platform_bus_type:
% P6 N( Z1 w+ I' ~0 M, v. ]               (Kernel\drivers\base\platform.c)
- e" D- D0 R' a: o                 {0 W( L1 ?9 F1 E
              Platform 总线通过 platform_match 这个成员函数来确定 platform_device 与 platform_driver 如何进行匹配:* h% H! X+ {# ^3 ]7 ?- P. i& p
              2 D# m, {/ b+ a

) K6 S. ]+ Y; m# B2 _八、 Camera 驱动工作流程:* M( K% u& y: u

+ S/ Y3 P! a. `6 z' i: e# L$ ~; K$ \% Z  |3 C7 j' G' A/ l' Z; g
             从上图可以清晰的了解到 Camera 的一个工作流程主要分为这么七步:
( f" n3 @0 e% e                   1. 打开 Camera Power LDO,让 Camera 有能量保证。
( v3 w8 \, ^# G' R  p& g$ u9 f                   2. 打开 IIC,设置 PDN 引脚,使 Camera 退出 Standby 模式,按照要求让 Reset 脚做一个复位动作。( J) j- }- ^2 V; n7 C' C2 g1 Y- q: z
                   3. 读一下 sensor 的版本 ID,这样可以让你确认是否连接上你想要的 sensor。
7 |/ Q9 w5 |0 X1 @0 E                   4. 对 Sensor 进行初始化下载最基本的参数让 Sensor 工作起来,可能包括软复位。
) i3 ]- {* x; r                   5. 下载 preview 的参数,为预览动作准备。, C: \' e& x; z% C  o! I
                   6. 下载 Capture 的参数,为拍照动作准备。
- G- F$ ^2 L) d& \' M                   7. 设置 PDN 引脚,使 Sensor 进入 Standby 模式, 或者关掉 LDO 等动作,退出 Camera。
+ S  }+ W. O3 A: |            我们都知道,Linux 内核是通过模块的机制来加载设备驱动的,那么接下来我们就从设备模块加载的角度来看下 Camera 工作流程的驱动代码是如何工作的。( _3 c0 Q- J- R* y
            在-alps\mediatek\custom\common\kernel\imgsensor\src\kd_sensorlist.c 中可以看到:
( @( M4 @5 N, k- D" j' l4 J6 |            module_init(CAMERA_HW_i2C_init);
: |* o+ X+ q4 G+ E7 u            module_exit(CAMERA_HW_i2C_exit);. |# I, e- c; p, L# _4 c8 O
            在这里 Linux 内核加载和卸载 Camera 模块。
3 x1 ~1 c8 ?# K0 d! a. d2 J            static struct platform_driver g_stCAMERA_HW_Driver = {
( f) P, v& {# \2 `( [7 s. F                     .probe = CAMERA_HW_probe,
7 j6 c8 Y! T+ ?6 {' l( z+ H1 Z                     .remove = CAMERA_HW_remove,
# z3 T2 X7 A. A9 e- Q                     .suspend = CAMERA_HW_suspend,
" a- ^' O! }* e( Q' Z8 M                     .resume = CAMERA_HW_resume," [" }' J- G/ w" G# ~3 J8 S
                     .driver ={
5 X) T$ |. T  F- p% Y4 K, v1 W/ ^                           .name = "image_sensor",# ]! n- M- Y3 j9 O6 d, ~
                           .owner = THIS_MODULE,
! `5 v) y' x5 m7 d- f                     }  B5 {% G' `7 g2 S2 p) I! R
            };  K1 x" z8 d3 M4 ^+ \$ [0 V8 O+ r9 i* g
             Camera 模块初始化开始向总线注册驱动,在 Platform_driver 的成员函数.probe()中,通过 i2c_add_driver(&CAMERA_HW_i2c_driver)向 I2C 申请,而 CAMERA_HW_i2c_driver 这个结构体里填充的是将 Camera 作为一个字符设备在 I2C 上进行注册:
( t! {- g' Z! C. [/ Q7 ?9 f& I            
: l0 l5 Y6 l; O' p! q6 q             " q3 t8 k. Y+ P/ M5 e$ y
             在 RegisterCAMERA_HWCharDrv()中cdev_init(g_pCAMERA_HW_CharDrv, &g_stCAMERA_HW_fops);对设备进行初始化,并将g_stCAMERA_HW_fops 这个文件操作函数作为上层对 Camera 设备操作的接口留给上层进行调用:+ [  l% j1 \1 S* ~1 p* Y8 f
             5 e3 u% z/ v# \. G
            其中成员函数 open()只是初始化一个原子变量留给系统调用。ioctl()才是整个 Camera驱动的入口:
( R# i% N, T& T& l            
" ]& E. L. W% w            CAMERA_HW_Ioctl()是上层文件操作系统操作底层硬件的方法,它先对 Camera 需要的Buffer 做一个初始化,然后建立对 Cameraopen、getinfo 等操作的接口:
$ f- e! R7 \" [. U            ( E- b7 q: s1 I$ {2 g$ p8 w! r
            通过判断 Sensor 状态的逻辑值来进行具体的操作,对于这个值的定义在:4 Y& _$ z2 g1 j! z
            Mediatek\custom\common\kernel\imgsensor\inc\Kd_imgsensor.h 中
8 A/ A! w  f0 r; a/ e            " Z8 ?8 A# i  h: Y
            在 KdSetDriver()中通过判断 name 和 ID 匹配具体型号的 sensor 的驱动,判断它是主摄还是次摄,并对它进行初始化:
. ^1 d9 g/ L" T7 ]2 ]! j            0 O4 x( E. B# _* u2 P
           
/ C* g# A# ]- `           通过 NAME 和 ID 匹配完成后会将 PSENSOR_FUNCTION_STRUCT *pfFunc 这个结构体匹配到具体型号的驱动代码中:) u* p5 _8 J+ \
           
7 r) J9 i0 m$ F: R" R           到这里,整个 Camera 驱动从总线注册到完成具体 sensor 的初始化的流程就完成了,CAMERA_HW_Ioctl()中其他的 ioctl 操作函数最后都会在$sensor$_sensor.c 中实现。
4 m( k9 U' ~2 o2 ~$ F6 I/ v$ d4 j, i7 G' ~/ F$ Z
九、 Camera 驱动添加、调试流程:
* c3 c7 K3 i( m  c* ^8 Z+ S4 p           1、 修改系统配置文件 ProjectConfig.mk:
( S# d$ k3 y8 J' k& ~0 o2 _                  -alps\mediatek\config\$project$\ProjectConfig.mk  ]- v5 d* p, l1 h" L* B# U
            6 ?7 f0 a5 T5 J2 l

. c9 H3 a' {6 u9 q- y            2、 检查、配置供电文件:
/ d$ `2 i/ S+ t7 c6 V$ @% s                  -alps\mediatek\custom\$project$\Kernel\Camera\Camera\kd_camera_hw.c) U4 m, w7 ^! D$ V% |$ a% x. G
                  Camera 供电流程(以 3M 前摄 MT9V114+5M 后摄 OV5647 为例):8 U- m* \, O" p& {" s
                  / A, a$ I" Y( c1 a- x6 j: ], x
                  其实在 kd_camera_hw.c 中只有一个函数 kdCISModulePowerOn(),在这个函数中需要注意的是通过 GPIO 口控制 PDN 和 RST 引脚的时候,对于其相关的定义,由其在切换平台的时候。例如 MT6573 和 MT6575 的定义顺序就不同' l7 {# B/ T5 l- Y
                  
: C" ?0 y0 ]7 [! \. C           3、 添加 Camera 驱动(以 ov5647 为例):
. U" s9 h! X0 ^" E/ g4 G8 F                 创建 SensorFuncOV5647 这样一个数据结构
4 p( O% z+ R% I' x; z. f9 C1 q                 SENSOR_FUNCTION_STRUCT SensorFuncOV5647={5 J/ s9 h" Q+ B7 u9 Q/ X
                    OV5647Open,
8 ]1 q- c5 Y1 U/ m" D                    OV5647GetInfo,
# B+ e/ o4 Z0 D' V/ h                    OV5647GetResolution,2 N# N- S6 n6 i
                    OV5647FeatureControl," D& _8 P0 I( P* t% X  D% w
                    OV5647Control,
. l3 E" M; |7 y' D3 L+ x. Z                    OV5647Close# m3 v6 e' F. P, ?5 t0 |! p
                };( g# s4 f: a  a) @) s6 b# {
               a)OV5647Open
$ H% P, m% X0 z7 I* w               
! y, c7 e4 s6 r  q- O               初始化操作就是对 SensorIC 中寄存器的操作,调试主要由 IC 原厂支持。Open 函数结束后返回 ERROR_NONE 表示初始化成功,可以正常使用4 l6 j% b0 M6 N8 S3 g  N- s4 B3 `
7 a2 r* Z* B- K
               b)OV5647GetInfo
# Z' v7 R$ ^" p8 Y; i( V: g1 g; r7 W& T1 M% Y% j
               UINT32 OV5647GetInfo(MSDK_SCENARIO_ID_ENUM ScenarioId,MSDK_SENSOR_INFO_STRUCT *pSensorInfo,MSDK_SENSOR_CONFIG_STRUCT *pSensorConfigData), f# U; J! F7 y$ i9 D
               第一个参数 ScenarioId 来自于 MSDK_SCENARIO_ID_ENUM 这个数组,在kd_imgsensor_define.h 中是这样定义的:1 |) h8 k2 W" B; c# p+ r
               #define MSDK_SCENARIO_ID_ENUM ACDK_SCENARIO_ID_ENUM
' T  L7 W+ q0 t) B" a              typedef enum{
& C1 m6 e4 [# Y2 e; m* B            ACDK_SCENARIO_ID_CAMERA_PREVIEW=0,- D2 B- j& A& t; N1 n. p) [. {
            ACDK_SCENARIO_ID_VIDEO_PREVIEW,
0 u$ z/ O4 Z& T8 Q2 i            ACDK_SCENARIO_ID_VIDEO_CAPTURE_MPEG4,# W  ~$ D; {+ J: z, s5 ~) _3 @
            ACDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG,
( X) Q% B: D! f; s            ACDK_SCENARIO_ID_CAMERA_CAPTURE_MEM,
  I6 b: D. ]$ B- b- e2 k: t            ACDK_SCENARIO_ID_CAMERA_BURST_CAPTURE_JPEG,
0 c  N) Z' w$ Q            ACDK_SCENARIO_ID_VIDEO_DECODE_MPEG4,4 W; X$ s4 O) h- g  s+ @4 X! ?0 ^
            ACDK_SCENARIO_ID_VIDEO_DECODE_H263,
% S+ [1 F. F5 [2 c! Y9 T            ACDK_SCENARIO_ID_VIDEO_DECODE_H264,
, J" `2 X. g9 I$ \            ACDK_SCENARIO_ID_VIDEO_DECODE_WMV78,& W' C8 Z1 S' I/ P. Q
            ACDK_SCENARIO_ID_VIDEO_DECODE_WMV9,+ Y( S, Y) m$ Y7 h
            ACDK_SCENARIO_ID_VIDEO_DECODE_MPEG2,
0 F1 R0 s7 z, N% Q0 B1 C            ACDK_SCENARIO_ID_IMAGE_YUV2RGB,
0 O. E" r- q  ?1 u1 L            ACDK_SCENARIO_ID_IMAGE_RESIZE,
( z0 h2 B4 R4 P& ^7 Y6 X! D/ U            ACDK_SCENARIO_ID_IMAGE_ROTATE,1 l: g  m2 g* M3 j; D, p3 D  P
            ACDK_SCENARIO_ID_IMAGE_POST_PROCESS,
" t" V7 E$ Q1 n$ [2 `- i            ACDK_SCENARIO_ID_JPEG_RESIZE,
& c. ?9 Q- w: y            ACDK_SCENARIO_ID_JPEG_DECODE,
- V6 o+ V) I  _" {9 Z            ACDK_SCENARIO_ID_JPEG_PARSE,
$ Q' \- x; L; W4 J( k1 E            ACDK_SCENARIO_ID_JPEG_ENCODE,, N% t- h2 I9 `) r) |
            ACDK_SCENARIO_ID_JPEG_ENCODE_THUMBNAIL,9 o* _2 ?6 `4 K
            ACDK_SCENARIO_ID_DRIVER_IO_CONTROL,
1 G+ \1 C% n# o            ACDK_SCENARIO_ID_DO_NOT_CARE,) X( ?$ R1 ?/ W# ^; y3 `
            ACDK_SCENARIO_ID_IMAGE_DSPL_BUFFER_ALLOC,
# O9 n6 o! l  ^& ^            ACDK_SCENARIO_ID_TV_OUT,2 C* v0 r$ a( i. H; Y" l
            ACDK_SCENARIO_ID_MAX,
5 J1 F* a# F0 U2 {0 C4 D! E            ACDK_SCENARIO_ID_VIDOE_ENCODE_WITHOUT_PREVIEW,' F# ?: n; y1 `& P
            ACDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG_BACK_PREVIEW,
% o8 h; |1 A; ]) O            ACDK_SCENARIO_ID_VIDEO_DECODE_RV8,
' I- ^6 B  H3 P            ACDK_SCENARIO_ID_VIDEO_DECODE_RV9,6 Z/ ~, y8 Z/ L( i* y
            ACDK_SCENARIO_ID_CAMERA_ZSD,/ J$ \4 y) V- P; k7 u
        }ACDK_SCENARIO_ID_ENUM;  h6 d# w% J/ _5 g$ v2 y
        通过这个数组定义 Camera 的各种模式,并且给他们从 0 开始给一个模拟的 ID,通过这个ScenarioID 来控制 Camera 的工作模式是在拍照、摄像等等。
1 ^) y8 W% t+ x$ o! r$ f        想要了解*pSensorInfo 这个指针的内容就得看 MSDK_SENSOR_INFO_STRUCT 的定义
' l# l6 |* M$ }5 a, ?        #define MSDK_SENSOR_INFO_STRUCT ACDK_SENSOR_INFO_STRUCT* G0 Y' ~* A( X: }+ ?

4 ?3 I6 [6 Z4 {6 T7 D
发表于 2015-7-26 22:24:35 | 显示全部楼层
这个怎么没有内容
高级模式
B Color Image Link Quote Code Smilies @朋友 |上传

本版积分规则

在线客服

客服电话

欢迎来电咨询

188-9985 8350

微信关注

手机APP程序:
扫码下载访问

微信公众平台:
摄像头之家公众号

微信小程序:
摄像头小程序

返回顶部

QQ|站点统计|小黑屋|手机版|Archiver|摄像头模组论坛网-摄像头方案网CCM99 ( 粤ICP备18155214号 )

Powered by Discuz! X3.4 Licensed© 2001-2013 Comsenz Inc.