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