blob: b027bbbee6e26199e6a79c58f74ec2886409a054 [file] [log] [blame]
Changyeon Joaab96aa2019-10-12 05:24:15 -07001/*
2 * Copyright (C) 2019 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 <sstream>
18#include <fstream>
19#include <thread>
20
21#include <hardware/gralloc.h>
22#include <utils/SystemClock.h>
23#include <android/hardware/camera/device/3.2/ICameraDevice.h>
24
25#include "ConfigManager.h"
26
27using ::android::hardware::camera::device::V3_2::StreamRotation;
28
29
30ConfigManager::~ConfigManager() {
31 /* Nothing to do */
32}
33
34
35void ConfigManager::printElementNames(const XMLElement *rootElem,
36 string prefix) const {
37 const XMLElement *curElem = rootElem;
38
39 while (curElem != nullptr) {
Changyeon Joffdf3db2020-03-06 15:23:02 -080040 LOG(VERBOSE) << "[ELEM] " << prefix << curElem->Name();
Changyeon Joaab96aa2019-10-12 05:24:15 -070041 const XMLAttribute *curAttr = curElem->FirstAttribute();
42 while (curAttr) {
Changyeon Joffdf3db2020-03-06 15:23:02 -080043 LOG(VERBOSE) << "[ATTR] " << prefix << curAttr->Name() << ": " << curAttr->Value();
Changyeon Joaab96aa2019-10-12 05:24:15 -070044 curAttr = curAttr->Next();
45 }
46
47 /* recursively go down to descendants */
48 printElementNames(curElem->FirstChildElement(), prefix + "\t");
49
50 curElem = curElem->NextSiblingElement();
51 }
52}
53
54
55void ConfigManager::readCameraInfo(const XMLElement * const aCameraElem) {
56 if (aCameraElem == nullptr) {
Changyeon Joffdf3db2020-03-06 15:23:02 -080057 LOG(WARNING) << "XML file does not have required camera element";
Changyeon Joaab96aa2019-10-12 05:24:15 -070058 return;
59 }
60
61 const XMLElement *curElem = aCameraElem->FirstChildElement();
62 while (curElem != nullptr) {
63 if (!strcmp(curElem->Name(), "group")) {
64 /* camera group identifier */
Changyeon Jo4ede4d62019-10-22 10:10:15 -070065 const char *id = curElem->FindAttribute("id")->Value();
Changyeon Joaab96aa2019-10-12 05:24:15 -070066
Changyeon Jo4ede4d62019-10-22 10:10:15 -070067 /* create a camera group to be filled */
68 CameraGroupInfo *aCamera = new CameraGroupInfo();
Changyeon Joaab96aa2019-10-12 05:24:15 -070069
Changyeon Jo4ede4d62019-10-22 10:10:15 -070070 /* read camera device information */
71 if (!readCameraDeviceInfo(aCamera, curElem)) {
Changyeon Joffdf3db2020-03-06 15:23:02 -080072 LOG(WARNING) << "Failed to read a camera information of " << id;
Changyeon Jo4ede4d62019-10-22 10:10:15 -070073 delete aCamera;
74 continue;
Changyeon Joaab96aa2019-10-12 05:24:15 -070075 }
76
77 /* camera group synchronization */
78 const char *sync = curElem->FindAttribute("synchronized")->Value();
Changyeon Jo4ede4d62019-10-22 10:10:15 -070079 if (!strcmp(sync, "CALIBRATED")) {
80 aCamera->synchronized =
81 ANDROID_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE_CALIBRATED;
82 } else if (!strcmp(sync, "APPROXIMATE")) {
83 aCamera->synchronized =
84 ANDROID_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE_APPROXIMATE;
85 } else {
86 aCamera->synchronized = 0; // Not synchronized
87 }
Changyeon Joaab96aa2019-10-12 05:24:15 -070088
89 /* add a group to hash map */
Changyeon Jo4ede4d62019-10-22 10:10:15 -070090 mCameraGroups.insert_or_assign(id, unique_ptr<CameraGroupInfo>(aCamera));
Changyeon Joaab96aa2019-10-12 05:24:15 -070091 } else if (!strcmp(curElem->Name(), "device")) {
92 /* camera unique identifier */
93 const char *id = curElem->FindAttribute("id")->Value();
94
95 /* camera mount location */
96 const char *pos = curElem->FindAttribute("position")->Value();
97
Changyeon Jo4ede4d62019-10-22 10:10:15 -070098 /* create a camera device to be filled */
99 CameraInfo *aCamera = new CameraInfo();
100
101 /* read camera device information */
102 if (!readCameraDeviceInfo(aCamera, curElem)) {
Changyeon Joffdf3db2020-03-06 15:23:02 -0800103 LOG(WARNING) << "Failed to read a camera information of " << id;
Changyeon Jo4ede4d62019-10-22 10:10:15 -0700104 delete aCamera;
105 continue;
106 }
107
Changyeon Joaab96aa2019-10-12 05:24:15 -0700108 /* store read camera module information */
Changyeon Jo4ede4d62019-10-22 10:10:15 -0700109 mCameraInfo.insert_or_assign(id, unique_ptr<CameraInfo>(aCamera));
Changyeon Joaab96aa2019-10-12 05:24:15 -0700110
111 /* assign a camera device to a position group */
112 mCameraPosition[pos].emplace(id);
113 } else {
114 /* ignore other device types */
Changyeon Joffdf3db2020-03-06 15:23:02 -0800115 LOG(DEBUG) << "Unknown element " << curElem->Name() << " is ignored";
Changyeon Joaab96aa2019-10-12 05:24:15 -0700116 }
117
118 curElem = curElem->NextSiblingElement();
119 }
120}
121
122
Changyeon Jo4ede4d62019-10-22 10:10:15 -0700123bool
124ConfigManager::readCameraDeviceInfo(CameraInfo *aCamera,
125 const XMLElement *aDeviceElem) {
126 if (aCamera == nullptr || aDeviceElem == nullptr) {
127 return false;
Changyeon Joaab96aa2019-10-12 05:24:15 -0700128 }
129
Changyeon Joaab96aa2019-10-12 05:24:15 -0700130 /* size information to allocate camera_metadata_t */
131 size_t totalEntries = 0;
132 size_t totalDataSize = 0;
133
134 /* read device capabilities */
135 totalEntries +=
136 readCameraCapabilities(aDeviceElem->FirstChildElement("caps"),
137 aCamera,
138 totalDataSize);
139
140
141 /* read camera metadata */
142 totalEntries +=
143 readCameraMetadata(aDeviceElem->FirstChildElement("characteristics"),
144 aCamera,
145 totalDataSize);
146
147 /* construct camera_metadata_t */
148 if (!constructCameraMetadata(aCamera, totalEntries, totalDataSize)) {
Changyeon Joffdf3db2020-03-06 15:23:02 -0800149 LOG(WARNING) << "Either failed to allocate memory or "
150 << "allocated memory was not large enough";
Changyeon Joaab96aa2019-10-12 05:24:15 -0700151 }
152
Changyeon Jo4ede4d62019-10-22 10:10:15 -0700153 return true;
Changyeon Joaab96aa2019-10-12 05:24:15 -0700154}
155
156
Changyeon Jo4ede4d62019-10-22 10:10:15 -0700157size_t
158ConfigManager::readCameraCapabilities(const XMLElement * const aCapElem,
159 CameraInfo *aCamera,
160 size_t &dataSize) {
161 if (aCapElem == nullptr || aCamera == nullptr) {
Changyeon Joaab96aa2019-10-12 05:24:15 -0700162 return 0;
163 }
164
165 string token;
166 const XMLElement *curElem = nullptr;
167
168 /* a list of supported camera parameters/controls */
169 curElem = aCapElem->FirstChildElement("supported_controls");
170 if (curElem != nullptr) {
171 const XMLElement *ctrlElem = curElem->FirstChildElement("control");
172 while (ctrlElem != nullptr) {
173 const char *nameAttr = ctrlElem->FindAttribute("name")->Value();;
174 const int32_t minVal = stoi(ctrlElem->FindAttribute("min")->Value());
175 const int32_t maxVal = stoi(ctrlElem->FindAttribute("max")->Value());
176
177 int32_t stepVal = 1;
178 const XMLAttribute *stepAttr = ctrlElem->FindAttribute("step");
179 if (stepAttr != nullptr) {
180 stepVal = stoi(stepAttr->Value());
181 }
182
183 CameraParam aParam;
184 if (ConfigManagerUtil::convertToEvsCameraParam(nameAttr,
185 aParam)) {
186 aCamera->controls.emplace(
187 aParam,
188 make_tuple(minVal, maxVal, stepVal)
189 );
190 }
191
192 ctrlElem = ctrlElem->NextSiblingElement("control");
193 }
194 }
195
196 /* a list of camera stream configurations */
197 curElem = aCapElem->FirstChildElement("stream");
198 while (curElem != nullptr) {
199 /* read 5 attributes */
200 const XMLAttribute *idAttr = curElem->FindAttribute("id");
201 const XMLAttribute *widthAttr = curElem->FindAttribute("width");
202 const XMLAttribute *heightAttr = curElem->FindAttribute("height");
203 const XMLAttribute *fmtAttr = curElem->FindAttribute("format");
204 const XMLAttribute *fpsAttr = curElem->FindAttribute("framerate");
205
206 const int32_t id = stoi(idAttr->Value());
207 int32_t framerate = 0;
208 if (fpsAttr != nullptr) {
209 framerate = stoi(fpsAttr->Value());
210 }
211
212 int32_t pixFormat;
213 if (ConfigManagerUtil::convertToPixelFormat(fmtAttr->Value(),
214 pixFormat)) {
215 RawStreamConfiguration cfg = {
216 id,
217 stoi(widthAttr->Value()),
218 stoi(heightAttr->Value()),
219 pixFormat,
220 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
221 framerate
222 };
Changyeon Jo67657b92019-11-07 11:21:29 -0800223 aCamera->streamConfigurations.insert_or_assign(id, cfg);
Changyeon Joaab96aa2019-10-12 05:24:15 -0700224 }
225
226 curElem = curElem->NextSiblingElement("stream");
227 }
228
229 dataSize = calculate_camera_metadata_entry_data_size(
230 get_camera_metadata_tag_type(
231 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS
232 ),
233 aCamera->streamConfigurations.size() * kStreamCfgSz
234 );
235
236 /* a single camera metadata entry contains multiple stream configurations */
237 return dataSize > 0 ? 1 : 0;
238}
239
240
Changyeon Jo4ede4d62019-10-22 10:10:15 -0700241size_t
242ConfigManager::readCameraMetadata(const XMLElement * const aParamElem,
243 CameraInfo *aCamera,
244 size_t &dataSize) {
245 if (aParamElem == nullptr || aCamera == nullptr) {
Changyeon Joaab96aa2019-10-12 05:24:15 -0700246 return 0;
247 }
248
249 const XMLElement *curElem = aParamElem->FirstChildElement("parameter");
250 size_t numEntries = 0;
251 camera_metadata_tag_t tag;
252 while (curElem != nullptr) {
Changyeon Jo035219e2019-11-26 18:25:04 -0800253 if (ConfigManagerUtil::convertToMetadataTag(curElem->FindAttribute("name")->Value(),
254 tag)) {
Changyeon Joaab96aa2019-10-12 05:24:15 -0700255 switch(tag) {
256 case ANDROID_LENS_DISTORTION:
257 case ANDROID_LENS_POSE_ROTATION:
258 case ANDROID_LENS_POSE_TRANSLATION:
259 case ANDROID_LENS_INTRINSIC_CALIBRATION: {
260 /* float[] */
261 size_t count = 0;
262 void *data = ConfigManagerUtil::convertFloatArray(
263 curElem->FindAttribute("size")->Value(),
264 curElem->FindAttribute("value")->Value(),
265 count
266 );
267
Changyeon Jo67657b92019-11-07 11:21:29 -0800268 aCamera->cameraMetadata.insert_or_assign(
Changyeon Job927b882019-11-21 10:16:33 -0800269 tag, make_pair(data, count)
Changyeon Jo67657b92019-11-07 11:21:29 -0800270 );
Changyeon Joaab96aa2019-10-12 05:24:15 -0700271
272 ++numEntries;
273 dataSize += calculate_camera_metadata_entry_data_size(
274 get_camera_metadata_tag_type(tag), count
275 );
276
277 break;
278 }
279
Changyeon Jo4ede4d62019-10-22 10:10:15 -0700280 case ANDROID_REQUEST_AVAILABLE_CAPABILITIES: {
281 camera_metadata_enum_android_request_available_capabilities_t *data =
282 new camera_metadata_enum_android_request_available_capabilities_t[1];
283 if (ConfigManagerUtil::convertToCameraCapability(
Changyeon Jo035219e2019-11-26 18:25:04 -0800284 curElem->FindAttribute("value")->Value(),
Changyeon Jo4ede4d62019-10-22 10:10:15 -0700285 *data)
286 ) {
287 aCamera->cameraMetadata.insert_or_assign(
Changyeon Job927b882019-11-21 10:16:33 -0800288 tag, make_pair((void *)data, 1)
Changyeon Jo4ede4d62019-10-22 10:10:15 -0700289 );
290
291 ++numEntries;
292 dataSize += calculate_camera_metadata_entry_data_size(
293 get_camera_metadata_tag_type(tag), 1
294 );
295 }
296 break;
297 }
298
299 case ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS: {
300 /* a comma-separated list of physical camera devices */
301 size_t len = strlen(curElem->FindAttribute("value")->Value());
302 char *data = new char[len + 1];
303 memcpy(data,
304 curElem->FindAttribute("value")->Value(),
305 len * sizeof(char));
306
307 /* replace commas with null char */
308 char *p = data;
309 while (*p != '\0') {
310 if (*p == ',') {
311 *p = '\0';
312 }
313 ++p;
314 }
315
316 aCamera->cameraMetadata.insert_or_assign(
Changyeon Jo035219e2019-11-26 18:25:04 -0800317 tag, make_pair((void *)data, len + 1)
Changyeon Jo4ede4d62019-10-22 10:10:15 -0700318 );
319
320 ++numEntries;
321 dataSize += calculate_camera_metadata_entry_data_size(
322 get_camera_metadata_tag_type(tag), len
323 );
324 break;
325 }
326
327
Changyeon Joaab96aa2019-10-12 05:24:15 -0700328 /* TODO(b/140416878): add vendor-defined/custom tag support */
329
330 default:
Changyeon Joffdf3db2020-03-06 15:23:02 -0800331 LOG(WARNING) << "Parameter "
332 << curElem->FindAttribute("name")->Value()
333 << " is not supported";
Changyeon Joaab96aa2019-10-12 05:24:15 -0700334 break;
335 }
Changyeon Jo035219e2019-11-26 18:25:04 -0800336 } else {
Changyeon Joffdf3db2020-03-06 15:23:02 -0800337 LOG(WARNING) << "Unsupported metadata tag "
338 << curElem->FindAttribute("name")->Value()
339 << " is found.";
Changyeon Joaab96aa2019-10-12 05:24:15 -0700340 }
341
342 curElem = curElem->NextSiblingElement("parameter");
343 }
344
345 return numEntries;
346}
347
348
Changyeon Jo4ede4d62019-10-22 10:10:15 -0700349bool
350ConfigManager::constructCameraMetadata(CameraInfo *aCamera,
351 const size_t totalEntries,
352 const size_t totalDataSize) {
353 if (aCamera == nullptr || !aCamera->allocate(totalEntries, totalDataSize)) {
Changyeon Joffdf3db2020-03-06 15:23:02 -0800354 LOG(ERROR) << "Failed to allocate memory for camera metadata";
Changyeon Joaab96aa2019-10-12 05:24:15 -0700355 return false;
356 }
357
358 const size_t numStreamConfigs = aCamera->streamConfigurations.size();
359 unique_ptr<int32_t[]> data(new int32_t[kStreamCfgSz * numStreamConfigs]);
360 int32_t *ptr = data.get();
361 for (auto &cfg : aCamera->streamConfigurations) {
362 for (auto i = 0; i < kStreamCfgSz; ++i) {
363 *ptr++ = cfg.second[i];
364 }
365 }
366 int32_t err = add_camera_metadata_entry(aCamera->characteristics,
367 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
368 data.get(),
369 numStreamConfigs * kStreamCfgSz);
370
371 if (err) {
Changyeon Joffdf3db2020-03-06 15:23:02 -0800372 LOG(ERROR) << "Failed to add stream configurations to metadata, ignored";
Changyeon Joaab96aa2019-10-12 05:24:15 -0700373 return false;
374 }
375
376 bool success = true;
377 for (auto &[tag, entry] : aCamera->cameraMetadata) {
378 /* try to add new camera metadata entry */
379 int32_t err = add_camera_metadata_entry(aCamera->characteristics,
380 tag,
Changyeon Job927b882019-11-21 10:16:33 -0800381 entry.first,
Changyeon Joaab96aa2019-10-12 05:24:15 -0700382 entry.second);
383 if (err) {
Changyeon Joffdf3db2020-03-06 15:23:02 -0800384 LOG(ERROR) << "Failed to add an entry with a tag, " << std::hex << tag;
Changyeon Joaab96aa2019-10-12 05:24:15 -0700385
386 /* may exceed preallocated capacity */
Changyeon Joffdf3db2020-03-06 15:23:02 -0800387 LOG(ERROR) << "Camera metadata has "
388 << get_camera_metadata_entry_count(aCamera->characteristics)
389 << " / "
390 << get_camera_metadata_entry_capacity(aCamera->characteristics)
391 << " entries and "
392 << get_camera_metadata_data_count(aCamera->characteristics)
393 << " / "
394 << get_camera_metadata_data_capacity(aCamera->characteristics)
395 << " bytes are filled.";
396 LOG(ERROR) << "\tCurrent metadata entry requires "
397 << calculate_camera_metadata_entry_data_size(tag, entry.second)
398 << " bytes.";
Changyeon Joaab96aa2019-10-12 05:24:15 -0700399
400 success = false;
401 }
402 }
403
Changyeon Joffdf3db2020-03-06 15:23:02 -0800404 LOG(VERBOSE) << "Camera metadata has "
405 << get_camera_metadata_entry_count(aCamera->characteristics)
406 << " / "
407 << get_camera_metadata_entry_capacity(aCamera->characteristics)
408 << " entries and "
409 << get_camera_metadata_data_count(aCamera->characteristics)
410 << " / "
411 << get_camera_metadata_data_capacity(aCamera->characteristics)
412 << " bytes are filled.";
Changyeon Joaab96aa2019-10-12 05:24:15 -0700413 return success;
414}
415
416
417void ConfigManager::readSystemInfo(const XMLElement * const aSysElem) {
418 if (aSysElem == nullptr) {
419 return;
420 }
421
422 /*
423 * Please note that this function assumes that a given system XML element
424 * and its child elements follow DTD. If it does not, it will cause a
425 * segmentation fault due to the failure of finding expected attributes.
426 */
427
428 /* read number of cameras available in the system */
429 const XMLElement *xmlElem = aSysElem->FirstChildElement("num_cameras");
430 if (xmlElem != nullptr) {
431 mSystemInfo.numCameras =
432 stoi(xmlElem->FindAttribute("value")->Value());
433 }
434}
435
436
437void ConfigManager::readDisplayInfo(const XMLElement * const aDisplayElem) {
438 if (aDisplayElem == nullptr) {
Changyeon Joffdf3db2020-03-06 15:23:02 -0800439 LOG(WARNING) << "XML file does not have required camera element";
Changyeon Joaab96aa2019-10-12 05:24:15 -0700440 return;
441 }
442
443 const XMLElement *curDev = aDisplayElem->FirstChildElement("device");
444 while (curDev != nullptr) {
445 const char *id = curDev->FindAttribute("id")->Value();
446 //const char *pos = curDev->FirstAttribute("position")->Value();
447
448 unique_ptr<DisplayInfo> dpy(new DisplayInfo());
449 if (dpy == nullptr) {
Changyeon Joffdf3db2020-03-06 15:23:02 -0800450 LOG(ERROR) << "Failed to allocate memory for DisplayInfo";
Changyeon Joaab96aa2019-10-12 05:24:15 -0700451 return;
452 }
453
454 const XMLElement *cap = curDev->FirstChildElement("caps");
455 if (cap != nullptr) {
456 const XMLElement *curStream = cap->FirstChildElement("stream");
457 while (curStream != nullptr) {
458 /* read 4 attributes */
459 const XMLAttribute *idAttr = curStream->FindAttribute("id");
460 const XMLAttribute *widthAttr = curStream->FindAttribute("width");
461 const XMLAttribute *heightAttr = curStream->FindAttribute("height");
462 const XMLAttribute *fmtAttr = curStream->FindAttribute("format");
463
464 const int32_t id = stoi(idAttr->Value());
465 int32_t pixFormat;
466 if (ConfigManagerUtil::convertToPixelFormat(fmtAttr->Value(),
467 pixFormat)) {
468 RawStreamConfiguration cfg = {
469 id,
470 stoi(widthAttr->Value()),
471 stoi(heightAttr->Value()),
472 pixFormat,
473 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT,
474 0 // unused
475 };
Changyeon Jo67657b92019-11-07 11:21:29 -0800476 dpy->streamConfigurations.insert_or_assign(id, cfg);
Changyeon Joaab96aa2019-10-12 05:24:15 -0700477 }
478
479 curStream = curStream->NextSiblingElement("stream");
480 }
481 }
482
Changyeon Jo67657b92019-11-07 11:21:29 -0800483 mDisplayInfo.insert_or_assign(id, std::move(dpy));
Changyeon Joaab96aa2019-10-12 05:24:15 -0700484 curDev = curDev->NextSiblingElement("device");
485 }
486
487 return;
488}
489
490
491bool ConfigManager::readConfigDataFromXML() noexcept {
492 XMLDocument xmlDoc;
493
494 const int64_t parsingStart = android::elapsedRealtimeNano();
495
496 /* load and parse a configuration file */
497 xmlDoc.LoadFile(mConfigFilePath);
498 if (xmlDoc.ErrorID() != XML_SUCCESS) {
Changyeon Joffdf3db2020-03-06 15:23:02 -0800499 LOG(ERROR) << "Failed to load and/or parse a configuration file, " << xmlDoc.ErrorStr();
Changyeon Joaab96aa2019-10-12 05:24:15 -0700500 return false;
501 }
502
503 /* retrieve the root element */
504 const XMLElement *rootElem = xmlDoc.RootElement();
505 if (strcmp(rootElem->Name(), "configuration")) {
Changyeon Joffdf3db2020-03-06 15:23:02 -0800506 LOG(ERROR) << "A configuration file is not in the required format. "
507 << "See /etc/automotive/evs/evs_configuration.dtd";
Changyeon Joaab96aa2019-10-12 05:24:15 -0700508 return false;
509 }
510
511 unique_lock<mutex> lock(mConfigLock);
512
513 /*
514 * parse camera information; this needs to be done before reading system
515 * information
516 */
517 readCameraInfo(rootElem->FirstChildElement("camera"));
518
519 /* parse system information */
520 readSystemInfo(rootElem->FirstChildElement("system"));
521
522 /* parse display information */
523 readDisplayInfo(rootElem->FirstChildElement("display"));
524
525 /* configuration data is ready to be consumed */
526 mIsReady = true;
527
528 /* notify that configuration data is ready */
529 lock.unlock();
530 mConfigCond.notify_all();
531
532 const int64_t parsingEnd = android::elapsedRealtimeNano();
Changyeon Joffdf3db2020-03-06 15:23:02 -0800533 LOG(INFO) << "Parsing configuration file takes "
534 << std::scientific << (double)(parsingEnd - parsingStart) / 1000000.0
535 << " ms.";
Changyeon Joaab96aa2019-10-12 05:24:15 -0700536
537 return true;
538}
539
540
541bool ConfigManager::readConfigDataFromBinary() {
542 /* Temporary buffer to hold configuration data read from a binary file */
543 char mBuffer[1024];
544
545 fstream srcFile;
546 const int64_t readStart = android::elapsedRealtimeNano();
547
548 srcFile.open(mBinaryFilePath, fstream::in | fstream::binary);
549 if (!srcFile) {
Changyeon Joffdf3db2020-03-06 15:23:02 -0800550 LOG(ERROR) << "Failed to open a source binary file, " << mBinaryFilePath;
Changyeon Joaab96aa2019-10-12 05:24:15 -0700551 return false;
552 }
553
Changyeon Jo4ede4d62019-10-22 10:10:15 -0700554 unique_lock<mutex> lock(mConfigLock);
555 mIsReady = false;
556
Changyeon Joaab96aa2019-10-12 05:24:15 -0700557 /* read configuration data into the internal buffer */
558 srcFile.read(mBuffer, sizeof(mBuffer));
Changyeon Joffdf3db2020-03-06 15:23:02 -0800559 LOG(VERBOSE) << __FUNCTION__ << ": " << srcFile.gcount() << " bytes are read.";
Changyeon Joaab96aa2019-10-12 05:24:15 -0700560 char *p = mBuffer;
Changyeon Jo4ede4d62019-10-22 10:10:15 -0700561 size_t sz = 0;
562
563 /* read number of camera group information entries */
564 size_t ngrps = *(reinterpret_cast<size_t *>(p)); p += sizeof(size_t);
565
566 /* read each camera information entry */
567 for (auto cidx = 0; cidx < ngrps; ++cidx) {
568 /* read camera identifier */
569 string cameraId = *(reinterpret_cast<string *>(p)); p += sizeof(string);
570
571 /* size of camera_metadata_t */
572 size_t num_entry = *(reinterpret_cast<size_t *>(p)); p += sizeof(size_t);
573 size_t num_data = *(reinterpret_cast<size_t *>(p)); p += sizeof(size_t);
574
575 /* create CameraInfo and add it to hash map */
576 unique_ptr<ConfigManager::CameraGroupInfo> aCamera;
577 if (aCamera == nullptr ||
578 !aCamera->allocate(num_entry, num_data)) {
Changyeon Joffdf3db2020-03-06 15:23:02 -0800579 LOG(ERROR) << "Failed to create new CameraInfo object";
Changyeon Jo4ede4d62019-10-22 10:10:15 -0700580 mCameraInfo.clear();
581 return false;
582 }
583
584 /* controls */
585 typedef struct {
586 CameraParam cid;
587 int32_t min;
588 int32_t max;
589 int32_t step;
590 } CameraCtrl;
591 sz = *(reinterpret_cast<size_t *>(p)); p += sizeof(size_t);
592 CameraCtrl *ptr = reinterpret_cast<CameraCtrl *>(p);
593 for (auto idx = 0; idx < sz; ++idx) {
594 CameraCtrl temp = *ptr++;
595 aCamera->controls.emplace(temp.cid,
596 make_tuple(temp.min, temp.max, temp.step));
597 }
598 p = reinterpret_cast<char *>(ptr);
599
600 /* stream configurations */
601 sz = *(reinterpret_cast<size_t *>(p)); p += sizeof(size_t);
602 int32_t *i32_ptr = reinterpret_cast<int32_t *>(p);
603 for (auto idx = 0; idx < sz; ++idx) {
604 const int32_t id = *i32_ptr++;
605
606 std::array<int32_t, kStreamCfgSz> temp;
607 for (auto i = 0; i < kStreamCfgSz; ++i) {
608 temp[i] = *i32_ptr++;
609 }
610 aCamera->streamConfigurations.insert_or_assign(id, temp);
611 }
612 p = reinterpret_cast<char *>(i32_ptr);
613
614 /* synchronization */
615 aCamera->synchronized =
616 *(reinterpret_cast<int32_t *>(p)); p += sizeof(int32_t);
617
618 for (auto idx = 0; idx < num_entry; ++idx) {
619 /* Read camera metadata entries */
620 camera_metadata_tag_t tag =
621 *reinterpret_cast<camera_metadata_tag_t *>(p);
622 p += sizeof(camera_metadata_tag_t);
623 size_t count = *reinterpret_cast<size_t *>(p); p += sizeof(size_t);
624
625 int32_t type = get_camera_metadata_tag_type(tag);
626 switch (type) {
627 case TYPE_BYTE: {
628 add_camera_metadata_entry(aCamera->characteristics,
629 tag,
630 p,
631 count);
632 p += count * sizeof(uint8_t);
633 break;
634 }
635 case TYPE_INT32: {
636 add_camera_metadata_entry(aCamera->characteristics,
637 tag,
638 p,
639 count);
640 p += count * sizeof(int32_t);
641 break;
642 }
643 case TYPE_FLOAT: {
644 add_camera_metadata_entry(aCamera->characteristics,
645 tag,
646 p,
647 count);
648 p += count * sizeof(float);
649 break;
650 }
651 case TYPE_INT64: {
652 add_camera_metadata_entry(aCamera->characteristics,
653 tag,
654 p,
655 count);
656 p += count * sizeof(int64_t);
657 break;
658 }
659 case TYPE_DOUBLE: {
660 add_camera_metadata_entry(aCamera->characteristics,
661 tag,
662 p,
663 count);
664 p += count * sizeof(double);
665 break;
666 }
667 case TYPE_RATIONAL:
668 p += count * sizeof(camera_metadata_rational_t);
669 break;
670 default:
Changyeon Joffdf3db2020-03-06 15:23:02 -0800671 LOG(WARNING) << "Type " << type << " is unknown; "
672 << "data may be corrupted.";
Changyeon Jo4ede4d62019-10-22 10:10:15 -0700673 break;
674 }
675 }
676
677 mCameraInfo.insert_or_assign(cameraId, std::move(aCamera));
678 }
679
680
Changyeon Joaab96aa2019-10-12 05:24:15 -0700681
682 /* read number of camera information entries */
683 size_t ncams = *(reinterpret_cast<size_t *>(p)); p += sizeof(size_t);
Changyeon Joaab96aa2019-10-12 05:24:15 -0700684
685 /* read each camera information entry */
Changyeon Joaab96aa2019-10-12 05:24:15 -0700686 for (auto cidx = 0; cidx < ncams; ++cidx) {
687 /* read camera identifier */
688 string cameraId = *(reinterpret_cast<string *>(p)); p += sizeof(string);
689
690 /* size of camera_metadata_t */
691 size_t num_entry = *(reinterpret_cast<size_t *>(p)); p += sizeof(size_t);
692 size_t num_data = *(reinterpret_cast<size_t *>(p)); p += sizeof(size_t);
693
694 /* create CameraInfo and add it to hash map */
695 unique_ptr<ConfigManager::CameraInfo> aCamera;
696 if (aCamera == nullptr ||
697 !aCamera->allocate(num_entry, num_data)) {
Changyeon Joffdf3db2020-03-06 15:23:02 -0800698 LOG(ERROR) << "Failed to create new CameraInfo object";
Changyeon Joaab96aa2019-10-12 05:24:15 -0700699 mCameraInfo.clear();
700 return false;
701 }
702
703 /* controls */
704 typedef struct {
705 CameraParam cid;
706 int32_t min;
707 int32_t max;
708 int32_t step;
709 } CameraCtrl;
710 sz = *(reinterpret_cast<size_t *>(p)); p += sizeof(size_t);
711 CameraCtrl *ptr = reinterpret_cast<CameraCtrl *>(p);
712 for (auto idx = 0; idx < sz; ++idx) {
713 CameraCtrl temp = *ptr++;
714 aCamera->controls.emplace(temp.cid,
715 make_tuple(temp.min, temp.max, temp.step));
716 }
717 p = reinterpret_cast<char *>(ptr);
718
Changyeon Joaab96aa2019-10-12 05:24:15 -0700719 /* stream configurations */
720 sz = *(reinterpret_cast<size_t *>(p)); p += sizeof(size_t);
Changyeon Jo4ede4d62019-10-22 10:10:15 -0700721 int32_t *i32_ptr = reinterpret_cast<int32_t *>(p);
Changyeon Joaab96aa2019-10-12 05:24:15 -0700722 for (auto idx = 0; idx < sz; ++idx) {
723 const int32_t id = *i32_ptr++;
724
725 std::array<int32_t, kStreamCfgSz> temp;
Changyeon Jo4ede4d62019-10-22 10:10:15 -0700726 for (auto i = 0; i < kStreamCfgSz; ++i) {
727 temp[i] = *i32_ptr++;
728 }
Changyeon Jo67657b92019-11-07 11:21:29 -0800729 aCamera->streamConfigurations.insert_or_assign(id, temp);
Changyeon Joaab96aa2019-10-12 05:24:15 -0700730 }
731 p = reinterpret_cast<char *>(i32_ptr);
732
733 for (auto idx = 0; idx < num_entry; ++idx) {
734 /* Read camera metadata entries */
735 camera_metadata_tag_t tag =
736 *reinterpret_cast<camera_metadata_tag_t *>(p);
737 p += sizeof(camera_metadata_tag_t);
738 size_t count = *reinterpret_cast<size_t *>(p); p += sizeof(size_t);
739
740 int32_t type = get_camera_metadata_tag_type(tag);
741 switch (type) {
742 case TYPE_BYTE: {
743 add_camera_metadata_entry(aCamera->characteristics,
744 tag,
745 p,
746 count);
747 p += count * sizeof(uint8_t);
748 break;
749 }
750 case TYPE_INT32: {
751 add_camera_metadata_entry(aCamera->characteristics,
752 tag,
753 p,
754 count);
755 p += count * sizeof(int32_t);
756 break;
757 }
758 case TYPE_FLOAT: {
759 add_camera_metadata_entry(aCamera->characteristics,
760 tag,
761 p,
762 count);
763 p += count * sizeof(float);
764 break;
765 }
766 case TYPE_INT64: {
767 add_camera_metadata_entry(aCamera->characteristics,
768 tag,
769 p,
770 count);
771 p += count * sizeof(int64_t);
772 break;
773 }
774 case TYPE_DOUBLE: {
775 add_camera_metadata_entry(aCamera->characteristics,
776 tag,
777 p,
778 count);
779 p += count * sizeof(double);
780 break;
781 }
782 case TYPE_RATIONAL:
783 p += count * sizeof(camera_metadata_rational_t);
784 break;
785 default:
Changyeon Joffdf3db2020-03-06 15:23:02 -0800786 LOG(WARNING) << "Type " << type << " is unknown; "
787 << "data may be corrupted.";
Changyeon Joaab96aa2019-10-12 05:24:15 -0700788 break;
789 }
790 }
791
Changyeon Jo67657b92019-11-07 11:21:29 -0800792 mCameraInfo.insert_or_assign(cameraId, std::move(aCamera));
Changyeon Joaab96aa2019-10-12 05:24:15 -0700793 }
794
795 mIsReady = true;
796
797 /* notify that configuration data is ready */
798 lock.unlock();
799 mConfigCond.notify_all();
800
801 int64_t readEnd = android::elapsedRealtimeNano();
Changyeon Joffdf3db2020-03-06 15:23:02 -0800802 LOG(INFO) << __FUNCTION__ << " takes "
803 << std::scientific << (double)(readEnd - readStart) / 1000000.0
804 << " ms.";
Changyeon Joaab96aa2019-10-12 05:24:15 -0700805
806 return true;
807}
808
809
810bool ConfigManager::writeConfigDataToBinary() {
811 fstream outFile;
812
813 int64_t writeStart = android::elapsedRealtimeNano();
814
815 outFile.open(mBinaryFilePath, fstream::out | fstream::binary);
816 if (!outFile) {
Changyeon Joffdf3db2020-03-06 15:23:02 -0800817 LOG(ERROR) << "Failed to open a destination binary file, " << mBinaryFilePath;
Changyeon Joaab96aa2019-10-12 05:24:15 -0700818 return false;
819 }
820
821 /* lock a configuration data while it's being written to the filesystem */
822 lock_guard<mutex> lock(mConfigLock);
823
Changyeon Jo4ede4d62019-10-22 10:10:15 -0700824 /* write camera group information */
825 size_t sz = mCameraGroups.size();
Changyeon Joaab96aa2019-10-12 05:24:15 -0700826 outFile.write(reinterpret_cast<const char *>(&sz),
827 sizeof(size_t));
Changyeon Jo4ede4d62019-10-22 10:10:15 -0700828 for (auto&& [camId, camInfo] : mCameraGroups) {
Changyeon Joffdf3db2020-03-06 15:23:02 -0800829 LOG(INFO) << "Storing camera group " << camId;
Changyeon Jo4ede4d62019-10-22 10:10:15 -0700830
831 /* write a camera identifier string */
832 outFile.write(reinterpret_cast<const char *>(&camId),
833 sizeof(string));
834
835 /* controls */
836 sz = camInfo->controls.size();
837 outFile.write(reinterpret_cast<const char *>(&sz),
838 sizeof(size_t));
839 for (auto&& [ctrl, range] : camInfo->controls) {
840 outFile.write(reinterpret_cast<const char *>(&ctrl),
841 sizeof(CameraParam));
842 outFile.write(reinterpret_cast<const char *>(&get<0>(range)),
843 sizeof(int32_t));
844 outFile.write(reinterpret_cast<const char *>(&get<1>(range)),
845 sizeof(int32_t));
846 outFile.write(reinterpret_cast<const char *>(&get<2>(range)),
847 sizeof(int32_t));
848 }
849
850 /* stream configurations */
851 sz = camInfo->streamConfigurations.size();
852 outFile.write(reinterpret_cast<const char *>(&sz),
853 sizeof(size_t));
854 for (auto&& [sid, cfg] : camInfo->streamConfigurations) {
855 outFile.write(reinterpret_cast<const char *>(sid),
856 sizeof(int32_t));
857 for (int idx = 0; idx < kStreamCfgSz; ++idx) {
858 outFile.write(reinterpret_cast<const char *>(&cfg[idx]),
859 sizeof(int32_t));
860 }
861 }
862
863 /* synchronization */
864 outFile.write(reinterpret_cast<const char *>(&camInfo->synchronized),
865 sizeof(int32_t));
866
867 /* size of camera_metadata_t */
868 size_t num_entry = 0;
869 size_t num_data = 0;
870 if (camInfo->characteristics != nullptr) {
871 num_entry = get_camera_metadata_entry_count(camInfo->characteristics);
872 num_data = get_camera_metadata_data_count(camInfo->characteristics);
873 }
874 outFile.write(reinterpret_cast<const char *>(&num_entry),
875 sizeof(size_t));
876 outFile.write(reinterpret_cast<const char *>(&num_data),
877 sizeof(size_t));
878
879 /* write each camera metadata entry */
880 if (num_entry > 0) {
881 camera_metadata_entry_t entry;
882 for (auto idx = 0; idx < num_entry; ++idx) {
883 if (get_camera_metadata_entry(camInfo->characteristics, idx, &entry)) {
Changyeon Joffdf3db2020-03-06 15:23:02 -0800884 LOG(ERROR) << "Failed to retrieve camera metadata entry " << idx;
Changyeon Jo4ede4d62019-10-22 10:10:15 -0700885 outFile.close();
886 return false;
887 }
888
889 outFile.write(reinterpret_cast<const char *>(&entry.tag),
890 sizeof(entry.tag));
891 outFile.write(reinterpret_cast<const char *>(&entry.count),
892 sizeof(entry.count));
893
894 int32_t type = get_camera_metadata_tag_type(entry.tag);
895 switch (type) {
896 case TYPE_BYTE:
897 outFile.write(reinterpret_cast<const char *>(entry.data.u8),
898 sizeof(uint8_t) * entry.count);
899 break;
900 case TYPE_INT32:
901 outFile.write(reinterpret_cast<const char *>(entry.data.i32),
902 sizeof(int32_t) * entry.count);
903 break;
904 case TYPE_FLOAT:
905 outFile.write(reinterpret_cast<const char *>(entry.data.f),
906 sizeof(float) * entry.count);
907 break;
908 case TYPE_INT64:
909 outFile.write(reinterpret_cast<const char *>(entry.data.i64),
910 sizeof(int64_t) * entry.count);
911 break;
912 case TYPE_DOUBLE:
913 outFile.write(reinterpret_cast<const char *>(entry.data.d),
914 sizeof(double) * entry.count);
915 break;
916 case TYPE_RATIONAL:
917 [[fallthrough]];
918 default:
Changyeon Joffdf3db2020-03-06 15:23:02 -0800919 LOG(WARNING) << "Type " << type << " is not supported.";
Changyeon Jo4ede4d62019-10-22 10:10:15 -0700920 break;
921 }
922 }
923 }
924 }
925
926 /* write camera device information */
927 sz = mCameraInfo.size();
928 outFile.write(reinterpret_cast<const char *>(&sz),
929 sizeof(size_t));
930 for (auto&& [camId, camInfo] : mCameraInfo) {
Changyeon Joffdf3db2020-03-06 15:23:02 -0800931 LOG(INFO) << "Storing camera " << camId;
Changyeon Joaab96aa2019-10-12 05:24:15 -0700932
933 /* write a camera identifier string */
934 outFile.write(reinterpret_cast<const char *>(&camId),
935 sizeof(string));
936
937 /* controls */
938 sz = camInfo->controls.size();
939 outFile.write(reinterpret_cast<const char *>(&sz),
940 sizeof(size_t));
941 for (auto& [ctrl, range] : camInfo->controls) {
942 outFile.write(reinterpret_cast<const char *>(&ctrl),
943 sizeof(CameraParam));
944 outFile.write(reinterpret_cast<const char *>(&get<0>(range)),
945 sizeof(int32_t));
946 outFile.write(reinterpret_cast<const char *>(&get<1>(range)),
947 sizeof(int32_t));
948 outFile.write(reinterpret_cast<const char *>(&get<2>(range)),
949 sizeof(int32_t));
950 }
951
Changyeon Joaab96aa2019-10-12 05:24:15 -0700952 /* stream configurations */
953 sz = camInfo->streamConfigurations.size();
954 outFile.write(reinterpret_cast<const char *>(&sz),
955 sizeof(size_t));
Changyeon Jo4ede4d62019-10-22 10:10:15 -0700956 for (auto&& [sid, cfg] : camInfo->streamConfigurations) {
Changyeon Joaab96aa2019-10-12 05:24:15 -0700957 outFile.write(reinterpret_cast<const char *>(sid),
958 sizeof(int32_t));
959 for (int idx = 0; idx < kStreamCfgSz; ++idx) {
960 outFile.write(reinterpret_cast<const char *>(&cfg[idx]),
961 sizeof(int32_t));
962 }
963 }
964
965 /* size of camera_metadata_t */
966 size_t num_entry = 0;
967 size_t num_data = 0;
968 if (camInfo->characteristics != nullptr) {
969 num_entry = get_camera_metadata_entry_count(camInfo->characteristics);
970 num_data = get_camera_metadata_data_count(camInfo->characteristics);
971 }
972 outFile.write(reinterpret_cast<const char *>(&num_entry),
973 sizeof(size_t));
974 outFile.write(reinterpret_cast<const char *>(&num_data),
975 sizeof(size_t));
976
977 /* write each camera metadata entry */
978 if (num_entry > 0) {
979 camera_metadata_entry_t entry;
980 for (auto idx = 0; idx < num_entry; ++idx) {
981 if (get_camera_metadata_entry(camInfo->characteristics, idx, &entry)) {
Changyeon Joffdf3db2020-03-06 15:23:02 -0800982 LOG(ERROR) << "Failed to retrieve camera metadata entry " << idx;
Changyeon Joaab96aa2019-10-12 05:24:15 -0700983 outFile.close();
984 return false;
985 }
986
987 outFile.write(reinterpret_cast<const char *>(&entry.tag),
988 sizeof(entry.tag));
989 outFile.write(reinterpret_cast<const char *>(&entry.count),
990 sizeof(entry.count));
991
992 int32_t type = get_camera_metadata_tag_type(entry.tag);
993 switch (type) {
994 case TYPE_BYTE:
995 outFile.write(reinterpret_cast<const char *>(entry.data.u8),
996 sizeof(uint8_t) * entry.count);
997 break;
998 case TYPE_INT32:
999 outFile.write(reinterpret_cast<const char *>(entry.data.i32),
1000 sizeof(int32_t) * entry.count);
1001 break;
1002 case TYPE_FLOAT:
1003 outFile.write(reinterpret_cast<const char *>(entry.data.f),
1004 sizeof(float) * entry.count);
1005 break;
1006 case TYPE_INT64:
1007 outFile.write(reinterpret_cast<const char *>(entry.data.i64),
1008 sizeof(int64_t) * entry.count);
1009 break;
1010 case TYPE_DOUBLE:
1011 outFile.write(reinterpret_cast<const char *>(entry.data.d),
1012 sizeof(double) * entry.count);
1013 break;
1014 case TYPE_RATIONAL:
1015 [[fallthrough]];
1016 default:
Changyeon Joffdf3db2020-03-06 15:23:02 -08001017 LOG(WARNING) << "Type " << type << " is not supported.";
Changyeon Joaab96aa2019-10-12 05:24:15 -07001018 break;
1019 }
1020 }
1021 }
1022 }
1023
1024 outFile.close();
1025 int64_t writeEnd = android::elapsedRealtimeNano();
Changyeon Joffdf3db2020-03-06 15:23:02 -08001026 LOG(INFO) << __FUNCTION__ << " takes "
1027 << std::scientific << (double)(writeEnd - writeStart) / 1000000.0
1028 << " ms.";
Changyeon Joaab96aa2019-10-12 05:24:15 -07001029
1030
1031 return true;
1032}
1033
1034
Changyeon Joaab96aa2019-10-12 05:24:15 -07001035std::unique_ptr<ConfigManager> ConfigManager::Create(const char *path) {
1036 unique_ptr<ConfigManager> cfgMgr(new ConfigManager(path));
1037
1038 /*
1039 * Read a configuration from XML file
1040 *
1041 * If this is too slow, ConfigManager::readConfigDataFromBinary() and
1042 * ConfigManager::writeConfigDataToBinary()can serialize CameraInfo object
1043 * to the filesystem and construct CameraInfo instead; this was
1044 * evaluated as 10x faster.
1045 */
1046 if (!cfgMgr->readConfigDataFromXML()) {
1047 return nullptr;
1048 } else {
1049 return cfgMgr;
1050 }
1051}
1052
Changyeon Jo035219e2019-11-26 18:25:04 -08001053ConfigManager::CameraInfo::~CameraInfo() {
1054 free_camera_metadata(characteristics);
1055
1056 for (auto&& [tag, val] : cameraMetadata) {
1057 switch(tag) {
1058 case ANDROID_LENS_DISTORTION:
1059 case ANDROID_LENS_POSE_ROTATION:
1060 case ANDROID_LENS_POSE_TRANSLATION:
1061 case ANDROID_LENS_INTRINSIC_CALIBRATION: {
1062 delete[] reinterpret_cast<float *>(val.first);
1063 break;
1064 }
1065
1066 case ANDROID_REQUEST_AVAILABLE_CAPABILITIES: {
1067 delete[] \
1068 reinterpret_cast<
1069 camera_metadata_enum_android_request_available_capabilities_t *
1070 >(val.first);
1071 break;
1072 }
1073
1074 case ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS: {
1075 delete[] reinterpret_cast<char *>(val.first);
1076 break;
1077 }
1078
1079 default:
Changyeon Joffdf3db2020-03-06 15:23:02 -08001080 LOG(WARNING) << "Tag " << std::hex << tag << " is not supported. "
1081 << "Data may be corrupted?";
Changyeon Jo035219e2019-11-26 18:25:04 -08001082 break;
1083 }
1084 }
1085}
1086