diff options
author | Wu-cheng Li <wuchengli@google.com> | 2011-07-30 05:00:37 +0800 |
---|---|---|
committer | Wu-cheng Li <wuchengli@google.com> | 2011-08-02 15:48:41 +0800 |
commit | bb1e275c0e684dd213f124da77110cdd9d6f090c (patch) | |
tree | 0a20f8da5c8e09ca8663053ae39e544bfd315243 | |
parent | 0175028b73eefc503f67d5686b71e1957677e0de (diff) | |
download | frameworks_base-bb1e275c0e684dd213f124da77110cdd9d6f090c.zip frameworks_base-bb1e275c0e684dd213f124da77110cdd9d6f090c.tar.gz frameworks_base-bb1e275c0e684dd213f124da77110cdd9d6f090c.tar.bz2 |
Pass camera frame metadata from camera service to Java.
bug:4460717
Change-Id: I2fae6e1dfca6b8f3a5ee5716fc7817f5417bf657
-rw-r--r-- | core/java/android/hardware/Camera.java | 19 | ||||
-rw-r--r-- | core/jni/android_hardware_Camera.cpp | 94 | ||||
-rw-r--r-- | include/camera/Camera.h | 6 | ||||
-rw-r--r-- | include/camera/ICameraClient.h | 4 | ||||
-rw-r--r-- | libs/camera/Camera.cpp | 5 | ||||
-rw-r--r-- | libs/camera/ICameraClient.cpp | 17 | ||||
-rwxr-xr-x | media/libstagefright/CameraSource.cpp | 6 | ||||
-rw-r--r-- | services/camera/libcameraservice/CameraService.cpp | 40 | ||||
-rw-r--r-- | services/camera/libcameraservice/CameraService.h | 10 |
9 files changed, 153 insertions, 48 deletions
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java index 4128a2c..6767747 100644 --- a/core/java/android/hardware/Camera.java +++ b/core/java/android/hardware/Camera.java @@ -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 @@ -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); } @@ -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 @@ -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 @@ -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 diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp index 3dcaa37..884fa78 100644 --- a/core/jni/android_hardware_Camera.cpp +++ b/core/jni/android_hardware_Camera.cpp @@ -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; @@ -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; } @@ -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; /* @@ -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; } @@ -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(); } @@ -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); @@ -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; @@ -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) @@ -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; @@ -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", diff --git a/include/camera/Camera.h b/include/camera/Camera.h index f701280..234e165 100644 --- a/include/camera/Camera.h +++ b/include/camera/Camera.h @@ -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; }; @@ -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(); diff --git a/include/camera/ICameraClient.h b/include/camera/ICameraClient.h index 236d0f6..b30aa7a 100644 --- a/include/camera/ICameraClient.h +++ b/include/camera/ICameraClient.h @@ -22,6 +22,7 @@ #include <binder/Parcel.h> #include <binder/IMemory.h> #include <utils/Timers.h> +#include <system/camera.h> namespace android { @@ -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; }; diff --git a/libs/camera/Camera.cpp b/libs/camera/Camera.cpp index 3c00db5..7ac3cc1 100644 --- a/libs/camera/Camera.cpp +++ b/libs/camera/Camera.cpp @@ -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; { @@ -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); } } diff --git a/libs/camera/ICameraClient.cpp b/libs/camera/ICameraClient.cpp index cb3bd0c..183429a 100644 --- a/libs/camera/ICameraClient.cpp +++ b/libs/camera/ICameraClient.cpp @@ -51,13 +51,18 @@ public: } // generic data callback from camera service to app with image data - void dataCallback(int32_t msgType, const sp<IMemory>& imageData) + void dataCallback(int32_t msgType, const sp<IMemory>& imageData, + camera_frame_metadata_t *metadata) { LOGV("dataCallback"); Parcel data, reply; data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor()); data.writeInt32(msgType); data.writeStrongBinder(imageData->asBinder()); + if (metadata) { + data.writeInt32(metadata->number_of_faces); + data.write(metadata->faces, sizeof(camera_face_t) * metadata->number_of_faces); + } remote()->transact(DATA_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY); } @@ -96,7 +101,15 @@ status_t BnCameraClient::onTransact( CHECK_INTERFACE(ICameraClient, data, reply); int32_t msgType = data.readInt32(); sp<IMemory> imageData = interface_cast<IMemory>(data.readStrongBinder()); - dataCallback(msgType, imageData); + camera_frame_metadata_t *metadata = NULL; + if (data.dataAvail() > 0) { + metadata = new camera_frame_metadata_t; + metadata->number_of_faces = data.readInt32(); + metadata->faces = (camera_face_t *) data.readInplace( + sizeof(camera_face_t) * metadata->number_of_faces); + } + dataCallback(msgType, imageData, metadata); + if (metadata) delete metadata; return NO_ERROR; } break; case DATA_CALLBACK_TIMESTAMP: { diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp index de66d99..ea8eaa4 100755 --- a/media/libstagefright/CameraSource.cpp +++ b/media/libstagefright/CameraSource.cpp @@ -37,7 +37,8 @@ struct CameraSourceListener : public CameraListener { CameraSourceListener(const sp<CameraSource> &source); 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); @@ -63,7 +64,8 @@ void CameraSourceListener::notify(int32_t msgType, int32_t ext1, int32_t ext2) { LOGV("notify(%d, %d, %d)", msgType, ext1, ext2); } -void CameraSourceListener::postData(int32_t msgType, const sp<IMemory> &dataPtr) { +void CameraSourceListener::postData(int32_t msgType, const sp<IMemory> &dataPtr, + camera_frame_metadata_t *metadata) { LOGV("postData(%d, ptr:%p, size:%d)", msgType, dataPtr->pointer(), dataPtr->size()); diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index def25d1..e193be0 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -350,10 +350,9 @@ CameraService::Client::Client(const sp<CameraService>& cameraService, dataCallbackTimestamp, (void *)cameraId); - // Enable zoom, error, and focus messages by default - enableMsgType(CAMERA_MSG_ERROR | - CAMERA_MSG_ZOOM | - CAMERA_MSG_FOCUS); + // Enable zoom, error, focus, and metadata messages by default + enableMsgType(CAMERA_MSG_ERROR | CAMERA_MSG_ZOOM | CAMERA_MSG_FOCUS | + CAMERA_MSG_PREVIEW_METADATA); // Callback is disabled by default mPreviewCallbackFlag = CAMERA_FRAME_CALLBACK_FLAG_NOOP; @@ -995,15 +994,15 @@ void CameraService::Client::dataCallback(int32_t msgType, if (client == 0) return; if (!client->lockIfMessageWanted(msgType)) return; - if (dataPtr == 0) { + if (dataPtr == 0 && metadata == NULL) { LOGE("Null data returned in data callback"); client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0); return; } - switch (msgType) { + switch (msgType & ~CAMERA_MSG_PREVIEW_METADATA) { case CAMERA_MSG_PREVIEW_FRAME: - client->handlePreviewData(dataPtr); + client->handlePreviewData(msgType, dataPtr, metadata); break; case CAMERA_MSG_POSTVIEW_FRAME: client->handlePostview(dataPtr); @@ -1015,7 +1014,7 @@ void CameraService::Client::dataCallback(int32_t msgType, client->handleCompressedPicture(dataPtr); break; default: - client->handleGenericData(msgType, dataPtr); + client->handleGenericData(msgType, dataPtr, metadata); break; } } @@ -1055,7 +1054,9 @@ void CameraService::Client::handleShutter(void) { } // preview callback - frame buffer update -void CameraService::Client::handlePreviewData(const sp<IMemory>& mem) { +void CameraService::Client::handlePreviewData(int32_t msgType, + const sp<IMemory>& mem, + camera_frame_metadata_t *metadata) { ssize_t offset; size_t size; sp<IMemoryHeap> heap = mem->getMemory(&offset, &size); @@ -1087,11 +1088,11 @@ void CameraService::Client::handlePreviewData(const sp<IMemory>& mem) { // Is the received frame copied out or not? if (flags & CAMERA_FRAME_CALLBACK_FLAG_COPY_OUT_MASK) { LOG2("frame is copied"); - copyFrameAndPostCopiedFrame(c, heap, offset, size); + copyFrameAndPostCopiedFrame(msgType, c, heap, offset, size, metadata); } else { LOG2("frame is forwarded"); mLock.unlock(); - c->dataCallback(CAMERA_MSG_PREVIEW_FRAME, mem); + c->dataCallback(msgType, mem, metadata); } } else { mLock.unlock(); @@ -1105,7 +1106,7 @@ void CameraService::Client::handlePostview(const sp<IMemory>& mem) { sp<ICameraClient> c = mCameraClient; mLock.unlock(); if (c != 0) { - c->dataCallback(CAMERA_MSG_POSTVIEW_FRAME, mem); + c->dataCallback(CAMERA_MSG_POSTVIEW_FRAME, mem, NULL); } } @@ -1120,7 +1121,7 @@ void CameraService::Client::handleRawPicture(const sp<IMemory>& mem) { sp<ICameraClient> c = mCameraClient; mLock.unlock(); if (c != 0) { - c->dataCallback(CAMERA_MSG_RAW_IMAGE, mem); + c->dataCallback(CAMERA_MSG_RAW_IMAGE, mem, NULL); } } @@ -1131,7 +1132,7 @@ void CameraService::Client::handleCompressedPicture(const sp<IMemory>& mem) { sp<ICameraClient> c = mCameraClient; mLock.unlock(); if (c != 0) { - c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem); + c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem, NULL); } } @@ -1146,11 +1147,11 @@ void CameraService::Client::handleGenericNotify(int32_t msgType, } void CameraService::Client::handleGenericData(int32_t msgType, - const sp<IMemory>& dataPtr) { + const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata) { sp<ICameraClient> c = mCameraClient; mLock.unlock(); if (c != 0) { - c->dataCallback(msgType, dataPtr); + c->dataCallback(msgType, dataPtr, metadata); } } @@ -1164,8 +1165,9 @@ void CameraService::Client::handleGenericDataTimestamp(nsecs_t timestamp, } void CameraService::Client::copyFrameAndPostCopiedFrame( - const sp<ICameraClient>& client, const sp<IMemoryHeap>& heap, - size_t offset, size_t size) { + int32_t msgType, const sp<ICameraClient>& client, + const sp<IMemoryHeap>& heap, size_t offset, size_t size, + camera_frame_metadata_t *metadata) { LOG2("copyFrameAndPostCopiedFrame"); // It is necessary to copy out of pmem before sending this to // the callback. For efficiency, reuse the same MemoryHeapBase @@ -1197,7 +1199,7 @@ void CameraService::Client::copyFrameAndPostCopiedFrame( } mLock.unlock(); - client->dataCallback(CAMERA_MSG_PREVIEW_FRAME, frame); + client->dataCallback(msgType, frame, metadata); } int CameraService::Client::getOrientation(int degrees, bool mirror) { diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h index af7f06e..57abf83 100644 --- a/services/camera/libcameraservice/CameraService.h +++ b/services/camera/libcameraservice/CameraService.h @@ -147,18 +147,22 @@ private: static sp<Client> getClientFromCookie(void* user); // handlers for messages void handleShutter(void); - void handlePreviewData(const sp<IMemory>& mem); + void handlePreviewData(int32_t msgType, const sp<IMemory>& mem, + camera_frame_metadata_t *metadata); void handlePostview(const sp<IMemory>& mem); void handleRawPicture(const sp<IMemory>& mem); void handleCompressedPicture(const sp<IMemory>& mem); void handleGenericNotify(int32_t msgType, int32_t ext1, int32_t ext2); - void handleGenericData(int32_t msgType, const sp<IMemory>& dataPtr); + void handleGenericData(int32_t msgType, const sp<IMemory>& dataPtr, + camera_frame_metadata_t *metadata); void handleGenericDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr); void copyFrameAndPostCopiedFrame( + int32_t msgType, const sp<ICameraClient>& client, const sp<IMemoryHeap>& heap, - size_t offset, size_t size); + size_t offset, size_t size, + camera_frame_metadata_t *metadata); int getOrientation(int orientation, bool mirror); |