diff options
author | Jamie Gennis <jgennis@google.com> | 2010-12-20 11:51:31 -0800 |
---|---|---|
committer | Jamie Gennis <jgennis@google.com> | 2011-01-06 13:31:53 -0800 |
commit | bfa33aae4f54c0020a0568b16a3acb7b30b6ca3d (patch) | |
tree | 3dae4190516dcddec996a2b7c51b5f192c3ed4ca | |
parent | 5de2001a5c3f854b63dbcea284e02f930881ca75 (diff) | |
download | frameworks_av-bfa33aae4f54c0020a0568b16a3acb7b30b6ca3d.zip frameworks_av-bfa33aae4f54c0020a0568b16a3acb7b30b6ca3d.tar.gz frameworks_av-bfa33aae4f54c0020a0568b16a3acb7b30b6ca3d.tar.bz2 |
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
-rw-r--r-- | camera/Android.mk | 3 | ||||
-rw-r--r-- | camera/Camera.cpp | 14 | ||||
-rw-r--r-- | camera/ICamera.cpp | 20 | ||||
-rw-r--r-- | include/camera/Camera.h | 4 | ||||
-rw-r--r-- | include/camera/ICamera.h | 5 | ||||
-rw-r--r-- | services/camera/libcameraservice/Android.mk | 3 | ||||
-rw-r--r-- | services/camera/libcameraservice/CameraService.cpp | 68 | ||||
-rw-r--r-- | services/camera/libcameraservice/CameraService.h | 4 |
8 files changed, 95 insertions, 26 deletions
diff --git a/camera/Android.mk b/camera/Android.mk index 03ff229..2f16923 100644 --- a/camera/Android.mk +++ b/camera/Android.mk @@ -14,7 +14,8 @@ LOCAL_SHARED_LIBRARIES := \ libbinder \ libhardware \ libsurfaceflinger_client \ - libui + libui \ + libgui LOCAL_MODULE:= libcamera_client diff --git a/camera/Camera.cpp b/camera/Camera.cpp index ab626ad..907f119 100644 --- a/camera/Camera.cpp +++ b/camera/Camera.cpp @@ -182,6 +182,20 @@ status_t Camera::setPreviewDisplay(const sp<Surface>& surface) } } +// pass the buffered ISurfaceTexture to the camera service +status_t Camera::setPreviewTexture(const sp<ISurfaceTexture>& surfaceTexture) +{ + LOGV("setPreviewTexture(%p)", surfaceTexture.get()); + sp <ICamera> 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/camera/ICamera.cpp b/camera/ICamera.cpp index 7ba8d12..0881d65 100644 --- a/camera/ICamera.cpp +++ b/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<ISurfaceTexture>& surfaceTexture) + { + LOGV("setPreviewTexture"); + Parcel data, reply; + data.writeInterfaceToken(ICamera::getInterfaceDescriptor()); + sp<IBinder> 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<ISurfaceTexture> st = interface_cast<ISurfaceTexture>(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/include/camera/Camera.h b/include/camera/Camera.h index c95f31e..e5f7e62 100644 --- a/include/camera/Camera.h +++ b/include/camera/Camera.h @@ -19,6 +19,7 @@ #include <utils/Timers.h> #include <camera/ICameraClient.h> +#include <gui/ISurfaceTexture.h> namespace android { @@ -175,6 +176,9 @@ public: // pass the buffered Surface to the camera service status_t setPreviewDisplay(const sp<Surface>& surface); + // pass the buffered ISurfaceTexture to the camera service + status_t setPreviewTexture(const sp<ISurfaceTexture>& surfaceTexture); + // start preview mode, must call setPreviewDisplay first status_t startPreview(); diff --git a/include/camera/ICamera.h b/include/camera/ICamera.h index b69e075..b2310a6 100644 --- a/include/camera/ICamera.h +++ b/include/camera/ICamera.h @@ -24,6 +24,7 @@ #include <binder/IMemory.h> #include <utils/String8.h> #include <camera/Camera.h> +#include <gui/ISurfaceTexture.h> namespace android { @@ -48,6 +49,10 @@ public: // pass the buffered Surface to the camera service virtual status_t setPreviewDisplay(const sp<Surface>& surface) = 0; + // pass the buffered ISurfaceTexture to the camera service + virtual status_t setPreviewTexture( + const sp<ISurfaceTexture>& 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/services/camera/libcameraservice/Android.mk b/services/camera/libcameraservice/Android.mk index 87975af..b52fc69 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 15f6a44..3d8ca7a 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -27,6 +27,7 @@ #include <binder/MemoryHeapBase.h> #include <cutils/atomic.h> #include <cutils/properties.h> +#include <gui/SurfaceTextureClient.h> #include <hardware/hardware.h> #include <media/AudioSystem.h> #include <media/mediaplayer.h> @@ -306,6 +307,8 @@ CameraService::Client::Client(const sp<CameraService>& 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>& 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>& surface) { return result; } +// set the SurfaceTexture that the preview will use +status_t CameraService::Client::setPreviewTexture( + const sp<ISurfaceTexture>& 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 d78d7e5..ccb9cf7 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>& surface); + virtual status_t setPreviewTexture(const sp<ISurfaceTexture>& 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<ISurface> mSurface; + // This is a binder of Surface or SurfaceTexture. + sp<IBinder> mSurface; sp<ANativeWindow> mPreviewWindow; // If the user want us to return a copy of the preview frame (instead |