1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "media/capture/video/chromeos/camera_metadata_utils.h"
6
7 #include <algorithm>
8 #include <unordered_set>
9
10 #include "base/containers/span.h"
11
12 namespace media {
13
14 template <>
15 const cros::mojom::EntryType entry_type_of<bool>::value =
16 cros::mojom::EntryType::TYPE_BYTE;
17
18 template <>
19 const cros::mojom::EntryType entry_type_of<uint8_t>::value =
20 cros::mojom::EntryType::TYPE_BYTE;
21
22 template <>
23 const cros::mojom::EntryType entry_type_of<int32_t>::value =
24 cros::mojom::EntryType::TYPE_INT32;
25
26 template <>
27 const cros::mojom::EntryType entry_type_of<float>::value =
28 cros::mojom::EntryType::TYPE_FLOAT;
29
30 template <>
31 const cros::mojom::EntryType entry_type_of<int64_t>::value =
32 cros::mojom::EntryType::TYPE_INT64;
33
34 template <>
35 const cros::mojom::EntryType entry_type_of<double>::value =
36 cros::mojom::EntryType::TYPE_DOUBLE;
37
38 // TODO(shik): support TYPE_RATIONAL
39
GetMetadataEntry(const cros::mojom::CameraMetadataPtr & camera_metadata,cros::mojom::CameraMetadataTag tag)40 cros::mojom::CameraMetadataEntryPtr* GetMetadataEntry(
41 const cros::mojom::CameraMetadataPtr& camera_metadata,
42 cros::mojom::CameraMetadataTag tag) {
43 if (!camera_metadata || !camera_metadata->entries.has_value()) {
44 return nullptr;
45 }
46 // We assume the metadata entries are sorted.
47 auto iter = std::find_if(camera_metadata->entries.value().begin(),
48 camera_metadata->entries.value().end(),
49 [tag](const cros::mojom::CameraMetadataEntryPtr& e) {
50 return e->tag == tag;
51 });
52 if (iter == camera_metadata->entries.value().end()) {
53 return nullptr;
54 }
55
56 auto* entry_ptr = &(camera_metadata->entries.value()[(*iter)->index]);
57 if (!(*entry_ptr)->data.data()) {
58 // Metadata tag found with no valid data.
59 LOG(WARNING) << "Found tag " << static_cast<int>(tag)
60 << " but with invalid data";
61 return nullptr;
62 }
63 return entry_ptr;
64 }
65
AddOrUpdateMetadataEntry(cros::mojom::CameraMetadataPtr * to,cros::mojom::CameraMetadataEntryPtr entry)66 void AddOrUpdateMetadataEntry(cros::mojom::CameraMetadataPtr* to,
67 cros::mojom::CameraMetadataEntryPtr entry) {
68 auto* e = GetMetadataEntry(*to, entry->tag);
69 if (e) {
70 (*to)->data_count += entry->data.size() - (*e)->data.size();
71 (*to)->data_capacity = std::max((*to)->data_capacity, (*to)->data_count);
72 (*e)->count = entry->count;
73 (*e)->data = std::move(entry->data);
74 } else {
75 entry->index = (*to)->entries->size();
76 (*to)->entry_count += 1;
77 (*to)->entry_capacity = std::max((*to)->entry_capacity, (*to)->entry_count);
78 (*to)->data_count += entry->data.size();
79 (*to)->data_capacity = std::max((*to)->data_capacity, (*to)->data_count);
80 if (!(*to)->entries) {
81 (*to)->entries = std::vector<cros::mojom::CameraMetadataEntryPtr>();
82 }
83 (*to)->entries->push_back(std::move(entry));
84 SortCameraMetadata(to);
85 }
86 }
87
SortCameraMetadata(cros::mojom::CameraMetadataPtr * camera_metadata)88 void SortCameraMetadata(cros::mojom::CameraMetadataPtr* camera_metadata) {
89 if (!camera_metadata || !(*camera_metadata) ||
90 !(*camera_metadata)->entries.has_value()) {
91 return;
92 }
93 std::sort((*camera_metadata)->entries.value().begin(),
94 (*camera_metadata)->entries.value().end(),
95 [](const cros::mojom::CameraMetadataEntryPtr& a,
96 const cros::mojom::CameraMetadataEntryPtr& b) {
97 return a->tag < b->tag;
98 });
99 for (size_t i = 0; i < (*camera_metadata)->entries.value().size(); ++i) {
100 (*camera_metadata)->entries.value()[i]->index = i;
101 }
102 }
103
MergeMetadata(cros::mojom::CameraMetadataPtr * to,const cros::mojom::CameraMetadataPtr & from)104 void MergeMetadata(cros::mojom::CameraMetadataPtr* to,
105 const cros::mojom::CameraMetadataPtr& from) {
106 DCHECK(to);
107 (*to)->entry_count += from->entry_count;
108 (*to)->entry_capacity += from->entry_count;
109 (*to)->data_count += from->data_count;
110 (*to)->data_capacity += from->data_count;
111
112 if (!from->entries) {
113 return;
114 }
115
116 std::unordered_set<cros::mojom::CameraMetadataTag> tags;
117 if ((*to)->entries) {
118 for (const auto& entry : (*to)->entries.value()) {
119 tags.insert(entry->tag);
120 }
121 } else {
122 (*to)->entries = std::vector<cros::mojom::CameraMetadataEntryPtr>();
123 }
124 for (const auto& entry : from->entries.value()) {
125 if (tags.find(entry->tag) != tags.end()) {
126 LOG(ERROR) << "Found duplicated entries for tag " << entry->tag;
127 continue;
128 }
129 tags.insert(entry->tag);
130 (*to)->entries->push_back(entry->Clone());
131 }
132 SortCameraMetadata(to);
133 }
134
135 } // namespace media
136