blob: 0dd62262d82b390dc4dcc29016addea879c31462 [file] [log] [blame]
Haoxiang Li0c078242020-06-10 16:59:29 -07001/*
2 * Copyright 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "CameraUtils.h"
18
19#include <android-base/logging.h>
20#include <android/hardware/automotive/evs/1.1/types.h>
21
Haoxiang Lia9d23d12020-06-13 18:09:13 -070022#include <math.h>
23
Haoxiang Li0c078242020-06-10 16:59:29 -070024using namespace android::hardware::automotive::evs::V1_1;
25
26using ::android::sp;
27using ::std::string;
28using ::std::vector;
Haoxiang Lia9d23d12020-06-13 18:09:13 -070029using ::std::map;
Haoxiang Li0c078242020-06-10 16:59:29 -070030
31namespace android {
32namespace hardware {
33namespace automotive {
34namespace sv {
35namespace V1_0 {
36namespace implementation {
37
38bool isLogicalCamera(const camera_metadata_t* metadata) {
39 if (metadata == nullptr) {
40 // A logical camera device must have a valid camera metadata.
41 return false;
42 }
43
44 // Looking for LOGICAL_MULTI_CAMERA capability from metadata.
45 camera_metadata_ro_entry_t entry;
46 int rc =
47 find_camera_metadata_ro_entry(metadata,
48 ANDROID_REQUEST_AVAILABLE_CAPABILITIES,
49 &entry);
50 if (0 != rc) {
51 // No capabilities are found.
52 return false;
53 }
54
55 for (size_t i = 0; i < entry.count; ++i) {
56 uint8_t cap = entry.data.u8[i];
57 if (cap ==
58 ANDROID_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA) {
59 return true;
60 }
61 }
62
63 return false;
64}
65
66vector<string> getPhysicalCameraIds(sp<IEvsCamera> camera) {
67 if (camera == nullptr) {
68 LOG(WARNING) << __FUNCTION__ << "The EVS camera object is invalid";
69 return {};
70 }
71
72 CameraDesc desc;
73 camera->getCameraInfo_1_1([&desc](const CameraDesc& info) {
74 desc = info;
75 });
76
77 vector<string> physicalCameras;
78 const camera_metadata_t* metadata =
79 reinterpret_cast<camera_metadata_t*>(&desc.metadata[0]);
80
81 if (!isLogicalCamera(metadata)) {
82 // EVS assumes that the device w/o a valid metadata is a physical
83 // device.
84 LOG(INFO) << desc.v1.cameraId << " is not a logical camera device.";
85 physicalCameras.emplace_back(desc.v1.cameraId);
86 return physicalCameras;
87 }
88
89 // Look for physical camera identifiers
90 camera_metadata_ro_entry entry;
91 int rc =
92 find_camera_metadata_ro_entry(metadata,
93 ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS,
94 &entry);
95 if (rc != 0) {
96 LOG(ERROR) << "No physical camera ID is found for "
97 << desc.v1.cameraId;
98 return {};
99 }
100
101 const uint8_t* ids = entry.data.u8;
102 size_t start = 0;
103 for (size_t i = 0; i < entry.count; ++i) {
104 if (ids[i] == '\0') {
105 if (start != i) {
106 string id(reinterpret_cast<const char*>(ids + start));
107 physicalCameras.emplace_back(id);
108 }
109 start = i + 1;
110 }
111 }
112
113 LOG(INFO) << desc.v1.cameraId << " consists of " << physicalCameras.size()
114 << " physical camera devices";
115 return physicalCameras;
116}
117
118string tagToString(uint32_t tag) {
119 switch (tag) {
120 case ANDROID_LENS_DISTORTION:
121 return "ANDROID_LENS_DISTORTION";
122 case ANDROID_LENS_INTRINSIC_CALIBRATION:
123 return "ANDROID_LENS_INTRINSIC_CALIBRATION";
124 case ANDROID_LENS_POSE_TRANSLATION:
125 return "ANDROID_LENS_POSE_TRANSLATION";
126 case ANDROID_LENS_POSE_ROTATION:
127 return "ANDROID_LENS_POSE_ROTATION";
128 default:
129 LOG(WARNING) << "Cannot recognize the tag: " << tag;
130 return {};
131 }
132}
133
134bool getParam(const camera_metadata_t* metadata,
135 uint32_t tag,
136 int size,
137 float* param) {
138 camera_metadata_ro_entry_t entry = camera_metadata_ro_entry_t();
139 int rc = find_camera_metadata_ro_entry(metadata, tag, &entry);
140
141 if (rc != 0) {
142 LOG(ERROR) << "No metadata found for " << tagToString(tag);
143 return false;
144 }
145
146 if (entry.count != size || entry.type != TYPE_FLOAT) {
147 LOG(ERROR) << "Unexpected size or type for " << tagToString(tag);
148 return false;
149 }
150
151 const float* lensParam = entry.data.f;
152 for (int i = 0; i < size; i++) {
153 param[i] = lensParam[i];
154 }
155 return true;
156}
157
158bool getAndroidCameraParams(sp<IEvsCamera> camera,
Haoxiang Lia9d23d12020-06-13 18:09:13 -0700159 const string& cameraId,
Haoxiang Li0c078242020-06-10 16:59:29 -0700160 AndroidCameraParams& params) {
161 if (camera == nullptr) {
162 LOG(WARNING) << __FUNCTION__ << "The EVS camera object is invalid";
163 return {};
164 }
165
166 CameraDesc desc = {};
167 camera->getPhysicalCameraInfo(cameraId, [&desc](const CameraDesc& info) {
168 desc = info;
169 });
170
171 if (desc.metadata.size() == 0) {
172 LOG(ERROR) << "No metadata found for " << desc.v1.cameraId;
173 return false;
174 }
175
176 const camera_metadata_t* metadata =
177 reinterpret_cast<camera_metadata_t*>(&desc.metadata[0]);
178
179 // Look for ANDROID_LENS_DISTORTION
180 if (!getParam(metadata,
181 ANDROID_LENS_DISTORTION,
182 kSizeLensDistortion,
183 &params.lensDistortion[0])) {
184 return false;
185 }
186
187 // Look for ANDROID_LENS_INTRINSIC_CALIBRATION
188 if (!getParam(metadata,
189 ANDROID_LENS_INTRINSIC_CALIBRATION,
190 kSizeLensIntrinsicCalibration,
191 &params.lensIntrinsicCalibration[0])) {
192 return false;
193 }
194
195 // Look for ANDROID_LENS_POSE_TRANSLATION
196 if (!getParam(metadata,
197 ANDROID_LENS_POSE_TRANSLATION,
198 kSizeLensPoseTranslation,
199 &params.lensPoseTranslation[0])) {
200 return false;
201 }
202
203 // Look for ANDROID_LENS_POSE_ROTATION
204 if (!getParam(metadata,
205 ANDROID_LENS_POSE_ROTATION,
206 kSizeLensPoseRotation,
207 &params.lensPoseRotation[0])) {
208 return false;
209 }
210
211 return true;
212}
213
Haoxiang Lia9d23d12020-06-13 18:09:13 -0700214vector<SurroundViewCameraParams> convertToSurroundViewCameraParams(
215 const map<string, AndroidCameraParams>& androidCameraParamsMap) {
216 vector<SurroundViewCameraParams> result;
217
218 // TODO(b/156101189): the cameras are in random order now. They need to be
219 // sorted based on the camera position info from config file.
220 for (const auto& entry : androidCameraParamsMap) {
221 SurroundViewCameraParams svParams;
222
223 // Android Camera format for intrinsics: [f_x, f_y, c_x, c_y, s]
224 //
225 // To corelib:
226 // SurroundViewCameraParams.intrinsics =
227 // [ f_x, s, c_x,
228 // 0, f_y, c_y,
229 // 0, 0, 1 ];
230 const float* intrinsics = &entry.second.lensIntrinsicCalibration[0];
231 svParams.intrinsics[0] = intrinsics[0];
232 svParams.intrinsics[1] = intrinsics[4];
233 svParams.intrinsics[2] = intrinsics[2];
234 svParams.intrinsics[3] = 0;
235 svParams.intrinsics[4] = intrinsics[1];
236 svParams.intrinsics[5] = intrinsics[3];
237 svParams.intrinsics[6] = 0;
238 svParams.intrinsics[7] = 0;
239 svParams.intrinsics[8] = 1;
240
241 // Android Camera format for lens distortion:
242 // Radial: [kappa_1, kappa_2, kappa_3]
243 // Tangential: [kappa_4, kappa_5]
244 //
245 // To corelib:
246 // SurroundViewCameraParams.distortion =
247 // [kappa_1, kappa_2, kappa_3, kappa_4];
248 const float* distortion = &entry.second.lensDistortion[0];
249 svParams.distorion[0] = distortion[0];
250 svParams.distorion[1] = distortion[1];
251 svParams.distorion[2] = distortion[2];
252 svParams.distorion[3] = distortion[3];
253
254 // Android Camera format for rotation:
255 // quaternion coefficients (x,y,z,w)
256 //
257 // To corelib:
258 // theta = 2 * acos(w)
259 // a_x = x / sin(theta/2)
260 // a_y = y / sin(theta/2)
261 // a_z = z / sin(theta/2)
262 // SurroundViewCameraParams.rvec =
263 // [theta * a_x, theta * a_y, theta * a_z];
264 const float* rotation = &entry.second.lensPoseRotation[0];
265 const float theta = 2 * acos(rotation[3]);
266 const float a_x = rotation[0] / sin(theta / 2);
267 const float a_y = rotation[1] / sin(theta / 2);
268 const float a_z = rotation[2] / sin(theta / 2);
269 svParams.rvec[0] = theta * a_x;
270 svParams.rvec[1] = theta * a_y;
271 svParams.rvec[2] = theta * a_z;
272
273 // Android Camera format for translation: Translation = (x,y,z)
274 //
275 // To corelib:
276 // SurroundViewCameraParams.tvec = [x, y, z];
277 const float* translation = &entry.second.lensPoseTranslation[0];
278 svParams.tvec[0] = translation[0];
279 svParams.tvec[1] = translation[1];
280 svParams.tvec[2] = translation[2];
281
282 LOG(INFO) << "Camera parameters for " << entry.first
283 << " have been converted to SV core lib format successfully";
284 result.emplace_back(svParams);
285 }
286
287 return result;
288}
289
Haoxiang Li0c078242020-06-10 16:59:29 -0700290} // namespace implementation
291} // namespace V1_0
292} // namespace sv
293} // namespace automotive
294} // namespace hardware
295} // namespace android
296