diff options
Diffstat (limited to 'camera')
-rw-r--r-- | camera/libcameraservice/CameraService.cpp | 159 | ||||
-rw-r--r-- | camera/libcameraservice/CameraService.h | 4 |
2 files changed, 102 insertions, 61 deletions
diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp index 2f4a1c9..030d887 100644 --- a/camera/libcameraservice/CameraService.cpp +++ b/camera/libcameraservice/CameraService.cpp @@ -98,7 +98,7 @@ sp<ICamera> CameraService::connect(const sp<ICameraClient>& cameraClient) LOGD("CameraService::connect E (pid %d, client %p)", callingPid, cameraClient->asBinder().get()); - Mutex::Autolock lock(mLock); + Mutex::Autolock lock(mServiceLock); sp<Client> client; if (mClient != 0) { sp<Client> currentClient = mClient.promote(); @@ -125,13 +125,14 @@ sp<ICamera> CameraService::connect(const sp<ICameraClient>& cameraClient) LOGD("New client (pid %d) connecting, old reference was dangling...", callingPid); mClient.clear(); - if (mUsers > 0) { - LOGD("Still have client, rejected"); - return client; - } } } + if (mUsers > 0) { + LOGD("Still have client, rejected"); + return client; + } + // create a new Client object client = new Client(this, cameraClient, callingPid); mClient = client; @@ -152,7 +153,7 @@ void CameraService::removeClient(const sp<ICameraClient>& cameraClient) // destructor won't be called with the lock held. sp<Client> client; - Mutex::Autolock lock(mLock); + Mutex::Autolock lock(mServiceLock); if (mClient == 0) { // This happens when we have already disconnected. @@ -390,8 +391,6 @@ void CameraService::Client::disconnect() // from the user directly, or called by the destructor. if (mHardware == 0) return; - mCameraService->removeClient(mCameraClient); - LOGD("hardware teardown"); // Before destroying mHardware, we must make sure it's in the // idle state. @@ -402,6 +401,7 @@ void CameraService::Client::disconnect() mHardware->release(); mHardware.clear(); + mCameraService->removeClient(mCameraClient); mCameraService->decUsers(); LOGD("Client::disconnect() X (pid %d)", callingPid); @@ -410,11 +410,14 @@ void CameraService::Client::disconnect() // pass the buffered ISurface to the camera service status_t CameraService::Client::setPreviewDisplay(const sp<ISurface>& surface) { - LOGD("setPreviewDisplay(%p) (pid %d)", surface.get(), getCallingPid()); + LOGD("setPreviewDisplay(%p) (pid %d)", + ((surface == NULL) ? NULL : surface.get()), getCallingPid()); Mutex::Autolock lock(mLock); status_t result = checkPid(); if (result != NO_ERROR) return result; + Mutex::Autolock surfaceLock(mSurfaceLock); + result = NO_ERROR; // asBinder() is safe on NULL (returns NULL) if (surface->asBinder() != mSurface->asBinder()) { if (mSurface != 0 && !mUseOverlay) { @@ -422,8 +425,17 @@ status_t CameraService::Client::setPreviewDisplay(const sp<ISurface>& surface) mSurface->unregisterBuffers(); } mSurface = surface; + // If preview has been already started, set overlay or register preview + // buffers now. + if (mHardware->previewEnabled()) { + if (mUseOverlay) { + result = setOverlay(); + } else if (mSurface != 0) { + result = registerPreviewBuffers(); + } + } } - return NO_ERROR; + return result; } // set the preview callback flag to affect how the received frames from @@ -436,7 +448,7 @@ void CameraService::Client::setPreviewCallbackFlag(int callback_flag) mPreviewCallbackFlag = callback_flag; } -// start preview mode, must call setPreviewDisplay first +// start preview mode status_t CameraService::Client::startCameraMode(camera_mode mode) { int callingPid = getCallingPid(); @@ -456,16 +468,18 @@ status_t CameraService::Client::startCameraMode(camera_mode mode) return INVALID_OPERATION; } - if (mSurface == 0) { - LOGE("setPreviewDisplay must be called before startCameraMode!"); - return INVALID_OPERATION; - } - switch(mode) { case CAMERA_RECORDING_MODE: + if (mSurface == 0) { + LOGE("setPreviewDisplay must be called before startRecordingMode."); + return INVALID_OPERATION; + } return startRecordingMode(); default: // CAMERA_PREVIEW_MODE + if (mSurface == 0) { + LOGD("mSurface is not set yet."); + } return startPreviewMode(); } } @@ -498,6 +512,62 @@ status_t CameraService::Client::startRecordingMode() return ret; } +status_t CameraService::Client::setOverlay() +{ + LOGD("setOverlay"); + int w, h; + CameraParameters params(mHardware->getParameters()); + params.getPreviewSize(&w, &h); + + const char *format = params.getPreviewFormat(); + int fmt; + if (!strcmp(format, "yuv422i")) + fmt = OVERLAY_FORMAT_YCbCr_422_I; + else if (!strcmp(format, "rgb565")) + fmt = OVERLAY_FORMAT_RGB_565; + else { + LOGE("Invalid preview format for overlays"); + return -EINVAL; + } + + status_t ret = NO_ERROR; + if (mSurface != 0) { + sp<OverlayRef> ref = mSurface->createOverlay(w, h, fmt); + ret = mHardware->setOverlay(new Overlay(ref)); + } else { + ret = mHardware->setOverlay(NULL); + } + if (ret != NO_ERROR) { + LOGE("mHardware->setOverlay() failed with status %d\n", ret); + } + return ret; +} + +status_t CameraService::Client::registerPreviewBuffers() +{ + int w, h; + CameraParameters params(mHardware->getParameters()); + params.getPreviewSize(&w, &h); + + uint32_t transform = 0; + if (params.getOrientation() == + CameraParameters::CAMERA_ORIENTATION_PORTRAIT) { + LOGV("portrait mode"); + transform = ISurface::BufferHeap::ROT_90; + } + ISurface::BufferHeap buffers(w, h, w, h, + PIXEL_FORMAT_YCbCr_420_SP, + transform, + 0, + mHardware->getPreviewHeap()); + + status_t ret = mSurface->registerBuffers(buffers); + if (ret != NO_ERROR) { + LOGE("registerBuffers failed with status %d", ret); + } + return ret; +} + status_t CameraService::Client::startPreviewMode() { LOGD("startPreviewMode (pid %d)", getCallingPid()); @@ -511,55 +581,24 @@ status_t CameraService::Client::startPreviewMode() #if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE debug_frame_cnt = 0; #endif - status_t ret = UNKNOWN_ERROR; - int w, h; - CameraParameters params(mHardware->getParameters()); - params.getPreviewSize(&w, &h); + status_t ret = NO_ERROR; if (mUseOverlay) { - const char *format = params.getPreviewFormat(); - int fmt; - LOGD("Use Overlays"); - if (!strcmp(format, "yuv422i")) - fmt = OVERLAY_FORMAT_YCbCr_422_I; - else if (!strcmp(format, "rgb565")) - fmt = OVERLAY_FORMAT_RGB_565; - else { - LOGE("Invalid preview format for overlays"); - return -EINVAL; - } - sp<OverlayRef> ref = mSurface->createOverlay(w, h, fmt); - ret = mHardware->setOverlay(new Overlay(ref)); - if (ret != NO_ERROR) { - LOGE("mHardware->setOverlay() failed with status %d\n", ret); - return ret; + // If preview display has been set, set overlay now. + if (mSurface != 0) { + ret = setOverlay(); } + if (ret != NO_ERROR) return ret; ret = mHardware->startPreview(NULL, mCameraService.get()); - if (ret != NO_ERROR) - LOGE("mHardware->startPreview() failed with status %d\n", ret); - } else { ret = mHardware->startPreview(previewCallback, mCameraService.get()); - if (ret == NO_ERROR) { - - mSurface->unregisterBuffers(); - - uint32_t transform = 0; - if (params.getOrientation() == - CameraParameters::CAMERA_ORIENTATION_PORTRAIT) { - LOGV("portrait mode"); - transform = ISurface::BufferHeap::ROT_90; - } - ISurface::BufferHeap buffers(w, h, w, h, - PIXEL_FORMAT_YCbCr_420_SP, - transform, - 0, - mHardware->getPreviewHeap()); - - mSurface->registerBuffers(buffers); - } else { - LOGE("mHardware->startPreview() failed with status %d", ret); + if (ret != NO_ERROR) return ret; + // If preview display has been set, register preview buffers now. + if (mSurface != 0) { + // Unregister here because the surface registered with raw heap. + mSurface->unregisterBuffers(); + ret = registerPreviewBuffers(); } } return ret; @@ -661,7 +700,7 @@ sp<CameraService::Client> CameraService::Client::getClientFromCookie(void* user) sp<Client> client = 0; CameraService *service = static_cast<CameraService*>(user); if (service != NULL) { - Mutex::Autolock ourLock(service->mLock); + Mutex::Autolock ourLock(service->mServiceLock); if (service->mClient != 0) { client = service->mClient.promote(); if (client == 0) { @@ -1104,7 +1143,7 @@ status_t CameraService::dump(int fd, const Vector<String16>& args) result.append(buffer); write(fd, result.string(), result.size()); } else { - AutoMutex lock(&mLock); + AutoMutex lock(&mServiceLock); if (mClient != 0) { sp<Client> currentClient = mClient.promote(); sprintf(buffer, "Client (%p) PID: %d\n", diff --git a/camera/libcameraservice/CameraService.h b/camera/libcameraservice/CameraService.h index 729e539..0f07673 100644 --- a/camera/libcameraservice/CameraService.h +++ b/camera/libcameraservice/CameraService.h @@ -157,6 +157,8 @@ private: status_t startCameraMode(camera_mode mode); status_t startPreviewMode(); status_t startRecordingMode(); + status_t setOverlay(); + status_t registerPreviewBuffers(); // Ensures atomicity among the public methods mutable Mutex mLock; @@ -199,7 +201,7 @@ private: virtual void incUsers(); virtual void decUsers(); - mutable Mutex mLock; + mutable Mutex mServiceLock; wp<Client> mClient; #if DEBUG_HEAP_LEAKS |