平台 | 内核版本 | 版本 |
---|---|---|
rv1108 | Linux3.1 | MiniGUI |
文章目录
源码目录:
Camera HAL
层为硬件抽象层,用于连接应用层和驱动层,使得应用程序不需关心具体的硬件驱动实现,各种硬件实现(ISP
, CIF
以及 USB camera
)可以使用同一套 API
接口,简化应用开发。
目录 | 解释 |
---|---|
build_system |
简易的HAL 编译系统,兼容 Android |
cam_calibdb |
tunning xml 解析数据管理 |
dumpsys |
用于 dump RAW 数据,主要用于 tunning |
expat |
xml 解析器,移植于Android |
oslayer |
os 抽象,考虑到跨平台时使用 |
testApp |
HAL 的示例程序 |
calib_xml |
解析 tunning xml 文件接口 |
cam_ia_api |
3A ,ISP 子模块控制 |
ebase |
基础数据类型,考虑到跨平台时使用 |
HAL |
Camera 硬件抽象,给应用提供统一接口 |
stlport |
c++ stlPort 移植, HAL 主要要 C++ 编写,某些平台编译器可能需要此支持 |
tinyxml2 |
xml 解析器,移植于Android |
include |
HAL 中共用的头文件,其中许多头文件从其他文件夹拷贝而来 |
libs |
打包好的 3A 算法库 |
camera 数据结构
文件:CamHwitf.h
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;
};
展开后三项:
struct rk_isp_dev_info {
int isp_dev_node_nums;
struct rk_cam_video_node video_nodes[ISP_DEV_VIDEO_NODES_NUM_MAX];
};
struct rk_cif_dev_info {
int cif_index;
struct rk_cam_video_node video_node;
};
struct rk_usb_cam_dev_infos {
int usb_dev_node_nums;
struct rk_cam_video_node video_nodes[USB_CAM_DEV_VIDEO_NODES_NUM_MAX];
};
可以看出rk_cam_video_input_infos
尤为重要:
struct rk_cam_video_input_infos {
int index;
char name[30];
void* dev;
RK_CAM_ATTACHED_TO_e type;
};
enum RK_CAM_ATTACHED_TO_e {
RK_CAM_ATTACHED_TO_INVALID,
RK_CAM_ATTACHED_TO_ISP,
RK_CAM_ATTACHED_TO_CIF,
RK_CAM_ATTACHED_TO_USB
};
获取camera
能力
获取支持的camera
的类型,cif isp usb
支持的个数:
struct v4l2_capability {
__u8 driver[16]; /* i.e. "bttv" */
__u8 card[32]; /* i.e. "Hauppauge WinTV" */
__u8 bus_info[32]; /* "PCI:" + pci_name(pci_dev) */
__u32 version; /* should use KERNEL_VERSION() */
__u32 capabilities; /* Device capabilities */
__u32 reserved[4];
};
int CamHwItf::getCameraInfos(struct rk_cams_dev_info* cam_infos) {
char video_dev_path[15];
//V4L2的能力描述类型
struct v4l2_capability capability;
snprintf(video_dev_path, sizeof(video_dev_path), "/dev/video%d", i);
fd = open(video_dev_path, O_RDONLY);
ioctl(fd, VIDIOC_QUERYCAP, &capability);
if (strstr((char*)(capability.driver), "rkisp")) {
...
} else if (strstr((char*)(capability.driver), "cif")) {
...
} else if (strstr((char*)(capability.driver), "UVC")) {
...
close(fd);
}
}
在if-else
中做的事情大同小异我们以rkisp
为例:
struct rk_isp_dev_info* isp_dev = &cam_infos->isp_dev;
if ((strstr((char*)(capability.card), "self"))
|| (strstr((char*)(capability.card), "main"))
|| (strstr((char*)(capability.card), "ispdev"))
|| (strstr((char*)(capability.card), "y12"))
|| strstr((char*)(capability.card), "dma")) {
node = &(isp_dev->video_nodes[video_node_num]);
node->video_index = i;
strncpy(node->card, (char*)(capability.card), strlen((char*)(capability.card)));
for (j = 0; j < RK_CAM_ATTRACED_INUPUT_MAX; j++) {
video_node_input_num = node->input_nums;
input.index = j;
//枚举视频输入
if (ioctl(fd, VIDIOC_ENUMINPUT, &input) == 0) {
node->input[video_node_input_num].index = j;
node->input[video_node_input_num].dev = node;
node->input[video_node_input_num].type = RK_CAM_ATTACHED_TO_ISP;
if (strstr((char*)(input.name), "DMA"))
else {
// sensor name
strcpy(node->input[video_node_input_num].name,
strtok((char*)(input.name), " "));
//only involve once
if (strstr((char*)(capability.card), "self")) {
cam_infos->cam[cam_infos->num_camers] =
&(node->input[video_node_input_num]);
cam_infos->num_camers++;
}
}
}
}
}
获取完摄像头信息后:
static void testTunningClass() {
//判断摄像头个数
if (g_test_cam_infos.num_camers <= 0)
ALOGE("%s:no camera connected!!");
//搜索链接的ISP摄像头
for (i = 0; i < g_test_cam_infos.num_camers; i++) {
if (g_test_cam_infos.cam[i]->type == RK_CAM_ATTACHED_TO_ISP) {
//打印名字和ID
ALOGD("connected isp camera name %s,input id %d", g_test_cam_infos.cam[i]->name,
g_test_cam_infos.cam[i]->index);
break;
}
if (i == g_test_cam_infos.num_camers)
ALOGE("%s:no camera connected to isp !!");
//new ISP DEV
shared_ptr<CamHwItf> testIspDev = getCamHwItf(&(g_test_cam_infos.isp_dev));
if (testIspDev->initHw(g_test_cam_infos.cam[i]->index) == false)
ALOGE("isp dev init error !\n");
}
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());
ALOGD("%s:%d", __func__, __LINE__);
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
的功能比较杂,基本上跟图像效果有关的它都有份。
它内部包含多个图像算法处理模块,其中比较有代表性的是:
扣暗电流 | 去掉底电流噪声 |
线性化 | 解决数据非线性问题 |
shading | 解决镜头带来的亮度衰减与颜色变化 |
去坏点 | 去掉sensor中坏点数据 |
去噪 | 去除噪声 |
demosaic | raw数据转为RGB数据 |
3A | 自动白平衡,自动对焦,自动曝光 |
gamma | 亮度映射曲线,优化局部与整体对比度 |
旋转 | 角度变化 |
锐化 | 调整锐度 |
缩放 | 放大缩小 |
色彩空间转换 | 转换到不同色彩空间进处理 |
颜色增强 | 可选,调整颜色 |
肤色增强 | 可选,优化肤色表现 |