From 0d9ea780257979cab241cbad21fdbd5cd8e30aa2 Mon Sep 17 00:00:00 2001 From: BlueMatthew Date: Mon, 15 Jan 2024 13:12:41 +0800 Subject: [PATCH] =?UTF-8?q?=20=E6=8B=8D=E7=85=A7=E6=97=B6=EF=BC=8C?= =?UTF-8?q?=E5=A6=82=E6=9E=9C=E6=8C=87=E5=AE=9A=E7=9A=84camera=E4=B8=8D?= =?UTF-8?q?=E5=AD=98=E5=9C=A8=EF=BC=8C=E7=AD=89=E5=BE=852s=E5=90=8E?= =?UTF-8?q?=E9=87=8D=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 电源打开之后,系统需要时间检测到相机 --- app/src/main/cpp/camera2/ndkcamera.cpp | 363 +++++++++++++------------ app/src/main/cpp/camera2/ndkcamera.h | 16 +- 2 files changed, 206 insertions(+), 173 deletions(-) diff --git a/app/src/main/cpp/camera2/ndkcamera.cpp b/app/src/main/cpp/camera2/ndkcamera.cpp index b9e70db7..7a557fd9 100644 --- a/app/src/main/cpp/camera2/ndkcamera.cpp +++ b/app/src/main/cpp/camera2/ndkcamera.cpp @@ -25,11 +25,13 @@ static void onAvailabilityCallback(void* context, const char* cameraId) { + ((NdkCamera*)context)->onAvailabilityCallback(cameraId); ALOGI("CameraStatus::onAvailability CameraId: %s", cameraId); } static void onUnavailabilityCallback(void* context, const char* cameraId) { + ((NdkCamera*)context)->onUnavailabilityCallback(cameraId); ALOGI("CameraStatus::onUnavailability CameraId: %s", cameraId); } @@ -123,11 +125,9 @@ NdkCamera::NdkCamera(int32_t width, int32_t height, const NdkCamera::CAMERA_PARA nightModeSupported = false; nightPortraitModeSupported = false; -#ifdef _DEBUG camera_manager_cb.context = this; - camera_manager_cb.onCameraAvailable = onAvailabilityCallback; - camera_manager_cb.onCameraUnavailable = onUnavailabilityCallback; -#endif + camera_manager_cb.onCameraAvailable = ::onAvailabilityCallback; + camera_manager_cb.onCameraUnavailable = ::onUnavailabilityCallback; camera_manager = 0; camera_device = 0; @@ -144,8 +144,6 @@ NdkCamera::NdkCamera(int32_t width, int32_t height, const NdkCamera::CAMERA_PARA NdkCamera::~NdkCamera() { close(); - - } int NdkCamera::open(const std::string& cameraId) { @@ -154,221 +152,224 @@ int NdkCamera::open(const std::string& cameraId) { // camera_facing = _camera_facing; camera_manager = ACameraManager_create(); -#ifdef _DEBUG ACameraManager_registerAvailabilityCallback(camera_manager, &camera_manager_cb); -#endif - // find front camera - std::string camera_id; + // find camera bool foundIt = false; DisplayDimension disp(mWidth, mHeight); DisplayDimension foundRes = disp; + { ACameraIdList *camera_id_list = 0; - ACameraManager_getCameraIdList(camera_manager, &camera_id_list); - - for (int i = 0; i < camera_id_list->numCameras; ++i) + for (int retry = 0; retry < 2; retry++) { - const char *id = camera_id_list->cameraIds[i]; - if (cameraId.compare(id) != 0) { - continue; + ACameraManager_getCameraIdList(camera_manager, &camera_id_list); + // ACameraManager_getCameraIdList will fire AvailabilityCallback + + 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; + } } - ACameraMetadata * camera_metadata = 0; - ACameraManager_getCameraCharacteristics(camera_manager, id, &camera_metadata); - // query faceing - acamera_metadata_enum_android_lens_facing_t facing = ACAMERA_LENS_FACING_FRONT; + ACameraManager_deleteCameraIdList(camera_id_list); + if (foundIt) { - ACameraMetadata_const_entry e = {0}; - ACameraMetadata_getConstEntry(camera_metadata, ACAMERA_LENS_FACING, &e); - facing = (acamera_metadata_enum_android_lens_facing_t) e.data.u8[0]; + break; } - camera_facing = facing; + if (retry == 0) + { + for (int idx = 0; idx < 128; idx++) + { + if (IsCameraAvailable(cameraId)) + { + break; + } + std::this_thread::sleep_for(std::chrono::milliseconds(16)); + } + } + } - camera_id = cameraId; - camera_id.assign(id, strlen(id)); + if (!foundIt) + { + return 1; + } - // query orientation - int orientation = 0; - { - ACameraMetadata_const_entry e = {0}; - ACameraMetadata_getConstEntry(camera_metadata, ACAMERA_SENSOR_ORIENTATION, &e); + mCameraId = cameraId; - orientation = (int) e.data.i32[0]; - } + ACameraMetadata * camera_metadata = 0; + ACameraManager_getCameraCharacteristics(camera_manager, cameraId.c_str(), &camera_metadata); - camera_orientation = orientation; + { + 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 - { - 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); - // DisplayDimension foundRes(4000, 4000); - // DisplayDimension maxJPG(0, 0); + foundIt = false; + unsigned long long minRatio = -1; + DisplayDimension temp; + unsigned long long pixels = (unsigned long long)mWidth * mHeight; - unsigned long long minRatio = -1; - DisplayDimension temp; - unsigned long long pixels = (unsigned long long)mWidth * mHeight; + 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; - for (int i = 0; i < e.count; i += 4) + if (format == AIMAGE_FORMAT_YUV_420_888 || format == AIMAGE_FORMAT_JPEG) { - 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)) { - DisplayDimension res(e.data.i32[i + 1], e.data.i32[i + 2]); - if (!disp.IsSameRatio(res)) + unsigned long long ps = res.width() * res.height(); + unsigned long long ratio = (ps >= pixels) ? (ps - pixels) : (pixels - ps); + if (ratio < minRatio) { - unsigned long long ps = res.width() * res.height(); - unsigned long long ratio = (ps >= pixels) ? (ps - pixels) : (pixels - ps); - if (ratio < minRatio) - { - temp = res; - minRatio = ratio; - } - continue; + temp = res; + minRatio = ratio; } + continue; + } - if (format == AIMAGE_FORMAT_YUV_420_888 && res > disp) - { - foundIt = true; - foundRes = res; - }/* else if (format == AIMAGE_FORMAT_JPEG && res > maxJPG) { + if (format == AIMAGE_FORMAT_YUV_420_888 && res > disp) + { + foundIt = true; + foundRes = res; + }/* else if (format == AIMAGE_FORMAT_JPEG && res > maxJPG) { maxJPG = res; }*/ - } - } - - if (!foundIt) - { - foundRes = temp; - foundIt = true; } } + if (!foundIt) { - ACameraMetadata_const_entry e = {0}; - camera_status_t status = ACameraMetadata_getConstEntry(camera_metadata,ACAMERA_LENS_INFO_MINIMUM_FOCUS_DISTANCE, &e); - - } - { - ACameraMetadata_const_entry e = {0}; - camera_status_t status = ACameraMetadata_getConstEntry(camera_metadata,ACAMERA_CONTROL_AF_AVAILABLE_MODES, &e); - afSupported = (status == ACAMERA_OK) && !(e.count == 0 || (e.count == 1 && e.data.u8[0] == ACAMERA_CONTROL_AF_MODE_OFF)); + foundRes = temp; + foundIt = true; } + } + + if (!foundIt) + { + ACameraMetadata_free(camera_metadata); + ALOGE("Camera RES(%d, %d) Not Found on ID: %s", mWidth, mHeight, cameraId.c_str()); + return 1; + } + // query faceing + acamera_metadata_enum_android_lens_facing_t facing = ACAMERA_LENS_FACING_FRONT; + { + ACameraMetadata_const_entry e = {0}; + ACameraMetadata_getConstEntry(camera_metadata, ACAMERA_LENS_FACING, &e); + 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}; + ACameraMetadata_getConstEntry(camera_metadata, ACAMERA_SENSOR_ORIENTATION, &e); + orientation = (int) e.data.i32[0]; + } + camera_orientation = orientation; + + { + ACameraMetadata_const_entry e = {0}; + camera_status_t status = ACameraMetadata_getConstEntry(camera_metadata,ACAMERA_LENS_INFO_MINIMUM_FOCUS_DISTANCE, &e); + } + + { + ACameraMetadata_const_entry e = {0}; + camera_status_t status = ACameraMetadata_getConstEntry(camera_metadata,ACAMERA_CONTROL_AF_AVAILABLE_MODES, &e); + afSupported = (status == ACAMERA_OK) && !(e.count == 0 || (e.count == 1 && e.data.u8[0] == ACAMERA_CONTROL_AF_MODE_OFF)); + } + + { + ACameraMetadata_const_entry val = {0}; + camera_status_t status = ACameraMetadata_getConstEntry(camera_metadata,ACAMERA_SENSOR_INFO_EXPOSURE_TIME_RANGE, &val); + if (status == ACAMERA_OK) { - ACameraMetadata_const_entry val = {0}; - camera_status_t status = ACameraMetadata_getConstEntry(camera_metadata,ACAMERA_SENSOR_INFO_EXPOSURE_TIME_RANGE, &val); - if (status == ACAMERA_OK) + exposureRange.min_ = val.data.i64[0]; + if (exposureRange.min_ < kMinExposureTime) { - 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); + exposureRange.min_ = kMinExposureTime; } - else + exposureRange.max_ = val.data.i64[1]; + if (exposureRange.max_ > kMaxExposureTime) { - ALOGW("Unsupported ACAMERA_SENSOR_INFO_EXPOSURE_TIME_RANGE"); - exposureRange.min_ = exposureRange.max_ = 0l; - // exposureTime_ = 0l; + 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 val = {0}; + camera_status_t status = ACameraMetadata_getConstEntry(camera_metadata, ACAMERA_CONTROL_AE_COMPENSATION_RANGE, &val); + if (status == ACAMERA_OK) { - ACameraMetadata_const_entry val = {0}; - camera_status_t 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]; - } - else - { - ALOGW("Unsupported ACAMERA_CONTROL_AE_COMPENSATION_RANGE"); - aeCompensationRange.min_ = aeCompensationRange.max_ = 0l; - } + aeCompensationRange.min_ = val.data.i32[0]; + aeCompensationRange.max_ = val.data.i32[1]; + } + else + { + ALOGW("Unsupported ACAMERA_CONTROL_AE_COMPENSATION_RANGE"); + aeCompensationRange.min_ = aeCompensationRange.max_ = 0l; + } + } + + { + ACameraMetadata_const_entry val = {0}; + camera_status_t 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 e = {0}; + camera_status_t status = ACameraMetadata_getConstEntry(camera_metadata,ACAMERA_CONTROL_AVAILABLE_SCENE_MODES, &e); + for (int i = 0; i < e.count; i++) { - ACameraMetadata_const_entry val = {0}; - camera_status_t status = ACameraMetadata_getConstEntry(camera_metadata,ACAMERA_SENSOR_INFO_SENSITIVITY_RANGE, &val); - if (status == ACAMERA_OK) + if (ACAMERA_CONTROL_SCENE_MODE_HDR == e.data.u8[i]) { - sensitivityRange.min_ = val.data.i32[0]; - sensitivityRange.max_ = val.data.i32[1]; + hdrSupported = true; + break; } - else + else if (ACAMERA_CONTROL_SCENE_MODE_NIGHT == e.data.u8[i]) { - ALOGW("failed for ACAMERA_SENSOR_INFO_SENSITIVITY_RANGE"); - sensitivityRange.min_ = sensitivityRange.max_ = 0; + nightModeSupported = true; } - } - - { - ACameraMetadata_const_entry e = {0}; - camera_status_t status = ACameraMetadata_getConstEntry(camera_metadata,ACAMERA_CONTROL_AVAILABLE_SCENE_MODES, &e); - for (int i = 0; i < e.count; i++) + else if (ACAMERA_CONTROL_SCENE_MODE_NIGHT_PORTRAIT == e.data.u8[i]) { - if (ACAMERA_CONTROL_SCENE_MODE_HDR == e.data.u8[i]) - { - hdrSupported = true; - break; - } - else if (ACAMERA_CONTROL_SCENE_MODE_NIGHT == e.data.u8[i]) - { - nightModeSupported = true; - } - else if (ACAMERA_CONTROL_SCENE_MODE_NIGHT_PORTRAIT == e.data.u8[i]) - { - nightPortraitModeSupported = true; - } + nightPortraitModeSupported = true; } } - - ACameraMetadata_free(camera_metadata); - - break; } - ACameraManager_deleteCameraIdList(camera_id_list); - } - - if (camera_id.empty() || !foundIt) { - ALOGE("CameraId %s With RES(%d, %d) Not Found", cameraId.c_str(), mWidth, mHeight); - return 1; - } - - // TODO: PATCH!!!! - if (camera_id == "0") - { - // afSupported = true; - } - if (camera_id == "1") - { -#if 0 - camera_facing = 1; -#endif - } - if (camera_id == "2") - { - // camera_orientation += 180; + ACameraMetadata_free(camera_metadata); } - mCameraId = camera_id; - camera_status_t res = ACAMERA_OK; // setup imagereader and its surface { @@ -394,7 +395,7 @@ int NdkCamera::open(const std::string& cameraId) { camera_device_state_callbacks.onDisconnected = onDisconnected; camera_device_state_callbacks.onError = onError; - res = ACameraManager_openCamera(camera_manager, camera_id.c_str(), &camera_device_state_callbacks, &camera_device); + res = ACameraManager_openCamera(camera_manager, cameraId.c_str(), &camera_device_state_callbacks, &camera_device); if (res != ACAMERA_OK) { ALOGE("Failed to open camera res=%d", res); @@ -402,7 +403,7 @@ int NdkCamera::open(const std::string& cameraId) { } } - ALOGI("CameraStatus::Open %s %d", camera_id.c_str(), camera_orientation); + ALOGI("CameraStatus::Open %s %d", cameraId.c_str(), camera_orientation); // std::this_thread::sleep_for(std::chrono::milliseconds(128)); // capture request @@ -573,9 +574,7 @@ void NdkCamera::close() if (camera_manager) { -#ifdef _DEBUG ACameraManager_unregisterAvailabilityCallback(camera_manager, &camera_manager_cb); -#endif ACameraManager_delete(camera_manager); camera_manager = 0; } @@ -845,4 +844,30 @@ void NdkCamera::onCaptureCompleted(ACameraCaptureSession* session, ACaptureReque ALOGD("onCaptureCompleted EXPOSURE_TIME=%lld, FocusDis=%f camera id=%s, AE=%s AF_STATE=%u", exTime, focusDistance, mCameraId.c_str(), ((aeMode == 1) ? "ON" : "OFF"), afState); // __android_log_print(ANDROID_LOG_WARN, "NdkCamera", "onCaptureCompleted %p %p %p", session, request, result); -} \ No newline at end of file +} + +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; +} diff --git a/app/src/main/cpp/camera2/ndkcamera.h b/app/src/main/cpp/camera2/ndkcamera.h index 19152bd9..10d0dcde 100644 --- a/app/src/main/cpp/camera2/ndkcamera.h +++ b/app/src/main/cpp/camera2/ndkcamera.h @@ -22,6 +22,8 @@ #include #include "Camera2Helper.h" +#include +#include /** * Range of Camera Exposure Time: @@ -67,6 +69,8 @@ public: int open(const std::string& cameraId); void close(); + void onAvailabilityCallback(const char* cameraId); + void onUnavailabilityCallback(const char* cameraId); void onImageAvailable(AImageReader* reader); virtual bool on_image(cv::Mat& rgb); virtual void on_error(const std::string& msg); @@ -79,8 +83,13 @@ public: return mResult; } + bool IsCameraAvailable(const std::string& cameraId); -public: +protected: + std::mutex m_locker; + std::set m_availableCameras; + +protected: CAMERA_PARAMS m_params; int camera_facing; int camera_orientation; @@ -104,10 +113,9 @@ public: CAPTURE_RESULT mResult; -private: -#ifdef _DEBUG +protected: + ACameraManager_AvailabilityCallbacks camera_manager_cb; -#endif ACameraManager* camera_manager; ACameraDevice* camera_device; AImageReader* image_reader;