1 #include "dynamic_depth/profile.h"
2
3 #include "android-base/logging.h"
4 #include "dynamic_depth/const.h"
5
6 using ::dynamic_depth::xmpmeta::xml::Deserializer;
7 using ::dynamic_depth::xmpmeta::xml::Serializer;
8
9 namespace dynamic_depth {
10 namespace {
11
12 const char kType[] = "Type";
13 const char kCameraIndices[] = "CameraIndices";
14
15 const char kNamespaceHref[] = "http://ns.google.com/photos/dd/1.0/profile/";
16
17 // Profile type names.
18 constexpr char kArPhoto[] = "ARPhoto";
19 constexpr char kArPhotoLowercase[] = "arphoto";
20 constexpr char kDepthPhoto[] = "DepthPhoto";
21 constexpr char kDepthPhotoLowercase[] = "depthphoto";
22
23 // Profile camera indices' sizes.
24 constexpr size_t kArPhotoIndicesSize = 1;
25 constexpr size_t kDepthPhotoIndicesSize = 1;
26
27 // Returns true if the type is unsupported, or if the type is supported in the
28 // Dynamic Depth Profile element and the size of the camera indices matches that
29 // specified in the spec.
ValidateKnownTypeAndIndices(const string & type,size_t camera_indices_size,string * matched_type)30 bool ValidateKnownTypeAndIndices(const string& type, size_t camera_indices_size,
31 string* matched_type) {
32 string type_lower = type;
33 std::transform(type_lower.begin(), type_lower.end(), type_lower.begin(),
34 ::tolower);
35 bool isArPhoto = (kArPhotoLowercase == type_lower);
36 bool isDepthPhoto = (kDepthPhotoLowercase == type_lower);
37 if (!isArPhoto && !isDepthPhoto) {
38 return true;
39 }
40 bool matches =
41 (isArPhoto && camera_indices_size >= kArPhotoIndicesSize) ||
42 (isDepthPhoto && camera_indices_size >= kDepthPhotoIndicesSize);
43 if (!matches) {
44 LOG(WARNING) << "Size of camera indices for "
45 << (isArPhoto ? kArPhoto : kDepthPhoto) << " must be at least "
46 << (isArPhoto ? kArPhotoIndicesSize : kDepthPhotoIndicesSize);
47 } else {
48 *matched_type = isArPhoto ? kArPhoto : kDepthPhoto;
49 }
50
51 return matches;
52 }
53
54 } // namespace
55
56 // Private constructor.
Profile(const string & type,const std::vector<int> & camera_indices)57 Profile::Profile(const string& type, const std::vector<int>& camera_indices)
58 : type_(type), camera_indices_(camera_indices) {}
59
60 // Public methods.
GetNamespaces(std::unordered_map<string,string> * ns_name_href_map)61 void Profile::GetNamespaces(
62 std::unordered_map<string, string>* ns_name_href_map) {
63 if (ns_name_href_map == nullptr) {
64 LOG(ERROR) << "Namespace list or own namespace is null";
65 return;
66 }
67 ns_name_href_map->emplace(DynamicDepthConst::Profile(), kNamespaceHref);
68 }
69
FromData(const string & type,const std::vector<int> & camera_indices)70 std::unique_ptr<Profile> Profile::FromData(
71 const string& type, const std::vector<int>& camera_indices) {
72 if (type.empty()) {
73 LOG(ERROR) << "Profile must have a type";
74 return nullptr;
75 }
76 // Check that the camera indices' length is at least the size of that
77 // specified for the type. This has no restrictions on unsupported profile
78 // types.
79 // Ensure also that a consistent case-sensitive profile is stored, even if the
80 // caller provided a case-insensitive name.
81 string matched_type;
82 if (!ValidateKnownTypeAndIndices(type, camera_indices.size(),
83 &matched_type)) {
84 return nullptr;
85 }
86
87 return std::unique_ptr<Profile>(
88 new Profile(matched_type.empty() ? type :
89 matched_type, camera_indices)); // NOLINT
90 }
91
FromDeserializer(const Deserializer & parent_deserializer)92 std::unique_ptr<Profile> Profile::FromDeserializer(
93 const Deserializer& parent_deserializer) {
94 std::unique_ptr<Deserializer> deserializer =
95 parent_deserializer.CreateDeserializer(
96 DynamicDepthConst::Namespace(DynamicDepthConst::Profile()),
97 DynamicDepthConst::Profile());
98 if (deserializer == nullptr) {
99 return nullptr;
100 }
101 std::unique_ptr<Profile> profile(new Profile("", {}));
102 if (!deserializer->ParseString(DynamicDepthConst::Profile(), kType,
103 &profile->type_)) {
104 return nullptr;
105 }
106 deserializer->ParseIntArray(DynamicDepthConst::Profile(), kCameraIndices,
107 &profile->camera_indices_);
108 if (!ValidateKnownTypeAndIndices(
109 profile->type_, profile->camera_indices_.size(), &profile->type_)) {
110 return nullptr;
111 }
112 return profile;
113 }
114
GetType() const115 const string& Profile::GetType() const { return type_; }
116
GetCameraIndices() const117 const std::vector<int>& Profile::GetCameraIndices() const {
118 return camera_indices_;
119 }
120
Serialize(Serializer * serializer) const121 bool Profile::Serialize(Serializer* serializer) const {
122 if (serializer == nullptr) {
123 LOG(ERROR) << "Serializer is null";
124 return false;
125 }
126 if (!serializer->WriteProperty(DynamicDepthConst::Profile(), kType, type_)) {
127 return false;
128 }
129 if (camera_indices_.empty()) {
130 return true;
131 }
132 return serializer->WriteIntArray(DynamicDepthConst::Profile(), kCameraIndices,
133 camera_indices_);
134 }
135
136 } // namespace dynamic_depth
137