Loading core/java/android/hardware/Camera.java +11 −8 Original line number Diff line number Diff line Loading @@ -131,7 +131,7 @@ public class Camera { private static final int CAMERA_MSG_RAW_IMAGE = 0x080; private static final int CAMERA_MSG_COMPRESSED_IMAGE = 0x100; private static final int CAMERA_MSG_RAW_IMAGE_NOTIFY = 0x200; private static final int CAMERA_MSG_METADATA_FACE = 0x400; private static final int CAMERA_MSG_PREVIEW_METADATA = 0x400; private static final int CAMERA_MSG_ALL_MSGS = 0x4FF; private int mNativeContext; // accessed by native methods Loading Loading @@ -721,7 +721,7 @@ public class Camera { } return; case CAMERA_MSG_METADATA_FACE: case CAMERA_MSG_PREVIEW_METADATA: if (mFaceListener != null) { mFaceListener.onFaceDetection((Face[])msg.obj, mCamera); } Loading Loading @@ -1156,6 +1156,9 @@ public class Camera { * @hide */ public static class Face { public Face() { } /** * Bounds of the face. (-1000, -1000) represents the top-left of the * camera field of view, and (1000, 1000) represents the bottom-right of Loading @@ -1168,7 +1171,7 @@ public class Camera { * * @see #startFaceDetection(int) */ Rect rect; public Rect rect; /** * The confidence level of the face. The range is 1 to 100. 100 is the Loading @@ -1177,32 +1180,32 @@ public class Camera { * * @see #startFaceDetection(int) */ int score; public int score; /** * An unique id per face while the face is visible to the tracker. If * the face leaves the field-of-view and comes back, it will get a new * id. If the value is 0, id is not supported. */ int id; public int id; /** * The coordinates of the center of the left eye. The range is -1000 to * 1000. null if this is not supported. */ Point leftEye; public Point leftEye; /** * The coordinates of the center of the right eye. The range is -1000 to * 1000. null if this is not supported. */ Point rightEye; public Point rightEye; /** * The coordinates of the center of the mouth. The range is -1000 to * 1000. null if this is not supported. */ Point mouth; public Point mouth; } // Error codes match the enum in include/ui/Camera.h Loading core/jni/android_hardware_Camera.cpp +85 −9 Original line number Diff line number Diff line Loading @@ -45,6 +45,8 @@ struct fields_t { jfieldID rect_right; jfieldID rect_bottom; jmethodID post_event; jmethodID rect_constructor; jmethodID face_constructor; }; static fields_t fields; Loading @@ -57,8 +59,10 @@ public: JNICameraContext(JNIEnv* env, jobject weak_this, jclass clazz, const sp<Camera>& camera); ~JNICameraContext() { release(); } virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2); virtual void postData(int32_t msgType, const sp<IMemory>& dataPtr); virtual void postData(int32_t msgType, const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata); virtual void postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr); void postMetadata(JNIEnv *env, int32_t msgType, camera_frame_metadata_t *metadata); void addCallbackBuffer(JNIEnv *env, jbyteArray cbb, int msgType); void setCallbackMode(JNIEnv *env, bool installed, bool manualMode); sp<Camera> getCamera() { Mutex::Autolock _l(mLock); return mCamera; } Loading @@ -74,6 +78,8 @@ private: jobject mCameraJObjectWeak; // weak reference to java object jclass mCameraJClass; // strong reference to java class sp<Camera> mCamera; // strong reference to native object jclass mFaceClass; // strong reference to Face class jclass mRectClass; // strong reference to Rect class Mutex mLock; /* Loading Loading @@ -124,6 +130,12 @@ JNICameraContext::JNICameraContext(JNIEnv* env, jobject weak_this, jclass clazz, mCameraJClass = (jclass)env->NewGlobalRef(clazz); mCamera = camera; jclass faceClazz = env->FindClass("android/hardware/Camera$Face"); mFaceClass = (jclass) env->NewGlobalRef(faceClazz); jclass rectClazz = env->FindClass("android/graphics/Rect"); mRectClass = (jclass) env->NewGlobalRef(rectClazz); mManualBufferMode = false; mManualCameraCallbackSet = false; } Loading @@ -142,6 +154,14 @@ void JNICameraContext::release() env->DeleteGlobalRef(mCameraJClass); mCameraJClass = NULL; } if (mFaceClass != NULL) { env->DeleteGlobalRef(mFaceClass); mFaceClass = NULL; } if (mRectClass != NULL) { env->DeleteGlobalRef(mRectClass); mRectClass = NULL; } clearCallbackBuffers_l(env); mCamera.clear(); } Loading Loading @@ -263,7 +283,8 @@ void JNICameraContext::copyAndPost(JNIEnv* env, const sp<IMemory>& dataPtr, int } } void JNICameraContext::postData(int32_t msgType, const sp<IMemory>& dataPtr) void JNICameraContext::postData(int32_t msgType, const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata) { // VM pointer will be NULL if object is released Mutex::Autolock _l(mLock); Loading @@ -273,8 +294,10 @@ void JNICameraContext::postData(int32_t msgType, const sp<IMemory>& dataPtr) return; } int32_t dataMsgType = msgType & ~CAMERA_MSG_PREVIEW_METADATA; // return data based on callback type switch (msgType) { switch (dataMsgType) { case CAMERA_MSG_VIDEO_FRAME: // should never happen break; Loading @@ -285,23 +308,63 @@ void JNICameraContext::postData(int32_t msgType, const sp<IMemory>& dataPtr) LOGV("rawCallback"); if (mRawImageCallbackBuffers.isEmpty()) { env->CallStaticVoidMethod(mCameraJClass, fields.post_event, mCameraJObjectWeak, msgType, 0, 0, NULL); mCameraJObjectWeak, dataMsgType, 0, 0, NULL); } else { copyAndPost(env, dataPtr, msgType); copyAndPost(env, dataPtr, dataMsgType); } break; // There is no data. case 0: break; default: LOGV("dataCallback(%d, %p)", msgType, dataPtr.get()); copyAndPost(env, dataPtr, msgType); LOGV("dataCallback(%d, %p)", dataMsgType, dataPtr.get()); copyAndPost(env, dataPtr, dataMsgType); break; } // post frame metadata to Java if (metadata && (msgType & CAMERA_MSG_PREVIEW_METADATA)) { postMetadata(env, CAMERA_MSG_PREVIEW_METADATA, metadata); } } void JNICameraContext::postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) { // TODO: plumb up to Java. For now, just drop the timestamp postData(msgType, dataPtr); postData(msgType, dataPtr, NULL); } void JNICameraContext::postMetadata(JNIEnv *env, int32_t msgType, camera_frame_metadata_t *metadata) { jobjectArray obj = NULL; obj = (jobjectArray) env->NewObjectArray(metadata->number_of_faces, mFaceClass, NULL); if (obj == NULL) { LOGE("Couldn't allocate face metadata array"); return; } for (int i = 0; i < metadata->number_of_faces; i++) { jobject face = env->NewObject(mFaceClass, fields.face_constructor); env->SetObjectArrayElement(obj, i, face); jobject rect = env->NewObject(mRectClass, fields.rect_constructor); env->SetIntField(rect, fields.rect_left, metadata->faces[i].rect[0]); env->SetIntField(rect, fields.rect_top, metadata->faces[i].rect[1]); env->SetIntField(rect, fields.rect_right, metadata->faces[i].rect[2]); env->SetIntField(rect, fields.rect_bottom, metadata->faces[i].rect[3]); env->SetObjectField(face, fields.face_rect, rect); env->SetIntField(face, fields.face_score, metadata->faces[i].score); env->DeleteLocalRef(face); env->DeleteLocalRef(rect); } env->CallStaticVoidMethod(mCameraJClass, fields.post_event, mCameraJObjectWeak, msgType, 0, 0, obj); env->DeleteLocalRef(obj); } void JNICameraContext::setCallbackMode(JNIEnv *env, bool installed, bool manualMode) Loading Loading @@ -715,7 +778,7 @@ static void android_hardware_Camera_setDisplayOrientation(JNIEnv *env, jobject t } static void android_hardware_Camera_startFaceDetection(JNIEnv *env, jobject thiz, jint type, jobjectArray face) jint type) { LOGV("startFaceDetection"); JNICameraContext* context; Loading Loading @@ -878,6 +941,19 @@ int register_android_hardware_Camera(JNIEnv *env) return -1; } clazz = env->FindClass("android/graphics/Rect"); fields.rect_constructor = env->GetMethodID(clazz, "<init>", "()V"); if (fields.rect_constructor == NULL) { LOGE("Can't find android/graphics/Rect.Rect()"); return -1; } clazz = env->FindClass("android/hardware/Camera$Face"); fields.face_constructor = env->GetMethodID(clazz, "<init>", "()V"); if (fields.face_constructor == NULL) { LOGE("Can't find android/hardware/Camera$Face.Face()"); return -1; } // Register native functions return AndroidRuntime::registerNativeMethods(env, "android/hardware/Camera", Loading include/camera/Camera.h +4 −2 Original line number Diff line number Diff line Loading @@ -59,7 +59,8 @@ class CameraListener: virtual public RefBase { public: virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2) = 0; virtual void postData(int32_t msgType, const sp<IMemory>& dataPtr) = 0; virtual void postData(int32_t msgType, const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata) = 0; virtual void postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) = 0; }; Loading Loading @@ -138,7 +139,8 @@ public: // ICameraClient interface virtual void notifyCallback(int32_t msgType, int32_t ext, int32_t ext2); virtual void dataCallback(int32_t msgType, const sp<IMemory>& dataPtr); virtual void dataCallback(int32_t msgType, const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata); virtual void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr); sp<ICamera> remote(); Loading include/camera/ICameraClient.h +3 −1 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include <binder/Parcel.h> #include <binder/IMemory.h> #include <utils/Timers.h> #include <system/camera.h> namespace android { Loading @@ -31,7 +32,8 @@ public: DECLARE_META_INTERFACE(CameraClient); virtual void notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2) = 0; virtual void dataCallback(int32_t msgType, const sp<IMemory>& data) = 0; virtual void dataCallback(int32_t msgType, const sp<IMemory>& data, camera_frame_metadata_t *metadata) = 0; virtual void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& data) = 0; }; Loading libs/camera/Camera.cpp +3 −2 Original line number Diff line number Diff line Loading @@ -360,7 +360,8 @@ void Camera::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2) } // callback from camera service when frame or image is ready void Camera::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr) void Camera::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata) { sp<CameraListener> listener; { Loading @@ -368,7 +369,7 @@ void Camera::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr) listener = mListener; } if (listener != NULL) { listener->postData(msgType, dataPtr); listener->postData(msgType, dataPtr, metadata); } } Loading Loading
core/java/android/hardware/Camera.java +11 −8 Original line number Diff line number Diff line Loading @@ -131,7 +131,7 @@ public class Camera { private static final int CAMERA_MSG_RAW_IMAGE = 0x080; private static final int CAMERA_MSG_COMPRESSED_IMAGE = 0x100; private static final int CAMERA_MSG_RAW_IMAGE_NOTIFY = 0x200; private static final int CAMERA_MSG_METADATA_FACE = 0x400; private static final int CAMERA_MSG_PREVIEW_METADATA = 0x400; private static final int CAMERA_MSG_ALL_MSGS = 0x4FF; private int mNativeContext; // accessed by native methods Loading Loading @@ -721,7 +721,7 @@ public class Camera { } return; case CAMERA_MSG_METADATA_FACE: case CAMERA_MSG_PREVIEW_METADATA: if (mFaceListener != null) { mFaceListener.onFaceDetection((Face[])msg.obj, mCamera); } Loading Loading @@ -1156,6 +1156,9 @@ public class Camera { * @hide */ public static class Face { public Face() { } /** * Bounds of the face. (-1000, -1000) represents the top-left of the * camera field of view, and (1000, 1000) represents the bottom-right of Loading @@ -1168,7 +1171,7 @@ public class Camera { * * @see #startFaceDetection(int) */ Rect rect; public Rect rect; /** * The confidence level of the face. The range is 1 to 100. 100 is the Loading @@ -1177,32 +1180,32 @@ public class Camera { * * @see #startFaceDetection(int) */ int score; public int score; /** * An unique id per face while the face is visible to the tracker. If * the face leaves the field-of-view and comes back, it will get a new * id. If the value is 0, id is not supported. */ int id; public int id; /** * The coordinates of the center of the left eye. The range is -1000 to * 1000. null if this is not supported. */ Point leftEye; public Point leftEye; /** * The coordinates of the center of the right eye. The range is -1000 to * 1000. null if this is not supported. */ Point rightEye; public Point rightEye; /** * The coordinates of the center of the mouth. The range is -1000 to * 1000. null if this is not supported. */ Point mouth; public Point mouth; } // Error codes match the enum in include/ui/Camera.h Loading
core/jni/android_hardware_Camera.cpp +85 −9 Original line number Diff line number Diff line Loading @@ -45,6 +45,8 @@ struct fields_t { jfieldID rect_right; jfieldID rect_bottom; jmethodID post_event; jmethodID rect_constructor; jmethodID face_constructor; }; static fields_t fields; Loading @@ -57,8 +59,10 @@ public: JNICameraContext(JNIEnv* env, jobject weak_this, jclass clazz, const sp<Camera>& camera); ~JNICameraContext() { release(); } virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2); virtual void postData(int32_t msgType, const sp<IMemory>& dataPtr); virtual void postData(int32_t msgType, const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata); virtual void postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr); void postMetadata(JNIEnv *env, int32_t msgType, camera_frame_metadata_t *metadata); void addCallbackBuffer(JNIEnv *env, jbyteArray cbb, int msgType); void setCallbackMode(JNIEnv *env, bool installed, bool manualMode); sp<Camera> getCamera() { Mutex::Autolock _l(mLock); return mCamera; } Loading @@ -74,6 +78,8 @@ private: jobject mCameraJObjectWeak; // weak reference to java object jclass mCameraJClass; // strong reference to java class sp<Camera> mCamera; // strong reference to native object jclass mFaceClass; // strong reference to Face class jclass mRectClass; // strong reference to Rect class Mutex mLock; /* Loading Loading @@ -124,6 +130,12 @@ JNICameraContext::JNICameraContext(JNIEnv* env, jobject weak_this, jclass clazz, mCameraJClass = (jclass)env->NewGlobalRef(clazz); mCamera = camera; jclass faceClazz = env->FindClass("android/hardware/Camera$Face"); mFaceClass = (jclass) env->NewGlobalRef(faceClazz); jclass rectClazz = env->FindClass("android/graphics/Rect"); mRectClass = (jclass) env->NewGlobalRef(rectClazz); mManualBufferMode = false; mManualCameraCallbackSet = false; } Loading @@ -142,6 +154,14 @@ void JNICameraContext::release() env->DeleteGlobalRef(mCameraJClass); mCameraJClass = NULL; } if (mFaceClass != NULL) { env->DeleteGlobalRef(mFaceClass); mFaceClass = NULL; } if (mRectClass != NULL) { env->DeleteGlobalRef(mRectClass); mRectClass = NULL; } clearCallbackBuffers_l(env); mCamera.clear(); } Loading Loading @@ -263,7 +283,8 @@ void JNICameraContext::copyAndPost(JNIEnv* env, const sp<IMemory>& dataPtr, int } } void JNICameraContext::postData(int32_t msgType, const sp<IMemory>& dataPtr) void JNICameraContext::postData(int32_t msgType, const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata) { // VM pointer will be NULL if object is released Mutex::Autolock _l(mLock); Loading @@ -273,8 +294,10 @@ void JNICameraContext::postData(int32_t msgType, const sp<IMemory>& dataPtr) return; } int32_t dataMsgType = msgType & ~CAMERA_MSG_PREVIEW_METADATA; // return data based on callback type switch (msgType) { switch (dataMsgType) { case CAMERA_MSG_VIDEO_FRAME: // should never happen break; Loading @@ -285,23 +308,63 @@ void JNICameraContext::postData(int32_t msgType, const sp<IMemory>& dataPtr) LOGV("rawCallback"); if (mRawImageCallbackBuffers.isEmpty()) { env->CallStaticVoidMethod(mCameraJClass, fields.post_event, mCameraJObjectWeak, msgType, 0, 0, NULL); mCameraJObjectWeak, dataMsgType, 0, 0, NULL); } else { copyAndPost(env, dataPtr, msgType); copyAndPost(env, dataPtr, dataMsgType); } break; // There is no data. case 0: break; default: LOGV("dataCallback(%d, %p)", msgType, dataPtr.get()); copyAndPost(env, dataPtr, msgType); LOGV("dataCallback(%d, %p)", dataMsgType, dataPtr.get()); copyAndPost(env, dataPtr, dataMsgType); break; } // post frame metadata to Java if (metadata && (msgType & CAMERA_MSG_PREVIEW_METADATA)) { postMetadata(env, CAMERA_MSG_PREVIEW_METADATA, metadata); } } void JNICameraContext::postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) { // TODO: plumb up to Java. For now, just drop the timestamp postData(msgType, dataPtr); postData(msgType, dataPtr, NULL); } void JNICameraContext::postMetadata(JNIEnv *env, int32_t msgType, camera_frame_metadata_t *metadata) { jobjectArray obj = NULL; obj = (jobjectArray) env->NewObjectArray(metadata->number_of_faces, mFaceClass, NULL); if (obj == NULL) { LOGE("Couldn't allocate face metadata array"); return; } for (int i = 0; i < metadata->number_of_faces; i++) { jobject face = env->NewObject(mFaceClass, fields.face_constructor); env->SetObjectArrayElement(obj, i, face); jobject rect = env->NewObject(mRectClass, fields.rect_constructor); env->SetIntField(rect, fields.rect_left, metadata->faces[i].rect[0]); env->SetIntField(rect, fields.rect_top, metadata->faces[i].rect[1]); env->SetIntField(rect, fields.rect_right, metadata->faces[i].rect[2]); env->SetIntField(rect, fields.rect_bottom, metadata->faces[i].rect[3]); env->SetObjectField(face, fields.face_rect, rect); env->SetIntField(face, fields.face_score, metadata->faces[i].score); env->DeleteLocalRef(face); env->DeleteLocalRef(rect); } env->CallStaticVoidMethod(mCameraJClass, fields.post_event, mCameraJObjectWeak, msgType, 0, 0, obj); env->DeleteLocalRef(obj); } void JNICameraContext::setCallbackMode(JNIEnv *env, bool installed, bool manualMode) Loading Loading @@ -715,7 +778,7 @@ static void android_hardware_Camera_setDisplayOrientation(JNIEnv *env, jobject t } static void android_hardware_Camera_startFaceDetection(JNIEnv *env, jobject thiz, jint type, jobjectArray face) jint type) { LOGV("startFaceDetection"); JNICameraContext* context; Loading Loading @@ -878,6 +941,19 @@ int register_android_hardware_Camera(JNIEnv *env) return -1; } clazz = env->FindClass("android/graphics/Rect"); fields.rect_constructor = env->GetMethodID(clazz, "<init>", "()V"); if (fields.rect_constructor == NULL) { LOGE("Can't find android/graphics/Rect.Rect()"); return -1; } clazz = env->FindClass("android/hardware/Camera$Face"); fields.face_constructor = env->GetMethodID(clazz, "<init>", "()V"); if (fields.face_constructor == NULL) { LOGE("Can't find android/hardware/Camera$Face.Face()"); return -1; } // Register native functions return AndroidRuntime::registerNativeMethods(env, "android/hardware/Camera", Loading
include/camera/Camera.h +4 −2 Original line number Diff line number Diff line Loading @@ -59,7 +59,8 @@ class CameraListener: virtual public RefBase { public: virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2) = 0; virtual void postData(int32_t msgType, const sp<IMemory>& dataPtr) = 0; virtual void postData(int32_t msgType, const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata) = 0; virtual void postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) = 0; }; Loading Loading @@ -138,7 +139,8 @@ public: // ICameraClient interface virtual void notifyCallback(int32_t msgType, int32_t ext, int32_t ext2); virtual void dataCallback(int32_t msgType, const sp<IMemory>& dataPtr); virtual void dataCallback(int32_t msgType, const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata); virtual void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr); sp<ICamera> remote(); Loading
include/camera/ICameraClient.h +3 −1 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include <binder/Parcel.h> #include <binder/IMemory.h> #include <utils/Timers.h> #include <system/camera.h> namespace android { Loading @@ -31,7 +32,8 @@ public: DECLARE_META_INTERFACE(CameraClient); virtual void notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2) = 0; virtual void dataCallback(int32_t msgType, const sp<IMemory>& data) = 0; virtual void dataCallback(int32_t msgType, const sp<IMemory>& data, camera_frame_metadata_t *metadata) = 0; virtual void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& data) = 0; }; Loading
libs/camera/Camera.cpp +3 −2 Original line number Diff line number Diff line Loading @@ -360,7 +360,8 @@ void Camera::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2) } // callback from camera service when frame or image is ready void Camera::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr) void Camera::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata) { sp<CameraListener> listener; { Loading @@ -368,7 +369,7 @@ void Camera::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr) listener = mListener; } if (listener != NULL) { listener->postData(msgType, dataPtr); listener->postData(msgType, dataPtr, metadata); } } Loading