Camera MetaData介绍_独家原创

目录

1. Camera MetaData 作用

2. Camera MetaData 定义

2.1 内存分布

2.2 Entry详解

Key

Value

2.3 常用 API

2.4 vendor tag 操作集

3. Camera Metadata 参数下发流程分析

4. More


1. Camera MetaData 作用

新的 Camera API2 / HAL3 架构将 SetParameter()/GetParameter() 改为 Camera MetaData 的方式设置或获取参数。

Camera MetaData 将参数以有序结构体的形式保存在一块连续内存中。

Camera API2/HAL3的核心为per-frame control,为了达成这个目标产生了metadata的机制,metadata一共分成了三类:static,control,dynamic。

对应的camera过程是:

  • Staticcharacteristic)描述device的规格与具备的能力,可以称为静态能力。
  • Controlrequest)当APK获取到static metadata后,可以做出想要的控制,即下发请求。
  • Dynamicresult)当HAL收到control metadata后,设定给ISP,然后产生对应的结果。

Metadata 贯穿了 Camera 的Application、Framework 和 vendor HAL,实现了去耦合的参数传递方式,是所有的APP层下发、hal层更新参数(如ISO、EV等)的接口实现。

2. Camera MetaData 定义

编译产物:libcamera_metadata.so

系统位置:/system/lib64/,/system/lib/

源代码位置:/system/media/camera/

看下编译配置文件 Android.bp:

package {
    // http://go/android-license-faq
    // A large-scale-change added 'default_applicable_licenses' to import
    // the below license kinds from "system_media_license":
    //   SPDX-license-identifier-Apache-2.0
    default_applicable_licenses: ["system_media_license"],
}

subdirs = ["tests"]

cc_library_shared {
    name: "libcamera_metadata",
    vendor_available: true,
    product_available: true,
    // remove when no longer needed.
    native_bridge_supported: true,
    host_supported: true,
    vndk: {
        enabled: true,
    },
    double_loadable: true,
    srcs: ["src/camera_metadata.c"],

    include_dirs: ["system/media/private/camera/include"],
    local_include_dirs: ["include"],
    export_include_dirs: ["include"],

    header_libs: [
        "libcutils_headers",
    ],

    export_header_lib_headers: [
        "libcutils_headers",
    ],

    shared_libs: [
        "liblog",
    ],

    cflags: [
        "-Wall",
        "-Wextra",
        "-Werror",
        "-fvisibility=hidden",
        "-std=c11",
    ],

    product_variables: {
        eng: {
            // Enable assert()
            cflags: [
                "-UNDEBUG",
                "-DLOG_NDEBUG=1",
            ],
        },
    },
}

filegroup {
    name: "libcamera_metadata_tags_file",
    srcs: ["include/system/camera_metadata_tags.h"],
}

2.1 内存分布

一块儿连续的内存空间,数据分布情况代码注释说明:

# system/media/camera/src/camera_metadata.c

/**
 * A packet of metadata. This is a list of entries, each of which may point to
 * its values stored at an offset in data.
 *
 * It is assumed by the utility functions that the memory layout of the packet
 * is as follows:
 *
 *   |-----------------------------------------------|
 *   | camera_metadata_t                             |
 *   |                                               |
 *   |-----------------------------------------------|
 *   | reserved for future expansion                 |
 *   |-----------------------------------------------|
 *   | camera_metadata_buffer_entry_t #0             |
 *   |-----------------------------------------------|
 *   | ....                                          |
 *   |-----------------------------------------------|
 *   | camera_metadata_buffer_entry_t #entry_count-1 |
 *   |-----------------------------------------------|
 *   | free space for                                |
 *   | (entry_capacity-entry_count) entries          |
 *   |-----------------------------------------------|
 *   | start of camera_metadata.data                 |
 *   |                                               |
 *   |-----------------------------------------------|
 *   | free space for                                |
 *   | (data_capacity-data_count) bytes              |
 *   |-----------------------------------------------|
 *
 * With the total length of the whole packet being camera_metadata.size bytes.
 *
 * In short, the entries and data are contiguous in memory after the metadata
 * header.
 */
#define METADATA_ALIGNMENT ((size_t) 4)
struct camera_metadata {
    metadata_size_t          size;
    uint32_t                 version;
    uint32_t                 flags;
    metadata_size_t          entry_count;
    metadata_size_t          entry_capacity;
    metadata_uptrdiff_t      entries_start; // Offset from camera_metadata
    metadata_size_t          data_count;
    metadata_size_t          data_capacity;
    metadata_uptrdiff_t      data_start; // Offset from camera_metadata
    uint32_t                 padding;    // padding to 8 bytes boundary
    metadata_vendor_id_t     vendor_id;
};

typedef struct camera_metadata camera_metadata_t;

结构体各成员含义: 

  • size:该包metadata所占的总的字节数
  • version:版本
  • flags: 标记当前是否有对entry进行排序
  • entry_count: entry数量,初始值为0
  • entry_capacity:该包metadata能存储的最大的entry数量
  • entries_start:entry相对于camera_metadata_t起始地址的偏移量,即从camera_metadata_t的起始地址再偏移entries_start就到了开始存储entry的位置了
  • data_count:data数量,初始值为0
  • data_capacity:该包metadata能存储的最大的data数量
  • data_start:data相对于camera_metadata_t起始地址的偏移量,即从camera_metadata_t的起始地址再偏移data_start就到了开始存储data的位置了
  • vendor_id:跟当前这个手机上的CameraDeviceProvider相关,每个CameraDeviceProvider都有自己对应的vendor_id
     

内存分布如下: 

  1. 存 camera_metadata_t 结构体具体对象
  2. 保留区:未来扩展使用
  3. 序号为 0~entry_count-1 的 camera_metadata_buffer_entry_t 结构体对象,简称 metadata_entry 结构体对象,每个对象有自己的 tag。
  4. 保留区:保留 entry_capacity-entry_count 个 camera_metadata_buffer_entry_t 的空间
  5. metadata_entry 结构体对象对应 camera_metadata_data_t 数据
  6. 保留区:保留的 metadata_entry 结构体对象对应 camera_metadata_data_t 数据的空间

可以简化记作三个分区:Header区、Entry区、Data区。 

上面涉及的结构体 camera_metadata_buffer_entry_t 和 camera_metadata_data_t 都是什么呢?直接看注释:

metadata_entry:

/**
 * A single metadata entry, storing an array of values of a given type. If the
 * array is no larger than 4 bytes in size, it is stored in the data.value[]
 * array; otherwise, it can found in the parent's data array at index
 * data.offset.
 */
#define ENTRY_ALIGNMENT ((size_t) 4)
typedef struct camera_metadata_buffer_entry {
    uint32_t tag;                  // tag的key值 
    uint32_t count;                // tag的value对应的data的数量
    union {                        
        uint32_t offset;           // offset标记当前的key值对应的value在data_start中的位
        uint8_t  value[4];         // 当value占用的字节数<=4时,直接存储到这里(省空间)
    } data;
    uint8_t  type;                 // TYPE_BYTE、TYPE_INT32、TYPE_FLOAT、TYPE_INT64
    uint8_t  reserved[3];
} camera_metadata_buffer_entry_t;

typedef uint32_t metadata_uptrdiff_t;
typedef uint32_t metadata_size_t;

metadata_data: 

/**
 * A datum of metadata. This corresponds to camera_metadata_entry_t::data
 * with the difference that each element is not a pointer. We need to have a
 * non-pointer type description in order to figure out the largest alignment
 * requirement for data (DATA_ALIGNMENT).
 */
#define DATA_ALIGNMENT ((size_t) 8)
typedef union camera_metadata_data {
    uint8_t u8;
    int32_t i32;
    float   f;
    int64_t i64;
    double  d;
    camera_metadata_rational_t r;
} camera_metadata_data_t;

2.2 Entry详解

Key

camera_metadata_buffer_entry里的tag就是key。

那问题来了,tag 究竟有哪些?AOSP里的tags都记录在system/media/camera/include/system/camera_metadata_tags.h

tag很多,会按功能分组,每组叫做一个section,先看section。在 system/media/camera/include/system/camera_metadata_tags.h 里定义:

/**
 * Top level hierarchy definitions for camera metadata. *_INFO sections are for
 * the static metadata that can be retrived without opening the camera device.
 * New sections must be added right before ANDROID_SECTION_COUNT to maintain
 * existing enumerations.
 */
typedef enum camera_metadata_section {
    ANDROID_COLOR_CORRECTION,
    ANDROID_CONTROL,
    ANDROID_DEMOSAIC,
    ANDROID_EDGE,
    ANDROID_FLASH,
    ANDROID_FLASH_INFO,
    ANDROID_HOT_PIXEL,
    ANDROID_JPEG,
    ANDROID_LENS,
    ANDROID_LENS_INFO,
    ANDROID_NOISE_REDUCTION,
    ANDROID_QUIRKS,
    ANDROID_REQUEST,
    ANDROID_SCALER,
    ANDROID_SENSOR,
    ANDROID_SENSOR_INFO,
    ANDROID_SHADING,
    ANDROID_STATISTICS,
    ANDROID_STATISTICS_INFO,
    ANDROID_TONEMAP,
    ANDROID_LED,
    ANDROID_INFO,
    ANDROID_BLACK_LEVEL,
    ANDROID_SYNC,
    ANDROID_REPROCESS,
    ANDROID_DEPTH,
    ANDROID_LOGICAL_MULTI_CAMERA,
    ANDROID_DISTORTION_CORRECTION,
    ANDROID_HEIC,
    ANDROID_HEIC_INFO,
    ANDROID_SECTION_COUNT,

    VENDOR_SECTION = 0x8000
} camera_metadata_section_t;

注意最后一个VENDOR_SECTION,它的枚举值为0x8000,因为除了Android自己定义的TAG外,还有平台厂商和OEM厂商自己定义的有其他用途的TAG,比如QualComm、MTK、Samsung和各个手机设备制造商等等,平台厂商和OEM厂商自定义的tag在0x8000后面enum值就不会冲突了。

再看详细的所有 tag,我想你应该懂了,没错,每个 tag 都是 section 为前缀的,并且都是以  [section]_START 开始以 [section]_END 结束:

/**
 * Main enum for defining camera metadata tags.  New entries must always go
 * before the section _END tag to preserve existing enumeration values.  In
 * addition, the name and type of the tag needs to be added to
 * system/media/camera/src/camera_metadata_tag_info.c
 */
typedef enum camera_metadata_tag {
    ANDROID_COLOR_CORRECTION_MODE =                   // enum         | public       | HIDL v3.2
            ANDROID_COLOR_CORRECTION_START,
    ANDROID_COLOR_CORRECTION_TRANSFORM,               // rational[]   | public       | HIDL v3.2
    ANDROID_COLOR_CORRECTION_GAINS,                   // float[]      | public       | HIDL v3.2
    ANDROID_COLOR_CORRECTION_ABERRATION_MODE,         // enum         | public       | HIDL v3.2
    ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
                                                      // byte[]       | public       | HIDL v3.2
    ANDROID_COLOR_CORRECTION_END,

    ANDROID_CONTROL_AE_ANTIBANDING_MODE =             // enum         | public       | HIDL v3.2
            ANDROID_CONTROL_START,
    ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,         // int32        | public       | HIDL v3.2
    ANDROID_CONTROL_AE_LOCK,                          // enum         | public       | HIDL v3.2
    ANDROID_CONTROL_AE_MODE,                          // enum         | public       | HIDL v3.2
    ANDROID_CONTROL_AE_REGIONS,                       // int32[]      | public       | HIDL v3.2
    ANDROID_CONTROL_AE_TARGET_FPS_RANGE,              // int32[]      | public       | HIDL v3.2
    ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,            // enum         | public       | HIDL v3.2
    ANDROID_CONTROL_AF_MODE,                          // enum         | public       | HIDL v3.2
    ANDROID_CONTROL_AF_REGIONS,                       // int32[]      | public       | HIDL v3.2
    ANDROID_CONTROL_AF_TRIGGER,                       // enum         | public       | HIDL v3.2
    ANDROID_CONTROL_AWB_LOCK,                         // enum         | public       | HIDL v3.2
    ANDROID_CONTROL_AWB_MODE,                         // enum         | public       | HIDL v3.2
    ANDROID_CONTROL_AWB_REGIONS,                      // int32[]      | public       | HIDL v3.2
    ANDROID_CONTROL_CAPTURE_INTENT,                   // enum         | public       | HIDL v3.2
    ANDROID_CONTROL_EFFECT_MODE,                      // enum         | public       | HIDL v3.2
    ANDROID_CONTROL_MODE,                             // enum         | public       | HIDL v3.2
    ANDROID_CONTROL_SCENE_MODE,                       // enum         | public       | HIDL v3.2
    ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,         // enum         | public       | HIDL v3.2
    ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,   // byte[]       | public       | HIDL v3.2
    ANDROID_CONTROL_AE_AVAILABLE_MODES,               // byte[]       | public       | HIDL v3.2
    ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,   // int32[]      | public       | HIDL v3.2
    ANDROID_CONTROL_AE_COMPENSATION_RANGE,            // int32[]      | public       | HIDL v3.2
    ANDROID_CONTROL_AE_COMPENSATION_STEP,             // rational     | public       | HIDL v3.2
    ANDROID_CONTROL_AF_AVAILABLE_MODES,               // byte[]       | public       | HIDL v3.2
    ANDROID_CONTROL_AVAILABLE_EFFECTS,                // byte[]       | public       | HIDL v3.2
    ANDROID_CONTROL_AVAILABLE_SCENE_MODES,            // byte[]       | public       | HIDL v3.2
    ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
                                                      // byte[]       | public       | HIDL v3.2
    ANDROID_CONTROL_AWB_AVAILABLE_MODES,              // byte[]       | public       | HIDL v3.2
    ANDROID_CONTROL_MAX_REGIONS,                      // int32[]      | ndk_public   | HIDL v3.2
    ANDROID_CONTROL_SCENE_MODE_OVERRIDES,             // byte[]       | system       | HIDL v3.2
    ANDROID_CONTROL_AE_PRECAPTURE_ID,                 // int32        | system       | HIDL v3.2
    ANDROID_CONTROL_AE_STATE,                         // enum         | public       | HIDL v3.2
    ANDROID_CONTROL_AF_STATE,                         // enum         | public       | HIDL v3.2
    ANDROID_CONTROL_AF_TRIGGER_ID,                    // int32        | system       | HIDL v3.2
    ANDROID_CONTROL_AWB_STATE,                        // enum         | public       | HIDL v3.2
    ANDROID_CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS,
                                                      // int32[]      | hidden       | HIDL v3.2
    ANDROID_CONTROL_AE_LOCK_AVAILABLE,                // enum         | public       | HIDL v3.2
    ANDROID_CONTROL_AWB_LOCK_AVAILABLE,               // enum         | public       | HIDL v3.2
    ANDROID_CONTROL_AVAILABLE_MODES,                  // byte[]       | public       | HIDL v3.2
    ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST_RANGE, // int32[]      | public       | HIDL v3.2
    ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST,       // int32        | public       | HIDL v3.2
    ANDROID_CONTROL_ENABLE_ZSL,                       // enum         | public       | HIDL v3.2
    ANDROID_CONTROL_AF_SCENE_CHANGE,                  // enum         | public       | HIDL v3.3
    ANDROID_CONTROL_AVAILABLE_EXTENDED_SCENE_MODE_MAX_SIZES,
                                                      // int32[]      | ndk_public   | HIDL v3.5
    ANDROID_CONTROL_AVAILABLE_EXTENDED_SCENE_MODE_ZOOM_RATIO_RANGES,
                                                      // float[]      | ndk_public   | HIDL v3.5
    ANDROID_CONTROL_EXTENDED_SCENE_MODE,              // enum         | public       | HIDL v3.5
    ANDROID_CONTROL_ZOOM_RATIO_RANGE,                 // float[]      | public       | HIDL v3.5
    ANDROID_CONTROL_ZOOM_RATIO,                       // float        | public       | HIDL v3.5
    ANDROID_CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS_MAXIMUM_RESOLUTION,
                                                      // int32[]      | hidden       | HIDL v3.6
    ANDROID_CONTROL_AF_REGIONS_SET,                   // enum         | fwk_only
    ANDROID_CONTROL_AE_REGIONS_SET,                   // enum         | fwk_only
    ANDROID_CONTROL_AWB_REGIONS_SET,                  // enum         | fwk_only
    ANDROID_CONTROL_END,

    ANDROID_DEMOSAIC_MODE =                           // enum         | system       | HIDL v3.2
            ANDROID_DEMOSAIC_START,
    ANDROID_DEMOSAIC_END,

    ANDROID_EDGE_MODE =                               // enum         | public       | HIDL v3.2
            ANDROID_EDGE_START,
    ANDROID_EDGE_STRENGTH,                            // byte         | system       | HIDL v3.2
    ANDROID_EDGE_AVAILABLE_EDGE_MODES,                // byte[]       | public       | HIDL v3.2
    ANDROID_EDGE_END,

    ANDROID_FLASH_FIRING_POWER =                      // byte         | system       | HIDL v3.2
            ANDROID_FLASH_START,
    ANDROID_FLASH_FIRING_TIME,                        // int64        | system       | HIDL v3.2
    ANDROID_FLASH_MODE,                               // enum         | public       | HIDL v3.2
    ANDROID_FLASH_COLOR_TEMPERATURE,                  // byte         | system       | HIDL v3.2
    ANDROID_FLASH_MAX_ENERGY,                         // byte         | system       | HIDL v3.2
    ANDROID_FLASH_STATE,                              // enum         | public       | HIDL v3.2
    ANDROID_FLASH_END,

    ANDROID_FLASH_INFO_AVAILABLE =                    // enum         | public       | HIDL v3.2
            ANDROID_FLASH_INFO_START,
    ANDROID_FLASH_INFO_CHARGE_DURATION,               // int64        | system       | HIDL v3.2
    ANDROID_FLASH_INFO_END,


// 省略一堆代码

} camera_metadata_tag_t;

Value

Value也就是每个tag的key对应的data,由 union 指针指向真实数据。

/**
 * A reference to a metadata entry in a buffer.
 *
 * The data union pointers point to the real data in the buffer, and can be
 * modified in-place if the count does not need to change. The count is the
 * number of entries in data of the entry's type, not a count of bytes.
 */
typedef struct camera_metadata_entry {
    size_t   index;
    uint32_t tag;
    uint8_t  type;
    size_t   count;
    union {
        uint8_t *u8;
        int32_t *i32;
        float   *f;
        int64_t *i64;
        double  *d;
        camera_metadata_rational_t *r;
    } data;
} camera_metadata_entry_t;

看system/media/camera/src/camera_metadata.c中的这个结构体:

typedef struct tag_info {
    const char *tag_name;
    uint8_t     tag_type;
} tag_info_t;

定义了tag的名字以及tag的类型,注意这里的类型不是说Value的类型,看下面android_statistics这个section的例子就懂了,tag_info_t的数组会分别定义这个section每个tag的实际Value类型:

static tag_info_t android_statistics[ANDROID_STATISTICS_END -
        ANDROID_STATISTICS_START] = {
    [ ANDROID_STATISTICS_FACE_DETECT_MODE - ANDROID_STATISTICS_START ] =
    { "faceDetectMode",                TYPE_BYTE   },
    [ ANDROID_STATISTICS_HISTOGRAM_MODE - ANDROID_STATISTICS_START ] =
    { "histogramMode",                 TYPE_BYTE   },
    [ ANDROID_STATISTICS_SHARPNESS_MAP_MODE - ANDROID_STATISTICS_START ] =
    { "sharpnessMapMode",              TYPE_BYTE   },
    [ ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE - ANDROID_STATISTICS_START ] =
    { "hotPixelMapMode",               TYPE_BYTE   },
    [ ANDROID_STATISTICS_FACE_IDS - ANDROID_STATISTICS_START ] =
    { "faceIds",                       TYPE_INT32  },
    [ ANDROID_STATISTICS_FACE_LANDMARKS - ANDROID_STATISTICS_START ] =
    { "faceLandmarks",                 TYPE_INT32  },
    [ ANDROID_STATISTICS_FACE_RECTANGLES - ANDROID_STATISTICS_START ] =
    { "faceRectangles",                TYPE_INT32  },
    [ ANDROID_STATISTICS_FACE_SCORES - ANDROID_STATISTICS_START ] =
    { "faceScores",                    TYPE_BYTE   },
    [ ANDROID_STATISTICS_HISTOGRAM - ANDROID_STATISTICS_START ] =
    { "histogram",                     TYPE_INT32  },
    [ ANDROID_STATISTICS_SHARPNESS_MAP - ANDROID_STATISTICS_START ] =
    { "sharpnessMap",                  TYPE_INT32  },
    [ ANDROID_STATISTICS_LENS_SHADING_CORRECTION_MAP - ANDROID_STATISTICS_START ] =
    { "lensShadingCorrectionMap",      TYPE_BYTE   },
    [ ANDROID_STATISTICS_LENS_SHADING_MAP - ANDROID_STATISTICS_START ] =
    { "lensShadingMap",                TYPE_FLOAT  },
    [ ANDROID_STATISTICS_PREDICTED_COLOR_GAINS - ANDROID_STATISTICS_START ] =
    { "predictedColorGains",           TYPE_FLOAT  },
    [ ANDROID_STATISTICS_PREDICTED_COLOR_TRANSFORM - ANDROID_STATISTICS_START ] =
    { "predictedColorTransform",       TYPE_RATIONAL
                },
    [ ANDROID_STATISTICS_SCENE_FLICKER - ANDROID_STATISTICS_START ] =
    { "sceneFlicker",                  TYPE_BYTE   },
    [ ANDROID_STATISTICS_HOT_PIXEL_MAP - ANDROID_STATISTICS_START ] =
    { "hotPixelMap",                   TYPE_INT32  },
    [ ANDROID_STATISTICS_LENS_SHADING_MAP_MODE - ANDROID_STATISTICS_START ] =
    { "lensShadingMapMode",            TYPE_BYTE   },
    [ ANDROID_STATISTICS_OIS_DATA_MODE - ANDROID_STATISTICS_START ] =
    { "oisDataMode",                   TYPE_BYTE   },
    [ ANDROID_STATISTICS_OIS_TIMESTAMPS - ANDROID_STATISTICS_START ] =
    { "oisTimestamps",                 TYPE_INT64  },
    [ ANDROID_STATISTICS_OIS_X_SHIFTS - ANDROID_STATISTICS_START ] =
    { "oisXShifts",                    TYPE_FLOAT  },
    [ ANDROID_STATISTICS_OIS_Y_SHIFTS - ANDROID_STATISTICS_START ] =
    { "oisYShifts",                    TYPE_FLOAT  },
};

每个tag不仅可以通过唯一的key找到,也可通过唯一的名字找到,进而获取Value。以人脸框为例子,ANDROID_STATISTICS_FACE_RECTANGLES对应的name叫做:android.statistics.faceRectangles,也就是section的名字拼接上tag_name。 

每个tag的key-value的具体名字、类型、含义,都可查询 system/media/camera/docs/docs.html ,记得用浏览器打开哦~

2.3 常用 API

在 system/media/camera/include/system/camera_metadata.h 里,用来操作 metadata,太多就不展示了。接口实现在 camera_metadata.c 里,举几个例子:

static camera_metadata_buffer_entry_t *get_entries(
        const camera_metadata_t *metadata) {
    return (camera_metadata_buffer_entry_t*)
            ((uint8_t*)metadata + metadata->entries_start);
}

static uint8_t *get_data(const camera_metadata_t *metadata) {
    return (uint8_t*)metadata + metadata->data_start;
}

size_t get_camera_metadata_alignment() {
    return METADATA_PACKET_ALIGNMENT;
}

camera_metadata_t *allocate_copy_camera_metadata_checked(
        const camera_metadata_t *src,
        size_t src_size) {

    if (src == NULL) {
        return NULL;
    }

    if (src_size < sizeof(camera_metadata_t)) {
        ALOGE("%s: Source size too small!", __FUNCTION__);
        android_errorWriteLog(0x534e4554, "67782345");
        return NULL;
    }

    void *buffer = calloc(1, src_size);
    memcpy(buffer, src, src_size);

    camera_metadata_t *metadata = (camera_metadata_t*) buffer;
    if (validate_camera_metadata_structure(metadata, &src_size) != OK) {
        free(buffer);
        return NULL;
    }

    return metadata;
}

camera_metadata_t *allocate_camera_metadata(size_t entry_capacity,
                                            size_t data_capacity) {

    size_t memory_needed = calculate_camera_metadata_size(entry_capacity,
                                                          data_capacity);
    void *buffer = calloc(1, memory_needed);
    camera_metadata_t *metadata = place_camera_metadata(
        buffer, memory_needed, entry_capacity, data_capacity);
    if (!metadata) {
        /* This should not happen when memory_needed is the same
         * calculated in this function and in place_camera_metadata.
         */
        free(buffer);
    }
    return metadata;
}

camera_metadata_t *place_camera_metadata(void *dst,
                                         size_t dst_size,
                                         size_t entry_capacity,
                                         size_t data_capacity) {
    if (dst == NULL) return NULL;

    size_t memory_needed = calculate_camera_metadata_size(entry_capacity,
                                                          data_capacity);
    if (memory_needed > dst_size) {
      ALOGE("%s: Memory needed to place camera metadata (%zu) > dst size (%zu)", __FUNCTION__,
              memory_needed, dst_size);
      return NULL;
    }

    camera_metadata_t *metadata = (camera_metadata_t*)dst;
    metadata->version = CURRENT_METADATA_VERSION;
    metadata->flags = 0;
    metadata->entry_count = 0;
    metadata->entry_capacity = entry_capacity;
    metadata->entries_start =
            ALIGN_TO(sizeof(camera_metadata_t), ENTRY_ALIGNMENT);
    metadata->data_count = 0;
    metadata->data_capacity = data_capacity;
    metadata->size = memory_needed;
    size_t data_unaligned = (uint8_t*)(get_entries(metadata) +
            metadata->entry_capacity) - (uint8_t*)metadata;
    metadata->data_start = ALIGN_TO(data_unaligned, DATA_ALIGNMENT);
    metadata->vendor_id = CAMERA_METADATA_INVALID_VENDOR_ID;

    assert(validate_camera_metadata_structure(metadata, NULL) == OK);
    return metadata;
}
void free_camera_metadata(camera_metadata_t *metadata) {
    free(metadata);
}

size_t calculate_camera_metadata_size(size_t entry_count,
                                      size_t data_count) {
    size_t memory_needed = sizeof(camera_metadata_t);
    // Start entry list at aligned boundary
    memory_needed = ALIGN_TO(memory_needed, ENTRY_ALIGNMENT);
    memory_needed += sizeof(camera_metadata_buffer_entry_t[entry_count]);
    // Start buffer list at aligned boundary
    memory_needed = ALIGN_TO(memory_needed, DATA_ALIGNMENT);
    memory_needed += sizeof(uint8_t[data_count]);
    // Make sure camera metadata can be stacked in continuous memory
    memory_needed = ALIGN_TO(memory_needed, METADATA_PACKET_ALIGNMENT);
    return memory_needed;
}

size_t get_camera_metadata_size(const camera_metadata_t *metadata) {
    if (metadata == NULL) return ERROR;

    return metadata->size;
}

size_t get_camera_metadata_compact_size(const camera_metadata_t *metadata) {
    if (metadata == NULL) return ERROR;

    return calculate_camera_metadata_size(metadata->entry_count,
                                          metadata->data_count);
}

size_t get_camera_metadata_entry_count(const camera_metadata_t *metadata) {
    return metadata->entry_count;
}

size_t get_camera_metadata_entry_capacity(const camera_metadata_t *metadata) {
    return metadata->entry_capacity;
}

size_t get_camera_metadata_data_count(const camera_metadata_t *metadata) {
    return metadata->data_count;
}

size_t get_camera_metadata_data_capacity(const camera_metadata_t *metadata) {
    return metadata->data_capacity;
}

camera_metadata_t* copy_camera_metadata(void *dst, size_t dst_size,
        const camera_metadata_t *src) {
    size_t memory_needed = get_camera_metadata_compact_size(src);

    if (dst == NULL) return NULL;
    if (dst_size < memory_needed) {
        ALOGE("%s: Memory needed to place camera metadata (%zu) > dst size (%zu)", __FUNCTION__,
                memory_needed, dst_size);
      return NULL;
    }

    camera_metadata_t *metadata =
        place_camera_metadata(dst, dst_size, src->entry_count, src->data_count);

    metadata->flags = src->flags;
    metadata->entry_count = src->entry_count;
    metadata->data_count = src->data_count;
    metadata->vendor_id = src->vendor_id;

    memcpy(get_entries(metadata), get_entries(src),
            sizeof(camera_metadata_buffer_entry_t[metadata->entry_count]));
    memcpy(get_data(metadata), get_data(src),
            sizeof(uint8_t[metadata->data_count]));

    assert(validate_camera_metadata_structure(metadata, NULL) == OK);
    return metadata;
}

如果对上面几个小节理解了,比如内存分布,结构体定义等,那么这些 API 代码实现也就好理解了。

2.4 vendor tag 操作集

对于OEM厂商可能想对自己定义的 metadata 进行操作。查询其静态信息,验证HAL返回的 metadata 数据结构,并允许供应商定义的元数据标签在面向相机API的应用程序中可见。

/**
 * Vendor tags:
 *
 * This structure contains basic functions for enumerating an immutable set of
 * vendor-defined camera metadata tags, and querying static information about
 * their structure/type.  The intended use of this information is to validate
 * the structure of metadata returned by the camera HAL, and to allow vendor-
 * defined metadata tags to be visible in application facing camera API.
 */
typedef struct vendor_tag_ops vendor_tag_ops_t;
struct vendor_tag_ops {
    /**
     * Get the number of vendor tags supported on this platform. Used to
     * calculate the size of buffer needed for holding the array of all tags
     * returned by get_all_tags().  This must return -1 on error.
     */
    int (*get_tag_count)(const vendor_tag_ops_t *v);

    /**
     * Fill an array with all of the supported vendor tags on this platform.
     * get_tag_count() must return the number of tags supported, and
     * tag_array will be allocated with enough space to hold the number of tags
     * returned by get_tag_count().
     */
    void (*get_all_tags)(const vendor_tag_ops_t *v, uint32_t *tag_array);

    /**
     * Get the vendor section name for a vendor-specified entry tag. This will
     * only be called for vendor-defined tags.
     *
     * The naming convention for the vendor-specific section names should
     * follow a style similar to the Java package style.  For example,
     * CameraZoom Inc. must prefix their sections with "com.camerazoom."
     * This must return NULL if the tag is outside the bounds of
     * vendor-defined sections.
     *
     * There may be different vendor-defined tag sections, for example the
     * phone maker, the chipset maker, and the camera module maker may each
     * have their own "com.vendor."-prefixed section.
     *
     * The memory pointed to by the return value must remain valid for the
     * lifetime of the module, and is owned by the module.
     */
    const char *(*get_section_name)(const vendor_tag_ops_t *v, uint32_t tag);

    /**
     * Get the tag name for a vendor-specified entry tag. This is only called
     * for vendor-defined tags, and must return NULL if it is not a
     * vendor-defined tag.
     *
     * The memory pointed to by the return value must remain valid for the
     * lifetime of the module, and is owned by the module.
     */
    const char *(*get_tag_name)(const vendor_tag_ops_t *v, uint32_t tag);

    /**
     * Get tag type for a vendor-specified entry tag. The type returned must be
     * a valid type defined in camera_metadata.h.  This method is only called
     * for tags >= CAMERA_METADATA_VENDOR_TAG_BOUNDARY, and must return
     * -1 if the tag is outside the bounds of the vendor-defined sections.
     */
    int (*get_tag_type)(const vendor_tag_ops_t *v, uint32_t tag);

    /* Reserved for future use.  These must be initialized to NULL. */
    void* reserved[8];
};

struct vendor_tag_cache_ops {
    /**
     * Get the number of vendor tags supported on this platform. Used to
     * calculate the size of buffer needed for holding the array of all tags
     * returned by get_all_tags().  This must return -1 on error.
     */
    int (*get_tag_count)(metadata_vendor_id_t id);

    /**
     * Fill an array with all of the supported vendor tags on this platform.
     * get_tag_count() must return the number of tags supported, and
     * tag_array will be allocated with enough space to hold the number of tags
     * returned by get_tag_count().
     */
    void (*get_all_tags)(uint32_t *tag_array, metadata_vendor_id_t id);

    /**
     * Get the vendor section name for a vendor-specified entry tag. This will
     * only be called for vendor-defined tags.
     *
     * The naming convention for the vendor-specific section names should
     * follow a style similar to the Java package style.  For example,
     * CameraZoom Inc. must prefix their sections with "com.camerazoom."
     * This must return NULL if the tag is outside the bounds of
     * vendor-defined sections.
     *
     * There may be different vendor-defined tag sections, for example the
     * phone maker, the chipset maker, and the camera module maker may each
     * have their own "com.vendor."-prefixed section.
     *
     * The memory pointed to by the return value must remain valid for the
     * lifetime of the module, and is owned by the module.
     */
    const char *(*get_section_name)(uint32_t tag, metadata_vendor_id_t id);

    /**
     * Get the tag name for a vendor-specified entry tag. This is only called
     * for vendor-defined tags, and must return NULL if it is not a
     * vendor-defined tag.
     *
     * The memory pointed to by the return value must remain valid for the
     * lifetime of the module, and is owned by the module.
     */
    const char *(*get_tag_name)(uint32_t tag, metadata_vendor_id_t id);

    /**
     * Get tag type for a vendor-specified entry tag. The type returned must be
     * a valid type defined in camera_metadata.h.  This method is only called
     * for tags >= CAMERA_METADATA_VENDOR_TAG_BOUNDARY, and must return
     * -1 if the tag is outside the bounds of the vendor-defined sections.
     */
    int (*get_tag_type)(uint32_t tag, metadata_vendor_id_t id);

    /* Reserved for future use.  These must be initialized to NULL. */
    void* reserved[8];
};

用户可以自定义 vendor tag 的操作方法:

// Declared in system/media/private/camera/include/camera_metadata_hidden.h
int set_camera_metadata_vendor_ops(const vendor_tag_ops_t* ops) {
    vendor_tag_ops = ops;
    return OK;
}

// Declared in system/media/private/camera/include/camera_metadata_hidden.h
int set_camera_metadata_vendor_cache_ops(
        const struct vendor_tag_cache_ops *query_cache_ops) {
    vendor_cache_ops = query_cache_ops;
    return OK;
}

3. Camera Metadata 参数下发流程分析

具体代码不讲,代码在更新,写法可能有区别,但流程一样。直接说流程:

  1. 初始化 mMetadata。要设定场景,比如 mDevice->createDefaultRequest(CAMERA3_TEMPLATE_PREVIEW, mMetadata) 这种写法。
  2. 更新参数 mMetadata.update()。比如 mMetadata->update(ANDROID_FLASH_MODE, &torchOn, 1)。
  3. 下发参数。比如 mDevice->setStreamingRequest(*mMetadata)。
  4. 在 Camera3Device.cpp 中,最终将 request 放入mRequestQueue 中。
    在 Camera3Device::RequestThread::threadLoop() 来对 mRequestQueue 消息进行处理。

  5. 调用 HAL 层的 process_capture_request() 方法,处理 request 请求
    最终通过ioctl(fd, VIDIOC_S_CTRL, &control); 往 V4L2 driver 下发参数。

  6. 在 driver 中,根据具体设备注册 V4L2_ctrl 时的 ops ,调用不同的操作函数,来更新具体的硬件寄存器。

4. More

关于更深入的内存,本人认为值得探索的是metadata的内存管理,主要包括两方面:

  1. 预分配内存不足时double内存
  2. 修改增删改entry时memmov

本人觉得内存再分配和内存移动这两方面不太smart,可改进。

有兴趣可以看下面的博客链接深入学习。

优秀博客链接:

Android Camera之Metadada(一)_android camera metadata_菜鸡UP的博客-CSDN博客

Android Camera HAL3-metadata_android camerahalv3_4-metadatacommon:setparm:729: _嵌入式Max的博客-CSDN博客

Android Camera之CameraMetadata分析_camera metadata_armwind的博客-CSDN博客

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值