Camera API2/HAL3 的核心为 per-frame control,为了达成这个目标产生了 metadata 的机制,metadata一共分成三类 constrol、dynamic 以及 static。
(A)Android Metadata
//system/media/camera/src/camera_metadata.c
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;
};
(B)Mtk Metadata
在定义 vendor tag时,为了避免直接修改 Android metadata tag 文件,Mtk 定义了自己的 metadata系统。
IMetadata 是 Mtk camera hal 层用来存储 metadata 的容器,会用来存储 request、result 或者static meta 信息。
//vendor/mediatek/proprietary/hardware/mtkcam/include/mtkcam/utils/metadata/IMetadata.h
//vendor/mediatek/proprietary/hardware/mtkcam/utils/metadata/metadata/Metadata.cpp
class IMetadata
{
size_t size() const;
void resize(const size_t size, uint8_t default_val = 0);
size_t append(const Memory &other);
const uint8_t* array() const;
uint8_t* editArray();
uint8_t itemAt(size_t index) const;
void clear();
// android support
size_t appendVector(const Memory &other);
size_t appendVector(const android::Vector<MUINT8> &v);
virtual MBOOL isEmpty() const;
virtual MUINT count() const;
virtual MVOID clear();
virtual android::status_t remove(Tag_t tag);
virtual android::status_t sort();
virtual android::status_t update(Tag_t tag, IEntry const& entry);
virtual IEntry entryFor(Tag_t tag) const;
virtual IEntry entryAt(MUINT index) const;
virtual IEntry takeEntryFor(Tag_t tag);
virtual IEntry takeEntryAt(MUINT index);
virtual ssize_t flatten(void* buf, size_t buf_size) const;
virtual ssize_t unflatten(void* buf, size_t buf_size);
virtual void dump(int layer=0);
bool getEntry(const IMetadata* metadata, MUINT32 const tag, T& val, size_t index = 0);
android::status_t setEntry(IMetadata* metadata, MUINT32 const tag, T const& val);
class IEntry
{
virtual MUINT32 tag() const;
virtual MINT32 type() const;
virtual const void* data() const;
virtual MBOOL isEmpty() const;
virtual MUINT count() const;
virtual MUINT capacity() const;
virtual MBOOL setCapacity(MUINT size);
virtual MUINT setSize(MUINT size);
virtual MVOID clear();
virtual android::status_t removeAt(MUINT index);
template <typename T> static int indexOf(const IEntry& entry, const T& target);
#define IMETADATA_IENTRY_OPS_DECLARATION(_T) \
virtual MVOID push_back(_T const& item, Type2Type<_T>); \
virtual MVOID replaceItemAt(MUINT index, _T const& item, Type2Type<_T>); \
virtual _T itemAt(MUINT index, Type2Type<_T>) const; \
IMETADATA_IENTRY_OPS_DECLARATION(MUINT8)
IMETADATA_IENTRY_OPS_DECLARATION(MINT32)
IMETADATA_IENTRY_OPS_DECLARATION(MFLOAT)
IMETADATA_IENTRY_OPS_DECLARATION(MINT64)
IMETADATA_IENTRY_OPS_DECLARATION(MDOUBLE)
IMETADATA_IENTRY_OPS_DECLARATION(MRational)
IMETADATA_IENTRY_OPS_DECLARATION(MPoint)
IMETADATA_IENTRY_OPS_DECLARATION(MSize)
IMETADATA_IENTRY_OPS_DECLARATION(MRect)
IMETADATA_IENTRY_OPS_DECLARATION(IMetadata)
IMETADATA_IENTRY_OPS_DECLARATION(Memory)
#undef IMETADATA_IENTRY_OPS_DECLARATION
}
}
那我们如何使用这些Metadata呢?
//(1)向IMetadata 中填充对应 Tag 的 meta 数据
MRect region1(MPoint(2,3),MSize(4,5));
IMetadata::IEntry entryA(MTK_SCALER_CROP_REGION);
entryA.push_back(region1,Type2Type<MRect>());
IMetadata metadataA;
metadataA.update(MTK_SCALER_CROP_REGION,entryA);
//(2)替换已经填充到 IMetadata 中对应 Tag 的 meta 数据
MRect region2(MPoint(7,8),MSize(9,10));
IMetadata::IEntry entryB = metadataA.entryFor(MTK_SCALER_CROP_REGION);
entryB. replaceItemAt(0, region2, Type2Type< MRect >());
metadataA.update(MTK_SCALER_CROP_REGION,entryB);
//(3)从 IMetadata 中获取对应 Tag 的 meta 数据
IMetadata::IEntry entryC = metadataA.entryFor(MTK_SCALER_CROP_REGION);
entryC.item(0, Type2Type<MRect>());
(C)Android Tag与Mtk Tag的关系
Mtk metadata tag 包含了所有的 Android Tag。Android Tag 都能在 Mtk metadata tag 中找到一一对应
的 Tag,因此Mtk metadata tag 可以转换到对应的 Android metadata tag。
//vendor/mediatek/proprietary/hardware/mtkcam/include/mtkcam/utils/metadata/client/TagMap.h
#define ADD_ALL_MEMBERS \
_IMP_TAGCONVERT_( ANDROID_COLOR_CORRECTION_MODE , MTK_COLOR_CORRECTION_MODE )\
_IMP_TAGCONVERT_( ANDROID_COLOR_CORRECTION_TRANSFORM, MTK_COLOR_CORRECTION_TRANSFORM)\
_IMP_TAGCONVERT_( ANDROID_COLOR_CORRECTION_GAINS , MTK_COLOR_CORRECTION_GAINS )\
_IMP_TAGCONVERT_( ANDROID_COLOR_CORRECTION_ABERRATION_MODE, MTK_COLOR_CORRECTION_ABERRATION_MODE)\
_IMP_TAGCONVERT_( ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES, MTK_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES)\
_IMP_TAGCONVERT_( ANDROID_CONTROL_AE_ANTIBANDING_MODE , MTK_CONTROL_AE_ANTIBANDING_MODE )\
_IMP_TAGCONVERT_( ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION, MTK_CONTROL_AE_EXPOSURE_COMPENSATION)\
_IMP_TAGCONVERT_( ANDROID_CONTROL_AE_LOCK, MTK_CONTROL_AE_LOCK)\
_IMP_TAGCONVERT_( ANDROID_CONTROL_AE_MODE, MTK_CONTROL_AE_MODE)\
_IMP_TAGCONVERT_( ANDROID_CONTROL_AE_REGIONS, MTK_CONTROL_AE_REGIONS)\
_IMP_TAGCONVERT_( ANDROID_CONTROL_AE_TARGET_FPS_RANGE, MTK_CONTROL_AE_TARGET_FPS_RANGE)\
_IMP_TAGCONVERT_( ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER, MTK_CONTROL_AE_PRECAPTURE_TRIGGER)\
_IMP_TAGCONVERT_( ANDROID_CONTROL_AF_MODE, MTK_CONTROL_AF_MODE)\
_IMP_TAGCONVERT_( ANDROID_CONTROL_AF_REGIONS, MTK_CONTROL_AF_REGIONS)\
_IMP_TAGCONVERT_( ANDROID_CONTROL_AF_TRIGGER, MTK_CONTROL_AF_TRIGGER)\
_IMP_TAGCONVERT_( ANDROID_CONTROL_AWB_LOCK, MTK_CONTROL_AWB_LOCK)\
_IMP_TAGCONVERT_( ANDROID_CONTROL_AWB_MODE, MTK_CONTROL_AWB_MODE)\
_IMP_TAGCONVERT_( ANDROID_CONTROL_AWB_REGIONS, MTK_CONTROL_AWB_REGIONS)\
//...
(D)Android Tag与Mtk Tag的转换
在 Camera Hal 层之上使用的是 Android 的 Camera metadata,而在 Camera Hal 层使用的是 Mtk Camera metadata。因此当 request metadata 从 App 层传递到 Hal 层时需要将 Android Camera metadata转换为 Mtk camera metadata。
与之相反,result 与 static meta 则由 Mtk camera metadata 转换为 AndroidCamera metadata 并传递给 AP。
IMetadataConvert.h 是用来进行转换的接口,在收到 App 的 request 时调用 convertFromHidl(上到下),
再返回 result 或者 static metadata 时调用 convertToHidl 进行转换(下到上)。
//vendor/mediatek/proprietary/hardware/mtkcam/include/mtkcam/utils/metadata/IMetadataConverter.h
//vendor/mediatek/proprietary/hardware/mtkcam/utils/metadata/conversion/MetadataConverter.cpp
//vendor/mediatek/proprietary/hardware/mtkcam/utils/metadata/conversion/TypeConvert.androidMetadata.cpp
//vendor/mediatek/proprietary/hardware/mtkcam/utils/metadata/conversion/TypeConvert.mtkMetadata.cpp
class IMetadataConverter : public virtual android::RefBase
{
public:
static android::sp<IMetadataConverter> createInstance(IMetadataTagSet const &pTagInfo);
virtual MBOOL convertFromHidl(const void* src/*const ::android::hardware::hidl_vec* */ , IMetadata& dst) = 0;
virtual MBOOL convertToHidl(const IMetadata& src, void* dst/*::android::hardware::hidl_vec* */ ) = 0;
virtual MBOOL convert(const camera_metadata* src, IMetadata& dst) const = 0;
virtual MBOOL convert(const IMetadata& src, camera_metadata*& dst, size_t* pDstSize = nullptr) const = 0;
virtual size_t getCameraMetadataSize(const camera_metadata *metadata) const = 0;
virtual void freeCameraMetadata(camera_metadata *metadata) const = 0;
virtual MVOID dump(const IMetadata &rMetadata, int frameNo = -1) const = 0;
virtual MVOID dumpAll(const IMetadata &rMetadata, int frameNo = -1) const = 0;
};