ITPub博客

首页 > 移动开发 > ANDROID > 高通msm8937/msm8939平台【备录】

高通msm8937/msm8939平台【备录】

原创 ANDROID 作者:小驰嘻嘻 时间:2021-09-11 12:06:24 0 删除 编辑

 

心怀浪漫宇宙,也珍惜人间日常。

这篇文章基于高通msm8937/msm8939平台,分下面几点内容展开:

一、主要硬件模块
二、Camera 预览数据流
三、Android Camera 软件架构 
四、HAL层dump Yuv 
五、Jepg Encoder dump YUV

01

主要硬件模块(Major Hardware Blocks Used)

1)Camera Control Interface (CCI) 

Used for dedicated I2C for camera subsystem

2)Video Frontend (VFE4) 

Image processing hardware for processing camera frame data    MSM8939 VFE can support up to 21 MP 

VFE4 maximum clock is 320 MHz in Normal mode and 600 MHz in Turbo mode

3)JPEG encoder/decoder 

Hardware block for JPEG encoding 

JPEG encoder maximum clock is 266 MHz in Normal mode 

LIBJPEG software library is used for decoding

4)Camera Postprocessor (CPP) 

Supports flip/rotate, denoise, smooth/sharpen, crop, and upscale features for full-size VFE output frames

--------- 我们经常说的翻转、旋转、降噪、裁剪、按比例缩放等操作就是放在cpp中进行出来。

02

Camera 预览数据量

MDP: (支持16bit总线以上LCD) lcd总线接口类型,支持高速刷屏。

03

Sortware Architechture - Android Camera

MCT :Media Controller

04

HAL层dump Yuv

上面的文档是针对8939平台的,如果在其它平台上,可能有有点差异,具体值以实际代码为准。

我这边是在8937平台上看的调试代码:

persist.vendor.camera.dumpimg

//------ hardware/qcom/camera/QCamera2/HAL3/QCamera3Channel.cpp
void QCamera3Channel::dumpYUV(mm_camera_buf_def_t *frame, cam_dimension_t dim,
        cam_frame_len_offset_t offset, uint8_t dump_type)
{
    char buf[FILENAME_MAX];
    memset(buf, 0, sizeof(buf));
    static int counter = 0;
    char prop[PROPERTY_VALUE_MAX];
    property_get("persist.vendor.camera.dumpimg", prop, "0");
    mYUVDump = (uint32_t)atoi(prop);
    if (mYUVDump & dump_type) {
        mFrmNum = ((mYUVDump & 0xffff0000) >> 16);
        if (mFrmNum == 0) {
            mFrmNum = 10;
        }
        if (mFrmNum > 256) {
            mFrmNum = 256;
        }
        mSkipMode = ((mYUVDump & 0x0000ff00) >> 8);
        if (mSkipMode == 0) {
            mSkipMode = 1;
        }
        if (mDumpSkipCnt == 0) {
            mDumpSkipCnt = 1;
        }
        if (mDumpSkipCnt % mSkipMode == 0) {
            if (mDumpFrmCnt < mFrmNum) {
                /* Note that the image dimension will be the unrotated stream dimension.
                * If you feel that the image would have been rotated during reprocess
                * then swap the dimensions while opening the file
                * */
                switch (dump_type) {
                    case QCAMERA_DUMP_FRM_PREVIEW:
                        snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"p_%d_%d_%dx%d.yuv",
                            counter, frame->frame_idx, dim.width, dim.height);
                    break;
                    case QCAMERA_DUMP_FRM_VIDEO:
                        snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"v_%d_%d_%dx%d.yuv",
                            counter, frame->frame_idx, dim.width, dim.height);
                    break;
                    case QCAMERA_DUMP_FRM_INPUT_JPEG:
                        snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"s_%d_%d_%dx%d.yuv",
                            counter, frame->frame_idx, dim.width, dim.height);
                    break;
                    case QCAMERA_DUMP_FRM_INPUT_REPROCESS:
                        snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"ir_%d_%d_%dx%d.yuv",
                            counter, frame->frame_idx, dim.width, dim.height);
                    break;
                    case QCAMERA_DUMP_FRM_CALLBACK:
                        snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"c_%d_%d_%dx%d.yuv",
                            counter, frame->frame_idx, dim.width, dim.height);
                    break;
                    case QCAMERA_DUMP_FRM_OUTPUT_JPEG:
                        snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"j_%d_%d_%dx%d.jpg",
                            counter, frame->frame_idx, dim.width, dim.height);
                    break;
                    default :
                        LOGE("dumping not enabled for stream type %d",dump_type);
                    break;
                }
                counter++;
                int file_fd = open(buf, O_RDWR | O_CREAT, 0777);
                ssize_t written_len = 0;
                if (file_fd >= 0) {
                    void *data = NULL;
                    fchmod(file_fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
                    if( dump_type == QCAMERA_DUMP_FRM_OUTPUT_JPEG ) {
                        written_len = write(file_fd, frame->buffer, frame->frame_len);
                    }
                    else {
                        for (uint32_t i = 0; i < offset.num_planes; i++) {
                            uint32_t index = offset.mp[i].offset;
                            if (i > 0) {
                                index += offset.mp[i-1].len;
                            }
                            for (int j = 0; j < offset.mp[i].height; j++) {
                                data = (void *)((uint8_t *)frame->buffer + index);
                                written_len += write(file_fd, data,
                                        (size_t)offset.mp[i].width);
                                index += (uint32_t)offset.mp[i].stride;
                            }
                        }
                    }
                    LOGH("written number of bytes %ld\n", written_len);
                    mDumpFrmCnt++;
                    frame->cache_flags |= CPU_HAS_READ;
                    close(file_fd);
                } else {
                    LOGE("failed to open file to dump image");
                }
            }
        } else {
            mDumpSkipCnt++;
        }
    }
}

1)setprop persist.vendor.camera.dumping 4

值设为 1<<2,也就是4,这个dump的是送给Jepg Encode之前的yuv数据。如果需要查看拍照前的yuv数据,可以设置这个进行dump。

2) setprop persist.vendor.camera.dumping 8

值设为 1 << 3 也就是4,可以dump callback的yuv。比如第三方app 的hdr算法,拍照的时候,请求了3张不同ev值的yuv,这时就可以把3张yuv dump出来。

下面是使用第三方app,hdr模式下拍照的dump的例子。

下图dump出来的3张yuv图,可以看到亮度是有变化的,也就是上层申请的不同ev值对应的yuv文件。

3)setprop persist.vendor.camera.dumping 32

值设为32,这个dump的是拍照返回的jpeg,这个是Jpeg Encoder处理后返回的,dump出来的格式自然也就是jpeg格式。

05

Jepg Encoder dump YUV

按照文档说明,在 mm_jpeg.c文件中添加定义宏  MM_JPEG_DUMP_INPUT即可打开dump。

这里需要注意文件路径读写权限的问题,相应的目录权限需要修改成777,如果文件夹路径不存在,需要手动创建下。

如果需要dump处理后的jpeg数据,则可以添加定义宏  MM_JPEG_DUMP_OUT_BS

推荐阅读:

ITS测试修改备录

哪些坑爹的Android CTS测试

Android Camera2 对焦梳理

Android Camera 测光梳理

一篇文章带你了解Android 最新Camera框架

这可能是介绍Android UvcCamera最详细的文章了


深圳上班,

生活简简单单,

14年开始从事Android Camera相关软件开发工作,

做过车载、手机、执法记录仪......

公众号记录生活和工作的点滴,

点击关注“小驰笔记”,期待和你相遇~

人生不设限,一起加油


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70006715/viewspace-2791609/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
Android 开发,专注Camera领域。 @公众号:小驰成长圈 个人博客:www.xiaochi820.top

注册时间:2021-09-11

  • 博文量
    15
  • 访问量
    10410