summaryrefslogtreecommitdiff
path: root/internal/dynamic_depth/depth_jpeg.cc
blob: af2ead97b15d2296c569874f9003538f75f93150 (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
131
132
133
134
135
#include "dynamic_depth/depth_jpeg.h"

#include <fstream>
#include <sstream>

#include "android-base/logging.h"
#include "dynamic_depth/container.h"
#include "dynamic_depth/device.h"
#include "dynamic_depth/dynamic_depth.h"
#include "dynamic_depth/item.h"
#include "image_io/gcontainer/gcontainer.h"
#include "xmpmeta/xmp_data.h"
#include "xmpmeta/xmp_parser.h"
#include "xmpmeta/xmp_writer.h"

using ::dynamic_depth::xmpmeta::XmpData;

namespace dynamic_depth {

int32_t ValidateAndroidDynamicDepthBuffer(const char* buffer, size_t buffer_length) {
  XmpData xmp_data;
  std::string itemMime("image/jpeg");
  const string image_data(buffer, buffer_length);
  ReadXmpFromMemory(image_data, /*XmpSkipExtended*/ false, &xmp_data);

  // Check device presence
  std::unique_ptr<Device> device = Device::FromXmp(xmp_data);
  if (device == nullptr) {
    LOG(ERROR) << "Dynamic depth device element not present!";
    return -1;
  }

  // Check the container items mime type
  if ((device->GetContainer() == nullptr) || (device->GetContainer()->GetItems().empty())) {
    LOG(ERROR) << "No container or container items found!";
    return -1;
  }
  auto items = device->GetContainer()->GetItems();
  for (const auto& item : items) {
    if (item->GetMime() != itemMime) {
      LOG(ERROR) << "Item MIME type doesn't match the expected value: " << itemMime;
      return -1;
    }
  }
  // Check profiles
  const Profiles* profiles = device->GetProfiles();
  if (profiles == nullptr) {
    LOG(ERROR) << "No Profile found in the dynamic depth metadata";
    return -1;
  }

  const std::vector<const Profile*> profile_list = profiles->GetProfiles();
  // Stop at the first depth photo profile found.
  bool depth_photo_profile_found = false;
  int camera_index = 0;
  for (auto profile : profile_list) {
    depth_photo_profile_found = !profile->GetType().compare("DepthPhoto");
    if (depth_photo_profile_found) {
      // Use the first one if available.
      auto indices = profile->GetCameraIndices();
      if (!indices.empty()) {
        camera_index = indices[0];
      } else {
        camera_index = -1;
      }
      break;
    }
  }

  if (!depth_photo_profile_found || camera_index < 0) {
    LOG(ERROR) << "No dynamic depth profile found";
    return -1;
  }

  auto cameras = device->GetCameras();
  if (cameras == nullptr || camera_index > cameras->GetCameras().size() ||
      cameras->GetCameras()[camera_index] == nullptr) {
    LOG(ERROR) << "No camera or depth photo data found";
    return -1;
  }

  auto camera = cameras->GetCameras()[camera_index];
  auto depth_map = camera->GetDepthMap();
  if (depth_map == nullptr) {
    LOG(ERROR) << "No depth map found";
    return -1;
  }

  auto depth_uri = depth_map->GetDepthUri();
  if (depth_uri.empty()) {
    LOG(ERROR) << "Invalid depth map URI";
    return -1;
  }

  auto depth_units = depth_map->GetUnits();
  if (depth_units != dynamic_depth::DepthUnits::kMeters) {
    LOG(ERROR) << "Unexpected depth map units";
    return -1;
  }

  auto depth_format = depth_map->GetFormat();
  if (depth_format != dynamic_depth::DepthFormat::kRangeInverse) {
    LOG(ERROR) << "Unexpected depth map format";
    return -1;
  }

  auto near = depth_map->GetNear();
  auto far = depth_map->GetFar();
  if ((near < 0.f) || (far < 0.f) || (near > far) || (near == far)) {
    LOG(ERROR) << "Unexpected depth map near and far values";
    return -1;
  }

  auto confidence_uri = depth_map->GetConfidenceUri();
  if (confidence_uri.empty()) {
    LOG(ERROR) << "No confidence URI";
    return -1;
  }

  std::istringstream input_jpeg_stream(std::string(buffer, buffer_length));
  std::string depth_payload;
  if (!GetItemPayload(device->GetContainer(), depth_uri, input_jpeg_stream, &depth_payload)) {
    LOG(ERROR) << "Unable to retrieve depth map";
    return -1;
  }

  if (depth_payload.empty()) {
    LOG(ERROR) << "Invalid depth map";
    return -1;
  }

  return 0;
}

}  // namespace dynamic_depth