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
~ConfigManager()30 ConfigManager::~ConfigManager() {
31 /* Nothing to do */
32 }
33
34
printElementNames(const XMLElement * rootElem,string prefix) const35 void ConfigManager::printElementNames(const XMLElement *rootElem,
36 string prefix) const {
37 const XMLElement *curElem = rootElem;
38
39 while (curElem != nullptr) {
40 LOG(VERBOSE) << "[ELEM] " << prefix << curElem->Name();
41 const XMLAttribute *curAttr = curElem->FirstAttribute();
42 while (curAttr) {
43 LOG(VERBOSE) << "[ATTR] " << prefix << curAttr->Name() << ": " << curAttr->Value();
44 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
readCameraInfo(const XMLElement * const aCameraElem)55 void ConfigManager::readCameraInfo(const XMLElement * const aCameraElem) {
56 if (aCameraElem == nullptr) {
57 LOG(WARNING) << "XML file does not have required camera element";
58 return;
59 }
60
61 const XMLElement *curElem = aCameraElem->FirstChildElement();
62 while (curElem != nullptr) {
63 if (!strcmp(curElem->Name(), "group")) {
64 /* camera group identifier */
65 const char *id = curElem->FindAttribute("id")->Value();
66
67 /* create a camera group to be filled */
68 CameraGroupInfo *aCamera = new CameraGroupInfo();
69
70 /* read camera device information */
71 if (!readCameraDeviceInfo(aCamera, curElem)) {
72 LOG(WARNING) << "Failed to read a camera information of " << id;
73 delete aCamera;
74 continue;
75 }
76
77 /* camera group synchronization */
78 const char *sync = curElem->FindAttribute("synchronized")->Value();
79 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 }
88
89 /* add a group to hash map */
90 mCameraGroups.insert_or_assign(id, unique_ptr<CameraGroupInfo>(aCamera));
91 } 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
98 /* create a camera device to be filled */
99 CameraInfo *aCamera = new CameraInfo();
100
101 /* read camera device information */
102 if (!readCameraDeviceInfo(aCamera, curElem)) {
103 LOG(WARNING) << "Failed to read a camera information of " << id;
104 delete aCamera;
105 continue;
106 }
107
108 /* store read camera module information */
109 mCameraInfo.insert_or_assign(id, unique_ptr<CameraInfo>(aCamera));
110
111 /* assign a camera device to a position group */
112 mCameraPosition[pos].emplace(id);
113 } else {
114 /* ignore other device types */
115 LOG(DEBUG) << "Unknown element " << curElem->Name() << " is ignored";
116 }
117
118 curElem = curElem->NextSiblingElement();
119 }
120 }
121
122
123 bool
readCameraDeviceInfo(CameraInfo * aCamera,const XMLElement * aDeviceElem)124 ConfigManager::readCameraDeviceInfo(CameraInfo *aCamera,
125 const XMLElement *aDeviceElem) {
126 if (aCamera == nullptr || aDeviceElem == nullptr) {
127 return false;
128 }
129
130 /* 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)) {
149 LOG(WARNING) << "Either failed to allocate memory or "
150 << "allocated memory was not large enough";
151 }
152
153 return true;
154 }
155
156
157 size_t
readCameraCapabilities(const XMLElement * const aCapElem,CameraInfo * aCamera,size_t & dataSize)158 ConfigManager::readCameraCapabilities(const XMLElement * const aCapElem,
159 CameraInfo *aCamera,
160 size_t &dataSize) {
161 if (aCapElem == nullptr || aCamera == nullptr) {
162 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 };
223 aCamera->streamConfigurations.insert_or_assign(id, cfg);
224 }
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
241 size_t
readCameraMetadata(const XMLElement * const aParamElem,CameraInfo * aCamera,size_t & dataSize)242 ConfigManager::readCameraMetadata(const XMLElement * const aParamElem,
243 CameraInfo *aCamera,
244 size_t &dataSize) {
245 if (aParamElem == nullptr || aCamera == nullptr) {
246 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) {
253 if (ConfigManagerUtil::convertToMetadataTag(curElem->FindAttribute("name")->Value(),
254 tag)) {
255 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
268 aCamera->cameraMetadata.insert_or_assign(
269 tag, make_pair(data, count)
270 );
271
272 ++numEntries;
273 dataSize += calculate_camera_metadata_entry_data_size(
274 get_camera_metadata_tag_type(tag), count
275 );
276
277 break;
278 }
279
280 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(
284 curElem->FindAttribute("value")->Value(),
285 *data)
286 ) {
287 aCamera->cameraMetadata.insert_or_assign(
288 tag, make_pair((void *)data, 1)
289 );
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(
317 tag, make_pair((void *)data, len + 1)
318 );
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
328 /* TODO(b/140416878): add vendor-defined/custom tag support */
329
330 default:
331 LOG(WARNING) << "Parameter "
332 << curElem->FindAttribute("name")->Value()
333 << " is not supported";
334 break;
335 }
336 } else {
337 LOG(WARNING) << "Unsupported metadata tag "
338 << curElem->FindAttribute("name")->Value()
339 << " is found.";
340 }
341
342 curElem = curElem->NextSiblingElement("parameter");
343 }
344
345 return numEntries;
346 }
347
348
349 bool
constructCameraMetadata(CameraInfo * aCamera,const size_t totalEntries,const size_t totalDataSize)350 ConfigManager::constructCameraMetadata(CameraInfo *aCamera,
351 const size_t totalEntries,
352 const size_t totalDataSize) {
353 if (aCamera == nullptr || !aCamera->allocate(totalEntries, totalDataSize)) {
354 LOG(ERROR) << "Failed to allocate memory for camera metadata";
355 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) {
372 LOG(ERROR) << "Failed to add stream configurations to metadata, ignored";
373 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,
381 entry.first,
382 entry.second);
383 if (err) {
384 LOG(ERROR) << "Failed to add an entry with a tag, " << std::hex << tag;
385
386 /* may exceed preallocated capacity */
387 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.";
399
400 success = false;
401 }
402 }
403
404 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.";
413 return success;
414 }
415
416
readSystemInfo(const XMLElement * const aSysElem)417 void 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
readDisplayInfo(const XMLElement * const aDisplayElem)437 void ConfigManager::readDisplayInfo(const XMLElement * const aDisplayElem) {
438 if (aDisplayElem == nullptr) {
439 LOG(WARNING) << "XML file does not have required camera element";
440 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) {
450 LOG(ERROR) << "Failed to allocate memory for DisplayInfo";
451 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 };
476 dpy->streamConfigurations.insert_or_assign(id, cfg);
477 }
478
479 curStream = curStream->NextSiblingElement("stream");
480 }
481 }
482
483 mDisplayInfo.insert_or_assign(id, std::move(dpy));
484 curDev = curDev->NextSiblingElement("device");
485 }
486
487 return;
488 }
489
490
readConfigDataFromXML()491 bool 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) {
499 LOG(ERROR) << "Failed to load and/or parse a configuration file, " << xmlDoc.ErrorStr();
500 return false;
501 }
502
503 /* retrieve the root element */
504 const XMLElement *rootElem = xmlDoc.RootElement();
505 if (strcmp(rootElem->Name(), "configuration")) {
506 LOG(ERROR) << "A configuration file is not in the required format. "
507 << "See /etc/automotive/evs/evs_configuration.dtd";
508 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();
533 LOG(INFO) << "Parsing configuration file takes "
534 << std::scientific << (double)(parsingEnd - parsingStart) / 1000000.0
535 << " ms.";
536
537 return true;
538 }
539
540
readConfigDataFromBinary()541 bool 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) {
550 LOG(ERROR) << "Failed to open a source binary file, " << mBinaryFilePath;
551 return false;
552 }
553
554 unique_lock<mutex> lock(mConfigLock);
555 mIsReady = false;
556
557 /* read configuration data into the internal buffer */
558 srcFile.read(mBuffer, sizeof(mBuffer));
559 LOG(VERBOSE) << __FUNCTION__ << ": " << srcFile.gcount() << " bytes are read.";
560 char *p = mBuffer;
561 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)) {
579 LOG(ERROR) << "Failed to create new CameraInfo object";
580 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:
671 LOG(WARNING) << "Type " << type << " is unknown; "
672 << "data may be corrupted.";
673 break;
674 }
675 }
676
677 mCameraInfo.insert_or_assign(cameraId, std::move(aCamera));
678 }
679
680
681
682 /* read number of camera information entries */
683 size_t ncams = *(reinterpret_cast<size_t *>(p)); p += sizeof(size_t);
684
685 /* read each camera information entry */
686 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)) {
698 LOG(ERROR) << "Failed to create new CameraInfo object";
699 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
719 /* stream configurations */
720 sz = *(reinterpret_cast<size_t *>(p)); p += sizeof(size_t);
721 int32_t *i32_ptr = reinterpret_cast<int32_t *>(p);
722 for (auto idx = 0; idx < sz; ++idx) {
723 const int32_t id = *i32_ptr++;
724
725 std::array<int32_t, kStreamCfgSz> temp;
726 for (auto i = 0; i < kStreamCfgSz; ++i) {
727 temp[i] = *i32_ptr++;
728 }
729 aCamera->streamConfigurations.insert_or_assign(id, temp);
730 }
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:
786 LOG(WARNING) << "Type " << type << " is unknown; "
787 << "data may be corrupted.";
788 break;
789 }
790 }
791
792 mCameraInfo.insert_or_assign(cameraId, std::move(aCamera));
793 }
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();
802 LOG(INFO) << __FUNCTION__ << " takes "
803 << std::scientific << (double)(readEnd - readStart) / 1000000.0
804 << " ms.";
805
806 return true;
807 }
808
809
writeConfigDataToBinary()810 bool ConfigManager::writeConfigDataToBinary() {
811 fstream outFile;
812
813 int64_t writeStart = android::elapsedRealtimeNano();
814
815 outFile.open(mBinaryFilePath, fstream::out | fstream::binary);
816 if (!outFile) {
817 LOG(ERROR) << "Failed to open a destination binary file, " << mBinaryFilePath;
818 return false;
819 }
820
821 /* lock a configuration data while it's being written to the filesystem */
822 lock_guard<mutex> lock(mConfigLock);
823
824 /* write camera group information */
825 size_t sz = mCameraGroups.size();
826 outFile.write(reinterpret_cast<const char *>(&sz),
827 sizeof(size_t));
828 for (auto&& [camId, camInfo] : mCameraGroups) {
829 LOG(INFO) << "Storing camera group " << camId;
830
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)) {
884 LOG(ERROR) << "Failed to retrieve camera metadata entry " << idx;
885 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:
919 LOG(WARNING) << "Type " << type << " is not supported.";
920 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) {
931 LOG(INFO) << "Storing camera " << camId;
932
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
952 /* stream configurations */
953 sz = camInfo->streamConfigurations.size();
954 outFile.write(reinterpret_cast<const char *>(&sz),
955 sizeof(size_t));
956 for (auto&& [sid, cfg] : camInfo->streamConfigurations) {
957 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)) {
982 LOG(ERROR) << "Failed to retrieve camera metadata entry " << idx;
983 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:
1017 LOG(WARNING) << "Type " << type << " is not supported.";
1018 break;
1019 }
1020 }
1021 }
1022 }
1023
1024 outFile.close();
1025 int64_t writeEnd = android::elapsedRealtimeNano();
1026 LOG(INFO) << __FUNCTION__ << " takes "
1027 << std::scientific << (double)(writeEnd - writeStart) / 1000000.0
1028 << " ms.";
1029
1030
1031 return true;
1032 }
1033
1034
Create(const char * path)1035 std::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
~CameraInfo()1053 ConfigManager::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:
1080 LOG(WARNING) << "Tag " << std::hex << tag << " is not supported. "
1081 << "Data may be corrupted?";
1082 break;
1083 }
1084 }
1085 }
1086
1087