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