高通chromatix加载流程

研究加载流程之前学习两个知识点

一、hash map

散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。

给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希(Hash)表,函数f(key)为哈希(Hash) 函数。


image.png

以上是百度的定义,简而言之,散列表是一种数据结构,但是其查找效率比较高,高通的chromatix name就是存放在哈希表中的。

/*创建一个哈希表*/
boolean hash_create(hash_type* obj, uint32_t hashSize)
{
  hash_node_type* table;
  uint32_t        allocSize;

  RETURN_ON_NULL(obj);

  if (hashSize < DEFAULT_HASH_SIZE)
    hashSize = DEFAULT_HASH_SIZE;

  allocSize = hashSize * sizeof(hash_node_type);  //创建一个hashsize大小的哈希表
  table = (hash_node_type*) malloc(allocSize);
  if (table == NULL) {
    SERR("failed : memory allocation");
    return FALSE;
  }
  memset(table, 0, allocSize );

  obj->count      = 0;
  obj->table      = table;
  obj->table_size = hashSize;

  return TRUE;
}
//往哈希表添加数据
boolean hash_add(hash_type* obj, const char *key,
  void *data_hdl, void *data_sym, uint32_t cIndex)
{
  uint32_t  hash_key, index;
  HASH_NODE node;

  RETURN_ON_NULL(obj);
  RETURN_ON_NULL(key);
  RETURN_ON_NULL(data_hdl);
  RETURN_ON_NULL(data_sym);

  /* create hash key from a given actual key (string) */
  hash_key = hash_makeHashKey(key);   //可以看出哈希函数为hash_makeHashKey
  index = hash_key % obj->table_size;

  /* check if (key:data) is already in hash */
  node = (obj->table + index)->next;
  while (node) {
    if (hash_key == node->hash_key) {   //哈希键值存在,则返回错误
      SLOW("%s is ALREADY in hash (%s:%u)", key, node->key, node->hash_key);
      return FALSE;
    }
    node = node->next;
  }

  node = (hash_node_type *)malloc(sizeof(hash_node_type));  //新建一个节点
  if (node == NULL) {
    SERR("failed to allocate a node");
    return FALSE;
  }

  snprintf(node->key, 256, "%s", key);   //赋值给节点
  node->hash_key = hash_key;    //存储生成的哈希键值
  node->data_hdl = data_hdl;  //赋值给节点
  node->data_sym = data_sym;   //赋值给节点
  node->cIndex   = cIndex;       //节点在哈希表中的第一层索引

  SLOW("%s : hash_key %u : hash table index %d",
    key, hash_key, index);

  node->prev = obj->table + index;   //以头插法将节点插入
  node->next = (obj->table + index)->next;
  if (node->next != NULL)
    node->next->prev = node;
  (obj->table + index)->next = node;

  ++obj->count;

  return TRUE;
}
//通过键值查找数据
boolean hash_find(hash_type* obj, const char *key,
  void **data_sym, uint32_t *cIndex)
{
  uint32_t  hash_key, index;
  HASH_NODE node;

  RETURN_ON_NULL(obj);
  RETURN_ON_NULL(key);
  RETURN_ON_NULL(data_sym);
  RETURN_ON_NULL(cIndex);

  if (obj->count == 0) {
    SLOW("empty hash!");
    return FALSE;
  }

  /* create hash key from a given actual key (string) */
  hash_key = hash_makeHashKey(key);     //通过键值生成哈希键值
  index = hash_key % obj->table_size;   //得到表索引

  node = (obj->table + index)->next;  //遍历链表
  while (node) {
    if (hash_key == node->hash_key) {  //哈希键值相同,则查找结束,可以看书actual key通过哈希函数映射得到的哈希键值是唯一的
      SLOW("%s FOUND %s:key%u:data%p",
        key, node->key, node->hash_key, node->data_sym);
      *data_sym = node->data_sym;
      *cIndex = node->cIndex;
      return TRUE;
    }
    node = node->next;
  }

  *data_sym = NULL;
  SLOW("%s NOT in HASH", key);
  return FALSE;
}
//哈希函数,实际调用crc32
static uint32_t hash_makeHashKey(const char *key)
{
  return crc32(0, key, strlen(key));
}

二、LRU map

LRU(Least Recently Used)表也是一种数据结构,利用LRU算法可以比较方便的找到最新最少使用的节点。


image.png

这里根据算法画了几个图,第一张是初始化部分,创建一个长度为30的LRU表,可以先看看结构体定义

typedef struct {   
  LIST_NODE *list_node;  //LRU表头,是个二级指针,也可看作数组的首地址
  uint32_t   node_count;  /* 最大节点数,创建表时赋值*/

  list_type  list;  //存储当前list的头尾数据以及list大小
} chromatix_lru_type;  //LRU表结构体
typedef struct {
  uint32_t count;   /* number of nodes */

  LIST_NODE front;  /* the first item in list */
  LIST_NODE back;   /* the last item in list */
} list_type;
typedef struct list_node_tag {
  struct list_node_tag *prev;
  struct list_node_tag *next;

  uint32_t cIndex;

  char     key[256];
} list_node_type, *LIST_NODE;
boolean lru_create(chromatix_lru_type *obj, uint32_t node_count)  //创建函数
{
  RETURN_ON_NULL(obj);

  if (node_count == 0) {
    SERR("wrong node count");
    return FALSE;
  }

  obj->list_node = (LIST_NODE *)malloc(sizeof(LIST_NODE) * node_count); //直接开辟了所有节点内存
  if (obj->list_node == NULL) {
    SERR("failed : memory allocation");
    return FALSE;
  }

  /* create list structure */
  list_create(&obj->list);

  obj->node_count = node_count;

  return TRUE;
}
image.png

上图是表添加节点流程,创建LRU表后所有节点处于未使用状态,当需要添加节点元素时有两种情况,第一种是当前开辟的所有节点还没有利用完,我们创建表时开辟了30个元素,所以前面三十个元素添加都是通过这种方式,第二种情况是所有节点已全部利用完,这时需要替换掉其中一个节点的方式插入,替换方式有两种,一种是替换掉最旧节点,一种是替换最新节点。上图表示以push_back的方式将节点插入表中

boolean lru_add(chromatix_lru_type *obj, const char *key, uint32_t *cIndex)
{
  LIST_NODE node;
  uint32_t  count;

  RETURN_ON_NULL(obj);
  RETURN_ON_NULL(cIndex);

  count = list_count(&obj->list);

  /* If cache has space, then use an empty slot.
     Otherwise, remove the least recent slot and return the slot */
  if (count < obj->node_count) {
    *cIndex = count;
    obj->list_node[*cIndex] = list_pushBack(&obj->list, *cIndex, key);
  } else {
    node = list_back(&obj->list);
    if (NULL == node)
    {
      return FALSE;
    }
    *cIndex = node->cIndex;

    list_popBack(&obj->list);
    obj->list_node[*cIndex] = list_pushFront(&obj->list, *cIndex, key);
  }

  return TRUE;
}
LIST_NODE list_pushBack(list_type *list, uint32_t cIndex, const char *key)
{
  LIST_NODE node = NULL;

  if (!list || !key) {
    SERR("failed NULL pointer detected");
    return NULL;
  }

  node = createNode(cIndex, key);
  if (!node) {
    SERR("failed: createNode");
    return NULL;
  }

  node->next = NULL;
  node->prev = list->back;

  if (list->back)
    list->back->next = node;

  list->back = node;
  if (!list->front)
    list->front = node;

  ++list->count;

  return node;
}

image.png

上图是更新一个cIndex=2的节点的场景,假如该键值的数据有变化,我们将其置为列表的最前端,首先将更新节点从list列表中删除,再创建一个新的节点,占用原来LRU表的坑位,将该节点置为list列表表头位置。list的back不变,front指针指向新更新的节点。下面是代码部分:

boolean lru_update(chromatix_lru_type *obj, uint32_t cIndex)
{
  LIST_NODE data;
  char      key[256];

  RETURN_ON_NULL(obj);

  data = obj->list_node[cIndex];
  RETURN_ON_NULL(data);

  snprintf(key, 256, "%s", data->key);
  SLOW("%s updated", data->key);

  list_erase(&obj->list, obj->list_node[cIndex]);  
  obj->list_node[cIndex] = list_pushFront(&obj->list, cIndex, key);

  return TRUE;
}
LIST_NODE list_pushFront(list_type *list, uint32_t cIndex, const char *key)
{
  LIST_NODE node = NULL;

  if (!list || !key) {
    SERR("failed NULL pointer detected");
    return NULL;
  }

  node = createNode(cIndex, key);
  if (!node) {
    SERR("failed: createNode");
    return NULL;
  }

  node->prev = NULL;
  node->next = list->front;

  if (list->front)
    list->front->prev = node;

  list->front = node;
  if (!list->back)
    list->back = node;

  ++list->count;

  return node;
}

三、chromatix加载

熟悉了这两种数据结构之后,接下来分析高通chromatix文件的加载流程,相信你也像我一样想知道,选用不用的分辨率是怎么加载对应的效果参数文件的,以及预览拍照录像模式下走的是哪一组参数。
初始化部分:
高通的效果参数文件是通过XML文件配置的,系统去解析XML文件,存储对应的key值,即各个模式下调用的参数文件名称,然后加载对应的库文件,用一个hash表来维护这些数据。

<ChromatixConfigurationRoot>
  <CommonChromatixInfo>
    <ChromatixName special_mode_mask="0">
      <ISPCommon>ov5675_common</ISPCommon>
      <PostProc>ov5675_postproc</PostProc>
    </ChromatixName>
  </CommonChromatixInfo>
  <ResolutionChromatixInfo>
    <ChromatixName sensor_resolution_index="0" special_mode_mask="0">
      <ISPPreview>ov5675_snapshot</ISPPreview>
      <ISPSnapshot>ov5675_snapshot</ISPSnapshot>
      <ISPVideo>ov5675_default_video</ISPVideo>
      <CPPPreview>ov5675_cpp_preview</CPPPreview>
      <CPPSnapshot>ov5675_cpp_snapshot</CPPSnapshot>
      <CPPVideo>ov5675_cpp_video</CPPVideo>
      <CPPLiveshot>ov5675_cpp_liveshot</CPPLiveshot>
      <A3Preview>ov5675_default_preview_3a</A3Preview>
      <A3Video>ov5675_zsl_video_3a</A3Video>
    </ChromatixName>
    <ChromatixName sensor_resolution_index="1" special_mode_mask="0">
      <ISPPreview>ov5675_snapshot</ISPPreview>
      <ISPSnapshot>ov5675_snapshot</ISPSnapshot>
      <ISPVideo>ov5675_default_video</ISPVideo>
      <CPPPreview>ov5675_cpp_preview</CPPPreview>
      <CPPSnapshot>ov5675_cpp_snapshot</CPPSnapshot>
      <CPPVideo>ov5675_cpp_video</CPPVideo>
      <CPPLiveshot>ov5675_cpp_liveshot</CPPLiveshot>
      <A3Preview>ov5675_default_preview_3a</A3Preview>
      <A3Video>ov5675_zsl_video_3a</A3Video>
    </ChromatixName>
    <ChromatixName sensor_resolution_index="2" special_mode_mask="0">
      <ISPPreview>ov5675_snapshot</ISPPreview>
      <ISPSnapshot>ov5675_snapshot</ISPSnapshot>
      <ISPVideo>ov5675_default_video</ISPVideo>
      <CPPPreview>ov5675_cpp_preview</CPPPreview>
      <CPPSnapshot>ov5675_cpp_snapshot</CPPSnapshot>
      <CPPVideo>ov5675_cpp_video</CPPVideo>
      <CPPLiveshot>ov5675_cpp_liveshot</CPPLiveshot>
      <A3Preview>ov5675_default_preview_3a</A3Preview>
      <A3Video>ov5675_zsl_video_3a</A3Video>
    </ChromatixName>
    <ChromatixName sensor_resolution_index="3" special_mode_mask="0">
      <ISPPreview>ov5675_snapshot</ISPPreview>
      <ISPSnapshot>ov5675_snapshot</ISPSnapshot>
      <ISPVideo>ov5675_default_video</ISPVideo>
      <CPPPreview>ov5675_cpp_preview</CPPPreview>
      <CPPSnapshot>ov5675_cpp_snapshot</CPPSnapshot>
      <CPPVideo>ov5675_cpp_video</CPPVideo>
      <CPPLiveshot>ov5675_cpp_liveshot</CPPLiveshot>
      <A3Preview>ov5675_default_preview_3a</A3Preview>
      <A3Video>ov5675_zsl_video_3a</A3Video>
    </ChromatixName>
  </ResolutionChromatixInfo>
</ChromatixConfigurationRoot>
需要对比设置chromatix的xml文件来看
static boolean sensor_xml_util_parse_chromatix_config(
  camera_module_config_t *configPtr)
{
  boolean                ret = FALSE;
  xmlNodePtr             nodePtr = NULL;
  xmlDocPtr              chromatixDocPtr = NULL;
  xmlNodePtr             chromatixRootPtr = NULL;
  char chromatix_xml_name[NAME_SIZE_MAX];

  /* Create the xml path */
  snprintf(chromatix_xml_name, NAME_SIZE_MAX, "%s%s.xml",
    CONFIG_XML_PATH, configPtr->chromatix_name); //取得xml路径 /data/vendor/camera/ov5675_chromatix.xml

  if (access(chromatix_xml_name, R_OK)) {
    SHIGH("cannot read file %s. Trying from system partition",
      chromatix_xml_name);
    /* Create the xml path from system partition */
    snprintf(chromatix_xml_name, NAME_SIZE_MAX, "%s%s.xml",
      CONFIG_XML_SYSTEM_PATH, configPtr->chromatix_name);
    if (access(chromatix_xml_name, R_OK)) {
      SERR("Cannot read file from %s. read failed",
        chromatix_xml_name);
      return FALSE;
    }
  }

  SLOW("reading from file %s", chromatix_xml_name);

  /* Get the Root pointer and Document pointer of XMl file */
  RETURN_ON_FALSE(sensor_xml_util_load_file(chromatix_xml_name,
    &chromatixDocPtr, &chromatixRootPtr, "ChromatixConfigurationRoot"));  //得到root节点

  configPtr->chromatix_info.size = 0;

  nodePtr = sensor_xml_util_get_node(chromatixRootPtr,
    "ResolutionChromatixInfo", 0);    //先解析ResolutionChromatixInfo节点
  if (nodePtr ==  NULL) {
    ret = FALSE;
    SERR("Could not get nodePtr for ResolutionChromatixInfo");
    goto CHROMATIX_CONFIG_EXIT;
  }

  ret = sensor_xml_util_parse_chromatix_name(
    configPtr, nodePtr, chromatixDocPtr, FALSE);
  if (ret == FALSE) {
    SERR("sensor_xml_util_parse_chromatix_name failed");
    goto CHROMATIX_CONFIG_EXIT;
  }

  nodePtr = sensor_xml_util_get_node(chromatixRootPtr,
    "CommonChromatixInfo", 0);  ////先解析CommonChromatixInfo节点
  if (nodePtr ==  NULL) {
    ret = FALSE;
    SERR("Could not get nodePtr for CommonChromatixInfo");
    goto CHROMATIX_CONFIG_EXIT;
  }

  ret = sensor_xml_util_parse_chromatix_name(
    configPtr, nodePtr, chromatixDocPtr, TRUE);
  if (ret == FALSE) {
    SERR("sensor_xml_util_parse_chromatix_name failed");
    goto CHROMATIX_CONFIG_EXIT;
  }

CHROMATIX_CONFIG_EXIT:
  sensor_xml_util_unload_file(chromatixDocPtr);
  return ret;
}

然后跟进sensor_xml_util_parse_chromatix_name函数:

static boolean sensor_xml_util_parse_chromatix_name(
  camera_module_config_t *configPtr, xmlNodePtr nodePtr,
  xmlDocPtr chromatixDocPtr, uint8_t is_common_chroamtix)
{
  ......
  chroamtix_arr_size = sensor_xml_util_get_num_nodes(nodePtr, "ChromatixName"); //chroamtix_arr_size=4
  if (chroamtix_arr_size == 0) {
    SERR("No nodes in ChromatixName");
    return FALSE;
  }

  SLOW("num_modes = %d", chroamtix_arr_size);

  for (count = 0; count < chroamtix_arr_size; count++, i++) {
    num_pairs = 0;

    if (is_common_chroamtix) {
      configPtr->chromatix_info.chromatix_name[i].sensor_resolution_index =
        0xFF;
    } else {
      strlcpy(key_value_pair[num_pairs].key, "sensor_resolution_index",
        MAX_KEY_SIZE);
      key_value_pair[num_pairs].value =
        &(configPtr->chromatix_info.chromatix_name[i].sensor_resolution_index);
      key_value_pair[num_pairs].value_type = XML_VALUE_UINT8;
      key_value_pair[num_pairs].nodeType = XML_ATTRIBUTE_NODE;
      num_pairs++;
    }

    memset(special_mode_str, 0, sizeof (special_mode_str));
    strlcpy(key_value_pair[num_pairs].key, "special_mode_mask", MAX_KEY_SIZE);
    key_value_pair[num_pairs].value = special_mode_str;
    key_value_pair[num_pairs].value_type = XML_VALUE_STRING;
    key_value_pair[num_pairs].nodeType = XML_ATTRIBUTE_NODE;
    num_pairs++;

    strlcpy(key_value_pair[num_pairs].key, "ISPCommon", MAX_KEY_SIZE);
    key_value_pair[num_pairs].value =
      configPtr->chromatix_info.chromatix_name[i].isp_common;
    key_value_pair[num_pairs].value_type = XML_VALUE_STRING;
    key_value_pair[num_pairs].nodeType = XML_ELEMENT_NODE;
    num_pairs++;

    strlcpy(key_value_pair[num_pairs].key, "ISPPreview", MAX_KEY_SIZE);
    key_value_pair[num_pairs].value =
      configPtr->chromatix_info.chromatix_name[i].isp_preview;
    key_value_pair[num_pairs].value_type = XML_VALUE_STRING;
    key_value_pair[num_pairs].nodeType = XML_ELEMENT_NODE;
    num_pairs++;

    strlcpy(key_value_pair[num_pairs].key, "ISPSnapshot", MAX_KEY_SIZE);
    key_value_pair[num_pairs].value =
      configPtr->chromatix_info.chromatix_name[i].isp_snapshot;
    key_value_pair[num_pairs].value_type = XML_VALUE_STRING;
    key_value_pair[num_pairs].nodeType = XML_ELEMENT_NODE;
    num_pairs++;

    strlcpy(key_value_pair[num_pairs].key, "ISPVideo", MAX_KEY_SIZE);
    key_value_pair[num_pairs].value =
      configPtr->chromatix_info.chromatix_name[i].isp_video;
    key_value_pair[num_pairs].value_type = XML_VALUE_STRING;
    key_value_pair[num_pairs].nodeType = XML_ELEMENT_NODE;
    num_pairs++;

    strlcpy(key_value_pair[num_pairs].key, "CPPPreview", MAX_KEY_SIZE);
    key_value_pair[num_pairs].value =
      configPtr->chromatix_info.chromatix_name[i].cpp_preview;
    key_value_pair[num_pairs].value_type = XML_VALUE_STRING;
    key_value_pair[num_pairs].nodeType = XML_ELEMENT_NODE;
    num_pairs++;

    strlcpy(key_value_pair[num_pairs].key, "CPPSnapshot", MAX_KEY_SIZE);
    key_value_pair[num_pairs].value =
      configPtr->chromatix_info.chromatix_name[i].cpp_snapshot;
    key_value_pair[num_pairs].value_type = XML_VALUE_STRING;
    key_value_pair[num_pairs].nodeType = XML_ELEMENT_NODE;
    num_pairs++;

    strlcpy(key_value_pair[num_pairs].key, "CPPVideo", MAX_KEY_SIZE);
    key_value_pair[num_pairs].value =
      configPtr->chromatix_info.chromatix_name[i].cpp_video;
    key_value_pair[num_pairs].value_type = XML_VALUE_STRING;
    key_value_pair[num_pairs].nodeType = XML_ELEMENT_NODE;
    num_pairs++;

    strlcpy(key_value_pair[num_pairs].key, "CPPLiveshot", MAX_KEY_SIZE);
    key_value_pair[num_pairs].value =
      configPtr->chromatix_info.chromatix_name[i].cpp_liveshot;
    key_value_pair[num_pairs].value_type = XML_VALUE_STRING;
    key_value_pair[num_pairs].nodeType = XML_ELEMENT_NODE;
    num_pairs++;

    strlcpy(key_value_pair[num_pairs].key, "PostProc", MAX_KEY_SIZE);
    key_value_pair[num_pairs].value =
      configPtr->chromatix_info.chromatix_name[i].postproc;
    key_value_pair[num_pairs].value_type = XML_VALUE_STRING;
    key_value_pair[num_pairs].nodeType = XML_ELEMENT_NODE;
    num_pairs++;

    strlcpy(key_value_pair[num_pairs].key, "A3Preview", MAX_KEY_SIZE);
    key_value_pair[num_pairs].value =
      configPtr->chromatix_info.chromatix_name[i].a3_preview;
    key_value_pair[num_pairs].value_type = XML_VALUE_STRING;
    key_value_pair[num_pairs].nodeType = XML_ELEMENT_NODE;
    num_pairs++;

    strlcpy(key_value_pair[num_pairs].key, "A3Video", MAX_KEY_SIZE);
    key_value_pair[num_pairs].value =
      configPtr->chromatix_info.chromatix_name[i].a3_video;
    key_value_pair[num_pairs].value_type = XML_VALUE_STRING;
    key_value_pair[num_pairs].nodeType = XML_ELEMENT_NODE;
    num_pairs++;

    strlcpy(key_value_pair[num_pairs].key, "External", MAX_KEY_SIZE);
    key_value_pair[num_pairs].value =
      configPtr->chromatix_info.chromatix_name[i].external;
    key_value_pair[num_pairs].value_type = XML_VALUE_STRING;
    key_value_pair[num_pairs].nodeType = XML_ELEMENT_NODE;
    num_pairs++;

    strlcpy(key_value_pair[num_pairs].key, "Iot", MAX_KEY_SIZE);
    key_value_pair[num_pairs].value =
      configPtr->chromatix_info.chromatix_name[i].iot;
    key_value_pair[num_pairs].value_type = XML_VALUE_STRING;
    key_value_pair[num_pairs].nodeType = XML_ELEMENT_NODE;
    num_pairs++;
    RETURN_ON_FALSE(sensor_xml_util_get_node_data(chromatixDocPtr, nodePtr,
      "ChromatixName", key_value_pair, num_pairs, count));  //真正读取xml文件节点内容
    /*key_value_pair只是一个临时局部变量,为了方便xml节点的解析,最终节点内容解析到configPtr- 
     >chromatix_info.chromatix_name中*/
    RETURN_ON_FALSE(sensor_xml_util_parse_special_mode(special_mode_str,
        &(configPtr->chromatix_info.chromatix_name[i]))); 
    }

  configPtr->chromatix_info.size+= chroamtix_arr_size;
  return TRUE;
}

最终节点内容存储在chromatix_info中,共有5组输入,res 4组,common一组,结构体定义如下:

typedef struct {
  unsigned char special_mode_type;
  unsigned long long int special_mode_mask;
  unsigned char sensor_resolution_index;
  char isp_common[NAME_SIZE_MAX];
  char isp_preview[NAME_SIZE_MAX];
  char isp_snapshot[NAME_SIZE_MAX];
  char isp_video[NAME_SIZE_MAX];
  char cpp_preview[NAME_SIZE_MAX];
  char cpp_snapshot[NAME_SIZE_MAX];
  char cpp_video[NAME_SIZE_MAX];
  char cpp_liveshot[NAME_SIZE_MAX];
  char postproc[NAME_SIZE_MAX];
  char a3_preview[NAME_SIZE_MAX];
  char a3_video[NAME_SIZE_MAX];
  char external[NAME_SIZE_MAX];
  char iot[NAME_SIZE_MAX];
} module_chromatix_name_t;

typedef struct {
  module_chromatix_name_t chromatix_name[MAX_CHROMATIX_ARRAY];
  uint16_t size;
} module_chromatix_info_t;

chromatix_info存储的只是键值信息,那实际上我们还需要加载相应的效果参数库文件才行,毕竟我们需要的不是一个名字,而是实际的参数值,参数是通过一个chromatix manager来管理的,库文件加载流程在module_sensor_init_chromatix中:

static boolean module_sensor_init_chromatix(void *data, void *eebin_hdl)
{
  module_sensor_bundle_info_t *s_bundle;
  sensor_lib_t                *sensor_lib_ptr;
  sensor_func_tbl_t            func_tbl;
  boolean                      rc = TRUE;

  SLOW("Enter");

  RETURN_ON_NULL(data);

  s_bundle = (module_sensor_bundle_info_t *)data;
  sensor_lib_ptr = s_bundle->sensor_lib_params->sensor_lib_ptr;

  /* No EEPROM */
  if (s_bundle->sensor_info->subdev_id[SUB_MODULE_EEPROM] == -1) {
    rc = cm_create(&s_bundle->chromatix_manager,
      s_bundle->sensor_info->sensor_name,
      &s_bundle->sensor_common_info.camera_config.chromatix_info,
      NULL, eebin_hdl);
    if (rc == FALSE) {
      SERR("failed: create cm");
      return FALSE;
    }
  /* EEPROM : pass the eeprom handle for calibration */
  } else {
    eeprom_sub_module_init(&func_tbl);

    if (func_tbl.open((void **)&s_bundle->eeprom_data,
           &s_bundle->subdev_info[SUB_MODULE_EEPROM]) < 0) {
      SERR("Failed EEPROM_OPEN");
      return FALSE;
    }

    rc = cm_create(&s_bundle->chromatix_manager,
      s_bundle->sensor_info->sensor_name,
      &s_bundle->sensor_common_info.camera_config.chromatix_info,
      s_bundle->eeprom_data, eebin_hdl);
    if (rc == FALSE) {
      SERR("failed: create cm");
      if (func_tbl.close(s_bundle->eeprom_data) < 0)
        SERR("Failed EEPROM_CLOSE");
      return FALSE;
    }

    if (func_tbl.close(s_bundle->eeprom_data) < 0) {
      cm_destroy(&s_bundle->chromatix_manager);
      SERR("Failed EEPROM_CLOSE");
      return FALSE;
    }
  }

  SLOW("Exit");
  return TRUE;
}

我们只需要关注cm_create:

boolean cm_create(chromatix_manager_type* cm,
  const char *sensor_name,
  module_chromatix_info_t *chromatix_array,
  sensor_eeprom_data_t *eeprom_ctrl, void *eebin_hdl)
{
  module_chromatix_name_t *chromatix_name;
  uint32_t                 i;
  boolean                  rc;

  RETURN_ON_NULL(cm);
  RETURN_ON_NULL(sensor_name);
  /* chromatix_array can be NULL */
  /* eeprom_ctrl can be NULL */
  /* eebin_hdl can be NULL */

  SLOW("Enter for %s", sensor_name);

  if (chromatix_array->size == 0) {
    SERR("YUV sensor : no chromatix loading");
    return TRUE;
  }

  if (hash_create(&cm->hash, 0) == FALSE) {  //创建一个hash表
    SERR("failed to create hash"); 
    return FALSE;
  }

  if (lru_create(&cm->lru, MAX_CHROMATIX_COUNT) == FALSE) {  //创建一个LRU表
    SERR("failed to create LRU");
    return FALSE;
  }

  pthread_mutex_init(&cm->mutex, NULL);
  cm->mutex_created = TRUE;

  cm->eeprom_ctrl = eeprom_ctrl;
  if (eeprom_ctrl) {
    cm->eeprom_func = (sensor_func_tbl_t *)malloc(sizeof(sensor_func_tbl_t));
    RETURN_ON_NULL(cm->eeprom_func);
    eeprom_sub_module_init(cm->eeprom_func);
  } else
    cm->eeprom_func = NULL;

  cm->eebin_hdl = eebin_hdl;
  bin_ctl.cmd = EEPROM_BIN_GET_LIB_NAME_DATA;
  bin_ctl.ctl.q_num.type = EEPROM_BIN_LIB_CHROMATIX;

  /* add all chromatix libraries */
  for (i = 0; i < chromatix_array->size; i++) {
    chromatix_name = &chromatix_array->chromatix_name[i];

    rc = addLib(cm, chromatix_name->isp_common, EEPROM_CALIBRATE_LSC);
    CHECK_RETURN(rc);
    rc = addLib(cm, chromatix_name->isp_preview, EEPROM_CALIBRATE_WB_GREEN);
    CHECK_RETURN(rc);
    rc = addLib(cm, chromatix_name->isp_snapshot, EEPROM_CALIBRATE_WB_GREEN);
    CHECK_RETURN(rc);
    rc = addLib(cm, chromatix_name->isp_video, EEPROM_CALIBRATE_WB_GREEN);
    CHECK_RETURN(rc);
    rc = addLib(cm, chromatix_name->cpp_preview, 0);
    CHECK_RETURN(rc);
    rc = addLib(cm, chromatix_name->cpp_snapshot, 0);
    CHECK_RETURN(rc);
    rc = addLib(cm, chromatix_name->cpp_video, 0);
    CHECK_RETURN(rc);
    rc = addLib(cm, chromatix_name->cpp_liveshot, 0);
    CHECK_RETURN(rc);
    rc = addLib(cm, chromatix_name->postproc, 0);
    CHECK_RETURN(rc);
    rc = addLib(cm, chromatix_name->a3_video, EEPROM_CALIBRATE_WB);
    CHECK_RETURN(rc);
    rc = addLib(cm, chromatix_name->a3_preview, EEPROM_CALIBRATE_WB);
    CHECK_RETURN(rc);
    rc = addLib(cm, chromatix_name->iot, 0);
    CHECK_RETURN(rc);

    if (lru_count(&cm->lru) == MAX_CHROMATIX_COUNT) {
      SERR("HASH cache is full");
      break;
    }
  }

  lru_traverse(&cm->lru);

  SLOW("Exit");

  return TRUE;

ERROR:
  if (cm->mutex_created) {
    pthread_mutex_destroy(&cm->mutex);
    cm->mutex_created = FALSE;
  }
  SERR("failed");
  return FALSE;
}
==》
static boolean addLib(chromatix_manager_type* cm, const char *key,
  int32_t cal_type)
{
  void    *data_hdl = NULL;
  void    *data_sym = NULL;
  uint32_t cIndex;
  int32_t  rc;

  if (strlen(key) == 0) return TRUE;

  SLOW("chromatix: %s", key);

  if (lru_count(&cm->lru) == MAX_CHROMATIX_COUNT) {
    SERR("HASH cache is full");
    return TRUE;
  }

  /* check if chromatix library is already in hash */
  if (hash_find(&cm->hash, key, &data_sym, &cIndex) == TRUE)
    return TRUE;

  if (addLib_getSymbol(cm, key, cal_type) == NULL) {
    SERR("failed to add chromatix to hash");
    return FALSE;
  }

  return TRUE;
}
==》
static void* addLib_getSymbol(chromatix_manager_type* cm, const char *key,
  int32_t cal_type)
{
  void    *data_hdl = NULL;
  void    *data_sym = NULL;
  uint32_t cIndex;
  int32_t  rc;

  if (key == NULL) return NULL;

  SLOW("chromatix: %s", key);

  /* open library */
  bin_ctl.ctl.name_data.lib_name = (char *)key;
  bin_ctl.ctl.name_data.path = NULL;
  if (cm->eebin_hdl)
    if (eebin_interface_control(cm->eebin_hdl, &bin_ctl) < 0)
      SERR("No Camera Multimodule data.");

  rc = load_chromatix(key, bin_ctl.ctl.name_data.path,
    &data_hdl, &data_sym);   
//这里就是加载效果参数库文件的地方了,key表示文件名称,比如ov5675_cpp_preview,data_hdl表示打开库文件操作句柄,data_sym表示参数数据指针。
  if (rc != SENSOR_SUCCESS) {
    SERR("fail : load_chromatix %s", key);
    return NULL;
  }

  /* calibration */
  if (cm->eeprom_ctrl && cm->eeprom_func && cal_type > 0)
    ((sensor_func_tbl_t*)(cm->eeprom_func))->process(
      cm->eeprom_ctrl, cal_type, data_sym);

  if (lru_add(&cm->lru, key, &cIndex) == FALSE)   
    goto ERROR;
  if (hash_add(&cm->hash, key, data_hdl, data_sym, cIndex)
    == FALSE)
    goto ERROR;

  return data_sym;

ERROR:
  unload_chromatix(data_hdl, data_sym);
  return NULL;
}
==》
cal_type参数表示的是加载库的时候做一次校准操作,如果有otp的话,会跑一回eeprom_func->process函数。

可以看出chromatix manager在初始化的时候,根据开机时候解析XML文件得到的chromatix_array加载所有的效果参数库文件,这里并没有做其他的分类处理,数据与数据之间是没有任何逻辑的,就是单纯将所有数据加载进hash表,LRU表存储键值,hash表存储键值和参数,两个表是通过cIndex建立关联的,cIndex由LRU表添加节点时生成,hash表节点中存储一份拷贝。

参数文件加载了以后,那应该如何加载对应的参数文件呢?首先通过module_chromatix_name_t的定义可以看出,isp,cpp,3a模块都支持preview,snapshot,video三种模式的参数,另外还有common模式,postproc模式,所以,只要保证我们能够确定好一组key值的配置,那系统就可以在pipeline的对应模块正确的加载对应的参数。当前调用哪组key值设置在sensor_get_cur_chromatix_name中:

static int32_t sensor_get_cur_chromatix_name(void *sctrl, void *data)
{
  sensor_ctrl_t               *ctrl;
  sensor_chromatix_params_t   *param;
  char                        **name;
  module_chromatix_name_t     *chromatix_name = NULL;
  sensor_submod_common_info_t *sensor_common_info = NULL;
  int16_t cur_res, i;

  RETURN_ERROR_ON_NULL(sctrl);
  RETURN_ERROR_ON_NULL(data);

  ctrl = (sensor_ctrl_t *)sctrl;
  param = (sensor_chromatix_params_t *)data;
  name = param->chromatix_lib_name;

  cur_res = (ctrl->s_data->cur_res <= SENSOR_INVALID_RESOLUTION) ?
    0 : ctrl->s_data->cur_res;
  if (cur_res >
    ctrl->s_data->sensor_common_info->camera_config.chromatix_info.size ||
    cur_res >= MAX_CHROMATIX_ARRAY) {
    SERR("failed cur res %d max size %d", cur_res,
      ctrl->s_data->sensor_common_info->camera_config.chromatix_info.size);
    return SENSOR_ERROR_INVAL;
  }

  sensor_common_info = ctrl->s_data->sensor_common_info;
  chromatix_name =
    &(sensor_common_info->camera_config.chromatix_info.chromatix_name[cur_res]);

  SLOW("special_mode_mask = %lld", sensor_common_info->special_mode_mask);

  for (i = 0; i < SENSOR_CHROMATIX_MAX; i++)
    name[i] = NULL;

  name[SENSOR_CHROMATIX_ISP_COMMON] =
    sensor_get_cur_chromatix_name_for_type(ctrl->s_data, CAMERA_MODULE_ISP,
      SENSOR_CHROMATIX_TYPE_COMMON);

  name[SENSOR_CHROMATIX_ISP] = name[SENSOR_CHROMATIX_ISP_SNAPSHOT] =
    sensor_get_cur_chromatix_name_for_type(ctrl->s_data, CAMERA_MODULE_ISP,
      SENSOR_CHROMATIX_TYPE_SNAPSHOT);

  name[SENSOR_CHROMATIX_CPP_PREVIEW] =
    sensor_get_cur_chromatix_name_for_type(ctrl->s_data, CAMERA_MODULE_CPP,
      SENSOR_CHROMATIX_TYPE_PREVIEW);

  name[SENSOR_CHROMATIX_CPP_SNAPSHOT] =
    sensor_get_cur_chromatix_name_for_type(ctrl->s_data, CAMERA_MODULE_CPP,
      SENSOR_CHROMATIX_TYPE_SNAPSHOT);

  sensor_util_set_special_mode(ctrl->s_data->sensor_common_info,
    SENSOR_SPECIAL_MODE_FLASH, TRUE);
  name[SENSOR_CHROMATIX_CPP_FLASH_SNAPSHOT] =
    sensor_get_cur_chromatix_name_for_type(ctrl->s_data, CAMERA_MODULE_CPP,
      SENSOR_CHROMATIX_TYPE_SNAPSHOT);
  sensor_util_set_special_mode(ctrl->s_data->sensor_common_info,
    SENSOR_SPECIAL_MODE_FLASH, FALSE);

  sensor_util_set_special_mode(ctrl->s_data->sensor_common_info,
    SENSOR_SPECIAL_MODE_OIS_CAPTURE, TRUE);
  name[SENSOR_CHROMATIX_CPP_OIS_SNAPSHOT] =
    sensor_get_cur_chromatix_name_for_type(ctrl->s_data, CAMERA_MODULE_CPP,
      SENSOR_CHROMATIX_TYPE_SNAPSHOT);
  sensor_util_set_special_mode(ctrl->s_data->sensor_common_info,
    SENSOR_SPECIAL_MODE_OIS_CAPTURE, FALSE);

  sensor_util_set_special_mode(ctrl->s_data->sensor_common_info,
    SENSOR_SPECIAL_MODE_ZOOM_DOWNSCALE, TRUE);
  name[SENSOR_CHROMATIX_CPP_OIS_DS_SNAPSHOT] =
    sensor_get_cur_chromatix_name_for_type(ctrl->s_data, CAMERA_MODULE_CPP,
      SENSOR_CHROMATIX_TYPE_SNAPSHOT);
  sensor_util_set_special_mode(ctrl->s_data->sensor_common_info,
    SENSOR_SPECIAL_MODE_ZOOM_DOWNSCALE, FALSE);

  sensor_util_set_special_mode(ctrl->s_data->sensor_common_info,
    SENSOR_SPECIAL_MODE_ZOOM_UPSCALE, TRUE);
  name[SENSOR_CHROMATIX_CPP_OIS_US_SNAPSHOT] =
    sensor_get_cur_chromatix_name_for_type(ctrl->s_data, CAMERA_MODULE_CPP,
      SENSOR_CHROMATIX_TYPE_SNAPSHOT);
  sensor_util_set_special_mode(ctrl->s_data->sensor_common_info,
    SENSOR_SPECIAL_MODE_ZOOM_UPSCALE, FALSE);

  sensor_util_set_special_mode(ctrl->s_data->sensor_common_info,
    SENSOR_SPECIAL_MODE_ZOOM_DOWNSCALE, TRUE);
  name[SENSOR_CHROMATIX_CPP_DS] =
    sensor_get_cur_chromatix_name_for_type(ctrl->s_data, CAMERA_MODULE_CPP,
      SENSOR_CHROMATIX_TYPE_SNAPSHOT);
  sensor_util_set_special_mode(ctrl->s_data->sensor_common_info,
    SENSOR_SPECIAL_MODE_ZOOM_DOWNSCALE, FALSE);

  sensor_util_set_special_mode(ctrl->s_data->sensor_common_info,
    SENSOR_SPECIAL_MODE_ZOOM_UPSCALE, TRUE);
  name[SENSOR_CHROMATIX_CPP_US] =
    sensor_get_cur_chromatix_name_for_type(ctrl->s_data, CAMERA_MODULE_CPP,
      SENSOR_CHROMATIX_TYPE_SNAPSHOT);
  sensor_util_set_special_mode(ctrl->s_data->sensor_common_info,
    SENSOR_SPECIAL_MODE_ZOOM_UPSCALE, FALSE);

  if (sensor_common_info->ir_mode)
    sensor_util_set_special_mode(ctrl->s_data->sensor_common_info,
      SENSOR_SPECIAL_MODE_IR, TRUE);

  name[SENSOR_CHROMATIX_CPP_VIDEO] =
    sensor_get_cur_chromatix_name_for_type(ctrl->s_data, CAMERA_MODULE_CPP,
      SENSOR_CHROMATIX_TYPE_VIDEO);

  name[SENSOR_CHROMATIX_SW_PPROC] =
    sensor_get_cur_chromatix_name_for_type(ctrl->s_data, CAMERA_MODULE_SW_PPROC,
      SENSOR_CHROMATIX_TYPE_COMMON);

  name[SENSOR_CHROMATIX_3A] =
    sensor_get_cur_chromatix_name_for_type(ctrl->s_data, CAMERA_MODULE_3A,
      SENSOR_CHROMATIX_TYPE_PREVIEW);

  name[SENSOR_CHROMATIX_EXTERNAL] =
    sensor_get_cur_chromatix_name_for_type(ctrl->s_data, CAMERA_MODULE_EXTERNAL,
      SENSOR_CHROMATIX_TYPE_COMMON);

  name[SENSOR_CHROMATIX_IOT] =
    sensor_get_cur_chromatix_name_for_type(ctrl->s_data, CAMERA_MODULE_IOT,
      SENSOR_CHROMATIX_TYPE_COMMON);

  if (ctrl->s_data->sensor_common_info->sensor_mode == SENSOR_MODE_VIDEO) {
    name[SENSOR_CHROMATIX_ISP] =
      sensor_get_cur_chromatix_name_for_type(ctrl->s_data, CAMERA_MODULE_ISP,
        SENSOR_CHROMATIX_TYPE_VIDEO);
    name[SENSOR_CHROMATIX_CPP_SNAPSHOT] =
      sensor_get_cur_chromatix_name_for_type(ctrl->s_data, CAMERA_MODULE_CPP,
        SENSOR_CHROMATIX_TYPE_LIVESHOT);
    name[SENSOR_CHROMATIX_3A] =
      sensor_get_cur_chromatix_name_for_type(ctrl->s_data, CAMERA_MODULE_3A,
        SENSOR_CHROMATIX_TYPE_VIDEO);
  } else if(ctrl->s_data->sensor_common_info->sensor_mode ==
    SENSOR_MODE_PREVIEW || ctrl->s_data->sensor_common_info->sensor_mode == SENSOR_MODE_ZSL) {
    name[SENSOR_CHROMATIX_ISP] =
      sensor_get_cur_chromatix_name_for_type(ctrl->s_data, CAMERA_MODULE_ISP,
        SENSOR_CHROMATIX_TYPE_PREVIEW);
  }

  for (i = 0; i < SENSOR_CHROMATIX_MAX; i++)
    if (name[i]) {
      SLOW("res_idx = %d chromatix_lib_name[%d] = %s",cur_res, i, name[i]);
    } else {
      SLOW("res_idx = %d chromatix_lib_name[%d] = %s",cur_res, i, "NULL");
    }

  return SENSOR_SUCCESS;
}
==>
static char * sensor_get_cur_chromatix_name_for_type(
  sensor_data_t *s_data, camera_module module,
  sensor_chroamtix_type stream_type)  //根据camera_module和stream_type加载当前resolution对应的key info array
{
  uint32_t                 i = 0;
  uint32_t                 j = 0;
  char                    *name = NULL;
  module_chromatix_name_t *chromatix_name = NULL;
  module_chromatix_info_t *chromatix_info =
    &s_data->sensor_common_info->camera_config.chromatix_info;
  uint64_t                 special_mode_mask =
    s_data->sensor_common_info->special_mode_mask;
  uint8_t                  res_idx =
    (s_data->cur_res == SENSOR_INVALID_RESOLUTION) ? 0 : s_data->cur_res;
  uint64_t                 index_array[4][2] =
    {
      {res_idx, special_mode_mask}, {0xFF, special_mode_mask},
      {res_idx, 0}, {0xFF, 0},
    };

  for (j = 0; j < 4; j++) {
    for (i = 0; i < chromatix_info->size; i++) {
      chromatix_name = &chromatix_info->chromatix_name[i];

      SLOW("index_array[%d][0] = %lld sensor_resolution_index = %d", j,
        index_array[j][0], chromatix_name->sensor_resolution_index);
      /* Check if the res_idx matches with the the one in chromatix array */
      if (index_array[j][0] != chromatix_name->sensor_resolution_index)
        continue;

      SLOW("index_array[%d][1] = %lld special_mode_mask = %lld", j,
        index_array[j][1], chromatix_name->special_mode_mask);

      /* Check if special_mode_mask matches with the one in chromatix array in xml file */
      if (chromatix_name->special_mode_type) {
        /* If special_mode_type is set, then the chroamtix modes have | (or) */
        if ((index_array[j][1] & chromatix_name->special_mode_mask) !=
          index_array[j][1])
          continue;
      }
      else if (index_array[j][1] != chromatix_name->special_mode_mask)
        continue;

      switch (module) {
      case CAMERA_MODULE_ISP:
        switch (stream_type) {
        case SENSOR_CHROMATIX_TYPE_PREVIEW:
          name = chromatix_name->isp_preview;
          break;
        case SENSOR_CHROMATIX_TYPE_SNAPSHOT:
          name = chromatix_name->isp_snapshot;
          break;
        case SENSOR_CHROMATIX_TYPE_VIDEO:
          name = chromatix_name->isp_video;
          break;
        case SENSOR_CHROMATIX_TYPE_COMMON:
          name = chromatix_name->isp_common;
          break;
        default:
          SERR("Invalid stream type = %d", stream_type);
          break;
        }
        break;
      case CAMERA_MODULE_CPP:
        switch (stream_type) {
        case SENSOR_CHROMATIX_TYPE_PREVIEW:
          name = chromatix_name->cpp_preview;
          break;
        case SENSOR_CHROMATIX_TYPE_SNAPSHOT:
          name = chromatix_name->cpp_snapshot;
          break;
        case SENSOR_CHROMATIX_TYPE_VIDEO:
          name = chromatix_name->cpp_video;
          break;
        case SENSOR_CHROMATIX_TYPE_LIVESHOT:
          name = chromatix_name->cpp_liveshot;
          break;
        default:
          SERR("Invalid stream type = %d", stream_type);
          break;
        }
        break;
      case CAMERA_MODULE_3A:
        switch (stream_type) {
        case SENSOR_CHROMATIX_TYPE_PREVIEW:
        case SENSOR_CHROMATIX_TYPE_SNAPSHOT:
          if(chromatix_name->external)
            name = chromatix_name->external;
          else
            name = chromatix_name->a3_preview;
          break;
        case SENSOR_CHROMATIX_TYPE_VIDEO:
        case SENSOR_CHROMATIX_TYPE_LIVESHOT:
          name = chromatix_name->a3_video;
          break;
        default:
          SERR("Invalid stream type = %d", stream_type);
          break;
        }
        break;
      case CAMERA_MODULE_SW_PPROC:
        name = chromatix_name->postproc;
        break;
      case CAMERA_MODULE_EXTERNAL:
        name = chromatix_name->external;
        break;
      case CAMERA_MODULE_IOT:
        name = chromatix_name->iot;
        break;
      default:
        SERR("Invalid module = %d", module);
        break;
      }

      if ((name != NULL) && strlen(name)) {
        SLOW("name = %s", name);
        return name;
      }
      else if (special_mode_mask == 0 && j == 1)
        goto CHROMATIX_NULL;
    }
  }

CHROMATIX_NULL:
  SHIGH("chromatix for res_idx = %d special_mode_mask = %lld \
    module = %d chromatix_type = %d is NULL",
    res_idx, special_mode_mask, module, stream_type);
  return NULL;
}

下一步是获取对应的效果参数的指针:

static int32_t chromatix_get_ptr(chromatix_data_t *ctrl, void *data)
{
  int32_t i;
  sensor_chromatix_params_t *params;

  SLOW("Enter");

  RETURN_ERROR_ON_NULL(ctrl);
  RETURN_ERROR_ON_NULL(data);

  params = (sensor_chromatix_params_t *)data;

  for(i = 0; i < SENSOR_CHROMATIX_MAX; i++) {
    SLOW("type[%d]:[%s]", i, params->chromatix_lib_name[i]);

    if (params->chromatix_lib_name[i] == ctrl->chromatix_name[i])
      params->chromatix_reloaded[i] = FALSE;
    else
      params->chromatix_reloaded[i] = TRUE;

    if (i == SENSOR_CHROMATIX_EXTERNAL) continue;

    if (!params->chromatix_lib_name[i]) {
      params->chromatix_ptr[i] = NULL;
      continue;
    }

    ctrl->chromatix_ptr[i] =
      cm_getChromatix(ctrl->cm, params->chromatix_lib_name[i],
      pick_calibration_type[i]);
    if (!ctrl->chromatix_ptr[i]) {
      SERR("Can't get chromatix pointer : %s", params->chromatix_lib_name[i]);
      return SENSOR_FAILURE;
    }

    params->chromatix_ptr[i] = ctrl->chromatix_ptr[i];

    SLOW("chromatix version: 0x%x",
      ((chromatix_parms_type*)ctrl->chromatix_ptr[i])
      ->chromatix_version_info.chromatix_version);
    ctrl->chromatix_name[i] = params->chromatix_lib_name[i];
  }

  SLOW("Exit");
  return SENSOR_SUCCESS;
}
==>  
void *cm_getChromatix(chromatix_manager_type* cm, const char *name,
  uint32_t calibration_type)
{
  void    *data_sym = NULL;
  void    *data_hdl = NULL;
  char    *key      = NULL;
  uint32_t cIndex;

  if (!cm || !name) {
    SERR("NULL pointer detected");
    return NULL;
  }

  SLOW("%s", name);

  PTHREAD_MUTEX_LOCK(&cm->mutex);
  if (hash_find(&cm->hash, name, &data_sym, &cIndex)) {
    /* Chromatix file is in the hash : update LRU */    //如果要加载的库已存在hash表,获取数据,并更新LRU表
    lru_update(&cm->lru, cIndex);
  } else {
    SLOW("Can't find the data of key[%s]", name);

    /* Chromatix file is NOT in the hash :
       (1) cache memory is available, add
       (2) delete least used file from cache, and add */
    if (lru_count(&cm->lru) < MAX_CHROMATIX_COUNT) {
      data_sym = addLib_getSymbol(cm, name, calibration_type);     
    } else { //当加载的库没有在hash表中,并且LRU表坑占满了,则需要先把最旧节点从hash表中删除,再unload参数,释放文件句柄和内存。如果不进行这一步操作,会造成LRU表会比hash表少一个数据,因为LRU新增数据如果cache不够了,会将新增节点替换旧节点,它最多只能存储MAX_CHROMATIX_COUNT个数据。不过现在也不知道这个LRU表是干嘛用的==
      /* get the least used chromatix file info */
      lru_getLeastRecent(&cm->lru, &key, &cIndex);
      /* delete has node and unload the library */
      hash_delete(&cm->hash, key, &data_hdl, &data_sym);
      unload_chromatix(data_hdl, data_sym);

      data_sym = addLib_getSymbol(cm, name, calibration_type);
      if (data_sym == NULL)
        SERR("failed : addLib2");
    }
  }

  lru_traverse(&cm->lru);
  PTHREAD_MUTEX_UNLOCK(&cm->mutex);

  return data_sym;
}

至此,结束!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容