6 君正ISP的封装

概述

        ISP,即图像信号处理单元,主要包含图像效果设置,模式切换以及Sensor的注册、添加、删除等操作。ISP模块与数据流无关,不需要进行绑定,仅作用于效果参数设置及Sensor控制。

ISP接口类

        君正的ISP模块除了能够设置亮度、对比度、饱和度等图像效果参数外,还可以设置日夜切换模式。日夜切换模式一般根据什么来设置呢?

        主要有三种方法:第一种是IPC上有硬光敏,且软件能够读取硬光敏的ADC值;第二种是IPC上有硬光敏,但软件无法读取硬光敏的ADC值,只能通过某个GPIO口读取是白天还是黑夜;第三种是IPC上没有硬光敏,只能通过对视频图像的颜色信息、曝光信息等进行统计分析,来判断当前是白天还是黑夜(这种方法也被称为“软光敏”)。

        ISP接口类主要有以下几个接口:

        1、初始化接口,用于传入初始化参数。

        2、设置某个通道的色调百分比值,范围为0到100。

        3、设置某个通道的对比度百分比值,范围为0到100。

        4、设置某个通道的亮度百分比值,范围为0到100。

        5、设置某个通道的饱和度百分比值,范围为0到100。

        6、设置某个通道的清晰度百分比值,范围为0到100。

        7、设置某个通道的日夜模式,日夜模式一共有五种,分别为:黑白模式关、黑白模式开、黑白模式自动、全彩模式、智能模式。黑白模式关表示强制不使用红外灯;黑白模式开表示强制使用红外灯;黑白模式自动表示白天不使用红外灯,夜晚使用红外灯;全彩模式表示夜晚自动打开白光灯,加强画面色彩效果;智能模式表示夜晚默认打开红外灯,当检测到移动或人形时,自动打开白光灯。

        8、设置某个通道的翻转模式,翻转模式一共有四种,分别为:不翻转、水平翻转、垂直翻转、水平垂直翻转。

        9、设置某个通道的抗闪烁模式,抗闪烁模式一共有三种,分别为:不使能抗闪烁、50Hz抗闪烁、60Hz抗闪烁。

        10、设置某个通道红外滤光片的使能情况,夜晚时使能,白天时不使能,该接口主要用于产线工具使用。

        11、设置某个通道红外灯的使能情况,夜晚时使能,白天时不使能,该接口主要用于产线工具使用。

        12、判断当前某个通道的日夜模式是否为夜晚。

        13、设置某个通道是否检测到了智能报警事件。当日夜模式为智能模式时,如果检测到了智能报警事件,则自动打开白光灯。

        ISP接口类的头文件如下:

#pragma once

#include "HP_MPPTypes.h"

class CHP_ISP
{
public:
    virtual int Init(const TMppIspParam &param) = 0;

    virtual int SetHuePercent(unsigned int uiCameraChannel, unsigned char ucPercent) = 0;
    virtual int SetContrastPercent(unsigned int uiCameraChannel, unsigned char ucPercent) = 0;
    virtual int SetBrightnessPercent(unsigned int uiCameraChannel, unsigned char ucPercent) = 0;
    virtual int SetSaturationPercent(unsigned int uiCameraChannel, unsigned char ucPercent) = 0;
    virtual int SetSharpnessPercent(unsigned int uiCameraChannel, unsigned char ucPercent) = 0;

    virtual int SetNightVisionMode(unsigned int uiCameraChannel, IMppNightVisionMode mode) = 0;
    virtual int SetFlipMode(unsigned int uiCameraChannel, IMppIspFlipMode mode) = 0;
    virtual int SetAntiFlickerMode(unsigned int uiCameraChannel, IMppAntiflickerMode mode) = 0;
    virtual int SetIrFilter(unsigned int uiCameraChannel, bool bNight) = 0;
    virtual int SetIrLight(unsigned int uiCameraChannel, bool bNight) = 0;
    virtual bool IsNight(unsigned int uiCameraChannel) = 0;
    virtual int SetSmartEventDetected(unsigned int uiCameraChannel, bool bDetected) = 0;

protected:
    CHP_ISP() {}
    virtual ~CHP_ISP() {}
};

        Init接口中,TMppIspParam结构体的定义如下:

typedef int(*CALLBACK_CUSTOM_SWITCH_IR_FILTER)(unsigned int uiCameraChannel, bool bNight, void *pContext);
typedef void(*CALLBACK_SWITCH_WHITE_LIGHT)(unsigned int uiCameraChannel, bool bOn, void *pContext);
typedef void(*CALLBACK_GET_WHITE_LIGHT_STATUS)(unsigned int uiCameraChannel, bool &bOpenForEver, bool &bIsOn, 
        bool &bTwinkle, void *pContext);

enum IMppDayNightDetectMode
{
        MppDayNightDetectMode_ADC,
        MppDayNightDetectMode_GPIO,
        MppDayNightDetectMode_Soft,
        MppDayNightDetectMode_Count
};

typedef struct _TMppCameraAdcInfo 
{
        _TMppCameraAdcInfo()
        {
                nAdcIndex = 0;
                nSwitchToDayAdc = 200;
                nSwitchToNightAdc = 80;
        }

        int nAdcIndex;
        int nSwitchToDayAdc;
        int nSwitchToNightAdc;
}TMppCameraAdcInfo;

typedef struct _TMppCameraGpioInfo 
{
        _TMppCameraGpioInfo()
        {
                uiDayNightDetectGpio = 0;
                bDayNightDetectGpioLowDay = false;
        }

        unsigned int uiDayNightDetectGpio;
        bool bDayNightDetectGpioLowDay;
}TMppCameraGpioInfo;

typedef struct _TMppCameraSoftInfo 
{
        _TMppCameraSoftInfo()
        {
                uiSwitchToNightEv = 60000;
                uiSwitchToDayEv = 8000;
                uiBlueGainDiffBetweenCurAndMin = 15;
                uiBlueGainDiffBetweenCurAndMax = 15;
        }

        unsigned int uiSwitchToNightEv;
        unsigned int uiSwitchToDayEv;
        unsigned int uiBlueGainDiffBetweenCurAndMin;
        unsigned int uiBlueGainDiffBetweenCurAndMax;
}TMppCameraSoftInfo;

typedef struct _TMppIspCameraParam 
{
        _TMppIspCameraParam()
        {
                uiIrFilterPGpio = 0;
                uiIrFilterNGpio = 0;
                uiIrLightGpio = 0;
                detectMode = MppDayNightDetectMode_ADC;
        }

        unsigned int uiIrFilterPGpio;
        unsigned int uiIrFilterNGpio;
        unsigned int uiIrLightGpio;
        IMppDayNightDetectMode detectMode;
        TMppCameraSoftInfo softInfo;
        union
        {
                TMppCameraAdcInfo adcInfo;
                TMppCameraGpioInfo gpioInfo;
        };
}TMppIspCameraParam;

typedef std::vector<TMppIspCameraParam> TMppIspCameraParamVector;

typedef struct _TMppIspParam 
{
        _TMppIspParam()
        {
                pCbCustomSwitchIrFilter = NULL;
                pCbSwitchWhiteLight = NULL;
                pCbGetWhiteLightStatus = NULL;
                pCbContext = NULL;
                pLogger = NULL;
        }

        TMppIspCameraParamVector vctCamera;
        CALLBACK_CUSTOM_SWITCH_IR_FILTER pCbCustomSwitchIrFilter;
        CALLBACK_SWITCH_WHITE_LIGHT pCbSwitchWhiteLight;
        CALLBACK_GET_WHITE_LIGHT_STATUS pCbGetWhiteLightStatus;
        void *pCbContext;
        CHP_Logger *pLogger;
}TMppIspParam;

        在TMppCameraAdcInfo结构体中,需要给出ADC的通道号、由夜晚切换到白天的ADC阈值、由白天切换到夜晚的ADC阈值。

        在TMppCameraGpioInfo结构体中,需要给出日夜切换的GPIO管脚、白天是否用低电平表示等参数。

        在TMppCameraSoftInfo结构体中,需要给出由白天切换到夜晚的EV阈值、由夜晚切换到白天的EV阈值、以及蓝色增益偏移量的最小最大值等参数。

        在TMppIspCameraParam结构体中,需要给出红外滤光片的两个GPIO管脚、白光灯的GPIO管脚、日夜探测模式等参数。由于使用硬光敏时,也需要使用软光敏进行辅助,因此softInfo变量没有放在共用体中。

        在TMppIspParam结构体中,需要给出每个通道的摄像头参数信息、自定义红外滤光片切换的回调函数、切换白光灯的回调函数、获取白光灯状态的回调函数等。

ADC的封装

        在君正芯片方案中,如果要使用ADC,需要先在内核中按下图进行配置。

        配置完成之后,接下来需要编写ADC辅助类,用于读取某个ADC通道的值。

        ADC辅助类的头文件AdcAux.h如下:

#pragma once

class CAdcAux
{
public:
    CAdcAux();
    ~CAdcAux();

    int Open(unsigned int uiIndex);
    void Close();

    int Enable();
    int Disable();
    int GetValue(int &nValue);

private:
    int m_nFd;
};

        ADC辅助类的实现文件AdcAux.cpp如下:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>

#include "HP_MPPErrorCode.h"
#include "AdcAux.h"

#define ADC_AUX_CMD_ENABLE                                  0
#define ADC_AUX_CMD_DISABLE                                 1
#define ADC_AUX_CMD_SET_VREF                                2
#define ADC_AUX_STD_VREF_VALUE                              1800

#if defined(CHIP_T31)
        #define ADC_AUX_DEV_PATH                            "/dev/jz_adc_aux_"
#elif defined(CHIP_T40)
        #define ADC_AUX_DEV_PATH                            "/dev/ingenic_adc_aux_"
#else
        #define ADC_AUX_DEV_PATH                            "/dev/jz_adc_aux_"
#endif

CAdcAux::CAdcAux() : m_nFd(-1)
{
        NULL;
}

CAdcAux::~CAdcAux()
{
        Disable();
        Close();
}

int CAdcAux::Open(unsigned int uiIndex)
{
        int nRet = 0;
        char pszFile[256] = { 0 };
        sprintf(pszFile, "%s%u", ADC_AUX_DEV_PATH, uiIndex);
        m_nFd = open(pszFile, O_RDONLY);
        if (m_nFd < 0)
        {
                nRet = E_MPP_File;
        }
        else
        {
                int nRef = ADC_AUX_STD_VREF_VALUE;
                nRet = ioctl(m_nFd, ADC_AUX_CMD_SET_VREF, &nRef);
                if (nRet != 0)
                {
                        Close();
                }
        }

        return nRet;
}

void CAdcAux::Close()
{
        if (m_nFd >= 0)
        {
                close(m_nFd);
                m_nFd = -1;
        }
}

int CAdcAux::Enable()
{
        if (m_nFd < 0)
        {
                return E_MPP_WrongState;
        }

        return ioctl(m_nFd, ADC_AUX_CMD_ENABLE);
}

int CAdcAux::Disable()
{
        if (m_nFd < 0)
        {
                return E_MPP_WrongState;
        }

        return ioctl(m_nFd, ADC_AUX_CMD_DISABLE);
}

int CAdcAux::GetValue(int &nValue)
{
        if (m_nFd < 0)
        {
                return E_MPP_WrongState;
        }

        int nValueTemp = 0;
        int nRet = read(m_nFd, &nValueTemp, sizeof(nValueTemp));
        if (nRet != sizeof(nValueTemp))
        {
                nRet = E_MPP_File;
        }
        else
        {
                nRet = 0;
                nValue = nValueTemp;
        }

        return nRet;
}

ISP实现类

        ISP实现类派生于ISP接口类,也派生于线程基类。ISP实现类的头文件如下:

#pragma once

#include <HP_Base/HP_BaseThread.h>
#include <HP_Base/HP_Mutex.h>

#include "HP_ISP.h"
#include "MPP_API_Base.h"

class CISP : public CHP_ISP, public CHP_BaseThread
{
public:
    static void Open(CMppApi_Base *pApi);
    static CISP *&Singleton();
    static void Close();

    virtual int Init(const TMppIspParam &param);

    virtual int SetHuePercent(unsigned int uiCameraChannel, unsigned char ucPercent);
    virtual int SetContrastPercent(unsigned int uiCameraChannel, unsigned char ucPercent);
    virtual int SetBrightnessPercent(unsigned int uiCameraChannel, unsigned char ucPercent);
    virtual int SetSaturationPercent(unsigned int uiCameraChannel, unsigned char ucPercent);
    virtual int SetSharpnessPercent(unsigned int uiCameraChannel, unsigned char ucPercent);

    virtual int SetNightVisionMode(unsigned int uiCameraChannel, IMppNightVisionMode mode);
    virtual int SetFlipMode(unsigned int uiCameraChannel, IMppIspFlipMode mode);
    virtual int SetAntiFlickerMode(unsigned int uiCameraChannel, IMppAntiflickerMode mode);
    virtual int SetIrFilter(unsigned int uiCameraChannel, bool bNight);
    virtual int SetIrLight(unsigned int uiCameraChannel, bool bNight);
    virtual bool IsNight(unsigned int uiCameraChannel);
    virtual int SetSmartEventDetected(unsigned int uiCameraChannel, bool bDetected);

protected:
    CISP(CMppApi_Base *pApi);
    virtual ~CISP();

    virtual unsigned int Run();

private:
    typedef struct _TIspCameraWorkAdcInfo
    {
        _TIspCameraWorkAdcInfo()
        {
            bOpened = false;
            uiOpenTryCount = 0;
            pAdc = NULL;
        }

        bool bOpened;
        unsigned int uiOpenTryCount;
        void *pAdc;
    }TIspCameraWorkAdcInfo;

    typedef struct _TIspCameraWorkSoftInfo
    {
        _TIspCameraWorkSoftInfo()
        {
            uiGbGainMin = 0;
            uiGbGainMax = 0;
            uiLastCheckTick = 0;
        }

        unsigned int uiGbGainMin;
        unsigned int uiGbGainMax;
        unsigned int uiLastCheckTick;
    }TIspCameraWorkSoftInfo;

    typedef struct _TIspCameraWorkInfo
    {
        _TIspCameraWorkInfo()
        {
            bNight = false;
            mode = MppNightVisionMode_BlackWhiteOff;
            bSmartEventLastDetected = false;
        }

        bool bNight;
        IMppNightVisionMode mode;
        bool bSmartEventLastDetected;
        unsigned int uiDayCount;
        unsigned int uiNightCount;
        union
        {
            TIspCameraWorkAdcInfo adc;
            TIspCameraWorkSoftInfo soft;
        };
    }TIspCameraWorkInfo;

    typedef std::vector<TIspCameraWorkInfo> TIspCameraWorkInfoVector;

    void Work_ADC(unsigned int uiCameraChannel, const TMppIspCameraParam &cp, TIspCameraWorkInfo &cwInfo);
    void Work_GPIO(unsigned int uiCameraChannel, const TMppIspCameraParam &cp, TIspCameraWorkInfo &cwInfo);
    void Work_Soft(unsigned int uiCameraChannel, const TMppIspCameraParam &cp, TIspCameraWorkInfo &cwInfo);
    void SwitchDayNight(unsigned int uiCameraChannel, bool bNight, const TMppIspCameraParam &cp, 
        TIspCameraWorkInfo &cwInfo);
    void SwitchToNight(unsigned int uiCameraChannel, TIspCameraWorkInfo &cwInfo, bool bNight);
    void SwitchToDay(unsigned int uiCameraChannel, const TMppIspCameraParam &cp, TIspCameraWorkInfo &cwInfo, 
        bool *pbNight = NULL);
    void SetIrNight(unsigned int uiCameraChannel, bool bNight);
    void SetNightMode(unsigned int uiCameraChannel, bool bNight);
    void SwitchWhiteLight(unsigned int uiCameraChannel, bool bOn);
    void SetNightVisionMode_Impl(unsigned int uiCameraChannel, IMppNightVisionMode mode, bool bNight);
    void GetGainThreshold(unsigned int uiCameraChannel, unsigned int &uiMin, unsigned int &uiMax);

private:
    static CISP *m_pThis;
    CMppApi_Base *m_pApi;
    TMppIspParam m_param;
    TIspCameraWorkInfoVector m_vctWorkInfo;
    CHP_Mutex m_mutexWork;
};

        可以看到,有一个TIspCameraWorkInfoVector的成员变量m_vctWorkInfo,用于保存每个摄像头的工作信息。每个摄像头的工作信息包括:当前是否为夜晚、当前的日夜模式、上一次是否检测到了智能报警事件、判定为白天的次数、判定为夜晚的次数、ADC信息、软光敏信息等。

        ADC信息TIspCameraWorkAdcInfo中,包括:ADC辅助类的指针、ADC辅助类是否已打开、ADC辅助类打开尝试的次数等。

        软光敏信息TIspCameraWorkSoftInfo中,包括:颜色增益的最小最大值、上一次检测的时间戳等。

        ISP实现类的实现文件如下:

#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>

#include <HP_Base/HP_Utils.h>

#include "ISP.h"
#include "AdcAux.h"
#include "HP_GPIOUtils.h"

CISP *CISP::m_pThis = NULL;

CISP::CISP(CMppApi_Base *pApi) : CHP_ISP(), CHP_BaseThread(), m_pApi(pApi)
{
    NULL;
}

CISP::~CISP()
{
        CHP_BaseThread::Stop();
        for (unsigned int i = 0; i < m_vctWorkInfo.size(); i++)
        {
                TIspCameraWorkInfo &cwInfo = m_vctWorkInfo[i];
                TMppIspCameraParam &cp = m_param.vctCamera[i];
                if (cp.detectMode == MppDayNightDetectMode_ADC && cwInfo.adc.pAdc != NULL)
                {
                        delete (CAdcAux *)cwInfo.adc.pAdc;
                        cwInfo.adc.pAdc = NULL;
                }
        }
}

void CISP::Open(CMppApi_Base *pApi)
{
        if (m_pThis == NULL)
        {
                m_pThis = new CISP(pApi);
        }
}

CISP *&CISP::Singleton()
{
        return m_pThis;
}

void CISP::Close()
{
        if (m_pThis != NULL)
        {
                delete m_pThis;
                m_pThis = NULL;
        }
}

int CISP::Init(const TMppIspParam &param)
{
        unsigned int uiMaxCameraCount = 1;
#if defined(CHIP_T40)
        uiMaxCameraCount = 2;
#endif

        if (param.vctCamera.empty() || param.vctCamera.size() > uiMaxCameraCount)
        {
                CHP_Logger::Error(param.pLogger, "isp camera size invalid: %u, %u", param.vctCamera.size(), 
                        uiMaxCameraCount);
                return E_MPP_Param;
        }

        for (unsigned int i = 0; i < param.vctCamera.size(); i++)
        {
                const TMppIspCameraParam &cp = param.vctCamera[i];
                if (cp.detectMode >= MppDayNightDetectMode_Count)
                {
                        CHP_Logger::Error(param.pLogger, "isp camera detect mode invalid: %u, %u", i, cp.detectMode);
                        return E_MPP_Param;
                }

                if (cp.softInfo.uiSwitchToNightEv <= cp.softInfo.uiSwitchToDayEv)
                {
                        CHP_Logger::Error(param.pLogger, "isp camera soft exposure value invalid: %u, %u, %u", i, 
                                cp.softInfo.uiSwitchToNightEv, cp.softInfo.uiSwitchToDayEv);
                        return E_MPP_Param;
                }

                if (cp.detectMode == MppDayNightDetectMode_ADC && cp.adcInfo.nSwitchToDayAdc <= 
                        cp.adcInfo.nSwitchToNightAdc)
                {
                        CHP_Logger::Error(param.pLogger, "isp camera adc value invalid: %u, %d, %d", i, 
                                cp.adcInfo.nSwitchToDayAdc, cp.adcInfo.nSwitchToNightAdc);
                        return E_MPP_Param;
                }

                if (cp.detectMode == MppDayNightDetectMode_GPIO && cp.gpioInfo.uiDayNightDetectGpio == 0)
                {
                        CHP_Logger::Error(param.pLogger, "isp camera gpio invalid: %u", i);
                        return E_MPP_Param;
                }
        }

        if (m_pApi == NULL || !m_param.vctCamera.empty())
        {
                CHP_Logger::Error(param.pLogger, "isp has been inited: %u", m_param.vctCamera.size());
                return E_MPP_WrongState;
        }

        for (unsigned int i = 0; i < param.vctCamera.size(); i++)
        {
                const TMppIspCameraParam &cp = param.vctCamera[i];
                int nRet = CHP_GPIOUtils::Init(cp.uiIrFilterPGpio);
                if (nRet != 0)
                {
                        CHP_Logger::Warn(param.pLogger, "isp camera ir filter p gpio init failed: %u, %d", i, nRet);
                }

                nRet = CHP_GPIOUtils::Init(cp.uiIrFilterNGpio);
                if (nRet != 0)
                {
                        CHP_Logger::Warn(param.pLogger, "isp camera ir filter n gpio init failed: %u, %d", i, nRet);
                }

                nRet = CHP_GPIOUtils::Init(cp.uiIrLightGpio);
                if (nRet != 0)
                {
                        CHP_Logger::Warn(param.pLogger, "isp camera ir light gpio init failed: %u, %d", i, nRet);
                }

                if (cp.detectMode == MppDayNightDetectMode_GPIO)
                {
                        nRet = CHP_GPIOUtils::Init(cp.gpioInfo.uiDayNightDetectGpio, false);
                        if (nRet != 0)
                        {
                                CHP_Logger::Warn(param.pLogger, "isp camera day night detect gpio init failed: %u, %d", i, nRet);
                        }
                }

                SetIrNight(i, false);
                TIspCameraWorkInfo cwInfo;
                cwInfo.mode = MppNightVisionMode_BlackWhiteOff;
                if (cp.detectMode == MppDayNightDetectMode_ADC)
                {
                        cwInfo.adc.pAdc = new CAdcAux();
                }

                m_vctWorkInfo.push_back(cwInfo);
        }

        m_param = param;
        CHP_BaseThread::Start();
        CHP_Logger::Info(param.pLogger, "isp init ok");
        return 0;
}

int CISP::SetHuePercent(unsigned int uiCameraChannel, unsigned char ucPercent)
{
        if (uiCameraChannel >= m_param.vctCamera.size())
        {
                return E_MPP_Param;
        }

        if (m_pApi == NULL)
        {
                return E_MPP_WrongState;
        }

        return m_pApi->Isp_SetHue(ucPercent, uiCameraChannel);
}

int CISP::SetContrastPercent(unsigned int uiCameraChannel, unsigned char ucPercent)
{
        if (uiCameraChannel >= m_param.vctCamera.size())
        {
                return E_MPP_Param;
        }

        if (m_pApi == NULL)
        {
                return E_MPP_WrongState;
        }

        return m_pApi->Isp_SetContrast(ucPercent, uiCameraChannel);
}

int CISP::SetBrightnessPercent(unsigned int uiCameraChannel, unsigned char ucPercent)
{
        if (uiCameraChannel >= m_param.vctCamera.size())
        {
                return E_MPP_Param;
        }

        if (m_pApi == NULL)
        {
                return E_MPP_WrongState;
        }

        return m_pApi->Isp_SetBrightness(ucPercent, uiCameraChannel);
}

int CISP::SetSaturationPercent(unsigned int uiCameraChannel, unsigned char ucPercent)
{
        if (uiCameraChannel >= m_param.vctCamera.size())
        {
                return E_MPP_Param;
        }

        if (m_pApi == NULL)
        {
                return E_MPP_WrongState;
        }

        return m_pApi->Isp_SetSaturation(ucPercent, uiCameraChannel);
}

int CISP::SetSharpnessPercent(unsigned int uiCameraChannel, unsigned char ucPercent)
{
        if (uiCameraChannel >= m_param.vctCamera.size())
        {
                return E_MPP_Param;
        }

        if (m_pApi == NULL)
        {
                return E_MPP_WrongState;
        }

        return m_pApi->Isp_SetSharpness(ucPercent, uiCameraChannel);
}

int CISP::SetNightVisionMode(unsigned int uiCameraChannel, IMppNightVisionMode mode)
{
        if (uiCameraChannel >= m_param.vctCamera.size() || mode >= MppNightVisionMode_Count)
        {
                return E_MPP_Param;
        }

        if (m_param.pCbSwitchWhiteLight == NULL && (mode == MppNightVisionMode_FullColor || 
                mode == MppNightVisionMode_Smart))
        {
                CHP_Logger::Warn(m_param.pLogger, "isp night vision mode not support: %u, %u", uiCameraChannel, mode);
                return E_MPP_Param;
        }

        if (m_pApi == NULL)
        {
                return E_MPP_WrongState;
        }

        int nRet = 0;
        m_mutexWork.Lock();
        TIspCameraWorkInfo &cwInfo = m_vctWorkInfo[uiCameraChannel];
        if (cwInfo.mode != mode)
        {
                cwInfo.mode = mode;
                SetNightVisionMode_Impl(uiCameraChannel, mode, cwInfo.bNight);
                CHP_Logger::Info(m_param.pLogger, "isp night vision mode change to %u", mode);
        }
        
        m_mutexWork.Unlock();
        return nRet;
}

int CISP::SetFlipMode(unsigned int uiCameraChannel, IMppIspFlipMode mode)
{
        if (uiCameraChannel >= m_param.vctCamera.size() || mode >= MppIspFlipMode_Count)
        {
                return E_MPP_Param;
        }

        if (m_pApi == NULL)
        {
                return E_MPP_WrongState;
        }

        int nRet = 0;
        switch (mode)
        {
        case MppIspFlipMode_None:
                nRet = m_pApi->Isp_SetHorVerFlip(false, uiCameraChannel);
                break;
        case MppIspFlipMode_Hor:
                nRet = m_pApi->Isp_SetHorFlip(true, uiCameraChannel);
                break;
        case MppIspFlipMode_Ver:
                nRet = m_pApi->Isp_SetVerFlip(true, uiCameraChannel);
                break;
        case MppIspFlipMode_HorVer:
                nRet = m_pApi->Isp_SetHorVerFlip(true, uiCameraChannel);
                break;
        default:
                break;
        }

        return nRet;
}

int CISP::SetAntiFlickerMode(unsigned int uiCameraChannel, IMppAntiflickerMode mode)
{
        if (uiCameraChannel >= m_param.vctCamera.size() || mode >= MppAntiflickerMode_Count)
        {
                return E_MPP_Param;
        }

        if (m_pApi == NULL)
        {
                return E_MPP_WrongState;
        }

        return m_pApi->Isp_SetAntiFlicker(mode, uiCameraChannel);
}

int CISP::SetIrFilter(unsigned int uiCameraChannel, bool bNight)
{
        if (uiCameraChannel >= m_param.vctCamera.size())
        {
                return E_MPP_Param;
        }

        if (m_param.pCbCustomSwitchIrFilter != NULL)
        {
                return m_param.pCbCustomSwitchIrFilter(uiCameraChannel, bNight, m_param.pCbContext);
        }

        TMppIspCameraParam &cp = m_param.vctCamera[uiCameraChannel];
        if (cp.uiIrFilterPGpio == 0 || cp.uiIrFilterNGpio == 0)
        {
                return E_MPP_NotSupport;
        }

        char pszFile[256] = {0};
        sprintf(pszFile, "/sys/class/gpio/gpio%u/value", cp.uiIrFilterPGpio);
        int nFileP = open(pszFile, O_RDWR);
        sprintf(pszFile, "/sys/class/gpio/gpio%u/value", cp.uiIrFilterNGpio);
        int nFileN = open(pszFile, O_RDWR);
        if (bNight)
        {
                write(nFileP, "1", 1);
                write(nFileN, "0", 1);
        }
        else
        {
                write(nFileP, "0", 1);
                write(nFileN, "1", 1);
        }

        usleep(100 * 1000);

        if (bNight)
        {
                write(nFileP, "0", 1);
                write(nFileN, "1", 1);
        }
        else
        {
                write(nFileP, "1", 1);
                write(nFileN, "0", 1);
        }

        usleep(100 * 1000);
        write(nFileP, "0", 1);
        write(nFileN, "0", 1);
        close(nFileP);
        close(nFileN);
        return 0;
}

int CISP::SetIrLight(unsigned int uiCameraChannel, bool bNight)
{
        if (uiCameraChannel >= m_param.vctCamera.size())
        {
                return E_MPP_Param;
        }

        TMppIspCameraParam &cp = m_param.vctCamera[uiCameraChannel];
        if (cp.uiIrLightGpio == 0)
        {
                return E_MPP_NotSupport;
        }

        return CHP_GPIOUtils::SetValue(cp.uiIrLightGpio, bNight);
}

bool CISP::IsNight(unsigned int uiCameraChannel)
{
        bool bNight = false;
        if (uiCameraChannel < m_vctWorkInfo.size())
        {
                TIspCameraWorkInfo &cwInfo = m_vctWorkInfo[uiCameraChannel];
                bNight = cwInfo.bNight;
        }

        return bNight;
}

int CISP::SetSmartEventDetected(unsigned int uiCameraChannel, bool bDetected)
{
        if (uiCameraChannel >= m_param.vctCamera.size())
        {
                return E_MPP_Param;
        }

        if (m_pApi == NULL)
        {
                return E_MPP_WrongState;
        }

        m_mutexWork.Lock();
        TIspCameraWorkInfo &cwInfo = m_vctWorkInfo[uiCameraChannel];
        bool bLastDetected = cwInfo.bSmartEventLastDetected;
        cwInfo.bSmartEventLastDetected = bDetected;
        if (cwInfo.mode == MppNightVisionMode_Smart && cwInfo.bNight)
        {
                if (!bLastDetected)
                {
                        if (bDetected)
                        {
                                SetNightMode(uiCameraChannel, false);
                                SwitchWhiteLight(uiCameraChannel, true);
                        }
                }
                else
                {
                        if (!bDetected)
                        {
                                SetNightMode(uiCameraChannel, true);
                                SwitchWhiteLight(uiCameraChannel, false);
                        }
                }
        }

        m_mutexWork.Unlock();
        return 0;
}

unsigned int CISP::Run()
{
        while (!m_bStop)
        {
                m_mutexWork.Lock();
                for (unsigned int i = 0; i < m_vctWorkInfo.size(); i++)
                {
                        TIspCameraWorkInfo &cwInfo = m_vctWorkInfo[i];
                        TMppIspCameraParam &cp = m_param.vctCamera[i];
                        if (cwInfo.mode != MppNightVisionMode_BlackWhiteOn && cwInfo.mode != MppNightVisionMode_BlackWhiteOff)
                        {
                                if (cp.detectMode == MppDayNightDetectMode_ADC)
                                {
                                        Work_ADC(i, cp, cwInfo);
                                }
                                else if (cp.detectMode == MppDayNightDetectMode_GPIO)
                                {
                                        Work_GPIO(i, cp, cwInfo);
                                }
                                else
                                {
                                        Work_Soft(i, cp, cwInfo);
                                }
                        }
                }
                m_mutexWork.Unlock();

                CHP_BaseThread::Sleep(1000, 10);
        }

        return 0;
}

void CISP::Work_ADC(unsigned int uiCameraChannel, const TMppIspCameraParam &cp, TIspCameraWorkInfo &cwInfo)
{
        CAdcAux *pAdc = (CAdcAux *)cwInfo.adc.pAdc;
        if (!cwInfo.adc.bOpened)
        {
                int nRet = pAdc->Open(uiCameraChannel);
                if (nRet == 0)
                {
                        pAdc->Enable();
                        cwInfo.adc.bOpened = true;
                }
                else
                {
                        cwInfo.adc.uiOpenTryCount++;
                        if (cwInfo.adc.uiOpenTryCount % 10 == 0)
                        {
                                CHP_Logger::Error(m_param.pLogger, "isp adc open failed: %d", nRet);
                        }
                }
        }
        else
        {
                bool bNight = false;
                int nValue = 0;
                int nRet = pAdc->GetValue(nValue);
                if (nRet == 0)
                {
                        if (nValue < cp.adcInfo.nSwitchToNightAdc)
                        {
                                bNight = true;
                        }
                        else if (nValue > cp.adcInfo.nSwitchToDayAdc)
                        {
                                bNight = false;
                        }
                        else
                        {
                                bNight = cwInfo.bNight;
                        }

#if false
                        TMppIspExposureAttr evAttr;
                        TMppIspWBAttr wbAttr;
                        m_pApi->Isp_GetExposureAttr(evAttr, uiCameraChannel);
                        m_pApi->Isp_GetGlobalWhiteBalance(wbAttr, uiCameraChannel);
                        unsigned int uiGbGain = (wbAttr.usBlueGain != 0) ? (65536 / wbAttr.usBlueGain) : wbAttr.usBlueGain;
                        CHP_Logger::Trace(m_param.pLogger, "adc value: %d, %u, %u", nValue, evAttr.uiEv, uiGbGain);
#endif
                }

                SwitchDayNight(uiCameraChannel, bNight, cp, cwInfo);
        }
}

void CISP::Work_GPIO(unsigned int uiCameraChannel, const TMppIspCameraParam &cp, TIspCameraWorkInfo &cwInfo)
{
        bool bNight = false;
        bool bValue = false;
        int nRet = CHP_GPIOUtils::GetValue(cp.gpioInfo.uiDayNightDetectGpio, bValue);
        if (nRet == 0)
        {
                bNight = cp.gpioInfo.bDayNightDetectGpioLowDay ? bValue : !bValue;
        }

        SwitchDayNight(uiCameraChannel, bNight, cp, cwInfo);
}

void CISP::Work_Soft(unsigned int uiCameraChannel, const TMppIspCameraParam &cp, TIspCameraWorkInfo &cwInfo)
{
        if (cwInfo.bNight)
        {
                SwitchToDay(uiCameraChannel, cp, cwInfo);
        } 
        else
        {
                TMppIspExposureAttr evAttr;
                int nRet = m_pApi->Isp_GetExposureAttr(evAttr, uiCameraChannel);
                bool bNight = nRet == 0 && evAttr.uiEv >= cp.softInfo.uiSwitchToNightEv;
                SwitchToNight(uiCameraChannel, cwInfo, bNight);
        }
}

void CISP::SwitchDayNight(unsigned int uiCameraChannel, bool bNight, const TMppIspCameraParam &cp, 
        TIspCameraWorkInfo &cwInfo)
{
        if (cwInfo.bNight)
        {
                SwitchToDay(uiCameraChannel, cp, cwInfo, &bNight);
        }
        else
        {
                SwitchToNight(uiCameraChannel, cwInfo, bNight);
        }
}

void CISP::SwitchToNight(unsigned int uiCameraChannel, TIspCameraWorkInfo &cwInfo, bool bNight)
{
        if (bNight)
        {
                cwInfo.uiNightCount++;
                if (cwInfo.uiNightCount > 5)
                {
                        cwInfo.bNight = true;
                        cwInfo.uiDayCount = 0;
                        cwInfo.soft.uiLastCheckTick = 0;
                        cwInfo.soft.uiGbGainMin = 65536;
                        cwInfo.soft.uiGbGainMax = 0;
                        SetNightVisionMode_Impl(uiCameraChannel, cwInfo.mode, true);
                        CHP_Logger::Info(m_param.pLogger, "isp switch to night");
                }
        }
        else
        {
                cwInfo.uiNightCount = 0;
        }
}

void CISP::SwitchToDay(unsigned int uiCameraChannel, const TMppIspCameraParam &cp, TIspCameraWorkInfo &cwInfo, 
        bool *pbNight /* = NULL */)
{
        TMppIspExposureAttr evAttr;
        int nRet = m_pApi->Isp_GetExposureAttr(evAttr, uiCameraChannel);
        TMppIspWBAttr wbAttr;
        int nRet2 = m_pApi->Isp_GetGlobalWhiteBalance(wbAttr, uiCameraChannel);
        if (nRet != 0 || nRet2 != 0)
        {
                return;
        }

        unsigned int uiCurTick = CHP_Utils::GetCurTick();
        if (cwInfo.soft.uiLastCheckTick == 0 || uiCurTick - cwInfo.soft.uiLastCheckTick >= 3 * 1000)
        {
                GetGainThreshold(uiCameraChannel, cwInfo.soft.uiGbGainMin, cwInfo.soft.uiGbGainMax);
                cwInfo.soft.uiLastCheckTick = uiCurTick;
        }

        if (evAttr.uiEv <= cp.softInfo.uiSwitchToDayEv)
        {
                bool bOpenForEver = false;
                bool bTwinkle = false;
                bool bIsOn = false;
                if (m_param.pCbGetWhiteLightStatus != NULL)
                {
                        m_param.pCbGetWhiteLightStatus(uiCameraChannel, bOpenForEver, bIsOn, bTwinkle, m_param.pCbContext);
                }

                bool bMaybeDay = false;
                unsigned int uiGbGain = (wbAttr.usBlueGain != 0) ? (65536 / wbAttr.usBlueGain) : wbAttr.usBlueGain;
                if (bOpenForEver)
                {
                        if (!bTwinkle)
                        {
                                bMaybeDay = uiGbGain + cp.softInfo.uiBlueGainDiffBetweenCurAndMax < cwInfo.soft.uiGbGainMax;
                        }
                }
                else
                {
                        if (!bTwinkle && !bIsOn)
                        {
                                if (pbNight == NULL)
                                {
                                        bMaybeDay = uiGbGain > cwInfo.soft.uiGbGainMin + cp.softInfo.uiBlueGainDiffBetweenCurAndMin;
                                }
                                else
                                {
                                        bMaybeDay = !(*pbNight);
                                }
                        }
                }

                if (bMaybeDay)
                {
                        cwInfo.uiDayCount++;
                        if (cwInfo.uiDayCount > 5)
                        {
                                cwInfo.bNight = false;
                                cwInfo.uiNightCount = 0;
                                SetNightVisionMode_Impl(uiCameraChannel, cwInfo.mode, false);
                                CHP_Logger::Info(m_param.pLogger, "isp switch to day, %u, %u, %u, %d, %d, %d", uiGbGain, 
                                        cwInfo.soft.uiGbGainMin, cwInfo.soft.uiGbGainMax, bOpenForEver, bTwinkle, bIsOn);
                        }
                }
                else
                {
                        cwInfo.uiDayCount = 0;
                }
        }
        else
        {
                cwInfo.uiDayCount = 0;
        }   
}

void CISP::SetIrNight(unsigned int uiCameraChannel, bool bNight)
{
    SetIrFilter(uiCameraChannel, bNight);
    SetIrLight(uiCameraChannel, bNight);
}

void CISP::SetNightMode(unsigned int uiCameraChannel, bool bNight)
{
        SetIrNight(uiCameraChannel, bNight);
        m_pApi->Isp_SetRunningMode(bNight, uiCameraChannel);
}

void CISP::SwitchWhiteLight(unsigned int uiCameraChannel, bool bOn)
{
        if (m_param.pCbSwitchWhiteLight != NULL)
        {
                m_param.pCbSwitchWhiteLight(uiCameraChannel, bOn, m_param.pCbContext);
        }
}

void CISP::SetNightVisionMode_Impl(unsigned int uiCameraChannel, IMppNightVisionMode mode, bool bNight)
{
        if (mode == MppNightVisionMode_BlackWhiteOff || mode == MppNightVisionMode_BlackWhiteOn)
        {
                bNight = mode == MppNightVisionMode_BlackWhiteOn;
                SetNightMode(uiCameraChannel, bNight);
                SwitchWhiteLight(uiCameraChannel, false);        
        }
        else if (mode == MppNightVisionMode_BlackWhiteAuto)
        {
                SetNightMode(uiCameraChannel, bNight);
                SwitchWhiteLight(uiCameraChannel, false);        
        }
        else if (mode == MppNightVisionMode_FullColor)
        {
                SetNightMode(uiCameraChannel, false);
                SwitchWhiteLight(uiCameraChannel, true);
        }
        else
        {
                SetNightMode(uiCameraChannel, bNight);
                SwitchWhiteLight(uiCameraChannel, false);
        }
}

void CISP::GetGainThreshold(unsigned int uiCameraChannel, unsigned int &uiMin, unsigned int &uiMax)
{
        TMppIspWBAttr wbAttr;
        int nRet = m_pApi->Isp_GetGlobalWhiteBalance(wbAttr, uiCameraChannel);
        if (nRet == 0)
        {
                unsigned int uiGbGain = (wbAttr.usBlueGain != 0) ? (65536 / wbAttr.usBlueGain) : wbAttr.usBlueGain;
                uiMin = (uiMin > uiGbGain) ? uiGbGain : uiMin;
                uiMax = (uiMax < uiGbGain) ? uiGbGain : uiMax;
        }
}

        在Init接口中,我们对传入的参数进行了合法性校验,初始化了红外滤光片、红外灯的GPIO管脚,并根据不同的日夜探测模式进行了不同的逻辑处理。

        在线程Run函数中,我们根据不同的日夜视觉模式和日夜探测模式,分别调用了Work_ADC、Work_GPIO、Work_Soft三个不同的函数进行处理。

        在Work_ADC函数中,会先打开ADC,然后读取ADC的值,并将值与nSwitchToNightAdc、nSwitchToDayAdc进行比较,以判断当前是白天还是夜晚。注意:这里的判断只是一个参考值,所以,还需要调用SwitchDayNight函数,通过软光敏的辅助来进一步判断。

        在Work_GPIO函数中,直接读取GPIO管脚的值,并结合bDayNightDetectGpioLowDay,即可判断当前是白天还是夜晚。后续也需要借助SwitchDayNight函数,通过软光敏的辅助来进一步判断。

        在Work_Soft函数中,会调用SwitchToDay、SwitchToNight函数来判断是否需要切换到白天和夜晚。

        君正ISP的封装就介绍到这里了,下一节,我们介绍君正视频采集的封装。

猜你喜欢

转载自blog.csdn.net/hope_wisdom/article/details/131613513
今日推荐