From e1ceec234c618729cc7bd35fecb11744b52c1cc8 Mon Sep 17 00:00:00 2001 From: Chih-Chung Chang Date: Thu, 21 Jan 2010 17:31:06 -0800 Subject: [PATCH] Add an orientation parameter for overlay, so we can do camera preview in portrait mode. --- camera/libcameraservice/CameraService.cpp | 29 +++++++++---------- camera/libcameraservice/CameraService.h | 1 + .../CameraServiceTest/CameraServiceTest.cpp | 5 ++-- include/ui/ISurface.h | 2 +- libs/surfaceflinger/LayerBase.cpp | 2 +- libs/surfaceflinger/LayerBase.h | 2 +- libs/surfaceflinger/LayerBuffer.cpp | 19 +++++++----- libs/surfaceflinger/LayerBuffer.h | 8 +++-- libs/surfaceflinger/Transform.cpp | 11 +++++++ libs/surfaceflinger/Transform.h | 1 + libs/ui/ISurface.cpp | 6 ++-- media/libstagefright/CameraSource.cpp | 2 +- 12 files changed, 55 insertions(+), 33 deletions(-) diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp index fae1f2604131b..a8e217e4e5100 100644 --- a/camera/libcameraservice/CameraService.cpp +++ b/camera/libcameraservice/CameraService.cpp @@ -235,6 +235,7 @@ CameraService::Client::Client(const sp& cameraService, // Callback is disabled by default mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP; + mOrientation = 0; cameraService->incUsers(); LOGV("Client::Client X (pid %d)", callingPid); } @@ -570,7 +571,8 @@ status_t CameraService::Client::setOverlay() // wait in the createOverlay call if the previous overlay is in the // process of being destroyed. for (int retry = 0; retry < 50; ++retry) { - mOverlayRef = mSurface->createOverlay(w, h, OVERLAY_FORMAT_DEFAULT); + mOverlayRef = mSurface->createOverlay(w, h, OVERLAY_FORMAT_DEFAULT, + mOrientation); if (mOverlayRef != NULL) break; LOGW("Overlay create failed - retrying"); usleep(20000); @@ -601,15 +603,9 @@ status_t CameraService::Client::registerPreviewBuffers() 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, + mOrientation, 0, mHardware->getPreviewHeap()); @@ -919,12 +915,6 @@ void CameraService::Client::handleShutter( if (mSurface != 0 && !mUseOverlay) { int w, h; CameraParameters params(mHardware->getParameters()); - uint32_t transform = 0; - if (params.getOrientation() == CameraParameters::CAMERA_ORIENTATION_PORTRAIT) { - LOGV("portrait mode"); - transform = ISurface::BufferHeap::ROT_90; - } - if (size == NULL) { params.getPictureSize(&w, &h); } else { @@ -935,7 +925,7 @@ void CameraService::Client::handleShutter( LOGV("Snapshot image width=%d, height=%d", w, h); } ISurface::BufferHeap buffers(w, h, w, h, - PIXEL_FORMAT_YCbCr_420_SP, transform, 0, mHardware->getRawHeap()); + PIXEL_FORMAT_YCbCr_420_SP, mOrientation, 0, mHardware->getRawHeap()); mSurface->registerBuffers(buffers); } @@ -1200,6 +1190,15 @@ status_t CameraService::Client::setParameters(const String8& params) } CameraParameters p(params); + + // The orientation parameter is actually for CameraService, not for the camera driver. + if (p.getOrientation() == CameraParameters::CAMERA_ORIENTATION_PORTRAIT) { + LOGV("portrait mode"); + mOrientation = ISurface::BufferHeap::ROT_90; + } else { + mOrientation = 0; + } + return mHardware->setParameters(p); } diff --git a/camera/libcameraservice/CameraService.h b/camera/libcameraservice/CameraService.h index 3e3e54f0a950d..b3d20f6194ad9 100644 --- a/camera/libcameraservice/CameraService.h +++ b/camera/libcameraservice/CameraService.h @@ -182,6 +182,7 @@ private: sp mCameraService; sp mSurface; int mPreviewCallbackFlag; + int mOrientation; sp mMediaPlayerClick; sp mMediaPlayerBeep; diff --git a/camera/tests/CameraServiceTest/CameraServiceTest.cpp b/camera/tests/CameraServiceTest/CameraServiceTest.cpp index 29320e0e7a786..f89d9d3556c7a 100644 --- a/camera/tests/CameraServiceTest/CameraServiceTest.cpp +++ b/camera/tests/CameraServiceTest/CameraServiceTest.cpp @@ -283,7 +283,7 @@ public: virtual void postBuffer(ssize_t offset); virtual void unregisterBuffers(); virtual sp createOverlay( - uint32_t w, uint32_t h, int32_t format); + uint32_t w, uint32_t h, int32_t format, int32_t orientation); virtual sp requestBuffer(int bufferIdx, int usage); // new functions @@ -346,7 +346,8 @@ void MSurface::waitUntil(int c0, int c1, int c2) { } } -sp MSurface::createOverlay(uint32_t w, uint32_t h, int32_t format) { +sp MSurface::createOverlay(uint32_t w, uint32_t h, int32_t format, + int32_t orientation) { // We don't expect this to be called in current hardware. ASSERT(0); sp dummy; diff --git a/include/ui/ISurface.h b/include/ui/ISurface.h index 2ca00267690d3..b37a8ace6b2c3 100644 --- a/include/ui/ISurface.h +++ b/include/ui/ISurface.h @@ -86,7 +86,7 @@ public: virtual void unregisterBuffers() = 0; virtual sp createOverlay( - uint32_t w, uint32_t h, int32_t format) = 0; + uint32_t w, uint32_t h, int32_t format, int32_t orientation) = 0; }; // ---------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp index 8003d22daa8ba..17db6f457397f 100644 --- a/libs/surfaceflinger/LayerBase.cpp +++ b/libs/surfaceflinger/LayerBase.cpp @@ -809,7 +809,7 @@ void LayerBaseClient::Surface::unregisterBuffers() } sp LayerBaseClient::Surface::createOverlay( - uint32_t w, uint32_t h, int32_t format) + uint32_t w, uint32_t h, int32_t format, int32_t orientation) { return NULL; }; diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h index ed07b3f933603..f73ea0c56b81c 100644 --- a/libs/surfaceflinger/LayerBase.h +++ b/libs/surfaceflinger/LayerBase.h @@ -351,7 +351,7 @@ public: virtual void postBuffer(ssize_t offset); virtual void unregisterBuffers(); virtual sp createOverlay(uint32_t w, uint32_t h, - int32_t format); + int32_t format, int32_t orientation); protected: friend class LayerBaseClient; diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp index ac9b6b05c460c..2735aa2a31e2a 100644 --- a/libs/surfaceflinger/LayerBuffer.cpp +++ b/libs/surfaceflinger/LayerBuffer.cpp @@ -182,14 +182,15 @@ status_t LayerBuffer::registerBuffers(const ISurface::BufferHeap& buffers) /** * This creates an "overlay" source for this surface */ -sp LayerBuffer::createOverlay(uint32_t w, uint32_t h, int32_t f) +sp LayerBuffer::createOverlay(uint32_t w, uint32_t h, int32_t f, + int32_t orientation) { sp result; Mutex::Autolock _l(mLock); if (mSource != 0) return result; - sp source = new OverlaySource(*this, &result, w, h, f); + sp source = new OverlaySource(*this, &result, w, h, f, orientation); if (result != 0) { mSource = source; } @@ -248,11 +249,11 @@ void LayerBuffer::SurfaceLayerBuffer::unregisterBuffers() } sp LayerBuffer::SurfaceLayerBuffer::createOverlay( - uint32_t w, uint32_t h, int32_t format) { + uint32_t w, uint32_t h, int32_t format, int32_t orientation) { sp result; sp owner(getOwner()); if (owner != 0) - result = owner->createOverlay(w, h, format); + result = owner->createOverlay(w, h, format, orientation); return result; } @@ -600,9 +601,9 @@ void LayerBuffer::BufferSource::clearTempBufferImage() const LayerBuffer::OverlaySource::OverlaySource(LayerBuffer& layer, sp* overlayRef, - uint32_t w, uint32_t h, int32_t format) + uint32_t w, uint32_t h, int32_t format, int32_t orientation) : Source(layer), mVisibilityChanged(false), - mOverlay(0), mOverlayHandle(0), mOverlayDevice(0) + mOverlay(0), mOverlayHandle(0), mOverlayDevice(0), mOrientation(orientation) { overlay_control_device_t* overlay_dev = mLayer.mFlinger->getOverlayEngine(); if (overlay_dev == NULL) { @@ -684,8 +685,12 @@ void LayerBuffer::OverlaySource::onVisibilityResolved( if (mOverlay) { overlay_control_device_t* overlay_dev = mOverlayDevice; overlay_dev->setPosition(overlay_dev, mOverlay, x,y,w,h); + // we need to combine the layer orientation and the + // user-requested orientation. + Transform finalTransform = Transform(mOrientation) * + Transform(mLayer.getOrientation()); overlay_dev->setParameter(overlay_dev, mOverlay, - OVERLAY_TRANSFORM, mLayer.getOrientation()); + OVERLAY_TRANSFORM, finalTransform.getOrientation()); overlay_dev->commit(overlay_dev, mOverlay); } } diff --git a/libs/surfaceflinger/LayerBuffer.h b/libs/surfaceflinger/LayerBuffer.h index 1b3143555a642..e03f92c7b1a45 100644 --- a/libs/surfaceflinger/LayerBuffer.h +++ b/libs/surfaceflinger/LayerBuffer.h @@ -74,7 +74,8 @@ public: status_t registerBuffers(const ISurface::BufferHeap& buffers); void postBuffer(ssize_t offset); void unregisterBuffers(); - sp createOverlay(uint32_t w, uint32_t h, int32_t format); + sp createOverlay(uint32_t w, uint32_t h, int32_t format, + int32_t orientation); sp getSource() const; sp clearSource(); @@ -150,7 +151,7 @@ private: public: OverlaySource(LayerBuffer& layer, sp* overlayRef, - uint32_t w, uint32_t h, int32_t format); + uint32_t w, uint32_t h, int32_t format, int32_t orientation); virtual ~OverlaySource(); virtual void onDraw(const Region& clip) const; virtual void onTransaction(uint32_t flags); @@ -183,6 +184,7 @@ private: int32_t mFormat; int32_t mWidthStride; int32_t mHeightStride; + int32_t mOrientation; mutable Mutex mOverlaySourceLock; bool mInitialized; }; @@ -200,7 +202,7 @@ private: virtual void unregisterBuffers(); virtual sp createOverlay( - uint32_t w, uint32_t h, int32_t format); + uint32_t w, uint32_t h, int32_t format, int32_t orientation); private: sp getOwner() const { return static_cast(Surface::getOwner().get()); diff --git a/libs/surfaceflinger/Transform.cpp b/libs/surfaceflinger/Transform.cpp index 1501536f29032..ab6f7badc2a13 100644 --- a/libs/surfaceflinger/Transform.cpp +++ b/libs/surfaceflinger/Transform.cpp @@ -42,6 +42,17 @@ Transform::Transform(const Transform& other) { } +Transform::Transform(int32_t flags) { + mTransform.reset(); + int sx = (flags & FLIP_H) ? -1 : 1; + int sy = (flags & FLIP_V) ? -1 : 1; + if (flags & ROT_90) { + this->set(0, -sy, sx, 0); + } else { + this->set(sx, 0, 0, sy); + } +} + Transform::~Transform() { } diff --git a/libs/surfaceflinger/Transform.h b/libs/surfaceflinger/Transform.h index 78f5c19601767..ddab404e27076 100644 --- a/libs/surfaceflinger/Transform.h +++ b/libs/surfaceflinger/Transform.h @@ -38,6 +38,7 @@ class Transform public: Transform(); Transform(const Transform& other); + Transform(int32_t flags); ~Transform(); enum orientation_flags { diff --git a/libs/ui/ISurface.cpp b/libs/ui/ISurface.cpp index 4fb38ed983148..6f3d762c3a86f 100644 --- a/libs/ui/ISurface.cpp +++ b/libs/ui/ISurface.cpp @@ -115,13 +115,14 @@ public: } virtual sp createOverlay( - uint32_t w, uint32_t h, int32_t format) + uint32_t w, uint32_t h, int32_t format, int32_t orientation) { Parcel data, reply; data.writeInterfaceToken(ISurface::getInterfaceDescriptor()); data.writeInt32(w); data.writeInt32(h); data.writeInt32(format); + data.writeInt32(orientation); remote()->transact(CREATE_OVERLAY, data, &reply); return OverlayRef::readFromParcel(reply); } @@ -173,7 +174,8 @@ status_t BnSurface::onTransact( int w = data.readInt32(); int h = data.readInt32(); int f = data.readInt32(); - sp o = createOverlay(w, h, f); + int orientation = data.readInt32(); + sp o = createOverlay(w, h, f, orientation); return OverlayRef::writeToParcel(reply, o); } break; default: diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp index bd862e0de34e1..8cd572ec2e0a3 100644 --- a/media/libstagefright/CameraSource.cpp +++ b/media/libstagefright/CameraSource.cpp @@ -56,7 +56,7 @@ struct DummySurface : public BnSurface { virtual void unregisterBuffers() {} virtual sp createOverlay( - uint32_t w, uint32_t h, int32_t format) { + uint32_t w, uint32_t h, int32_t format, int32_t orientation) { return NULL; }