1 /**
2 * Copyright (C) 2022 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 <ImsMediaCamera.h>
18 #include <ImsMediaTrace.h>
19 #include <ImsMediaVideoUtil.h>
20 #include <unistd.h>
21 #include <cinttypes>
22 #include <thread>
23 #include <camera/NdkCaptureRequest.h>
24 #include <media/NdkImage.h>
25
26 #define UNKNOWN_TAG "UNKNOWN_TAG"
27 #define MAKE_PAIR(val) std::make_pair(val, #val)
28 template <typename T>
GetPairStr(T key,std::vector<std::pair<T,const char * >> & store)29 const char* GetPairStr(T key, std::vector<std::pair<T, const char*>>& store)
30 {
31 typedef typename std::vector<std::pair<T, const char*>>::iterator iterator;
32 for (iterator it = store.begin(); it != store.end(); ++it)
33 {
34 if (it->first == key)
35 {
36 return it->second;
37 }
38 }
39 IMLOGW1("[GetPairStr] %#08x : UNKNOWN_TAG", key);
40 return UNKNOWN_TAG;
41 }
42
43 /*
44 * camera_status_t error translation
45 */
46 using ERROR_PAIR = std::pair<camera_status_t, const char*>;
47 static std::vector<ERROR_PAIR> errorInfo{
48 MAKE_PAIR(ACAMERA_OK),
49 MAKE_PAIR(ACAMERA_ERROR_UNKNOWN),
50 MAKE_PAIR(ACAMERA_ERROR_INVALID_PARAMETER),
51 MAKE_PAIR(ACAMERA_ERROR_CAMERA_DISCONNECTED),
52 MAKE_PAIR(ACAMERA_ERROR_NOT_ENOUGH_MEMORY),
53 MAKE_PAIR(ACAMERA_ERROR_METADATA_NOT_FOUND),
54 MAKE_PAIR(ACAMERA_ERROR_CAMERA_DEVICE),
55 MAKE_PAIR(ACAMERA_ERROR_CAMERA_SERVICE),
56 MAKE_PAIR(ACAMERA_ERROR_SESSION_CLOSED),
57 MAKE_PAIR(ACAMERA_ERROR_INVALID_OPERATION),
58 MAKE_PAIR(ACAMERA_ERROR_STREAM_CONFIGURE_FAIL),
59 MAKE_PAIR(ACAMERA_ERROR_CAMERA_IN_USE),
60 MAKE_PAIR(ACAMERA_ERROR_MAX_CAMERA_IN_USE),
61 MAKE_PAIR(ACAMERA_ERROR_CAMERA_DISABLED),
62 MAKE_PAIR(ACAMERA_ERROR_PERMISSION_DENIED),
63 };
GetErrorStr(camera_status_t err)64 const char* GetErrorStr(camera_status_t err)
65 {
66 return GetPairStr<camera_status_t>(err, errorInfo);
67 }
68
69 /**
70 * Range of Camera Exposure Time:
71 * Camera's capability range have a very long range which may be disturbing
72 * on camera. For this sample purpose, clamp to a range showing visible
73 * video on preview: 100000ns ~ 250000000ns
74 */
75 static const uint64_t kMinExposureTime = static_cast<uint64_t>(1000000);
76 static const uint64_t kMaxExposureTime = static_cast<uint64_t>(250000000);
77
78 std::map<std::string, CameraId> ImsMediaCamera::gCameraIds;
79 ImsMediaCondition ImsMediaCamera::gCondition;
80 ImsMediaCamera ImsMediaCamera::gCamera;
81
getInstance()82 ImsMediaCamera* ImsMediaCamera::getInstance()
83 {
84 return &gCamera;
85 }
86
ImsMediaCamera()87 ImsMediaCamera::ImsMediaCamera() :
88 mManager(nullptr),
89 mSessionOutputContainer(nullptr),
90 mCaptureSession(nullptr),
91 mCaptureSessionState(CaptureSessionState::kStateMax),
92 mExposureTime(0),
93 mSensitivity(0),
94 mCameraMode(kCameraModePreview),
95 mCameraFacing(ACAMERA_LENS_FACING_FRONT),
96 mCameraOrientation(0),
97 mActiveCameraId(""),
98 mCameraZoom(0),
99 mFramerate(-1)
100 {
101 IMLOGD0("[ImsMediaCamera]");
102 }
103
~ImsMediaCamera()104 ImsMediaCamera::~ImsMediaCamera()
105 {
106 IMLOGD0("[~ImsMediaCamera]");
107 }
108
Initialize()109 void ImsMediaCamera::Initialize()
110 {
111 IMLOGD0("[Initialize]");
112 gCameraIds.clear();
113 mManager = ACameraManager_create();
114
115 if (mManager == nullptr)
116 {
117 IMLOGD0("[Initialize] manager is not created");
118 return;
119 }
120
121 EnumerateCamera();
122 mCaptureRequest.outputNativeWindows.resize(0);
123 mCaptureRequest.sessionOutputs.resize(0);
124 mCaptureRequest.targets.resize(0);
125 }
126
DeInitialize()127 void ImsMediaCamera::DeInitialize()
128 {
129 IMLOGD0("[DeInitialize]");
130
131 for (auto& cam : gCameraIds)
132 {
133 if (cam.second.mDevice)
134 {
135 ACameraDevice_close(cam.second.mDevice);
136 }
137 }
138
139 if (mManager)
140 {
141 camera_status_t status =
142 ACameraManager_unregisterAvailabilityCallback(mManager, GetManagerListener());
143
144 if (status != ACAMERA_OK)
145 {
146 IMLOGE0("[DeInitialize] error[%s], GetErrorStr(status)");
147 }
148
149 ACameraManager_delete(mManager);
150 mManager = nullptr;
151 }
152
153 gCameraIds.clear();
154 for (auto& cam : gCameraIds)
155 {
156 if (cam.second.mDevice)
157 {
158 ACameraDevice_close(cam.second.mDevice);
159 }
160 }
161
162 if (mManager)
163 {
164 camera_status_t status =
165 ACameraManager_unregisterAvailabilityCallback(mManager, GetManagerListener());
166
167 if (status != ACAMERA_OK)
168 {
169 IMLOGE0("[~ImsMediaCamera] error[%s], GetErrorStr(status)");
170 }
171
172 ACameraManager_delete(mManager);
173 mManager = nullptr;
174 }
175
176 gCameraIds.clear();
177 }
178
OpenCamera()179 bool ImsMediaCamera::OpenCamera()
180 {
181 IMLOGD1("[OpenCamera] active camera[%s]", mActiveCameraId.c_str());
182
183 if (mManager == nullptr)
184 {
185 return false;
186 }
187
188 if (mActiveCameraId.compare(std::string("")) == 0)
189 {
190 IMLOGE0("[OpenCamera] no active camera");
191 return false;
192 }
193
194 camera_status_t status = ACameraManager_openCamera(mManager, mActiveCameraId.c_str(),
195 GetDeviceListener(), &gCameraIds[mActiveCameraId].mDevice);
196
197 if (status != ACAMERA_OK)
198 {
199 IMLOGE1("[OpenCamera] cannot open camera, error[%s]", GetErrorStr(status));
200 return false;
201 }
202
203 status = ACameraManager_registerAvailabilityCallback(mManager, GetManagerListener());
204
205 if (status != ACAMERA_OK)
206 {
207 IMLOGE1("[OpenCamera] fail to register manager callback, error[%s]", GetErrorStr(status));
208 return false;
209 }
210
211 // Initialize camera controls(exposure time and sensitivity), pick
212 // up value of 2% * range + min as starting value (just a number, no magic)
213 ACameraMetadata* metadataObj;
214 ACameraManager_getCameraCharacteristics(mManager, mActiveCameraId.c_str(), &metadataObj);
215 ACameraMetadata_const_entry val;
216 status = ACameraMetadata_getConstEntry(
217 metadataObj, ACAMERA_SENSOR_INFO_EXPOSURE_TIME_RANGE, &val);
218
219 if (status == ACAMERA_OK)
220 {
221 mExposureRange.min = val.data.i64[0];
222
223 if (mExposureRange.min < kMinExposureTime)
224 {
225 mExposureRange.min = kMinExposureTime;
226 }
227
228 mExposureRange.max = val.data.i64[1];
229
230 if (mExposureRange.max > kMaxExposureTime)
231 {
232 mExposureRange.max = kMaxExposureTime;
233 }
234
235 mExposureTime = mExposureRange.value(2);
236 }
237 else
238 {
239 IMLOGW0("[OpenCamera] Unsupported ACAMERA_SENSOR_INFO_EXPOSURE_TIME_RANGE");
240 mExposureRange.min = mExposureRange.max = 0L;
241 mExposureTime = 0L;
242 }
243 status =
244 ACameraMetadata_getConstEntry(metadataObj, ACAMERA_SENSOR_INFO_SENSITIVITY_RANGE, &val);
245
246 if (status == ACAMERA_OK)
247 {
248 mSensitivityRange.min = val.data.i32[0];
249 mSensitivityRange.max = val.data.i32[1];
250 mSensitivity = mSensitivityRange.value(2);
251 }
252 else
253 {
254 IMLOGW0("[OpenCamera] failed for ACAMERA_SENSOR_INFO_SENSITIVITY_RANGE");
255 mSensitivityRange.min = mSensitivityRange.max = 0;
256 mSensitivity = 0;
257 }
258
259 return true;
260 }
261
SetCameraConfig(int32_t cameraId,int32_t cameraZoom,int32_t framerate)262 void ImsMediaCamera::SetCameraConfig(int32_t cameraId, int32_t cameraZoom, int32_t framerate)
263 {
264 IMLOGD3("[SetCameraConfig] id[%d], zoom[%d], FPS[%d]", cameraId, cameraZoom, framerate);
265 uint32_t idx = 0;
266 for (std::map<std::string, CameraId>::iterator it = gCameraIds.begin(); it != gCameraIds.end();
267 ++it)
268 {
269 if (idx == cameraId)
270 {
271 mActiveCameraId = (it->second).mId;
272 break;
273 }
274 ++idx;
275 }
276
277 mCameraZoom = cameraZoom;
278 mFramerate = framerate;
279 }
280
CreateSession(ANativeWindow * preview,ANativeWindow * recording)281 bool ImsMediaCamera::CreateSession(ANativeWindow* preview, ANativeWindow* recording)
282 {
283 if (preview == nullptr)
284 {
285 return false;
286 }
287
288 if (!MatchCaptureSizeRequest(preview))
289 {
290 IMLOGE0("[CreateSession] resolution is not matched");
291 return false;
292 }
293
294 mCaptureRequest.outputNativeWindows.push_back(preview);
295
296 if (recording != nullptr)
297 {
298 mCaptureRequest.outputNativeWindows.push_back(recording);
299 }
300
301 mCaptureRequest.sessionOutputs.resize(mCaptureRequest.outputNativeWindows.size());
302 mCaptureRequest.targets.resize(mCaptureRequest.outputNativeWindows.size());
303
304 // Create output from this app's ANativeWindow, and add into output container
305 recording == nullptr ? mCaptureRequest.requestTemplate = TEMPLATE_PREVIEW
306 : mCaptureRequest.requestTemplate = TEMPLATE_RECORD;
307
308 camera_status_t status = ACaptureSessionOutputContainer_create(&mSessionOutputContainer);
309
310 if (status != ACAMERA_OK)
311 {
312 IMLOGE1("[CreateSession] create output container, error[%s]", GetErrorStr(status));
313 return false;
314 }
315
316 for (int idxTarget = 0; idxTarget < mCaptureRequest.outputNativeWindows.size(); idxTarget++)
317 {
318 if (mCaptureRequest.outputNativeWindows[idxTarget] == nullptr)
319 continue;
320
321 IMLOGD0("[CreateSession] acquire window");
322 ANativeWindow_acquire(mCaptureRequest.outputNativeWindows[idxTarget]);
323 status = ACaptureSessionOutput_create(mCaptureRequest.outputNativeWindows[idxTarget],
324 &mCaptureRequest.sessionOutputs[idxTarget]);
325 if (status != ACAMERA_OK)
326 {
327 IMLOGE1("[CreateSession] create capture output, error[%s]", GetErrorStr(status));
328 continue;
329 }
330
331 ACaptureSessionOutputContainer_add(
332 mSessionOutputContainer, mCaptureRequest.sessionOutputs[idxTarget]);
333 status = ACameraOutputTarget_create(mCaptureRequest.outputNativeWindows[idxTarget],
334 &mCaptureRequest.targets[idxTarget]);
335 if (status != ACAMERA_OK)
336 {
337 IMLOGE1("[CreateSession] create output target, error[%s]", GetErrorStr(status));
338 continue;
339 }
340 }
341
342 if (!gCameraIds[mActiveCameraId].mAvailable)
343 {
344 gCondition.wait_timeout(MAX_WAIT_CAMERA);
345 }
346
347 status = ACameraDevice_createCaptureRequest(gCameraIds[mActiveCameraId].mDevice,
348 mCaptureRequest.requestTemplate, &mCaptureRequest.request);
349 if (status != ACAMERA_OK)
350 {
351 IMLOGE1("[CreateSession] create capture request, error[%s]", GetErrorStr(status));
352 return false;
353 }
354
355 for (int idxTarget = 0; idxTarget < mCaptureRequest.outputNativeWindows.size(); idxTarget++)
356 {
357 IMLOGD0("[CreateSession] add target");
358 ACaptureRequest_addTarget(mCaptureRequest.request, mCaptureRequest.targets[idxTarget]);
359 }
360
361 // Create a capture session for the given preview request
362 mCaptureSessionState = CaptureSessionState::kStateReady;
363 status = ACameraDevice_createCaptureSession(gCameraIds[mActiveCameraId].mDevice,
364 mSessionOutputContainer, GetSessionListener(), &mCaptureSession);
365
366 if (status != ACAMERA_OK)
367 {
368 IMLOGE1("[CreateSession] create capture session, error[%s]", GetErrorStr(status));
369 mCaptureSession = nullptr;
370 return false;
371 }
372
373 IMLOGD1("[CreateSession] create capture session[%p]", mCaptureSession);
374
375 uint8_t afModeAuto = ACAMERA_CONTROL_AF_MODE_AUTO;
376 ACaptureRequest_setEntry_u8(mCaptureRequest.request, ACAMERA_CONTROL_AF_MODE, 1, &afModeAuto);
377 const int32_t targetFps[2] = {mFramerate, mFramerate};
378 ACaptureRequest_setEntry_i32(
379 mCaptureRequest.request, ACAMERA_CONTROL_AE_TARGET_FPS_RANGE, 2, targetFps);
380
381 return true;
382 }
383
DeleteSession()384 bool ImsMediaCamera::DeleteSession()
385 {
386 IMLOGD0("[DeleteSession]");
387 camera_status_t status;
388
389 if (mCaptureSession != nullptr)
390 {
391 IMLOGD0("[DeleteSession] session close");
392 gCondition.reset();
393 ACameraCaptureSession_close(mCaptureSession);
394 gCondition.wait_timeout(MAX_WAIT_CAMERA);
395 mCaptureSession = nullptr;
396 }
397
398 if (mCaptureRequest.request != nullptr)
399 {
400 for (int idxTarget = 0; idxTarget < mCaptureRequest.outputNativeWindows.size(); idxTarget++)
401 {
402 if (mCaptureRequest.outputNativeWindows[idxTarget] == nullptr)
403 {
404 continue;
405 }
406
407 status = ACaptureRequest_removeTarget(
408 mCaptureRequest.request, mCaptureRequest.targets[idxTarget]);
409
410 if (status != ACAMERA_OK)
411 {
412 IMLOGE1("[DeleteSession] error ACaptureRequest_removeTarget[%s]",
413 GetErrorStr(status));
414 }
415
416 ACameraOutputTarget_free(mCaptureRequest.targets[idxTarget]);
417 status = ACaptureSessionOutputContainer_remove(
418 mSessionOutputContainer, mCaptureRequest.sessionOutputs[idxTarget]);
419
420 if (status != ACAMERA_OK)
421 {
422 IMLOGE1("[DeleteSession] error ACaptureSessionOutputContainer_remove[%s]",
423 GetErrorStr(status));
424 }
425
426 ACaptureSessionOutput_free(mCaptureRequest.sessionOutputs[idxTarget]);
427 ANativeWindow_release(mCaptureRequest.outputNativeWindows[idxTarget]);
428 }
429
430 IMLOGD0("[DeleteSession] free request");
431 ACaptureRequest_free(mCaptureRequest.request);
432 mCaptureRequest.request = nullptr;
433 }
434
435 mCaptureRequest.outputNativeWindows.resize(0);
436 mCaptureRequest.sessionOutputs.resize(0);
437 mCaptureRequest.targets.resize(0);
438
439 if (mSessionOutputContainer != nullptr)
440 {
441 IMLOGD0("[DeleteSession] free container");
442 ACaptureSessionOutputContainer_free(mSessionOutputContainer);
443 mSessionOutputContainer = nullptr;
444 }
445
446 return true;
447 }
448
StartSession(bool bRecording)449 bool ImsMediaCamera::StartSession(bool bRecording)
450 {
451 IMLOGD1("[StartSession] recording[%d]", bRecording);
452
453 camera_status_t status;
454 bRecording ? mCameraMode = kCameraModeRecord : kCameraModePreview;
455
456 gCondition.reset();
457 status = ACameraCaptureSession_setRepeatingRequest(
458 mCaptureSession, nullptr, 1, &mCaptureRequest.request, nullptr);
459
460 if (status != ACAMERA_OK)
461 {
462 IMLOGE1("[StartSession] error[%s]", GetErrorStr(status));
463 return false;
464 }
465
466 gCondition.wait_timeout(MAX_WAIT_CAMERA);
467 return true;
468 }
469
StopSession()470 bool ImsMediaCamera::StopSession()
471 {
472 IMLOGD1("[StopSession] state[%d]", mCaptureSessionState);
473
474 if (mCaptureSessionState == CaptureSessionState::kStateActive)
475 {
476 gCondition.reset();
477 camera_status_t status = ACameraCaptureSession_stopRepeating(mCaptureSession);
478
479 if (status != ACAMERA_OK)
480 {
481 IMLOGE1("[StopSession] stopRepeating error[%s]", GetErrorStr(status));
482 return false;
483 }
484 }
485
486 gCondition.wait_timeout(MAX_WAIT_CAMERA);
487 return true;
488 }
489
490 /*
491 * Camera Manager Listener object
492 */
OnCameraAvailable(void * context,const char * id)493 void OnCameraAvailable(void* context, const char* id)
494 {
495 IMLOGD1("[OnCameraAvailable] id[%s]", id == nullptr ? "nullptr" : id);
496
497 if (context != nullptr)
498 {
499 reinterpret_cast<ImsMediaCamera*>(context)->OnCameraStatusChanged(id, true);
500 }
501 }
502
OnCameraUnavailable(void * context,const char * id)503 void OnCameraUnavailable(void* context, const char* id)
504 {
505 IMLOGD1("[OnCameraUnavailable] id[%s]", id == nullptr ? "nullptr" : id);
506
507 if (context != nullptr)
508 {
509 reinterpret_cast<ImsMediaCamera*>(context)->OnCameraStatusChanged(id, false);
510 }
511 }
512
OnCameraStatusChanged(const char * id,bool available)513 void ImsMediaCamera::OnCameraStatusChanged(const char* id, bool available)
514 {
515 IMLOGD2("[OnCameraStatusChanged] id[%s], available[%d]", id == nullptr ? "nullptr" : id,
516 available);
517
518 if (id != nullptr && mManager != nullptr && !gCameraIds.empty())
519 {
520 if (gCameraIds.find(std::string(id)) != gCameraIds.end())
521 {
522 gCameraIds[std::string(id)].mAvailable = available;
523
524 if (available)
525 {
526 gCondition.signal();
527 }
528 }
529 }
530 }
531
GetManagerListener()532 ACameraManager_AvailabilityCallbacks* ImsMediaCamera::GetManagerListener()
533 {
534 static ACameraManager_AvailabilityCallbacks cameraMgrListener = {
535 .context = this,
536 .onCameraAvailable = ::OnCameraAvailable,
537 .onCameraUnavailable = ::OnCameraUnavailable,
538 };
539 return &cameraMgrListener;
540 }
541
542 /*
543 * CameraDevice callbacks
544 */
OnDeviceStateChanges(void * context,ACameraDevice * dev)545 void OnDeviceStateChanges(void* context, ACameraDevice* dev)
546 {
547 IMLOGW0("[OnDeviceStateChanges]");
548
549 if (context != nullptr)
550 {
551 reinterpret_cast<ImsMediaCamera*>(context)->OnDeviceState(dev);
552 }
553 }
554
OnDeviceErrorChanges(void * context,ACameraDevice * dev,int err)555 void OnDeviceErrorChanges(void* context, ACameraDevice* dev, int err)
556 {
557 IMLOGW0("[OnDeviceErrorChanges]");
558
559 if (context != nullptr)
560 {
561 reinterpret_cast<ImsMediaCamera*>(context)->OnDeviceError(dev, err);
562 }
563 }
564
GetDeviceListener()565 ACameraDevice_stateCallbacks* ImsMediaCamera::GetDeviceListener()
566 {
567 static ACameraDevice_stateCallbacks cameraDeviceListener = {
568 .context = this,
569 .onDisconnected = ::OnDeviceStateChanges,
570 .onError = ::OnDeviceErrorChanges,
571 };
572 return &cameraDeviceListener;
573 }
574
OnDeviceState(ACameraDevice * dev)575 void ImsMediaCamera::OnDeviceState(ACameraDevice* dev)
576 {
577 std::string id(ACameraDevice_getId(dev));
578 IMLOGW1("[OnDeviceState] device %s is disconnected", id.c_str());
579 gCameraIds[id].mAvailable = false;
580 ACameraDevice_close(gCameraIds[id].mDevice);
581 }
582
583 /*
584 * CameraDevice error state translation, used in
585 * ACameraDevice_ErrorStateCallback
586 */
587 using DEV_ERROR_PAIR = std::pair<int, const char*>;
588 static std::vector<DEV_ERROR_PAIR> devErrors{
589 MAKE_PAIR(ERROR_CAMERA_IN_USE),
590 MAKE_PAIR(ERROR_MAX_CAMERAS_IN_USE),
591 MAKE_PAIR(ERROR_CAMERA_DISABLED),
592 MAKE_PAIR(ERROR_CAMERA_DEVICE),
593 MAKE_PAIR(ERROR_CAMERA_SERVICE),
594 };
595
GetCameraDeviceErrorStr(int err)596 const char* GetCameraDeviceErrorStr(int err)
597 {
598 return GetPairStr<int>(err, devErrors);
599 }
600
PrintCameraDeviceError(int err)601 void PrintCameraDeviceError(int err)
602 {
603 IMLOGD2("[PrintCameraDeviceError] CameraDeviceError(%#x): %s", err,
604 GetCameraDeviceErrorStr(err));
605 }
606
OnDeviceError(ACameraDevice * dev,int err)607 void ImsMediaCamera::OnDeviceError(ACameraDevice* dev, int err)
608 {
609 std::string id(ACameraDevice_getId(dev));
610 IMLOGE2("[OnDeviceError] CameraDevice %s is in error %#x", id.c_str(), err);
611 PrintCameraDeviceError(err);
612 gCameraIds[id].mAvailable = false;
613 gCameraIds[id].mOwner = false;
614 }
615
616 // CaptureSession state callbacks
OnSessionClosed(void * context,ACameraCaptureSession * session)617 void OnSessionClosed(void* context, ACameraCaptureSession* session)
618 {
619 IMLOGW1("[OnSessionClosed] session[%p] closed", session);
620 reinterpret_cast<ImsMediaCamera*>(context)->OnSessionState(
621 session, CaptureSessionState::kStateClosed);
622 }
623
OnSessionReady(void * context,ACameraCaptureSession * session)624 void OnSessionReady(void* context, ACameraCaptureSession* session)
625 {
626 IMLOGW1("[OnSessionReady] session[%p] ready", session);
627 reinterpret_cast<ImsMediaCamera*>(context)->OnSessionState(
628 session, CaptureSessionState::kStateReady);
629 }
630
OnSessionActive(void * context,ACameraCaptureSession * session)631 void OnSessionActive(void* context, ACameraCaptureSession* session)
632 {
633 IMLOGW1("[OnSessionActive] session[%p] active", session);
634 reinterpret_cast<ImsMediaCamera*>(context)->OnSessionState(
635 session, CaptureSessionState::kStateActive);
636 }
637
GetSessionListener()638 ACameraCaptureSession_stateCallbacks* ImsMediaCamera::GetSessionListener()
639 {
640 static ACameraCaptureSession_stateCallbacks sessionListener = {
641 .context = this,
642 .onClosed = ::OnSessionClosed,
643 .onReady = ::OnSessionReady,
644 .onActive = ::OnSessionActive,
645 };
646 return &sessionListener;
647 }
648
OnSessionState(ACameraCaptureSession * session,CaptureSessionState state)649 void ImsMediaCamera::OnSessionState(ACameraCaptureSession* session, CaptureSessionState state)
650 {
651 IMLOGD0("[OnSessionState]");
652
653 if (mCaptureSession == nullptr)
654 {
655 IMLOGW0("[OnSessionState] CaptureSession closed");
656 return;
657 }
658
659 if (!session || session != mCaptureSession)
660 {
661 IMLOGW1("[OnSessionState] CaptureSession is %s", (session ? "NOT our session" : "nullptr"));
662 return;
663 }
664
665 if (state >= CaptureSessionState::kStateMax)
666 {
667 IMLOGE1("[OnSessionState] Wrong state[%d]", state);
668 }
669 else
670 {
671 mCaptureSessionState = state;
672 gCondition.signal();
673 IMLOGD1("[OnSessionState] state[%d]", state);
674 }
675 }
676
EnumerateCamera()677 void ImsMediaCamera::EnumerateCamera()
678 {
679 if (mManager == nullptr)
680 {
681 return;
682 }
683
684 ACameraIdList* cameraIds = nullptr;
685 auto ret = ACameraManager_getCameraIdList(mManager, &cameraIds);
686
687 if (ret != ACAMERA_OK)
688 {
689 return;
690 }
691
692 for (int i = 0; i < cameraIds->numCameras; ++i)
693 {
694 const char* id = cameraIds->cameraIds[i];
695 ACameraMetadata* metadataObj;
696 ACameraManager_getCameraCharacteristics(mManager, id, &metadataObj);
697
698 int32_t count = 0;
699 const uint32_t* tags = nullptr;
700 ACameraMetadata_getAllTags(metadataObj, &count, &tags);
701
702 for (int tagIdx = 0; tagIdx < count; ++tagIdx)
703 {
704 if (ACAMERA_LENS_FACING == tags[tagIdx])
705 {
706 ACameraMetadata_const_entry lensInfo;
707 ACameraMetadata_getConstEntry(metadataObj, tags[tagIdx], &lensInfo);
708 CameraId cam(id);
709 cam.mFacing = static_cast<acamera_metadata_enum_android_lens_facing_t>(
710 lensInfo.data.u8[0]);
711 cam.mOwner = false;
712 cam.mDevice = nullptr;
713 gCameraIds[cam.mId] = cam;
714 IMLOGD2("[EnumerateCamera] cameraId[%s], facing[%d]", cam.mId.c_str(), cam.mFacing);
715 }
716 }
717 ACameraMetadata_free(metadataObj);
718 }
719
720 if (gCameraIds.size() == 0)
721 {
722 IMLOGD0("[EnumerateCamera] No Camera Available on the device");
723 }
724
725 ACameraManager_deleteCameraIdList(cameraIds);
726 }
727
GetSensorOrientation(const int cameraId,int32_t * facing,int32_t * angle)728 bool ImsMediaCamera::GetSensorOrientation(const int cameraId, int32_t* facing, int32_t* angle)
729 {
730 if (!mManager || facing == nullptr || angle == nullptr)
731 {
732 return false;
733 }
734
735 ACameraMetadata* metadataObj;
736 uint32_t idx = 0;
737
738 for (std::map<std::string, CameraId>::iterator it = gCameraIds.begin(); it != gCameraIds.end();
739 ++it)
740 {
741 if (idx == cameraId)
742 {
743 camera_status_t status = ACameraManager_getCameraCharacteristics(
744 mManager, (it->second).mId.c_str(), &metadataObj);
745 if (status == ACAMERA_OK)
746 {
747 ACameraMetadata_const_entry face, orientation;
748 ACameraMetadata_getConstEntry(metadataObj, ACAMERA_LENS_FACING, &face);
749 mCameraFacing = static_cast<int32_t>(face.data.u8[0]);
750 ACameraMetadata_getConstEntry(
751 metadataObj, ACAMERA_SENSOR_ORIENTATION, &orientation);
752 mCameraOrientation = orientation.data.i32[0];
753 mCameraFacing == 0 ? * facing = kCameraFacingFront : * facing = kCameraFacingRear;
754 *angle = mCameraOrientation;
755 ACameraMetadata_free(metadataObj);
756 return true;
757 }
758 }
759 ++idx;
760 }
761
762 return false;
763 }
764
GetExposureRange(int64_t * min,int64_t * max,int64_t * curVal)765 bool ImsMediaCamera::GetExposureRange(int64_t* min, int64_t* max, int64_t* curVal)
766 {
767 if (!mExposureRange.Supported() || !mExposureTime || !min || !max || !curVal)
768 {
769 return false;
770 }
771 *min = mExposureRange.min;
772 *max = mExposureRange.max;
773 *curVal = mExposureTime;
774
775 return true;
776 }
777
GetSensitivityRange(int64_t * min,int64_t * max,int64_t * curVal)778 bool ImsMediaCamera::GetSensitivityRange(int64_t* min, int64_t* max, int64_t* curVal)
779 {
780 if (!mSensitivityRange.Supported() || !mSensitivity || !min || !max || !curVal)
781 {
782 return false;
783 }
784 *min = static_cast<int64_t>(mSensitivityRange.min);
785 *max = static_cast<int64_t>(mSensitivityRange.max);
786 *curVal = mSensitivity;
787 return true;
788 }
789
790 /**
791 * A helper class to assist image size comparison, by comparing the absolute
792 * size
793 * regardless of the portrait or landscape mode.
794 */
795 class DisplayDimension
796 {
797 public:
DisplayDimension(int32_t w,int32_t h)798 DisplayDimension(int32_t w, int32_t h) :
799 w_(w),
800 h_(h),
801 portrait_(false)
802 {
803 if (h > w)
804 {
805 // make it landscape
806 w_ = h;
807 h_ = w;
808 portrait_ = true;
809 }
810 }
DisplayDimension(const DisplayDimension & other)811 DisplayDimension(const DisplayDimension& other)
812 {
813 w_ = other.w_;
814 h_ = other.h_;
815 portrait_ = other.portrait_;
816 }
817
DisplayDimension(void)818 DisplayDimension(void)
819 {
820 w_ = 0;
821 h_ = 0;
822 portrait_ = false;
823 }
operator =(const DisplayDimension & other)824 DisplayDimension& operator=(const DisplayDimension& other)
825 {
826 if (this != &other)
827 {
828 w_ = other.w_;
829 h_ = other.h_;
830 portrait_ = other.portrait_;
831 }
832
833 return (*this);
834 }
835
IsSameRatio(const DisplayDimension & other) const836 bool IsSameRatio(const DisplayDimension& other) const
837 {
838 return (w_ * other.h_ == h_ * other.w_);
839 }
operator >(const DisplayDimension & other) const840 bool operator>(const DisplayDimension& other) const
841 {
842 return (w_ >= other.w_ && h_ >= other.h_);
843 }
operator ==(const DisplayDimension & other) const844 bool operator==(const DisplayDimension& other) const
845 {
846 return (w_ == other.w_ && h_ == other.h_ && portrait_ == other.portrait_);
847 }
operator -(const DisplayDimension & other)848 DisplayDimension operator-(const DisplayDimension& other)
849 {
850 DisplayDimension delta(w_ - other.w_, h_ - other.h_);
851 return delta;
852 }
Flip(void)853 void Flip(void) { portrait_ = !portrait_; }
width(void) const854 int32_t width(void) const { return w_; }
height(void) const855 int32_t height(void) const { return h_; }
856
857 private:
858 int32_t w_, h_;
859 bool portrait_;
860 };
861
MatchCaptureSizeRequest(ANativeWindow * window)862 bool ImsMediaCamera::MatchCaptureSizeRequest(ANativeWindow* window)
863 {
864 DisplayDimension disp(ANativeWindow_getWidth(window), ANativeWindow_getHeight(window));
865 IMLOGD3("[MatchCaptureSizeRequest] request width[%d], height[%d], camOrientation[%d]",
866 disp.width(), disp.height(), mCameraOrientation);
867
868 if (mCameraOrientation == 90 || mCameraOrientation == 270)
869 {
870 disp.Flip();
871 }
872
873 ACameraMetadata* metadata;
874 ACameraManager_getCameraCharacteristics(mManager, mActiveCameraId.c_str(), &metadata);
875 ACameraMetadata_const_entry entry;
876 ACameraMetadata_getConstEntry(metadata, ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, &entry);
877
878 for (int32_t i = 0; i < entry.count; i += 4)
879 {
880 int32_t input = entry.data.i32[i + 3];
881 int32_t format = entry.data.i32[i + 0];
882 if (input)
883 continue;
884
885 if (format == AIMAGE_FORMAT_YUV_420_888 || format == AIMAGE_FORMAT_JPEG)
886 {
887 DisplayDimension dimension(entry.data.i32[i + 1], entry.data.i32[i + 2]);
888 if (!disp.IsSameRatio(dimension))
889 continue;
890
891 // here only width and height should be compared and not portrait flag.
892 if (disp.width() == dimension.width() && disp.height() == dimension.height())
893 {
894 return true;
895 }
896 }
897 }
898
899 return false;
900 }
901