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

Camera手机工作格式流程

[复制链接]
发表于 2015-6-29 13:47:39 | 显示全部楼层 |阅读模式
一、 手机 Camera 的物理结构:+ l8 ^* g8 |! `* i6 B' H: k
      
3 J1 {4 C7 D7 Z
% ~5 H7 _$ k- Y9 V. X$ K- k6 R1 m+ d二、 Camera 的成像原理:) \% _3 P: g3 ^5 M9 C$ O0 t

' X8 @2 A% {5 p, x: f& o2 e       景物通过镜头(LENS)生成的光学图像投射到图像传感器(Sensor)表面上,然后转为模拟的电信号,经过 A/D(模数转换)转换后变为数字图像信号,再送到数字信号处理芯片(DSP)中加工处理,再通过 IO 接口传输到 CPU 中处理,通过 LCD 就可以看到图像了。
- V5 k' x. Q. R6 D1 J0 u
& ~( o, }# m# \/ Q2 x             
9 p% f! n- k7 J& q9 }/ F       图像传感器(SENSOR)是一种半导体芯片,其表面包含有几十万到几百万的光电二极管。光电二极管受到光照射时,就会产生电荷。目前的 SENSOR 类型有两种:
$ M0 `/ M  O% i. t+ Q- @, V       CCD(Charge Couple Device),电荷耦合器件,它是目前高像素类 sensor 中比较成熟的成像器件,是以一行为单位的电流信号。1 o6 o3 T% {8 k/ j) ?" {
       CMOS(Complementary Metal Oxide Semiconductor),互补金属氧化物半导体。CMOS的信号是以点为单位的电荷信号,更为敏感,速度也更快,更为省电。
; I) H3 L' k, y5 b! D* a8 i       ISP 的性能是决定影像流畅的关键,JPEG encoder 的性能也是关键指标之一。而 JPEG encoder 又分为硬件 JPEG 压缩方式,和软件 RGB 压缩方式。
; {/ J( m: v8 T, f* V       DSP 控制芯片的作用是:将感光芯片获取的数据及时快速地传到 baseband 中并刷新感光芯片,因此控制芯片的好坏,直接决定画面品质(比如色彩饱和度、清晰度)与流畅度。+ g: c$ B) f2 O

& r0 T/ N; K7 v7 j" T3 t1 Q6 }三、 Camera 常见的数据输出格式:
5 M& \" W# v/ E       常见的数据输出格式有:Rawdata 格式、YUV 格式、RGB 格式。
" _" {0 M0 X" D. O$ R& e       RGB 格式:采用这种编码方法,每种颜色都可用三个变量来表示红色、绿色以及蓝色的强度。每一个像素有三原色 R 红色、G 绿色、B 蓝色组成。8 v! ]) M0 E, E) c8 a
       YUV 格式:其中“Y”表示明亮度(Luminance 或 Luma),就是灰阶值;而“U”和“V”表示色度(Chrominance 或 Chroma),是描述影像色彩及饱和度,用于指定像素的颜色。
( t! t% X9 L2 W7 H       RAW DATA 格式:是 CCD 或 CMOS 在将光信号转换为电信号时的电平高低的原始记录,单纯地将没有进行任何处理的图像数据,即摄像元件直接得到的电信号进行数字化处理而得到的。
1 e3 t7 [8 m, E  M       支持 YUV/RGB 格式的模组,一般会在模组上集成 ISP(Image Single Processor),经过A/D 转换过的原始数据经过 ISP 处理生成 YUV 标准格式传到 BB。一般来说,这种设计适用于低像素 Camera 的要求,会在主板上省去一个 DSP,可降低成本。在调试过程中,YUV/RGB 格式的摄像头,其所有参数都可在 kernel 层通过寄存器来控制。调试一般由 sensor的原厂支持。
& U8 G5 g$ \# s  l       支持 RawData 格式的模组,由于感光区域的需求,不会再模组内集成 ISP 以最大程度的增大感光区域的面积,提高照片质量。模组把原始的数字信号传给 BB 上的 DSP 进行处理,MTK 自带的 DSP 一般包含 ISP、JPEG encoder、和 DSP 控制芯片。在调试的时候图像的效果需要 MTK 在 HAL 层的参数进行支持。- D, D. B$ ^+ q% c# s' X( b

% Z" _5 z7 k9 Z( A  l四、 阅读 Camera 的规格书(以 Truly 模组 OV5647_Raw 为例):
3 W* C+ b" B  ?2 U- c      
, M$ J+ t' [. ]* {/ m          5 P/ D$ T5 S2 |3 \( b; ~# l

3 X4 A/ F# }' R五、 Camera 的硬件原理图及引脚:' }  {/ |3 V% |% d0 {
         
0 g0 o8 ]  ]; I1 W$ o       从上面可看出,连接 Camera 的 30 根 Pin 脚可大致分为以下几类:. k' A  S1 |) _- H2 m; Z; s0 r
          1、电源部分:
& f, G) Z8 l) B' a                   a)VCAMD 就是 DVDD 数字供电,主要给 ISP 供电,由于 RAWDATA格式的sensor其ISP是在 BB 端,所以将其引脚将其 NC。从上面的规格书上可以看出 DVDD 是内部 BB 端供电。模组已将其 NC 掉了;
4 Y, Z/ Y2 y( J8 D+ @8 ~                   b) VCAM_IO 就是 VDDIO 数字 IO 电源主要给 I2C 部分供电;2 \& f2 K, ^5 |
                   c) VCAMA 就是 AVDD 模拟供电,主要给感光区和 ADC 部分供电;
& [; |9 K' u' `                   d) VCAM_AF 是对 Camera 自动对焦马达的供电。% W) k& g9 P% \# \8 w
             2、Sensor Input 部分:1 l: S1 {1 c5 w
                   a) Reset 信号,用于复位、初始化。9 ~" C3 F) R! v
                   b) Standby/PowerDown 信号,用于进入待机模式,降低功耗。% y! h) w) q2 B+ @5 }! C6 N
                   c) Mclk,即 MasterClock 信号,是由 BB 端提供。
3 N8 S1 c# f& w+ _* n; P             3、Sensor OutPut 部分:
  L1 b4 Z! |7 s7 y% [& n8 u1 C3 R1 L                   a)Pclk,即 PixelClock 信号,由 MCLK 分频得到,作为外部时钟控制图像传输帧率. M( f4 X5 w) b& k' w; y
                   b) HSYNC,行同步信号,其上升沿表示新一列行图像数据的开始。  G) w3 |  [; _5 T( \3 x2 R( _
                   c) VSYNC,帧同步信号,其下降沿表示新的一帧图片的开始。- s% [+ X: c- u' U. {  W3 c" i9 @
                   d) D0-D9 一共 10 根数据线(8/10 根等);
! N6 g/ {& H  h! Z" l             4、I2C 部分:SCL,I2C 时钟信号线和 SDA,I2C 数据信号线。  W2 Q6 E4 z' U; s2 v8 r
( B2 j; {, v: c5 g

6 [. g; c4 E+ L7 S六、 MTK 平台 Camera 相关代码文件(以下代码均为 MTK6575 平台). M7 J5 Z/ a9 h: z
       1、 CameraSensor 驱动相关文件( S! w+ Z5 }) a5 c+ {3 w
              / g" \; `4 q3 G6 b
        2、 Sensor ID 和一些枚举类型的定义
3 g" M& [) f7 i             + t& ^$ ^, u/ l* }9 H/ }
      3、 Sensor 供电
! E5 R7 j. z3 h" E4 R/ Q( g% V3 E: [/ _0 l7 \6 I3 p
            
7 p4 T* c7 P+ \. t! a4 T       4、 Kernel Space 的 SensorList,imgsensor 模块注册* l2 `: J* d6 @. w
               
* z% H2 o5 n7 z: a1 {* H# p      5、 User Space 的 SensorList,向用户空间提供支持的 SensorList* `# ~3 S6 A8 k" M2 s5 v- e! ~: M
                           
; Q  e3 _5 U+ k' }$ B2 v( t9 ^. v2 O0 M1 |, W
       6、 Sensor 效果调整的接口
% {# f) U. E# d( d7 [              8 ^" p8 o$ a: A& P% s1 }
              
; l& a( ~0 O! \4 w- s
* t$ X+ g- O4 {& R& v. ^9 \- i七、 Camera 模块驱动、设备与总线结构:
0 p2 X0 i! A2 Y* z           一般在 Linux 设备驱动模型中,我们只需要关心总线、设备、驱动这三个实体。总线会充当红娘对加载于其上的设备与驱动进行配对,对于 Camera 模块也不例外,下面从总线、设备、驱动的角度来分析 Camera 模块驱动的注册、匹配与加载过程。1 A/ Y5 @( H" I% }
           a) 驱动的注册:
: [( ]# e' D" y! v1 J' N# b0 S0 _( M               在(\custom\common\kernel\imgsensor\src\Kd_sensorlist.c)CAMERA_HW_i2C_init 这个函数里通过 Platform_driver_register(&g_stCAMERA_HW_Driver)把 Camera 模块驱动注册
) c0 `! b) C: O* Q' T7 `: B8 c; K到 Platform 总线上。而 g_stCAMERA_HW_Driver 是对结构体 Platform_driver 这个结构体的填充。* _& N" F, s. C. }. i; T
           
/ @8 O( y9 g! r7 I( c          (Kernel\include\linux\Platform_device.h)2 b! R4 i1 w6 b% d3 h
         
4 H2 B) e  ]% Y# [$ K' k         b) 设备的注册:# ^. G: X$ u. k
              对 platform_device 的定义通常在 BSP 的板级文件:
; O% C; D* O; a( j8 z/ E- J              (kernel\arch\sh\boards\mach-ap325rxa\Setup.c)中实现,在板级文件中,将 platform_device归纳为一个数组,最终通过 platform_add_device()函数统一注册:
1 p- j. m$ p' m            
- V+ R  V7 ?6 n2 a8 D9 L+ y             5 M* K( H' F( K% j2 A  J5 L
            
( ?: ~% f5 v. Z3 Q5 m            c) 总线的匹配:( {/ \6 m. ?" {2 B' u4 u. ~  t
                既 然 是 驱 动 Platform_device 那 对 应 的 设 备 必 然 是 挂 载 Platform 总 线 上 的Platform_device,Platform 总线是 Linux 系统提供的一种机制,不同于 I2C、I2S 等总线,它
$ y3 w* w7 J" ?9 b7 x; S是一种虚拟的总线。Linux 系统为 Platform 总线定义了一个 bus_type 的实例 Platform_bus_type:: Y* O8 K0 f$ J: w; `' z& h
               (Kernel\drivers\base\platform.c)
. C  J, y/ l% ]- Y& k; S# t" N               
7 _2 W7 w9 C+ B$ S! D              Platform 总线通过 platform_match 这个成员函数来确定 platform_device 与 platform_driver 如何进行匹配:8 [& n& ^, x8 l1 a9 }! z9 m: k
              
! u+ ~5 c( P! K, T9 i; P, `( A
$ O  B+ N% |7 c5 Z- r/ v$ p$ B( g八、 Camera 驱动工作流程:
# y7 [1 H( ]! u8 D
- ^( E  w$ H2 C+ S5 s3 h: G
6 }  R' `. [$ O* B             从上图可以清晰的了解到 Camera 的一个工作流程主要分为这么七步:3 M/ e) P& [) Y6 W  j* e
                   1. 打开 Camera Power LDO,让 Camera 有能量保证。
& E8 _! U+ \3 \& J0 `/ o                   2. 打开 IIC,设置 PDN 引脚,使 Camera 退出 Standby 模式,按照要求让 Reset 脚做一个复位动作。0 A* @) _3 u) P" F6 ]( n
                   3. 读一下 sensor 的版本 ID,这样可以让你确认是否连接上你想要的 sensor。) E8 H9 \4 x# D+ h
                   4. 对 Sensor 进行初始化下载最基本的参数让 Sensor 工作起来,可能包括软复位。
- B: V  U" _7 t1 h                   5. 下载 preview 的参数,为预览动作准备。
3 L- ^( J; n+ [& f! Z                   6. 下载 Capture 的参数,为拍照动作准备。9 j* s/ O' H3 x+ _7 S
                   7. 设置 PDN 引脚,使 Sensor 进入 Standby 模式, 或者关掉 LDO 等动作,退出 Camera。' b1 {# i9 X$ K2 Y' c
            我们都知道,Linux 内核是通过模块的机制来加载设备驱动的,那么接下来我们就从设备模块加载的角度来看下 Camera 工作流程的驱动代码是如何工作的。
9 O: G+ J. P) |9 R. E3 {" s2 r            在-alps\mediatek\custom\common\kernel\imgsensor\src\kd_sensorlist.c 中可以看到:
5 g% b& n- V2 i# Y7 h9 V4 G$ x            module_init(CAMERA_HW_i2C_init);1 ^1 W4 \# B5 z# n
            module_exit(CAMERA_HW_i2C_exit);
, l8 I" n: A* o3 e8 [/ N            在这里 Linux 内核加载和卸载 Camera 模块。
& O2 X$ n5 E* h  p! J2 q$ }            static struct platform_driver g_stCAMERA_HW_Driver = {' e& b; I9 R6 X6 W) _, f
                     .probe = CAMERA_HW_probe,
! r7 l7 e2 _" q# `+ a" p0 W( ]                     .remove = CAMERA_HW_remove,/ a+ u# M& f' K( ~  d
                     .suspend = CAMERA_HW_suspend,
' S; N1 n* z8 i: C3 Q% j; K5 s3 q. o                     .resume = CAMERA_HW_resume,
, |$ j% b) R; _, b* H, G5 B                     .driver ={0 f  l6 ^5 j) U7 ^/ u! v
                           .name = "image_sensor",
8 B. u+ \5 h$ t! A                           .owner = THIS_MODULE,, a/ e, C+ ^) E$ O+ D
                     }9 [/ y$ N& ~  H0 s  c) T
            };
2 F4 w3 R7 Z1 r7 p  n. w             Camera 模块初始化开始向总线注册驱动,在 Platform_driver 的成员函数.probe()中,通过 i2c_add_driver(&CAMERA_HW_i2c_driver)向 I2C 申请,而 CAMERA_HW_i2c_driver 这个结构体里填充的是将 Camera 作为一个字符设备在 I2C 上进行注册:' m" P  n1 ^6 @" K; q. E9 k
            
# q) ]6 V  B* A; o             9 n9 L& _& ]/ A; v4 O
             在 RegisterCAMERA_HWCharDrv()中cdev_init(g_pCAMERA_HW_CharDrv, &g_stCAMERA_HW_fops);对设备进行初始化,并将g_stCAMERA_HW_fops 这个文件操作函数作为上层对 Camera 设备操作的接口留给上层进行调用:( A0 P. ]8 M  {3 U1 V
             $ M8 k; O: H/ K& Z; M% M
            其中成员函数 open()只是初始化一个原子变量留给系统调用。ioctl()才是整个 Camera驱动的入口:: a7 Z1 Q1 J' Y$ s4 J$ |
            6 E1 `, T$ o6 \7 `3 h
            CAMERA_HW_Ioctl()是上层文件操作系统操作底层硬件的方法,它先对 Camera 需要的Buffer 做一个初始化,然后建立对 Cameraopen、getinfo 等操作的接口:- Y7 u; B5 o2 n) q0 p# y
            
( D3 d3 ?7 A, W% y! Q! i* w3 H            通过判断 Sensor 状态的逻辑值来进行具体的操作,对于这个值的定义在:
8 w6 L) K7 W& X9 I: b            Mediatek\custom\common\kernel\imgsensor\inc\Kd_imgsensor.h 中7 B' o& W1 P$ Z1 ]) E8 j
            
/ O  d" j: J. W8 S9 s5 C7 B% S            在 KdSetDriver()中通过判断 name 和 ID 匹配具体型号的 sensor 的驱动,判断它是主摄还是次摄,并对它进行初始化:
- z6 B' d! u  `8 P8 g7 \            - t2 g& v/ @1 V7 F# ?6 p' f, C1 }
           : X# H  [4 D8 m
           通过 NAME 和 ID 匹配完成后会将 PSENSOR_FUNCTION_STRUCT *pfFunc 这个结构体匹配到具体型号的驱动代码中:
, i+ K; X) W3 u! @- {7 L           * H2 P  w! c' N5 V6 o$ P. W0 z
           到这里,整个 Camera 驱动从总线注册到完成具体 sensor 的初始化的流程就完成了,CAMERA_HW_Ioctl()中其他的 ioctl 操作函数最后都会在$sensor$_sensor.c 中实现。$ B4 p8 s1 F" ?4 N

" K0 @) S8 }7 @9 `0 `九、 Camera 驱动添加、调试流程:
- T# h) n- ~2 G3 y" j% F( a7 c           1、 修改系统配置文件 ProjectConfig.mk:
! T/ ~" v+ p9 N                  -alps\mediatek\config\$project$\ProjectConfig.mk
/ y7 w$ }8 i$ T( f            
8 @( [" A7 Z5 ~& W+ A1 }  G, C% k# [$ g0 \
            2、 检查、配置供电文件:
4 g7 n9 m# @& i% G7 g7 Z) O                  -alps\mediatek\custom\$project$\Kernel\Camera\Camera\kd_camera_hw.c' I; B* R) O. t5 Z3 y
                  Camera 供电流程(以 3M 前摄 MT9V114+5M 后摄 OV5647 为例):7 X# Q/ j- @8 I; g* |0 k# e
                  
. N4 R  ~) B! o                  其实在 kd_camera_hw.c 中只有一个函数 kdCISModulePowerOn(),在这个函数中需要注意的是通过 GPIO 口控制 PDN 和 RST 引脚的时候,对于其相关的定义,由其在切换平台的时候。例如 MT6573 和 MT6575 的定义顺序就不同
6 [5 N, i' ?( W) v- U                  
8 W$ B7 s6 l- K. o           3、 添加 Camera 驱动(以 ov5647 为例):7 J" Y& ?% k  g; v$ b- ^
                 创建 SensorFuncOV5647 这样一个数据结构2 g' S  ~" g& ]) ?( T
                 SENSOR_FUNCTION_STRUCT SensorFuncOV5647={5 |0 ~6 l4 P" R$ g4 w) e0 e
                    OV5647Open,- A- f! W# y( U
                    OV5647GetInfo,# _  F8 Y, E. `& d( t
                    OV5647GetResolution,  v% Z( d  M2 i7 G. I0 k7 e
                    OV5647FeatureControl,$ F  \. X, \5 k5 `5 y9 E2 {4 ]
                    OV5647Control,8 p8 ^7 O6 T9 g% J
                    OV5647Close1 D( u, x8 k. V, k3 B+ Q  n
                };0 h& V% w; Z, c1 G
               a)OV5647Open/ B; B$ E& T! z
               
& a) L3 H0 w8 q( L               初始化操作就是对 SensorIC 中寄存器的操作,调试主要由 IC 原厂支持。Open 函数结束后返回 ERROR_NONE 表示初始化成功,可以正常使用. B0 g2 v5 b$ k

0 D. j5 f7 o6 e- p6 D5 _! W- S) Q( h               b)OV5647GetInfo/ H8 |. h( P+ X0 T3 P

7 ~1 ?( `! T* ]  P               UINT32 OV5647GetInfo(MSDK_SCENARIO_ID_ENUM ScenarioId,MSDK_SENSOR_INFO_STRUCT *pSensorInfo,MSDK_SENSOR_CONFIG_STRUCT *pSensorConfigData)
# ?( i+ T1 l5 G7 u6 W               第一个参数 ScenarioId 来自于 MSDK_SCENARIO_ID_ENUM 这个数组,在kd_imgsensor_define.h 中是这样定义的:+ n/ y4 \8 g, g# z( i
               #define MSDK_SCENARIO_ID_ENUM ACDK_SCENARIO_ID_ENUM0 t. ~7 c4 _  a3 P3 s4 {' R
              typedef enum{
& T0 u( U- U$ T% H            ACDK_SCENARIO_ID_CAMERA_PREVIEW=0,1 |" B: t& E$ ~6 E* I
            ACDK_SCENARIO_ID_VIDEO_PREVIEW,: W# T; C' V+ Y5 F( y, {( S- Q
            ACDK_SCENARIO_ID_VIDEO_CAPTURE_MPEG4,- k9 z" B& W" X% U4 @" C0 {( }* M
            ACDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG,0 C0 ?: i& f1 v
            ACDK_SCENARIO_ID_CAMERA_CAPTURE_MEM,
# x  L8 x$ S/ `, L6 j' ^$ Z9 V            ACDK_SCENARIO_ID_CAMERA_BURST_CAPTURE_JPEG,
/ ^* h0 X& S7 \            ACDK_SCENARIO_ID_VIDEO_DECODE_MPEG4,
* ?  m1 Y( H" t& y0 ^# O- i            ACDK_SCENARIO_ID_VIDEO_DECODE_H263,
5 B8 I- H. s' e. Q& c            ACDK_SCENARIO_ID_VIDEO_DECODE_H264,
5 I; w  P0 T) M            ACDK_SCENARIO_ID_VIDEO_DECODE_WMV78,2 ~+ [- F4 R4 v" L/ x, y
            ACDK_SCENARIO_ID_VIDEO_DECODE_WMV9,3 m+ R  X  `! `3 u& _8 e
            ACDK_SCENARIO_ID_VIDEO_DECODE_MPEG2,
8 b- J8 H+ n' o$ d* k# u# G. e& g            ACDK_SCENARIO_ID_IMAGE_YUV2RGB,
+ P6 X" m' X1 u  y5 {            ACDK_SCENARIO_ID_IMAGE_RESIZE,/ j) @5 [) w8 H; l# U' S. O% ^
            ACDK_SCENARIO_ID_IMAGE_ROTATE,( Q8 n  f4 ~" B7 o1 i/ w
            ACDK_SCENARIO_ID_IMAGE_POST_PROCESS,% h9 n* c' J) t. D" Y# u' \# C
            ACDK_SCENARIO_ID_JPEG_RESIZE,, T& {/ L) _; r6 H) C' d
            ACDK_SCENARIO_ID_JPEG_DECODE,- t  @$ U5 u, W; q: T5 x1 O
            ACDK_SCENARIO_ID_JPEG_PARSE,4 ^- \! d/ C0 a8 t1 a' Y: @
            ACDK_SCENARIO_ID_JPEG_ENCODE,
) e8 j$ L2 l+ a. Q            ACDK_SCENARIO_ID_JPEG_ENCODE_THUMBNAIL,
- b5 x/ `5 y7 X# Y0 E3 [' O7 \            ACDK_SCENARIO_ID_DRIVER_IO_CONTROL,
3 f9 ~0 k0 [& D; {7 q$ b            ACDK_SCENARIO_ID_DO_NOT_CARE,
1 `  u5 \- _- K- A1 j8 V            ACDK_SCENARIO_ID_IMAGE_DSPL_BUFFER_ALLOC,1 ^0 [  C4 @0 Y# `* `9 F
            ACDK_SCENARIO_ID_TV_OUT,
: N3 Z0 \7 I& j3 `+ E$ }$ B            ACDK_SCENARIO_ID_MAX,' F2 T! ~9 Y) b  ^2 N. `/ d
            ACDK_SCENARIO_ID_VIDOE_ENCODE_WITHOUT_PREVIEW,; x) i% r+ p7 R$ O& F$ I7 ~/ v
            ACDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG_BACK_PREVIEW,
4 B9 O6 X$ V4 H3 e1 W7 ]/ E            ACDK_SCENARIO_ID_VIDEO_DECODE_RV8,; \: y- Z+ v6 C. F0 ~9 A# c
            ACDK_SCENARIO_ID_VIDEO_DECODE_RV9,1 R0 s6 [: W1 F$ S7 o
            ACDK_SCENARIO_ID_CAMERA_ZSD,
  J2 A$ m: ~& @6 ]8 H& S0 g$ H0 z        }ACDK_SCENARIO_ID_ENUM;
/ p% \! s  o" z9 `6 x        通过这个数组定义 Camera 的各种模式,并且给他们从 0 开始给一个模拟的 ID,通过这个ScenarioID 来控制 Camera 的工作模式是在拍照、摄像等等。
. _7 H, B! j6 G$ w# v9 H        想要了解*pSensorInfo 这个指针的内容就得看 MSDK_SENSOR_INFO_STRUCT 的定义. W  \, c2 ?$ s! X; G" `1 k. {% w' N
        #define MSDK_SENSOR_INFO_STRUCT ACDK_SENSOR_INFO_STRUCT, ]5 {7 T. m' Z

% o' k( u, P8 o2 i
发表于 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.