1 // This file is part of OpenCV project.
2 // It is subject to the license terms in the LICENSE file found in the top-level directory
3 // of this distribution and at http://opencv.org/license.html
4 // Contributed by Giles Payne
5
6 #include "precomp.hpp"
7
8 #include <memory>
9 #include <condition_variable>
10 #include <mutex>
11 #include <thread>
12 #include <chrono>
13 #include <android/log.h>
14 #include <camera/NdkCameraManager.h>
15 #include <camera/NdkCameraError.h>
16 #include <camera/NdkCameraDevice.h>
17 #include <camera/NdkCameraMetadataTags.h>
18 #include <media/NdkImageReader.h>
19
20 using namespace cv;
21
22 #define TAG "NativeCamera"
23 #define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, TAG, __VA_ARGS__)
24 #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)
25 #define LOGW(...) __android_log_print(ANDROID_LOG_WARN, TAG, __VA_ARGS__)
26 #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)
27
28 #define MAX_BUF_COUNT 4
29
30 #define COLOR_FormatUnknown -1
31 #define COLOR_FormatYUV420Planar 19
32 #define COLOR_FormatYUV420SemiPlanar 21
33
34 #define FOURCC_BGR CV_FOURCC_MACRO('B','G','R','3')
35 #define FOURCC_RGB CV_FOURCC_MACRO('R','G','B','3')
36 #define FOURCC_GRAY CV_FOURCC_MACRO('G','R','E','Y')
37 #define FOURCC_NV21 CV_FOURCC_MACRO('N','V','2','1')
38 #define FOURCC_YV12 CV_FOURCC_MACRO('Y','V','1','2')
39 #define FOURCC_UNKNOWN 0xFFFFFFFF
40
41 template <typename T> class RangeValue {
42 public:
43 T min, max;
44 /**
45 * return absolute value from relative value
46 * * value: in percent (50 for 50%)
47 * */
value(int percent)48 T value(int percent) {
49 return static_cast<T>(min + (max - min) * percent / 100);
50 }
RangeValue()51 RangeValue() { min = max = static_cast<T>(0); }
Supported(void) const52 bool Supported(void) const { return (min != max); }
53 };
54
deleter_ACameraManager(ACameraManager * cameraManager)55 static inline void deleter_ACameraManager(ACameraManager *cameraManager) {
56 ACameraManager_delete(cameraManager);
57 }
58
deleter_ACameraIdList(ACameraIdList * cameraIdList)59 static inline void deleter_ACameraIdList(ACameraIdList *cameraIdList) {
60 ACameraManager_deleteCameraIdList(cameraIdList);
61 }
62
deleter_ACameraDevice(ACameraDevice * cameraDevice)63 static inline void deleter_ACameraDevice(ACameraDevice *cameraDevice) {
64 ACameraDevice_close(cameraDevice);
65 }
66
deleter_ACameraMetadata(ACameraMetadata * cameraMetadata)67 static inline void deleter_ACameraMetadata(ACameraMetadata *cameraMetadata) {
68 ACameraMetadata_free(cameraMetadata);
69 }
70
deleter_AImageReader(AImageReader * imageReader)71 static inline void deleter_AImageReader(AImageReader *imageReader) {
72 AImageReader_delete(imageReader);
73 }
74
deleter_ACaptureSessionOutputContainer(ACaptureSessionOutputContainer * outputContainer)75 static inline void deleter_ACaptureSessionOutputContainer(ACaptureSessionOutputContainer *outputContainer) {
76 ACaptureSessionOutputContainer_free(outputContainer);
77 }
78
deleter_ACameraCaptureSession(ACameraCaptureSession * captureSession)79 static inline void deleter_ACameraCaptureSession(ACameraCaptureSession *captureSession) {
80 ACameraCaptureSession_close(captureSession);
81 }
82
deleter_AImage(AImage * image)83 static inline void deleter_AImage(AImage *image) {
84 AImage_delete(image);
85 }
86
deleter_ANativeWindow(ANativeWindow * nativeWindow)87 static inline void deleter_ANativeWindow(ANativeWindow *nativeWindow) {
88 ANativeWindow_release(nativeWindow);
89 }
90
deleter_ACaptureSessionOutput(ACaptureSessionOutput * sessionOutput)91 static inline void deleter_ACaptureSessionOutput(ACaptureSessionOutput *sessionOutput) {
92 ACaptureSessionOutput_free(sessionOutput);
93 }
94
deleter_ACameraOutputTarget(ACameraOutputTarget * outputTarget)95 static inline void deleter_ACameraOutputTarget(ACameraOutputTarget *outputTarget) {
96 ACameraOutputTarget_free(outputTarget);
97 }
98
deleter_ACaptureRequest(ACaptureRequest * captureRequest)99 static inline void deleter_ACaptureRequest(ACaptureRequest *captureRequest) {
100 ACaptureRequest_free(captureRequest);
101 }
102
103 /*
104 * CameraDevice callbacks
105 */
OnDeviceDisconnect(void *,ACameraDevice * dev)106 static void OnDeviceDisconnect(void* /* ctx */, ACameraDevice* dev) {
107 std::string id(ACameraDevice_getId(dev));
108 LOGW("Device %s disconnected", id.c_str());
109 }
110
OnDeviceError(void *,ACameraDevice * dev,int err)111 static void OnDeviceError(void* /* ctx */, ACameraDevice* dev, int err) {
112 std::string id(ACameraDevice_getId(dev));
113 LOGI("Camera Device Error: %#x, Device %s", err, id.c_str());
114
115 switch (err) {
116 case ERROR_CAMERA_IN_USE:
117 LOGI("Camera in use");
118 break;
119 case ERROR_CAMERA_SERVICE:
120 LOGI("Fatal Error occured in Camera Service");
121 break;
122 case ERROR_CAMERA_DEVICE:
123 LOGI("Fatal Error occured in Camera Device");
124 break;
125 case ERROR_CAMERA_DISABLED:
126 LOGI("Camera disabled");
127 break;
128 case ERROR_MAX_CAMERAS_IN_USE:
129 LOGI("System limit for maximum concurrent cameras used was exceeded");
130 break;
131 default:
132 LOGI("Unknown Camera Device Error: %#x", err);
133 }
134 }
135
136 enum class CaptureSessionState {
137 INITIALIZING, // session is ready
138 READY, // session is ready
139 ACTIVE, // session is busy
140 CLOSED // session was closed
141 };
142
143 void OnSessionClosed(void* context, ACameraCaptureSession* session);
144
145 void OnSessionReady(void* context, ACameraCaptureSession* session);
146
147 void OnSessionActive(void* context, ACameraCaptureSession* session);
148
149 void OnCaptureCompleted(void* context,
150 ACameraCaptureSession* session,
151 ACaptureRequest* request,
152 const ACameraMetadata* result);
153
154 void OnCaptureFailed(void* context,
155 ACameraCaptureSession* session,
156 ACaptureRequest* request,
157 ACameraCaptureFailure* failure);
158
159 #define CAPTURE_TIMEOUT_SECONDS 2
160
161 /**
162 * Range of Camera Exposure Time:
163 * Camera's capability range have a very long range which may be disturbing
164 * on camera. For this sample purpose, clamp to a range showing visible
165 * video on preview: 100000ns ~ 250000000ns
166 */
167 static const long kMinExposureTime = 1000000L;
168 static const long kMaxExposureTime = 250000000L;
169
170 class AndroidCameraCapture : public IVideoCapture
171 {
172 int cachedIndex;
173 std::shared_ptr<ACameraManager> cameraManager;
174 std::shared_ptr<ACameraDevice> cameraDevice;
175 std::shared_ptr<AImageReader> imageReader;
176 std::shared_ptr<ACaptureSessionOutputContainer> outputContainer;
177 std::shared_ptr<ACaptureSessionOutput> sessionOutput;
178 std::shared_ptr<ANativeWindow> nativeWindow;
179 std::shared_ptr<ACameraOutputTarget> outputTarget;
180 std::shared_ptr<ACaptureRequest> captureRequest;
181 std::shared_ptr<ACameraCaptureSession> captureSession;
182 CaptureSessionState sessionState = CaptureSessionState::INITIALIZING;
183 int32_t frameWidth = 0;
184 int32_t frameHeight = 0;
185 int32_t colorFormat;
186 std::vector<uint8_t> buffer;
187 bool sessionOutputAdded = false;
188 bool targetAdded = false;
189 // properties
190 uint32_t fourCC = FOURCC_UNKNOWN;
191 bool settingWidth = false;
192 bool settingHeight = false;
193 int desiredWidth = 640;
194 int desiredHeight = 480;
195 bool autoExposure = true;
196 int64_t exposureTime = 0L;
197 RangeValue<int64_t> exposureRange;
198 int32_t sensitivity = 0;
199 RangeValue<int32_t> sensitivityRange;
200
201 public:
202 // for synchronization with NDK capture callback
203 bool waitingCapture = false;
204 bool captureSuccess = false;
205 std::mutex mtx;
206 std::condition_variable condition;
207
208 public:
AndroidCameraCapture()209 AndroidCameraCapture() {}
210
~AndroidCameraCapture()211 ~AndroidCameraCapture() { cleanUp(); }
212
GetDeviceListener()213 ACameraDevice_stateCallbacks* GetDeviceListener() {
214 static ACameraDevice_stateCallbacks cameraDeviceListener = {
215 .onDisconnected = ::OnDeviceDisconnect,
216 .onError = ::OnDeviceError,
217 };
218 return &cameraDeviceListener;
219 }
220
221 ACameraCaptureSession_stateCallbacks sessionListener;
222
GetSessionListener()223 ACameraCaptureSession_stateCallbacks* GetSessionListener() {
224 sessionListener = {
225 .context = this,
226 .onClosed = ::OnSessionClosed,
227 .onReady = ::OnSessionReady,
228 .onActive = ::OnSessionActive,
229 };
230 return &sessionListener;
231 }
232
233 ACameraCaptureSession_captureCallbacks captureListener;
234
GetCaptureCallback()235 ACameraCaptureSession_captureCallbacks* GetCaptureCallback() {
236 captureListener = {
237 .context = this,
238 .onCaptureStarted = nullptr,
239 .onCaptureProgressed = nullptr,
240 .onCaptureCompleted = ::OnCaptureCompleted,
241 .onCaptureFailed = ::OnCaptureFailed,
242 .onCaptureSequenceCompleted = nullptr,
243 .onCaptureSequenceAborted = nullptr,
244 .onCaptureBufferLost = nullptr,
245 };
246 return &captureListener;
247 }
248
setSessionState(CaptureSessionState newSessionState)249 void setSessionState(CaptureSessionState newSessionState) {
250 this->sessionState = newSessionState;
251 }
252
isOpened() const253 bool isOpened() const CV_OVERRIDE { return imageReader.get() != nullptr && captureSession.get() != nullptr; }
254
getCaptureDomain()255 int getCaptureDomain() CV_OVERRIDE { return CAP_ANDROID; }
256
grabFrame()257 bool grabFrame() CV_OVERRIDE
258 {
259 AImage* img;
260 {
261 std::unique_lock<std::mutex> lock(mtx);
262 media_status_t mStatus = AImageReader_acquireLatestImage(imageReader.get(), &img);
263 if (mStatus != AMEDIA_OK) {
264 if (mStatus == AMEDIA_IMGREADER_NO_BUFFER_AVAILABLE) {
265 // this error is not fatal - we just need to wait for a buffer to become available
266 LOGW("No Buffer Available error occured - waiting for callback");
267 waitingCapture = true;
268 captureSuccess = false;
269 bool captured = condition.wait_for(lock, std::chrono::seconds(CAPTURE_TIMEOUT_SECONDS), [this]{ return captureSuccess; });
270 waitingCapture = false;
271 if (captured) {
272 mStatus = AImageReader_acquireLatestImage(imageReader.get(), &img);
273 if (mStatus != AMEDIA_OK) {
274 LOGE("Acquire image failed with error code: %d", mStatus);
275 return false;
276 }
277 } else {
278 LOGE("Capture failed or callback timed out");
279 return false;
280 }
281 } else {
282 LOGE("Acquire image failed with error code: %d", mStatus);
283 return false;
284 }
285 }
286 }
287 std::shared_ptr<AImage> image = std::shared_ptr<AImage>(img, deleter_AImage);
288 int32_t srcFormat = -1;
289 AImage_getFormat(image.get(), &srcFormat);
290 if (srcFormat != AIMAGE_FORMAT_YUV_420_888) {
291 LOGE("Incorrect image format");
292 return false;
293 }
294 int32_t srcPlanes = 0;
295 AImage_getNumberOfPlanes(image.get(), &srcPlanes);
296 if (srcPlanes != 3) {
297 LOGE("Incorrect number of planes in image data");
298 return false;
299 }
300 int32_t yStride, uvStride;
301 uint8_t *yPixel, *uPixel, *vPixel;
302 int32_t yLen, uLen, vLen;
303 int32_t uvPixelStride;
304 AImage_getPlaneRowStride(image.get(), 0, &yStride);
305 AImage_getPlaneRowStride(image.get(), 1, &uvStride);
306 AImage_getPlaneData(image.get(), 0, &yPixel, &yLen);
307 AImage_getPlaneData(image.get(), 1, &vPixel, &vLen);
308 AImage_getPlaneData(image.get(), 2, &uPixel, &uLen);
309 AImage_getPlanePixelStride(image.get(), 1, &uvPixelStride);
310
311 if ( (uvPixelStride == 2) && (vPixel == uPixel + 1) && (yLen == frameWidth * frameHeight) && (uLen == ((yLen / 2) - 1)) && (vLen == uLen) ) {
312 colorFormat = COLOR_FormatYUV420SemiPlanar;
313 if (fourCC == FOURCC_UNKNOWN) {
314 fourCC = FOURCC_NV21;
315 }
316 } else if ( (uvPixelStride == 1) && (vPixel = uPixel + uLen) && (yLen == frameWidth * frameHeight) && (uLen == yLen / 4) && (vLen == uLen) ) {
317 colorFormat = COLOR_FormatYUV420Planar;
318 if (fourCC == FOURCC_UNKNOWN) {
319 fourCC = FOURCC_YV12;
320 }
321 } else {
322 colorFormat = COLOR_FormatUnknown;
323 fourCC = FOURCC_UNKNOWN;
324 LOGE("Unsupported format");
325 return false;
326 }
327
328 buffer.clear();
329 buffer.insert(buffer.end(), yPixel, yPixel + yLen);
330 buffer.insert(buffer.end(), uPixel, uPixel + yLen / 2);
331 return true;
332 }
333
retrieveFrame(int,OutputArray out)334 bool retrieveFrame(int, OutputArray out) CV_OVERRIDE
335 {
336 if (buffer.empty()) {
337 return false;
338 }
339 Mat yuv(frameHeight + frameHeight/2, frameWidth, CV_8UC1, buffer.data());
340 if (colorFormat == COLOR_FormatYUV420Planar) {
341 switch (fourCC) {
342 case FOURCC_BGR:
343 cv::cvtColor(yuv, out, cv::COLOR_YUV2BGR_YV12);
344 break;
345 case FOURCC_RGB:
346 cv::cvtColor(yuv, out, cv::COLOR_YUV2RGB_YV12);
347 break;
348 case FOURCC_GRAY:
349 cv::cvtColor(yuv, out, cv::COLOR_YUV2GRAY_YV12);
350 break;
351 case FOURCC_YV12:
352 yuv.copyTo(out);
353 break;
354 default:
355 LOGE("Unexpected FOURCC value: %d", fourCC);
356 break;
357 }
358 } else if (colorFormat == COLOR_FormatYUV420SemiPlanar) {
359 switch (fourCC) {
360 case FOURCC_BGR:
361 cv::cvtColor(yuv, out, cv::COLOR_YUV2BGR_NV21);
362 break;
363 case FOURCC_RGB:
364 cv::cvtColor(yuv, out, cv::COLOR_YUV2RGB_NV21);
365 break;
366 case FOURCC_GRAY:
367 cv::cvtColor(yuv, out, cv::COLOR_YUV2GRAY_NV21);
368 break;
369 case FOURCC_NV21:
370 yuv.copyTo(out);
371 break;
372 default:
373 LOGE("Unexpected FOURCC value: %d", fourCC);
374 break;
375 }
376 } else {
377 LOGE("Unsupported video format: %d", colorFormat);
378 return false;
379 }
380 return true;
381 }
382
getProperty(int property_id) const383 double getProperty(int property_id) const CV_OVERRIDE
384 {
385 switch (property_id) {
386 case CV_CAP_PROP_FRAME_WIDTH:
387 return isOpened() ? frameWidth : desiredWidth;
388 case CV_CAP_PROP_FRAME_HEIGHT:
389 return isOpened() ? frameHeight : desiredHeight;
390 case CAP_PROP_AUTO_EXPOSURE:
391 return autoExposure ? 1 : 0;
392 case CV_CAP_PROP_EXPOSURE:
393 return exposureTime;
394 case CV_CAP_PROP_ISO_SPEED:
395 return sensitivity;
396 case CV_CAP_PROP_FOURCC:
397 return fourCC;
398 default:
399 break;
400 }
401 // unknown parameter or value not available
402 return -1;
403 }
404
setProperty(int property_id,double value)405 bool setProperty(int property_id, double value) CV_OVERRIDE
406 {
407 switch (property_id) {
408 case CV_CAP_PROP_FRAME_WIDTH:
409 desiredWidth = value;
410 settingWidth = true;
411 if (settingWidth && settingHeight) {
412 setWidthHeight();
413 settingWidth = false;
414 settingHeight = false;
415 }
416 return true;
417 case CV_CAP_PROP_FRAME_HEIGHT:
418 desiredHeight = value;
419 settingHeight = true;
420 if (settingWidth && settingHeight) {
421 setWidthHeight();
422 settingWidth = false;
423 settingHeight = false;
424 }
425 return true;
426 case CV_CAP_PROP_FOURCC:
427 {
428 uint32_t newFourCC = cvRound(value);
429 if (fourCC == newFourCC) {
430 return true;
431 } else {
432 switch (newFourCC) {
433 case FOURCC_BGR:
434 case FOURCC_RGB:
435 case FOURCC_GRAY:
436 fourCC = newFourCC;
437 return true;
438 case FOURCC_YV12:
439 if (colorFormat == COLOR_FormatYUV420Planar) {
440 fourCC = newFourCC;
441 return true;
442 } else {
443 LOGE("Unsupported FOURCC conversion COLOR_FormatYUV420SemiPlanar -> COLOR_FormatYUV420Planar");
444 return false;
445 }
446 case FOURCC_NV21:
447 if (colorFormat == COLOR_FormatYUV420SemiPlanar) {
448 fourCC = newFourCC;
449 return true;
450 } else {
451 LOGE("Unsupported FOURCC conversion COLOR_FormatYUV420Planar -> COLOR_FormatYUV420SemiPlanar");
452 return false;
453 }
454 default:
455 LOGE("Unsupported FOURCC value: %d\n", fourCC);
456 return false;
457 }
458 }
459 }
460 case CAP_PROP_AUTO_EXPOSURE:
461 autoExposure = (value != 0);
462 if (isOpened()) {
463 uint8_t aeMode = autoExposure ? ACAMERA_CONTROL_AE_MODE_ON : ACAMERA_CONTROL_AE_MODE_OFF;
464 camera_status_t status = ACaptureRequest_setEntry_u8(captureRequest.get(), ACAMERA_CONTROL_AE_MODE, 1, &aeMode);
465 return status == ACAMERA_OK;
466 }
467 return true;
468 case CV_CAP_PROP_EXPOSURE:
469 if (isOpened() && exposureRange.Supported()) {
470 exposureTime = (int64_t)value;
471 LOGI("Setting CV_CAP_PROP_EXPOSURE will have no effect unless CAP_PROP_AUTO_EXPOSURE is off");
472 camera_status_t status = ACaptureRequest_setEntry_i64(captureRequest.get(), ACAMERA_SENSOR_EXPOSURE_TIME, 1, &exposureTime);
473 return status == ACAMERA_OK;
474 }
475 return false;
476 case CV_CAP_PROP_ISO_SPEED:
477 if (isOpened() && sensitivityRange.Supported()) {
478 sensitivity = (int32_t)value;
479 LOGI("Setting CV_CAP_PROP_ISO_SPEED will have no effect unless CAP_PROP_AUTO_EXPOSURE is off");
480 camera_status_t status = ACaptureRequest_setEntry_i32(captureRequest.get(), ACAMERA_SENSOR_SENSITIVITY, 1, &sensitivity);
481 return status == ACAMERA_OK;
482 }
483 return false;
484 default:
485 break;
486 }
487 return false;
488 }
489
setWidthHeight()490 void setWidthHeight() {
491 cleanUp();
492 initCapture(cachedIndex);
493 }
494
495 // calculate a score based on how well the width and height match the desired width and height
496 // basically draw the 2 rectangle on top of each other and take the ratio of the non-overlapping
497 // area to the overlapping area
getScore(int32_t width,int32_t height)498 double getScore(int32_t width, int32_t height) {
499 double area1 = width * height;
500 double area2 = desiredWidth * desiredHeight;
501 if ((width < desiredWidth) == (height < desiredHeight)) {
502 return (width < desiredWidth) ? (area2 - area1)/area1 : (area1 - area2)/area2;
503 } else {
504 int32_t overlappedWidth = std::min(width, desiredWidth);
505 int32_t overlappedHeight = std::min(height, desiredHeight);
506 double overlappedArea = overlappedWidth * overlappedHeight;
507 return (area1 + area2 - overlappedArea)/overlappedArea;
508 }
509 }
510
initCapture(int index)511 bool initCapture(int index)
512 {
513 cachedIndex = index;
514 cameraManager = std::shared_ptr<ACameraManager>(ACameraManager_create(), deleter_ACameraManager);
515 if (!cameraManager) {
516 return false;
517 }
518 ACameraIdList* cameraIds = nullptr;
519 camera_status_t cStatus = ACameraManager_getCameraIdList(cameraManager.get(), &cameraIds);
520 if (cStatus != ACAMERA_OK) {
521 LOGE("Get camera list failed with error code: %d", cStatus);
522 return false;
523 }
524 std::shared_ptr<ACameraIdList> cameraIdList = std::shared_ptr<ACameraIdList>(cameraIds, deleter_ACameraIdList);
525 if (index < 0 || index >= cameraIds->numCameras) {
526 LOGE("Camera index out of range %d (Number of cameras: %d)", index, cameraIds->numCameras);
527 return false;
528 }
529 ACameraDevice* camera = nullptr;
530 cStatus = ACameraManager_openCamera(cameraManager.get(), cameraIdList.get()->cameraIds[index], GetDeviceListener(), &camera);
531 if (cStatus != ACAMERA_OK) {
532 LOGE("Open camera failed with error code: %d", cStatus);
533 return false;
534 }
535 cameraDevice = std::shared_ptr<ACameraDevice>(camera, deleter_ACameraDevice);
536 ACameraMetadata* metadata;
537 cStatus = ACameraManager_getCameraCharacteristics(cameraManager.get(), cameraIdList.get()->cameraIds[index], &metadata);
538 if (cStatus != ACAMERA_OK) {
539 LOGE("Get camera characteristics failed with error code: %d", cStatus);
540 return false;
541 }
542 std::shared_ptr<ACameraMetadata> cameraMetadata = std::shared_ptr<ACameraMetadata>(metadata, deleter_ACameraMetadata);
543 ACameraMetadata_const_entry entry;
544 ACameraMetadata_getConstEntry(cameraMetadata.get(), ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, &entry);
545
546 double bestScore = std::numeric_limits<double>::max();
547 int32_t bestMatchWidth = 0;
548 int32_t bestMatchHeight = 0;
549
550 for (uint32_t i = 0; i < entry.count; i += 4) {
551 int32_t input = entry.data.i32[i + 3];
552 int32_t format = entry.data.i32[i + 0];
553 if (input) {
554 continue;
555 }
556 if (format == AIMAGE_FORMAT_YUV_420_888) {
557 int32_t width = entry.data.i32[i + 1];
558 int32_t height = entry.data.i32[i + 2];
559 if (width == desiredWidth && height == desiredHeight) {
560 bestMatchWidth = width;
561 bestMatchHeight = height;
562 bestScore = 0;
563 break;
564 } else {
565 double score = getScore(width, height);
566 if (score < bestScore) {
567 bestMatchWidth = width;
568 bestMatchHeight = height;
569 bestScore = score;
570 }
571 }
572 }
573 }
574
575 ACameraMetadata_const_entry val = { 0, };
576 camera_status_t status = ACameraMetadata_getConstEntry(cameraMetadata.get(), ACAMERA_SENSOR_INFO_EXPOSURE_TIME_RANGE, &val);
577 if (status == ACAMERA_OK) {
578 exposureRange.min = val.data.i64[0];
579 if (exposureRange.min < kMinExposureTime) {
580 exposureRange.min = kMinExposureTime;
581 }
582 exposureRange.max = val.data.i64[1];
583 if (exposureRange.max > kMaxExposureTime) {
584 exposureRange.max = kMaxExposureTime;
585 }
586 exposureTime = exposureRange.value(2);
587 } else {
588 LOGW("Unsupported ACAMERA_SENSOR_INFO_EXPOSURE_TIME_RANGE");
589 exposureRange.min = exposureRange.max = 0l;
590 exposureTime = 0l;
591 }
592 status = ACameraMetadata_getConstEntry(cameraMetadata.get(), ACAMERA_SENSOR_INFO_SENSITIVITY_RANGE, &val);
593 if (status == ACAMERA_OK){
594 sensitivityRange.min = val.data.i32[0];
595 sensitivityRange.max = val.data.i32[1];
596 sensitivity = sensitivityRange.value(2);
597 } else {
598 LOGW("Unsupported ACAMERA_SENSOR_INFO_SENSITIVITY_RANGE");
599 sensitivityRange.min = sensitivityRange.max = 0;
600 sensitivity = 0;
601 }
602
603 AImageReader* reader;
604 media_status_t mStatus = AImageReader_new(bestMatchWidth, bestMatchHeight, AIMAGE_FORMAT_YUV_420_888, MAX_BUF_COUNT, &reader);
605 if (mStatus != AMEDIA_OK) {
606 LOGE("ImageReader creation failed with error code: %d", mStatus);
607 return false;
608 }
609 frameWidth = bestMatchWidth;
610 frameHeight = bestMatchHeight;
611 imageReader = std::shared_ptr<AImageReader>(reader, deleter_AImageReader);
612
613 ANativeWindow *window;
614 mStatus = AImageReader_getWindow(imageReader.get(), &window);
615 if (mStatus != AMEDIA_OK) {
616 LOGE("Could not get ANativeWindow: %d", mStatus);
617 return false;
618 }
619 nativeWindow = std::shared_ptr<ANativeWindow>(window, deleter_ANativeWindow);
620
621 ACaptureSessionOutputContainer* container;
622 cStatus = ACaptureSessionOutputContainer_create(&container);
623 if (cStatus != ACAMERA_OK) {
624 LOGE("CaptureSessionOutputContainer creation failed with error code: %d", cStatus);
625 return false;
626 }
627 outputContainer = std::shared_ptr<ACaptureSessionOutputContainer>(container, deleter_ACaptureSessionOutputContainer);
628
629 ANativeWindow_acquire(nativeWindow.get());
630 ACaptureSessionOutput* output;
631 cStatus = ACaptureSessionOutput_create(nativeWindow.get(), &output);
632 if (cStatus != ACAMERA_OK) {
633 LOGE("CaptureSessionOutput creation failed with error code: %d", cStatus);
634 return false;
635 }
636 sessionOutput = std::shared_ptr<ACaptureSessionOutput>(output, deleter_ACaptureSessionOutput);
637 ACaptureSessionOutputContainer_add(outputContainer.get(), sessionOutput.get());
638 sessionOutputAdded = true;
639
640 ACameraOutputTarget* target;
641 cStatus = ACameraOutputTarget_create(nativeWindow.get(), &target);
642 if (cStatus != ACAMERA_OK) {
643 LOGE("CameraOutputTarget creation failed with error code: %d", cStatus);
644 return false;
645 }
646 outputTarget = std::shared_ptr<ACameraOutputTarget>(target, deleter_ACameraOutputTarget);
647
648 ACaptureRequest * request;
649 cStatus = ACameraDevice_createCaptureRequest(cameraDevice.get(), TEMPLATE_PREVIEW, &request);
650 if (cStatus != ACAMERA_OK) {
651 LOGE("CaptureRequest creation failed with error code: %d", cStatus);
652 return false;
653 }
654 captureRequest = std::shared_ptr<ACaptureRequest>(request, deleter_ACaptureRequest);
655
656 cStatus = ACaptureRequest_addTarget(captureRequest.get(), outputTarget.get());
657 if (cStatus != ACAMERA_OK) {
658 LOGE("Add target to CaptureRequest failed with error code: %d", cStatus);
659 return false;
660 }
661 targetAdded = true;
662
663 ACameraCaptureSession *session;
664 cStatus = ACameraDevice_createCaptureSession(cameraDevice.get(), outputContainer.get(), GetSessionListener(), &session);
665 if (cStatus != ACAMERA_OK) {
666 LOGE("CaptureSession creation failed with error code: %d", cStatus);
667 return false;
668 }
669 captureSession = std::shared_ptr<ACameraCaptureSession>(session, deleter_ACameraCaptureSession);
670 uint8_t aeMode = autoExposure ? ACAMERA_CONTROL_AE_MODE_ON : ACAMERA_CONTROL_AE_MODE_OFF;
671 ACaptureRequest_setEntry_u8(captureRequest.get(), ACAMERA_CONTROL_AE_MODE, 1, &aeMode);
672 ACaptureRequest_setEntry_i32(captureRequest.get(), ACAMERA_SENSOR_SENSITIVITY, 1, &sensitivity);
673 if (!autoExposure) {
674 ACaptureRequest_setEntry_i64(captureRequest.get(), ACAMERA_SENSOR_EXPOSURE_TIME, 1, &exposureTime);
675 }
676
677 cStatus = ACameraCaptureSession_setRepeatingRequest(captureSession.get(), GetCaptureCallback(), 1, &request, nullptr);
678 if (cStatus != ACAMERA_OK) {
679 LOGE("CameraCaptureSession set repeating request failed with error code: %d", cStatus);
680 return false;
681 }
682 return true;
683 }
684
cleanUp()685 void cleanUp() {
686 captureListener.context = nullptr;
687 sessionListener.context = nullptr;
688 if (sessionState == CaptureSessionState::ACTIVE) {
689 ACameraCaptureSession_stopRepeating(captureSession.get());
690 }
691 captureSession = nullptr;
692 if (targetAdded) {
693 ACaptureRequest_removeTarget(captureRequest.get(), outputTarget.get());
694 targetAdded = false;
695 }
696 captureRequest = nullptr;
697 outputTarget = nullptr;
698 if (sessionOutputAdded) {
699 ACaptureSessionOutputContainer_remove(outputContainer.get(), sessionOutput.get());
700 sessionOutputAdded = false;
701 }
702 sessionOutput = nullptr;
703 nativeWindow = nullptr;
704 outputContainer = nullptr;
705 cameraDevice = nullptr;
706 cameraManager = nullptr;
707 imageReader = nullptr;
708 }
709 };
710
711 /******************************** Session management *******************************/
712
OnSessionClosed(void * context,ACameraCaptureSession * session)713 void OnSessionClosed(void* context, ACameraCaptureSession* session) {
714 if (context == nullptr) return;
715 LOGW("session %p closed", session);
716 reinterpret_cast<AndroidCameraCapture*>(context)->setSessionState(CaptureSessionState::CLOSED);
717 }
718
OnSessionReady(void * context,ACameraCaptureSession * session)719 void OnSessionReady(void* context, ACameraCaptureSession* session) {
720 if (context == nullptr) return;
721 LOGW("session %p ready", session);
722 reinterpret_cast<AndroidCameraCapture*>(context)->setSessionState(CaptureSessionState::READY);
723 }
724
OnSessionActive(void * context,ACameraCaptureSession * session)725 void OnSessionActive(void* context, ACameraCaptureSession* session) {
726 if (context == nullptr) return;
727 LOGW("session %p active", session);
728 reinterpret_cast<AndroidCameraCapture*>(context)->setSessionState(CaptureSessionState::ACTIVE);
729 }
730
OnCaptureCompleted(void * context,ACameraCaptureSession * session,ACaptureRequest *,const ACameraMetadata *)731 void OnCaptureCompleted(void* context,
732 ACameraCaptureSession* session,
733 ACaptureRequest* /* request */,
734 const ACameraMetadata* /* result */) {
735 if (context == nullptr) return;
736 LOGV("session %p capture completed", session);
737 AndroidCameraCapture* cameraCapture = reinterpret_cast<AndroidCameraCapture*>(context);
738 std::unique_lock<std::mutex> lock(cameraCapture->mtx);
739
740 if (cameraCapture->waitingCapture) {
741 cameraCapture->waitingCapture = false;
742 cameraCapture->captureSuccess = true;
743 cameraCapture->condition.notify_one();
744 }
745 }
746
OnCaptureFailed(void * context,ACameraCaptureSession * session,ACaptureRequest *,ACameraCaptureFailure *)747 void OnCaptureFailed(void* context,
748 ACameraCaptureSession* session,
749 ACaptureRequest* /* request */,
750 ACameraCaptureFailure* /* failure */) {
751 if (context == nullptr) return;
752 LOGV("session %p capture failed", session);
753 AndroidCameraCapture* cameraCapture = reinterpret_cast<AndroidCameraCapture*>(context);
754 std::unique_lock<std::mutex> lock(cameraCapture->mtx);
755
756 if (cameraCapture->waitingCapture) {
757 cameraCapture->waitingCapture = false;
758 cameraCapture->captureSuccess = false;
759 cameraCapture->condition.notify_one();
760 }
761 }
762
763 /****************** Implementation of interface functions ********************/
764
createAndroidCapture_cam(int index)765 Ptr<IVideoCapture> cv::createAndroidCapture_cam( int index ) {
766 Ptr<AndroidCameraCapture> res = makePtr<AndroidCameraCapture>();
767 if (res && res->initCapture(index))
768 return res;
769 return Ptr<IVideoCapture>();
770 }
771