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