[RV1108][Linux]camera系列-dumpsys程序分析

平台 内核版本 版本
rv1108 Linux3.1 MiniGUI

源码目录:

Camera HAL 层为硬件抽象层,用于连接应用层和驱动层,使得应用程序不需关心具体的硬件驱动实现,各种硬件实现(ISPCIF 以及 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支持的个数:

v4l2_capability 详解手册

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 亮度映射曲线,优化局部与整体对比度
旋转 角度变化
锐化 调整锐度
缩放 放大缩小
色彩空间转换 转换到不同色彩空间进处理
颜色增强 可选,调整颜色
肤色增强 可选,优化肤色表现
发布了247 篇原创文章 · 获赞 93 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/qq_33487044/article/details/95741133
今日推荐