对高通代码结构以及编写技巧的学习和总结,不断更新…
数组和枚举定义的另类写法
方便后期添加新值,便于维护。增加一个值,不必去考虑数组或者枚举的大小,也不用去考虑位置和顺序。
//枚举类型
ADD_ENTRY(AEC_GET_EXPOSURE_PARAMS) /* Mask to get aec info. */ \
ADD_ENTRY(AEC_GET_META_INFO) /* Mask to get meta info. */ \
ADD_ENTRY(AEC_GET_REAL_GAIN_FROM_ISO) \
ADD_ENTRY(AEC_GET_STATS_REQUIRED) /* Mask to get stats type 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)
typedef enum
{
AEC_CORE_GET_ENUM_LIST(AEC_CORE_GENERATE_ENUM)
} aec_core_get_enum_type;
//字符串数组
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)
//# 是把参数字符串化,## 是将两个参数连为一个整体
static char *aec_biz_set_param_strings[AEC_SET_PARAM_MAX+1] = {
AEC_SET_PARAM_ENUM_LIST(AEC_PARAM_GENERATE_STRING)
};
//获取数组值(eventId的值)
return aec_biz_set_param_strings[eventId < AEC_SET_PARAM_MAX ?
eventId : AEC_SET_PARAM_MAX];用union去定义接口结构体
用union只需要最大的值的空间,节省空间。
加上type,可以利用switch对不同类型的请求做处理,在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;用函数指针实现多态
扩展性:把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化。
//c文件
//函数定义
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;注释
/*===========================================================================
* FUNCTION : set_parameters
*
* DESCRIPTION: set camera parameters
*
* PARAMETERS :
* @device : ptr to camera device struct
* @parms : string of packed parameters
*
* RETURN : int32_t type of status
* NO_ERROR -- success
* none-zero failure code
*==========================================================================*/能力集的使用
高通很多部分用到能力集,当时一直觉得这个一个多余的操作。后来有了各种各样的设备之后才知道了能力集的好处。
比如说不同的sensor,你会对每个sensor都写一套代码么?每次都在代码中加sensor型号的判断?不说代码复杂,但是肯定很乱。