// Tencent is pleased to support the open source community by making ncnn available.
//
// Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
//
// Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// https://opensource.org/licenses/BSD-3-Clause
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
# include "ndkcamera.h"
# include <string>
# include <thread>
# include <numeric>
# include <android/log.h>
# include <opencv2/opencv.hpp>
# include <opencv2/core/core.hpp>
# include <opencv2/highgui.hpp>
# include "mat.h"
# include "gpu.h"
# include "Camera2Helper.h"
# include <AndroidHelper.h>
# include <LogThread.h>
static void onAvailabilityCallback ( void * context , const char * cameraId )
{
( ( NdkCamera * ) context ) - > onAvailabilityCallback ( cameraId ) ;
// ALOGI("CameraStatus::onAvailability CameraId: %s", cameraId);
XYLOG ( XYLOG_SEVERITY_INFO , " CameraStatus::onAvailability CameraId: %s " , cameraId ) ;
}
static void onUnavailabilityCallback ( void * context , const char * cameraId )
{
( ( NdkCamera * ) context ) - > onUnavailabilityCallback ( cameraId ) ;
XYLOG ( XYLOG_SEVERITY_INFO , " CameraStatus::onUnavailability CameraId: %s " , cameraId ) ;
}
static void onDisconnected ( void * context , ACameraDevice * device )
{
( ( NdkCamera * ) context ) - > onDisconnected ( device ) ;
XYLOG ( XYLOG_SEVERITY_INFO , " CameraStatus::onDisconnected CameraId: %s " , ACameraDevice_getId ( device ) ) ;
}
static void onError ( void * context , ACameraDevice * device , int error )
{
if ( ACAMERA_ERROR_CAMERA_DEVICE = = error )
{
}
XYLOG ( XYLOG_SEVERITY_ERROR , " CameraStatus::onError CameraId: %s err=%d " , ACameraDevice_getId ( device ) , error ) ;
std : : string msg = " NdkCamera error code= " + std : : to_string ( error ) ;
( ( NdkCamera * ) context ) - > on_error ( msg ) ;
// __android_log_print(ANDROID_LOG_WARN, "NdkCamera", "onError %p %d", device, error);
}
static void onImageAvailable ( void * context , AImageReader * reader )
{
( ( NdkCamera * ) context ) - > onImageAvailable ( reader ) ;
}
static void onSessionActive ( void * context , ACameraCaptureSession * session )
{
ALOGD ( " onSessionActive %p " , session ) ;
}
static void onSessionReady ( void * context , ACameraCaptureSession * session )
{
ALOGD ( " onSessionReady %p " , session ) ;
( ( NdkCamera * ) context ) - > onSessionReady ( session ) ;
}
static void onSessionClosed ( void * context , ACameraCaptureSession * session )
{
XYLOG ( XYLOG_SEVERITY_INFO , " onSessionClosed %p " , session ) ;
}
void onCaptureFailed ( void * context , ACameraCaptureSession * session , ACaptureRequest * request , ACameraCaptureFailure * failure )
{
XYLOG ( XYLOG_SEVERITY_WARNING , " onCaptureFailed session=%p request=%p reason=%d " , session , request , failure - > reason ) ;
}
void onCaptureSequenceCompleted ( void * context , ACameraCaptureSession * session , int sequenceId , int64_t frameNumber )
{
ALOGD ( " onCaptureSequenceCompleted %p %d %ld " , session , sequenceId , frameNumber ) ;
}
void onCaptureSequenceAborted ( void * context , ACameraCaptureSession * session , int sequenceId )
{
ALOGD ( " onCaptureSequenceAborted %p %d " , session , sequenceId ) ;
}
void onCaptureProgressed ( void * context , ACameraCaptureSession * session , ACaptureRequest * request , const ACameraMetadata * result )
{
( ( NdkCamera * ) context ) - > onCaptureProgressed ( session , request , result ) ;
}
void onCaptureCompleted ( void * context , ACameraCaptureSession * session , ACaptureRequest * request , const ACameraMetadata * result )
{
( ( NdkCamera * ) context ) - > onCaptureCompleted ( session , request , result ) ;
}
NdkCamera : : NdkCamera ( int32_t width , int32_t height , const NdkCamera : : CAMERA_PARAMS & params )
{
camera_facing = 0 ;
camera_orientation = 0 ;
m_params = params ;
m_firstFrame = true ;
mWidth = width ;
mHeight = height ;
m_imagesCaptured = ~ 0 ;
afSupported = false ;
aeLockAvailable = false ;
awbLockAvailable = false ;
sceneModeSupported = false ;
activeArraySize [ 0 ] = 0 ;
activeArraySize [ 1 ] = 0 ;
maxRegions [ 0 ] = 0 ;
maxRegions [ 1 ] = 0 ;
maxRegions [ 2 ] = 0 ;
camera_manager_cb . context = this ;
camera_manager_cb . onCameraAvailable = : : onAvailabilityCallback ;
camera_manager_cb . onCameraUnavailable = : : onUnavailabilityCallback ;
camera_device = 0 ;
image_reader = 0 ;
image_reader_surface = 0 ;
image_reader_target = 0 ;
capture_request = 0 ;
capture_session_output_container = 0 ;
capture_session_output = 0 ;
capture_session = 0 ;
captureSequenceId = 0 ;
lightDetected = false ;
mResult = { 0 } ;
}
NdkCamera : : ~ NdkCamera ( )
{
close ( ) ;
}
int NdkCamera : : open ( const std : : string & cameraId ) {
XYLOG ( XYLOG_SEVERITY_DEBUG , " DBG::try open %s " , cameraId . c_str ( ) ) ;
// camera_facing = _camera_facing;
camera_manager . Create ( ) ;
// ACameraManager_registerAvailabilityCallback(camera_manager, &camera_manager_cb);
// find camera
bool foundIt = false ;
DisplayDimension disp ( mWidth , mHeight ) ;
DisplayDimension foundRes = disp ;
camera_status_t status = ACAMERA_OK ;
ALOGD ( " Start ACameraManager_getCameraIdList " ) ;
{
ACameraIdList * camera_id_list = 0 ;
for ( int retry = 0 ; retry < 100 ; retry + + )
{
status = ACameraManager_getCameraIdList ( camera_manager , & camera_id_list ) ;
AASSERT ( status = = ACAMERA_OK , " ACameraManager_getCameraIdList return error, %d " , status ) ;
for ( int i = 0 ; i < camera_id_list - > numCameras ; + + i ) {
const char * id = camera_id_list - > cameraIds [ i ] ;
if ( cameraId . compare ( id ) = = 0 ) {
foundIt = true ;
break ;
}
}
ACameraManager_deleteCameraIdList ( camera_id_list ) ;
if ( foundIt )
{
break ;
}
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 16 ) ) ;
}
ALOGD ( " End ACameraManager_getCameraIdList " ) ;
// ACameraManager_unregisterAvailabilityCallback(camera_manager, &camera_manager_cb);
if ( ! foundIt )
{
XYLOG ( XYLOG_SEVERITY_ERROR , " Camera Not Found on ID: %s " , cameraId . c_str ( ) ) ;
return 1 ;
}
mCameraId = cameraId ;
ACameraMetadata * camera_metadata = 0 ;
status = ACameraManager_getCameraCharacteristics ( camera_manager , cameraId . c_str ( ) , & camera_metadata ) ;
AASSERT ( status = = ACAMERA_OK , " ACameraManager_getCameraCharacteristics return error, %d " , status ) ;
{
ACameraMetadata_const_entry e = { 0 } ;
camera_status_t status = ACameraMetadata_getConstEntry ( camera_metadata , ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS , & e ) ;
// format of the data: format, width, height, input?, type int32
// DisplayDimension foundRes(4000, 4000);
// DisplayDimension maxJPG(0, 0);
foundIt = false ;
DisplayDimension temp ;
for ( int i = 0 ; i < e . count ; i + = 4 )
{
int32_t input = e . data . i32 [ i + 3 ] ;
int32_t format = e . data . i32 [ i + 0 ] ;
if ( input ) continue ;
// if (format == AIMAGE_FORMAT_YUV_420_888 || format == AIMAGE_FORMAT_JPEG)
{
DisplayDimension res ( e . data . i32 [ i + 1 ] , e . data . i32 [ i + 2 ] ) ;
if ( ! disp . IsSameRatio ( res ) )
{
if ( res . width ( ) > = mWidth & & res . height ( ) > = mHeight )
{
temp = res ;
}
continue ;
}
if ( /*format == AIMAGE_FORMAT_YUV_420_888 && */ res > disp )
{
foundIt = true ;
foundRes = res ;
}
}
}
if ( ! foundIt )
{
foundRes = temp ;
foundIt = true ;
}
}
if ( ! foundIt | | foundRes . width ( ) = = 0 | | foundRes . height ( ) = = 0 )
{
ACameraMetadata_free ( camera_metadata ) ;
XYLOG ( XYLOG_SEVERITY_ERROR , " Camera RES(%d, %d) Not Found on ID: %s " , mWidth , mHeight , cameraId . c_str ( ) ) ;
return 1 ;
}
// foundRes.Flip();
// query faceing
acamera_metadata_enum_android_lens_facing_t facing = ACAMERA_LENS_FACING_FRONT ;
{
ACameraMetadata_const_entry e = { 0 } ;
status = ACameraMetadata_getConstEntry ( camera_metadata , ACAMERA_LENS_FACING , & e ) ;
AASSERT ( status = = ACAMERA_OK , " ACameraMetadata_getConstEntry::ACAMERA_LENS_FACING return error, %d " , status ) ;
if ( status = = ACAMERA_OK )
{
facing = ( acamera_metadata_enum_android_lens_facing_t ) e . data . u8 [ 0 ] ;
}
}
camera_facing = facing ;
// query orientation
int orientation = 0 ;
{
ACameraMetadata_const_entry e = { 0 } ;
status = ACameraMetadata_getConstEntry ( camera_metadata , ACAMERA_SENSOR_ORIENTATION , & e ) ;
AASSERT ( status = = ACAMERA_OK , " ACameraMetadata_getConstEntry::ACAMERA_SENSOR_ORIENTATION return error, %d " , status ) ;
if ( status = = ACAMERA_OK )
{
orientation = ( int ) e . data . i32 [ 0 ] ;
}
}
camera_orientation = orientation ;
{
ACameraMetadata_const_entry e = { 0 } ;
status = ACameraMetadata_getConstEntry ( camera_metadata , ACAMERA_LENS_INFO_MINIMUM_FOCUS_DISTANCE , & e ) ;
}
{
ACameraMetadata_const_entry e = { 0 } ;
status = ACameraMetadata_getConstEntry ( camera_metadata , ACAMERA_CONTROL_AF_AVAILABLE_MODES , & e ) ;
// AASSERT(status == ACAMERA_OK, "ACameraMetadata_getConstEntry::ACAMERA_CONTROL_AF_AVAILABLE_MODES return error, %d", status);
# ifdef _DEBUG
for ( int idx = 0 ; idx < e . count ; idx + + )
{
unsigned int m = e . data . u8 [ idx ] ;
XYLOG ( XYLOG_SEVERITY_DEBUG , " Available AF Mode %u " , m ) ;
}
# endif
afSupported = ( status = = ACAMERA_OK ) & & ! ( e . count = = 0 | | ( e . count = = 1 & & e . data . u8 [ 0 ] = = ACAMERA_CONTROL_AF_MODE_OFF ) ) ;
}
if ( ! afSupported )
{
XYLOG ( XYLOG_SEVERITY_ERROR , " AF not Supported " ) ;
}
{
ACameraMetadata_const_entry val = { 0 } ;
status = ACameraMetadata_getConstEntry ( camera_metadata , ACAMERA_SENSOR_INFO_EXPOSURE_TIME_RANGE , & val ) ;
// AASSERT(status == ACAMERA_OK, "ACameraMetadata_getConstEntry::ACAMERA_SENSOR_INFO_EXPOSURE_TIME_RANGE return error, %d", status);
if ( status = = ACAMERA_OK )
{
exposureRange . min_ = val . data . i64 [ 0 ] ;
if ( exposureRange . min_ < kMinExposureTime )
{
exposureRange . min_ = kMinExposureTime ;
}
exposureRange . max_ = val . data . i64 [ 1 ] ;
if ( exposureRange . max_ > kMaxExposureTime )
{
exposureRange . max_ = kMaxExposureTime ;
}
// exposureTime = exposureRange.value(2);
}
else
{
ALOGW ( " Unsupported ACAMERA_SENSOR_INFO_EXPOSURE_TIME_RANGE " ) ;
exposureRange . min_ = exposureRange . max_ = 0l ;
// exposureTime_ = 0l;
}
}
{
ACameraMetadata_const_entry e = { 0 } ;
status = ACameraMetadata_getConstEntry ( camera_metadata , ACAMERA_CONTROL_AE_LOCK_AVAILABLE , & e ) ;
// AASSERT(status == ACAMERA_OK, "ACameraMetadata_getConstEntry::ACAMERA_CONTROL_AF_AVAILABLE_MODES return error, %d", status);
aeLockAvailable = ( status = = ACAMERA_OK ) ? ( * e . data . u8 = = ACAMERA_CONTROL_AE_LOCK_AVAILABLE_TRUE ) : false ;
}
{
ACameraMetadata_const_entry e = { 0 } ;
status = ACameraMetadata_getConstEntry ( camera_metadata , ACAMERA_CONTROL_AWB_LOCK_AVAILABLE , & e ) ;
awbLockAvailable = ( status = = ACAMERA_OK ) ? ( * e . data . u8 = = ACAMERA_CONTROL_AWB_LOCK_AVAILABLE_TRUE ) : false ;
}
{
ACameraMetadata_const_entry val = { 0 } ;
status = ACameraMetadata_getConstEntry ( camera_metadata , ACAMERA_CONTROL_ZOOM_RATIO_RANGE , & val ) ;
if ( status = = ACAMERA_OK )
{
float zoomRatioMin = val . data . f [ 0 ] ;
float zoomRatioMax = val . data . f [ 1 ] ;
ALOGI ( " Zoom Ratio Range: %f -> %f " , zoomRatioMin , zoomRatioMax ) ;
}
}
{
ACameraMetadata_const_entry val = { 0 } ;
status = ACameraMetadata_getConstEntry ( camera_metadata , ACAMERA_CONTROL_AE_COMPENSATION_RANGE , & val ) ;
if ( status = = ACAMERA_OK )
{
aeCompensationRange . min_ = val . data . i32 [ 0 ] ;
aeCompensationRange . max_ = val . data . i32 [ 1 ] ;
XYLOG ( XYLOG_SEVERITY_DEBUG , " AE_COMPENSATION_RANGE %d-%d " , aeCompensationRange . min_ , aeCompensationRange . max_ ) ;
}
else
{
ALOGW ( " Unsupported ACAMERA_CONTROL_AE_COMPENSATION_RANGE " ) ;
aeCompensationRange . min_ = aeCompensationRange . max_ = 0l ;
}
}
{
ACameraMetadata_const_entry val = { 0 } ;
status = ACameraMetadata_getConstEntry ( camera_metadata , ACAMERA_CONTROL_AE_COMPENSATION_STEP , & val ) ;
if ( status = = ACAMERA_OK )
{
aeCompensationStep = val . data . r [ 0 ] ;
XYLOG ( XYLOG_SEVERITY_DEBUG , " AE_COMPENSATION_RANGE num=%d den=%d " , aeCompensationStep . numerator , aeCompensationStep . denominator ) ;
}
}
{
ACameraMetadata_const_entry val = { 0 } ;
status = ACameraMetadata_getConstEntry ( camera_metadata , ACAMERA_SENSOR_INFO_SENSITIVITY_RANGE , & val ) ;
if ( status = = ACAMERA_OK )
{
sensitivityRange . min_ = val . data . i32 [ 0 ] ;
sensitivityRange . max_ = val . data . i32 [ 1 ] ;
}
else
{
ALOGW ( " failed for ACAMERA_SENSOR_INFO_SENSITIVITY_RANGE " ) ;
sensitivityRange . min_ = sensitivityRange . max_ = 0 ;
}
}
{
ACameraMetadata_const_entry val = { 0 } ;
status = ACameraMetadata_getConstEntry ( camera_metadata , ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE , & val ) ;
if ( status = = ACAMERA_OK )
{
activeArraySize [ 0 ] = val . data . i32 [ 2 ] ;
activeArraySize [ 1 ] = val . data . i32 [ 3 ] ;
}
}
{
ACameraMetadata_const_entry val = { 0 } ;
status = ACameraMetadata_getConstEntry ( camera_metadata , ACAMERA_CONTROL_MAX_REGIONS , & val ) ;
if ( status = = ACAMERA_OK )
{
maxRegions [ 0 ] = val . data . i32 [ 0 ] ;
maxRegions [ 1 ] = val . data . i32 [ 1 ] ;
maxRegions [ 2 ] = val . data . i32 [ 2 ] ;
}
}
{
ACameraMetadata_const_entry e = { 0 } ;
status = ACameraMetadata_getConstEntry ( camera_metadata , ACAMERA_CONTROL_AVAILABLE_SCENE_MODES , & e ) ;
if ( status = = ACAMERA_OK )
{
for ( int i = 0 ; i < e . count ; i + + )
{
if ( m_params . sceneMode = = e . data . u8 [ i ] )
{
sceneModeSupported = true ;
break ;
}
}
}
}
ACameraMetadata_free ( camera_metadata ) ;
}
// open camera
{
ACameraDevice_StateCallbacks camera_device_state_callbacks ;
camera_device_state_callbacks . context = this ;
camera_device_state_callbacks . onDisconnected = : : onDisconnected ;
camera_device_state_callbacks . onError = onError ;
status = ACameraManager_openCamera ( camera_manager , cameraId . c_str ( ) , & camera_device_state_callbacks , & camera_device ) ;
if ( status ! = ACAMERA_OK )
{
XYLOG ( XYLOG_SEVERITY_ERROR , " Failed to open camera %s res=%d " , cameraId . c_str ( ) , status ) ;
return 1 ;
}
}
XYLOG ( XYLOG_SEVERITY_INFO , " CameraStatus::Open %s Orientation=%d width=%d height=%d " , cameraId . c_str ( ) , camera_orientation , foundRes . width ( ) , foundRes . height ( ) ) ;
// setup imagereader and its surface
{
// media_status_t mstatus = AImageReader_new(foundRes.width(), foundRes.height(), AIMAGE_FORMAT_YUV_420_888, /*maxImages*/2, &image_reader);
media_status_t mstatus = AImageReader_new ( foundRes . org_width ( ) , foundRes . org_height ( ) , AIMAGE_FORMAT_YUV_420_888 , /*maxImages*/ 2 , & image_reader ) ;
if ( mstatus = = AMEDIA_OK )
{
AImageReader_ImageListener listener ;
listener . context = this ;
listener . onImageAvailable = : : onImageAvailable ;
mstatus = AImageReader_setImageListener ( image_reader , & listener ) ;
mstatus = AImageReader_getWindow ( image_reader , & image_reader_surface ) ;
// ANativeWindow_setBuffersGeometry(image_reader_surface, width, height,WINDOW_FORMAT_RGBX_8888);
ANativeWindow_acquire ( image_reader_surface ) ;
}
}
m_imagesCaptured = 0 ;
// capture request
{
ACameraDevice_request_template templateId = ( ( afSupported & & m_params . autoFocus ) | |
m_params . autoExposure ) ? TEMPLATE_PREVIEW
: TEMPLATE_STILL_CAPTURE ;
status = ACameraDevice_createCaptureRequest ( camera_device , templateId , & capture_request ) ;
int32_t fpsRange [ 2 ] = { 1 , 10 } ;
status = ACaptureRequest_setEntry_i32 ( capture_request , ACAMERA_CONTROL_AE_TARGET_FPS_RANGE , 2 , fpsRange ) ;
}
if ( afSupported & & m_params . autoFocus ) {
if ( ! m_params . zoom )
{
if ( maxRegions [ 2 ] > 0 )
{
int32_t centerX = activeArraySize [ 0 ] > > 1 ;
int32_t centerY = activeArraySize [ 1 ] > > 1 ;
int32_t sizeX = activeArraySize [ 0 ] > > 4 ;
int32_t sizeY = activeArraySize [ 1 ] > > 4 ;
int32_t afRegions [ ] = { centerX - sizeX , centerY - sizeY , centerX + sizeX , centerY + sizeY , 1000 } ;
status = ACaptureRequest_setEntry_i32 ( capture_request , ACAMERA_CONTROL_AF_REGIONS , 5 , afRegions ) ;
if ( status = = ACAMERA_OK )
{
// m_imagesCaptured = ~0;
# ifdef _DEBUG
int aa = 0 ;
# endif
}
}
// uint8_t afMode = ACAMERA_CONTROL_AF_MODE_CONTINUOUS_VIDEO;
uint8_t afMode = ACAMERA_CONTROL_AF_MODE_CONTINUOUS_PICTURE ;
// uint8_t afMode = ACAMERA_CONTROL_AF_MODE_AUTO;
status = ACaptureRequest_setEntry_u8 ( capture_request , ACAMERA_CONTROL_AF_MODE , 1 , & afMode ) ;
uint8_t trig = ACAMERA_CONTROL_AF_TRIGGER_CANCEL ;
// status = ACaptureRequest_setEntry_u8(capture_request, ACAMERA_CONTROL_AF_TRIGGER, 1, &trig);
trig = ACAMERA_CONTROL_AF_TRIGGER_START ;
// status = ACaptureRequest_setEntry_u8(capture_request, ACAMERA_CONTROL_AF_TRIGGER, 1, &trig);
}
if ( status = = ACAMERA_OK )
{
m_imagesCaptured = ~ 0 ;
}
}
else
{
uint8_t trig = ACAMERA_CONTROL_AF_TRIGGER_START ;
// status = ACaptureRequest_setEntry_u8(capture_request, ACAMERA_CONTROL_AF_TRIGGER, 1, &trig);
// m_imagesCaptured = (status == ACAMERA_OK) ? ~0 : 0;
}
// std::this_thread::sleep_for(std::chrono::milliseconds(128));
{
if ( m_params . sceneMode ! = 0 )
{
uint8_t sceneMode = m_params . sceneMode ;
status = ACaptureRequest_setEntry_u8 ( capture_request , ACAMERA_CONTROL_SCENE_MODE , 1 , & sceneMode ) ;
}
if ( m_params . autoExposure ) {
uint8_t aeMode = ACAMERA_CONTROL_AE_MODE_ON ;
status = ACaptureRequest_setEntry_u8 ( capture_request , ACAMERA_CONTROL_AE_MODE , 1 , & aeMode ) ;
// ACaptureRequest_setEntry_i32(capture_request, ACAMERA_SENSOR_SENSITIVITY, 1, &sensitivity_);
if ( ( aeCompensationRange . min_ ! = 0 | | aeCompensationRange . max_ ! = 0 ) & & m_params . compensation ! = 0 )
{
int32_t compensation = m_params . compensation ;
if ( compensation < aeCompensationRange . min_ )
{
compensation = aeCompensationRange . min_ ;
}
if ( compensation > aeCompensationRange . max_ )
{
compensation = aeCompensationRange . max_ ;
}
// int32_t aeCompensation = aeCompensationRange.max_;
status = ACaptureRequest_setEntry_i32 ( capture_request , ACAMERA_CONTROL_AE_EXPOSURE_COMPENSATION , 1 , & compensation ) ;
if ( status ! = ACAMERA_OK )
{
int aa = 0 ;
}
}
if ( maxRegions [ 0 ] > 0 )
{
int32_t aeRegions [ ] = { 0 , 0 , activeArraySize [ 0 ] - 1 , activeArraySize [ 1 ] - 1 , 1000 } ;
status = ACaptureRequest_setEntry_i32 ( capture_request , ACAMERA_CONTROL_AE_REGIONS , 5 , aeRegions ) ;
if ( status = = ACAMERA_OK )
{
// m_imagesCaptured = ~0;
# ifdef _DEBUG
int aa = 0 ;
# endif
}
}
uint8_t aePrecatureTrigger = ACAMERA_CONTROL_AE_PRECAPTURE_TRIGGER_START ;
status = ACaptureRequest_setEntry_u8 ( capture_request , ACAMERA_CONTROL_AE_PRECAPTURE_TRIGGER , 1 , & aePrecatureTrigger ) ;
if ( status = = ACAMERA_OK )
{
m_imagesCaptured = ~ 0 ;
}
uint8_t aeLockOff = ACAMERA_CONTROL_AE_LOCK_OFF ;
// ACaptureRequest_setEntry_u8(capture_request, ACAMERA_CONTROL_AE_LOCK, 1, &aeLockOff);
}
else
{
uint8_t aeMode = ACAMERA_CONTROL_AE_MODE_OFF ;
status = ACaptureRequest_setEntry_u8 ( capture_request , ACAMERA_CONTROL_AE_MODE , 1 , & aeMode ) ;
if ( m_params . sensitivity > 0 )
{
int32_t sensitivity = m_params . sensitivity ;
status = ACaptureRequest_setEntry_i32 ( capture_request , ACAMERA_SENSOR_SENSITIVITY , 1 , & sensitivity ) ;
}
if ( m_params . exposureTime > 0 )
{
int64_t exposureTime = ( ( int64_t ) m_params . exposureTime ) * 1000000 ;
status = ACaptureRequest_setEntry_i64 ( capture_request , ACAMERA_SENSOR_EXPOSURE_TIME , 1 , & exposureTime ) ;
}
}
// TODO:
// m_imagesCaptured = 0;
uint8_t awbMode = ACAMERA_CONTROL_AWB_MODE_AUTO ;
status = ACaptureRequest_setEntry_u8 ( capture_request , ACAMERA_CONTROL_AWB_MODE , 1 , & awbMode ) ;
#if 0
uint8_t antiBandingMode = ACAMERA_CONTROL_AE_ANTIBANDING_MODE_60HZ ;
status = ACaptureRequest_setEntry_u8 ( capture_request , ACAMERA_CONTROL_AE_ANTIBANDING_MODE , 1 , & antiBandingMode ) ;
uint8_t flicker = ACAMERA_STATISTICS_SCENE_FLICKER_60HZ ;
status = ACaptureRequest_setEntry_u8 ( capture_request , ACAMERA_STATISTICS_SCENE_FLICKER , 1 , & flicker ) ;
# endif
status = ACameraOutputTarget_create ( image_reader_surface , & image_reader_target ) ;
status = ACaptureRequest_addTarget ( capture_request , image_reader_target ) ;
}
if ( m_params . zoom )
{
float zoomRatio = m_params . zoomRatio ;
// uint8_t afMode = ACAMERA_CONTROL_AF_MODE_AUTO;
status = ACaptureRequest_setEntry_float ( capture_request , ACAMERA_CONTROL_ZOOM_RATIO , 1 , & zoomRatio ) ;
if ( status ! = ACAMERA_OK )
{
# ifdef _DEBUG
int aa = 0 ;
# endif
}
}
// capture session
{
ACameraCaptureSession_stateCallbacks camera_capture_session_state_callbacks ;
camera_capture_session_state_callbacks . context = this ;
camera_capture_session_state_callbacks . onActive = onSessionActive ;
camera_capture_session_state_callbacks . onReady = : : onSessionReady ;
camera_capture_session_state_callbacks . onClosed = onSessionClosed ;
status = ACaptureSessionOutputContainer_create ( & capture_session_output_container ) ;
status = ACaptureSessionOutput_create ( image_reader_surface , & capture_session_output ) ;
status = ACaptureSessionOutputContainer_add ( capture_session_output_container , capture_session_output ) ;
status = ACameraDevice_createCaptureSession ( camera_device , capture_session_output_container , & camera_capture_session_state_callbacks , & capture_session ) ;
ACameraCaptureSession_captureCallbacks camera_capture_session_capture_callbacks ;
camera_capture_session_capture_callbacks . context = this ;
camera_capture_session_capture_callbacks . onCaptureStarted = 0 ;
camera_capture_session_capture_callbacks . onCaptureProgressed = : : onCaptureProgressed ;
camera_capture_session_capture_callbacks . onCaptureCompleted = : : onCaptureCompleted ;
camera_capture_session_capture_callbacks . onCaptureFailed = onCaptureFailed ;
camera_capture_session_capture_callbacks . onCaptureSequenceCompleted = onCaptureSequenceCompleted ;
camera_capture_session_capture_callbacks . onCaptureSequenceAborted = onCaptureSequenceAborted ;
camera_capture_session_capture_callbacks . onCaptureBufferLost = 0 ;
if ( m_imagesCaptured ! = 0 )
{
status = ACameraCaptureSession_setRepeatingRequest ( capture_session , & camera_capture_session_capture_callbacks , 1 , & capture_request , & captureSequenceId ) ;
}
else
{
status = ACameraCaptureSession_capture ( capture_session , & camera_capture_session_capture_callbacks , 1 , & capture_request , & captureSequenceId ) ;
}
m_startTime = GetMicroTimeStamp ( ) ;
}
return status = = ACAMERA_OK ? 0 : 1 ;
}
void NdkCamera : : close ( )
{
XYLOG ( XYLOG_SEVERITY_INFO , " CameraStatus::try close %s " , mCameraId . c_str ( ) ) ;
camera_status_t res = ACAMERA_OK ;
if ( ( ACameraManager * ) camera_manager ! = NULL )
{
// res = ACameraManager_unregisterAvailabilityCallback(camera_manager, &camera_manager_cb);
}
if ( capture_session )
{
// res = ACameraCaptureSession_stopRepeating(capture_session);
ACameraCaptureSession_close ( capture_session ) ;
capture_session = 0 ;
}
if ( capture_request )
{
res = ACaptureRequest_removeTarget ( capture_request , image_reader_target ) ;
ACaptureRequest_free ( capture_request ) ;
capture_request = 0 ;
}
if ( image_reader_target )
{
ACameraOutputTarget_free ( image_reader_target ) ;
image_reader_target = 0 ;
}
if ( capture_session_output )
{
if ( capture_session_output_container )
{
ACaptureSessionOutputContainer_remove ( capture_session_output_container , capture_session_output ) ;
}
ACaptureSessionOutput_free ( capture_session_output ) ;
capture_session_output = 0 ;
}
if ( capture_session_output_container )
{
ACaptureSessionOutputContainer_free ( capture_session_output_container ) ;
capture_session_output_container = 0 ;
}
if ( camera_device )
{
XYLOG ( XYLOG_SEVERITY_INFO , " CameraStatus::close device %s, %p " , mCameraId . c_str ( ) , camera_device ) ;
ACameraDevice_close ( camera_device ) ;
XYLOG ( XYLOG_SEVERITY_INFO , " CameraStatus::closed device %s, %p " , mCameraId . c_str ( ) , camera_device ) ;
camera_device = 0 ;
}
if ( image_reader_surface )
{
ANativeWindow_release ( image_reader_surface ) ;
image_reader_surface = 0 ;
}
if ( image_reader ! = NULL )
{
// AImageReader_setImageListener(image_reader, NULL);
XYLOG ( XYLOG_SEVERITY_INFO , " CameraStatus::AImageReader_delete %s " , mCameraId . c_str ( ) ) ;
AImageReader_delete ( image_reader ) ;
XYLOG ( XYLOG_SEVERITY_INFO , " CameraStatus::End AImageReader_delete %s " , mCameraId . c_str ( ) ) ;
image_reader = 0 ;
}
XYLOG ( XYLOG_SEVERITY_INFO , " CameraStatus::closed %s " , mCameraId . c_str ( ) ) ;
}
void NdkCamera : : onImageAvailable ( AImageReader * reader )
{
ALOGD ( " onImageAvailable %p " , reader ) ;
AImage * image = 0 ;
media_status_t mstatus = AImageReader_acquireLatestImage ( reader , & image ) ;
if ( mstatus ! = AMEDIA_OK )
{
// error
XYLOG ( XYLOG_SEVERITY_ERROR , " AImageReader_acquireLatestImage error: %d " , mstatus ) ;
return ;
}
uint8_t * y_data = 0 ;
int y_len = 0 ;
#if 0
if ( ! lightDetected )
{
AImage_getPlaneData ( image , 0 , & y_data , & y_len ) ;
lightDetected = true ;
# if __cplusplus >= 201703L
uint64_t avgY = std : : reduce ( y_data , y_data + y_len , 0 ) ;
# else
uint64_t avgY = std : : accumulate ( y_data , y_data + y_len , 0 ) ;
# endif
avgY = avgY / ( uint64_t ) y_len ;
mResult . avgY = avgY ;
# if 1
if ( avgY < 50 )
{
if ( m_params . autoExposure )
{
uint8_t aeMode = ACAMERA_CONTROL_AE_MODE_OFF ;
camera_status_t status = ACaptureRequest_setEntry_u8 ( capture_request , ACAMERA_CONTROL_AE_MODE , 1 , & aeMode ) ;
int32_t sensitivity = ( avgY < 5 ) ? 2000 : ( mResult . sensitibity * 60.0 / avgY ) ;
status = ACaptureRequest_setEntry_i32 ( capture_request , ACAMERA_SENSOR_SENSITIVITY , 1 , & sensitivity ) ;
int64_t exposureTime = ( avgY < 5 ) ? 200 * 1000000 : ( mResult . exposureTime * 120.0 / avgY ) ;
status = ACaptureRequest_setEntry_i64 ( capture_request , ACAMERA_SENSOR_EXPOSURE_TIME , 1 , & exposureTime ) ;
XYLOG ( XYLOG_SEVERITY_WARNING , " YUV Light: %u EXPO:%lld => %lld ISO: %u => %u " , ( uint32_t ) avgY ,
mResult . exposureTime , exposureTime , mResult . sensitibity , sensitivity ) ;
}
AImage_delete ( image ) ;
return ;
}
# endif
}
# endif
if ( m_imagesCaptured = = ~ 0 | | m_imagesCaptured > = 1 )
{
// XYLOG(XYLOG_SEVERITY_DEBUG, "m_imagesCaptured=%u wait for next image", m_imagesCaptured);
// Not Ready Or Taken
AImage_delete ( image ) ;
return ;
}
int32_t format ;
AImage_getFormat ( image , & format ) ;
// ASSERT(format == AIMAGE_FORMAT_YUV_420_888);
int32_t width = 0 ;
int32_t height = 0 ;
AImage_getWidth ( image , & width ) ;
AImage_getHeight ( image , & height ) ;
int32_t y_pixelStride = 0 ;
int32_t u_pixelStride = 0 ;
int32_t v_pixelStride = 0 ;
AImage_getPlanePixelStride ( image , 0 , & y_pixelStride ) ;
AImage_getPlanePixelStride ( image , 1 , & u_pixelStride ) ;
AImage_getPlanePixelStride ( image , 2 , & v_pixelStride ) ;
int32_t y_rowStride = 0 ;
int32_t u_rowStride = 0 ;
int32_t v_rowStride = 0 ;
AImage_getPlaneRowStride ( image , 0 , & y_rowStride ) ;
AImage_getPlaneRowStride ( image , 1 , & u_rowStride ) ;
AImage_getPlaneRowStride ( image , 2 , & v_rowStride ) ;
// uint8_t* y_data = 0;
uint8_t * u_data = 0 ;
uint8_t * v_data = 0 ;
// int y_len = 0;
int u_len = 0 ;
int v_len = 0 ;
if ( y_data = = 0 )
{
AImage_getPlaneData ( image , 0 , & y_data , & y_len ) ;
}
AImage_getPlaneData ( image , 1 , & u_data , & u_len ) ;
AImage_getPlaneData ( image , 2 , & v_data , & v_len ) ;
#if 0
# if __cplusplus >= 201703L
uint64_t avgy = std : : reduce ( y_data , y_data + y_len , 0 ) ;
# else
uint64_t avgy = std : : accumulate ( y_data , y_data + y_len , 0 ) ;
# endif
mResult . avgY = avgy / y_len ;
# endif
if ( u_data = = v_data + 1 & & v_data = = y_data + width * height & & y_pixelStride = = 1 & & u_pixelStride = = 2 & & v_pixelStride = = 2 & & y_rowStride = = width & & u_rowStride = = width & & v_rowStride = = width )
{
// already nv21 :)
on_image ( ( unsigned char * ) y_data , ( int ) width , ( int ) height ) ;
}
else
{
// construct nv21
unsigned char * nv21 = new unsigned char [ width * height + width * height / 2 ] ;
{
// Y
unsigned char * yptr = nv21 ;
for ( int y = 0 ; y < height ; y + + )
{
const unsigned char * y_data_ptr = y_data + y_rowStride * y ;
for ( int x = 0 ; x < width ; x + + )
{
yptr [ 0 ] = y_data_ptr [ 0 ] ;
yptr + + ;
y_data_ptr + = y_pixelStride ;
}
}
// UV
unsigned char * uvptr = nv21 + width * height ;
for ( int y = 0 ; y < height / 2 ; y + + )
{
const unsigned char * v_data_ptr = v_data + v_rowStride * y ;
const unsigned char * u_data_ptr = u_data + u_rowStride * y ;
for ( int x = 0 ; x < width / 2 ; x + + )
{
uvptr [ 0 ] = v_data_ptr [ 0 ] ;
uvptr [ 1 ] = u_data_ptr [ 0 ] ;
uvptr + = 2 ;
v_data_ptr + = v_pixelStride ;
u_data_ptr + = u_pixelStride ;
}
}
}
on_image ( ( unsigned char * ) nv21 , ( int ) width , ( int ) height ) ;
delete [ ] nv21 ;
}
AImage_delete ( image ) ;
m_imagesCaptured + + ;
if ( capture_session ! = 0 )
{
// camera_status_t cs = ACameraCaptureSession_stopRepeating(capture_session);
//if (cs != ACAMERA_OK)
{
// XYLOG(XYLOG_SEVERITY_ERROR, "ACameraCaptureSession_stopRepeating error=%d", cs);
}
}
}
void NdkCamera : : on_error ( const std : : string & msg )
{
}
void NdkCamera : : onDisconnected ( ACameraDevice * device )
{
}
bool NdkCamera : : on_image ( cv : : Mat & rgb )
{
return false ;
}
void NdkCamera : : on_image ( const unsigned char * nv21 , int nv21_width , int nv21_height )
{
// ALOGW("nv21 size: %d x %d", nv21_width, nv21_height);
// rotate nv21
int w = 0 ;
int h = 0 ;
int rotate_type = 0 ;
cv : : Mat nv21_rotated ;
const unsigned char * yuv420data = nv21 ;
// TODO !!!???
/*
if ( camera_ - > GetSensorOrientation ( & facing , & angle ) ) {
if ( facing = = ACAMERA_LENS_FACING_FRONT ) {
imageRotation = ( angle + rotation_ ) % 360 ;
imageRotation = ( 360 - imageRotation ) % 360 ;
} else {
imageRotation = ( angle - rotation_ + 360 ) % 360 ;
}
}
*/
int orgWidth = mWidth ;
int orgHeight = mHeight ;
// int co = camera_orientation > 0 ? camera_orientation + 90 : camera_orientation;
if ( m_params . orientation ! = 0 )
{
int co = 0 ;
if ( camera_facing = = ACAMERA_LENS_FACING_FRONT )
{
co = ( camera_orientation + ( m_params . orientation - 1 ) * 90 ) % 360 ;
co = ( 360 - co ) % 360 ;
}
else
{
co = ( camera_orientation - ( m_params . orientation - 1 ) * 90 + 360 ) % 360 ;
}
XYLOG ( XYLOG_SEVERITY_DEBUG , " Orientation=%d Facing=%d " , co , camera_facing ) ;
// int co = 0;
if ( co = = 0 )
{
w = nv21_width ;
h = nv21_height ;
rotate_type = camera_facing = = ACAMERA_LENS_FACING_FRONT ? 2 : 1 ;
}
else if ( co = = 90 )
{
w = nv21_height ;
h = nv21_width ;
orgWidth = mHeight ;
orgHeight = mWidth ;
rotate_type = camera_facing = = ACAMERA_LENS_FACING_FRONT ? 5 : 6 ;
}
else if ( co = = 180 )
{
w = nv21_width ;
h = nv21_height ;
rotate_type = camera_facing = = ACAMERA_LENS_FACING_FRONT ? 4 : 3 ;
}
else if ( co = = 270 )
{
w = nv21_height ;
h = nv21_width ;
orgWidth = mHeight ;
orgHeight = mWidth ;
rotate_type = camera_facing = = ACAMERA_LENS_FACING_FRONT ? 7 : 8 ;
}
nv21_rotated . create ( h + h / 2 , w , CV_8UC1 ) ;
ncnn : : kanna_rotate_yuv420sp ( nv21 , nv21_width , nv21_height , nv21_rotated . data , w , h , rotate_type ) ;
yuv420data = nv21_rotated . data ;
}
else
{
w = nv21_width ;
h = nv21_height ;
XYLOG ( XYLOG_SEVERITY_DEBUG , " NO Orientation Facing=%d " , camera_facing ) ;
}
// nv21_rotated to rgb
cv : : Mat rgb ;
if ( w = = orgWidth & & h = = orgHeight )
{
rgb . create ( h , w , CV_8UC3 ) ;
// ncnn::yuv420sp2rgb(nv21_rotated.data, w, h, rgb.data);
ncnn : : yuv420sp2rgb_nv12 ( yuv420data , w , h , rgb . data ) ;
}
else
{
cv : : Mat org ( h , w , CV_8UC3 ) ;
ncnn : : yuv420sp2rgb_nv12 ( yuv420data , w , h , org . data ) ;
if ( w * orgHeight = = h * orgWidth ) // Same Ratio
{
cv : : resize ( org , rgb , cv : : Size ( orgWidth , orgHeight ) ) ;
}
else
{
// Crop image
int left = ( w - orgWidth ) / 2 ;
int top = ( h - orgHeight ) / 2 ;
rgb = org ( cv : : Range ( top , top + orgHeight ) , cv : : Range ( left , left + orgWidth ) ) ;
}
}
on_image ( rgb ) ;
}
void NdkCamera : : onSessionReady ( ACameraCaptureSession * session )
{
return ;
camera_status_t status = ACAMERA_OK ;
ACameraCaptureSession_captureCallbacks camera_capture_session_capture_callbacks ;
camera_capture_session_capture_callbacks . context = this ;
camera_capture_session_capture_callbacks . onCaptureStarted = 0 ;
camera_capture_session_capture_callbacks . onCaptureProgressed = : : onCaptureProgressed ;
camera_capture_session_capture_callbacks . onCaptureCompleted = : : onCaptureCompleted ;
camera_capture_session_capture_callbacks . onCaptureFailed = onCaptureFailed ;
camera_capture_session_capture_callbacks . onCaptureSequenceCompleted = onCaptureSequenceCompleted ;
camera_capture_session_capture_callbacks . onCaptureSequenceAborted = onCaptureSequenceAborted ;
camera_capture_session_capture_callbacks . onCaptureBufferLost = 0 ;
if ( m_imagesCaptured ! = 0 )
{
status = ACameraCaptureSession_setRepeatingRequest ( capture_session , & camera_capture_session_capture_callbacks , 1 , & capture_request , & captureSequenceId ) ;
}
else
{
status = ACameraCaptureSession_capture ( capture_session , & camera_capture_session_capture_callbacks , 1 , & capture_request , & captureSequenceId ) ;
}
}
void NdkCamera : : onCaptureProgressed ( ACameraCaptureSession * session , ACaptureRequest * request , const ACameraMetadata * result )
{
}
void NdkCamera : : onCaptureCompleted ( ACameraCaptureSession * session , ACaptureRequest * request , const ACameraMetadata * result )
{
// CALL_REQUEST(setEntry_i64(requests_[PREVIEW_REQUEST_IDX].request_,
// ACAMERA_SENSOR_EXPOSURE_TIME, 1, &exposureTime_));
// ACameraMetadata_getConstEntry(result, )
ACameraMetadata_const_entry val = { 0 } ;
camera_status_t status = ACAMERA_ERROR_BASE ;
mResult . afState = ACAMERA_CONTROL_AF_STATE_INACTIVE ;
val = { 0 } ;
status = ACameraMetadata_getConstEntry ( result , ACAMERA_CONTROL_AE_STATE , & val ) ;
mResult . aeState = ( status = = ACAMERA_OK ) ? * ( val . data . u8 ) : ACAMERA_CONTROL_AE_STATE_INACTIVE ;
if ( ! lightDetected )
{
val = { 0 } ;
status = ACameraMetadata_getConstEntry ( result , ACAMERA_SENSOR_EXPOSURE_TIME , & val ) ;
int64_t exTime = ( status = = ACAMERA_OK ) ? val . data . i64 [ 0 ] : - 1 ;
mResult . exposureTime = exTime ;
val = { 0 } ;
status = ACameraMetadata_getConstEntry ( result , ACAMERA_SENSOR_SENSITIVITY , & val ) ;
mResult . sensitibity = * ( val . data . i32 ) ;
}
if ( afSupported & & ( m_params . autoFocus ! = 0 ) )
{
val = { 0 } ;
status = ACameraMetadata_getConstEntry ( result , ACAMERA_CONTROL_AF_STATE , & val ) ;
mResult . afState = ( status = = ACAMERA_OK ) ? * ( val . data . u8 ) : ACAMERA_CONTROL_AF_STATE_INACTIVE ;
}
if ( m_imagesCaptured = = ~ 0 )
{
unsigned long long ts = GetMicroTimeStamp ( ) ;
if ( ts - m_startTime > = m_params . focusTimeout * 2 )
{
XYLOG ( XYLOG_SEVERITY_WARNING , " onCaptureCompleted Timeout for AF/AE And will Capture AFS=%u AES=%u Time=%u " , ( unsigned int ) mResult . afState , ( unsigned int ) mResult . aeState , ( unsigned int ) ( ts - m_startTime ) ) ;
m_imagesCaptured = 0 ;
}
else
{
if ( m_params . autoExposure ! = 0 )
{
if ( mResult . aeState = = ACAMERA_CONTROL_AE_STATE_SEARCHING )
{
// Waiting
return ;
}
else if ( mResult . aeState = = ACAMERA_CONTROL_AE_STATE_PRECAPTURE )
{
uint8_t aePrecatureTrigger = ACAMERA_CONTROL_AE_PRECAPTURE_TRIGGER_START ;
status = ACaptureRequest_setEntry_u8 ( capture_request , ACAMERA_CONTROL_AE_PRECAPTURE_TRIGGER , 1 , & aePrecatureTrigger ) ;
return ;
}
else if ( mResult . aeState = = ACAMERA_CONTROL_AE_STATE_CONVERGED )
{
if ( aeLockAvailable )
{
uint8_t aeLock = ACAMERA_CONTROL_AE_LOCK_ON ;
status = ACaptureRequest_setEntry_u8 ( capture_request , ACAMERA_CONTROL_AE_LOCK , 1 , & aeLock ) ;
}
}
}
if ( afSupported & & ( m_params . autoFocus ! = 0 ) )
{
// if (mResult.afState == ACAMERA_CONTROL_AF_STATE_NOT_FOCUSED_LOCKED || mResult.afState == ACAMERA_CONTROL_AF_STATE_PASSIVE_UNFOCUSED)
if ( mResult . afState = = ACAMERA_CONTROL_AF_STATE_NOT_FOCUSED_LOCKED )
{
// uint8_t aePrecatureTrigger = ACAMERA_CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL;
// status = ACaptureRequest_setEntry_u8(capture_request, ACAMERA_CONTROL_AE_PRECAPTURE_TRIGGER, 1, &aePrecatureTrigger);
// aePrecatureTrigger = ACAMERA_CONTROL_AE_PRECAPTURE_TRIGGER_START;
// status = ACaptureRequest_setEntry_u8(capture_request, ACAMERA_CONTROL_AE_PRECAPTURE_TRIGGER, 1, &aePrecatureTrigger);
// XYLOG(XYLOG_SEVERITY_INFO, "onCaptureCompleted New Focus Trigger AFS=%u AES=%u Time=%u", (unsigned int)mResult.afState, (unsigned int)mResult.aeState);
return ;
}
ALOGD ( " onCaptureCompleted 1 AFS=%u AES=%u " , ( unsigned int ) mResult . afState , ( unsigned int ) mResult . aeState ) ;
if ( mResult . afState = = ACAMERA_CONTROL_AF_STATE_PASSIVE_FOCUSED | | mResult . afState = = ACAMERA_CONTROL_AF_STATE_FOCUSED_LOCKED )
// if (afState != ACAMERA_CONTROL_AF_STATE_INACTIVE)
{
m_imagesCaptured = 0 ;
}
}
else
{
m_imagesCaptured = 0 ;
}
}
}
if ( m_imagesCaptured ! = 0 | | camera_facing = = 2 )
{
return ;
}
val = { 0 } ;
status = ACameraMetadata_getConstEntry ( result , ACAMERA_SENSOR_EXPOSURE_TIME , & val ) ;
int64_t exTime = ( status = = ACAMERA_OK ) ? val . data . i64 [ 0 ] : - 1 ;
mResult . exposureTime = exTime ;
val = { 0 } ;
status = ACameraMetadata_getConstEntry ( result , ACAMERA_CONTROL_AE_MODE , & val ) ;
uint8_t aeMode = ( status = = ACAMERA_OK ) ? val . data . u8 [ 0 ] : 0 ;
// ACaptureRequest_setEntry_i32(capture_request, ACAMERA_SENSOR_SENSITIVITY, 1, &sensitivity_);
mResult . autoExposure = aeMode ;
val = { 0 } ;
status = ACameraMetadata_getConstEntry ( result , ACAMERA_CONTROL_AWB_STATE , & val ) ;
mResult . awbState = ( status = = ACAMERA_OK ) ? val . data . u8 [ 0 ] : 0 ;
val = { 0 } ;
float focusDistance = NAN ;
if ( afSupported & & ( m_params . autoFocus ! = 0 ) )
{
status = ACameraMetadata_getConstEntry ( result , ACAMERA_LENS_FOCUS_DISTANCE , & val ) ;
if ( status = = ACAMERA_OK )
{
focusDistance = * val . data . f ;
}
}
mResult . FocusDistance = focusDistance ;
val = { 0 } ;
status = ACameraMetadata_getConstEntry ( result , ACAMERA_CONTROL_ZOOM_RATIO , & val ) ;
if ( status = = ACAMERA_OK )
{
mResult . zoomRatio = * val . data . f ;
}
/*
val = { 0 } ;
status = ACameraMetadata_getConstEntry ( result , ACAMERA_CONTROL_AF_STATE , & val ) ;
mResult . afState = * ( val . data . u8 ) ;
*/
ALOGD ( " onCaptureCompleted 2 AFS=%u AES=%u " , ( unsigned int ) mResult . afState , ( unsigned int ) mResult . aeState ) ;
val = { 0 } ;
status = ACameraMetadata_getConstEntry ( result , ACAMERA_SENSOR_SENSITIVITY , & val ) ;
mResult . sensitibity = * ( val . data . i32 ) ;
val = { 0 } ;
status = ACameraMetadata_getConstEntry ( result , ACAMERA_CONTROL_SCENE_MODE , & val ) ;
mResult . sceneMode = status = = ACAMERA_OK ? * ( val . data . u8 ) : 0 ;
val = { 0 } ;
status = ACameraMetadata_getConstEntry ( result , ACAMERA_CONTROL_AF_MODE , & val ) ;
mResult . autoFocus = * ( val . data . u8 ) ;
val = { 0 } ;
status = ACameraMetadata_getConstEntry ( result , ACAMERA_CONTROL_AE_EXPOSURE_COMPENSATION , & val ) ;
mResult . compensation = * ( val . data . i32 ) ;
ALOGD ( " onCaptureCompleted EXPO=%lld, FD=%f camera id=%s, AE=%s AFS=%u AES=%u " , exTime , focusDistance , mCameraId . c_str ( ) , ( ( aeMode = = 1 ) ? " ON " : " OFF " ) , mResult . afState , mResult . aeState ) ;
// __android_log_print(ANDROID_LOG_WARN, "NdkCamera", "onCaptureCompleted %p %p %p", session, request, result);
}
void NdkCamera : : onAvailabilityCallback ( const char * cameraId )
{
std : : string s ( cameraId ) ;
m_locker . lock ( ) ;
m_availableCameras . insert ( s ) ;
m_locker . unlock ( ) ;
}
void NdkCamera : : onUnavailabilityCallback ( const char * cameraId )
{
std : : string s ( cameraId ) ;
m_locker . lock ( ) ;
m_availableCameras . erase ( s ) ;
m_locker . unlock ( ) ;
}
bool NdkCamera : : IsCameraAvailable ( const std : : string & cameraId )
{
bool existed = false ;
m_locker . lock ( ) ;
existed = ( m_availableCameras . find ( cameraId ) ! = m_availableCameras . cend ( ) ) ;
m_locker . unlock ( ) ;
return existed ;
}