SLProject  4.3.020
A platform independent 3D computer graphics framework for desktop OS, Android, iOS and online in web browsers
SENSAndroidCamera Class Reference

#include <SENSAndroidCamera.h>

Inheritance diagram for SENSAndroidCamera:
[legend]

Public Member Functions

 SENSAndroidCamera ()
 
 ~SENSAndroidCamera ()
 
const SENSCameraConfigstart (std::string deviceId, const SENSCameraStreamConfig &streamConfig, bool provideIntrinsics=true) override
 
void stop () override
 Stop a started camera device. More...
 
const SENSCapturePropscaptureProperties () override
 Get SENSCaptureProps which contains necessary information about all available camera devices and their capabilities. More...
 
void onDeviceDisconnected (ACameraDevice *dev)
 
void onDeviceError (ACameraDevice *dev, int err)
 
void onCameraStatusChanged (const char *id, bool available)
 
void onSessionState (ACameraCaptureSession *ses, CaptureSessionState state)
 
void imageCallback (AImageReader *reader)
 
- Public Member Functions inherited from SENSBaseCamera
SENSFrameBasePtr latestFrame () override
 Get the latest captured frame. If no frame was captured the frame will be empty (null). More...
 
const SENSCameraConfigconfig () const override
 defines how the camera was configured during start More...
 
void registerListener (SENSCameraListener *listener) override
 
void unregisterListener (SENSCameraListener *listener) override
 
bool started () const override
 
bool permissionGranted () const override
 
void setPermissionGranted () override
 
- Public Member Functions inherited from SENSCamera
virtual ~SENSCamera ()
 

Private Member Functions

void openCamera ()
 
void createCaptureSession ()
 

Static Private Member Functions

static cv::Mat convertToYuv (AImage *image)
 

Private Attributes

ACameraManager_AvailabilityCallbacks _cameraManagerAvailabilityCallbacks
 
ACameraManager * _cameraManager = nullptr
 
ACameraDevice * _cameraDevice = nullptr
 
AImageReader * _imageReader = nullptr
 
ANativeWindow * _surface = nullptr
 
ACaptureSessionOutput * _captureSessionOutput = nullptr
 
ACaptureSessionOutputContainer * _captureSessionOutputContainer = nullptr
 
ACameraOutputTarget * _cameraOutputTarget = nullptr
 
ACaptureRequest * _captureRequest = nullptr
 
ACameraCaptureSession * _captureSession = nullptr
 
CaptureSessionState _captureSessionState = CaptureSessionState::MAX_STATE
 
std::condition_variable _captureSessionStateCV
 
std::mutex _captureSessionStateMutex
 
std::map< std::string, bool > _cameraAvailability
 
std::mutex _cameraAvailabilityMutex
 
std::condition_variable _openCameraCV
 
std::atomic< bool > _cameraDeviceOpened {false}
 
cv::Size _captureSize
 

Additional Inherited Members

- Protected Member Functions inherited from SENSBaseCamera
void updateFrame (cv::Mat bgrImg, cv::Mat intrinsics, int width, int height, bool intrinsicsChanged)
 
void processStart ()
 call from start function to do startup preprocessing More...
 
- Protected Attributes inherited from SENSBaseCamera
SENSCaptureProps _captureProperties
 
std::atomic< bool > _started {false}
 flags if camera was started More...
 
SENSCameraConfig _config
 indicates what is currently running More...
 
std::atomic< bool > _permissionGranted {false}
 
std::vector< SENSCameraListener * > _listeners
 
std::mutex _listenerMutex
 
SENSFrameBasePtr _frame
 current frame More...
 
std::mutex _frameMutex
 

Detailed Description

Definition at line 32 of file SENSAndroidCamera.h.

Constructor & Destructor Documentation

◆ SENSAndroidCamera()

SENSAndroidCamera::SENSAndroidCamera ( )

Definition at line 74 of file SENSAndroidCamera.cpp.

75  : _cameraDeviceOpened(false)
76 {
77  LOG_NDKCAM_INFO("Camera instantiated");
78 }
#define LOG_NDKCAM_INFO(...)
std::atomic< bool > _cameraDeviceOpened

◆ ~SENSAndroidCamera()

SENSAndroidCamera::~SENSAndroidCamera ( )

Definition at line 80 of file SENSAndroidCamera.cpp.

81 {
82  //stop();
83  LOG_NDKCAM_INFO("~SENSAndroidCamera: Camera destructor finished");
84 }

Member Function Documentation

◆ captureProperties()

const SENSCaptureProps & SENSAndroidCamera::captureProperties ( )
overridevirtual

Get SENSCaptureProps which contains necessary information about all available camera devices and their capabilities.

Implements SENSCamera.

Definition at line 652 of file SENSAndroidCamera.cpp.

653 {
654  if (_captureProperties.size() == 0)
655  {
656  ACameraManager* cameraManager = ACameraManager_create();
657  if (!cameraManager)
658  throw SENSException(SENSType::CAM, "Could not instantiate camera manager!", __LINE__, __FILE__);
659 
660  ACameraIdList* cameraIds = nullptr;
661  if (ACameraManager_getCameraIdList(cameraManager, &cameraIds) != ACAMERA_OK)
662  throw SENSException(SENSType::CAM, "Could not retrieve camera list!", __LINE__, __FILE__);
663 
664  for (int i = 0; i < cameraIds->numCameras; ++i)
665  {
666  std::string cameraId = cameraIds->cameraIds[i];
667 
668  ACameraMetadata* camCharacteristics;
669  ACameraManager_getCameraCharacteristics(cameraManager, cameraId.c_str(), &camCharacteristics);
670 
671  int32_t numEntries = 0; //will be filled by getAllTags with number of entries
672  const uint32_t* tags = nullptr;
673  ACameraMetadata_getAllTags(camCharacteristics, &numEntries, &tags);
674 
675  std::vector<float> focalLengthsMM;
676  cv::Size2f physicalSensorSizeMM;
678 
679  //make a first loop to estimate physical sensor parameters
680  for (int tagIdx = 0; tagIdx < numEntries; ++tagIdx)
681  {
682  ACameraMetadata_const_entry lensInfo = {0};
683  //first check that ACAMERA_LENS_FACING is contained at all
684  if (tags[tagIdx] == ACAMERA_LENS_FACING)
685  {
686  ACameraMetadata_getConstEntry(camCharacteristics, tags[tagIdx], &lensInfo);
687  acamera_metadata_enum_android_lens_facing_t androidFacing = static_cast<acamera_metadata_enum_android_lens_facing_t>(lensInfo.data.u8[0]);
688  if (androidFacing == ACAMERA_LENS_FACING_BACK)
689  facing = SENSCameraFacing::BACK;
690  else if (androidFacing == ACAMERA_LENS_FACING_FRONT)
691  facing = SENSCameraFacing::FRONT;
692  else //if (androidFacing == ACAMERA_LENS_FACING_EXTERNAL)
694  }
695  else if (tags[tagIdx] == ACAMERA_LENS_INFO_AVAILABLE_FOCAL_LENGTHS)
696  {
697  if (ACameraMetadata_getConstEntry(camCharacteristics, tags[tagIdx], &lensInfo) ==
698  ACAMERA_OK)
699  {
700  for (int i = 0; i < lensInfo.count; ++i)
701  {
702  //characteristics.focalLenghtsMM.push_back(lensInfo.data.f[i]);
703  focalLengthsMM.push_back(lensInfo.data.f[i]);
704  }
705  }
706  }
707  else if (tags[tagIdx] == ACAMERA_SENSOR_INFO_PHYSICAL_SIZE)
708  {
709  if (ACameraMetadata_getConstEntry(camCharacteristics, tags[tagIdx], &lensInfo) == ACAMERA_OK)
710  {
711  //characteristics.physicalSensorSizeMM.width = lensInfo.data.f[0];
712  //characteristics.physicalSensorSizeMM.height = lensInfo.data.f[1];
713 
714  physicalSensorSizeMM.width = lensInfo.data.f[0];
715  physicalSensorSizeMM.height = lensInfo.data.f[1];
716  }
717  }
718  }
719 
720  //todo: if we have more than one focal length, what do we do?
721  //if we have more than one focal length, we select the first one..
722 
723  SENSCameraDeviceProps characteristics(cameraId, facing);
724 
725  //in the second loop we use the physical sensor parameters to specify a focal length in pixel for every stream config
726  for (int tagIdx = 0; tagIdx < numEntries; ++tagIdx)
727  {
728  if (tags[tagIdx] == ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS)
729  {
730  ACameraMetadata_const_entry lensInfo = {0};
731  if (ACameraMetadata_getConstEntry(camCharacteristics, tags[tagIdx], &lensInfo) == ACAMERA_OK)
732  {
733  if (lensInfo.count & 0x3)
735  "STREAM_CONFIGURATION (%d) should multiple of 4",
736  __LINE__,
737  __FILE__);
738 
739  if (lensInfo.type != ACAMERA_TYPE_INT32)
741  "STREAM_CONFIGURATION TYPE(%d) is not ACAMERA_TYPE_INT32(1)",
742  __LINE__,
743  __FILE__);
744 
745  int width = 0, height = 0;
746  for (uint32_t i = 0; i < lensInfo.count; i += 4)
747  {
748  //example for content interpretation:
749  //std::string direction = lensInfo.data.i32[i + 3] ? "INPUT" : "OUTPUT";
750  //std::string format = GetFormatStr(lensInfo.data.i32[i]);
751 
752  //OUTPUT format and AIMAGE_FORMAT_YUV_420_888 image format
753  if (!lensInfo.data.i32[i + 3] && lensInfo.data.i32[i] == AIMAGE_FORMAT_YUV_420_888)
754  {
755  width = lensInfo.data.i32[i + 1];
756  height = lensInfo.data.i32[i + 2];
757 
758  float focalLengthPix = -1.f;
759  if (focalLengthsMM.size() && physicalSensorSizeMM.width > 0 && physicalSensorSizeMM.height > 0)
760  {
761  //we assume the image is cropped at one side only. we compare the sensor aspect ratio
762  //with the image aspect ratio and use the uncropped length to estimate a focal length in pixel that fits to this stream configuration size
763  if ((float)physicalSensorSizeMM.width / (float)physicalSensorSizeMM.height > (float)width / (float)height)
764  focalLengthPix = focalLengthsMM.front() / physicalSensorSizeMM.height * (float)height;
765  else
766  focalLengthPix = focalLengthsMM.front() / physicalSensorSizeMM.width * (float)width;
767  }
768 
769  if (!characteristics.contains({width, height}))
770  characteristics.add(width, height, focalLengthPix);
771  }
772  }
773  }
774  }
775  }
776  ACameraMetadata_free(camCharacteristics);
777  _captureProperties.push_back(characteristics);
778  }
779 
780  ACameraManager_deleteCameraIdList(cameraIds);
781  ACameraManager_delete(cameraManager);
782  }
783 
784  return _captureProperties;
785 }
SENSCameraFacing
Definition of camera facing.
Definition: SENSCamera.h:28
SENSCaptureProps _captureProperties
Definition: SENSCamera.h:216

◆ convertToYuv()

cv::Mat SENSAndroidCamera::convertToYuv ( AImage *  image)
staticprivate

Definition at line 464 of file SENSAndroidCamera.cpp.

465 {
466  int32_t height, width, rowStrideY;
467  AImage_getHeight(image, &height);
468  AImage_getWidth(image, &width);
469  AImage_getPlaneRowStride(image, 0, &rowStrideY);
470 
471  //pointers to yuv data planes and length of yuv data planes in byte
472  uint8_t *yPixel, /* *uPixel,*/ *vPixel;
473  int32_t yLen, /*uLen,*/ vLen;
474  AImage_getPlaneData(image, 0, &yPixel, &yLen);
475  //AImage_getPlaneData(image, 1, &uPixel, &uLen);
476  AImage_getPlaneData(image, 2, &vPixel, &vLen);
477 
478  //Attention: There may be additional padding at the end of every line, in this case width is not equal to rowStrideY.
479  //As this padding is not contained at the end of the Y-block, yLen can be calculated as follows:
480  // yLen = rowStrideY * height - (rowStrideY - width)
481  //But when copying the UV-block we have to "insert" the additional padding at the end of the Y-block
482  //in the new yuv image!
483  //(https://stackoverflow.com/questions/40030533/android-camera2-preview-output-sizes)
484  //(https://stackoverflow.com/questions/52726002/camera2-captured-picture-conversion-from-yuv-420-888-to-nv21/52740776#52740776)
485 
486  //copy image data to yuv image: we use the rowStrideY to define the maximum data block width including potential padding
487  cv::Mat yuv(height + (height / 2), rowStrideY, CV_8UC1);
488  memcpy(yuv.data, yPixel, yLen);
489  //The interleaved uv data starts with v pixels, you can inspect this by comparing uPixel and vPixel adresses,
490  //which is one byte lower. So the order is V/U: NV12: YYYYUV NV21: YYYYVU
491  // This is also described like this in wikipedia in section https://en.wikipedia.org/wiki/YUV#Y%E2%80%B2UV420sp_(NV21)_to_RGB_conversion_(Android)
492  // U follows V in the interleaved block (in contradiction to what is shown in the drawing explaining yuv in wikipedia).
493  // As both planes have the same length, but one starts one byte lower, we have to copy one
494  //additional byte to get all the data (see vLen+1).
495  //We do not have to additionally copy the v plane. The u plane contains the interleaved u and v data!
496  memcpy(yuv.data + yLen + (rowStrideY - width), vPixel, vLen + 1);
497 
498  //If there is line padding we get rid of it now by defining a sub region of interest in the target image size
499  if (rowStrideY > width)
500  {
501  cv::Rect roi(0, 0, width, yuv.rows);
502  cv::Mat roiYuv = yuv(roi);
503  return roiYuv;
504  }
505  else
506  return yuv;
507 }

◆ createCaptureSession()

void SENSAndroidCamera::createCaptureSession ( )
private

Definition at line 324 of file SENSAndroidCamera.cpp.

325 {
326  //Get the pointer to a surface from the image reader (Surface from java is like nativeWindow in ndk)
327  AImageReader_getWindow(_imageReader, &_surface);
328 
329  // Avoid surface to be deleted
330  ANativeWindow_acquire(_surface);
331  //create a capture session and provide the surfaces to it
332  ACaptureSessionOutput_create(_surface, &_captureSessionOutput);
333  //create an output container for capture session and add it to the session
334  ACaptureSessionOutputContainer_create(&_captureSessionOutputContainer);
335  ACaptureSessionOutputContainer_add(_captureSessionOutputContainer, _captureSessionOutput);
336 
337  ACameraOutputTarget_create(_surface, &_cameraOutputTarget);
338  ACameraDevice_createCaptureRequest(_cameraDevice, TEMPLATE_PREVIEW, &_captureRequest);
339 
340  ACaptureRequest_addTarget(_captureRequest, _cameraOutputTarget);
341 
343 
344  ACameraCaptureSession_stateCallbacks captureSessionStateCallbacks = {
345  .context = this,
346  .onActive = ::onSessionActive,
347  .onReady = ::onSessionReady,
348  .onClosed = ::onSessionClosed};
349  camera_status_t captureSessionStatus = ACameraDevice_createCaptureSession(_cameraDevice,
351  &captureSessionStateCallbacks,
352  &_captureSession);
353  if (captureSessionStatus != AMEDIA_OK)
354  {
355  LOG_NDKCAM_WARN("Creating capture session failed!");
356  }
357  //throw SENSException(SENSType::CAM, "Could not create capture session!", __LINE__, __FILE__);
358 
359  //adjust capture request properties:
360 
361  //auto focus mode
363  {
364  uint8_t afMode = ACAMERA_CONTROL_AF_MODE_OFF;
365  ACaptureRequest_setEntry_u8(_captureRequest, ACAMERA_CONTROL_AF_MODE, 1, &afMode);
366  float focusDistance = 0.0f;
367  ACaptureRequest_setEntry_float(_captureRequest, ACAMERA_LENS_FOCUS_DISTANCE, 1, &focusDistance);
368  }
369  else
370  {
371  uint8_t afMode = ACAMERA_CONTROL_AF_MODE_CONTINUOUS_VIDEO;
372  ACaptureRequest_setEntry_u8(_captureRequest, ACAMERA_CONTROL_AF_MODE, 1, &afMode);
373  }
374 
375  //digital video stabilization (software) -> turn off by default (for now)
376  {
377  uint8_t mode = ACAMERA_CONTROL_VIDEO_STABILIZATION_MODE_OFF;
378  ACaptureRequest_setEntry_u8(_captureRequest, ACAMERA_CONTROL_VIDEO_STABILIZATION_MODE, 1, &mode);
379  }
380  //optical video stabilization (hardware)
381  {
382  uint8_t mode = ACAMERA_LENS_OPTICAL_STABILIZATION_MODE_OFF;
383  ACaptureRequest_setEntry_u8(_captureRequest, ACAMERA_LENS_OPTICAL_STABILIZATION_MODE, 1, &mode);
384  }
385 
386  //install repeating request
387  ACameraCaptureSession_setRepeatingRequest(_captureSession, nullptr, 1, &_captureRequest, nullptr);
388 }
void onSessionActive(void *ctx, ACameraCaptureSession *ses)
#define LOG_NDKCAM_WARN(...)
void onSessionClosed(void *ctx, ACameraCaptureSession *ses)
void onSessionReady(void *ctx, ACameraCaptureSession *ses)
static WAI::ModeOrbSlam2 * mode
Definition: WAIInterface.cpp:5
ACaptureRequest * _captureRequest
AImageReader * _imageReader
ACaptureSessionOutput * _captureSessionOutput
ACameraOutputTarget * _cameraOutputTarget
CaptureSessionState _captureSessionState
ANativeWindow * _surface
ACameraCaptureSession * _captureSession
ACaptureSessionOutputContainer * _captureSessionOutputContainer
ACameraDevice * _cameraDevice
SENSCameraConfig _config
indicates what is currently running
Definition: SENSCamera.h:218
SENSCameraFocusMode focusMode
autofocus mode
Definition: SENSCamera.h:132

◆ imageCallback()

void SENSAndroidCamera::imageCallback ( AImageReader *  reader)

Definition at line 509 of file SENSAndroidCamera.cpp.

510 {
511  AImage* image = nullptr;
512  media_status_t status = AImageReader_acquireLatestImage(reader, &image);
513  if (status == AMEDIA_OK && image)
514  {
515  cv::Mat yuv = convertToYuv(image);
516 
517  AImage_delete(image);
518 
519  cv::Mat bgr;
520  HighResTimer t;
521  cv::cvtColor(yuv, bgr, cv::COLOR_YUV2BGR_NV21, 3);
522  SENS_DEBUG("SENSAndroidCamera: time for yuv conversion: %f ms", t.elapsedTimeInMilliSec());
523 
524  updateFrame(bgr, cv::Mat(), false, bgr.cols, bgr.rows);
525  }
526 }
#define SENS_DEBUG(...)
Definition: SENS.h:60
High Resolution Timer class using C++11.
Definition: HighResTimer.h:31
float elapsedTimeInMilliSec()
Definition: HighResTimer.h:38
static cv::Mat convertToYuv(AImage *image)
void updateFrame(cv::Mat bgrImg, cv::Mat intrinsics, int width, int height, bool intrinsicsChanged)
Definition: SENSCamera.cpp:220

◆ onCameraStatusChanged()

void SENSAndroidCamera::onCameraStatusChanged ( const char *  id,
bool  available 
)

OnCameraStatusChanged() handles Callback from ACameraManager

Definition at line 596 of file SENSAndroidCamera.cpp.

597 {
598  LOG_NDKCAM_INFO("onCameraStatusChanged: id: %s available: %s ", id, available ? "true" : "false");
599  {
600  std::lock_guard<std::mutex> lock(_cameraAvailabilityMutex);
601  _cameraAvailability[std::string(id)] = available;
602  }
603  _openCameraCV.notify_one();
604 }
std::condition_variable _openCameraCV
std::map< std::string, bool > _cameraAvailability
std::mutex _cameraAvailabilityMutex

◆ onDeviceDisconnected()

void SENSAndroidCamera::onDeviceDisconnected ( ACameraDevice *  dev)

Handle Camera DeviceStateChanges msg, notify device is disconnected simply close the camera

Definition at line 532 of file SENSAndroidCamera.cpp.

533 {
534  if (dev == _cameraDevice)
535  {
536  std::string id(ACameraDevice_getId(dev));
537  LOG_NDKCAM_WARN("device %s is disconnected", id.c_str());
538 
539  {
540  std::lock_guard<std::mutex> lock(_cameraAvailabilityMutex);
541  _cameraAvailability[id] = false;
542  }
543 
544  _cameraDeviceOpened = false;
545  ACameraDevice_close(_cameraDevice);
546  _cameraDevice = nullptr;
547  }
548 }

◆ onDeviceError()

void SENSAndroidCamera::onDeviceError ( ACameraDevice *  dev,
int  err 
)

Handles Camera's deviceErrorChanges message, no action; mainly debugging purpose

Definition at line 555 of file SENSAndroidCamera.cpp.

556 {
557  if (dev == _cameraDevice)
558  {
559  std::string errStr;
560  switch (err)
561  {
562  case ERROR_CAMERA_IN_USE:
563  errStr = "ERROR_CAMERA_IN_USE";
564  break;
565  case ERROR_CAMERA_SERVICE:
566  errStr = "ERROR_CAMERA_SERVICE";
567  break;
568  case ERROR_CAMERA_DEVICE:
569  errStr = "ERROR_CAMERA_DEVICE";
570  break;
571  case ERROR_CAMERA_DISABLED:
572  errStr = "ERROR_CAMERA_DISABLED";
573  break;
574  case ERROR_MAX_CAMERAS_IN_USE:
575  errStr = "ERROR_MAX_CAMERAS_IN_USE";
576  break;
577  default:
578  errStr = "Unknown Error";
579  }
580 
581  std::string id(ACameraDevice_getId(dev));
582  {
583  std::lock_guard<std::mutex> lock(_cameraAvailabilityMutex);
584  _cameraAvailability[id] = false;
585  }
586  _cameraDeviceOpened = false;
587 
588  LOG_NDKCAM_INFO("CameraDevice %s is in error %s", id.c_str(), errStr.c_str());
589  }
590 }

◆ onSessionState()

void SENSAndroidCamera::onSessionState ( ACameraCaptureSession *  ses,
CaptureSessionState  state 
)

Handles capture session state changes. Update into internal session state.

Definition at line 623 of file SENSAndroidCamera.cpp.

625 {
626  if (!_captureSession)
627  LOG_NDKCAM_WARN("onSessionState: CaptureSession is NULL");
628 
629  if (state >= CaptureSessionState::MAX_STATE)
630  {
631  throw SENSException(SENSType::CAM, "Wrong state " + std::to_string((int)state), __LINE__, __FILE__);
632  }
633 
634  LOG_NDKCAM_WARN("onSessionState: CaptureSession state: %s", getPrintableState(state).c_str());
635 
636  {
637  std::lock_guard<std::mutex> lock(_captureSessionStateMutex);
638  _captureSessionState = state;
639 
641  {
642  _started = true;
643  }
644  else
645  {
646  _started = false;
647  }
648  }
649  _captureSessionStateCV.notify_one();
650 }
std::string getPrintableState(CaptureSessionState state)
std::mutex _captureSessionStateMutex
std::condition_variable _captureSessionStateCV
std::atomic< bool > _started
flags if camera was started
Definition: SENSCamera.h:217

◆ openCamera()

void SENSAndroidCamera::openCamera ( )
private

Definition at line 102 of file SENSAndroidCamera.cpp.

103 {
104  //init camera manager
105  if (!_cameraManager)
106  {
107  //init availability
109  {
110  _cameraAvailability[c.deviceId()] = false;
111  }
112 
113  LOG_NDKCAM_DEBUG("openCamera: Creating camera manager ...");
114  _cameraManager = ACameraManager_create();
115  if (!_cameraManager)
116  throw SENSException(SENSType::CAM, "Could not instantiate camera manager!", __LINE__, __FILE__);
117 
118  //register callbacks
120  .context = this,
121  .onCameraAvailable = onCameraAvailable,
122  .onCameraUnavailable = onCameraUnavailable,
123  };
124  ACameraManager_registerAvailabilityCallback(_cameraManager,
126 
127  //Attention: if we never access the _cameraManager the onCameraStatusChanged never comes (seems to be an android bug)
128  {
129  ACameraIdList* cameraIds = nullptr;
130  camera_status_t status = ACameraManager_getCameraIdList(_cameraManager, &cameraIds);
131  ACameraManager_deleteCameraIdList(cameraIds);
132  //PrintCameras(_cameraManager);
133  }
134  LOG_NDKCAM_DEBUG("openCamera: Camera manager created!");
135  }
136 
137  //find current SENSCameraDeviceProps
139 
140  if (!_cameraDeviceOpened)
141  {
142  LOG_NDKCAM_DEBUG("openCamera: Camera device not open");
143  auto condition = [&]
144  {
145  LOG_NDKCAM_DEBUG("openCamera: checking condition");
146  return (_cameraAvailability[camProps->deviceId()]);
147  };
148  std::unique_lock<std::mutex> lock(_cameraAvailabilityMutex);
149  //wait here before opening the required camera device until it is available
150  _openCameraCV.wait(lock, condition);
151 
152  LOG_NDKCAM_DEBUG("openCamera: Opening camera ...");
153  //open the so found camera with _characteristics.cameraId
154  ACameraDevice_stateCallbacks cameraDeviceListener = {
155  .context = this,
156  .onDisconnected = ::onDeviceDisconnected,
157  .onError = ::onDeviceErrorChanges,
158  };
159 
160  camera_status_t cameraState;
161  int n = 0;
162  int nMax = 10;
163  while (n < nMax)
164  {
165  cameraState = ACameraManager_openCamera(_cameraManager,
166  camProps->deviceId().c_str(),
167  &cameraDeviceListener,
168  &_cameraDevice);
169 
170  if (cameraState == ACAMERA_OK)
171  break;
172  n++;
173  }
174 
175  if (cameraState != ACAMERA_OK)
176  {
177  throw SENSException(SENSType::CAM, "Could not camera camera!", __LINE__, __FILE__);
178  }
179  else
180  {
181  _cameraDeviceOpened = true;
182  LOG_NDKCAM_DEBUG("openCamera: Camera opened!");
183  }
184  }
185  else
186  {
187  LOG_NDKCAM_DEBUG("openCamera: Camera device is already open");
188  }
189 
190  const auto& streamConfig = _config.streamConfig;
191  LOG_NDKCAM_INFO("openCamera: CaptureSize (%d, %d)", streamConfig.widthPix, streamConfig.heightPix);
192 
193  if (_imageReader && _captureSize != cv::Size(streamConfig.widthPix, streamConfig.heightPix))
194  {
195  LOG_NDKCAM_INFO("openCamera: ImageReader valid and captureSize does not fit");
196  //stop repeating request and wait for stopped state
197  if (_captureSession)
198  {
199  LOG_NDKCAM_DEBUG("openCamera: Stopping repeating request...");
200  //if (_captureSessionState == CaptureSessionState::ACTIVE)
201  //{
202  ACameraCaptureSession_stopRepeating(_captureSession);
203 
204  auto condition = [&]
205  {
207  };
208  std::unique_lock<std::mutex> lock(_captureSessionStateMutex);
209  //wait here until capture session is stopped
210  _captureSessionStateCV.wait(lock, condition);
211  //}
212  //else
213  // LOG_NDKCAM_WARN("CaptureSessionState NOT ACTIVE");
214  LOG_NDKCAM_DEBUG("openCamera: Repeating request stopped!");
215 
216  //LOG_NDKCAM_DEBUG("stop: closing capture session...");
217  //todo: it is recommended not to close before creating a new session
218  //ACameraCaptureSession_close(_captureSession);
219  //_captureSession = nullptr;
220  }
221 
222  LOG_NDKCAM_DEBUG("openCamera: Free request stuff...");
223  if (_captureRequest)
224  {
225  ACaptureRequest_removeTarget(_captureRequest, _cameraOutputTarget);
226  ACaptureRequest_free(_captureRequest);
227  _captureRequest = nullptr;
228  }
229 
231  {
232  ACaptureSessionOutputContainer_remove(_captureSessionOutputContainer,
234  ACaptureSessionOutput_free(_captureSessionOutput);
235  _captureSessionOutput = nullptr;
236  }
237 
238  if (_surface)
239  {
240  ANativeWindow_release(_surface);
241  _surface = nullptr;
242  }
243 
245  {
246  ACaptureSessionOutputContainer_free(_captureSessionOutputContainer);
248  }
249 
250  if (_imageReader)
251  {
252  LOG_NDKCAM_DEBUG("openCamera: Deleting image reader...");
253  AImageReader_delete(_imageReader);
254  _imageReader = nullptr;
255  }
256  }
257 
259  {
260  if (!_imageReader)
261  {
262  LOG_NDKCAM_INFO("openCamera: Creating image reader...");
263 
264  _captureSize = cv::Size(streamConfig.widthPix, streamConfig.heightPix);
265 
266  //create image reader with 2 surfaces (a surface is the like a ring buffer for images)
267  if (AImageReader_new(streamConfig.widthPix, streamConfig.heightPix, AIMAGE_FORMAT_YUV_420_888, 2, &_imageReader) != AMEDIA_OK)
268  throw SENSException(SENSType::CAM, "Could not create image reader!", __LINE__, __FILE__);
269 
270  //register onImageAvailable listener
271  AImageReader_ImageListener listener{
272  .context = this,
273  .onImageAvailable = onImageCallback,
274  };
275  AImageReader_setImageListener(_imageReader, &listener);
276 
278  }
279  }
280  else
281  {
282  //todo: throw something
283  }
284 }
void onImageCallback(void *ctx, AImageReader *reader)
void onDeviceErrorChanges(void *ctx, ACameraDevice *dev, int err)
void onCameraAvailable(void *ctx, const char *id)
void onCameraUnavailable(void *ctx, const char *id)
#define LOG_NDKCAM_DEBUG(...)
ACameraManager_AvailabilityCallbacks _cameraManagerAvailabilityCallbacks
ACameraManager * _cameraManager
void onDeviceDisconnected(ACameraDevice *dev)
const std::string & deviceId() const
Definition: SENSCamera.h:85
const SENSCameraDeviceProps * camPropsForDeviceId(const std::string &deviceId) const
Definition: SENSCamera.cpp:73
SENSCameraStreamConfig streamConfig
currently selected stream config index (use it to look up original capture size)
Definition: SENSCamera.h:131
std::string deviceId
Definition: SENSCamera.h:130

◆ start()

const SENSCameraConfig & SENSAndroidCamera::start ( std::string  deviceId,
const SENSCameraStreamConfig streamConfig,
bool  provideIntrinsics = true 
)
overridevirtual

Call this function to configure the camera if you exactly know, what device you want to open and with which stream configuration. You can find out these properties by using SENSCaptureProps object (see getCaptureProperties())

Parameters
deviceIdcamera device id to start
streamConfigSENSCameraStreamConfig from camera device. This defines the size of the image. The image is converted to BGR and assigned to SENSFrame::imgBGR.
provideIntrinsicsspecifies if intrinsics estimation should be enabled. The estimated intrinsics are transferred with every SENSFrame as they may be different for every frame (e.g. on iOS). This value has different effects on different architectures.
Returns
the found configuration that is adjusted and used when SENSCamera::start() is called.

Implements SENSCamera.

Definition at line 286 of file SENSAndroidCamera.cpp.

289 {
290  if (_started)
291  {
292  Utils::warnMsg("SENSWebCamera", "Call to start was ignored. Camera is currently running!", __LINE__, __FILE__);
293  return _config;
294  }
295 
296  //retrieve all camera characteristics
297  if (_captureProperties.size() == 0)
299 
300  if (_captureProperties.size() == 0)
301  throw SENSException(SENSType::CAM, "Could not retrieve camera properties!", __LINE__, __FILE__);
302 
303  if (!_captureProperties.containsDeviceId(deviceId))
304  throw SENSException(SENSType::CAM, "DeviceId does not exist!", __LINE__, __FILE__);
305 
308  if (props)
309  facing = props->facing();
310 
311  //init config here
312  _config = SENSCameraConfig(deviceId,
313  streamConfig,
314  facing,
316  processStart();
317 
318  openCamera();
319 
320  _started = true;
321  return _config;
322 }
const SENSCaptureProps & captureProperties() override
Get SENSCaptureProps which contains necessary information about all available camera devices and thei...
void processStart()
call from start function to do startup preprocessing
Definition: SENSCamera.cpp:294
const SENSCameraFacing & facing() const
Definition: SENSCamera.h:86
bool containsDeviceId(const std::string &deviceId) const
Definition: SENSCamera.cpp:61
void warnMsg(const char *tag, const char *msg, const int line, const char *file)
Platform independent warn message output.
Definition: Utils.cpp:1142

◆ stop()

void SENSAndroidCamera::stop ( )
overridevirtual

Stop a started camera device.

Implements SENSCamera.

Definition at line 390 of file SENSAndroidCamera.cpp.

391 {
392  if (_started)
393  {
394  if (_captureSession)
395  {
396  LOG_NDKCAM_DEBUG("stop: stopping repeating request...");
398  {
399  ACameraCaptureSession_stopRepeating(_captureSession);
400  }
401  else
402  LOG_NDKCAM_WARN("stop: CaptureSessionState NOT ACTIVE");
403 
404  LOG_NDKCAM_DEBUG("stop: closing capture session...");
405  //todo: it is recommended not to close before creating a new session
406  ACameraCaptureSession_close(_captureSession);
407  _captureSession = nullptr;
408  }
409 
410  if (_captureRequest)
411  {
412  LOG_NDKCAM_DEBUG("stop: free request stuff...");
413  ACaptureRequest_removeTarget(_captureRequest, _cameraOutputTarget);
414  ACaptureRequest_free(_captureRequest);
415  _captureRequest = nullptr;
416  }
417 
419  {
420  ACaptureSessionOutputContainer_remove(_captureSessionOutputContainer,
422  ACaptureSessionOutput_free(_captureSessionOutput);
423  _captureSessionOutput = nullptr;
424  }
425 
426  if (_surface)
427  {
428  ANativeWindow_release(_surface);
429  _surface = nullptr;
430  }
431 
433  {
434  ACaptureSessionOutputContainer_free(_captureSessionOutputContainer);
436  }
437 
438  if (_cameraDevice)
439  {
440  LOG_NDKCAM_DEBUG("stop: closing camera...");
441  ACameraDevice_close(_cameraDevice);
442  _cameraDevice = nullptr;
443  _cameraDeviceOpened = false;
444  }
445 
446  if (_cameraManager)
447  {
448  LOG_NDKCAM_DEBUG("stop: deleting camera manager...");
449  ACameraManager_unregisterAvailabilityCallback(_cameraManager,
451  ACameraManager_delete(_cameraManager);
452  _cameraManager = nullptr;
453  }
454 
455  if (_imageReader)
456  {
457  LOG_NDKCAM_DEBUG("stop: free image reader...");
458  AImageReader_delete(_imageReader);
459  _imageReader = nullptr;
460  }
461  }
462 }

Member Data Documentation

◆ _cameraAvailability

std::map<std::string, bool> SENSAndroidCamera::_cameraAvailability
private

Definition at line 78 of file SENSAndroidCamera.h.

◆ _cameraAvailabilityMutex

std::mutex SENSAndroidCamera::_cameraAvailabilityMutex
private

Definition at line 79 of file SENSAndroidCamera.h.

◆ _cameraDevice

ACameraDevice* SENSAndroidCamera::_cameraDevice = nullptr
private

Definition at line 63 of file SENSAndroidCamera.h.

◆ _cameraDeviceOpened

std::atomic<bool> SENSAndroidCamera::_cameraDeviceOpened {false}
private

Definition at line 83 of file SENSAndroidCamera.h.

◆ _cameraManager

ACameraManager* SENSAndroidCamera::_cameraManager = nullptr
private

Definition at line 62 of file SENSAndroidCamera.h.

◆ _cameraManagerAvailabilityCallbacks

ACameraManager_AvailabilityCallbacks SENSAndroidCamera::_cameraManagerAvailabilityCallbacks
private

Definition at line 58 of file SENSAndroidCamera.h.

◆ _cameraOutputTarget

ACameraOutputTarget* SENSAndroidCamera::_cameraOutputTarget = nullptr
private

Definition at line 68 of file SENSAndroidCamera.h.

◆ _captureRequest

ACaptureRequest* SENSAndroidCamera::_captureRequest = nullptr
private

Definition at line 69 of file SENSAndroidCamera.h.

◆ _captureSession

ACameraCaptureSession* SENSAndroidCamera::_captureSession = nullptr
private

Definition at line 70 of file SENSAndroidCamera.h.

◆ _captureSessionOutput

ACaptureSessionOutput* SENSAndroidCamera::_captureSessionOutput = nullptr
private

Definition at line 66 of file SENSAndroidCamera.h.

◆ _captureSessionOutputContainer

ACaptureSessionOutputContainer* SENSAndroidCamera::_captureSessionOutputContainer = nullptr
private

Definition at line 67 of file SENSAndroidCamera.h.

◆ _captureSessionState

CaptureSessionState SENSAndroidCamera::_captureSessionState = CaptureSessionState::MAX_STATE
private

Definition at line 72 of file SENSAndroidCamera.h.

◆ _captureSessionStateCV

std::condition_variable SENSAndroidCamera::_captureSessionStateCV
private

Definition at line 73 of file SENSAndroidCamera.h.

◆ _captureSessionStateMutex

std::mutex SENSAndroidCamera::_captureSessionStateMutex
private

Definition at line 74 of file SENSAndroidCamera.h.

◆ _captureSize

cv::Size SENSAndroidCamera::_captureSize
private

Definition at line 86 of file SENSAndroidCamera.h.

◆ _imageReader

AImageReader* SENSAndroidCamera::_imageReader = nullptr
private

Definition at line 64 of file SENSAndroidCamera.h.

◆ _openCameraCV

std::condition_variable SENSAndroidCamera::_openCameraCV
private

Definition at line 80 of file SENSAndroidCamera.h.

◆ _surface

ANativeWindow* SENSAndroidCamera::_surface = nullptr
private

Definition at line 65 of file SENSAndroidCamera.h.


The documentation for this class was generated from the following files: