libcamera_client.so这个lib里,有相机的相关参数,比如相机支持的场景模式参数、白平衡模式参数,对焦模式参数……等等
大部分参数是高通或google定义的标准参数,部分手机厂商不更改直接使用这些参数。
有些手机,被消费者批为没个性,甚至从电路板到模具外壳都一样,当然手机厂商终极目标就是千元机,为了节省研发成本和材料成本,这么做无可厚非。但其实这种手机,对于咱第三方开发者来讲也是省时省力,皆大欢喜。
而有些手机厂商则会新增一些自定义的参数以个性化,这样才不会沦为通用模具的大路货,手机售价也相应噌噌地往上涨,但逼格高的代价就是适配起来更麻烦,泛泰就属于这种。
同级适配msm-aosp可能不需要用到这个技巧,可以直接替换官方rom里的libcamera_client.so。
但在越级适配msm-aosp或CM等第三方rom的时候,就必须从源代码下手,编译出可配合高版本系统的libcamera_client.so
本文所属方法为笔者自己摸索总结的方法,可能也有其它更加方便快捷的方法。
最后,老生常谈,本文只可参考,切勿照搬。
通过查看frameworks/av/camera/Android.mk
可知,此文件夹编译后生成libcamera_client.so
对比相近版本的cm与msm-aosp的
frameworks/av/camera/CameraParameters.cpp
frameworks/av/include/camera/CameraParameters.h
先看cpp文件,左边为cm11,右边为msm-aosp4.4.2
可以看出cm比msm-aosp多出了许多类似
#ifdef OPPO_CAMERA_HARDWARE
#ifdef SAMSUNG_CAMERA_HARDWARE
等等各手机厂商特殊CameraParameters定义,以及各厂商自定义的导出函数
如果你的手机正好是CM11支持的手机厂商,那么就直接照抄cm11的frameworks/av/camera和frameworks/av/include/camera
然后在BoardConfig.mk里增加对应的的cflags,例如
COMMON_GLOBAL_CFLAGS += -DOPPO_CAMERA_HARDWARE
如果cm11正好不支持本机型,其实cm仍然不支持大多数手机厂商,那么苦逼开发者就必须自己手动分析CameraParameters
接下来要用到objdump这个工具,在源码源代码目录里的prebuilts/gcc/linux-x86/arm/arm-eabi-4.7/bin/arm-eabi-objdump,可以单独复制出来到任意目录使用
新建一个目录,把arm-eabi-objdump和需要分析的libcamera_client.so复制进去
./arm-eabi-objdump -h libcamera_client.so
libcamera_client.so: file format elf32-littlearm
Sections:
Idx Name Size VMA LMA File off Algn
0 .interp 00000013 00000134 00000134 00000134 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .dynsym 000044c0 00000148 00000148 00000148 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .dynstr 0000d6dd 00004608 00004608 00004608 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .hash 00002154 00011ce8 00011ce8 00011ce8 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .rel.dyn 0000aa80 00013e3c 00013e3c 00013e3c 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .rel.plt 00000560 0001e8bc 0001e8bc 0001e8bc 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
6 .plt 00000824 0001ee1c 0001ee1c 0001ee1c 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
7 .text 00009058 0001f640 0001f640 0001f640 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
8 .ARM.exidx 00001000 00028698 00028698 00028698 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
9 .ARM.extab 00000090 00029698 00029698 00029698 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
10 .rodata 0000188c 00029728 00029728 00029728 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
11 .data.rel.ro.local 00000010 0002c7f0 0002c7f0 0002b7f0 2**3
CONTENTS, ALLOC, LOAD, DATA
12 .fini_array 00000004 0002c800 0002c800 0002b800 2**2
CONTENTS, ALLOC, LOAD, DATA
13 .data.rel.ro 00008260 0002c808 0002c808 0002b808 2**3
CONTENTS, ALLOC, LOAD, DATA
14 .init_array 0000002c 00034a68 00034a68 00033a68 2**2
CONTENTS, ALLOC, LOAD, DATA
15 .dynamic 00000130 00034a94 00034a94 00033a94 2**2
CONTENTS, ALLOC, LOAD, DATA
16 .got 00000438 00034bc8 00034bc8 00033bc8 2**2
CONTENTS, ALLOC, LOAD, DATA
17 .data 00000014 00035000 00035000 00034000 2**2
CONTENTS, ALLOC, LOAD, DATA
18 .bss 00000034 00035014 00035014 00034014 2**2
ALLOC
19 .comment 00000010 00000000 00000000 00034014 2**0
CONTENTS, READONLY
20 .note.gnu.gold-version 0000001c 00000000 00000000 00034024 2**2
CONTENTS, READONLY
21 .ARM.attributes 00000036 00000000 00000000 00034040 2**0
CONTENTS, READONLY
其中.rodata和.text这2个Section是我们要重点关注的
.rodata里存有CameraParameters
.text里存有导出函数
./arm-eabi-objdump -d -T --section=.rodata libcamera_client.so > rodata.txt
./arm-eabi-objdump -d -T --section=.text libcamera_client.so > text.txt
分别取得对应的rodata.txt和text.txt用于进一步对比分析
对比官方rom与自己编译的aosp的rodata
左边为官方rom,右边为自己编译的aosp
滚动到文件中部,可以找到以尖括号包括的小节
00028eeb <_ZN7android16CameraParameters22KEY_AUTO_EXPOSURE_LOCKE>:
28eeb: 6f747561 7078652d 7275736f 6f6c2d65 auto-exposure-lo
28efb: 73006b63 ck.
查看frameworks/av/camera/CameraParameters.cpp对应的源代码可以知道
const char CameraParameters::KEY_AUTO_EXPOSURE_LOCK[] = “auto-exposure-lock”;
请读者自行思考其中的对应关系
如下总结成规律
固定开头:<_ZN7android16CameraParametersxx
常量名称:中间的部分,例如KEY_AUTO_EXPOSURE_LOCK
固定结尾:E>:
空格开头,以.结尾,长度太长的话可能分成多行,例如本例里的auto-exposure-lock,其中就是结尾的ck被分到第2行
这段里有所有CameraParameters参数,对比这个table就能找出2者的差异,从而补齐缺失的CameraParameters。
frameworks/av/camera/CameraParameters.cpp添加
#ifdef VEGA_CAMERA_HARDWARE
const char CameraParameters::KEY_SKY_COLOREXT_COORDINATES_B[] ="pantech-color-extraction-coordinates-b";
const char CameraParameters::KEY_SKY_COLOREXT_COORDINATES_G[] ="pantech-color-extraction-coordinates-g";
const char CameraParameters::KEY_SKY_COLOREXT_COORDINATES_R[] ="pantech-color-extraction-coordinates-r";
const char CameraParameters::KEY_SKY_COLOREXT_COORDINATES[] ="pantech-color-extraction-coordinates";
const char CameraParameters::KEY_SKY_COLOREXT_RGB_B[] ="pantech-colorextraction-rgb-b";
const char CameraParameters::KEY_SKY_COLOREXT_RGB_G[] ="pantech-colorextraction-rgb-g";
const char CameraParameters::KEY_SKY_COLOREXT_RGB_R[] ="pantech-colorextraction-rgb-r";
const char CameraParameters::SKY_COLOREXT_YELLOW[] ="color_yellow";
const char CameraParameters::SKY_COLOREXT_BLUE[] ="color_blue";
const char CameraParameters::SKY_COLOREXT_GREEN[] ="color_green";
const char CameraParameters::SKY_COLOREXT_RED[] ="color_red";
const char CameraParameters::SKY_COLOREXT_TOUCH[] ="color_touch";
const char CameraParameters::SKY_COLOREXT_OFF[] ="off";
const char CameraParameters::KEY_SKY_COLOREXTRACTION[] ="pantech-colorextraction";
const char CameraParameters::SKY_IPL_COLOR_DOT_WHITE[] ="pantech-ipl-color-dot-wht";
const char CameraParameters::SKY_IPL_COLOR_DOT_BLACK[] ="pantech-ipl-color-dot-blk";
const char CameraParameters::SKY_IPL_MONO_DOT[] ="pantech-ipl-mono-dot";
const char CameraParameters::SKY_IPL_FIXED_DOT[] ="pantech-ipl-fixed-dot";
const char CameraParameters::SKY_IPL_MINIATURE[] ="pantech-ipl-miniature";
const char CameraParameters::SKY_IPL_TEXT_BB_B[] ="pantech-ipl-blackboard-b";
const char CameraParameters::SKY_IPL_TEXT_WB_B[] ="pantech-ipl-whiteboard-b";
const char CameraParameters::SKY_IPL_TEXT_WB_C[] ="pantech-ipl-whiteboard-c";
const char CameraParameters::SKY_IPL_EFFECT_EXT_4[] ="pantech-ipl-effect-ext-4";
const char CameraParameters::SKY_IPL_EFFECT_EXT_3[] ="pantech-ipl-effect-ext-3";
const char CameraParameters::SKY_IPL_EFFECT_EXT_2[] ="pantech-ipl-effect-ext-2";
const char CameraParameters::SKY_IPL_EFFECT_EXT_1[] ="pantech-ipl-effect-ext-1";
const char CameraParameters::SKY_IPL_SKIN_DETECTOR[] ="pantech-ipl-skincolorextract";
const char CameraParameters::SKY_IPL_DITHER_BW_M[] ="pantech-ipl-ditherbw-m";
const char CameraParameters::SKY_IPL_DITHER_BW_C[] ="pantech-ipl-ditherbw-c";
const char CameraParameters::SKY_IPL_COLOR_CHANGE_3[] ="pantech-ipl-colorchange-4";
const char CameraParameters::SKY_IPL_COLOR_CHANGE_2[] ="pantech-ipl-colorchange-3";
const char CameraParameters::SKY_IPL_COLOR_CHANGE_1[] ="pantech-ipl-colorchange-2";
const char CameraParameters::SKY_IPL_COLOR_CHANGE_0[] ="pantech-ipl-colorchange-1";
const char CameraParameters::SKY_IPL_NEON[] ="pantech-ipl-neon";
const char CameraParameters::SKY_IPL_EMBOSS[] ="pantech-ipl-emboss";
const char CameraParameters::SKY_IPL_SOLARIZE[] ="pantech-ipl-solarize";
const char CameraParameters::SKY_IPL_SKETCH_M[] ="pantech-ipl-sketch-m";
const char CameraParameters::SKY_IPL_SKETCH_C[] ="pantech-ipl-sketch-c";
const char CameraParameters::SKY_IPL_CARTOON_M[] ="pantech-ipl-cartoon-m";
const char CameraParameters::SKY_IPL_CARTOON_C[] ="pantech-ipl-cartoon-c";
const char CameraParameters::SKY_IPL_POSTER_CARTOON_M[] ="pantech-ipl-poster-cartoon-m";
const char CameraParameters::SKY_IPL_POSTER_CARTOON_C[] ="pantech-ipl-poster-cartoon-c";
const char CameraParameters::SKY_IPL_BEAUTY[] ="pantech-ipl-beauty";
const char CameraParameters::SKY_IPL_OFF[] ="pantech-ipl-off";
const char CameraParameters::LLS_ON[] ="on";
const char CameraParameters::LLS_OFF[] ="off";
const char CameraParameters::KEY_LLS_MODE[] ="pantech-lls-mode";
const char CameraParameters::KEY_LLS[] ="pantech-lls";
const char CameraParameters::HDR_ON[] ="on";
const char CameraParameters::HDR_OFF[] ="off";
const char CameraParameters::FLASH_ON[] ="on";
const char CameraParameters::FLASH_OFF[] ="off";
const char CameraParameters::KEY_FLASH[] ="pantech-flash";
const char CameraParameters::VTS_ON[] ="on";
const char CameraParameters::VTS_OFF[] ="off";
const char CameraParameters::KEY_VTS[] ="pantech-vts";
const char CameraParameters::FLASH_MODE_TORCH_FLASH[] ="torch_flash";
#endif
frameworks/av/include/camera/CameraParameters.h添加
#ifdef VEGA_CAMERA_HARDWARE
static const char KEY_SKY_COLOREXT_COORDINATES_B[];
static const char KEY_SKY_COLOREXT_COORDINATES_G[];
static const char KEY_SKY_COLOREXT_COORDINATES_R[];
static const char KEY_SKY_COLOREXT_COORDINATES[];
static const char KEY_SKY_COLOREXT_RGB_B[];
static const char KEY_SKY_COLOREXT_RGB_G[];
static const char KEY_SKY_COLOREXT_RGB_R[];
static const char SKY_COLOREXT_YELLOW[];
static const char SKY_COLOREXT_BLUE[];
static const char SKY_COLOREXT_GREEN[];
static const char SKY_COLOREXT_RED[];
static const char SKY_COLOREXT_TOUCH[];
static const char SKY_COLOREXT_OFF[];
static const char KEY_SKY_COLOREXTRACTION[];
static const char SKY_IPL_COLOR_DOT_WHITE[];
static const char SKY_IPL_COLOR_DOT_BLACK[];
static const char SKY_IPL_MONO_DOT[];
static const char SKY_IPL_FIXED_DOT[];
static const char SKY_IPL_MINIATURE[];
static const char SKY_IPL_TEXT_BB_B[];
static const char SKY_IPL_TEXT_WB_B[];
static const char SKY_IPL_TEXT_WB_C[];
static const char SKY_IPL_EFFECT_EXT_4[];
static const char SKY_IPL_EFFECT_EXT_3[];
static const char SKY_IPL_EFFECT_EXT_2[];
static const char SKY_IPL_EFFECT_EXT_1[];
static const char SKY_IPL_SKIN_DETECTOR[];
static const char SKY_IPL_DITHER_BW_M[];
static const char SKY_IPL_DITHER_BW_C[];
static const char SKY_IPL_COLOR_CHANGE_3[];
static const char SKY_IPL_COLOR_CHANGE_2[];
static const char SKY_IPL_COLOR_CHANGE_1[];
static const char SKY_IPL_COLOR_CHANGE_0[];
static const char SKY_IPL_NEON[];
static const char SKY_IPL_EMBOSS[];
static const char SKY_IPL_SOLARIZE[];
static const char SKY_IPL_SKETCH_M[];
static const char SKY_IPL_SKETCH_C[];
static const char SKY_IPL_CARTOON_M[];
static const char SKY_IPL_CARTOON_C[];
static const char SKY_IPL_POSTER_CARTOON_M[];
static const char SKY_IPL_POSTER_CARTOON_C[];
static const char SKY_IPL_BEAUTY[];
static const char SKY_IPL_OFF[];
static const char LLS_ON[];
static const char LLS_OFF[];
static const char KEY_LLS_MODE[];
static const char KEY_LLS[];
static const char HDR_ON[];
static const char HDR_OFF[];
static const char FLASH_ON[];
static const char FLASH_OFF[];
static const char KEY_FLASH[];
static const char VTS_ON[];
static const char VTS_OFF[];
static const char KEY_VTS[];
static const char FLASH_MODE_TORCH_FLASH[];
#endif
以泛泰A910为例,如下:
_ZN7android16CameraParameters29setColorExtractionCoordinatesEii
_ZN7android16CameraParameters23setColorExtractionRGB_BEii
_ZN7android16CameraParameters23setColorExtractionRGB_GEii
_ZN7android16CameraParameters23setColorExtractionRGB_REii
_ZNK7android16CameraParameters29getColorExtractionCoordinatesEPiS1_
_ZNK7android16CameraParameters23getColorExtractionRGB_BEPiS1_
_ZNK7android16CameraParameters23getColorExtractionRGB_GEPiS1_
_ZNK7android16CameraParameters23getColorExtractionRGB_REPiS1_
固定开头:_ZN7android16CameraParametersxx
函数名称:中间的部分,例如setColorExtractionCoordinates
不固定结尾:Eii、EPiS1_,总是以Exxx为形式
随便找一个以Eii结尾的已有函数来参考,比如_ZN7android16CameraParameters14setPictureSizeEii
找到对应的源代码:
void CameraParameters::setPictureSize(int width, int height)
那么可以猜测Eii即代表输入参数为2个int,即(int x, int y)
最终还原出函数如下
void CameraParameters::setColorExtractionCoordinates(int x, int y) {}
void CameraParameters::setColorExtractionRGB_B(int x, int y) {}
void CameraParameters::setColorExtractionRGB_G(int x, int y) {}
void CameraParameters::setColorExtractionRGB_R(int x, int y) {}
随便找一个以EPiS1_结尾的已有函数来参考,比如ZNK7android16CameraParameters14getPictureSizeEPiS1
找到对应的源代码:
void CameraParameters::getPictureSize(int *width, int *height) const
那么可以猜测EPiS1_即代表输入参数为2个int * const,即(int *x, int *y) const
最终还原出函数如下
void CameraParameters::getColorExtractionCoordinates(int *x, int *y) const{}
void CameraParameters::getColorExtractionRGB_B(int *x, int *y) const{}
void CameraParameters::getColorExtractionRGB_G(int *x, int *y) const{}
void CameraParameters::getColorExtractionRGB_R(int *x, int *y) const{}
**注意:咱还没能力通过反汇编还原成C代码,可能慢慢摸索可以做到,但实在太花时间。
在现在人人吃快餐搞移植的时代背景下,为了一个导出函数的实现研究十天半个月可能大部分人无法做到。
即使真的实现了,还要修改顶层的相机程序支持这些参数特效,这个工程量不是一般的大。
所以这里只补齐了函数,并未实现其中的方法。**
frameworks/av/camera/CameraParameters.cpp添加
#ifdef VEGA_CAMERA_HARDWARE
void CameraParameters::setColorExtractionCoordinates(int x, int y) {}
void CameraParameters::setColorExtractionRGB_B(int x, int y) {}
void CameraParameters::setColorExtractionRGB_G(int x, int y) {}
void CameraParameters::setColorExtractionRGB_R(int x, int y) {}
void CameraParameters::getColorExtractionCoordinates(int *x, int *y) const{}
void CameraParameters::getColorExtractionRGB_B(int *x, int *y) const{}
void CameraParameters::getColorExtractionRGB_G(int *x, int *y) const{}
void CameraParameters::getColorExtractionRGB_R(int *x, int *y) const{}
#endif
frameworks/av/include/camera/CameraParameters.h添加
#ifdef VEGA_CAMERA_HARDWARE
void setColorExtractionCoordinates(int x, int y);
void setColorExtractionRGB_B(int x, int y);
void setColorExtractionRGB_G(int x, int y);
void setColorExtractionRGB_R(int x, int y);
void getColorExtractionCoordinates(int *x, int *y) const;
void getColorExtractionRGB_B(int *x, int *y) const;
void getColorExtractionRGB_G(int *x, int *y) const;
void getColorExtractionRGB_R(int *x, int *y) const;
#endif
用vs2013编写一个小程序,用来读取rodata,因为CameraParameters比较多,还是用程序批量处理比较方便
运行需要.netframework 4.5,提供程序和源代码以供读者参考。
http://download.csdn.net/detail/benjaminwan/8606769
界面如下:
open_rodata用于打开objdump的输出文件rodata.txt
Export_CSV用于把解析结果导出成CSV,方便用Bcompare对比