海思android随笔之工厂菜单PQ acm color调用流程

提示:本文是基于海思android 9.0方案进行分析的



前言

PQ组觉得我们工厂菜单可调的acm color范围不够广,要求进行一些扩展。故深入追踪了海思从上层接口调用到底层color控制范围的整个流程


流程图

Created with Raphaël 2.3.0 开始 HiDtvShare.jar---->setHueGain() FactoryImpl.java---->setHueGain() HitvManager.java---->excuteCommandSet(CMD_FACTORY_SETHUEGAIN) hi_mw_logic_factory_module.cpp---->SetHueGain() hi_mw_logic_factory.cpp---->SetHueGain() hi_mw_framework_pqctrl.cpp---->SetHueGain() unf_pq.c---->HI_UNF_PQ_SetHueGain() mpi_pq.c---->hi_mpi_pq_set_color_section_gain() drv_pq_intf.c---->drv_pq_ioctl_set_color_section_gain() pq_acm.c---->pq_acm_set_section_color() pq_acm.c---->acm_set_pq_color_hsv() pq_acm.c---->acm_update_color_by_hsv() pq_acm.c---->acm_adjust_section_color_bri_hue_sat_by_hue() 分叉路,先走Yes,再走No pq_acm.c---->acm_set_section_color_bri_hue_sat_by_hue() pq_acm_param.c---->acm_get_pq_color_range() pq_acm_param.c---->g_st_pq_color_range() pq_acm.c---->acm_set_section_color_cross_sat_by_hue() pq_acm_param.c---->acm_get_pq_color_cross_range() pq_acm_param.c---->g_st_pq_color_cross_range() yes no

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函数,我们追踪下

Created with Raphaël 2.3.0 开始 HitvManager.java---->excuteCommandSet() HitvManager.java---->invoke() android_hitv_manager.cpp---->android_hitvmanager_native_invoke() HiTVManager.cpp---->invoke() TVClient.cpp---->invoke() Hwtvmw.cpp---->hwInvoke() TVService.cpp---->invoke() HiTVSettingAdaptor.cpp---->invoke() HiModuleAdaptor.cpp---->dispath() HiDispatch.cpp---->dispatch() 结束

这里具体的过程就不详细描述了,根据函数一步步追踪很容易到这里。
我们来分析下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

Created with Raphaël 2.3.0 开始 osal_device.c---->g_osal_fops.unlocked_ioctl osal_device.c---->osal_ioctl() osal_device.c---->osal_ioctl_call_fun() osal_device.c---->osal_fileops->cmd_list[CMD_PQ_S_COLOR_SECTION_ADJUST].handler() drv_pq_intf.c---->g_pq_cmd_list[CMD_PQ_S_COLOR_SECTION_ADJUST] drv_pq_intf.c---->drv_pq_proccess_cmd() drv_pq_intf.c---->g_st_pq_ioctl_info[CMD_PQ_S_COLOR_SECTION_ADJUST].pq_ioctl_func() drv_pq_intf.c---->drv_pq_ioctl_set_color_section_gain() 结束

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了。

猜你喜欢

转载自blog.csdn.net/hmz0303hf/article/details/128662616
ACM
今日推荐