diff options
Diffstat (limited to 'camera')
-rw-r--r-- | camera/libcameraservice/Android.mk | 11 | ||||
-rw-r--r-- | camera/libcameraservice/CameraService.cpp | 135 | ||||
-rw-r--r-- | camera/libcameraservice/CameraService.h | 26 |
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 |