blob: bf8d2781cc2181b3cc0c8378f1b5d1552f183a7c [file] [log] [blame]
Laurent Pinchart9214e2b2019-09-05 03:12:34 +03001/* 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 Pinchart93e72b62020-05-12 00:58:34 +030010#include "libcamera/internal/log.h"
Laurent Pinchart9214e2b2019-09-05 03:12:34 +030011
12using namespace libcamera;
13
Hirokazu Honda6c5792f2020-10-20 18:15:01 +090014LOG_DEFINE_CATEGORY(CameraMetadata)
Laurent Pinchart9214e2b2019-09-05 03:12:34 +030015
Jacopo Mondib9369a02021-01-21 12:50:04 +010016CameraMetadata::CameraMetadata()
17 : metadata_(nullptr), valid_(false)
18{
19}
20
Laurent Pinchart9214e2b2019-09-05 03:12:34 +030021CameraMetadata::CameraMetadata(size_t entryCapacity, size_t dataCapacity)
22{
23 metadata_ = allocate_camera_metadata(entryCapacity, dataCapacity);
24 valid_ = metadata_ != nullptr;
25}
26
Paul Elder5e259602021-01-21 19:15:42 +090027CameraMetadata::CameraMetadata(const camera_metadata_t *metadata)
28{
29 metadata_ = clone_camera_metadata(metadata);
30 valid_ = metadata_ != nullptr;
31}
32
33CameraMetadata::CameraMetadata(const CameraMetadata &other)
34 : CameraMetadata(other.get())
35{
36}
37
Laurent Pinchart9214e2b2019-09-05 03:12:34 +030038CameraMetadata::~CameraMetadata()
39{
40 if (metadata_)
41 free_camera_metadata(metadata_);
42}
43
Paul Elder5e259602021-01-21 19:15:42 +090044CameraMetadata &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
58bool 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 Elder1ff68872021-04-30 17:10:05 +090066/*
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 */
72bool CameraMetadata::resize(size_t count, size_t size)
Laurent Pinchart9214e2b2019-09-05 03:12:34 +030073{
74 if (!valid_)
75 return false;
76
Paul Elder1ff68872021-04-30 17:10:05 +090077 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
112bool 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 Pinchart9214e2b2019-09-05 03:12:34 +0300124 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 Mondi29b59a92020-07-24 14:28:01 +0200140bool 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 Elder1ff68872021-04-30 17:10:05 +0900155 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 Mondi29b59a92020-07-24 14:28:01 +0200165 return false;
166 }
167
Paul Elder1ff68872021-04-30 17:10:05 +0900168 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 Mondi29b59a92020-07-24 14:28:01 +0200180}
181
Laurent Pinchart9214e2b2019-09-05 03:12:34 +0300182camera_metadata_t *CameraMetadata::get()
183{
184 return valid_ ? metadata_ : nullptr;
185}
Jacopo Mondif2d19262020-07-24 13:59:15 +0200186
187const camera_metadata_t *CameraMetadata::get() const
188{
189 return valid_ ? metadata_ : nullptr;
190}