概述
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 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 ¶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;
#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的封装就介绍到这里了,下一节,我们介绍君正视频采集的封装。