拍照时,如果指定的camera不存在,等待2s后重试

电源打开之后,系统需要时间检测到相机
serial
BlueMatthew 1 year ago
parent a7a36547fa
commit 0d9ea78025

@ -25,11 +25,13 @@
static void onAvailabilityCallback(void* context, const char* cameraId) static void onAvailabilityCallback(void* context, const char* cameraId)
{ {
((NdkCamera*)context)->onAvailabilityCallback(cameraId);
ALOGI("CameraStatus::onAvailability CameraId: %s", cameraId); ALOGI("CameraStatus::onAvailability CameraId: %s", cameraId);
} }
static void onUnavailabilityCallback(void* context, const char* cameraId) static void onUnavailabilityCallback(void* context, const char* cameraId)
{ {
((NdkCamera*)context)->onUnavailabilityCallback(cameraId);
ALOGI("CameraStatus::onUnavailability CameraId: %s", 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; nightModeSupported = false;
nightPortraitModeSupported = false; nightPortraitModeSupported = false;
#ifdef _DEBUG
camera_manager_cb.context = this; camera_manager_cb.context = this;
camera_manager_cb.onCameraAvailable = onAvailabilityCallback; camera_manager_cb.onCameraAvailable = ::onAvailabilityCallback;
camera_manager_cb.onCameraUnavailable = onUnavailabilityCallback; camera_manager_cb.onCameraUnavailable = ::onUnavailabilityCallback;
#endif
camera_manager = 0; camera_manager = 0;
camera_device = 0; camera_device = 0;
@ -144,8 +144,6 @@ NdkCamera::NdkCamera(int32_t width, int32_t height, const NdkCamera::CAMERA_PARA
NdkCamera::~NdkCamera() NdkCamera::~NdkCamera()
{ {
close(); close();
} }
int NdkCamera::open(const std::string& cameraId) { int NdkCamera::open(const std::string& cameraId) {
@ -154,221 +152,224 @@ int NdkCamera::open(const std::string& cameraId) {
// camera_facing = _camera_facing; // camera_facing = _camera_facing;
camera_manager = ACameraManager_create(); camera_manager = ACameraManager_create();
#ifdef _DEBUG
ACameraManager_registerAvailabilityCallback(camera_manager, &camera_manager_cb); ACameraManager_registerAvailabilityCallback(camera_manager, &camera_manager_cb);
#endif
// find front camera // find camera
std::string camera_id;
bool foundIt = false; bool foundIt = false;
DisplayDimension disp(mWidth, mHeight); DisplayDimension disp(mWidth, mHeight);
DisplayDimension foundRes = disp; DisplayDimension foundRes = disp;
{ {
ACameraIdList *camera_id_list = 0; ACameraIdList *camera_id_list = 0;
ACameraManager_getCameraIdList(camera_manager, &camera_id_list); for (int retry = 0; retry < 2; retry++)
for (int i = 0; i < camera_id_list->numCameras; ++i)
{ {
const char *id = camera_id_list->cameraIds[i]; ACameraManager_getCameraIdList(camera_manager, &camera_id_list);
if (cameraId.compare(id) != 0) { // ACameraManager_getCameraIdList will fire AvailabilityCallback
continue;
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 ACameraManager_deleteCameraIdList(camera_id_list);
acamera_metadata_enum_android_lens_facing_t facing = ACAMERA_LENS_FACING_FRONT; if (foundIt)
{ {
ACameraMetadata_const_entry e = {0}; break;
ACameraMetadata_getConstEntry(camera_metadata, ACAMERA_LENS_FACING, &e);
facing = (acamera_metadata_enum_android_lens_facing_t) e.data.u8[0];
} }
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; if (!foundIt)
camera_id.assign(id, strlen(id)); {
return 1;
}
// query orientation mCameraId = cameraId;
int orientation = 0;
{
ACameraMetadata_const_entry e = {0};
ACameraMetadata_getConstEntry(camera_metadata, ACAMERA_SENSOR_ORIENTATION, &e);
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
{ // DisplayDimension foundRes(4000, 4000);
ACameraMetadata_const_entry e = {0}; // DisplayDimension maxJPG(0, 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); foundIt = false;
// DisplayDimension maxJPG(0, 0); unsigned long long minRatio = -1;
DisplayDimension temp;
unsigned long long pixels = (unsigned long long)mWidth * mHeight;
unsigned long long minRatio = -1; for (int i = 0; i < e.count; i += 4)
DisplayDimension temp; {
unsigned long long pixels = (unsigned long long)mWidth * mHeight; 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]; DisplayDimension res(e.data.i32[i + 1], e.data.i32[i + 2]);
int32_t format = e.data.i32[i + 0]; if (!disp.IsSameRatio(res))
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]); unsigned long long ps = res.width() * res.height();
if (!disp.IsSameRatio(res)) unsigned long long ratio = (ps >= pixels) ? (ps - pixels) : (pixels - ps);
if (ratio < minRatio)
{ {
unsigned long long ps = res.width() * res.height(); temp = res;
unsigned long long ratio = (ps >= pixels) ? (ps - pixels) : (pixels - ps); minRatio = ratio;
if (ratio < minRatio)
{
temp = res;
minRatio = ratio;
}
continue;
} }
continue;
}
if (format == AIMAGE_FORMAT_YUV_420_888 && res > disp) if (format == AIMAGE_FORMAT_YUV_420_888 && res > disp)
{ {
foundIt = true; foundIt = true;
foundRes = res; foundRes = res;
}/* else if (format == AIMAGE_FORMAT_JPEG && res > maxJPG) { }/* else if (format == AIMAGE_FORMAT_JPEG && res > maxJPG) {
maxJPG = res; maxJPG = res;
}*/ }*/
}
}
if (!foundIt)
{
foundRes = temp;
foundIt = true;
} }
} }
if (!foundIt)
{ {
ACameraMetadata_const_entry e = {0}; foundRes = temp;
camera_status_t status = ACameraMetadata_getConstEntry(camera_metadata,ACAMERA_LENS_INFO_MINIMUM_FOCUS_DISTANCE, &e); foundIt = true;
}
{
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));
} }
}
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}; exposureRange.min_ = val.data.i64[0];
camera_status_t status = ACameraMetadata_getConstEntry(camera_metadata,ACAMERA_SENSOR_INFO_EXPOSURE_TIME_RANGE, &val); if (exposureRange.min_ < kMinExposureTime)
if (status == ACAMERA_OK)
{ {
exposureRange.min_ = val.data.i64[0]; exposureRange.min_ = kMinExposureTime;
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 exposureRange.max_ = val.data.i64[1];
if (exposureRange.max_ > kMaxExposureTime)
{ {
ALOGW("Unsupported ACAMERA_SENSOR_INFO_EXPOSURE_TIME_RANGE"); exposureRange.max_ = kMaxExposureTime;
exposureRange.min_ = exposureRange.max_ = 0l;
// exposureTime_ = 0l;
} }
// 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}; aeCompensationRange.min_ = val.data.i32[0];
camera_status_t status = ACameraMetadata_getConstEntry(camera_metadata, ACAMERA_CONTROL_AE_COMPENSATION_RANGE, &val); aeCompensationRange.max_ = val.data.i32[1];
if (status == ACAMERA_OK) }
{ else
aeCompensationRange.min_ = val.data.i32[0]; {
aeCompensationRange.max_ = val.data.i32[1]; ALOGW("Unsupported ACAMERA_CONTROL_AE_COMPENSATION_RANGE");
} aeCompensationRange.min_ = aeCompensationRange.max_ = 0l;
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}; if (ACAMERA_CONTROL_SCENE_MODE_HDR == e.data.u8[i])
camera_status_t status = ACameraMetadata_getConstEntry(camera_metadata,ACAMERA_SENSOR_INFO_SENSITIVITY_RANGE, &val);
if (status == ACAMERA_OK)
{ {
sensitivityRange.min_ = val.data.i32[0]; hdrSupported = true;
sensitivityRange.max_ = val.data.i32[1]; break;
} }
else else if (ACAMERA_CONTROL_SCENE_MODE_NIGHT == e.data.u8[i])
{ {
ALOGW("failed for ACAMERA_SENSOR_INFO_SENSITIVITY_RANGE"); nightModeSupported = true;
sensitivityRange.min_ = sensitivityRange.max_ = 0;
} }
} else if (ACAMERA_CONTROL_SCENE_MODE_NIGHT_PORTRAIT == e.data.u8[i])
{
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++)
{ {
if (ACAMERA_CONTROL_SCENE_MODE_HDR == e.data.u8[i]) nightPortraitModeSupported = true;
{
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;
}
} }
} }
ACameraMetadata_free(camera_metadata);
break;
} }
ACameraManager_deleteCameraIdList(camera_id_list); ACameraMetadata_free(camera_metadata);
}
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;
} }
mCameraId = camera_id;
camera_status_t res = ACAMERA_OK; camera_status_t res = ACAMERA_OK;
// setup imagereader and its surface // 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.onDisconnected = onDisconnected;
camera_device_state_callbacks.onError = onError; 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) if (res != ACAMERA_OK)
{ {
ALOGE("Failed to open camera res=%d", res); 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)); // std::this_thread::sleep_for(std::chrono::milliseconds(128));
// capture request // capture request
@ -573,9 +574,7 @@ void NdkCamera::close()
if (camera_manager) if (camera_manager)
{ {
#ifdef _DEBUG
ACameraManager_unregisterAvailabilityCallback(camera_manager, &camera_manager_cb); ACameraManager_unregisterAvailabilityCallback(camera_manager, &camera_manager_cb);
#endif
ACameraManager_delete(camera_manager); ACameraManager_delete(camera_manager);
camera_manager = 0; 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); 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); // __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;
}

@ -22,6 +22,8 @@
#include <opencv2/core/core.hpp> #include <opencv2/core/core.hpp>
#include "Camera2Helper.h" #include "Camera2Helper.h"
#include <mutex>
#include <set>
/** /**
* Range of Camera Exposure Time: * Range of Camera Exposure Time:
@ -67,6 +69,8 @@ public:
int open(const std::string& cameraId); int open(const std::string& cameraId);
void close(); void close();
void onAvailabilityCallback(const char* cameraId);
void onUnavailabilityCallback(const char* cameraId);
void onImageAvailable(AImageReader* reader); void onImageAvailable(AImageReader* reader);
virtual bool on_image(cv::Mat& rgb); virtual bool on_image(cv::Mat& rgb);
virtual void on_error(const std::string& msg); virtual void on_error(const std::string& msg);
@ -79,8 +83,13 @@ public:
return mResult; return mResult;
} }
bool IsCameraAvailable(const std::string& cameraId);
public: protected:
std::mutex m_locker;
std::set<std::string> m_availableCameras;
protected:
CAMERA_PARAMS m_params; CAMERA_PARAMS m_params;
int camera_facing; int camera_facing;
int camera_orientation; int camera_orientation;
@ -104,10 +113,9 @@ public:
CAPTURE_RESULT mResult; CAPTURE_RESULT mResult;
private: protected:
#ifdef _DEBUG
ACameraManager_AvailabilityCallbacks camera_manager_cb; ACameraManager_AvailabilityCallbacks camera_manager_cb;
#endif
ACameraManager* camera_manager; ACameraManager* camera_manager;
ACameraDevice* camera_device; ACameraDevice* camera_device;
AImageReader* image_reader; AImageReader* image_reader;

Loading…
Cancel
Save