提示:本文是基于海思android 9.0方案进行分析的
文章目录
- 前言
- 流程图
- 分析过程
- 1. HiDtvShare.jar---->setHueGain()
- 2. FactoryImpl.java---->setHueGain()
- 3. HitvManager.java---->excuteCommandSet()
- 4. hi_mw_logic_factory_module.cpp---->SetHueGain()
- 5. hi_mw_logic_factory.cpp---->SetHueGain()
- 6. hi_mw_framework_pqctrl.cpp---->SetHueGain()
- 7. unf_pq.c---->HI_UNF_PQ_SetHueGain()
- 8. mpi_pq.c---->hi_mpi_pq_set_color_section_gain()
- 9. drv_pq_intf.c---->drv_pq_ioctl_set_color_section_gain()
- 10. pq_acm.c---->pq_acm_set_section_color()
- 11. pq_acm.c---->acm_set_pq_color_hsv()
- 12. pq_acm.c---->acm_update_color_by_hsv()
- 13. pq_acm.c---->acm_adjust_section_color_bri_hue_sat_by_hue()
- 总结
前言
PQ组觉得我们工厂菜单可调的acm color范围不够广,要求进行一些扩展。故深入追踪了海思从上层接口调用到底层color控制范围的整个流程
流程图
setSatGain和setBriGain的流程跟setSatGain相似99%,这里单就setHueGain进行举例,另外两个有兴趣的同学可以自己分析下
分析过程
1. HiDtvShare.jar---->setHueGain()
app调用方法:
先导入系统代码编译生成的Android\out\target\common\obj\JAVA_LIBRARIES\HiDtvShare_intermediates\classes.jar包,然后调用HitvManager.getInstance().getFactory().setHueGain(int HueType, int HueGain)
2. FactoryImpl.java---->setHueGain()
HitvManager.getInstance().getFactory()获取的是FactoryImpl对象
所以到了这里Android/device/hisilicon/bigfish/hippo/api/java/com/hisilicon/android/tvapi/impl/FactoryImpl.java
public int setHueGain(int SatType, int SatGain) {
int ret = HitvManager.getInstance().excuteCommandSet(EnumSystemCmd.CMD_FACTORY_SETHUEGAIN, SatType, SatGain);
HiMwLogTool.info(TAG, "type:" + SatType + ", gain:" + SatGain + retStatu(ret));
return ret;
}
3. HitvManager.java---->excuteCommandSet()
这里调用了Android/device/hisilicon/bigfish/hippo/api/java/com/hisilicon/android/tvapi/HitvManager.java的重载函数excuteCommandSet,传递是EnumSystemCmd.CMD_FACTORY_SETHUEGAIN, 以及两个int型参数SatType和SatGain
public int excuteCommandSet(int cmd_id, int arg1, int arg2) {
Parcel request = Parcel.obtain();
Parcel reply = Parcel.obtain();
request.writeInt(cmd_id);
request.writeInt(arg1);
request.writeInt(arg2);
int ret = invoke(request, reply);
request.recycle();
reply.recycle();
return ret;
}
可以看到,这里关键在于invoke函数,我们追踪下
这里具体的过程就不详细描述了,根据函数一步步追踪很容易到这里。
我们来分析下Android/device/hisilicon/bigfish/hippo/vendor/adapter/module/HiDispatch.cpp里的dispatch()
HI_S32 HiDispatch::dispatch(const Parcel &request, Parcel *reply)
{
LOGV("begin dispatch in HiDispatch");
request.setDataPosition(0);
Parcel output;
HI_U32 id = static_cast<HI_U32>(request.readInt32());
HI_U32 flag = id & 0xf000;
if (reply == NULL) {
LOGE("erorr:reply is null ptr!");
return HI_FAILURE;
}
LOGV("before lock in dispatch, ID: 0x%x", id);
HiMutex::Autolock _l(mDispatchLock);
FullMapIter dispatchMapIter = mDispatchMap.find(flag);
LOGV("after lock in dispatch");
if (dispatchMapIter != mDispatchMap.end()) {
ModuleMapIter moduleMapIter = dispatchMapIter->second.find(id);
if (moduleMapIter != dispatchMapIter->second.end()) {
if (moduleMapIter->second) {
LOGV("before reply write in dispatch");
reply->writeInt32(moduleMapIter->second(request, output));
reply->write(output.data(), output.dataSize());
reply->setDataPosition(0);
LOGV("after reply write and end dispatch in HiDispatch");
return HI_SUCCESS;
}
LOGE("local pfn is null:%d", id);
return HI_FAILURE;
}
LOGE("id:%d not found!", id);
return HI_FAILURE;
}
LOGE("flag:%d not found!", flag);
return HI_FAILURE;
}
不难发现,这里先获取到一个FullMapIter数据类型
FullMapIter dispatchMapIter = mDispatchMap.find(flag);
然后再获取到一个ModuleMapIter数据类型
ModuleMapIter moduleMapIter = dispatchMapIter->second.find(id);
reply先返回ModuleMapIter数据类型里的second()函数结果
reply->writeInt32(moduleMapIter->second(request, output));
通过调用这个request,得到的返回结果output,再写入reply
reply->write(output.data(), output.dataSize());
所以最终执行的是moduleMapIter->second(request, output),然后把output结果返回上去。那么这个moduleMapIter->second又是什么东西呢?
我们先回到第一步,这里最先是通过mDispatchMap获取到一个FullMapIter数据类型,我们看看mDispatchMap是怎么构成的。
搜索下发现在Android/device/hisilicon/bigfish/hippo/vendor/adapter/module/HiDispatch.h有定义
FullMap mDispatchMap;
数据插入主要在Android/device/hisilicon/bigfish/hippo/vendor/adapter/module/HiDispatch.cpp
HI_VOID HiDispatch::insertInterface(HI_U32 id, LocalAtomicPfn pfn)
{
HI_U32 flag = id & 0xf000;
HiMutex::Autolock _l(mDispatchLock);
FullMapIter dispatchMapIter = mDispatchMap.find(flag);
if (dispatchMapIter == mDispatchMap.end()) {
dispatchMapIter = mDispatchMap.insert(dispatchMapIter, FullMap::value_type(flag, ModuleMap()));
dispatchMapIter->second.insert(ModuleMap::value_type(id, pfn));
return;
}
ModuleMapIter moduleMapIter = dispatchMapIter->second.find(id);
if (moduleMapIter == dispatchMapIter->second.end()) {
dispatchMapIter->second.insert(ModuleMap::value_type(id, pfn));
}
}
很明显,所有模块都是通过HiDispatch::insertInterface方法把对应ID和函数指针插入到mDispatchMap.find(flag)->second里,也就是上面的moduleMapIter->second。所以我们根据对应ID找到对应的函数指针,那么就是我们最终的调用函数。
搜索一下我们调用的CMD_FACTORY_SETHUEGAIN,发现在Android/device/hisilicon/bigfish/hippo/vendor/logic/module_api/hi_mw_logic_factory_module.cpp里的g_astFactoryModuleLocalAtomicInfo数组里,这是个LocalAtomicInfo数组,这个数组只有两个元素,1个ID,1个函数指针
typedef HI_S32 (*LocalAtomicPfn)(const Parcel &request, Parcel &reply);
typedef struct tagLocalAtomicInfo {
HI_U32 id; /* �ӿ�id */
LocalAtomicPfn pfn; /* �ӿں��� */
} LocalAtomicInfo;
在g_astFactoryModuleLocalAtomicInfo数组里,我们CMD_FACTORY_SETHUEGAIN对应的是SetHueGain。
static LocalAtomicInfo g_astFactoryModuleLocalAtomicInfo[] = {
/* 接口指令、id */ /* 接口函数 */
{ CMD_FACTORY_AUTOCALIBRATION, AutoCalibration },
{ CMD_FACTORY_SETADCGAINOFFSET, SetADCGainOffset },
{ CMD_FACTORY_GETADCGAINOFFSET, GetADCGainOffset },
******
{ CMD_FACTORY_SETHUEGAIN, SetHueGain },
******
};
HiFactoryModule初始化的时候会把g_astFactoryModuleLocalAtomicInfo数组insertInterface到mDispatchMap
static HI_S32 Init(IDispatch *dispatch)
{
LOGI("HiFactoryModule->Init");
for (HI_U32 i = 0; i < sizeof(g_astFactoryModuleLocalAtomicInfo) / sizeof(LocalAtomicInfo); i++) {
dispatch->insertInterface(g_astFactoryModuleLocalAtomicInfo[i].id, g_astFactoryModuleLocalAtomicInfo[i].pfn);
}
return HI_SUCCESS;
}
以上可知,我们通过接口调用CMD_FACTORY_SETHUEGAIN,最终实现就是在Android/device/hisilicon/bigfish/hippo/vendor/logic/module_api/hi_mw_logic_factory_module.cpp里的
SetHueGain
4. hi_mw_logic_factory_module.cpp---->SetHueGain()
从上一步追踪到,最终实现是在这里,我们来看看它的内容
static HI_S32 SetHueGain(const Parcel &in, Parcel &out)
{
HI_MW_PQ_HUE_GAIN_S stHueGain;
errno_t rc = memset_s(&stHueGain, sizeof(stHueGain), 0, sizeof(stHueGain));
if (rc != EOK) {
LOGE("memset_s_func failed, rc = %d", rc);
return HI_FAILURE;
}
stHueGain.eColorType = (HI_MW_PQ_COLOR_E)in.readInt32();
stHueGain.s32Gain = in.readInt32();
HI_S32 s32Ret = HiFactory::instance()->SetHueGain(&stHueGain);
LOGI("ColorType:%d, Gain:%d, ret:%d",
stHueGain.eColorType, stHueGain.s32Gain, s32Ret);
return s32Ret;
}
从这里我可以发现,我们通过HiDtvShare.jar接口包setHueGain(int HueType, int HueGain)传下的数据,HueType被转成了HI_MW_PQ_COLOR_E类型,
并存到了HI_MW_PQ_HUE_GAIN_S结构体的eColorType成员里,
HueGain则存到了HI_MW_PQ_HUE_GAIN_S结构体的s32Gain成员里。
我们看下这个HI_MW_PQ_HUE_GAIN_S结构体和HI_MW_PQ_COLOR_E类型
Android/device/hisilicon/bigfish/hippo/include/hi_mw_common.h
enum HI_MW_PQ_COLOR_E {
HI_MW_PQ_COLOR_R = 0,
HI_MW_PQ_COLOR_G = 1,
HI_MW_PQ_COLOR_B = 2,
HI_MW_PQ_COLOR_CYAN = 3,
HI_MW_PQ_COLOR_PURPLE = 4,
HI_MW_PQ_COLOR_YELLOW = 5,
HI_MW_PQ_COLOR_FLESH = 6,
HI_MW_PQ_COLOR_HAIR = 7,
HI_MW_PQ_COLOR_LIPS = 8,
HI_MW_PQ_COLOR_OLIVINE = 9,
HI_MW_PQ_COLOR_BUTT = 10,
};
******
struct HI_MW_PQ_HUE_GAIN_S {
HI_MW_PQ_COLOR_E eColorType;
HI_S32 s32Gain;
};
所以,我们使用接口的时候要注意int HueType的取值范围,要小于HI_MW_PQ_COLOR_BUTT才是有效的值。
回归流程,我们继续往下分析HiFactory::instance()->SetHueGain(&stHueGain);
5. hi_mw_logic_factory.cpp---->SetHueGain()
Android/device/hisilicon/bigfish/hippo/vendor/logic/setting/hi_mw_logic_factory.cpp
HI_S32 HiFactory::SetHueGain(HI_MW_PQ_HUE_GAIN_S *pstHueGain)
{
******
s32Ret = HiPQCtrl::instance()->SetHueGain(pstHueGain);
******
return s32Ret;
}
这里主要是读取db里的数据,然后调用HiPQCtrl的方法。为简化文章内容,无关内容就都省略了,下面的code分析也会这样。
6. hi_mw_framework_pqctrl.cpp---->SetHueGain()
Android/device/hisilicon/bigfish/hippo/vendor/framework/hal/hi_mw_framework_pqctrl.cpp
HI_S32 HiPQCtrl::SetHueGain(HI_MW_PQ_HUE_GAIN_S *pstHueGain)
{
if (m_stPqCtrlCb.pfnSetHueGainCb) {
return m_stPqCtrlCb.pfnSetHueGainCb(pstHueGain);
}
if (pstHueGain == HI_NULL) {
LOGE("pstHueGain is null ptr");
return HI_FAILURE;
}
HI_S32 ret;
HI_UNF_PQ_HUE_GAIN_S stHueGain;
errno_t rc = memcpy_s(&stHueGain, sizeof(stHueGain), pstHueGain, sizeof(HI_MW_PQ_HUE_GAIN_S));
if (rc != EOK) {
LOGE("memcpy_s_func failed rc = %d", rc);
return HI_FAILURE;
}
ret = HI_UNF_PQ_SetHueGain(&stHueGain);
return ret;
}
在这里,发现把上面传下来的HI_MW_PQ_HUE_GAIN_S结构体内容copy到了HI_UNF_PQ_HUE_GAIN_S结构体里。我看下这个结构体
Android/device/hisilicon/bigfish/sdk/source/msp/include/hi_unf_pq.h
typedef enum hiUNF_PQ_COLOR_E {
HI_UNF_PQ_COLOR_R, /* <color red */ /* <CNcomment: 红色 */
HI_UNF_PQ_COLOR_G, /* <color green */ /* <CNcomment: 绿色 */
HI_UNF_PQ_COLOR_B, /* <color blue */ /* <CNcomment:蓝色 */
HI_UNF_PQ_COLOR_CYAN, /* <color cyan */ /* <CNcomment:青色 */
HI_UNF_PQ_COLOR_PURPLE, /* <color purple */ /* <CNcomment:紫色 */
HI_UNF_PQ_COLOR_YELLOW, /* <color yellow */ /* <CNcomment:黄色 */
HI_UNF_PQ_COLOR_FLESH, /* <color flesh */ /* <CNcomment:肤色 */
HI_UNF_PQ_COLOR_HAIR, /* <color flesh1 */ /* <CNcomment:肤色1头发 */
HI_UNF_PQ_COLOR_LIPS, /* <color lips */ /* <CNcomment:肤色2嘴唇 */
HI_UNF_PQ_COLOR_OLIVINE, /* <color olivine */ /* <CNcomment:黄绿色 */
HI_UNF_PQ_COLOR_BUTT /* <Invalid value */ /* <CNcomment:非法边界值 */
} HI_UNF_PQ_COLOR_E;
******
typedef struct hiUNF_PQ_HUE_GAIN_S {
HI_UNF_PQ_COLOR_E enColorType; /* <color type */ /* <CNcomment: 颜色类型 */
HI_S32 s32Gain; /* <hue gain */ /* <CNcomment: 色调增益 */
} HI_UNF_PQ_HUE_GAIN_S;
所以我们上面接口使用的HI_MW_PQ_COLOR_E类型,一定要与这个中间件HI_UNF_PQ_COLOR_E类型的值保持一一对应,否则就会出问题。
回归流程,我们继续分析HI_UNF_PQ_SetHueGain(&stHueGain);
7. unf_pq.c---->HI_UNF_PQ_SetHueGain()
Android/device/hisilicon/bigfish/sdk/source/msp/api/pq/unf_pq.c
hi_s32 HI_UNF_PQ_SetHueGain(HI_UNF_PQ_HUE_GAIN_S *pst_hue_gain)
{
hi_drv_pq_color_section_gain st_hue_gain_temp;
PQ_CHECK_NULL_PTR(pst_hue_gain);
PQ_CHECK_UPPER_LIMIT(pst_hue_gain->enColorType, HI_UNF_PQ_COLOR_BUTT);
if ((pst_hue_gain->s32Gain > SECTION_COLOR_GAIN_MAX) || (pst_hue_gain->s32Gain < SECTION_COLOR_GAIN_MIN)) {
hi_err_print_s32(pst_hue_gain->s32Gain);
return HI_ERR_PQ_INVALID_PARA;
}
HI_LOG_NOTICE("set hue_gain: color_type=%d gain=%d \n", pst_hue_gain->enColorType, pst_hue_gain->s32Gain);
#if defined (CHIP_TYPE_hi3731v110)
hi_unf_pq_transform_pq_color(pst_hue_gain->enColorType, &st_hue_gain_temp);
#else
st_hue_gain_temp.color_type = pst_hue_gain->enColorType;
#endif
st_hue_gain_temp.hsv_type = HI_DRV_PQ_HSV_HUE;
st_hue_gain_temp.color_gain = pst_hue_gain->s32Gain;
return hi_mpi_pq_set_color_section_gain(&st_hue_gain_temp);
}
这里要注意,传下的数据类型又发生的变更。
HI_UNF_PQ_HUE_GAIN_S结构体的enColorType保存到了hi_drv_pq_color_section_gain结构体的color_type里,HI_UNF_PQ_HUE_GAIN_S结构体的s32Gain保存到了hi_drv_pq_color_section_gain结构体的color_gain。
我们看看这个结构体
Android/device/hisilicon/bigfish/sdk/source/msp/drv/include/drv_pq_ioctl.h
typedef enum {
HI_DRV_PQ_COLOR_R = 0,
HI_DRV_PQ_COLOR_G,
HI_DRV_PQ_COLOR_B,
HI_DRV_PQ_COLOR_CYAN,
HI_DRV_PQ_COLOR_PURPLE,
HI_DRV_PQ_COLOR_YELLOW,
HI_DRV_PQ_COLOR_FLESH,
HI_DRV_PQ_COLOR_HAIR,
HI_DRV_PQ_COLOR_LIPS,
HI_DRV_PQ_COLOR_OLIVINE,
HI_DRV_PQ_COLOR_BUTT
} hi_drv_pq_color;
******
typedef struct {
hi_drv_pq_color color_type;
hi_drv_pq_hsv hsv_type;
hi_s32 color_gain;
} hi_drv_pq_color_section_gain;
所以,这里要重点注意中间件的HI_UNF_PQ_COLOR_E类型也要与这里的hi_drv_pq_color类型一一对应,否则也会出问题。
回归流程,我们继续分析,很明显,下一步关键在于return的函数结果
8. mpi_pq.c---->hi_mpi_pq_set_color_section_gain()
Android/device/hisilicon/bigfish/sdk/source/msp/api/pq/mpi_pq.c
hi_s32 hi_mpi_pq_set_color_section_gain(const hi_drv_pq_color_section_gain *sat_gain)
{
hi_s32 ret;
ret = pq_check_pq_init();
if (ret == HI_ERR_PQ_NOT_INIT) {
return ret;
}
PQ_CHECK_FUNC_RET(ioctl(g_pq_fd, CMD_PQ_S_COLOR_SECTION_ADJUST, sat_gain), CMD_PQ_S_COLOR_SECTION_ADJUST);
return HI_SUCCESS;
}
这里调用了设备函数,ioctl相关原理这里就不介绍了,这里贴一些文档,有兴趣的同学可以学习下。
一文搞懂内核块设备操作之ioctl系统调用过程
ioctl的原理及实现
ioctl的自定义命令
从上面我们可以看到,通过ioctl调用的是CMD_PQ_S_COLOR_SECTION_ADJUST,这里简单画下流程图。
主要code在Android/device/hisilicon/bigfish/sdk/source/common/drv/osal/osal_device.c
9. drv_pq_intf.c---->drv_pq_ioctl_set_color_section_gain()
接着上面的ioctl流程图,最终跑到了这里来Android/device/hisilicon/bigfish/sdk/source/msp/drv/pq/drv_pq_intf.c
static hi_s32 drv_pq_ioctl_set_color_section_gain(hi_void *p_args)
{
hi_drv_pq_color_section_gain *pst_gain = (hi_drv_pq_color_section_gain *)p_args;
return pq_acm_set_section_color(pst_gain);
}
继续
10. pq_acm.c---->pq_acm_set_section_color()
Android/device/hisilicon/bigfish/sdk/source/msp/drv/pq/acm/pq_acm.c
hi_s32 pq_acm_set_section_color(hi_drv_pq_color_section_gain *gain)
{
hi_s32 ret;
pq_acm_context *pq_acm_ctx = get_pq_acm_context();
PQ_CHECK_NULL_PTR(gain);
PQ_CHECK_UPPER_LIMIT(gain->color_type, HI_DRV_PQ_COLOR_BUTT);
PQ_CHECK_UPPER_LIMIT(gain->hsv_type, HI_DRV_PQ_HSV_BUTT);
if ((gain->color_gain > SECTION_COLOR_GAIN_MAX) || (gain->color_gain < SECTION_COLOR_GAIN_MIN)) {
hi_err_print_s32(gain->color_gain);
return HI_ERR_PQ_INVALID_PARA;
}
ret = acm_set_pq_color_hsv(gain->color_type, gain->color_gain, gain->hsv_type);
if (ret != HI_SUCCESS) {
return ret;
}
pq_acm_ctx->color_gain[gain->hsv_type][gain->color_type] = gain->color_gain;
return HI_SUCCESS;
}
11. pq_acm.c---->acm_set_pq_color_hsv()
相同文件
static hi_s32 acm_set_pq_color_hsv(hi_drv_pq_color color_type, hi_s32 gain, hi_drv_pq_hsv hsv)
{
hi_s32 ret;
if (hsv == HI_DRV_PQ_HSV_SAT) {
acm_set_pq_color_hsv_sat(color_type, gain);
} else if (hsv == HI_DRV_PQ_HSV_HUE) {
acm_set_pq_color_hsv_hue(color_type, gain);
} else if (hsv == HI_DRV_PQ_HSV_BRI) {
acm_set_pq_color_hsv_bri(color_type, gain);
}
ret = acm_update_color_by_hsv();
if (ret != HI_SUCCESS) {
return ret;
}
return HI_SUCCESS;
}
注意,这里根据前面传下来的hi_drv_pq_hsv类型,对不同类型的color做不同的set处理,这里还是以hue为例,另外两个过程99%相似。
static void acm_set_pq_color_hsv_hue(hi_drv_pq_color color_type, hi_s32 gain)
{
switch (color_type) {
case HI_DRV_PQ_COLOR_R:
case HI_DRV_PQ_COLOR_G:
g_color_hue_gain[color_type] = gain;
break;
case HI_DRV_PQ_COLOR_B:
g_color_hue_gain[color_type] = gain;
g_color_hue_gain[color_type + 1] = gain;
break;
case HI_DRV_PQ_COLOR_CYAN:
case HI_DRV_PQ_COLOR_PURPLE:
case HI_DRV_PQ_COLOR_YELLOW:
case HI_DRV_PQ_COLOR_FLESH:
case HI_DRV_PQ_COLOR_HAIR:
case HI_DRV_PQ_COLOR_LIPS:
case HI_DRV_PQ_COLOR_OLIVINE:
g_color_hue_gain[color_type + 1] = gain;
break;
default:
break;
}
}
可以看到,根据上面传下来的hi_drv_pq_color类型和数值,转成对应数组g_color_hue_gain[]里值。
static hi_s32 g_color_sat_gain[PQ_MNG_COLOR_BUTT] = {0};
static hi_s32 g_color_hue_gain[PQ_MNG_COLOR_BUTT] = {0};
static hi_s32 g_color_bri_gain[PQ_MNG_COLOR_BUTT] = {0};
这个数组范围取决于PQ_MNG_COLOR_BUTT,
Android/device/hisilicon/bigfish/sdk/source/msp/drv/pq/acm/pq_acm.h
typedef enum {
PQ_MNG_COLOR_R, // 红
PQ_MNG_COLOR_G, // 绿
PQ_MNG_COLOR_B1, // 蓝
PQ_MNG_COLOR_B2, //
PQ_MNG_COLOR_CYAN, // 青
PQ_MNG_COLOR_MAGENTA, // 紫
PQ_MNG_COLOR_YELLOW, // 黄
PQ_MNG_COLOR_FLESH,
PQ_MNG_COLOR_HAIR,
PQ_MNG_COLOR_LIPS,
PQ_MNG_COLOR_OLIVINE,
PQ_MNG_COLOR_BUTT
} pq_mng_color;
所以这里要重点注意hi_drv_pq_color类型与pq_mng_color匹配,匹配关系主要在上面的那三个acm_set_pq_color_hsv函数,
****
if (hsv == HI_DRV_PQ_HSV_SAT) {
acm_set_pq_color_hsv_sat(color_type, gain);
} else if (hsv == HI_DRV_PQ_HSV_HUE) {
acm_set_pq_color_hsv_hue(color_type, gain);
} else if (hsv == HI_DRV_PQ_HSV_BRI) {
acm_set_pq_color_hsv_bri(color_type, gain);
}
****
一定要做好对应,否则也会出问题。可能调节无效或者跟你预想的不匹配。
这里简单画下对应关系
HI_MW_PQ_COLOR_E | HI_UNF_PQ_COLOR_E | hi_drv_pq_color | pq_mng_color |
---|---|---|---|
HI_MW_PQ_COLOR_R | HI_UNF_PQ_COLOR_R | HI_DRV_PQ_COLOR_R | PQ_MNG_COLOR_R |
HI_MW_PQ_COLOR_G | HI_UNF_PQ_COLOR_G | HI_DRV_PQ_COLOR_G | PQ_MNG_COLOR_G |
HI_MW_PQ_COLOR_B | HI_UNF_PQ_COLOR_B | HI_DRV_PQ_COLOR_B | PQ_MNG_COLOR_B1 PQ_MNG_COLOR_B2 |
HI_MW_PQ_COLOR_CYAN | HI_UNF_PQ_COLOR_CYAN | HI_DRV_PQ_COLOR_CYAN | PQ_MNG_COLOR_CYAN |
HI_MW_PQ_COLOR_PURPLE | HI_UNF_PQ_COLOR_PURPLE | HI_DRV_PQ_COLOR_PURPLE | PQ_MNG_COLOR_MAGENTA |
HI_MW_PQ_COLOR_YELLOW | HI_UNF_PQ_COLOR_YELLOW | HI_DRV_PQ_COLOR_YELLOW | PQ_MNG_COLOR_YELLOW |
HI_MW_PQ_COLOR_FLESH | HI_UNF_PQ_COLOR_FLESH | HI_DRV_PQ_COLOR_FLESH | PQ_MNG_COLOR_FLESH |
HI_MW_PQ_COLOR_HAIR | HI_UNF_PQ_COLOR_HAIR | HI_DRV_PQ_COLOR_HAIR | PQ_MNG_COLOR_HAIR |
HI_MW_PQ_COLOR_LIPS | HI_UNF_PQ_COLOR_LIPS | HI_DRV_PQ_COLOR_LIPS | PQ_MNG_COLOR_LIPS |
HI_MW_PQ_COLOR_OLIVINE | HI_UNF_PQ_COLOR_OLIVINE | HI_DRV_PQ_COLOR_OLIVINE | PQ_MNG_COLOR_OLIVINE |
HI_MW_PQ_COLOR_BUTT | HI_UNF_PQ_COLOR_BUTT | HI_DRV_PQ_COLOR_BUTT | PQ_MNG_COLOR_BUTT |
12. pq_acm.c---->acm_update_color_by_hsv()
还是这个文件
static hi_s32 acm_update_color_by_hsv(hi_void)
{
******
acm_adjust_section_color_bri_hue_sat_by_hue();
******
return HI_SUCCESS;
}
13. pq_acm.c---->acm_adjust_section_color_bri_hue_sat_by_hue()
继续
static hi_void acm_adjust_section_color_bri_hue_sat_by_hue(hi_void)
{
pq_mng_color color_type = 0;
for (color_type = PQ_MNG_COLOR_R; color_type <= PQ_MNG_COLOR_OLIVINE; color_type++) {
/* 先求中心点的值 */
acm_set_section_color_bri_hue_sat_by_hue(color_type);
/* 再求边界点的值 */
/* 边界点的亮度、色调、饱和度调节(依赖于两边点的值,与UI无直接联系,被依赖的点与UI直接相关) */
/* 某段颜色调整,其两边的边界点都随之变化.由于颜色点定义时是按R,G,B,C,M,Y,F的顺序, */
/* 与实际颜色分布的先后顺序不同,需要通过find数组找到 */
if (g_color_bri_gain[color_type] != 0) {
acm_set_section_color_cross_bri_by_hue(color_type);
acm_set_section_color_cross_bri_by_hue(g_aen_color_find_next_cross[color_type]);
}
if (g_color_hue_gain[color_type] != 0) {
acm_set_section_color_cross_hue_by_hue(color_type);
acm_set_section_color_cross_hue_by_hue(g_aen_color_find_next_cross[color_type]);
}
if (g_color_sat_gain[color_type] != 0) {
acm_set_section_color_cross_sat_by_hue(color_type);
acm_set_section_color_cross_sat_by_hue(g_aen_color_find_next_cross[color_type]);
}
}
}
看备注,很明显这里开始分叉,先求中心点,再求边界点
13.1 pq_acm.c---->acm_set_section_color_bri_hue_sat_by_hue()
还是这个文件,先看中心点
static hi_void acm_set_section_color_bri_hue_sat_by_hue(pq_mng_color color_type)
{
hi_u32 hue_start;
hi_u32 hue_end;
hi_s32 bri = g_color_bri_gain[color_type];
hi_s32 hue = g_color_hue_gain[color_type];
hi_s32 sat = g_color_sat_gain[color_type];
hue_rang* color_range = HI_NULL_PTR;
color_range = acm_get_pq_color_range(color_type);
if (color_range == HI_NULL_PTR) {
hi_err_print_null_pointer(color_range);
return;
}
hue_start = color_range->hue_start;
hue_end = color_range->hue_end;
acm_set_section_color_bri_by_hue(bri, hue_start, hue_end);
acm_set_section_color_hue_by_hue(hue, hue_start, hue_end);
acm_set_section_color_sat_by_hue(sat, hue_start, hue_end);
return;
}
13.1.1 pq_acm_param.c---->acm_get_pq_color_range()
跑到这里了Android/device/hisilicon/bigfish/sdk/source/msp/drv/pq/acm/hi3751v350/pq_acm_param.c
hue_rang* acm_get_pq_color_range(pq_mng_color color_type)
{
if (color_type >= PQ_MNG_COLOR_BUTT) {
hi_err_print_u32(color_type);
return HI_NULL_PTR;
}
return &g_st_pq_color_range[color_type];
}
13.1.2 pq_acm_param.c---->g_st_pq_color_range[]
继续追数组
static hue_rang g_st_pq_color_range[PQ_MNG_COLOR_BUTT] = {
{ 4, 6 }, // R
{ 22, 23 }, // G
{ 0, 1 }, // B1
{ 26, 28 }, // B2
{ 24, 25 }, // CYAN
{ 2, 3 }, // MAGENTA
{ 16, 19 }, // YELLOW
{ 9, 12 }, // FLESH
{ 13, 15 }, // HAIR
{ 7, 8 }, // Lips
{ 20, 21 }, // YELLOW-Green
};
这里的数组都是可以在海思pqtools.exe工具的color页面获取
比如{4, 8}代表4到8的整个x坐标颜色,调节的时候就是同时调这一段
到这,已经拿到中心点了。回到分叉点继续分析,求边界点。
13.2 pq_acm.c---->acm_set_section_color_cross_sat_by_hue()
再看边界点
13.2.1 pq_acm_param.c---->acm_get_pq_color_cross_range()
hue_rang* acm_get_pq_color_cross_range(pq_mng_color color_type)
{
if (color_type >= PQ_MNG_COLOR_BUTT) {
hi_err_print_u32(color_type);
return HI_NULL_PTR;
}
return &g_st_pq_color_cross_range[color_type];
}
13.2.2 pq_acm_param.c---->g_st_pq_color_cross_range[]
同样是数组
/********************************************************************
定义边界点的范围:若两段颜色的中心点是连续的,则边界点的起始都定义为0,
边界点处理函数判断到此情况,直接返回HI_SUCCESS
********************************************************************/
static hue_rang g_st_pq_color_cross_range[PQ_MNG_COLOR_BUTT] = {
{ 0, 0 }, // R
{ 0, 0 }, // G
{ 0, 0 }, // B1
{ 0, 0 }, // B1
{ 0, 0 }, // CYAN
{ 0, 0 }, // MAGENTA
{ 0, 0 }, // YELLOW
{ 0, 0 }, // FLESH
{ 0, 0 }, // HAIR
{ 0, 0 }, // Lips
{ 0, 0 }, // YELLOW-Green
};
总结
追到这两个数组,也就差不多结束了。
根据这个流程,如果要增加新的调试点,pq_acm_param.c里要新增中心点和边界点,然后那4个枚举新增ID,并设好对应的关系。另外要注意新增海思DB里的数据对应新增的调试点。上层app就可以使用新的调试colortype了。