平台 | 内核版本 |
---|---|
RK1108 | Linux3.1 |
需求分析
本博客将讲解RK1108
平台的摄像头模式的切换:
- IR(红外模式)
- YUV(彩色模式)
模式切换的场景:
- 车辆进入隧道导致对内的驾驶员监控系统摄像头无法有效获取图像。
- 晚上时间段摄像头无法有效获取图像
IR
图像如下图所示:
摄像头模式切换
通过代码的分析我们将熟悉rk1108
的camera HAL
。
首先介绍下rk
摄像头的描述结构体
目录external/libcamerahal/CameraHal10_Release/CameraHal/HAL/include/CamHwItf.h
#define RK_SUPPORTED_CAMERA_NUM_MAX 10
struct rk_cams_dev_info {
int num_camers;
struct rk_cam_video_input_infos* cam[RK_SUPPORTED_CAMERA_NUM_MAX];
struct rk_isp_dev_info isp_dev;
struct rk_cif_dev_infos cif_devs;
struct rk_usb_cam_dev_infos usb_devs;
};
因此应用层定义rk_cams_dev_info
类型结构体,并获取其信息:
struct rk_cams_dev_info Camera::camera_devive_;
CamHwItf::getCameraInfos(&camera_devive_);
HAL
层对应接口分析:
目录external/libcamerahal/CameraHal10_Release/CameraHal/HAL/src/CamHwItf.cpp
shared_ptr<CamHwItf> getCamHwItf(struct rk_isp_dev_info* isp_dev_info) {
shared_ptr<CamHwItf> instance;
#ifdef RK_ISP10
instance = shared_ptr<CamHwItf>(new CamIsp10DevHwItf(isp_dev_info));
mCamIsp10DevHwItf = static_cast<CamIsp10DevHwItf*>(instance.get());
return instance;
#endif
#ifdef RK_ISP11
instance = shared_ptr<CamHwItf>(new CamIsp11DevHwItf(isp_dev_info));
mCamIsp11DevHwItf = static_cast<CamIsp11DevHwItf*>(instance.get());
return instance;
#endif
}
因此应用层需要进行实例化操作,我们后摄是isp
:
instance->camera_instance_ = getCamHwItf(&camera_devive_.isp_dev)
可以看出上面返回的是shared_ptr<CamHwItf>
智能指针 ,那么我就先看下这个类:
目录external/libcamerahal/CameraHal10_Release/CameraHal/HAL/include/CamHwItf.h
class CamHwItf : virtual public enable_shared_from_this<CamHwItf> {
...
CamHwItf(void);
virtual ~CamHwItf(void) {};
//controls
virtual bool initHw(int inputId) = 0;
virtual void deInitHw() = 0;
...
//>0 means IRCUT is working
virtual int getIrCutState();
virtual int setIrCutState(int state);
virtual void setNightMode(bool night_mode);
virtual bool getNightMode();
virtual void setDayNightSwitch(enum HAL_DAYNIGHT_MODE sw);
virtual enum HAL_DAYNIGHT_MODE getDayNightSwitch();
...
}
应用调用其方法进行摄像头模式的切换
shared_ptr<CamHwItf> camera_instance_;
if(camera_instance_.get() != nullptr){
camera_instance_->setDayNightSwitch(HAL_DAYNIGHT_NIGHT);
}
HAL 代码分析
目录:/external/libcamerahal/CameraHal10_Release/CameraHal/HAL/source/CamHwItf.cpp
void CamHwItf::setDayNightSwitch(enum HAL_DAYNIGHT_MODE sw) {
mDayNightSwitch = sw;
}
enum HAL_DAYNIGHT_MODE CamHwItf::getDayNightSwitch() {
return mDayNightSwitch;
}
目录:/external/libcamerahal/CameraHal10_Release/CameraHal/HAL/source/CamIsp11CtrItf.cpp
bool CamIsp11CtrItf::threadLoop() {
...
//ircut
//not do this in convertIAResults, that will cause deadlock now
bool night_mode = mCamHwItf->getNightMode();
enum HAL_DAYNIGHT_MODE day_night_sw = mCamHwItf->getDayNightSwitch();
if (night_mode == true) {
int is_night = CIFISP_LS_INVAL;
switch (day_night_sw) {
case HAL_DAYNIGHT_DAY:
is_night = LIGHT_MODE_DAY;
break;
case HAL_DAYNIGHT_NIGHT:
is_night = LIGHT_MODE_NIGHT;
break;
default:
if (ia_results.aec.Night_Trigger != TRIGGER_OFF){
if (ia_results.aec.Night_Trigger == LIGHT_SENS)// for Light-senstive Trigger
is_night = mIspStats[v4l2_buf.index]->subdev_stat.ls.val;
else if (ia_results.aec.Night_Trigger == NO_LIGHT_SENS)// without Light-senstive Trigger
is_night = ia_results.aec.DON_LightMode;
}
break;
}
if (is_night != CIFISP_LS_INVAL){
if (ia_results.aec.Night_Mode == WHITE_BLACK){// This case requires switch the IR cut filter.
switchSubDevIrCutMode(!is_night);
}
mCamIA_DyCfg.LightMode = is_night ? LIGHT_MODE_NIGHT : LIGHT_MODE_DAY;
}
} else {
switchSubDevIrCutMode(1);
mCamIA_DyCfg.LightMode = LIGHT_MODE_DAY;
}
#endif
...
目录:/external/libcamerahal/CameraHal10_Release/CameraHal/HAL/source/CamIsp1xCtrItf.cpp
mCamHwItf->setIrCutState(1);
目录:/external/libcamerahal/CameraHal10_Release/CameraHal/HAL/source/CamHwItf.cpp
int CamHwItf::setIrCutState(int state) {
return mSpDev->setCtrl(V4L2_CID_BAND_STOP_FILTER, state);
}
目录:external/libcamerahal/CameraHal10_Release/CameraHal/HAL/source/V4l2DevIoctr.cpp
int V4L2DevIoctr::setCtrl(unsigned int id, unsigned int value) {
struct v4l2_control ctrl;
int ret;
ctrl.id = id;
ctrl.value = value;
ret = ioctl(mDevFp, VIDIOC_S_CTRL, &ctrl);
if (ret < 0) {
LOGE("ERR(%s):VIDIOC_S_CTRL(id = %#x (%d), value = %d) failed ret = %d\n",
__func__, id, id - V4L2_CID_PRIVATE_BASE, value, ret);
}
return ret;
}