summaryrefslogtreecommitdiff
path: root/includes/dynamic_depth/device.h
blob: 39894a41a71c2b489fc1975e06e1a51b5b3f47b9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#ifndef DYNAMIC_DEPTH_INCLUDES_DYNAMIC_DEPTH_DEVICE_H_  // NOLINT
#define DYNAMIC_DEPTH_INCLUDES_DYNAMIC_DEPTH_DEVICE_H_  // NOLINT

#include <libxml/parser.h>
#include <libxml/tree.h>
#include <libxml/xmlmemory.h>
#include <libxml/xpath.h>

#include <memory>
#include <string>
#include <unordered_map>
#include <utility>

#include "dynamic_depth/app_info.h"
#include "dynamic_depth/cameras.h"
#include "dynamic_depth/container.h"
#include "dynamic_depth/earth_pose.h"
#include "dynamic_depth/planes.h"
#include "dynamic_depth/pose.h"
#include "dynamic_depth/profiles.h"
#include "dynamic_depth/vendor_info.h"
#include "xmpmeta/xmp_data.h"

namespace dynamic_depth {

struct DeviceParams {
  // Cameras must be present (i.e. contain at least one camera).
  std::unique_ptr<Cameras> cameras;

  // GContainer. Optional, depending on element presence or user choice.
  std::unique_ptr<Container> container;

  // Optional elements.
  std::unique_ptr<Profiles> profiles;
  std::unique_ptr<Planes> planes;
  std::unique_ptr<EarthPose> earth_pose;
  std::unique_ptr<Pose> pose;
  std::unique_ptr<VendorInfo> vendor_info;
  std::unique_ptr<AppInfo> app_info;

  explicit DeviceParams(std::unique_ptr<Cameras> new_cameras)
      : container(nullptr),
        profiles(nullptr),
        planes(nullptr),
        earth_pose(nullptr),
        pose(nullptr),
        vendor_info(nullptr),
        app_info(nullptr) {
    cameras = std::move(new_cameras);
  }

  inline bool operator==(const DeviceParams& other) const {
    return cameras.get() == other.cameras.get() &&
           container.get() == other.container.get() &&
           profiles.get() == other.profiles.get() &&
           planes.get() == other.planes.get() &&
           earth_pose.get() == other.earth_pose.get() &&
           pose.get() == other.pose.get() &&
           vendor_info.get() == other.vendor_info.get() &&
           app_info.get() == other.app_info.get();
  }

  inline bool operator!=(const DeviceParams& other) const {
    return !(*this == other);
  }
};

// Implements a Device from the Dynamic Depth specification, with serialization
// and deserialization.
// Does not implement the Element interface because Device is at the top level
// in the tree.
class Device {
 public:
  // Creates a Device from the given elements.
  static std::unique_ptr<Device> FromData(std::unique_ptr<DeviceParams> params);

  // Creates a Device from pre-extracted XMP metadata. Returns null if
  // parsing fails. Both the standard and extended XMP sections are required.
  static std::unique_ptr<Device> FromXmp(
      const ::dynamic_depth::xmpmeta::XmpData& xmp);

  // Creates a Device by extracting XMP metadata from a JPEG and parsing it.
  // If using XMP for other things as well, FromXmp() should be used instead to
  // prevent redundant extraction of XMP from the JPEG.
  static std::unique_ptr<Device> FromJpegFile(const string& filename);

  // Creates a Device by parsing XML file containing the metadata.
  static std::unique_ptr<Device> FromXmlFile(const string& filename);

  // Getters.
  // May return null values for optional fields.
  const Cameras* GetCameras() const;
  const Container* GetContainer() const;
  const EarthPose* GetEarthPose() const;
  const Pose* GetPose() const;
  const Planes* GetPlanes() const;
  const Profiles* GetProfiles() const;
  const VendorInfo* GetVendorInfo() const;
  const AppInfo* GetAppInfo() const;

  // Not const for XML memory management reasons. More info in source comments.
  bool SerializeToXmp(::dynamic_depth::xmpmeta::XmpData* xmp);

  // Saves Device metadata to a .xml file.
  bool SerializeToXmlFile(const char* filename);

  // Disallow copying.
  Device(const Device&) = delete;
  void operator=(const Device&) = delete;

 private:
  explicit Device(std::unique_ptr<DeviceParams> params);

  // Retrieves the namespaces of all child elements.
  void GetNamespaces(
      std::unordered_map<string, string>* ns_name_href_map) const;
  // Gathers all the XML namespaces of child elements.
  void PopulateNamespaces();
  bool Serialize(xmlDocPtr* xmlDoc);

  // Keep a reference to the XML namespaces, so that they are created only once
  // when Device is constructed.
  std::unordered_map<string, xmlNsPtr> namespaces_;

  std::unique_ptr<DeviceParams> params_;
};

}  // namespace dynamic_depth

#endif  // DYNAMIC_DEPTH_INCLUDES_DYNAMIC_DEPTH_DEVICE_H_  // NOLINT