概述
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 ¶m) = 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 onceclass 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_"
#endifCAdcAux::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 ¶m);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 ¶m)
{unsigned int uiMaxCameraCount = 1;
#if defined(CHIP_T40)uiMaxCameraCount = 2;
#endifif (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 falseTMppIspExposureAttr 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的封装就介绍到这里了,下一节,我们介绍君正视频采集的封装。