diff options
author | Benny Wong <Benny.Wong@motorola.com> | 2009-08-12 12:01:27 -0500 |
---|---|---|
committer | James Dong <jdong@google.com> | 2009-08-13 10:46:28 -0700 |
commit | da83f4674a564007baac03db062a289c8158d940 (patch) | |
tree | c1476d13a17ddff1bbd3769d3406ab3d639318d2 | |
parent | ddb79c9fd53893aa126599330a9289497e5f5c93 (diff) | |
download | frameworks_base-da83f4674a564007baac03db062a289c8158d940.zip frameworks_base-da83f4674a564007baac03db062a289c8158d940.tar.gz frameworks_base-da83f4674a564007baac03db062a289c8158d940.tar.bz2 |
Modified the camera HAL interface to use the same generic callback architecture as camera services
-rw-r--r-- | camera/libcameraservice/CameraHardwareStub.cpp | 100 | ||||
-rw-r--r-- | camera/libcameraservice/CameraHardwareStub.h | 39 | ||||
-rw-r--r-- | camera/libcameraservice/CameraService.cpp | 420 | ||||
-rw-r--r-- | camera/libcameraservice/CameraService.h | 24 | ||||
-rw-r--r-- | core/java/android/hardware/Camera.java | 19 | ||||
-rw-r--r-- | include/ui/Camera.h | 19 | ||||
-rw-r--r-- | include/ui/CameraHardwareInterface.h | 137 |
7 files changed, 384 insertions, 374 deletions
diff --git a/camera/libcameraservice/CameraHardwareStub.cpp b/camera/libcameraservice/CameraHardwareStub.cpp index a7af57c..24496bb 100644 --- a/camera/libcameraservice/CameraHardwareStub.cpp +++ b/camera/libcameraservice/CameraHardwareStub.cpp @@ -33,13 +33,11 @@ CameraHardwareStub::CameraHardwareStub() mRawHeap(0), mFakeCamera(0), mPreviewFrameSize(0), - mRawPictureCallback(0), - mJpegPictureCallback(0), - mPictureCallbackCookie(0), - mPreviewCallback(0), - mPreviewCallbackCookie(0), - mAutoFocusCallback(0), - mAutoFocusCallbackCookie(0), + mNotifyCb(0), + mDataCb(0), + mDataCbTimestamp(0), + mCallbackCookie(0), + mMsgEnabled(0), mCurrentPreviewFrame(0) { initDefaultParameters(); @@ -112,6 +110,36 @@ sp<IMemoryHeap> CameraHardwareStub::getRawHeap() const return mRawHeap; } +void CameraHardwareStub::setCallbacks(notify_callback notify_cb, + data_callback data_cb, + data_callback_timestamp data_cb_timestamp, + void* user) +{ + Mutex::Autolock lock(mLock); + mNotifyCb = notify_cb; + mDataCb = data_cb; + mDataCbTimestamp = data_cb_timestamp; + mCallbackCookie = user; +} + +void CameraHardwareStub::enableMsgType(int32_t msgType) +{ + Mutex::Autolock lock(mLock); + mMsgEnabled |= msgType; +} + +void CameraHardwareStub::disableMsgType(int32_t msgType) +{ + Mutex::Autolock lock(mLock); + mMsgEnabled &= ~msgType; +} + +bool CameraHardwareStub::msgTypeEnabled(int32_t msgType) +{ + Mutex::Autolock lock(mLock); + return (mMsgEnabled & msgType); +} + // --------------------------------------------------------------------------- int CameraHardwareStub::previewThread() @@ -150,7 +178,8 @@ int CameraHardwareStub::previewThread() //LOGV("previewThread: generated frame to buffer %d", mCurrentPreviewFrame); // Notify the client of a new frame. - mPreviewCallback(buffer, mPreviewCallbackCookie); + if (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME) + mDataCb(CAMERA_MSG_PREVIEW_FRAME, buffer, mCallbackCookie); // Advance the buffer pointer. mCurrentPreviewFrame = (mCurrentPreviewFrame + 1) % kBufferCount; @@ -162,15 +191,13 @@ int CameraHardwareStub::previewThread() return NO_ERROR; } -status_t CameraHardwareStub::startPreview(preview_callback cb, void* user) +status_t CameraHardwareStub::startPreview() { Mutex::Autolock lock(mLock); if (mPreviewThread != 0) { // already running return INVALID_OPERATION; } - mPreviewCallback = cb; - mPreviewCallbackCookie = user; mPreviewThread = new PreviewThread(this); return NO_ERROR; } @@ -197,7 +224,7 @@ bool CameraHardwareStub::previewEnabled() { return mPreviewThread != 0; } -status_t CameraHardwareStub::startRecording(recording_callback cb, void* user) +status_t CameraHardwareStub::startRecording() { return UNKNOWN_ERROR; } @@ -225,25 +252,14 @@ int CameraHardwareStub::beginAutoFocusThread(void *cookie) int CameraHardwareStub::autoFocusThread() { - if (mAutoFocusCallback != NULL) { - mAutoFocusCallback(true, mAutoFocusCallbackCookie); - mAutoFocusCallback = NULL; - return NO_ERROR; - } - return UNKNOWN_ERROR; + if (mMsgEnabled & CAMERA_MSG_FOCUS) + mNotifyCb(CAMERA_MSG_FOCUS, true, 0, mCallbackCookie); + return NO_ERROR; } -status_t CameraHardwareStub::autoFocus(autofocus_callback af_cb, - void *user) +status_t CameraHardwareStub::autoFocus() { Mutex::Autolock lock(mLock); - - if (mAutoFocusCallback != NULL) { - return mAutoFocusCallback == af_cb ? NO_ERROR : INVALID_OPERATION; - } - - mAutoFocusCallback = af_cb; - mAutoFocusCallbackCookie = user; if (createThread(beginAutoFocusThread, this) == false) return UNKNOWN_ERROR; return NO_ERROR; @@ -257,10 +273,10 @@ status_t CameraHardwareStub::autoFocus(autofocus_callback af_cb, int CameraHardwareStub::pictureThread() { - if (mShutterCallback) - mShutterCallback(mPictureCallbackCookie); + if (mMsgEnabled & CAMERA_MSG_SHUTTER) + mNotifyCb(CAMERA_MSG_SHUTTER, 0, 0, mCallbackCookie); - if (mRawPictureCallback) { + if (mMsgEnabled & CAMERA_MSG_RAW_IMAGE) { //FIXME: use a canned YUV image! // In the meantime just make another fake camera picture. int w, h; @@ -268,42 +284,28 @@ int CameraHardwareStub::pictureThread() sp<MemoryBase> mem = new MemoryBase(mRawHeap, 0, w * 2 * h); FakeCamera cam(w, h); cam.getNextFrameAsYuv422((uint8_t *)mRawHeap->base()); - if (mRawPictureCallback) - mRawPictureCallback(mem, mPictureCallbackCookie); + mDataCb(CAMERA_MSG_RAW_IMAGE, mem, mCallbackCookie); } - if (mJpegPictureCallback) { + if (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE) { sp<MemoryHeapBase> heap = new MemoryHeapBase(kCannedJpegSize); sp<MemoryBase> mem = new MemoryBase(heap, 0, kCannedJpegSize); memcpy(heap->base(), kCannedJpeg, kCannedJpegSize); - if (mJpegPictureCallback) - mJpegPictureCallback(mem, mPictureCallbackCookie); + mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, mem, mCallbackCookie); } return NO_ERROR; } -status_t CameraHardwareStub::takePicture(shutter_callback shutter_cb, - raw_callback raw_cb, - jpeg_callback jpeg_cb, - void* user) +status_t CameraHardwareStub::takePicture() { stopPreview(); - mShutterCallback = shutter_cb; - mRawPictureCallback = raw_cb; - mJpegPictureCallback = jpeg_cb; - mPictureCallbackCookie = user; if (createThread(beginPictureThread, this) == false) return -1; return NO_ERROR; } -status_t CameraHardwareStub::cancelPicture(bool cancel_shutter, - bool cancel_raw, - bool cancel_jpeg) +status_t CameraHardwareStub::cancelPicture() { - if (cancel_shutter) mShutterCallback = NULL; - if (cancel_raw) mRawPictureCallback = NULL; - if (cancel_jpeg) mJpegPictureCallback = NULL; return NO_ERROR; } diff --git a/camera/libcameraservice/CameraHardwareStub.h b/camera/libcameraservice/CameraHardwareStub.h index dd3c706..000906a 100644 --- a/camera/libcameraservice/CameraHardwareStub.h +++ b/camera/libcameraservice/CameraHardwareStub.h @@ -32,23 +32,27 @@ public: virtual sp<IMemoryHeap> getPreviewHeap() const; virtual sp<IMemoryHeap> getRawHeap() const; - virtual status_t startPreview(preview_callback cb, void* user); + virtual void setCallbacks(notify_callback notify_cb, + data_callback data_cb, + data_callback_timestamp data_cb_timestamp, + void* user); + + virtual void enableMsgType(int32_t msgType); + virtual void disableMsgType(int32_t msgType); + virtual bool msgTypeEnabled(int32_t msgType); + + virtual status_t startPreview(); virtual void stopPreview(); virtual bool previewEnabled(); - virtual status_t startRecording(recording_callback cb, void* user); + virtual status_t startRecording(); virtual void stopRecording(); virtual bool recordingEnabled(); virtual void releaseRecordingFrame(const sp<IMemory>& mem); - virtual status_t autoFocus(autofocus_callback, void *user); - virtual status_t takePicture(shutter_callback, - raw_callback, - jpeg_callback, - void* user); - virtual status_t cancelPicture(bool cancel_shutter, - bool cancel_raw, - bool cancel_jpeg); + virtual status_t autoFocus(); + virtual status_t takePicture(); + virtual status_t cancelPicture(); virtual status_t dump(int fd, const Vector<String16>& args) const; virtual status_t setParameters(const CameraParameters& params); virtual CameraParameters getParameters() const; @@ -109,18 +113,15 @@ private: bool mPreviewRunning; int mPreviewFrameSize; - shutter_callback mShutterCallback; - raw_callback mRawPictureCallback; - jpeg_callback mJpegPictureCallback; - void *mPictureCallbackCookie; - // protected by mLock sp<PreviewThread> mPreviewThread; - preview_callback mPreviewCallback; - void *mPreviewCallbackCookie; - autofocus_callback mAutoFocusCallback; - void *mAutoFocusCallbackCookie; + notify_callback mNotifyCb; + data_callback mDataCb; + data_callback_timestamp mDataCbTimestamp; + void *mCallbackCookie; + + int32_t mMsgEnabled; // only used from PreviewThread int mCurrentPreviewFrame; diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp index e7c1fbb..e66b00f 100644 --- a/camera/libcameraservice/CameraService.cpp +++ b/camera/libcameraservice/CameraService.cpp @@ -59,6 +59,7 @@ extern "C" { #define DEBUG_DUMP_PREVIEW_FRAME_TO_FILE 0 /* n-th frame to write */ #define DEBUG_DUMP_JPEG_SNAPSHOT_TO_FILE 0 #define DEBUG_DUMP_YUV_SNAPSHOT_TO_FILE 0 +#define DEBUG_DUMP_POSTVIEW_SNAPSHOT_TO_FILE 0 #if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE static int debug_frame_cnt; @@ -218,6 +219,16 @@ CameraService::Client::Client(const sp<CameraService>& cameraService, mHardware = openCameraHardware(); mUseOverlay = mHardware->useOverlay(); + mHardware->setCallbacks(notifyCallback, + dataCallback, + dataCallbackTimestamp, + mCameraService.get()); + + // Enable zoom, error, and focus messages by default + mHardware->enableMsgType(CAMERA_MSG_ERROR | + CAMERA_MSG_ZOOM | + CAMERA_MSG_FOCUS); + mMediaPlayerClick = newMediaPlayer("/system/media/audio/ui/camera_click.ogg"); mMediaPlayerBeep = newMediaPlayer("/system/media/audio/ui/VideoRecord.ogg"); mOverlayW = 0; @@ -391,7 +402,13 @@ void CameraService::Client::disconnect() // idle state. mHardware->stopPreview(); // Cancel all picture callbacks. - mHardware->cancelPicture(true, true, true); + mHardware->disableMsgType(CAMERA_MSG_SHUTTER | + CAMERA_MSG_POSTVIEW_FRAME | + CAMERA_MSG_RAW_IMAGE | + CAMERA_MSG_COMPRESSED_IMAGE); + mHardware->cancelPicture(); + // Turn off remaining messages. + mHardware->disableMsgType(CAMERA_MSG_ALL_MSGS); // Release the hardware resources. mHardware->release(); // Release the held overlay resources. @@ -456,6 +473,13 @@ void CameraService::Client::setPreviewCallbackFlag(int callback_flag) Mutex::Autolock lock(mLock); if (checkPid() != NO_ERROR) return; mPreviewCallbackFlag = callback_flag; + + if(mUseOverlay) { + if(mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ENABLE_MASK) + mHardware->enableMsgType(CAMERA_MSG_PREVIEW_FRAME); + else + mHardware->disableMsgType(CAMERA_MSG_PREVIEW_FRAME); + } } // start preview mode @@ -514,7 +538,7 @@ status_t CameraService::Client::startRecordingMode() } // start recording mode - ret = mHardware->startRecording(recordingCallback, mCameraService.get()); + ret = mHardware->startRecording(); if (ret != NO_ERROR) { LOGE("mHardware->startRecording() failed with status %d", ret); } @@ -617,10 +641,10 @@ status_t CameraService::Client::startPreviewMode() ret = setOverlay(); } if (ret != NO_ERROR) return ret; - ret = mHardware->startPreview(NULL, mCameraService.get()); + ret = mHardware->startPreview(); } else { - ret = mHardware->startPreview(previewCallback, - mCameraService.get()); + mHardware->enableMsgType(CAMERA_MSG_PREVIEW_FRAME); + ret = mHardware->startPreview(); if (ret != NO_ERROR) return ret; // If preview display has been set, register preview buffers now. if (mSurface != 0) { @@ -647,6 +671,9 @@ status_t CameraService::Client::startRecording() mMediaPlayerBeep->seekTo(0); mMediaPlayerBeep->start(); } + + mHardware->enableMsgType(CAMERA_MSG_VIDEO_FRAME); + return startCameraMode(CAMERA_RECORDING_MODE); } @@ -664,6 +691,7 @@ void CameraService::Client::stopPreview() } mHardware->stopPreview(); + mHardware->disableMsgType(CAMERA_MSG_PREVIEW_FRAME); LOGD("stopPreview(), hardware stopped OK"); if (mSurface != 0 && !mUseOverlay) { @@ -689,8 +717,11 @@ void CameraService::Client::stopRecording() mMediaPlayerBeep->seekTo(0); mMediaPlayerBeep->start(); } + mHardware->stopRecording(); + mHardware->disableMsgType(CAMERA_MSG_VIDEO_FRAME); LOGD("stopRecording(), hardware stopped OK"); + mPreviewBuffer.clear(); } @@ -778,65 +809,6 @@ static void dump_to_file(const char *fname, } #endif -// 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; - } - -#if DEBUG_HEAP_LEAKS && 0 // debugging - if (gWeakHeap == NULL) { - ssize_t offset; - size_t size; - sp<IMemoryHeap> heap = mem->getMemory(&offset, &size); - if (gWeakHeap != heap) { - LOGD("SETTING PREVIEW HEAP"); - heap->trackMe(true, true); - gWeakHeap = heap; - } - } -#endif - -#if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE - { - if (debug_frame_cnt++ == DEBUG_DUMP_PREVIEW_FRAME_TO_FILE) { - ssize_t offset; - size_t size; - sp<IMemoryHeap> heap = mem->getMemory(&offset, &size); - dump_to_file("/data/preview.yuv", - (uint8_t *)heap->base() + offset, size); - } - } -#endif - - // The strong pointer guarantees the client will exist, but no lock is held. - client->postPreviewFrame(mem); - -#if DEBUG_CLIENT_REFERENCES - //**** 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!"); - client->printRefs(); - } -#endif -} - -// recording callback -void CameraService::Client::recordingCallback(nsecs_t timestamp, const sp<IMemory>& mem, void* user) -{ - LOGV("recordingCallback"); - sp<Client> client = getClientFromCookie(user); - if (client == 0) { - return; - } - // The strong pointer guarantees the client will exist, but no lock is held. - client->postRecordingFrame(timestamp, mem); -} - // take a picture - image is returned in callback status_t CameraService::Client::autoFocus() { @@ -851,8 +823,7 @@ status_t CameraService::Client::autoFocus() return INVALID_OPERATION; } - return mHardware->autoFocus(autoFocusCallback, - mCameraService.get()); + return mHardware->autoFocus(); } // take a picture - image is returned in callback @@ -869,38 +840,36 @@ status_t CameraService::Client::takePicture() return INVALID_OPERATION; } - return mHardware->takePicture(shutterCallback, - yuvPictureCallback, - jpegPictureCallback, - mCameraService.get()); + mHardware->enableMsgType(CAMERA_MSG_SHUTTER | + CAMERA_MSG_POSTVIEW_FRAME | + CAMERA_MSG_RAW_IMAGE | + CAMERA_MSG_COMPRESSED_IMAGE); + + return mHardware->takePicture(); } -// picture callback - snapshot taken -void CameraService::Client::shutterCallback(void *user) +// snapshot taken +void CameraService::Client::handleShutter() { - sp<Client> client = getClientFromCookie(user); - if (client == 0) { - return; - } - // Play shutter sound. - if (client->mMediaPlayerClick.get() != NULL) { - client->mMediaPlayerClick->seekTo(0); - client->mMediaPlayerClick->start(); + if (mMediaPlayerClick.get() != NULL) { + mMediaPlayerClick->seekTo(0); + mMediaPlayerClick->start(); } // Screen goes black after the buffer is unregistered. - if (client->mSurface != 0 && !client->mUseOverlay) { - client->mSurface->unregisterBuffers(); + if (mSurface != 0 && !mUseOverlay) { + mSurface->unregisterBuffers(); } - client->postShutter(); + mCameraClient->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0); + mHardware->disableMsgType(CAMERA_MSG_SHUTTER); // It takes some time before yuvPicture callback to be called. // Register the buffer for raw image here to reduce latency. - if (client->mSurface != 0 && !client->mUseOverlay) { + if (mSurface != 0 && !mUseOverlay) { int w, h; - CameraParameters params(client->mHardware->getParameters()); + CameraParameters params(mHardware->getParameters()); params.getPictureSize(&w, &h); uint32_t transform = 0; if (params.getOrientation() == CameraParameters::CAMERA_ORIENTATION_PORTRAIT) { @@ -908,26 +877,92 @@ void CameraService::Client::shutterCallback(void *user) transform = ISurface::BufferHeap::ROT_90; } ISurface::BufferHeap buffers(w, h, w, h, - PIXEL_FORMAT_YCbCr_420_SP, transform, 0, client->mHardware->getRawHeap()); + PIXEL_FORMAT_YCbCr_420_SP, transform, 0, mHardware->getRawHeap()); - client->mSurface->registerBuffers(buffers); + mSurface->registerBuffers(buffers); } } -// picture callback - raw image ready -void CameraService::Client::yuvPictureCallback(const sp<IMemory>& mem, - void *user) +// preview callback - frame buffer update +void CameraService::Client::handlePreviewData(const sp<IMemory>& mem) { - sp<Client> client = getClientFromCookie(user); - if (client == 0) { - return; + ssize_t offset; + size_t size; + sp<IMemoryHeap> heap = mem->getMemory(&offset, &size); + +#if DEBUG_HEAP_LEAKS && 0 // debugging + if (gWeakHeap == NULL) { + if (gWeakHeap != heap) { + LOGD("SETTING PREVIEW HEAP"); + heap->trackMe(true, true); + gWeakHeap = heap; + } } - if (mem == NULL) { - client->postRaw(NULL); - client->postError(UNKNOWN_ERROR); +#endif +#if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE + { + if (debug_frame_cnt++ == DEBUG_DUMP_PREVIEW_FRAME_TO_FILE) { + dump_to_file("/data/preview.yuv", + (uint8_t *)heap->base() + offset, size); + } + } +#endif + + if (!mUseOverlay) + { + Mutex::Autolock surfaceLock(mSurfaceLock); + if (mSurface != NULL) { + mSurface->postBuffer(offset); + } + } + + // Is the callback enabled or not? + if (!(mPreviewCallbackFlag & 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 (mPreviewCallbackFlag & 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->dataCallback(CAMERA_MSG_PREVIEW_FRAME, mem); + } + + // Is this is one-shot only? + if (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ONE_SHOT_MASK) { + LOGV("One-shot only, thus clear the bits and disable frame callback"); + mPreviewCallbackFlag &= ~(FRAME_CALLBACK_FLAG_ONE_SHOT_MASK | + FRAME_CALLBACK_FLAG_COPY_OUT_MASK | + FRAME_CALLBACK_FLAG_ENABLE_MASK); + if (mUseOverlay) + mHardware->disableMsgType(CAMERA_MSG_PREVIEW_FRAME); + } +} + +// picture callback - postview image ready +void CameraService::Client::handlePostview(const sp<IMemory>& mem) +{ +#if DEBUG_DUMP_POSTVIEW_SNAPSHOT_TO_FILE // for testing pursposes only + { + ssize_t offset; + size_t size; + sp<IMemoryHeap> heap = mem->getMemory(&offset, &size); + dump_to_file("/data/postview.yuv", + (uint8_t *)heap->base() + offset, size); + } +#endif + + mCameraClient->dataCallback(CAMERA_MSG_POSTVIEW_FRAME, mem); + mHardware->disableMsgType(CAMERA_MSG_POSTVIEW_FRAME); +} + +// picture callback - raw image ready +void CameraService::Client::handleRawPicture(const sp<IMemory>& mem) +{ ssize_t offset; size_t size; sp<IMemoryHeap> heap = mem->getMemory(&offset, &size); @@ -935,80 +970,128 @@ void CameraService::Client::yuvPictureCallback(const sp<IMemory>& mem, gWeakHeap = heap; // debugging #endif - //LOGV("yuvPictureCallback(%d, %d, %p)", offset, size, user); + //LOGV("handleRawPicture(%d, %d)", offset, size); #if DEBUG_DUMP_YUV_SNAPSHOT_TO_FILE // for testing pursposes only dump_to_file("/data/photo.yuv", (uint8_t *)heap->base() + offset, size); #endif // Put the YUV version of the snapshot in the preview display. - if (client->mSurface != 0 && !client->mUseOverlay) { - client->mSurface->postBuffer(offset); + if (mSurface != 0 && !mUseOverlay) { + mSurface->postBuffer(offset); } - client->postRaw(mem); + mCameraClient->dataCallback(CAMERA_MSG_RAW_IMAGE, mem); + mHardware->disableMsgType(CAMERA_MSG_RAW_IMAGE); +} + +// picture callback - compressed picture ready +void CameraService::Client::handleCompressedPicture(const sp<IMemory>& mem) +{ +#if DEBUG_DUMP_JPEG_SNAPSHOT_TO_FILE // for testing pursposes only + { + ssize_t offset; + size_t size; + sp<IMemoryHeap> heap = mem->getMemory(&offset, &size); + dump_to_file("/data/photo.jpg", + (uint8_t *)heap->base() + offset, size); + } +#endif + + mCameraClient->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem); + mHardware->disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE); +} + +void CameraService::Client::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2, void* user) +{ + LOGV("notifyCallback(%d)", msgType); + + sp<Client> client = getClientFromCookie(user); + if (client == 0) { + return; + } + + switch (msgType) { + case CAMERA_MSG_SHUTTER: + client->handleShutter(); + break; + default: + client->mCameraClient->notifyCallback(msgType, ext1, ext2); + break; + } #if DEBUG_CLIENT_REFERENCES - //**** 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!"); + LOGE("++++++++++++++++ (NOTIFY CALLBACK) THIS WILL CAUSE A LOCKUP!"); client->printRefs(); } #endif } -// picture callback - jpeg ready -void CameraService::Client::jpegPictureCallback(const sp<IMemory>& mem, void *user) +void CameraService::Client::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr, void* user) { + LOGV("dataCallback(%d)", msgType); + sp<Client> client = getClientFromCookie(user); if (client == 0) { return; } - if (mem == NULL) { - client->postJpeg(NULL); - client->postError(UNKNOWN_ERROR); + + if (dataPtr == NULL) { + LOGE("Null data returned in data callback"); + client->mCameraClient->notifyCallback(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0); + client->mCameraClient->dataCallback(msgType, NULL); return; } - /** We absolutely CANNOT call into user code with a lock held **/ - -#if DEBUG_DUMP_JPEG_SNAPSHOT_TO_FILE // for testing pursposes only - { - ssize_t offset; - size_t size; - sp<IMemoryHeap> heap = mem->getMemory(&offset, &size); - dump_to_file("/data/photo.jpg", - (uint8_t *)heap->base() + offset, size); + switch (msgType) { + case CAMERA_MSG_PREVIEW_FRAME: + client->handlePreviewData(dataPtr); + break; + case CAMERA_MSG_POSTVIEW_FRAME: + client->handlePostview(dataPtr); + break; + case CAMERA_MSG_RAW_IMAGE: + client->handleRawPicture(dataPtr); + break; + case CAMERA_MSG_COMPRESSED_IMAGE: + client->handleCompressedPicture(dataPtr); + break; + default: + client->mCameraClient->dataCallback(msgType, dataPtr); + break; } -#endif - - client->postJpeg(mem); #if DEBUG_CLIENT_REFERENCES - //**** 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!"); + LOGE("++++++++++++++++ (DATA CALLBACK) THIS WILL CAUSE A LOCKUP!"); client->printRefs(); } #endif } -void CameraService::Client::autoFocusCallback(bool focused, void *user) +void CameraService::Client::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, + const sp<IMemory>& dataPtr, void* user) { - LOGV("autoFocusCallback"); + LOGV("dataCallbackTimestamp(%d)", msgType); sp<Client> client = getClientFromCookie(user); if (client == 0) { return; } - client->postAutoFocus(focused); + if (dataPtr == NULL) { + LOGE("Null data returned in data with timestamp callback"); + client->mCameraClient->notifyCallback(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0); + client->mCameraClient->dataCallbackTimestamp(0, msgType, NULL); + return; + } + + client->mCameraClient->dataCallbackTimestamp(timestamp, msgType, dataPtr); #if DEBUG_CLIENT_REFERENCES if (client->getStrongCount() == 1) { - LOGE("++++++++++++++++ (AUTOFOCUS) THIS WILL CAUSE A LOCKUP!"); + LOGE("++++++++++++++++ (DATA CALLBACK TIMESTAMP) THIS WILL CAUSE A LOCKUP!"); client->printRefs(); } #endif @@ -1048,30 +1131,6 @@ String8 CameraService::Client::getParameters() const return params; } -void CameraService::Client::postAutoFocus(bool focused) -{ - LOGV("postAutoFocus"); - mCameraClient->notifyCallback(CAMERA_MSG_FOCUS, (int32_t)focused, 0); -} - -void CameraService::Client::postShutter() -{ - LOGD("postShutter"); - mCameraClient->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0); -} - -void CameraService::Client::postRaw(const sp<IMemory>& mem) -{ - LOGD("postRaw"); - mCameraClient->dataCallback(CAMERA_MSG_RAW_IMAGE, mem); -} - -void CameraService::Client::postJpeg(const sp<IMemory>& mem) -{ - LOGD("postJpeg"); - mCameraClient->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem); -} - void CameraService::Client::copyFrameAndPostCopiedFrame(sp<IMemoryHeap> heap, size_t offset, size_t size) { LOGV("copyFrameAndPostCopiedFrame"); @@ -1100,65 +1159,6 @@ void CameraService::Client::copyFrameAndPostCopiedFrame(sp<IMemoryHeap> heap, si mCameraClient->dataCallback(CAMERA_MSG_PREVIEW_FRAME, frame); } -void CameraService::Client::postRecordingFrame(nsecs_t timestamp, const sp<IMemory>& frame) -{ - LOGV("postRecordingFrame"); - if (frame == 0) { - LOGW("frame is a null pointer"); - return; - } - mCameraClient->dataCallbackTimestamp(timestamp, CAMERA_MSG_VIDEO_FRAME, frame); -} - -void CameraService::Client::postPreviewFrame(const sp<IMemory>& mem) -{ - LOGV("postPreviewFrame"); - if (mem == 0) { - LOGW("mem is a null pointer"); - return; - } - - ssize_t offset; - size_t size; - sp<IMemoryHeap> heap = mem->getMemory(&offset, &size); - if ( !mUseOverlay ) - { - Mutex::Autolock surfaceLock(mSurfaceLock); - if (mSurface != NULL) { - mSurface->postBuffer(offset); - } - } - - // Is the callback enabled or not? - if (!(mPreviewCallbackFlag & 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 (mPreviewCallbackFlag & 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->dataCallback(CAMERA_MSG_PREVIEW_FRAME, mem); - } - - // Is this is one-shot only? - if (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ONE_SHOT_MASK) { - LOGV("One-shot only, thus clear the bits and disable frame callback"); - mPreviewCallbackFlag &= ~(FRAME_CALLBACK_FLAG_ONE_SHOT_MASK | - FRAME_CALLBACK_FLAG_COPY_OUT_MASK | - FRAME_CALLBACK_FLAG_ENABLE_MASK); - } -} - -void CameraService::Client::postError(status_t error) -{ - mCameraClient->notifyCallback(CAMERA_MSG_ERROR, error, 0); -} - status_t CameraService::dump(int fd, const Vector<String16>& args) { const size_t SIZE = 256; diff --git a/camera/libcameraservice/CameraService.h b/camera/libcameraservice/CameraService.h index 8a49fa6..f8c7216 100644 --- a/camera/libcameraservice/CameraService.h +++ b/camera/libcameraservice/CameraService.h @@ -132,22 +132,20 @@ private: status_t checkPid(); - static void recordingCallback(nsecs_t timestamp, const sp<IMemory>& mem, void* user); - static void previewCallback(const sp<IMemory>& mem, void* user); - static void shutterCallback(void *user); - static void yuvPictureCallback(const sp<IMemory>& mem, void* user); - static void jpegPictureCallback(const sp<IMemory>& mem, void* user); - static void autoFocusCallback(bool focused, void* user); + static void notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2, void* user); + static void dataCallback(int32_t msgType, const sp<IMemory>& dataPtr, void* user); + static void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, + const sp<IMemory>& dataPtr, void* user); + static sp<Client> getClientFromCookie(void* user); - void postShutter(); - void postRaw(const sp<IMemory>& mem); - void postJpeg(const sp<IMemory>& mem); - void postPreviewFrame(const sp<IMemory>& mem); - void postRecordingFrame(nsecs_t timestamp, const sp<IMemory>& frame); + void handlePreviewData(const sp<IMemory>&); + void handleShutter(); + void handlePostview(const sp<IMemory>&); + void handleRawPicture(const sp<IMemory>&); + void handleCompressedPicture(const sp<IMemory>&); + void copyFrameAndPostCopiedFrame(sp<IMemoryHeap> heap, size_t offset, size_t size); - void postError(status_t error); - void postAutoFocus(bool focused); // camera operation mode enum camera_mode { diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java index 40d2c86..aa3b852 100644 --- a/core/java/android/hardware/Camera.java +++ b/core/java/android/hardware/Camera.java @@ -40,15 +40,16 @@ public class Camera { private static final String TAG = "Camera"; // These match the enums in frameworks/base/include/ui/Camera.h - private static final int CAMERA_MSG_ERROR = 0; - private static final int CAMERA_MSG_SHUTTER = 1; - private static final int CAMERA_MSG_FOCUS = 2; - private static final int CAMERA_MSG_ZOOM = 3; - private static final int CAMERA_MSG_PREVIEW_FRAME = 4; - private static final int CAMERA_MSG_VIDEO_FRAME = 5; - private static final int CAMERA_MSG_POSTVIEW_FRAME = 6; - private static final int CAMERA_MSG_RAW_IMAGE = 7; - private static final int CAMERA_MSG_COMPRESSED_IMAGE = 8; + private static final int CAMERA_MSG_ERROR = 0x001; + private static final int CAMERA_MSG_SHUTTER = 0x002; + private static final int CAMERA_MSG_FOCUS = 0x004; + private static final int CAMERA_MSG_ZOOM = 0x008; + private static final int CAMERA_MSG_PREVIEW_FRAME = 0x010; + private static final int CAMERA_MSG_VIDEO_FRAME = 0x020; + private static final int CAMERA_MSG_POSTVIEW_FRAME = 0x040; + private static final int CAMERA_MSG_RAW_IMAGE = 0x080; + private static final int CAMERA_MSG_COMPRESSED_IMAGE = 0x100; + private static final int CAMERA_MSG_ALL_MSGS = 0x1FF; private int mNativeContext; // accessed by native methods private EventHandler mEventHandler; diff --git a/include/ui/Camera.h b/include/ui/Camera.h index afb07b5..ae6e255 100644 --- a/include/ui/Camera.h +++ b/include/ui/Camera.h @@ -66,15 +66,16 @@ namespace android { // msgType in notifyCallback and dataCallback functions enum { - CAMERA_MSG_ERROR = 0, - CAMERA_MSG_SHUTTER, - CAMERA_MSG_FOCUS, - CAMERA_MSG_ZOOM, - CAMERA_MSG_PREVIEW_FRAME, - CAMERA_MSG_VIDEO_FRAME, - CAMERA_MSG_POSTVIEW_FRAME, - CAMERA_MSG_RAW_IMAGE, - CAMERA_MSG_COMPRESSED_IMAGE + CAMERA_MSG_ERROR = 0x001, + CAMERA_MSG_SHUTTER = 0x002, + CAMERA_MSG_FOCUS = 0x004, + CAMERA_MSG_ZOOM = 0x008, + CAMERA_MSG_PREVIEW_FRAME = 0x010, + CAMERA_MSG_VIDEO_FRAME = 0x020, + CAMERA_MSG_POSTVIEW_FRAME = 0x040, + CAMERA_MSG_RAW_IMAGE = 0x080, + CAMERA_MSG_COMPRESSED_IMAGE = 0x100, + CAMERA_MSG_ALL_MSGS = 0x1FF }; // camera fatal errors diff --git a/include/ui/CameraHardwareInterface.h b/include/ui/CameraHardwareInterface.h index c703f5e..535f70e 100644 --- a/include/ui/CameraHardwareInterface.h +++ b/include/ui/CameraHardwareInterface.h @@ -19,28 +19,26 @@ #include <binder/IMemory.h> #include <utils/RefBase.h> +#include <ui/ISurface.h> +#include <ui/Camera.h> #include <ui/CameraParameters.h> #include <ui/Overlay.h> namespace android { -/** Callback for startPreview() */ -typedef void (*preview_callback)(const sp<IMemory>& mem, void* user); +typedef void (*notify_callback)(int32_t msgType, + int32_t ext1, + int32_t ext2, + void* user); -/** Callback for startRecord() */ -typedef void (*recording_callback)(nsecs_t timestamp, const sp<IMemory>& mem, void* user); +typedef void (*data_callback)(int32_t msgType, + const sp<IMemory>& dataPtr, + void* user); -/** Callback for takePicture() */ -typedef void (*shutter_callback)(void* user); - -/** Callback for takePicture() */ -typedef void (*raw_callback)(const sp<IMemory>& mem, void* user); - -/** Callback for takePicture() */ -typedef void (*jpeg_callback)(const sp<IMemory>& mem, void* user); - -/** Callback for autoFocus() */ -typedef void (*autofocus_callback)(bool focused, void* user); +typedef void (*data_callback_timestamp)(nsecs_t timestamp, + int32_t msgType, + const sp<IMemory>& dataPtr, + void* user); /** * CameraHardwareInterface.h defines the interface to the @@ -57,28 +55,21 @@ typedef void (*autofocus_callback)(bool focused, void* user); * CameraService calls getPreviewHeap() to establish access to the * preview heap so it can be registered with SurfaceFlinger for * efficient display updating while in preview mode. - * -# startPreview() is called, which is passed a preview_callback() - * function and a user parameter. The camera instance then periodically - * calls preview_callback() each time a new preview frame is available. - * The callback routine has two parameters: the first is a pointer to - * the IMemory containing the frame and the second a user parameter. If - * the preview_callback code needs to use this memory after returning, - * it must copy the data. + * -# startPreview() is called. The camera instance then periodically + * sends the message CAMERA_MSG_PREVIEW_FRAME (if enabled) each time + * a new preview frame is available. If data callback code needs to use + * this memory after returning, it must copy the data. * - * Prior to taking a picture, CameraService calls autofocus() with - * autofocus_callback() and a user parameter. When auto focusing has - * completed, the camera instance calls autofocus_callback(), which informs - * the application whether focusing was successful. The camera instance - * only calls autofocus_callback() once and it is up to the application to - * call autoFocus() again if refocusing is desired. + * Prior to taking a picture, CameraService calls autofocus(). When auto + * focusing has completed, the camera instance sends a CAMERA_MSG_FOCUS notification, + * which informs the application whether focusing was successful. The camera instance + * only sends this message once and it is up to the application to call autoFocus() + * again if refocusing is desired. * * CameraService calls takePicture() to request the camera instance take a - * picture. This method has two callbacks: raw_callback() and jpeg_callback(). - * When the raw image is available, raw_callback() is called with a pointer - * to the IMemory containing the raw image. When the jpeg image is available, - * jpeg_callback() is called with a pointer to the IMemory containing the - * jpeg image. As with preview_callback(), the memory must be copied if it's - * needed after returning. + * picture. At this point, if a shutter, postview, raw, and/or compressed callback + * is desired, the corresponding message must be enabled. As with CAMERA_MSG_PREVIEW_FRAME, + * any memory provided in a data callback must be copied if it's needed after returning. */ class CameraHardwareInterface : public virtual RefBase { public: @@ -90,17 +81,45 @@ public: /** Return the IMemoryHeap for the raw image heap */ virtual sp<IMemoryHeap> getRawHeap() const = 0; + /** Set the notification and data callbacks */ + virtual void setCallbacks(notify_callback notify_cb, + data_callback data_cb, + data_callback_timestamp data_cb_timestamp, + void* user) = 0; + /** - * Start preview mode. When a preview image is available - * preview_callback is called with the user parameter. The - * call back parameter may be null. + * The following three functions all take a msgtype, + * which is a bitmask of the messages defined in + * include/ui/Camera.h */ - virtual status_t startPreview(preview_callback cb, void* user) = 0; + + /** + * Enable a message, or set of messages. + */ + virtual void enableMsgType(int32_t msgType) = 0; + + /** + * Disable a message, or a set of messages. + */ + virtual void disableMsgType(int32_t msgType) = 0; + + /** + * Query whether a message, or a set of messages, is enabled. + * Note that this is operates as an AND, if any of the messages + * queried are off, this will return false. + */ + virtual bool msgTypeEnabled(int32_t msgType) = 0; + + /** + * Start preview mode. + */ + virtual status_t startPreview() = 0; + /** * Only used if overlays are used for camera preview. */ - virtual bool useOverlay() {return false;} - virtual status_t setOverlay(const sp<Overlay> &overlay) {return BAD_VALUE;} + virtual bool useOverlay() {return false;} + virtual status_t setOverlay(const sp<Overlay> &overlay) {return BAD_VALUE;} /** * Stop a previously started preview. @@ -113,11 +132,11 @@ public: virtual bool previewEnabled() = 0; /** - * Start record mode. When a record image is available recording_callback() - * is called with the user parameter. Every record frame must be released + * Start record mode. When a record image is available a CAMERA_MSG_VIDEO_FRAME + * message is sent with the corresponding frame. Every record frame must be released * by calling releaseRecordingFrame(). */ - virtual status_t startRecording(recording_callback cb, void* user) = 0; + virtual status_t startRecording() = 0; /** * Stop a previously started recording. @@ -130,39 +149,27 @@ public: virtual bool recordingEnabled() = 0; /** - * Release a record frame previously returned by the recording_callback() - * passed to startRecord(). + * Release a record frame previously returned by CAMERA_MSG_VIDEO_FRAME. */ virtual void releaseRecordingFrame(const sp<IMemory>& mem) = 0; /** - * Start auto focus, the callback routine is called - * once when focusing is complete. autoFocus() will - * be called again if another auto focus is needed. + * Start auto focus, the notification callback routine is called + * with CAMERA_MSG_FOCUS once when focusing is complete. autoFocus() + * will be called again if another auto focus is needed. */ - virtual status_t autoFocus(autofocus_callback, - void* user) = 0; + virtual status_t autoFocus() = 0; /** - * Take a picture. The raw_callback is called when - * the uncompressed image is available. The jpeg_callback - * is called when the compressed image is available. These - * call backs may be null. The user parameter is passed - * to each of the call back routines. + * Take a picture. */ - virtual status_t takePicture(shutter_callback, - raw_callback, - jpeg_callback, - void* user) = 0; + virtual status_t takePicture() = 0; /** - * Cancel a picture that was started with takePicture. You may cancel any - * of the shutter, raw, or jpeg callbacks. Calling this method when no - * picture is being taken is a no-op. + * Cancel a picture that was started with takePicture. Calling this + * method when no picture is being taken is a no-op. */ - virtual status_t cancelPicture(bool cancel_shutter, - bool cancel_raw, - bool cancel_jpeg) = 0; + virtual status_t cancelPicture() = 0; /** Set the camera parameters. */ virtual status_t setParameters(const CameraParameters& params) = 0; |