From 0ed3ec00d0242c9dc77532fe0cf0082645b6662c Mon Sep 17 00:00:00 2001 From: Jamie Gennis Date: Wed, 13 Jul 2011 15:13:14 -0700 Subject: CameraService: (dis)connect from preview windows This change makes CameraService connect and disconnect from preview windows (Surfaces and SurfaceTextures) that get set. Change-Id: I726971688367d5ce0d9aa90c44168037bce33deb --- services/camera/libcameraservice/CameraService.cpp | 97 ++++++++++++---------- services/camera/libcameraservice/CameraService.h | 4 + 2 files changed, 55 insertions(+), 46 deletions(-) (limited to 'services') diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index 9b09983..0eff776 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -502,77 +502,82 @@ void CameraService::Client::disconnect() { // ---------------------------------------------------------------------------- -// set the Surface that the preview will use -status_t CameraService::Client::setPreviewDisplay(const sp& surface) { - LOG1("setPreviewDisplay(%p) (pid %d)", surface.get(), getCallingPid()); +static void disconnectWindow(const sp& window) { + if (window != 0) { + status_t result = native_window_disconnect(window.get(), + NATIVE_WINDOW_API_CAMERA); + if (result != NO_ERROR) { + LOGW("native_window_disconnect failed: %s (%d)", strerror(-result), + result); + } + } +} + +status_t CameraService::Client::setPreviewWindow(const sp& binder, + const sp& window) { Mutex::Autolock lock(mLock); status_t result = checkPidAndHardware(); if (result != NO_ERROR) return result; - result = NO_ERROR; - // return if no change in surface. - sp binder(surface != 0 ? surface->asBinder() : 0); if (binder == mSurface) { - return result; + return NO_ERROR; } - if (mSurface != 0) { - LOG1("clearing old preview surface %p", mSurface.get()); + if (window != 0) { + result = native_window_connect(window.get(), NATIVE_WINDOW_API_CAMERA); + if (result != NO_ERROR) { + LOGE("native_window_connect failed: %s (%d)", strerror(-result), + result); + return result; + } } - mSurface = binder; - mPreviewWindow = surface; - // If preview has been already started, register preview - // buffers now. + // If preview has been already started, register preview buffers now. if (mHardware->previewEnabled()) { - if (mPreviewWindow != 0) { - native_window_set_buffers_transform(mPreviewWindow.get(), - mOrientation); - result = mHardware->setPreviewWindow(mPreviewWindow); + if (window != 0) { + native_window_set_buffers_transform(window.get(), mOrientation); + result = mHardware->setPreviewWindow(window); } } + if (result == NO_ERROR) { + // Everything has succeeded. Disconnect the old window and remember the + // new window. + disconnectWindow(mPreviewWindow); + mSurface = binder; + mPreviewWindow = window; + } else { + // Something went wrong after we connected to the new window, so + // disconnect here. + disconnectWindow(window); + } + return result; } +// set the Surface that the preview will use +status_t CameraService::Client::setPreviewDisplay(const sp& surface) { + LOG1("setPreviewDisplay(%p) (pid %d)", surface.get(), getCallingPid()); + + sp binder(surface != 0 ? surface->asBinder() : 0); + sp window(surface); + return setPreviewWindow(binder, window); +} + // set the SurfaceTexture that the preview will use status_t CameraService::Client::setPreviewTexture( const sp& surfaceTexture) { LOG1("setPreviewTexture(%p) (pid %d)", surfaceTexture.get(), getCallingPid()); - Mutex::Autolock lock(mLock); - status_t result = checkPidAndHardware(); - if (result != NO_ERROR) return result; - - // return if no change in surface. - // asBinder() is safe on NULL (returns NULL) - if (surfaceTexture->asBinder() == mSurface) { - return result; - } - if (mSurface != 0) { - LOG1("clearing old preview surface %p", mSurface.get()); - } - mSurface = surfaceTexture->asBinder(); + sp binder; + sp window; if (surfaceTexture != 0) { - mPreviewWindow = new SurfaceTextureClient(surfaceTexture); - } else { - mPreviewWindow = 0; - } - - // If preview has been already started, set overlay or register preview - // buffers now. - if (mHardware->previewEnabled()) { - // XXX: What if the new preview window is 0? - if (mPreviewWindow != 0) { - native_window_set_buffers_transform(mPreviewWindow.get(), - mOrientation); - result = mHardware->setPreviewWindow(mPreviewWindow); - } + binder = surfaceTexture->asBinder(); + window = new SurfaceTextureClient(surfaceTexture); } - - return result; + return setPreviewWindow(binder, window); } // set the preview callback flag to affect how the received frames from diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h index 5e2d571..c5fefb8 100644 --- a/services/camera/libcameraservice/CameraService.h +++ b/services/camera/libcameraservice/CameraService.h @@ -161,6 +161,10 @@ private: int getOrientation(int orientation, bool mirror); + status_t setPreviewWindow( + const sp& binder, + const sp& window); + // these are initialized in the constructor. sp mCameraService; // immutable after constructor sp mCameraClient; -- cgit v1.1