From ff2dc46c121c166f10684da069d07ae11d4f9b9a Mon Sep 17 00:00:00 2001 From: Jamie Gennis Date: Mon, 20 Dec 2010 11:51:31 -0800 Subject: [PATCH] Add camera service support for SurfaceTexture. This change enables the use of a SurfaceTexture in place of a Surface as the destination of camera preview frames. Change-Id: Ic70d404c8fe261e9d5da6f1de93d6babb5b191cb --- include/camera/Camera.h | 4 ++ include/camera/ICamera.h | 5 ++ libs/camera/Android.mk | 3 +- libs/camera/Camera.cpp | 14 ++++ libs/camera/ICamera.cpp | 20 ++++++ services/camera/libcameraservice/Android.mk | 3 +- .../camera/libcameraservice/CameraService.cpp | 68 ++++++++++++------- .../camera/libcameraservice/CameraService.h | 4 +- 8 files changed, 95 insertions(+), 26 deletions(-) diff --git a/include/camera/Camera.h b/include/camera/Camera.h index c95f31edfcbb8..e5f7e623c476e 100644 --- a/include/camera/Camera.h +++ b/include/camera/Camera.h @@ -19,6 +19,7 @@ #include #include +#include namespace android { @@ -175,6 +176,9 @@ public: // pass the buffered Surface to the camera service status_t setPreviewDisplay(const sp& surface); + // pass the buffered ISurfaceTexture to the camera service + status_t setPreviewTexture(const sp& surfaceTexture); + // start preview mode, must call setPreviewDisplay first status_t startPreview(); diff --git a/include/camera/ICamera.h b/include/camera/ICamera.h index b69e075995eb9..b2310a64c7d71 100644 --- a/include/camera/ICamera.h +++ b/include/camera/ICamera.h @@ -24,6 +24,7 @@ #include #include #include +#include namespace android { @@ -48,6 +49,10 @@ public: // pass the buffered Surface to the camera service virtual status_t setPreviewDisplay(const sp& surface) = 0; + // pass the buffered ISurfaceTexture to the camera service + virtual status_t setPreviewTexture( + const sp& surfaceTexture) = 0; + // set the preview callback flag to affect how the received frames from // preview are handled. virtual void setPreviewCallbackFlag(int flag) = 0; diff --git a/libs/camera/Android.mk b/libs/camera/Android.mk index 03ff229dacdfc..2f16923de473f 100644 --- a/libs/camera/Android.mk +++ b/libs/camera/Android.mk @@ -14,7 +14,8 @@ LOCAL_SHARED_LIBRARIES := \ libbinder \ libhardware \ libsurfaceflinger_client \ - libui + libui \ + libgui LOCAL_MODULE:= libcamera_client diff --git a/libs/camera/Camera.cpp b/libs/camera/Camera.cpp index ab626ad4c9e0b..907f119b81745 100644 --- a/libs/camera/Camera.cpp +++ b/libs/camera/Camera.cpp @@ -182,6 +182,20 @@ status_t Camera::setPreviewDisplay(const sp& surface) } } +// pass the buffered ISurfaceTexture to the camera service +status_t Camera::setPreviewTexture(const sp& surfaceTexture) +{ + LOGV("setPreviewTexture(%p)", surfaceTexture.get()); + sp c = mCamera; + if (c == 0) return NO_INIT; + if (surfaceTexture != 0) { + return c->setPreviewTexture(surfaceTexture); + } else { + LOGD("app passed NULL surface"); + return c->setPreviewTexture(0); + } +} + // start preview mode status_t Camera::startPreview() { diff --git a/libs/camera/ICamera.cpp b/libs/camera/ICamera.cpp index 7ba8d120bea90..0881d65ae3d22 100644 --- a/libs/camera/ICamera.cpp +++ b/libs/camera/ICamera.cpp @@ -28,6 +28,7 @@ namespace android { enum { DISCONNECT = IBinder::FIRST_CALL_TRANSACTION, SET_PREVIEW_DISPLAY, + SET_PREVIEW_TEXTURE, SET_PREVIEW_CALLBACK_FLAG, START_PREVIEW, STOP_PREVIEW, @@ -78,6 +79,18 @@ public: return reply.readInt32(); } + // pass the buffered SurfaceTexture to the camera service + status_t setPreviewTexture(const sp& surfaceTexture) + { + LOGV("setPreviewTexture"); + Parcel data, reply; + data.writeInterfaceToken(ICamera::getInterfaceDescriptor()); + sp b(surfaceTexture->asBinder()); + data.writeStrongBinder(b); + remote()->transact(SET_PREVIEW_TEXTURE, data, &reply); + return reply.readInt32(); + } + // set the preview callback flag to affect how the received frames from // preview are handled. See Camera.h for details. void setPreviewCallbackFlag(int flag) @@ -296,6 +309,13 @@ status_t BnCamera::onTransact( reply->writeInt32(setPreviewDisplay(surface)); return NO_ERROR; } break; + case SET_PREVIEW_TEXTURE: { + LOGV("SET_PREVIEW_TEXTURE"); + CHECK_INTERFACE(ICamera, data, reply); + sp st = interface_cast(data.readStrongBinder()); + reply->writeInt32(setPreviewTexture(st)); + return NO_ERROR; + } break; case SET_PREVIEW_CALLBACK_FLAG: { LOGV("SET_PREVIEW_CALLBACK_TYPE"); CHECK_INTERFACE(ICamera, data, reply); diff --git a/services/camera/libcameraservice/Android.mk b/services/camera/libcameraservice/Android.mk index 87975af9eabfb..b52fc694e781b 100644 --- a/services/camera/libcameraservice/Android.mk +++ b/services/camera/libcameraservice/Android.mk @@ -49,7 +49,8 @@ LOCAL_SHARED_LIBRARIES:= \ libcutils \ libmedia \ libcamera_client \ - libsurfaceflinger_client + libsurfaceflinger_client \ + libgui LOCAL_MODULE:= libcameraservice diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index 15f6a44e7b7e7..3d8ca7a3da131 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -306,6 +307,8 @@ CameraService::Client::Client(const sp& cameraService, mCameraFacing = cameraFacing; mClientPid = clientPid; mMsgEnabled = 0; + mSurface = 0; + mPreviewWindow = 0; mHardware->setCallbacks(notifyCallback, dataCallback, dataCallbackTimestamp, @@ -470,19 +473,16 @@ status_t CameraService::Client::setPreviewDisplay(const sp& surface) { // return if no change in surface. // asBinder() is safe on NULL (returns NULL) - if (getISurface(surface)->asBinder() == mSurface->asBinder()) { + if (getISurface(surface)->asBinder() == mSurface) { return result; } if (mSurface != 0) { LOG1("clearing old preview surface %p", mSurface.get()); } - if (surface != 0) { - mSurface = getISurface(surface); - } else { - mSurface = 0; - } + mSurface = getISurface(surface)->asBinder(); mPreviewWindow = surface; + // If preview has been already started, register preview // buffers now. if (mHardware->previewEnabled()) { @@ -496,6 +496,45 @@ status_t CameraService::Client::setPreviewDisplay(const sp& surface) { return result; } +// 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(); + 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); + } + } + + return result; +} + // set the preview callback flag to affect how the received frames from // preview are handled. void CameraService::Client::setPreviewCallbackFlag(int callback_flag) { @@ -960,23 +999,6 @@ void CameraService::Client::handleShutter(image_rect_type *size) { } 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 (mSurface != 0) { - int w, h; - CameraParameters params(mHardware->getParameters()); - if (size == NULL) { - params.getPictureSize(&w, &h); - } else { - w = size->width; - h = size->height; - w &= ~1; - h &= ~1; - LOG1("Snapshot image width=%d, height=%d", w, h); - } - IPCThreadState::self()->flushCommands(); - } - mLock.unlock(); } diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h index d78d7e596aaa6..ccb9cf7082ccf 100644 --- a/services/camera/libcameraservice/CameraService.h +++ b/services/camera/libcameraservice/CameraService.h @@ -94,6 +94,7 @@ private: virtual status_t lock(); virtual status_t unlock(); virtual status_t setPreviewDisplay(const sp& surface); + virtual status_t setPreviewTexture(const sp& surfaceTexture); virtual void setPreviewCallbackFlag(int flag); virtual status_t startPreview(); virtual void stopPreview(); @@ -180,7 +181,8 @@ private: // Ensures atomicity among the public methods mutable Mutex mLock; - sp mSurface; + // This is a binder of Surface or SurfaceTexture. + sp mSurface; sp mPreviewWindow; // If the user want us to return a copy of the preview frame (instead