diff options
author | Eino-Ville Talvala <etalvala@google.com> | 2013-04-02 15:45:11 -0700 |
---|---|---|
committer | Eino-Ville Talvala <etalvala@google.com> | 2013-04-17 15:01:08 -0700 |
commit | 3ee3550a2f529cbf56d87d8503f59a8f45dccf32 (patch) | |
tree | 99bf718ddc0429a1319523abaae975d3305face3 | |
parent | d72ec85d1d0b92ed82927e3925f21912a659b799 (diff) | |
download | frameworks_av-3ee3550a2f529cbf56d87d8503f59a8f45dccf32.zip frameworks_av-3ee3550a2f529cbf56d87d8503f59a8f45dccf32.tar.gz frameworks_av-3ee3550a2f529cbf56d87d8503f59a8f45dccf32.tar.bz2 |
Camera: Add preview callback surface support
- Add call to set a preview callback surface
- Implement support for HAL2/3 devices
- Still need HAL1 implementation
Change-Id: I0dc0bd72e43d871aa487858d1665c1efca633ffe
-rw-r--r-- | camera/Camera.cpp | 8 | ||||
-rw-r--r-- | camera/ICamera.cpp | 21 | ||||
-rw-r--r-- | include/camera/Camera.h | 8 | ||||
-rw-r--r-- | include/camera/ICamera.h | 9 | ||||
-rw-r--r-- | services/camera/libcameraservice/Camera2Client.cpp | 95 | ||||
-rw-r--r-- | services/camera/libcameraservice/Camera2Client.h | 3 | ||||
-rw-r--r-- | services/camera/libcameraservice/CameraClient.cpp | 6 | ||||
-rw-r--r-- | services/camera/libcameraservice/CameraClient.h | 2 | ||||
-rw-r--r-- | services/camera/libcameraservice/CameraService.h | 2 | ||||
-rw-r--r-- | services/camera/libcameraservice/camera2/CallbackProcessor.cpp | 52 | ||||
-rw-r--r-- | services/camera/libcameraservice/camera2/CallbackProcessor.h | 5 | ||||
-rw-r--r-- | services/camera/libcameraservice/camera2/Parameters.cpp | 1 | ||||
-rw-r--r-- | services/camera/libcameraservice/camera2/Parameters.h | 1 |
13 files changed, 191 insertions, 22 deletions
diff --git a/camera/Camera.cpp b/camera/Camera.cpp index 1b136de..fd78572 100644 --- a/camera/Camera.cpp +++ b/camera/Camera.cpp @@ -255,6 +255,14 @@ void Camera::setPreviewCallbackFlags(int flag) mCamera->setPreviewCallbackFlag(flag); } +status_t Camera::setPreviewCallbackTarget( + const sp<IGraphicBufferProducer>& callbackProducer) +{ + sp <ICamera> c = mCamera; + if (c == 0) return NO_INIT; + return c->setPreviewCallbackTarget(callbackProducer); +} + // callback from camera service void Camera::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2) { diff --git a/camera/ICamera.cpp b/camera/ICamera.cpp index 8900867..732c204 100644 --- a/camera/ICamera.cpp +++ b/camera/ICamera.cpp @@ -31,6 +31,7 @@ enum { DISCONNECT = IBinder::FIRST_CALL_TRANSACTION, SET_PREVIEW_TEXTURE, SET_PREVIEW_CALLBACK_FLAG, + SET_PREVIEW_CALLBACK_TARGET, START_PREVIEW, STOP_PREVIEW, AUTO_FOCUS, @@ -90,6 +91,18 @@ public: remote()->transact(SET_PREVIEW_CALLBACK_FLAG, data, &reply); } + status_t setPreviewCallbackTarget( + const sp<IGraphicBufferProducer>& callbackProducer) + { + ALOGV("setPreviewCallbackTarget"); + Parcel data, reply; + data.writeInterfaceToken(ICamera::getInterfaceDescriptor()); + sp<IBinder> b(callbackProducer->asBinder()); + data.writeStrongBinder(b); + remote()->transact(SET_PREVIEW_CALLBACK_TARGET, data, &reply); + return reply.readInt32(); + } + // start preview mode, must call setPreviewDisplay first status_t startPreview() { @@ -285,6 +298,14 @@ status_t BnCamera::onTransact( setPreviewCallbackFlag(callback_flag); return NO_ERROR; } break; + case SET_PREVIEW_CALLBACK_TARGET: { + ALOGV("SET_PREVIEW_CALLBACK_TARGET"); + CHECK_INTERFACE(ICamera, data, reply); + sp<IGraphicBufferProducer> cp = + interface_cast<IGraphicBufferProducer>(data.readStrongBinder()); + reply->writeInt32(setPreviewCallbackTarget(cp)); + return NO_ERROR; + } case START_PREVIEW: { ALOGV("START_PREVIEW"); CHECK_INTERFACE(ICamera, data, reply); diff --git a/include/camera/Camera.h b/include/camera/Camera.h index 37626a4..c34b3ea 100644 --- a/include/camera/Camera.h +++ b/include/camera/Camera.h @@ -121,7 +121,15 @@ public: void setListener(const sp<CameraListener>& listener); void setRecordingProxyListener(const sp<ICameraRecordingProxyListener>& listener); + + // Configure preview callbacks to app. Only one of the older + // callbacks or the callback surface can be active at the same time; + // enabling one will disable the other if active. Flags can be + // disabled by calling it with CAMERA_FRAME_CALLBACK_FLAG_NOOP, and + // Target by calling it with a NULL interface. void setPreviewCallbackFlags(int preview_callback_flag); + status_t setPreviewCallbackTarget( + const sp<IGraphicBufferProducer>& callbackProducer); sp<ICameraRecordingProxy> getRecordingProxy(); diff --git a/include/camera/ICamera.h b/include/camera/ICamera.h index 2236c1f..b2125bd 100644 --- a/include/camera/ICamera.h +++ b/include/camera/ICamera.h @@ -51,8 +51,15 @@ public: const sp<IGraphicBufferProducer>& bufferProducer) = 0; // set the preview callback flag to affect how the received frames from - // preview are handled. + // preview are handled. Enabling preview callback flags disables any active + // preview callback surface set by setPreviewCallbackTarget(). virtual void setPreviewCallbackFlag(int flag) = 0; + // set a buffer interface to use for client-received preview frames instead + // of preview callback buffers. Passing a valid interface here disables any + // active preview callbacks set by setPreviewCallbackFlag(). Passing NULL + // disables the use of the callback target. + virtual status_t setPreviewCallbackTarget( + const sp<IGraphicBufferProducer>& callbackProducer) = 0; // start preview mode, must call setPreviewDisplay first virtual status_t startPreview() = 0; diff --git a/services/camera/libcameraservice/Camera2Client.cpp b/services/camera/libcameraservice/Camera2Client.cpp index 9421a77..f3b3d94 100644 --- a/services/camera/libcameraservice/Camera2Client.cpp +++ b/services/camera/libcameraservice/Camera2Client.cpp @@ -578,27 +578,94 @@ void Camera2Client::setPreviewCallbackFlagL(Parameters ¶ms, int flag) { params.previewCallbackOneShot = true; } if (params.previewCallbackFlags != (uint32_t)flag) { + + if (flag != CAMERA_FRAME_CALLBACK_FLAG_NOOP) { + // Disable any existing preview callback window when enabling + // preview callback flags + res = mCallbackProcessor->setCallbackWindow(NULL); + if (res != OK) { + ALOGE("%s: Camera %d: Unable to clear preview callback surface:" + " %s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); + return; + } + params.previewCallbackSurface = false; + } + params.previewCallbackFlags = flag; + switch(params.state) { + case Parameters::PREVIEW: + res = startPreviewL(params, true); + break; + case Parameters::RECORD: + case Parameters::VIDEO_SNAPSHOT: + res = startRecordingL(params, true); + break; + default: + break; + } + if (res != OK) { + ALOGE("%s: Camera %d: Unable to refresh request in state %s", + __FUNCTION__, mCameraId, + Parameters::getStateName(params.state)); + } + } + +} + +status_t Camera2Client::setPreviewCallbackTarget( + const sp<IGraphicBufferProducer>& callbackProducer) { + ATRACE_CALL(); + ALOGV("%s: E", __FUNCTION__); + Mutex::Autolock icl(mBinderSerializationLock); + status_t res; + if ( (res = checkPid(__FUNCTION__) ) != OK) return res; + + sp<ANativeWindow> window; + if (callbackProducer != 0) { + window = new Surface(callbackProducer); + } + + res = mCallbackProcessor->setCallbackWindow(window); + if (res != OK) { + ALOGE("%s: Camera %d: Unable to set preview callback surface: %s (%d)", + __FUNCTION__, mCameraId, strerror(-res), res); + return res; + } + + SharedParameters::Lock l(mParameters); + + if (window != NULL) { + // Disable traditional callbacks when a valid callback target is given + l.mParameters.previewCallbackFlags = CAMERA_FRAME_CALLBACK_FLAG_NOOP; + l.mParameters.previewCallbackOneShot = false; + l.mParameters.previewCallbackSurface = true; + } else { + // Disable callback target if given a NULL interface. + l.mParameters.previewCallbackSurface = false; + } + + switch(l.mParameters.state) { case Parameters::PREVIEW: - res = startPreviewL(params, true); + res = startPreviewL(l.mParameters, true); break; case Parameters::RECORD: case Parameters::VIDEO_SNAPSHOT: - res = startRecordingL(params, true); + res = startRecordingL(l.mParameters, true); break; default: break; - } - if (res != OK) { - ALOGE("%s: Camera %d: Unable to refresh request in state %s", - __FUNCTION__, mCameraId, - Parameters::getStateName(params.state)); - } + } + if (res != OK) { + ALOGE("%s: Camera %d: Unable to refresh request in state %s", + __FUNCTION__, mCameraId, + Parameters::getStateName(l.mParameters.state)); } + return OK; } + status_t Camera2Client::startPreview() { ATRACE_CALL(); ALOGV("%s: E", __FUNCTION__); @@ -645,8 +712,10 @@ status_t Camera2Client::startPreviewL(Parameters ¶ms, bool restart) { } Vector<uint8_t> outputStreams; - bool callbacksEnabled = params.previewCallbackFlags & - CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK; + bool callbacksEnabled = (params.previewCallbackFlags & + CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK) || + params.previewCallbackSurface; + if (callbacksEnabled) { res = mCallbackProcessor->updateStream(params); if (res != OK) { @@ -860,8 +929,10 @@ status_t Camera2Client::startRecordingL(Parameters ¶ms, bool restart) { } Vector<uint8_t> outputStreams; - bool callbacksEnabled = params.previewCallbackFlags & - CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK; + bool callbacksEnabled = (params.previewCallbackFlags & + CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK) || + params.previewCallbackSurface; + if (callbacksEnabled) { res = mCallbackProcessor->updateStream(params); if (res != OK) { diff --git a/services/camera/libcameraservice/Camera2Client.h b/services/camera/libcameraservice/Camera2Client.h index 713fab3..46c6ceb 100644 --- a/services/camera/libcameraservice/Camera2Client.h +++ b/services/camera/libcameraservice/Camera2Client.h @@ -51,6 +51,9 @@ public: virtual status_t setPreviewTexture( const sp<IGraphicBufferProducer>& bufferProducer); virtual void setPreviewCallbackFlag(int flag); + virtual status_t setPreviewCallbackTarget( + const sp<IGraphicBufferProducer>& callbackProducer); + virtual status_t startPreview(); virtual void stopPreview(); virtual bool previewEnabled(); diff --git a/services/camera/libcameraservice/CameraClient.cpp b/services/camera/libcameraservice/CameraClient.cpp index e577fa3..be78f69 100644 --- a/services/camera/libcameraservice/CameraClient.cpp +++ b/services/camera/libcameraservice/CameraClient.cpp @@ -347,6 +347,12 @@ void CameraClient::setPreviewCallbackFlag(int callback_flag) { } } +status_t CameraClient::setPreviewCallbackTarget( + const sp<IGraphicBufferProducer>& callbackProducer) { + ALOGE("%s: Unimplemented!", __FUNCTION__); + return INVALID_OPERATION; +} + // start preview mode status_t CameraClient::startPreview() { LOG1("startPreview (pid %d)", getCallingPid()); diff --git a/services/camera/libcameraservice/CameraClient.h b/services/camera/libcameraservice/CameraClient.h index 7f0cb29..abde75a 100644 --- a/services/camera/libcameraservice/CameraClient.h +++ b/services/camera/libcameraservice/CameraClient.h @@ -40,6 +40,8 @@ public: virtual status_t setPreviewDisplay(const sp<Surface>& surface); virtual status_t setPreviewTexture(const sp<IGraphicBufferProducer>& bufferProducer); virtual void setPreviewCallbackFlag(int flag); + virtual status_t setPreviewCallbackTarget( + const sp<IGraphicBufferProducer>& callbackProducer); virtual status_t startPreview(); virtual void stopPreview(); virtual bool previewEnabled(); diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h index 8cb1691..bb3fb25 100644 --- a/services/camera/libcameraservice/CameraService.h +++ b/services/camera/libcameraservice/CameraService.h @@ -190,6 +190,8 @@ public: virtual status_t setPreviewDisplay(const sp<Surface>& surface) = 0; virtual status_t setPreviewTexture(const sp<IGraphicBufferProducer>& bufferProducer)=0; virtual void setPreviewCallbackFlag(int flag) = 0; + virtual status_t setPreviewCallbackTarget( + const sp<IGraphicBufferProducer>& callbackProducer) = 0; virtual status_t startPreview() = 0; virtual void stopPreview() = 0; virtual bool previewEnabled() = 0; diff --git a/services/camera/libcameraservice/camera2/CallbackProcessor.cpp b/services/camera/libcameraservice/camera2/CallbackProcessor.cpp index 30c14ef..1734c6a 100644 --- a/services/camera/libcameraservice/camera2/CallbackProcessor.cpp +++ b/services/camera/libcameraservice/camera2/CallbackProcessor.cpp @@ -34,6 +34,7 @@ CallbackProcessor::CallbackProcessor(wp<Camera2Client> client): Thread(false), mClient(client), mCallbackAvailable(false), + mCallbackToApp(false), mCallbackStreamId(NO_STREAM) { } @@ -50,6 +51,35 @@ void CallbackProcessor::onFrameAvailable() { } } +status_t CallbackProcessor::setCallbackWindow( + sp<ANativeWindow> callbackWindow) { + ATRACE_CALL(); + status_t res; + + Mutex::Autolock l(mInputMutex); + + sp<Camera2Client> client = mClient.promote(); + if (client == 0) return OK; + sp<CameraDeviceBase> device = client->getCameraDevice(); + + // If the window is changing, clear out stream if it already exists + if (mCallbackWindow != callbackWindow && mCallbackStreamId != NO_STREAM) { + res = device->deleteStream(mCallbackStreamId); + if (res != OK) { + ALOGE("%s: Camera %d: Unable to delete old stream " + "for callbacks: %s (%d)", __FUNCTION__, + client->getCameraId(), strerror(-res), res); + return res; + } + mCallbackStreamId = NO_STREAM; + mCallbackConsumer.clear(); + } + mCallbackWindow = callbackWindow; + mCallbackToApp = (mCallbackWindow != NULL); + + return OK; +} + status_t CallbackProcessor::updateStream(const Parameters ¶ms) { ATRACE_CALL(); status_t res; @@ -60,8 +90,8 @@ status_t CallbackProcessor::updateStream(const Parameters ¶ms) { if (client == 0) return OK; sp<CameraDeviceBase> device = client->getCameraDevice(); - if (mCallbackConsumer == 0) { - // Create CPU buffer queue endpoint + if (!mCallbackToApp && mCallbackConsumer == 0) { + // Create CPU buffer queue endpoint, since app hasn't given us one mCallbackConsumer = new CpuConsumer(kCallbackHeapCount); mCallbackConsumer->setFrameAvailableListener(this); mCallbackConsumer->setName(String8("Camera2Client::CallbackConsumer")); @@ -69,6 +99,9 @@ status_t CallbackProcessor::updateStream(const Parameters ¶ms) { mCallbackConsumer->getProducerInterface()); } + uint32_t targetFormat = mCallbackToApp ? (uint32_t)HAL_PIXEL_FORMAT_YV12 : + (uint32_t)params.previewFormat; + if (mCallbackStreamId != NO_STREAM) { // Check if stream parameters have to change uint32_t currentWidth, currentHeight, currentFormat; @@ -82,17 +115,18 @@ status_t CallbackProcessor::updateStream(const Parameters ¶ms) { } if (currentWidth != (uint32_t)params.previewWidth || currentHeight != (uint32_t)params.previewHeight || - currentFormat != (uint32_t)params.previewFormat) { + currentFormat != targetFormat) { // Since size should only change while preview is not running, // assuming that all existing use of old callback stream is // completed. - ALOGV("%s: Camera %d: Deleting stream %d since the buffer dimensions changed", - __FUNCTION__, client->getCameraId(), mCallbackStreamId); + ALOGV("%s: Camera %d: Deleting stream %d since the buffer" + " dimensions changed", __FUNCTION__, + client->getCameraId(), mCallbackStreamId); res = device->deleteStream(mCallbackStreamId); if (res != OK) { ALOGE("%s: Camera %d: Unable to delete old output stream " - "for callbacks: %s (%d)", __FUNCTION__, client->getCameraId(), - strerror(-res), res); + "for callbacks: %s (%d)", __FUNCTION__, + client->getCameraId(), strerror(-res), res); return res; } mCallbackStreamId = NO_STREAM; @@ -102,10 +136,10 @@ status_t CallbackProcessor::updateStream(const Parameters ¶ms) { if (mCallbackStreamId == NO_STREAM) { ALOGV("Creating callback stream: %d %d format 0x%x", params.previewWidth, params.previewHeight, - params.previewFormat); + targetFormat); res = device->createStream(mCallbackWindow, params.previewWidth, params.previewHeight, - params.previewFormat, 0, &mCallbackStreamId); + targetFormat, 0, &mCallbackStreamId); if (res != OK) { ALOGE("%s: Camera %d: Can't create output stream for callbacks: " "%s (%d)", __FUNCTION__, client->getCameraId(), diff --git a/services/camera/libcameraservice/camera2/CallbackProcessor.h b/services/camera/libcameraservice/camera2/CallbackProcessor.h index e68bb75..5c46e0d 100644 --- a/services/camera/libcameraservice/camera2/CallbackProcessor.h +++ b/services/camera/libcameraservice/camera2/CallbackProcessor.h @@ -44,6 +44,8 @@ class CallbackProcessor: void onFrameAvailable(); + // Set to NULL to disable the direct-to-app callback window + status_t setCallbackWindow(sp<ANativeWindow> callbackWindow); status_t updateStream(const Parameters ¶ms); status_t deleteStream(); int getStreamId() const; @@ -61,6 +63,9 @@ class CallbackProcessor: NO_STREAM = -1 }; + // True if mCallbackWindow is a remote consumer, false if just the local + // mCallbackConsumer + bool mCallbackToApp; int mCallbackStreamId; static const size_t kCallbackHeapCount = 6; sp<CpuConsumer> mCallbackConsumer; diff --git a/services/camera/libcameraservice/camera2/Parameters.cpp b/services/camera/libcameraservice/camera2/Parameters.cpp index d13fe8b..1108535 100644 --- a/services/camera/libcameraservice/camera2/Parameters.cpp +++ b/services/camera/libcameraservice/camera2/Parameters.cpp @@ -787,6 +787,7 @@ status_t Parameters::initialize(const CameraMetadata *info) { previewCallbackFlags = 0; previewCallbackOneShot = false; + previewCallbackSurface = false; char value[PROPERTY_VALUE_MAX]; property_get("camera.disable_zsl_mode", value, "0"); diff --git a/services/camera/libcameraservice/camera2/Parameters.h b/services/camera/libcameraservice/camera2/Parameters.h index fe3ec1d..83743f8 100644 --- a/services/camera/libcameraservice/camera2/Parameters.h +++ b/services/camera/libcameraservice/camera2/Parameters.h @@ -142,6 +142,7 @@ struct Parameters { uint32_t previewCallbackFlags; bool previewCallbackOneShot; + bool previewCallbackSurface; bool zslMode; |