对高通代码结构以及编写技巧的学习和总结,不断更新…
数组和枚举定义的另类写法
用列表的形式去表示数组和枚举类型
优点:
方便后期添加新值,便于维护。增加一个值,不必去考虑数组或者枚举的大小,也不用去考虑位置和顺序。
#define AEC_CORE_GET_ENUM_LIST(ADD_ENTRY) \ ADD_ENTRY(AEC_GET_EXPOSURE_PARAMS) \ ADD_ENTRY(AEC_GET_META_INFO) \ ADD_ENTRY(AEC_GET_REAL_GAIN_FROM_ISO) \ ADD_ENTRY(AEC_GET_STATS_REQUIRED) \ ADD_ENTRY(AEC_GET_UNIFIED_FLASH) \ ADD_ENTRY(AEC_GET_RGN_SKIP_PATTERN) \ ADD_ENTRY(AEC_GET_RELOAD_EXPOSURE_PARAMS) \ ADD_ENTRY(AEC_GET_LED_CAL_CONFIG) \ ADD_ENTRY(AEC_GET_MAX) #define AEC_CORE_GENERATE_ENUM(ENUM) ENUM, typedef enum { AEC_CORE_GET_ENUM_LIST(AEC_CORE_GENERATE_ENUM) } aec_core_get_enum_type;
|
#define AEC_SET_PARAM_ENUM_LIST(ADD_ENTRY) \ ADD_ENTRY(AEC_SET_PARAM_INVALID) \ ADD_ENTRY(AEC_SET_PARAM_INIT_CHROMATIX_SENSOR) \ ADD_ENTRY(AEC_SET_PARAM_EXP_COMPENSATION) \ ADD_ENTRY(AEC_SET_PARAM_BRIGHTNESS_LVL) \ ADD_ENTRY(AEC_SET_PARAM_MAX)
#define AEC_PARAM_GENERATE_STRING(STRING) #STRING, static char *aec_biz_set_param_strings[AEC_SET_PARAM_MAX+1] = { AEC_SET_PARAM_ENUM_LIST(AEC_PARAM_GENERATE_STRING) };
return aec_biz_set_param_strings[eventId < AEC_SET_PARAM_MAX ?
eventId : AEC_SET_PARAM_MAX];
|
用union去定义接口结构体
优点:
typedef struct { aec_set_enum_type type; union { aec_set_parameter_init_t init_param; aec_bracket_t aec_bracket; int32 video_hdr; aec_core_hdr_type snapshot_hdr; aec_precapture_trigger_t aec_trigger; boolean est_for_af; aec_algo_ramp_test_type ramp_test; } u; } aec_core_set_param_type;
|
用函数指针实现多态
优点:
- 扩展性:把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化。
boolean aec_biz_set_param(aec_set_parameter_t *param, aec_output_data_t *output, uint8_t num_of_outputs, void *aec_obj){ …… }
void aec_biz_load_function(aec_object_t *aec_object)
{
if (!aec_object) { return NULL; } aec_object->set_parameters = aec_biz_set_param; aec_object->get_parameters = aec_biz_get_param; aec_object->process = aec_biz_process; aec_object->init = aec_biz_init; aec_object->deinit = aec_biz_destroy; aec_object->iso_to_real_gain = aec_biz_map_iso_to_real_gain; aec_object->get_version = aec_biz_get_version; }
typedef boolean (* aec_set_parameters_func)(aec_set_parameter_t *param, aec_output_data_t *output, uint8_t num_of_outputs, void *aec_obj); typedef boolean (* aec_get_parameters_func)(aec_get_parameter_t *param, void *aec_obj); typedef boolean (* aec_process_func)(stats_t *stats, void *aec_obj, aec_output_data_t *output, uint8_t num_of_ouputs); typedef void (* aec_callback_func)(aec_output_data_t *output, void *port); typedef void *(* aec_init_func)(void *aec_lib); typedef void (* aec_deinit_func)(void *aec); typedef float (* aec_iso_to_real_gain)(void *aec_obj, uint32_t iso, uint8_t camera_id); typedef boolean (* aec_get_version)(void *aec_obj, Q3a_version_t *version, uint8_t camera_id); typedef struct _aec_object { pthread_mutex_t obj_lock; void *aec; aec_set_parameters_func set_parameters; aec_get_parameters_func get_parameters; aec_process_func process; aec_init_func init; aec_deinit_func deinit; aec_output_data_t output; aec_iso_to_real_gain iso_to_real_gain; q3a_custom_data_t aec_custom_param; aec_get_version get_version; } aec_object_t;
|
注释
由于变量可能到处被定义和引用,当它被引用的次数很多时,就很难找到这个变量的含义。可以变量值前面需要加上@,这样搜索变量的含义很快。
在高通代码中搜索某个变量的意义的时候,也可以使用这个方法进行查找。
下面是注释范例:
能力集的使用
高通很多部分用到能力集,当时一直觉得这个一个多余的操作。后来有了各种各样的设备之后才知道了能力集的好处。
比如说不同的sensor,你会对每个sensor都写一套代码么?每次都在代码中加sensor型号的判断?不说代码复杂,但是肯定很乱。
如果每个sensor都有自己的能力集之后,代码中只需要根据能力集的配置进行判断,就屏蔽了对sensor型号的判断,即使是新增一个sensor型号,也只需要多配置一组能力集,十分方便。继续推广开来,视频流也有自己的能力集(如分辨率,格式等),每个设备也有自己的能力集(如不同的镜头,sensor型号,各种功能的配置),这样就更加容易实现各种各样设备的管理。
能力集中可能会用到多组配置,比如多种分辨率有不同的配置。这个时候可以在结构体里面定义数组,也可以定义指针。数组会提前分配内存,可能会分配大了,占用空间,指针的话分配的内存可控。
高通的能力集也经历了几个阶段:8056的老代码是把能力集写到代码里面,编译成动态库,进行调用的。后来变成了利用xml进行配置,在设备中读取进行配置。再接下来,是在本地将xml编译成bin文件,在设备中进行读取,减少xml解码的时间,提高效率。
typedef struct power_setting_t { int seq_val; int delay; }; typedef struct power_setting_array { power_setting_t power_setting_a[10]; power_setting_t *power_setting_b; int num; }; static power_setting_t test_b[] = { { .seq_val = 1, .delay = 1, }, { .seq_val = 2, .delay = 2, }}; static power_setting_array test = { .power_setting_a = { { seq_val : 1, delay : 1, }, { .seq_val = 2, .delay = 2, }}, .power_setting_b = test_b, .num = sizeof(test_b) / sizeof(test_b[0]), };
|
回调函数的注册和使用