Add HAL support for face detection feature.
Change-Id: Ic8a307db5e9a68ce696929e91f6442a9986c9830
diff --git a/QualcommCameraHardware.cpp b/QualcommCameraHardware.cpp
index 0c152be..40778ea 100644
--- a/QualcommCameraHardware.cpp
+++ b/QualcommCameraHardware.cpp
@@ -217,11 +217,11 @@
static unsigned int previewSizeCount;
board_property boardProperties[] = {
- {TARGET_MSM7625, 0x00000fff, false, false},
- {TARGET_MSM7627, 0x000006ff, false, false},
- {TARGET_MSM7630, 0x00000fff, true, true},
- {TARGET_MSM8660, 0x00001fff, true, true},
- {TARGET_QSD8250, 0x00000fff, false, false}
+ {TARGET_MSM7625, 0x00000fff, false, false, false},
+ {TARGET_MSM7627, 0x000006ff, false, false, false},
+ {TARGET_MSM7630, 0x00000fff, true, true, false},
+ {TARGET_MSM8660, 0x00001fff, true, true, false},
+ {TARGET_QSD8250, 0x00000fff, false, false, false}
};
//static const camera_size_type* picture_sizes;
@@ -686,6 +686,11 @@
{ CameraParameters::SELECTABLE_ZONE_AF_FRAME_AVERAGE, AVERAGE }
};
+static const str_map facedetection[] = {
+ { CameraParameters::FACE_DETECTION_OFF, FALSE },
+ { CameraParameters::FACE_DETECTION_ON, TRUE }
+};
+
#define DONT_CARE_COORDINATE -1
static const str_map touchafaec[] = {
{ CameraParameters::TOUCH_AF_AEC_OFF, FALSE },
@@ -702,11 +707,6 @@
int bitMask;
};
-
-/*
- * Values based on aec.c
- */
-
#define CAMERA_HISTOGRAM_ENABLE 1
#define CAMERA_HISTOGRAM_DISABLE 0
#define HISTOGRAM_STATS_SIZE 257
@@ -715,6 +715,9 @@
#define FOCUS_RECTANGLE_DX 100
#define FOCUS_RECTANGLE_DY 100
+/*
+ * Values based on aec.c
+ */
#define EXPOSURE_COMPENSATION_MAXIMUM_NUMERATOR 12
#define EXPOSURE_COMPENSATION_MINIMUM_NUMERATOR -12
#define EXPOSURE_COMPENSATION_DEFAULT_NUMERATOR 0
@@ -772,8 +775,11 @@
static String8 scenedetect_values;
static String8 preview_format_values;
static String8 selectable_zone_af_values;
+static String8 facedetection_values;
+
mm_camera_notify mCamNotify;
mm_camera_ops mCamOps;
+
static String8 create_sizes_str(const camera_size_type *sizes, int len) {
String8 str;
char buffer[32];
@@ -1188,6 +1194,18 @@
return false;
}
+bool QualcommCameraHardware::supportsFaceDetection() {
+ int prop = 0;
+ for(prop=0; prop<sizeof(boardProperties)/sizeof(board_property); prop++) {
+ if((mCurrentTarget == boardProperties[prop].target)
+ && boardProperties[prop].hasFaceDetect == true) {
+ return true;
+ break;
+ }
+ }
+ return false;
+}
+
void QualcommCameraHardware::initDefaultParameters()
{
LOGI("initDefaultParameters E");
@@ -1285,6 +1303,10 @@
selectable_zone_af, sizeof(selectable_zone_af) / sizeof(str_map));
}
+ if(mHasAutoFocusSupport && supportsFaceDetection()) {
+ facedetection_values = create_values_str(
+ facedetection, sizeof(facedetection) / sizeof(str_map));
+ }
parameter_string_initialized = true;
}
@@ -1479,6 +1501,10 @@
CameraParameters::SELECTABLE_ZONE_AF_AUTO);
mParameters.set(CameraParameters::KEY_SUPPORTED_SELECTABLE_ZONE_AF,
selectable_zone_af_values);
+ mParameters.set(CameraParameters::KEY_FACE_DETECTION,
+ CameraParameters::FACE_DETECTION_OFF);
+ mParameters.set(CameraParameters::KEY_SUPPORTED_FACE_DETECTION,
+ facedetection_values);
if (setParameters(mParameters) != NO_ERROR) {
LOGE("Failed to set default parameters?!");
}
@@ -3596,7 +3622,7 @@
if ((rc = setContinuousAf(params))) final_rc = rc;
if ((rc = setSelectableZoneAf(params))) final_rc = rc;
if ((rc = setTouchAfAec(params))) final_rc = rc;
- if ((rc = setSceneMode(params))) final_rc = rc;
+ if ((rc = setSceneMode(params))) final_rc = rc;
if ((rc = setContrast(params))) final_rc = rc;
if ((rc = setRecordSize(params))) final_rc = rc;
if ((rc = setSceneDetect(params))) final_rc = rc;
@@ -3693,6 +3719,45 @@
}
+status_t QualcommCameraHardware::runFaceDetection()
+{
+ bool ret = true;
+
+ const char *str = mParameters.get(CameraParameters::KEY_FACE_DETECTION);
+ if (str != NULL) {
+ int value = attr_lookup(facedetection,
+ sizeof(facedetection) / sizeof(str_map), str);
+
+ mMetaDataWaitLock.lock();
+ if (value == true) {
+ if(mMetaDataHeap != NULL)
+ mMetaDataHeap.clear();
+
+ mMetaDataHeap =
+ new AshmemPool((sizeof(int)*(MAX_ROI*4+1)),
+ 1,
+ (sizeof(int)*(MAX_ROI*4+1)),
+ "metadata");
+ if (!mMetaDataHeap->initialized()) {
+ LOGE("Meta Data Heap allocation failed ");
+ mMetaDataHeap.clear();
+ LOGE("runFaceDetection X: error initializing mMetaDataHeap");
+ mMetaDataWaitLock.unlock();
+ return UNKNOWN_ERROR;
+ }
+ mSendMetaData = true;
+ } else {
+ if(mMetaDataHeap != NULL)
+ mMetaDataHeap.clear();
+ }
+ mMetaDataWaitLock.unlock();
+ ret = native_set_parms(CAMERA_PARM_FD, sizeof(int8_t), (void *)&value);
+ return ret ? NO_ERROR : UNKNOWN_ERROR;
+ }
+ LOGE("Invalid Face Detection value: %s", (str == NULL) ? "NULL" : str);
+ return BAD_VALUE;
+}
+
status_t QualcommCameraHardware::sendCommand(int32_t command, int32_t arg1,
int32_t arg2)
{
@@ -3713,6 +3778,19 @@
mSendData = true;
mStatsWaitLock.unlock();
return NO_ERROR;
+ case CAMERA_CMD_FACE_DETECTION_ON:
+ setFaceDetection("on");
+ return runFaceDetection();
+ case CAMERA_CMD_FACE_DETECTION_OFF:
+ setFaceDetection("off");
+ return runFaceDetection();
+ case CAMERA_CMD_SEND_META_DATA:
+ mMetaDataWaitLock.lock();
+ if(mFaceDetectOn == true) {
+ mSendMetaData = true;
+ }
+ mMetaDataWaitLock.unlock();
+ return NO_ERROR;
}
return BAD_VALUE;
}
@@ -3951,13 +4029,14 @@
void *pdata = mCallbackCookie;
data_callback_timestamp rcb = mDataCallbackTimestamp;
void *rdata = mCallbackCookie;
+ data_callback mcb = mDataCallback;
+ void *mdata = mCallbackCookie;
mCallbackLock.unlock();
// Find the offset within the heap of the current buffer.
ssize_t offset_addr =
(ssize_t)frame->buffer - (ssize_t)mPreviewHeap->mHeap->base();
ssize_t offset = offset_addr / mPreviewHeap->mAlignedBufferSize;
-
common_crop_t *crop = (common_crop_t *) (frame->cropinfo);
#ifdef DUMP_PREVIEW_FRAMES
static int frameCnt = 0;
@@ -4067,9 +4146,40 @@
mReleasedRecordingFrame = false;
}
}
+
+ if ( mCurrentTarget == TARGET_MSM8660 ) {
+ mMetaDataWaitLock.lock();
+ if (mFaceDetectOn == true && mSendMetaData == true) {
+ mSendMetaData = false;
+ fd_roi_t *fd = (fd_roi_t *)(frame->roi_info.info);
+ int faces_detected = fd->rect_num;
+ int max_faces_detected = MAX_ROI * 4;
+ int array[max_faces_detected + 1];
+
+ array[0] = faces_detected * 4;
+ for (int i = 1, j = 0;j < MAX_ROI; j++, i = i + 4) {
+ if (j < faces_detected) {
+ array[i] = fd->faces[j].x;
+ array[i+1] = fd->faces[j].y;
+ array[i+2] = fd->faces[j].dx;
+ array[i+3] = fd->faces[j].dx;
+ } else {
+ array[i] = -1;
+ array[i+1] = -1;
+ array[i+2] = -1;
+ array[i+3] = -1;
+ }
+ }
+ memcpy((uint32_t *)mMetaDataHeap->mHeap->base(), (uint32_t *)array, (sizeof(int)*(MAX_ROI*4+1)));
+ if (mcb != NULL && (msgEnabled & CAMERA_MSG_META_DATA)) {
+ mcb(CAMERA_MSG_META_DATA, mMetaDataHeap->mBuffers[0], mdata);
+ }
+ }
+ mMetaDataWaitLock.unlock();
+ }
mInPreviewCallback = false;
-// LOGV("receivePreviewFrame X");
+// LOGV("receivePreviewFrame X");
}
void QualcommCameraHardware::receiveCameraStats(camstats_type stype, camera_preview_histogram_info* histinfo)
{
@@ -5430,6 +5540,23 @@
return NO_ERROR;
}
+status_t QualcommCameraHardware::setFaceDetection(const char *str)
+{
+ if (str != NULL) {
+ int value = attr_lookup(facedetection,
+ sizeof(facedetection) / sizeof(str_map), str);
+ if (value != NOT_FOUND) {
+ mMetaDataWaitLock.lock();
+ mFaceDetectOn = value;
+ mMetaDataWaitLock.unlock();
+ mParameters.set(CameraParameters::KEY_FACE_DETECTION, str);
+ return NO_ERROR;
+ }
+ }
+ LOGE("Invalid Face Detection value: %s", (str == NULL) ? "NULL" : str);
+ return BAD_VALUE;
+}
+
status_t QualcommCameraHardware::setISOValue(const CameraParameters& params) {
int8_t temp_hjr;
if(!mCfgControl.mm_camera_is_supported(CAMERA_PARM_ISO)) {
diff --git a/QualcommCameraHardware.h b/QualcommCameraHardware.h
index 55f4ce3..1efdde6 100644
--- a/QualcommCameraHardware.h
+++ b/QualcommCameraHardware.h
@@ -62,6 +62,7 @@
unsigned int previewSizeMask;
bool hasSceneDetect;
bool hasSelectableZoneAf;
+ bool hasFaceDetect;
};
namespace android {
@@ -123,6 +124,9 @@
status_t startPreviewInternal();
status_t setHistogramOn();
status_t setHistogramOff();
+ status_t runFaceDetection();
+ status_t setFaceDetection(const char *str);
+
void stopPreviewInternal();
friend void *auto_focus_thread(void *user);
void runAutoFocus();
@@ -208,6 +212,7 @@
sp<PmemPool> mDisplayHeap;
sp<AshmemPool> mJpegHeap;
sp<AshmemPool> mStatHeap;
+ sp<AshmemPool> mMetaDataHeap;
sp<PmemPool> mRawSnapShotPmemHeap;
sp<PmemPool> mPostViewHeap;
@@ -242,7 +247,10 @@
Mutex mStatsWaitLock;
Condition mStatsWait;
-
+ //For Face Detection
+ int mFaceDetectOn;
+ bool mSendMetaData;
+ Mutex mMetaDataWaitLock;
bool mShutterPending;
Mutex mShutterLock;
@@ -274,6 +282,7 @@
void storeTargetType();
bool supportsSceneDetection();
bool supportsSelectableZoneAf();
+ bool supportsFaceDetection();
void initDefaultParameters();
void findSensorType();