Laurent Pinchart | 9214e2b | 2019-09-05 03:12:34 +0300 | [diff] [blame] | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
| 2 | /* |
| 3 | * Copyright (C) 2019, Google Inc. |
| 4 | * |
| 5 | * camera_metadata.cpp - libcamera Android Camera Metadata Helper |
| 6 | */ |
| 7 | |
| 8 | #include "camera_metadata.h" |
| 9 | |
Laurent Pinchart | 93e72b6 | 2020-05-12 00:58:34 +0300 | [diff] [blame] | 10 | #include "libcamera/internal/log.h" |
Laurent Pinchart | 9214e2b | 2019-09-05 03:12:34 +0300 | [diff] [blame] | 11 | |
| 12 | using namespace libcamera; |
| 13 | |
Hirokazu Honda | 6c5792f | 2020-10-20 18:15:01 +0900 | [diff] [blame] | 14 | LOG_DEFINE_CATEGORY(CameraMetadata) |
Laurent Pinchart | 9214e2b | 2019-09-05 03:12:34 +0300 | [diff] [blame] | 15 | |
Jacopo Mondi | b9369a0 | 2021-01-21 12:50:04 +0100 | [diff] [blame] | 16 | CameraMetadata::CameraMetadata() |
| 17 | : metadata_(nullptr), valid_(false) |
| 18 | { |
| 19 | } |
| 20 | |
Laurent Pinchart | 9214e2b | 2019-09-05 03:12:34 +0300 | [diff] [blame] | 21 | CameraMetadata::CameraMetadata(size_t entryCapacity, size_t dataCapacity) |
| 22 | { |
| 23 | metadata_ = allocate_camera_metadata(entryCapacity, dataCapacity); |
| 24 | valid_ = metadata_ != nullptr; |
| 25 | } |
| 26 | |
Paul Elder | 5e25960 | 2021-01-21 19:15:42 +0900 | [diff] [blame] | 27 | CameraMetadata::CameraMetadata(const camera_metadata_t *metadata) |
| 28 | { |
| 29 | metadata_ = clone_camera_metadata(metadata); |
| 30 | valid_ = metadata_ != nullptr; |
| 31 | } |
| 32 | |
| 33 | CameraMetadata::CameraMetadata(const CameraMetadata &other) |
| 34 | : CameraMetadata(other.get()) |
| 35 | { |
| 36 | } |
| 37 | |
Laurent Pinchart | 9214e2b | 2019-09-05 03:12:34 +0300 | [diff] [blame] | 38 | CameraMetadata::~CameraMetadata() |
| 39 | { |
| 40 | if (metadata_) |
| 41 | free_camera_metadata(metadata_); |
| 42 | } |
| 43 | |
Paul Elder | 5e25960 | 2021-01-21 19:15:42 +0900 | [diff] [blame] | 44 | CameraMetadata &CameraMetadata::operator=(const CameraMetadata &other) |
| 45 | { |
| 46 | if (this == &other) |
| 47 | return *this; |
| 48 | |
| 49 | if (metadata_) |
| 50 | free_camera_metadata(metadata_); |
| 51 | |
| 52 | metadata_ = clone_camera_metadata(other.get()); |
| 53 | valid_ = metadata_ != nullptr; |
| 54 | |
| 55 | return *this; |
| 56 | } |
| 57 | |
| 58 | bool CameraMetadata::getEntry(uint32_t tag, camera_metadata_ro_entry_t *entry) const |
| 59 | { |
| 60 | if (find_camera_metadata_ro_entry(metadata_, tag, entry)) |
| 61 | return false; |
| 62 | |
| 63 | return true; |
| 64 | } |
| 65 | |
Paul Elder | 1ff6887 | 2021-04-30 17:10:05 +0900 | [diff] [blame^] | 66 | /* |
| 67 | * \brief Resize the metadata container, if necessary |
| 68 | * \param[in] count Number of entries to add to the container |
| 69 | * \param[in] size Total size of entries to add, in bytes |
| 70 | * \return True if resize was successful or unnecessary, false otherwise |
| 71 | */ |
| 72 | bool CameraMetadata::resize(size_t count, size_t size) |
Laurent Pinchart | 9214e2b | 2019-09-05 03:12:34 +0300 | [diff] [blame] | 73 | { |
| 74 | if (!valid_) |
| 75 | return false; |
| 76 | |
Paul Elder | 1ff6887 | 2021-04-30 17:10:05 +0900 | [diff] [blame^] | 77 | if (!count && !size) |
| 78 | return true; |
| 79 | |
| 80 | size_t currentEntryCount = get_camera_metadata_entry_count(metadata_); |
| 81 | size_t currentEntryCapacity = get_camera_metadata_entry_capacity(metadata_); |
| 82 | size_t newEntryCapacity = currentEntryCapacity < currentEntryCount + count ? |
| 83 | currentEntryCapacity * 2 : currentEntryCapacity; |
| 84 | |
| 85 | size_t currentDataCount = get_camera_metadata_data_count(metadata_); |
| 86 | size_t currentDataCapacity = get_camera_metadata_data_capacity(metadata_); |
| 87 | size_t newDataCapacity = currentDataCapacity < currentDataCount + size ? |
| 88 | currentDataCapacity * 2 : currentDataCapacity; |
| 89 | |
| 90 | if (newEntryCapacity > currentEntryCapacity || |
| 91 | newDataCapacity > currentDataCapacity) { |
| 92 | camera_metadata_t *oldMetadata = metadata_; |
| 93 | metadata_ = allocate_camera_metadata(newEntryCapacity, newDataCapacity); |
| 94 | if (!metadata_) { |
| 95 | metadata_ = oldMetadata; |
| 96 | return false; |
| 97 | } |
| 98 | |
| 99 | LOG(CameraMetadata, Info) |
| 100 | << "Resized: old entry capacity " << currentEntryCapacity |
| 101 | << ", old data capacity " << currentDataCapacity |
| 102 | << ", new entry capacity " << newEntryCapacity |
| 103 | << ", new data capacity " << newDataCapacity; |
| 104 | |
| 105 | append_camera_metadata(metadata_, oldMetadata); |
| 106 | free_camera_metadata(oldMetadata); |
| 107 | } |
| 108 | |
| 109 | return true; |
| 110 | } |
| 111 | |
| 112 | bool CameraMetadata::addEntry(uint32_t tag, const void *data, size_t count, |
| 113 | size_t sizeofT) |
| 114 | { |
| 115 | if (!valid_) |
| 116 | return false; |
| 117 | |
| 118 | if (!resize(1, count * sizeofT)) { |
| 119 | LOG(CameraMetadata, Error) << "Failed to resize"; |
| 120 | valid_ = false; |
| 121 | return false; |
| 122 | } |
| 123 | |
Laurent Pinchart | 9214e2b | 2019-09-05 03:12:34 +0300 | [diff] [blame] | 124 | if (!add_camera_metadata_entry(metadata_, tag, data, count)) |
| 125 | return true; |
| 126 | |
| 127 | const char *name = get_camera_metadata_tag_name(tag); |
| 128 | if (name) |
| 129 | LOG(CameraMetadata, Error) |
| 130 | << "Failed to add tag " << name; |
| 131 | else |
| 132 | LOG(CameraMetadata, Error) |
| 133 | << "Failed to add unknown tag " << tag; |
| 134 | |
| 135 | valid_ = false; |
| 136 | |
| 137 | return false; |
| 138 | } |
| 139 | |
Jacopo Mondi | 29b59a9 | 2020-07-24 14:28:01 +0200 | [diff] [blame] | 140 | bool CameraMetadata::updateEntry(uint32_t tag, const void *data, size_t count) |
| 141 | { |
| 142 | if (!valid_) |
| 143 | return false; |
| 144 | |
| 145 | camera_metadata_entry_t entry; |
| 146 | int ret = find_camera_metadata_entry(metadata_, tag, &entry); |
| 147 | if (ret) { |
| 148 | const char *name = get_camera_metadata_tag_name(tag); |
| 149 | LOG(CameraMetadata, Error) |
| 150 | << "Failed to update tag " |
| 151 | << (name ? name : "<unknown>") << ": not present"; |
| 152 | return false; |
| 153 | } |
| 154 | |
Paul Elder | 1ff6887 | 2021-04-30 17:10:05 +0900 | [diff] [blame^] | 155 | size_t oldSize = |
| 156 | calculate_camera_metadata_entry_data_size(entry.type, |
| 157 | entry.count); |
| 158 | size_t newSize = |
| 159 | calculate_camera_metadata_entry_data_size(entry.type, |
| 160 | count); |
| 161 | size_t sizeIncrement = newSize - oldSize > 0 ? newSize - oldSize : 0; |
| 162 | if (!resize(0, sizeIncrement)) { |
| 163 | LOG(CameraMetadata, Error) << "Failed to resize"; |
| 164 | valid_ = false; |
Jacopo Mondi | 29b59a9 | 2020-07-24 14:28:01 +0200 | [diff] [blame] | 165 | return false; |
| 166 | } |
| 167 | |
Paul Elder | 1ff6887 | 2021-04-30 17:10:05 +0900 | [diff] [blame^] | 168 | ret = update_camera_metadata_entry(metadata_, entry.index, data, |
| 169 | count, nullptr); |
| 170 | if (!ret) |
| 171 | return true; |
| 172 | |
| 173 | const char *name = get_camera_metadata_tag_name(tag); |
| 174 | LOG(CameraMetadata, Error) |
| 175 | << "Failed to update tag " << (name ? name : "<unknown>"); |
| 176 | |
| 177 | valid_ = false; |
| 178 | |
| 179 | return false; |
Jacopo Mondi | 29b59a9 | 2020-07-24 14:28:01 +0200 | [diff] [blame] | 180 | } |
| 181 | |
Laurent Pinchart | 9214e2b | 2019-09-05 03:12:34 +0300 | [diff] [blame] | 182 | camera_metadata_t *CameraMetadata::get() |
| 183 | { |
| 184 | return valid_ ? metadata_ : nullptr; |
| 185 | } |
Jacopo Mondi | f2d1926 | 2020-07-24 13:59:15 +0200 | [diff] [blame] | 186 | |
| 187 | const camera_metadata_t *CameraMetadata::get() const |
| 188 | { |
| 189 | return valid_ ? metadata_ : nullptr; |
| 190 | } |