/* * Copyright (c) 2021-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "metadata_utils.h" #include #include "metadata_log.h" #define IF_COND_PRINT_MSG_AND_RETURN(cond, msg) \ if (cond) { \ METADATA_ERR_LOG(msg); \ return {}; \ } static constexpr uint32_t MAX_SUPPORTED_TAGS = 1000; static constexpr uint32_t MAX_SUPPORTED_ITEMS = 2000; static constexpr uint32_t MAX_ITEM_CAPACITY = (1000 * 10); static constexpr uint32_t MAX_DATA_CAPACITY = (1000 * 10 * 10); namespace OHOS::Camera { void MetadataUtils::WriteMetadataDataToVec(const camera_metadata_item_t &entry, std::vector& cameraAbility) { if (entry.data_type == META_TYPE_BYTE) { for (size_t i = 0; i < entry.count; i++) { WriteData(*(entry.data.u8 + i), cameraAbility); } } else if (entry.data_type == META_TYPE_INT32) { for (size_t i = 0; i < entry.count; i++) { WriteData(*(entry.data.i32 + i), cameraAbility); } } else if (entry.data_type == META_TYPE_FLOAT) { for (size_t i = 0; i < entry.count; i++) { WriteData(*(entry.data.f + i), cameraAbility); } } else if (entry.data_type == META_TYPE_INT64) { for (size_t i = 0; i < entry.count; i++) { WriteData(*(entry.data.i64 + i), cameraAbility); } } else if (entry.data_type == META_TYPE_DOUBLE) { for (size_t i = 0; i < entry.count; i++) { WriteData(*(entry.data.d + i), cameraAbility); } } else if (entry.data_type == META_TYPE_RATIONAL) { for (size_t i = 0; i < entry.count; i++) { WriteData((*(entry.data.r + i)).numerator, cameraAbility); WriteData((*(entry.data.r + i)).denominator, cameraAbility); } } } bool MetadataUtils::ConvertMetadataToVec(const std::shared_ptr &metadata, std::vector& cameraAbility) { if (metadata == nullptr) { METADATA_ERR_LOG("MetadataUtils::ConvertMetadataToVec: metadata is null!"); return false; } common_metadata_header_t *meta = metadata->get(); if (meta == nullptr) { WriteData(0, cameraAbility); METADATA_WARNING_LOG("MetadataUtils::ConvertMetadataToVec: tagCount is 0!"); return true; } uint32_t tagCount = GetCameraMetadataItemCount(meta); if (tagCount > MAX_SUPPORTED_TAGS) { METADATA_ERR_LOG("MetadataUtils::ConvertMetadataToVec: tagCount out of range: %u", tagCount); return false; } uint32_t itemCapacity = GetCameraMetadataItemCapacity(meta); if (itemCapacity > MAX_ITEM_CAPACITY) { METADATA_ERR_LOG("MetadataUtils::ConvertMetadataToVec: itemCapacity out of range: %u", itemCapacity); return false; } uint32_t dataCapacity = GetCameraMetadataDataSize(meta); if (dataCapacity > MAX_DATA_CAPACITY) { METADATA_ERR_LOG("MetadataUtils::ConvertMetadataToVec: dataCapacity out of range: %u", dataCapacity); return false; } WriteData(tagCount, cameraAbility); WriteData(itemCapacity, cameraAbility); WriteData(dataCapacity, cameraAbility); for (uint32_t i = 0; i < tagCount; i++) { camera_metadata_item_t item; int ret = GetCameraMetadataItem(meta, i, &item); if (ret != CAM_META_SUCCESS) { METADATA_ERR_LOG("MetadataUtils::ConvertMetadataToVec: get meta item failed!"); return false; } if (item.count > MAX_SUPPORTED_ITEMS) { METADATA_ERR_LOG("MetadataUtils::ConvertMetadataToVec: item.count out of range:%u", item.count); return false; } WriteData(item.index, cameraAbility); WriteData(item.item, cameraAbility); WriteData(item.data_type, cameraAbility); WriteData(item.count, cameraAbility); WriteMetadataDataToVec(item, cameraAbility); } return true; } bool MetadataUtils::EncodeCameraMetadata(const std::shared_ptr &metadata, MessageParcel &data) { if (metadata == nullptr) { return false; } bool bRet = true; uint32_t tagCount = 0; common_metadata_header_t *meta = metadata->get(); if (meta != nullptr) { tagCount = GetCameraMetadataItemCount(meta); bRet = bRet && data.WriteUint32(tagCount); bRet = bRet && data.WriteUint32(GetCameraMetadataItemCapacity(meta)); bRet = bRet && data.WriteUint32(GetCameraMetadataDataSize(meta)); for (uint32_t i = 0; i < tagCount; i++) { camera_metadata_item_t item; int ret = GetCameraMetadataItem(meta, i, &item); if (ret != CAM_META_SUCCESS) { return false; } bRet = bRet && data.WriteUint32(item.index); bRet = bRet && data.WriteUint32(item.item); bRet = bRet && data.WriteUint32(item.data_type); bRet = bRet && data.WriteUint32(item.count); bRet = bRet && MetadataUtils::WriteMetadata(item, data); } } else { bRet = data.WriteUint32(tagCount); } return bRet; } void MetadataUtils::ReadMetadataDataFromVec(int32_t &index, camera_metadata_item_t &entry, const std::vector& cameraAbility) { if (entry.data_type == META_TYPE_BYTE) { entry.data.u8 = new(std::nothrow) uint8_t[entry.count]; if (entry.data.u8 != nullptr) { for (size_t i = 0; i < entry.count; i++) { ReadData(entry.data.u8[i], index, cameraAbility); } } } else if (entry.data_type == META_TYPE_INT32) { entry.data.i32 = new(std::nothrow) int32_t[entry.count]; if (entry.data.i32 != nullptr) { for (size_t i = 0; i < entry.count; i++) { ReadData(entry.data.i32[i], index, cameraAbility); } } } else if (entry.data_type == META_TYPE_FLOAT) { entry.data.f = new(std::nothrow) float[entry.count]; if (entry.data.f != nullptr) { for (size_t i = 0; i < entry.count; i++) { ReadData(entry.data.f[i], index, cameraAbility); } } } else if (entry.data_type == META_TYPE_INT64) { entry.data.i64 = new(std::nothrow) int64_t[entry.count]; if (entry.data.i64 != nullptr) { for (size_t i = 0; i < entry.count; i++) { ReadData(entry.data.i64[i], index, cameraAbility); } } } else if (entry.data_type == META_TYPE_DOUBLE) { entry.data.d = new(std::nothrow) double[entry.count]; if (entry.data.d != nullptr) { for (size_t i = 0; i < entry.count; i++) { ReadData(entry.data.d[i], index, cameraAbility); } } } else if (entry.data_type == META_TYPE_RATIONAL) { entry.data.r = new(std::nothrow) camera_rational_t[entry.count]; if (entry.data.r != nullptr) { for (size_t i = 0; i < entry.count; i++) { ReadData(entry.data.r[i].numerator, index, cameraAbility); ReadData(entry.data.r[i].denominator, index, cameraAbility); } } } } void MetadataUtils::ConvertVecToMetadata(const std::vector& cameraAbility, std::shared_ptr &metadata) { int32_t index = 0; uint32_t tagCount = 0; uint32_t itemCapacity = 0; uint32_t dataCapacity = 0; ReadData(tagCount, index, cameraAbility); if (tagCount > MAX_SUPPORTED_TAGS) { METADATA_ERR_LOG("MetadataUtils::ConvertVecToMetadata: tagCount out of range: %u", tagCount); return; } ReadData(itemCapacity, index, cameraAbility); if (itemCapacity > MAX_ITEM_CAPACITY) { METADATA_ERR_LOG("MetadataUtils::ConvertVecToMetadata: itemCapacity out of range: %u", itemCapacity); return; } ReadData(dataCapacity, index, cameraAbility); if (dataCapacity > MAX_DATA_CAPACITY) { METADATA_ERR_LOG("MetadataUtils::ConvertVecToMetadata: dataCapacity out of range: %u", dataCapacity); return; } std::vector items; for (uint32_t i = 0; i < tagCount; i++) { camera_metadata_item_t item; ReadData(item.index, index, cameraAbility); ReadData(item.item, index, cameraAbility); ReadData(item.data_type, index, cameraAbility); ReadData(item.count, index, cameraAbility); if (item.count > MAX_SUPPORTED_ITEMS) { METADATA_ERR_LOG("MetadataUtils::DecodeCameraMetadata item.count out of range:%u", item.count); return; } ReadMetadataDataFromVec(index, item, cameraAbility); items.push_back(item); } metadata = std::make_shared(itemCapacity, dataCapacity); common_metadata_header_t *meta = metadata->get(); for (auto &item_ : items) { void *buffer = nullptr; MetadataUtils::ItemDataToBuffer(item_, &buffer); (void)AddCameraMetadataItem(meta, item_.item, buffer, item_.count); FreeMetadataBuffer(item_); } } void MetadataUtils::DecodeCameraMetadata(MessageParcel &data, std::shared_ptr &metadata) { uint32_t tagCount = data.ReadUint32(); uint32_t itemCapacity = data.ReadUint32(); uint32_t dataCapacity = data.ReadUint32(); if (tagCount > MAX_SUPPORTED_TAGS) { tagCount = MAX_SUPPORTED_TAGS; METADATA_ERR_LOG("MetadataUtils::DecodeCameraMetadata tagCount is more than supported value"); } if (itemCapacity > MAX_ITEM_CAPACITY) { itemCapacity = MAX_ITEM_CAPACITY; METADATA_ERR_LOG("MetadataUtils::DecodeCameraMetadata itemCapacity is more than supported value"); } if (dataCapacity > MAX_DATA_CAPACITY) { dataCapacity = MAX_DATA_CAPACITY; METADATA_ERR_LOG("MetadataUtils::DecodeCameraMetadata dataCapacity is more than supported value"); } std::vector items; for (uint32_t i = 0; i < tagCount; i++) { camera_metadata_item_t item; item.index = data.ReadUint32(); item.item = data.ReadUint32(); item.data_type = data.ReadUint32(); item.count = data.ReadUint32(); if (item.count > MAX_SUPPORTED_ITEMS) { item.count = MAX_SUPPORTED_ITEMS; METADATA_ERR_LOG("MetadataUtils::DecodeCameraMetadata item.count is more than supported value"); } MetadataUtils::ReadMetadata(item, data); items.push_back(item); } metadata = std::make_shared(itemCapacity, dataCapacity); common_metadata_header_t *meta = metadata->get(); for (auto &item_ : items) { void *buffer = nullptr; MetadataUtils::ItemDataToBuffer(item_, &buffer); (void)AddCameraMetadataItem(meta, item_.item, buffer, item_.count); FreeMetadataBuffer(item_); } } bool MetadataUtils::WriteMetadata(const camera_metadata_item_t &item, MessageParcel &data) { bool bRet = false; size_t i; if (item.data_type == META_TYPE_BYTE) { std::vector byteBuffers; for (i = 0; i < item.count; i++) { byteBuffers.push_back(*(item.data.u8 + i)); } bRet = data.WriteUInt8Vector(byteBuffers); } else if (item.data_type == META_TYPE_INT32) { std::vector int32Buffers; for (i = 0; i < item.count; i++) { int32Buffers.push_back(*(item.data.i32 + i)); } bRet = data.WriteInt32Vector(int32Buffers); } else if (item.data_type == META_TYPE_FLOAT) { std::vector floatBuffers; for (i = 0; i < item.count; i++) { floatBuffers.push_back(*(item.data.f + i)); } bRet = data.WriteFloatVector(floatBuffers); } else if (item.data_type == META_TYPE_UINT32) { std::vector uInt32Buffers; for (i = 0; i < item.count; i++) { uInt32Buffers.push_back(*(item.data.ui32 + i)); } bRet = data.WriteUInt32Vector(uInt32Buffers); } else if (item.data_type == META_TYPE_INT64) { std::vector int64Buffers; for (i = 0; i < item.count; i++) { int64Buffers.push_back(*(item.data.i64 + i)); } bRet = data.WriteInt64Vector(int64Buffers); } else if (item.data_type == META_TYPE_DOUBLE) { std::vector doubleBuffers; for (i = 0; i < item.count; i++) { doubleBuffers.push_back(*(item.data.d + i)); } bRet = data.WriteDoubleVector(doubleBuffers); } else if (item.data_type == META_TYPE_RATIONAL) { std::vector rationalBuffers; for (i = 0; i < item.count; i++) { rationalBuffers.push_back((*(item.data.r + i)).numerator); rationalBuffers.push_back((*(item.data.r + i)).denominator); } bRet = data.WriteInt32Vector(rationalBuffers); } return bRet; } std::string MetadataUtils::EncodeToString(std::shared_ptr metadata) { int32_t ret; const int32_t headerLength = sizeof(common_metadata_header_t); const int32_t itemLen = sizeof(camera_metadata_item_entry_t); const int32_t itemFixedLen = static_cast(offsetof(camera_metadata_item_entry_t, data)); if (metadata == nullptr || metadata->get() == nullptr) { METADATA_ERR_LOG("MetadataUtils::EncodeToString Metadata is invalid"); return {}; } common_metadata_header_t *meta = metadata->get(); int32_t encodeDataLen = headerLength + (itemLen * meta->item_count) + meta->data_count; std::string s(encodeDataLen, '\0'); char *encodeData = &s[0]; ret = memcpy_s(encodeData, encodeDataLen, meta, headerLength); if (ret != EOK) { METADATA_ERR_LOG("MetadataUtils::EncodeToString Failed to copy memory for metadata header"); return {}; } encodeData += headerLength; encodeDataLen -= headerLength; camera_metadata_item_entry_t *item = GetMetadataItems(meta); for (uint32_t index = 0; index < meta->item_count; index++, item++) { ret = memcpy_s(encodeData, encodeDataLen, item, itemFixedLen); if (ret != EOK) { METADATA_ERR_LOG("MetadataUtils::EncodeToString Failed to copy memory for item fixed fields"); return {}; } encodeData += itemFixedLen; encodeDataLen -= itemFixedLen; int32_t dataLen = itemLen - itemFixedLen; ret = memcpy_s(encodeData, encodeDataLen, &(item->data), dataLen); if (ret != EOK) { METADATA_ERR_LOG("MetadataUtils::EncodeToString Failed to copy memory for item data field"); return {}; } encodeData += dataLen; encodeDataLen -= dataLen; } if (meta->data_count != 0) { ret = memcpy_s(encodeData, encodeDataLen, GetMetadataData(meta), meta->data_count); if (ret != EOK) { METADATA_ERR_LOG("MetadataUtils::EncodeToString Failed to copy memory for data"); return {}; } encodeData += meta->data_count; } METADATA_DEBUG_LOG("MetadataUtils::EncodeToString Calculated length: %{public}d, encoded length: %{public}d", s.capacity(), (encodeData - &s[0])); return s; } std::shared_ptr MetadataUtils::DecodeFromString(std::string setting) { uint32_t ret; uint32_t totalLen = setting.capacity(); const uint32_t headerLength = sizeof(common_metadata_header_t); const uint32_t itemLen = sizeof(camera_metadata_item_entry_t); const uint32_t itemFixedLen = offsetof(camera_metadata_item_entry_t, data); IF_COND_PRINT_MSG_AND_RETURN(totalLen < headerLength, "MetadataUtils::DecodeFromString Length is less than metadata header length") char *decodeData = &setting[0]; common_metadata_header_t header; ret = memcpy_s(&header, headerLength, decodeData, headerLength); IF_COND_PRINT_MSG_AND_RETURN(ret != EOK, "MetadataUtils::DecodeFromString Failed to copy memory for metadata header") std::shared_ptr metadata = std::make_shared(header.item_capacity, header.data_capacity); common_metadata_header_t *meta = metadata->get(); IF_COND_PRINT_MSG_AND_RETURN(!meta, "MetadataUtils::DecodeFromString Failed to get metadata header") ret = memcpy_s(meta, headerLength, &header, headerLength); IF_COND_PRINT_MSG_AND_RETURN(ret != EOK, "MetadataUtils::DecodeFromString Failed to copy memory for metadata header") decodeData += headerLength; camera_metadata_item_entry_t *item = GetMetadataItems(meta); for (uint32_t index = 0; index < meta->item_count; index++, item++) { if (totalLen < ((decodeData - &setting[0]) + itemLen)) { METADATA_ERR_LOG("MetadataUtils::DecodeFromString Failed at item index: %{public}d", index); return {}; } ret = memcpy_s(item, itemFixedLen, decodeData, itemFixedLen); IF_COND_PRINT_MSG_AND_RETURN(ret != EOK, "MetadataUtils::DecodeFromString Failed to copy memory for item fixed fields") decodeData += itemFixedLen; uint32_t dataLen = itemLen - itemFixedLen; ret = memcpy_s(&(item->data), dataLen, decodeData, dataLen); IF_COND_PRINT_MSG_AND_RETURN(ret != EOK, "MetadataUtils::DecodeFromString Failed to copy memory for item data field") decodeData += dataLen; } if (meta->data_count != 0) { IF_COND_PRINT_MSG_AND_RETURN(totalLen < static_cast(((decodeData - &setting[0]) + meta->data_count)), "MetadataUtils::DecodeFromString Failed at data copy") ret = memcpy_s(GetMetadataData(meta), meta->data_count, decodeData, meta->data_count); IF_COND_PRINT_MSG_AND_RETURN(ret != EOK, "MetadataUtils::DecodeFromString Failed to copy memory for item data field") decodeData += meta->data_count; } METADATA_DEBUG_LOG("MetadataUtils::DecodeFromString String length: %{public}d, Decoded length: %{public}d", setting.capacity(), (decodeData - &setting[0])); return metadata; } static void ReadMetadataUInt8(camera_metadata_item_t &entry, MessageParcel &data) { std::vector buffers; data.ReadUInt8Vector(&buffers); entry.data.u8 = new(std::nothrow) uint8_t[entry.count]; if (entry.data.u8 != nullptr) { for (size_t i = 0; i < entry.count && i < buffers.size(); i++) { entry.data.u8[i] = buffers.at(i); } } } static void ReadMetadataInt32(camera_metadata_item_t &entry, MessageParcel &data) { std::vector buffers; data.ReadInt32Vector(&buffers); entry.data.i32 = new(std::nothrow) int32_t[entry.count]; if (entry.data.i32 != nullptr) { for (size_t i = 0; i < entry.count && i < buffers.size(); i++) { entry.data.i32[i] = buffers.at(i); } } } static void ReadMetadataUInt32(camera_metadata_item_t &entry, MessageParcel &data) { std::vector buffers; data.ReadUInt32Vector(&buffers); entry.data.ui32 = new(std::nothrow) uint32_t[entry.count]; if (entry.data.ui32 != nullptr) { for (size_t i = 0; i < entry.count && i < buffers.size(); i++) { entry.data.ui32[i] = buffers.at(i); } } } static void ReadMetadataFloat(camera_metadata_item_t &entry, MessageParcel &data) { std::vector buffers; data.ReadFloatVector(&buffers); entry.data.f = new(std::nothrow) float[entry.count]; if (entry.data.f != nullptr) { for (size_t i = 0; i < entry.count && i < buffers.size(); i++) { entry.data.f[i] = buffers.at(i); } } } static void ReadMetadataInt64(camera_metadata_item_t &entry, MessageParcel &data) { std::vector buffers; data.ReadInt64Vector(&buffers); entry.data.i64 = new(std::nothrow) int64_t[entry.count]; if (entry.data.i64 != nullptr) { for (size_t i = 0; i < entry.count && i < buffers.size(); i++) { entry.data.i64[i] = buffers.at(i); } } } static void ReadMetadataDouble(camera_metadata_item_t &entry, MessageParcel &data) { std::vector buffers; data.ReadDoubleVector(&buffers); entry.data.d = new(std::nothrow) double[entry.count]; if (entry.data.d != nullptr) { for (size_t i = 0; i < entry.count && i < buffers.size(); i++) { entry.data.d[i] = buffers.at(i); } } } static void ReadMetadataRational(camera_metadata_item_t &entry, MessageParcel &data) { std::vector buffers; data.ReadInt32Vector(&buffers); entry.data.r = new(std::nothrow) camera_rational_t[entry.count]; if (entry.data.r != nullptr) { for (size_t i = 0, j = 0; i < entry.count && j < static_cast(buffers.size() - 1); i++, j += 2) { // 2:Take two elements from the buffer vector container entry.data.r[i].numerator = buffers.at(j); entry.data.r[i].denominator = buffers.at(j + 1); } } } bool MetadataUtils::ReadMetadata(camera_metadata_item_t &entry, MessageParcel &data) { if (entry.count > MAX_SUPPORTED_ITEMS) { entry.count = MAX_SUPPORTED_ITEMS; METADATA_ERR_LOG("MetadataUtils::ReadMetadata item.count is more than supported value"); } switch (entry.data_type) { case META_TYPE_BYTE: ReadMetadataUInt8(entry, data); break; case META_TYPE_INT32: ReadMetadataInt32(entry, data); break; case META_TYPE_UINT32: ReadMetadataUInt32(entry, data); break; case META_TYPE_FLOAT: ReadMetadataFloat(entry, data); break; case META_TYPE_INT64: ReadMetadataInt64(entry, data); break; case META_TYPE_DOUBLE: ReadMetadataDouble(entry, data); break; case META_TYPE_RATIONAL: ReadMetadataRational(entry, data); break; } return true; } void MetadataUtils::ItemDataToBuffer(const camera_metadata_item_t &item, void **buffer) { if (buffer == nullptr) { METADATA_ERR_LOG("MetadataUtils::ItemDataToBuffer buffer is null"); return; } if (item.data_type == META_TYPE_BYTE) { *buffer = reinterpret_cast(item.data.u8); } else if (item.data_type == META_TYPE_INT32) { *buffer = reinterpret_cast(item.data.i32); } else if (item.data_type == META_TYPE_FLOAT) { *buffer = reinterpret_cast(item.data.f); } else if (item.data_type == META_TYPE_UINT32) { *buffer = reinterpret_cast(item.data.ui32); } else if (item.data_type == META_TYPE_INT64) { *buffer = reinterpret_cast(item.data.i64); } else if (item.data_type == META_TYPE_DOUBLE) { *buffer = reinterpret_cast(item.data.d); } else if (item.data_type == META_TYPE_RATIONAL) { *buffer = reinterpret_cast(item.data.r); } } void MetadataUtils::FreeMetadataBuffer(camera_metadata_item_t &entry) { if (entry.data_type == META_TYPE_BYTE) { if (entry.data.u8 != nullptr) { delete[] entry.data.u8; } } else if (entry.data_type == META_TYPE_INT32) { if (entry.data.i32 != nullptr) { delete[] entry.data.i32; } } else if (entry.data_type == META_TYPE_FLOAT) { if (entry.data.f != nullptr) { delete[] entry.data.f; } } else if (entry.data_type == META_TYPE_INT64) { if (entry.data.i64 != nullptr) { delete[] entry.data.i64; } } else if (entry.data_type == META_TYPE_UINT32) { if (entry.data.ui32 != nullptr) { delete[] entry.data.ui32; } } else if (entry.data_type == META_TYPE_DOUBLE) { if (entry.data.d != nullptr) { delete[] entry.data.d; } } else if (entry.data_type == META_TYPE_RATIONAL) { if (entry.data.r != nullptr) { delete[] entry.data.r; } } } } // Camera