xref: /aosp_15_r20/external/dynamic_depth/internal/dynamic_depth/depth_jpeg.cc (revision a62be0856e8e1158f43b03e41bbad10f4d005fde)
1 #include "dynamic_depth/depth_jpeg.h"
2 
3 #include <fstream>
4 #include <sstream>
5 
6 #include "android-base/logging.h"
7 #include "dynamic_depth/container.h"
8 #include "dynamic_depth/device.h"
9 #include "dynamic_depth/dynamic_depth.h"
10 #include "dynamic_depth/item.h"
11 #include "image_io/gcontainer/gcontainer.h"
12 #include "xmpmeta/xmp_data.h"
13 #include "xmpmeta/xmp_parser.h"
14 #include "xmpmeta/xmp_writer.h"
15 
16 using ::dynamic_depth::xmpmeta::XmpData;
17 
18 namespace dynamic_depth {
19 
ValidateAndroidDynamicDepthBuffer(const char * buffer,size_t buffer_length)20 int32_t ValidateAndroidDynamicDepthBuffer(const char* buffer, size_t buffer_length) {
21   XmpData xmp_data;
22   std::string itemMime("image/jpeg");
23   const string image_data(buffer, buffer_length);
24   ReadXmpFromMemory(image_data, /*XmpSkipExtended*/ false, &xmp_data);
25 
26   // Check device presence
27   std::unique_ptr<Device> device = Device::FromXmp(xmp_data);
28   if (device == nullptr) {
29     LOG(ERROR) << "Dynamic depth device element not present!";
30     return -1;
31   }
32 
33   // Check the container items mime type
34   if ((device->GetContainer() == nullptr) || (device->GetContainer()->GetItems().empty())) {
35     LOG(ERROR) << "No container or container items found!";
36     return -1;
37   }
38   auto items = device->GetContainer()->GetItems();
39   for (const auto& item : items) {
40     if (item->GetMime() != itemMime) {
41       LOG(ERROR) << "Item MIME type doesn't match the expected value: " << itemMime;
42       return -1;
43     }
44   }
45   // Check profiles
46   const Profiles* profiles = device->GetProfiles();
47   if (profiles == nullptr) {
48     LOG(ERROR) << "No Profile found in the dynamic depth metadata";
49     return -1;
50   }
51 
52   const std::vector<const Profile*> profile_list = profiles->GetProfiles();
53   // Stop at the first depth photo profile found.
54   bool depth_photo_profile_found = false;
55   int camera_index = 0;
56   for (auto profile : profile_list) {
57     depth_photo_profile_found = !profile->GetType().compare("DepthPhoto");
58     if (depth_photo_profile_found) {
59       // Use the first one if available.
60       auto indices = profile->GetCameraIndices();
61       if (!indices.empty()) {
62         camera_index = indices[0];
63       } else {
64         camera_index = -1;
65       }
66       break;
67     }
68   }
69 
70   if (!depth_photo_profile_found || camera_index < 0) {
71     LOG(ERROR) << "No dynamic depth profile found";
72     return -1;
73   }
74 
75   auto cameras = device->GetCameras();
76   if (cameras == nullptr || camera_index > cameras->GetCameras().size() ||
77       cameras->GetCameras()[camera_index] == nullptr) {
78     LOG(ERROR) << "No camera or depth photo data found";
79     return -1;
80   }
81 
82   auto camera = cameras->GetCameras()[camera_index];
83   auto depth_map = camera->GetDepthMap();
84   if (depth_map == nullptr) {
85     LOG(ERROR) << "No depth map found";
86     return -1;
87   }
88 
89   auto depth_uri = depth_map->GetDepthUri();
90   if (depth_uri.empty()) {
91     LOG(ERROR) << "Invalid depth map URI";
92     return -1;
93   }
94 
95   auto depth_units = depth_map->GetUnits();
96   if (depth_units != dynamic_depth::DepthUnits::kMeters) {
97     LOG(ERROR) << "Unexpected depth map units";
98     return -1;
99   }
100 
101   auto depth_format = depth_map->GetFormat();
102   if (depth_format != dynamic_depth::DepthFormat::kRangeInverse) {
103     LOG(ERROR) << "Unexpected depth map format";
104     return -1;
105   }
106 
107   auto near = depth_map->GetNear();
108   auto far = depth_map->GetFar();
109   if ((near < 0.f) || (far < 0.f) || (near > far) || (near == far)) {
110     LOG(ERROR) << "Unexpected depth map near and far values";
111     return -1;
112   }
113 
114   auto confidence_uri = depth_map->GetConfidenceUri();
115   if (confidence_uri.empty()) {
116     LOG(ERROR) << "No confidence URI";
117     return -1;
118   }
119 
120   std::istringstream input_jpeg_stream(std::string(buffer, buffer_length));
121   std::string depth_payload;
122   if (!GetItemPayload(device->GetContainer(), depth_uri, input_jpeg_stream, &depth_payload)) {
123     LOG(ERROR) << "Unable to retrieve depth map";
124     return -1;
125   }
126 
127   if (depth_payload.empty()) {
128     LOG(ERROR) << "Invalid depth map";
129     return -1;
130   }
131 
132   return 0;
133 }
134 
135 }  // namespace dynamic_depth
136