summaryrefslogtreecommitdiffstats
path: root/camera
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2008-12-17 18:05:43 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2008-12-17 18:05:43 -0800
commite09fd9e819c23dc90bca68375645e15544861330 (patch)
tree9a9fdadd1301625f875a3c126c986c79e3363ac4 /camera
parent7c1b96a165f970a09ed239bb4fb3f1b0d8f2a407 (diff)
downloadframeworks_native-e09fd9e819c23dc90bca68375645e15544861330.tar.gz
frameworks_native-e09fd9e819c23dc90bca68375645e15544861330.tar.bz2
frameworks_native-e09fd9e819c23dc90bca68375645e15544861330.zip
Code drop from //branches/cupcake/...@124589
Diffstat (limited to 'camera')
-rw-r--r--camera/libcameraservice/Android.mk11
-rw-r--r--camera/libcameraservice/CameraService.cpp135
-rw-r--r--camera/libcameraservice/CameraService.h26
3 files changed, 116 insertions, 56 deletions
diff --git a/camera/libcameraservice/Android.mk b/camera/libcameraservice/Android.mk
index 4e7d6d23e..2dfe659a2 100644
--- a/camera/libcameraservice/Android.mk
+++ b/camera/libcameraservice/Android.mk
@@ -4,12 +4,13 @@ LOCAL_PATH:= $(call my-dir)
# Set USE_CAMERA_STUB for non-emulator and non-simulator builds, if you want
# the camera service to use the fake camera. For emulator or simulator builds,
# we always use the fake camera.
-#
-ifeq ($(BOARD_CAMERA_LIBRARIES),)
-USE_CAMERA_STUB:=true
-else
+
+ifeq ($(USE_CAMERA_STUB),)
USE_CAMERA_STUB:=false
+ifneq ($(filter sooner generic sim,$(TARGET_DEVICE)),)
+USE_CAMERA_STUB:=true
endif #libcamerastub
+endif
ifeq ($(USE_CAMERA_STUB),true)
#
@@ -51,7 +52,7 @@ ifeq ($(USE_CAMERA_STUB), true)
LOCAL_STATIC_LIBRARIES += libcamerastub
LOCAL_CFLAGS += -include CameraHardwareStub.h
else
-LOCAL_SHARED_LIBRARIES += $(BOARD_CAMERA_LIBRARIES)
+LOCAL_SHARED_LIBRARIES += libcamera
endif
include $(BUILD_SHARED_LIBRARY)
diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp
index 5784c4b12..800ffa48a 100644
--- a/camera/libcameraservice/CameraService.cpp
+++ b/camera/libcameraservice/CameraService.cpp
@@ -1,6 +1,7 @@
/*
**
-** Copyright 2008, The Android Open Source Project
+** Copyright (C) 2008, The Android Open Source Project
+** Copyright (C) 2008 HTC Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
@@ -15,7 +16,7 @@
** limitations under the License.
*/
-
+//#define LOG_NDEBUG 0
#define LOG_TAG "CameraService"
#include <utils/Log.h>
@@ -155,10 +156,22 @@ CameraService::Client::Client(const sp<CameraService>& cameraService,
{
LOGD("Client E constructor");
mHardware = openCameraHardware();
- mHasFrameCallback = false;
+
+ // Callback is disabled by default
+ mFrameCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
LOGD("Client X constructor");
}
+status_t CameraService::Client::connect(const sp<ICameraClient>& client)
+{
+ // remvoe old client
+ LOGD("connect (new client)");
+ Mutex::Autolock _l(mLock);
+ mCameraClient = client;
+ mFrameCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
+ return NO_ERROR;
+}
+
#if HAVE_ANDROID_OS
static void *unregister_surface(void *arg)
{
@@ -170,7 +183,7 @@ static void *unregister_surface(void *arg)
#endif
CameraService::Client::~Client()
-{
+{
// spin down hardware
LOGD("Client E destructor");
if (mSurface != 0) {
@@ -179,7 +192,7 @@ CameraService::Client::~Client()
// We unregister the buffers in a different thread because binder does
// not let us make sychronous transactions in a binder destructor (that
// is, upon our reaching a refcount of zero.)
- pthread_create(&thr, NULL,
+ pthread_create(&thr, NULL,
unregister_surface,
mSurface.get());
pthread_join(thr, NULL);
@@ -227,12 +240,12 @@ status_t CameraService::Client::setPreviewDisplay(const sp<ISurface>& surface)
return NO_ERROR;
}
-// tell the service whether to callback with each preview frame
-void CameraService::Client::setHasFrameCallback(bool installed)
+// set the frame callback flag to affect how the received frames from
+// preview are handled.
+void CameraService::Client::setFrameCallbackFlag(int frame_callback_flag)
{
Mutex::Autolock lock(mLock);
- mHasFrameCallback = installed;
- // If installed is false, mPreviewBuffer will be released in stopPreview().
+ mFrameCallbackFlag = frame_callback_flag;
}
// start preview mode, must call setPreviewDisplay first
@@ -250,24 +263,24 @@ status_t CameraService::Client::startPreview()
LOGE("mHardware is NULL, returning.");
return INVALID_OPERATION;
}
-
+
if (mSurface == 0) {
LOGE("setPreviewDisplay must be called before startPreview!");
return INVALID_OPERATION;
}
-
+
// XXX: This needs to be improved. remove all hardcoded stuff
-
+
int w, h;
CameraParameters params(mHardware->getParameters());
params.getPreviewSize(&w, &h);
-
+
mSurface->unregisterBuffers();
#if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
debug_frame_cnt = 0;
#endif
-
+
status_t ret = mHardware->startPreview(previewCallback,
mCameraService.get());
if (ret == NO_ERROR) {
@@ -277,7 +290,7 @@ status_t CameraService::Client::startPreview()
}
else LOGE("mHardware->startPreview() failed with status %d\n",
ret);
-
+
return ret;
}
@@ -295,7 +308,7 @@ void CameraService::Client::stopPreview()
mHardware->stopPreview();
LOGD("stopPreview(), hardware stopped OK");
-
+
if (mSurface != 0) {
mSurface->unregisterBuffers();
}
@@ -361,6 +374,7 @@ static void dump_to_file(const char *fname,
// preview callback - frame buffer update
void CameraService::Client::previewCallback(const sp<IMemory>& mem, void* user)
{
+ LOGV("previewCallback()");
sp<Client> client = getClientFromCookie(user);
if (client == 0) {
return;
@@ -395,7 +409,7 @@ void CameraService::Client::previewCallback(const sp<IMemory>& mem, void* user)
client->postFrame(mem);
#if DEBUG_CLIENT_REFERENCES
- //**** if the client's refcount is 1, then we are about to destroy it here,
+ //**** if the client's refcount is 1, then we are about to destroy it here,
// which is bad--print all refcounts.
if (client->getStrongCount() == 1) {
LOGE("++++++++++++++++ (PREVIEW) THIS WILL CAUSE A LOCKUP!");
@@ -431,7 +445,7 @@ status_t CameraService::Client::takePicture()
LOGE("mHardware is NULL, returning.");
return INVALID_OPERATION;
}
-
+
if (mSurface != NULL)
mSurface->unregisterBuffers();
@@ -495,7 +509,7 @@ void CameraService::Client::yuvPictureCallback(const sp<IMemory>& mem,
client->postRaw(mem);
#if DEBUG_CLIENT_REFERENCES
- //**** if the client's refcount is 1, then we are about to destroy it here,
+ //**** if the client's refcount is 1, then we are about to destroy it here,
// which is bad--print all refcounts.
if (client->getStrongCount() == 1) {
LOGE("++++++++++++++++ (RAW) THIS WILL CAUSE A LOCKUP!");
@@ -532,7 +546,7 @@ void CameraService::Client::jpegPictureCallback(const sp<IMemory>& mem, void *us
client->postJpeg(mem);
#if DEBUG_CLIENT_REFERENCES
- //**** if the client's refcount is 1, then we are about to destroy it here,
+ //**** if the client's refcount is 1, then we are about to destroy it here,
// which is bad--print all refcounts.
if (client->getStrongCount() == 1) {
LOGE("++++++++++++++++ (JPEG) THIS WILL CAUSE A LOCKUP!");
@@ -615,37 +629,74 @@ void CameraService::Client::postJpeg(const sp<IMemory>& mem)
mCameraClient->jpegCallback(mem);
}
+void CameraService::Client::copyFrameAndPostCopiedFrame(sp<IMemoryHeap> heap, size_t offset, size_t size)
+{
+ LOGV("copyFrameAndPostCopiedFrame");
+ // It is necessary to copy out of pmem before sending this to
+ // the callback. For efficiency, reuse the same MemoryHeapBase
+ // provided it's big enough. Don't allocate the memory or
+ // perform the copy if there's no callback.
+ if (mPreviewBuffer == 0) {
+ mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
+ } else if (size > mPreviewBuffer->virtualSize()) {
+ mPreviewBuffer.clear();
+ mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
+ if (mPreviewBuffer == 0) {
+ LOGE("failed to allocate space for preview buffer");
+ return;
+ }
+ }
+ memcpy(mPreviewBuffer->base(),
+ (uint8_t *)heap->base() + offset, size);
+
+ sp<MemoryBase> frame = new MemoryBase(mPreviewBuffer, 0, size);
+ if (frame == 0) {
+ LOGE("failed to allocate space for frame callback");
+ return;
+ }
+ mCameraClient->frameCallback(frame);
+}
+
void CameraService::Client::postFrame(const sp<IMemory>& mem)
{
+ LOGV("postFrame");
+ if (mem == 0) {
+ LOGW("mem is a null pointer");
+ return;
+ }
+
ssize_t offset;
size_t size;
sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
-
- sp<MemoryBase> frame;
-
{
Mutex::Autolock surfaceLock(mSurfaceLock);
- if (mSurface != NULL)
+ if (mSurface != NULL) {
mSurface->postBuffer(offset);
- }
-
- // It is necessary to copy out of pmem before sending this to the callback.
- // For efficiency, reuse the same MemoryHeapBase provided it's big enough.
- // Don't allocate the memory or perform the copy if there's no callback.
- if (mHasFrameCallback) {
- if (mPreviewBuffer == 0) {
- mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
- } else if (size > mPreviewBuffer->virtualSize()) {
- mPreviewBuffer.clear();
- mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
}
- memcpy(mPreviewBuffer->base(), (uint8_t *)heap->base() + offset, size);
- frame = new MemoryBase(mPreviewBuffer, 0, size);
}
-
- // Do not hold the client lock while calling back.
- if (frame != 0) {
- mCameraClient->frameCallback(frame);
+
+ // Is the callback enabled or not?
+ if (!(mFrameCallbackFlag & FRAME_CALLBACK_FLAG_ENABLE_MASK)) {
+ // If the enable bit is off, the copy-out and one-shot bits are ignored
+ LOGV("frame callback is diabled");
+ return;
+ }
+
+ // Is the received frame copied out or not?
+ if (mFrameCallbackFlag & FRAME_CALLBACK_FLAG_COPY_OUT_MASK) {
+ LOGV("frame is copied out");
+ copyFrameAndPostCopiedFrame(heap, offset, size);
+ } else {
+ LOGV("frame is directly sent out without copying");
+ mCameraClient->frameCallback(mem);
+ }
+
+ // Is this is one-shot only?
+ if (mFrameCallbackFlag & FRAME_CALLBACK_FLAG_ONE_SHOT_MASK) {
+ LOGV("One-shot only, thus clear the bits and disable frame callback");
+ mFrameCallbackFlag &= ~(FRAME_CALLBACK_FLAG_ONE_SHOT_MASK |
+ FRAME_CALLBACK_FLAG_COPY_OUT_MASK |
+ FRAME_CALLBACK_FLAG_ENABLE_MASK);
}
}
@@ -711,7 +762,7 @@ status_t CameraService::onTransact(
}
status_t err = BnCameraService::onTransact(code, data, reply, flags);
-
+
LOGD("+++ onTransact err %d code %d", err, code);
if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {
diff --git a/camera/libcameraservice/CameraService.h b/camera/libcameraservice/CameraService.h
index 683c51b9f..b225aa9f3 100644
--- a/camera/libcameraservice/CameraService.h
+++ b/camera/libcameraservice/CameraService.h
@@ -1,6 +1,7 @@
/*
**
-** Copyright 2008, The Android Open Source Project
+** Copyright (C) 2008, The Android Open Source Project
+** Copyright (C) 2008 HTC Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
@@ -20,6 +21,8 @@
#include <ui/ICameraService.h>
#include <ui/CameraHardwareInterface.h>
+#include <ui/Camera.h>
+
class android::MemoryHeapBase;
namespace android {
@@ -32,7 +35,7 @@ namespace android {
// When enabled, this feature allows you to send an event to the CameraService
// so that you can cause all references to the heap object gWeakHeap, defined
// below, to be printed. You will also need to set DEBUG_REFS=1 and
-// DEBUG_REFS_ENABLED_BY_DEFAULT=0 in libutils/RefBase.cpp. You just have to
+// DEBUG_REFS_ENABLED_BY_DEFAULT=0 in libutils/RefBase.cpp. You just have to
// set gWeakHeap to the appropriate heap you want to track.
#define DEBUG_HEAP_LEAKS 0
@@ -67,11 +70,15 @@ private:
public:
virtual void disconnect();
+ // connect new client with existing camera remote
+ virtual status_t connect(const sp<ICameraClient>& client);
+
// pass the buffered ISurface to the camera service
virtual status_t setPreviewDisplay(const sp<ISurface>& surface);
-
- // tell the service whether to callback with each preview frame
- virtual void setHasFrameCallback(bool installed);
+
+ // set the frame callback flag to affect how the received frames from
+ // preview are handled.
+ virtual void setFrameCallbackFlag(int frame_callback_flag);
// start preview mode, must call setPreviewDisplay first
virtual status_t startPreview();
@@ -112,6 +119,7 @@ private:
void postRaw(const sp<IMemory>& mem);
void postJpeg(const sp<IMemory>& mem);
void postFrame(const sp<IMemory>& mem);
+ void copyFrameAndPostCopiedFrame(sp<IMemoryHeap> heap, size_t offset, size_t size);
void postError(status_t error);
void postAutoFocus(bool focused);
@@ -119,20 +127,20 @@ private:
mutable Mutex mLock;
// mSurfaceLock synchronizes access to mSurface between
// setPreviewSurface() and postFrame(). Note that among
- // the public methods, all accesses to mSurface are
+ // the public methods, all accesses to mSurface are
// syncrhonized by mLock. However, postFrame() is called
- // by the CameraHardwareInterface callback, and needs to
+ // by the CameraHardwareInterface callback, and needs to
// access mSurface. It cannot hold mLock, however, because
// stopPreview() may be holding that lock while attempting
// top stop preview, and stopPreview itself will block waiting
- // for a callback from CameraHardwareInterface. If this
+ // for a callback from CameraHardwareInterface. If this
// happens, it will cause a deadlock.
mutable Mutex mSurfaceLock;
mutable Condition mReady;
sp<CameraService> mCameraService;
sp<ISurface> mSurface;
sp<MemoryHeapBase> mPreviewBuffer;
- bool mHasFrameCallback;
+ int mFrameCallbackFlag;
// these are immutable once the object is created,
// they don't need to be protected by a lock