美文网首页高通camera框架camera tuning
【Camera专题】Qcom-你应该掌握的Camera调试技巧1

【Camera专题】Qcom-你应该掌握的Camera调试技巧1

作者: c枫_撸码的日子 | 来源:发表于2019-01-25 16:01 被阅读0次

    一、吐槽

    日常吐槽:。
    修行靠个人,自己慢慢积累吧!摸索出自己的方法。

    本文涉及知识点:


    • 1.Camera启动速度分析(Hal层的耗时)
    • 2.如何查看Camera的帧率(fps):拍照和视频
    • 3.获取数据流的帧(YUV图)

    二、知识点

    如何看log是我们新手工程师很头疼的问题,很多新手工程师遇到了问题,
    却不知道log怎么分析,看着几万行的log,就头大!
    我觉得,想要分析问题,学会看log很重要,无法就以下2个方面:

    • 1 掌握相关模块的知识
      例如:你要做Camera驱动和Hal层这一块,
      首先你得掌握它的流程吧,比如open、preview、takePicture等流程,
      其次你得掌握数据流是怎么传送的吧等等
      这些就要你自己看博客,看官方文档,跟源码,向老师傅请假去学习了。
    • 2 经验积累
      这些经验可能是高通工程师教你的,也可能是老前辈,比如他们会告诉你
      搜索xxx关键字去查看,比如怎么看查看拍照时的帧率(fps)等

    老前辈的经验分享
    赶紧做笔记!!!

    ps:以下操作需要在adb root情况下进行

    1.Camera启动速度(Hal层的耗时)

    Camera的启动速度,是我们经常做优化的地方,除了通过仪器去测量,还可以通过Log来查看!
    搜索关键字:[KPI Perf]

    01-24 17:55:57.657   371  4074 D QCamera2HWI: [KPI Perf] int qcamera::QCamera2HardwareInterface::openCamera(hw_device_t**): 
    E PROFILE_OPEN_CAMERA camera id 0  //这里打开摄像头
    01-24 17:55:58.139   371  2380 D QCamera2HWI: [KPI Perf] 
    static int qcamera::QCamera2HardwareInterface::start_preview(camera_device*):
     E PROFILE_START_PREVIEW
    01-24 17:55:58.528   371 16975 D QCamera2HWI: int qcamera::QCamera2HardwareInterface::startPreview(): X
    01-24 17:55:58.528   371  2380 D QCamera2HWI: [KPI Perf] static int qcamera::QCamera2HardwareInterface::
    start_preview(camera_device*): X
    01-24 17:55:58.530  2971  2971 D CameraManager: {CameraManager.initVideoCamera-199} 
    摄像头打开预览.
    01-24 17:55:58.654   371 17015 D QCamera2HWI: [KPI Perf] static void qcamera::QCamera2HardwareInterface::
    preview_stream_cb_routine(mm_camera_super_buf_t*, qcamera::QCameraStream*, void*) : 
    PROFILE_FIRST_PREVIEW_FRAME  //第一帧预览画面出现
    

    打开Camera的时间点:01-24 17:55:57.657
    第一帧预览画面出现的时间点:01-24 17:55:58.654
    耗时:0.997s(将近1s左右)
    注意这是从进入开始Hal层的计算的耗时
    我们来看看源码,

    int QCamera2HardwareInterface::openCamera(struct hw_device_t **hw_device)
    {
    ··· 
        CDBG_HIGH("[KPI Perf] %s: E PROFILE_OPEN_CAMERA camera id %d", __func__,mCameraId);
        rc = openCamera();
    ···
    }
    
    void QCamera2HardwareInterface::preview_stream_cb_routine(mm_camera_super_buf_t *super_frame,
                                                              QCameraStream * stream,
                                                              void *userdata)
    {
        ALOGD("[KPI Perf] %s : BEGIN", __func__);
    ···
        if(pme->m_bPreviewStarted) {
           CDBG_HIGH("[KPI Perf] %s : PROFILE_FIRST_PREVIEW_FRAME", __func__);
           pme->m_bPreviewStarted = false ;
        }
    ···
    }
    

    事实上,高通也只是在调用地方打印了一下当前的时间点,因此如果你想分析某个功能的耗时,
    就按照高通的思路,调用前后打印一下当前函数就可以了,最后再通过时间戳计算耗时!
    当然了,在哪里加log就要自己对流程熟悉了!!!

    2.如何查看Camera的帧率(fps):拍照和视频

    • 1 拍照帧率
      源码:
      hardware/qcom/camera/QCamera2/HAL/QCamera2HWICallbacks.cpp
    void QCamera2HardwareInterface::debugShowPreviewFPS()
    {
        static int n_pFrameCount = 0; 
        static int n_pLastFrameCount = 0; 
        static nsecs_t n_pLastFpsTime = 0; 
        static double n_pFps = 0; 
        n_pFrameCount++;
        nsecs_t now = systemTime();
        nsecs_t diff = now - n_pLastFpsTime;
        if (diff > ms2ns(250)) {
            n_pFps = (((double)(n_pFrameCount - n_pLastFrameCount)) *
                    (double)(s2ns(1))) / (double)diff;
            CDBG_HIGH("[KPI Perf] %s: PROFILE_PREVIEW_FRAMES_PER_SECOND : %.4f", __func__, n_pFps);
            n_pLastFpsTime = now; 
            n_pLastFrameCount = n_pFrameCount;
        }    
    }
    

    hal层是如何计算实际输出的帧率:

      n_pFps = (((double)(n_pFrameCount - n_pLastFrameCount)) *(double)(s2ns(1))) / (double)diff;
    

    搜索关键字:PROFILE_PREVIEW_FRAMES_PER_SECOND
    默认fps是不输出的,需要用到adb命令打开

    adb root
    adb shell setprop persist.debug.sf.showfps 1 
    adb logcat | findstr "PROFILE_PREVIEW_FRAMES_PER_SECOND"
    
    拍照帧率
    • 2.视频帧率
      源码:
      hardware/qcom/camera/QCamera2/HAL/QCamera2HWICallbacks.cpp
    void QCamera2HardwareInterface::debugShowVideoFPS()
    {
        static int n_vFrameCount = 0; 
        static int n_vLastFrameCount = 0; 
        static nsecs_t n_vLastFpsTime = 0; 
        static double n_vFps = 0; 
        n_vFrameCount++;
        nsecs_t now = systemTime();
        nsecs_t diff = now - n_vLastFpsTime;
        if (diff > ms2ns(250)) {
            n_vFps = (((double)(n_vFrameCount - n_vLastFrameCount)) *
                    (double)(s2ns(1))) / (double)diff;
            ALOGE("Video Frames Per Second: %.4f", n_vFps);
            n_vLastFpsTime = now; 
            n_vLastFrameCount = n_vFrameCount;
        }    
    }
    

    搜索关键字:Video Frames Per Second
    执行命令

    adb root
    adb shell setprop persist.debug.sf.showfps 1 
    adb shell
    logcat | grep  "Video Frames Per Second"
    
    视频帧率

    3.获取数据流的帧(YUV图)

    源码:
    hardware/qcom/camera/QCamera2/HAL/QCamera2HWICallbacks.cpp

    void QCamera2HardwareInterface::dumpFrameToFile(QCameraStream *stream,
            mm_camera_buf_def_t *frame, uint32_t dump_type)
    {
        char value[PROPERTY_VALUE_MAX];
        property_get("persist.camera.dumpimg", value, "0");
        uint32_t enabled = (uint32_t) atoi(value);
        uint32_t frm_num = 0;
        uint32_t skip_mode = 0;
    
        if (stream)
            mDumpFrmCnt = stream->mDumpFrame;
        if(enabled & QCAMERA_DUMP_FRM_MASK_ALL) {
            if((enabled & dump_type) && stream && frame) {
                frm_num = ((enabled & 0xffff0000) >> 16);
                if(frm_num == 0) {
                    frm_num = 10; //default 10 frames
                }
                if(frm_num > 256) {
                    frm_num = 256; //256 buffers cycle around
                }
                skip_mode = ((enabled & 0x0000ff00) >> 8);
                if(skip_mode == 0) {
                    skip_mode = 1; //no-skip
                }
                if(stream->mDumpSkipCnt == 0)
                    stream->mDumpSkipCnt = 1;
    
                if( stream->mDumpSkipCnt % skip_mode == 0) {
                    if((frm_num == 256) && (mDumpFrmCnt >= frm_num)) {
                        // reset frame count if cycling
                        mDumpFrmCnt = 0;
                    }
                if (timeinfo != NULL)
                    strftime (timeBuf, sizeof(timeBuf), "/data/misc/camera/%Y%m%d%H%M%S", timeinfo);
    ···   
    }
    

    从源码中我们可以得出很多信息:
    如果你想查看预览、视频、快照、缩略图、Raw 或 JPEG 帧,那么:



    以下命令可在启动摄像头应用之前启用帧转储设置。

    adb root 
    adb shell chmod 777 /data/misc/camera 
    //存10帧  655615     =A00FF
    adb shell setprop persist.camera.dumpimg 655615    
    //存256帧 100 00 FF
    adb shell setprop persist.camera.dumpimg 16777471
    //最大dump 268帧图像1 000 00 FF
    adb shell setprop persist.camera.dumpimg 33554687  
    

    在本例中,655615(十六进制表示为 0xA00FF)是指根据摄像头应用的工作模式,
    连续十 个帧的所用预览、视频、快照、缩略图、Raw 或 JPEG 帧
    都会被转储到 /data/misc/camera 文件夹。 /vendor/qcom/hardware/qcom/camera/QCamera2/HAL/QCamera2HWICallbacks.cpp 文件的 QCamera2HardwareInterface::dumpFrameToFile() 函数用于转储 /data 文件夹下的文件。
    有关 为每种帧类型使用的文件命名约定,可参见源代码中的 dumpFrameToFile() 函数.

    我们来看实际效果:
    以下是预览的时候的yuv图,使用YUVViewer工具查看
    YUVView工具下载链接
    提取码: h6j6

    预览流YUV图
    为啥是从第三张开始:
    因为默认跳过了前2帧图像
    vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/
    modules/sensors/sensor_libs/ov5675_d5v15b/ov5675_d5v15b_lib.c
    static sensor_lib_t sensor_lib_ptr = {
    ···
      /* number of frames to skip after start stream */
      .sensor_num_frame_skip = 2, 
    ···
    }
    
    第3张和第8张 第9张和第13张

    以上就是本篇Camera的知识积累了!
    一会就要开年会了,
    下期再见!!!

    Stay hungry,Stay foolish!

    相关文章

      网友评论

        本文标题:【Camera专题】Qcom-你应该掌握的Camera调试技巧1

        本文链接:https://www.haomeiwen.com/subject/mwwsjqtx.html