Camera - dump 预览帧数据处理(三)

应用层处理CPU、GPU框架下TextureView、GLSurfaceView所对应的Surface获取到的ImageReader数据以及dump相关的方法前面已经讲了,本次主要以展讯平台的HAL层dump预览的相关节点看一下如何抓取我们想要的任何节点下的帧数据

一、平台HAL层预览Dump数据分析

vendor/sprd/modules/libcamera/oem2v6/src/cmr_preview.c

cmr_int prev_construct_frame(struct prev_handle *handle, cmr_u32 camera_id,
                             struct frm_info *info,
                             struct camera_frame_type *frame_type) {
    ATRACE_BEGIN(__FUNCTION__);

    ...

    char value[PROPERTY_VALUE_MAX];
        //dump命令节点
        property_get("debug.camera.preview.dump.count", value, "null");

        cmr_uint dump_num = atoi(value);
        if (strcmp(value, "null")) {
            if (g_preview_frame_dump_cnt < dump_num) {
                char tag_name[30]={0};
                char cameraId[2] ={0};
                strcpy(tag_name, "prev_construct_frame_id");
                sprintf(cameraId, "%d", camera_id);
                strcat(tag_name, cameraId);

                //dump数据接口
                dump_image(tag_name, CAM_IMG_FMT_YUV420_NV21,
                           frame_type->width, frame_type->height,
                           prev_cxt->prev_frm_cnt,
                           &prev_cxt->prev_frm[frm_id].addr_vir,
                           frame_type->width * frame_type->height * 3 / 2);
                g_preview_frame_dump_cnt++;
            }
        }

    ...

}
// tag used for description, for example, preview, video, snapshot and so on
 cmr_int dump_image(char *tag, cmr_u32 img_fmt, cmr_u32 width, cmr_u32 height,
                    cmr_u32 index, struct img_addr *vir_addr,
                    cmr_u32 image_size) {
     cmr_int ret = CMR_CAMERA_SUCCESS;
     char file_name[0x80];
     char tmp_str[80];
     char datetime[15];
     FILE *fp = NULL;

     CMR_LOGD("%s: format %d width %d height %d", tag, img_fmt, width, height);

    time_t timep;
    struct tm *p;
    time(&timep);
    p = localtime(&timep);
    sprintf(datetime, "%04d%02d%02d%02d%02d%02d", (1900 + p->tm_year),
            (1 + p->tm_mon), p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec);

    cmr_bzero(file_name, 0x80);
    strcpy(file_name, CAMERA_DUMP_PATH);

    sprintf(tmp_str, "%s_", tag);
    strcat(file_name, tmp_str);
    sprintf(tmp_str, "%d", width);
    strcat(file_name, tmp_str);
    strcat(file_name, "X");
    sprintf(tmp_str, "%d", height);
    strcat(file_name, tmp_str);
    strcat(file_name, "_");
    sprintf(tmp_str, "_frame_num_%d", index);
    strcat(file_name, tmp_str);
    sprintf(tmp_str, "_%s", datetime);
    strcat(file_name, tmp_str);

    if (CAM_IMG_FMT_YUV420_NV21 == img_fmt) {
        strcat(file_name, ".yuv");
        CMR_LOGD("file name %s", file_name);
        fp = fopen(file_name, "wb");
        if (NULL == fp) {
            CMR_LOGE("can not open file: %s", file_name);
            return 0;
        }
        CMR_LOGV("yuv addr_vir:0x%x,0x%x,0x%x", vir_addr->addr_y,
                 vir_addr->addr_u, vir_addr->addr_v);
        // dump y
        fwrite((void *)vir_addr->addr_y, 1, width * height * 1, fp);
        // dump uv, uv can independent of y
        fwrite((void *)vir_addr->addr_u, 1, width * height * 1 / 2, fp);
        fclose(fp);
    } else if (CAM_IMG_FMT_BAYER_MIPI_RAW == img_fmt) {
        strcat(file_name, ".mipi_raw");
        CMR_LOGD("file name %s", file_name);
        fp = fopen(file_name, "wb");
        if (NULL == fp) {
            CMR_LOGE("can not open file: %s", file_name);
            return 0;
        }
        fwrite((void *)vir_addr->addr_y, 1, (uint32_t)width * height * 5 / 4,
               fp);
        fclose(fp);
    } else if (CAM_IMG_FMT_BAYER_SPRD_DCAM_RAW == img_fmt) {
        strcat(file_name, "_mipi2.raw");
        CMR_LOGD("file name %s", file_name);
        fp = fopen(file_name, "wb");
        if (NULL == fp) {
            CMR_LOGE("can not open file: %s", file_name);
            return 0;
        }
        fwrite((void *)vir_addr->addr_y, 1, (uint32_t)width * height * 5 / 4,
               fp);
        fclose(fp);
    } else if (CAM_IMG_FMT_JPEG == img_fmt) {
        strcat(file_name, ".jpg");
        CMR_LOGD("file name %s", file_name);
        fp = fopen(file_name, "wb");
        if (NULL == fp) {
            CMR_LOGE("can not open file: %s", file_name);
            return 0;
        }
        fwrite((void *)vir_addr->addr_y, 1, image_size, fp);
        fclose(fp);
    }

    return 0;

具体调用以及dump信息如下:

 

       

二、平台其他节点Dump数据指令

        由此及彼,根据预览的相关介绍,可以直接衍生到平台的各个算法以及流程节点的相关命令,入拍照、缩略图等。

/vendor/sprd/modules/libcamera/oem2v6/cmr_snapshot.c

以微距拍照的相关节点进行check

#ifdef SUPER_MACRO
cmr_int snp_save_yuv_for_macro(cmr_handle snp_handle, struct snp_jpeg_param *jpeg_in)
{
    cmr_u32 tmp = 0;
    cmr_int ret = 0;
    cmr_uint tmp_dst_addr = 0;
    cmr_uint tmp_src_addr = 0;
    cmr_uint rotation = 0;
    char name[20] = {0};
    char value[PROPERTY_VALUE_MAX] = {0};

    ...

     memcpy((char *)tmp_dst_addr, (char *)&tmp_src_addr, sizeof(int));
    property_get("persist.vendor.cam.macro.dump", value, "0");
    if (atoi(value) == 1) {
        sprintf(name, "sp_yuv_rot_%d", rotation);
        dump_image(name, CAM_IMG_FMT_YUV420_NV21,
            jpeg_in->super.size.width, jpeg_in->super.size.height,
            FORM_DUMPINDEX(SNP_ENCODE_SRC_DATA, 1, 0),
            &jpeg_in->super.addr_vir,
            jpeg_in->super.size.width * jpeg_in->super.size.height *
            3 / 2);
    }

    return ret;
}

        诸如此等,各位有需要的可以自己查看相关的平台代码以及相关的节点,进行dump数据分析,更利于check Camera各个流程的状态是否正常。

三、HAL层自己添加节点dump指令

         可以参考平台的相关流程,在自己的算法节点前后进行dump以check算法的input、output节点是否异常。

static cmr_int xxx_thread_proc(struct cmr_msg *message, void *data) {

    cmr_int ret = CMR_CAMERA_SUCCESS;
    struct xxx *xxxhandle

    ...
    
    //dump before algo
    char value[VALUE_MAX];
    if (!strcmp(value, "true")) {
        addr = &in->src_frame.addr_vir;
        dump_image("wsj_befor", CAM_IMG_FMT_YUV420_NV21, image.width, image.height, 0, addr, (image.width) * (image.height) * 3 / 2);
    }
        
    

    //run related algo
    ...


    //dump after algo
    property_get("debug.dump.after.singlertbokeh", value, "null");
    if (!strcmp(value, "true")) {
        addr = &in->src_frame.addr_vir;
        dump_image("wsj_after", CAM_IMG_FMT_YUV420_NV21, out_image.width, out_image.height, 1, addr, (out_image.width) * (out_image.height) * 3 / 2);
    }

    
    free(xxx);
}

总结

        关键的节点check关键信息不管对于什么process都是百利无一害的,dump各个流程节点对于快速定位、分析问题至关重要。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值