summaryrefslogtreecommitdiffstats
path: root/services/camera/libcameraservice
diff options
context:
space:
mode:
authorEino-Ville Talvala <etalvala@google.com>2013-04-23 15:16:57 -0700
committerIgor Murashkin <iam@google.com>2013-04-26 11:13:22 -0700
commitd09801b99503b57c35e321ad9afa7e861e012813 (patch)
tree62787f87bab856acffb5cb271dd6c2287d001c0b /services/camera/libcameraservice
parentec77122351b4e78c1fe5b60a208f76baf8c67591 (diff)
downloadframeworks_av-d09801b99503b57c35e321ad9afa7e861e012813.zip
frameworks_av-d09801b99503b57c35e321ad9afa7e861e012813.tar.gz
frameworks_av-d09801b99503b57c35e321ad9afa7e861e012813.tar.bz2
Camera2: Fix deadlock on shutdown due to client getting killed.
When the binder connection dies and is the only holder of a strong pointer to the Camera2Client, disconnect is called from the destructor. At this point, all weak pointers to Camera2Client are no longer promotable, and lots of cleanup code paths are broken as a result. Rework all such code paths to not need the client pointer, and to discard image buffers that arrive during shutdown. Bug: 8696047 Change-Id: Ic0672ecde7c1baaf65079f925a45bd5be45f1fb3
Diffstat (limited to 'services/camera/libcameraservice')
-rw-r--r--services/camera/libcameraservice/Camera2Client.cpp20
-rw-r--r--services/camera/libcameraservice/Camera2Device.cpp3
-rw-r--r--services/camera/libcameraservice/CameraService.cpp4
-rw-r--r--services/camera/libcameraservice/camera2/CallbackProcessor.cpp78
-rw-r--r--services/camera/libcameraservice/camera2/CallbackProcessor.h8
-rw-r--r--services/camera/libcameraservice/camera2/JpegProcessor.cpp45
-rw-r--r--services/camera/libcameraservice/camera2/JpegProcessor.h8
-rw-r--r--services/camera/libcameraservice/camera2/StreamingProcessor.cpp161
-rw-r--r--services/camera/libcameraservice/camera2/StreamingProcessor.h5
-rw-r--r--services/camera/libcameraservice/camera2/ZslProcessor.cpp74
-rw-r--r--services/camera/libcameraservice/camera2/ZslProcessor.h6
11 files changed, 263 insertions, 149 deletions
diff --git a/services/camera/libcameraservice/Camera2Client.cpp b/services/camera/libcameraservice/Camera2Client.cpp
index 9421a77..eae7461 100644
--- a/services/camera/libcameraservice/Camera2Client.cpp
+++ b/services/camera/libcameraservice/Camera2Client.cpp
@@ -135,6 +135,7 @@ status_t Camera2Client::initialize(camera_module_t *module)
Camera2Client::~Camera2Client() {
ATRACE_CALL();
+ ALOGV("~Camera2Client");
mDestructionStarted = true;
@@ -369,6 +370,12 @@ void Camera2Client::disconnect() {
ALOGV("Camera %d: Shutting down", mCameraId);
+ /**
+ * disconnect() cannot call any methods that might need to promote a
+ * wp<Camera2Client>, since disconnect can be called from the destructor, at
+ * which point all such promotions will fail.
+ */
+
stopPreviewL();
{
@@ -538,7 +545,12 @@ status_t Camera2Client::setPreviewWindowL(const sp<IBinder>& binder,
break;
case Parameters::PREVIEW:
// Already running preview - need to stop and create a new stream
- mStreamingProcessor->stopStream();
+ res = stopStream();
+ if (res != OK) {
+ ALOGE("%s: Unable to stop preview to swap windows: %s (%d)",
+ __FUNCTION__, strerror(-res), res);
+ return res;
+ }
state = Parameters::WAITING_FOR_PREVIEW_WINDOW;
break;
}
@@ -745,7 +757,11 @@ void Camera2Client::stopPreviewL() {
// no break
case Parameters::RECORD:
case Parameters::PREVIEW:
- mStreamingProcessor->stopStream();
+ res = stopStream();
+ if (res != OK) {
+ ALOGE("%s: Camera %d: Can't stop streaming: %s (%d)",
+ __FUNCTION__, mCameraId, strerror(-res), res);
+ }
res = mDevice->waitUntilDrained();
if (res != OK) {
ALOGE("%s: Camera %d: Waiting to stop streaming failed: %s (%d)",
diff --git a/services/camera/libcameraservice/Camera2Device.cpp b/services/camera/libcameraservice/Camera2Device.cpp
index 946cdba..77df152 100644
--- a/services/camera/libcameraservice/Camera2Device.cpp
+++ b/services/camera/libcameraservice/Camera2Device.cpp
@@ -1133,7 +1133,8 @@ cleanUpBuffers:
status_t Camera2Device::StreamAdapter::release() {
ATRACE_CALL();
status_t res;
- ALOGV("%s: Releasing stream %d", __FUNCTION__, mId);
+ ALOGV("%s: Releasing stream %d (%d x %d, format %d)", __FUNCTION__, mId,
+ mWidth, mHeight, mFormat);
if (mState >= ALLOCATED) {
res = mHal2Device->ops->release_stream(mHal2Device, mId);
if (res != OK) {
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 2db5224..cdeb92e 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -793,6 +793,7 @@ CameraService::Client::Client(const sp<CameraService>& cameraService,
// tear down the client
CameraService::Client::~Client() {
+ ALOGV("~Client");
mDestructionStarted = true;
mCameraService->releaseSound();
@@ -820,10 +821,12 @@ CameraService::BasicClient::BasicClient(const sp<CameraService>& cameraService,
}
CameraService::BasicClient::~BasicClient() {
+ ALOGV("~BasicClient");
mDestructionStarted = true;
}
void CameraService::BasicClient::disconnect() {
+ ALOGV("BasicClient::disconnect");
mCameraService->removeClientByRemote(mRemoteBinder);
// client shouldn't be able to call into us anymore
mClientPid = 0;
@@ -922,6 +925,7 @@ void CameraService::Client::notifyError() {
// NOTE: function is idempotent
void CameraService::Client::disconnect() {
+ ALOGV("Client::disconnect");
BasicClient::disconnect();
mCameraService->setCameraFree(mCameraId);
mCameraService->updateStatus(ICameraServiceListener::STATUS_PRESENT,
diff --git a/services/camera/libcameraservice/camera2/CallbackProcessor.cpp b/services/camera/libcameraservice/camera2/CallbackProcessor.cpp
index 30c14ef..dd37283 100644
--- a/services/camera/libcameraservice/camera2/CallbackProcessor.cpp
+++ b/services/camera/libcameraservice/camera2/CallbackProcessor.cpp
@@ -30,9 +30,11 @@
namespace android {
namespace camera2 {
-CallbackProcessor::CallbackProcessor(wp<Camera2Client> client):
+CallbackProcessor::CallbackProcessor(sp<Camera2Client> client):
Thread(false),
mClient(client),
+ mDevice(client->getCameraDevice()),
+ mId(client->getCameraId()),
mCallbackAvailable(false),
mCallbackStreamId(NO_STREAM) {
}
@@ -56,9 +58,11 @@ status_t CallbackProcessor::updateStream(const Parameters &params) {
Mutex::Autolock l(mInputMutex);
- sp<Camera2Client> client = mClient.promote();
- if (client == 0) return OK;
- sp<CameraDeviceBase> device = client->getCameraDevice();
+ sp<CameraDeviceBase> device = mDevice.promote();
+ if (device == 0) {
+ ALOGE("%s: Camera %d: Device does not exist", __FUNCTION__, mId);
+ return INVALID_OPERATION;
+ }
if (mCallbackConsumer == 0) {
// Create CPU buffer queue endpoint
@@ -76,7 +80,7 @@ status_t CallbackProcessor::updateStream(const Parameters &params) {
&currentWidth, &currentHeight, &currentFormat);
if (res != OK) {
ALOGE("%s: Camera %d: Error querying callback output stream info: "
- "%s (%d)", __FUNCTION__, client->getCameraId(),
+ "%s (%d)", __FUNCTION__, mId,
strerror(-res), res);
return res;
}
@@ -87,11 +91,11 @@ status_t CallbackProcessor::updateStream(const Parameters &params) {
// 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);
+ __FUNCTION__, mId, 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(),
+ "for callbacks: %s (%d)", __FUNCTION__, mId,
strerror(-res), res);
return res;
}
@@ -108,7 +112,7 @@ status_t CallbackProcessor::updateStream(const Parameters &params) {
params.previewFormat, 0, &mCallbackStreamId);
if (res != OK) {
ALOGE("%s: Camera %d: Can't create output stream for callbacks: "
- "%s (%d)", __FUNCTION__, client->getCameraId(),
+ "%s (%d)", __FUNCTION__, mId,
strerror(-res), res);
return res;
}
@@ -119,15 +123,24 @@ status_t CallbackProcessor::updateStream(const Parameters &params) {
status_t CallbackProcessor::deleteStream() {
ATRACE_CALL();
+ sp<CameraDeviceBase> device;
- Mutex::Autolock l(mInputMutex);
+ {
+ Mutex::Autolock l(mInputMutex);
- if (mCallbackStreamId != NO_STREAM) {
- sp<Camera2Client> client = mClient.promote();
- if (client == 0) return OK;
- sp<CameraDeviceBase> device = client->getCameraDevice();
+ if (mCallbackStreamId == NO_STREAM) {
+ return OK;
+ }
+ device = mDevice.promote();
+ if (device == 0) {
+ ALOGE("%s: Camera %d: Device does not exist", __FUNCTION__, mId);
+ return INVALID_OPERATION;
+ }
+ }
+ device->deleteStream(mCallbackStreamId);
- device->deleteStream(mCallbackStreamId);
+ {
+ Mutex::Autolock l(mInputMutex);
mCallbackHeap.clear();
mCallbackWindow.clear();
@@ -161,13 +174,32 @@ bool CallbackProcessor::threadLoop() {
do {
sp<Camera2Client> client = mClient.promote();
- if (client == 0) return false;
- res = processNewCallback(client);
+ if (client == 0) {
+ res = discardNewCallback();
+ } else {
+ res = processNewCallback(client);
+ }
} while (res == OK);
return true;
}
+status_t CallbackProcessor::discardNewCallback() {
+ ATRACE_CALL();
+ status_t res;
+ CpuConsumer::LockedBuffer imgBuffer;
+ res = mCallbackConsumer->lockNextBuffer(&imgBuffer);
+ if (res != OK) {
+ if (res != BAD_VALUE) {
+ ALOGE("%s: Camera %d: Error receiving next callback buffer: "
+ "%s (%d)", __FUNCTION__, mId, strerror(-res), res);
+ }
+ return res;
+ }
+ mCallbackConsumer->unlockBuffer(imgBuffer);
+ return OK;
+}
+
status_t CallbackProcessor::processNewCallback(sp<Camera2Client> &client) {
ATRACE_CALL();
status_t res;
@@ -181,12 +213,12 @@ status_t CallbackProcessor::processNewCallback(sp<Camera2Client> &client) {
if (res != OK) {
if (res != BAD_VALUE) {
ALOGE("%s: Camera %d: Error receiving next callback buffer: "
- "%s (%d)", __FUNCTION__, client->getCameraId(), strerror(-res), res);
+ "%s (%d)", __FUNCTION__, mId, strerror(-res), res);
}
return res;
}
ALOGV("%s: Camera %d: Preview callback available", __FUNCTION__,
- client->getCameraId());
+ mId);
{
SharedParameters::Lock l(client->getParameters());
@@ -195,7 +227,7 @@ status_t CallbackProcessor::processNewCallback(sp<Camera2Client> &client) {
&& l.mParameters.state != Parameters::RECORD
&& l.mParameters.state != Parameters::VIDEO_SNAPSHOT) {
ALOGV("%s: Camera %d: No longer streaming",
- __FUNCTION__, client->getCameraId());
+ __FUNCTION__, mId);
mCallbackConsumer->unlockBuffer(imgBuffer);
return OK;
}
@@ -216,7 +248,7 @@ status_t CallbackProcessor::processNewCallback(sp<Camera2Client> &client) {
if (imgBuffer.format != l.mParameters.previewFormat) {
ALOGE("%s: Camera %d: Unexpected format for callback: "
- "%x, expected %x", __FUNCTION__, client->getCameraId(),
+ "%x, expected %x", __FUNCTION__, mId,
imgBuffer.format, l.mParameters.previewFormat);
mCallbackConsumer->unlockBuffer(imgBuffer);
return INVALID_OPERATION;
@@ -241,7 +273,7 @@ status_t CallbackProcessor::processNewCallback(sp<Camera2Client> &client) {
"Camera2Client::CallbackHeap");
if (mCallbackHeap->mHeap->getSize() == 0) {
ALOGE("%s: Camera %d: Unable to allocate memory for callbacks",
- __FUNCTION__, client->getCameraId());
+ __FUNCTION__, mId);
mCallbackConsumer->unlockBuffer(imgBuffer);
return INVALID_OPERATION;
}
@@ -252,7 +284,7 @@ status_t CallbackProcessor::processNewCallback(sp<Camera2Client> &client) {
if (mCallbackHeapFree == 0) {
ALOGE("%s: Camera %d: No free callback buffers, dropping frame",
- __FUNCTION__, client->getCameraId());
+ __FUNCTION__, mId);
mCallbackConsumer->unlockBuffer(imgBuffer);
return OK;
}
@@ -282,7 +314,7 @@ status_t CallbackProcessor::processNewCallback(sp<Camera2Client> &client) {
l(client->mSharedCameraCallbacks);
if (l.mRemoteCallback != 0) {
ALOGV("%s: Camera %d: Invoking client data callback",
- __FUNCTION__, client->getCameraId());
+ __FUNCTION__, mId);
l.mRemoteCallback->dataCallback(CAMERA_MSG_PREVIEW_FRAME,
mCallbackHeap->mBuffers[heapIdx], NULL);
}
diff --git a/services/camera/libcameraservice/camera2/CallbackProcessor.h b/services/camera/libcameraservice/camera2/CallbackProcessor.h
index e68bb75..1c40a03 100644
--- a/services/camera/libcameraservice/camera2/CallbackProcessor.h
+++ b/services/camera/libcameraservice/camera2/CallbackProcessor.h
@@ -30,6 +30,7 @@
namespace android {
class Camera2Client;
+class CameraDeviceBase;
namespace camera2 {
@@ -39,7 +40,7 @@ namespace camera2 {
class CallbackProcessor:
public Thread, public CpuConsumer::FrameAvailableListener {
public:
- CallbackProcessor(wp<Camera2Client> client);
+ CallbackProcessor(sp<Camera2Client> client);
~CallbackProcessor();
void onFrameAvailable();
@@ -52,6 +53,8 @@ class CallbackProcessor:
private:
static const nsecs_t kWaitDuration = 10000000; // 10 ms
wp<Camera2Client> mClient;
+ wp<CameraDeviceBase> mDevice;
+ int mId;
mutable Mutex mInputMutex;
bool mCallbackAvailable;
@@ -72,7 +75,8 @@ class CallbackProcessor:
virtual bool threadLoop();
status_t processNewCallback(sp<Camera2Client> &client);
-
+ // Used when shutting down
+ status_t discardNewCallback();
};
diff --git a/services/camera/libcameraservice/camera2/JpegProcessor.cpp b/services/camera/libcameraservice/camera2/JpegProcessor.cpp
index 286fac4..01d7f9c 100644
--- a/services/camera/libcameraservice/camera2/JpegProcessor.cpp
+++ b/services/camera/libcameraservice/camera2/JpegProcessor.cpp
@@ -35,11 +35,12 @@ namespace android {
namespace camera2 {
JpegProcessor::JpegProcessor(
- wp<Camera2Client> client,
+ sp<Camera2Client> client,
wp<CaptureSequencer> sequencer):
Thread(false),
- mClient(client),
+ mDevice(client->getCameraDevice()),
mSequencer(sequencer),
+ mId(client->getCameraId()),
mCaptureAvailable(false),
mCaptureStreamId(NO_STREAM) {
}
@@ -64,16 +65,18 @@ status_t JpegProcessor::updateStream(const Parameters &params) {
Mutex::Autolock l(mInputMutex);
- sp<Camera2Client> client = mClient.promote();
- if (client == 0) return OK;
- sp<CameraDeviceBase> device = client->getCameraDevice();
+ sp<CameraDeviceBase> device = mDevice.promote();
+ if (device == 0) {
+ ALOGE("%s: Camera %d: Device does not exist", __FUNCTION__, mId);
+ return INVALID_OPERATION;
+ }
// Find out buffer size for JPEG
camera_metadata_ro_entry_t maxJpegSize =
params.staticInfo(ANDROID_JPEG_MAX_SIZE);
if (maxJpegSize.count == 0) {
ALOGE("%s: Camera %d: Can't find ANDROID_JPEG_MAX_SIZE!",
- __FUNCTION__, client->getCameraId());
+ __FUNCTION__, mId);
return INVALID_OPERATION;
}
@@ -89,7 +92,7 @@ status_t JpegProcessor::updateStream(const Parameters &params) {
"Camera2Client::CaptureHeap");
if (mCaptureHeap->getSize() == 0) {
ALOGE("%s: Camera %d: Unable to allocate memory for capture",
- __FUNCTION__, client->getCameraId());
+ __FUNCTION__, mId);
return NO_MEMORY;
}
}
@@ -102,18 +105,18 @@ status_t JpegProcessor::updateStream(const Parameters &params) {
if (res != OK) {
ALOGE("%s: Camera %d: Error querying capture output stream info: "
"%s (%d)", __FUNCTION__,
- client->getCameraId(), strerror(-res), res);
+ mId, strerror(-res), res);
return res;
}
if (currentWidth != (uint32_t)params.pictureWidth ||
currentHeight != (uint32_t)params.pictureHeight) {
ALOGV("%s: Camera %d: Deleting stream %d since the buffer dimensions changed",
- __FUNCTION__, client->getCameraId(), mCaptureStreamId);
+ __FUNCTION__, mId, mCaptureStreamId);
res = device->deleteStream(mCaptureStreamId);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to delete old output stream "
"for capture: %s (%d)", __FUNCTION__,
- client->getCameraId(), strerror(-res), res);
+ mId, strerror(-res), res);
return res;
}
mCaptureStreamId = NO_STREAM;
@@ -128,7 +131,7 @@ status_t JpegProcessor::updateStream(const Parameters &params) {
&mCaptureStreamId);
if (res != OK) {
ALOGE("%s: Camera %d: Can't create output stream for capture: "
- "%s (%d)", __FUNCTION__, client->getCameraId(),
+ "%s (%d)", __FUNCTION__, mId,
strerror(-res), res);
return res;
}
@@ -143,9 +146,11 @@ status_t JpegProcessor::deleteStream() {
Mutex::Autolock l(mInputMutex);
if (mCaptureStreamId != NO_STREAM) {
- sp<Camera2Client> client = mClient.promote();
- if (client == 0) return OK;
- sp<CameraDeviceBase> device = client->getCameraDevice();
+ sp<CameraDeviceBase> device = mDevice.promote();
+ if (device == 0) {
+ ALOGE("%s: Camera %d: Device does not exist", __FUNCTION__, mId);
+ return INVALID_OPERATION;
+ }
device->deleteStream(mCaptureStreamId);
@@ -180,15 +185,13 @@ bool JpegProcessor::threadLoop() {
}
do {
- sp<Camera2Client> client = mClient.promote();
- if (client == 0) return false;
- res = processNewCapture(client);
+ res = processNewCapture();
} while (res == OK);
return true;
}
-status_t JpegProcessor::processNewCapture(sp<Camera2Client> &client) {
+status_t JpegProcessor::processNewCapture() {
ATRACE_CALL();
status_t res;
sp<Camera2Heap> captureHeap;
@@ -200,17 +203,17 @@ status_t JpegProcessor::processNewCapture(sp<Camera2Client> &client) {
if (res != BAD_VALUE) {
ALOGE("%s: Camera %d: Error receiving still image buffer: "
"%s (%d)", __FUNCTION__,
- client->getCameraId(), strerror(-res), res);
+ mId, strerror(-res), res);
}
return res;
}
ALOGV("%s: Camera %d: Still capture available", __FUNCTION__,
- client->getCameraId());
+ mId);
if (imgBuffer.format != HAL_PIXEL_FORMAT_BLOB) {
ALOGE("%s: Camera %d: Unexpected format for still image: "
- "%x, expected %x", __FUNCTION__, client->getCameraId(),
+ "%x, expected %x", __FUNCTION__, mId,
imgBuffer.format,
HAL_PIXEL_FORMAT_BLOB);
mCaptureConsumer->unlockBuffer(imgBuffer);
diff --git a/services/camera/libcameraservice/camera2/JpegProcessor.h b/services/camera/libcameraservice/camera2/JpegProcessor.h
index 74f4738..a38611c 100644
--- a/services/camera/libcameraservice/camera2/JpegProcessor.h
+++ b/services/camera/libcameraservice/camera2/JpegProcessor.h
@@ -29,6 +29,7 @@
namespace android {
class Camera2Client;
+class CameraDeviceBase;
class MemoryHeapBase;
namespace camera2 {
@@ -41,7 +42,7 @@ class CaptureSequencer;
class JpegProcessor:
public Thread, public CpuConsumer::FrameAvailableListener {
public:
- JpegProcessor(wp<Camera2Client> client, wp<CaptureSequencer> sequencer);
+ JpegProcessor(sp<Camera2Client> client, wp<CaptureSequencer> sequencer);
~JpegProcessor();
// CpuConsumer listener implementation
@@ -54,8 +55,9 @@ class JpegProcessor:
void dump(int fd, const Vector<String16>& args) const;
private:
static const nsecs_t kWaitDuration = 10000000; // 10 ms
- wp<Camera2Client> mClient;
+ wp<CameraDeviceBase> mDevice;
wp<CaptureSequencer> mSequencer;
+ int mId;
mutable Mutex mInputMutex;
bool mCaptureAvailable;
@@ -72,7 +74,7 @@ class JpegProcessor:
virtual bool threadLoop();
- status_t processNewCapture(sp<Camera2Client> &client);
+ status_t processNewCapture();
size_t findJpegSize(uint8_t* jpegBuffer, size_t maxSize);
};
diff --git a/services/camera/libcameraservice/camera2/StreamingProcessor.cpp b/services/camera/libcameraservice/camera2/StreamingProcessor.cpp
index fbc5b93..c36cf87 100644
--- a/services/camera/libcameraservice/camera2/StreamingProcessor.cpp
+++ b/services/camera/libcameraservice/camera2/StreamingProcessor.cpp
@@ -31,8 +31,10 @@
namespace android {
namespace camera2 {
-StreamingProcessor::StreamingProcessor(wp<Camera2Client> client):
+StreamingProcessor::StreamingProcessor(sp<Camera2Client> client):
mClient(client),
+ mDevice(client->getCameraDevice()),
+ mId(client->getCameraId()),
mActiveRequest(NONE),
mPreviewRequestId(Camera2Client::kPreviewRequestIdStart),
mPreviewStreamId(NO_STREAM),
@@ -40,7 +42,6 @@ StreamingProcessor::StreamingProcessor(wp<Camera2Client> client):
mRecordingStreamId(NO_STREAM),
mRecordingHeapCount(kDefaultRecordingHeapCount)
{
-
}
StreamingProcessor::~StreamingProcessor() {
@@ -70,16 +71,19 @@ bool StreamingProcessor::haveValidPreviewWindow() const {
status_t StreamingProcessor::updatePreviewRequest(const Parameters &params) {
ATRACE_CALL();
status_t res;
- sp<Camera2Client> client = mClient.promote();
- if (client == 0) return INVALID_OPERATION;
+ sp<CameraDeviceBase> device = mDevice.promote();
+ if (device == 0) {
+ ALOGE("%s: Camera %d: Device does not exist", __FUNCTION__, mId);
+ return INVALID_OPERATION;
+ }
Mutex::Autolock m(mMutex);
if (mPreviewRequest.entryCount() == 0) {
- res = client->getCameraDevice()->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
+ res = device->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
&mPreviewRequest);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to create default preview request: "
- "%s (%d)", __FUNCTION__, client->getCameraId(), strerror(-res), res);
+ "%s (%d)", __FUNCTION__, mId, strerror(-res), res);
return res;
}
}
@@ -87,7 +91,7 @@ status_t StreamingProcessor::updatePreviewRequest(const Parameters &params) {
res = params.updateRequest(&mPreviewRequest);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to update common entries of preview "
- "request: %s (%d)", __FUNCTION__, client->getCameraId(),
+ "request: %s (%d)", __FUNCTION__, mId,
strerror(-res), res);
return res;
}
@@ -96,7 +100,7 @@ status_t StreamingProcessor::updatePreviewRequest(const Parameters &params) {
&mPreviewRequestId, 1);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to update request id for preview: %s (%d)",
- __FUNCTION__, client->getCameraId(), strerror(-res), res);
+ __FUNCTION__, mId, strerror(-res), res);
return res;
}
@@ -108,9 +112,11 @@ status_t StreamingProcessor::updatePreviewStream(const Parameters &params) {
Mutex::Autolock m(mMutex);
status_t res;
- sp<Camera2Client> client = mClient.promote();
- if (client == 0) return INVALID_OPERATION;
- sp<CameraDeviceBase> device = client->getCameraDevice();
+ sp<CameraDeviceBase> device = mDevice.promote();
+ if (device == 0) {
+ ALOGE("%s: Camera %d: Device does not exist", __FUNCTION__, mId);
+ return INVALID_OPERATION;
+ }
if (mPreviewStreamId != NO_STREAM) {
// Check if stream parameters have to change
@@ -119,24 +125,24 @@ status_t StreamingProcessor::updatePreviewStream(const Parameters &params) {
&currentWidth, &currentHeight, 0);
if (res != OK) {
ALOGE("%s: Camera %d: Error querying preview stream info: "
- "%s (%d)", __FUNCTION__, client->getCameraId(), strerror(-res), res);
+ "%s (%d)", __FUNCTION__, mId, strerror(-res), res);
return res;
}
if (currentWidth != (uint32_t)params.previewWidth ||
currentHeight != (uint32_t)params.previewHeight) {
ALOGV("%s: Camera %d: Preview size switch: %d x %d -> %d x %d",
- __FUNCTION__, client->getCameraId(), currentWidth, currentHeight,
+ __FUNCTION__, mId, currentWidth, currentHeight,
params.previewWidth, params.previewHeight);
res = device->waitUntilDrained();
if (res != OK) {
ALOGE("%s: Camera %d: Error waiting for preview to drain: "
- "%s (%d)", __FUNCTION__, client->getCameraId(), strerror(-res), res);
+ "%s (%d)", __FUNCTION__, mId, strerror(-res), res);
return res;
}
res = device->deleteStream(mPreviewStreamId);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to delete old output stream "
- "for preview: %s (%d)", __FUNCTION__, client->getCameraId(),
+ "for preview: %s (%d)", __FUNCTION__, mId,
strerror(-res), res);
return res;
}
@@ -151,7 +157,7 @@ status_t StreamingProcessor::updatePreviewStream(const Parameters &params) {
&mPreviewStreamId);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to create preview stream: %s (%d)",
- __FUNCTION__, client->getCameraId(), strerror(-res), res);
+ __FUNCTION__, mId, strerror(-res), res);
return res;
}
}
@@ -160,7 +166,7 @@ status_t StreamingProcessor::updatePreviewStream(const Parameters &params) {
params.previewTransform);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to set preview stream transform: "
- "%s (%d)", __FUNCTION__, client->getCameraId(), strerror(-res), res);
+ "%s (%d)", __FUNCTION__, mId, strerror(-res), res);
return res;
}
@@ -174,12 +180,14 @@ status_t StreamingProcessor::deletePreviewStream() {
Mutex::Autolock m(mMutex);
if (mPreviewStreamId != NO_STREAM) {
- sp<Camera2Client> client = mClient.promote();
- if (client == 0) return INVALID_OPERATION;
- sp<CameraDeviceBase> device = client->getCameraDevice();
+ sp<CameraDeviceBase> device = mDevice.promote();
+ if (device == 0) {
+ ALOGE("%s: Camera %d: Device does not exist", __FUNCTION__, mId);
+ return INVALID_OPERATION;
+ }
ALOGV("%s: for cameraId %d on streamId %d",
- __FUNCTION__, client->getCameraId(), mPreviewStreamId);
+ __FUNCTION__, mId, mPreviewStreamId);
res = device->waitUntilDrained();
if (res != OK) {
@@ -206,11 +214,9 @@ int StreamingProcessor::getPreviewStreamId() const {
status_t StreamingProcessor::setRecordingBufferCount(size_t count) {
ATRACE_CALL();
// 32 is the current upper limit on the video buffer count for BufferQueue
- sp<Camera2Client> client = mClient.promote();
- if (client == 0) return INVALID_OPERATION;
if (count > 32) {
ALOGE("%s: Camera %d: Error setting %d as video buffer count value",
- __FUNCTION__, client->getCameraId(), count);
+ __FUNCTION__, mId, count);
return BAD_VALUE;
}
@@ -233,15 +239,18 @@ status_t StreamingProcessor::updateRecordingRequest(const Parameters &params) {
status_t res;
Mutex::Autolock m(mMutex);
- sp<Camera2Client> client = mClient.promote();
- if (client == 0) return INVALID_OPERATION;
+ sp<CameraDeviceBase> device = mDevice.promote();
+ if (device == 0) {
+ ALOGE("%s: Camera %d: Device does not exist", __FUNCTION__, mId);
+ return INVALID_OPERATION;
+ }
if (mRecordingRequest.entryCount() == 0) {
- res = client->getCameraDevice()->createDefaultRequest(CAMERA2_TEMPLATE_VIDEO_RECORD,
+ res = device->createDefaultRequest(CAMERA2_TEMPLATE_VIDEO_RECORD,
&mRecordingRequest);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to create default recording request:"
- " %s (%d)", __FUNCTION__, client->getCameraId(), strerror(-res), res);
+ " %s (%d)", __FUNCTION__, mId, strerror(-res), res);
return res;
}
}
@@ -249,7 +258,7 @@ status_t StreamingProcessor::updateRecordingRequest(const Parameters &params) {
res = params.updateRequest(&mRecordingRequest);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to update common entries of recording "
- "request: %s (%d)", __FUNCTION__, client->getCameraId(),
+ "request: %s (%d)", __FUNCTION__, mId,
strerror(-res), res);
return res;
}
@@ -258,7 +267,7 @@ status_t StreamingProcessor::updateRecordingRequest(const Parameters &params) {
&mRecordingRequestId, 1);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to update request id for request: %s (%d)",
- __FUNCTION__, client->getCameraId(), strerror(-res), res);
+ __FUNCTION__, mId, strerror(-res), res);
return res;
}
@@ -270,9 +279,11 @@ status_t StreamingProcessor::updateRecordingStream(const Parameters &params) {
status_t res;
Mutex::Autolock m(mMutex);
- sp<Camera2Client> client = mClient.promote();
- if (client == 0) return INVALID_OPERATION;
- sp<CameraDeviceBase> device = client->getCameraDevice();
+ sp<CameraDeviceBase> device = mDevice.promote();
+ if (device == 0) {
+ ALOGE("%s: Camera %d: Device does not exist", __FUNCTION__, mId);
+ return INVALID_OPERATION;
+ }
if (mRecordingConsumer == 0) {
// Create CPU buffer queue endpoint. We need one more buffer here so that we can
@@ -296,7 +307,7 @@ status_t StreamingProcessor::updateRecordingStream(const Parameters &params) {
&currentWidth, &currentHeight, 0);
if (res != OK) {
ALOGE("%s: Camera %d: Error querying recording output stream info: "
- "%s (%d)", __FUNCTION__, client->getCameraId(),
+ "%s (%d)", __FUNCTION__, mId,
strerror(-res), res);
return res;
}
@@ -307,7 +318,7 @@ status_t StreamingProcessor::updateRecordingStream(const Parameters &params) {
if (res != OK) {
ALOGE("%s: Camera %d: Unable to delete old output stream "
"for recording: %s (%d)", __FUNCTION__,
- client->getCameraId(), strerror(-res), res);
+ mId, strerror(-res), res);
return res;
}
mRecordingStreamId = NO_STREAM;
@@ -321,7 +332,7 @@ status_t StreamingProcessor::updateRecordingStream(const Parameters &params) {
CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, 0, &mRecordingStreamId);
if (res != OK) {
ALOGE("%s: Camera %d: Can't create output stream for recording: "
- "%s (%d)", __FUNCTION__, client->getCameraId(),
+ "%s (%d)", __FUNCTION__, mId,
strerror(-res), res);
return res;
}
@@ -337,9 +348,11 @@ status_t StreamingProcessor::deleteRecordingStream() {
Mutex::Autolock m(mMutex);
if (mRecordingStreamId != NO_STREAM) {
- sp<Camera2Client> client = mClient.promote();
- if (client == 0) return INVALID_OPERATION;
- sp<CameraDeviceBase> device = client->getCameraDevice();
+ sp<CameraDeviceBase> device = mDevice.promote();
+ if (device == 0) {
+ ALOGE("%s: Camera %d: Device does not exist", __FUNCTION__, mId);
+ return INVALID_OPERATION;
+ }
res = device->waitUntilDrained();
if (res != OK) {
@@ -369,10 +382,13 @@ status_t StreamingProcessor::startStream(StreamType type,
if (type == NONE) return INVALID_OPERATION;
- sp<Camera2Client> client = mClient.promote();
- if (client == 0) return INVALID_OPERATION;
+ sp<CameraDeviceBase> device = mDevice.promote();
+ if (device == 0) {
+ ALOGE("%s: Camera %d: Device does not exist", __FUNCTION__, mId);
+ return INVALID_OPERATION;
+ }
- ALOGV("%s: Camera %d: type = %d", __FUNCTION__, client->getCameraId(), type);
+ ALOGV("%s: Camera %d: type = %d", __FUNCTION__, mId, type);
Mutex::Autolock m(mMutex);
@@ -384,22 +400,22 @@ status_t StreamingProcessor::startStream(StreamType type,
outputStreams);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to set up preview request: %s (%d)",
- __FUNCTION__, client->getCameraId(), strerror(-res), res);
+ __FUNCTION__, mId, strerror(-res), res);
return res;
}
res = request.sort();
if (res != OK) {
ALOGE("%s: Camera %d: Error sorting preview request: %s (%d)",
- __FUNCTION__, client->getCameraId(), strerror(-res), res);
+ __FUNCTION__, mId, strerror(-res), res);
return res;
}
- res = client->getCameraDevice()->setStreamingRequest(request);
+ res = device->setStreamingRequest(request);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to set preview request to start preview: "
"%s (%d)",
- __FUNCTION__, client->getCameraId(), strerror(-res), res);
+ __FUNCTION__, mId, strerror(-res), res);
return res;
}
mActiveRequest = type;
@@ -413,16 +429,19 @@ status_t StreamingProcessor::stopStream() {
Mutex::Autolock m(mMutex);
- sp<Camera2Client> client = mClient.promote();
- if (client == 0) return INVALID_OPERATION;
- sp<CameraDeviceBase> device = client->getCameraDevice();
+ sp<CameraDeviceBase> device = mDevice.promote();
+ if (device == 0) {
+ ALOGE("%s: Camera %d: Device does not exist", __FUNCTION__, mId);
+ return INVALID_OPERATION;
+ }
res = device->clearStreamingRequest();
if (res != OK) {
ALOGE("%s: Camera %d: Can't clear stream request: %s (%d)",
- __FUNCTION__, client->getCameraId(), strerror(-res), res);
+ __FUNCTION__, mId, strerror(-res), res);
return res;
}
+
mActiveRequest = NONE;
return OK;
@@ -466,7 +485,18 @@ void StreamingProcessor::onFrameAvailable() {
nsecs_t timestamp;
sp<Camera2Client> client = mClient.promote();
- if (client == 0) return;
+ if (client == 0) {
+ // Discard frames during shutdown
+ BufferItemConsumer::BufferItem imgBuffer;
+ res = mRecordingConsumer->acquireBuffer(&imgBuffer);
+ if (res != OK) {
+ ALOGE("%s: Camera %d: Error receiving recording buffer: %s (%d)",
+ __FUNCTION__, mId, strerror(-res), res);
+ return;
+ }
+ mRecordingConsumer->releaseBuffer(imgBuffer);
+ return;
+ }
{
/* acquire SharedParameters before mMutex so we don't dead lock
@@ -477,7 +507,7 @@ void StreamingProcessor::onFrameAvailable() {
res = mRecordingConsumer->acquireBuffer(&imgBuffer);
if (res != OK) {
ALOGE("%s: Camera %d: Error receiving recording buffer: %s (%d)",
- __FUNCTION__, client->getCameraId(), strerror(-res), res);
+ __FUNCTION__, mId, strerror(-res), res);
return;
}
timestamp = imgBuffer.mTimestamp;
@@ -490,7 +520,7 @@ void StreamingProcessor::onFrameAvailable() {
l.mParameters.state != Parameters::VIDEO_SNAPSHOT) {
ALOGV("%s: Camera %d: Discarding recording image buffers "
"received after recording done", __FUNCTION__,
- client->getCameraId());
+ mId);
mRecordingConsumer->releaseBuffer(imgBuffer);
return;
}
@@ -498,14 +528,14 @@ void StreamingProcessor::onFrameAvailable() {
if (mRecordingHeap == 0) {
const size_t bufferSize = 4 + sizeof(buffer_handle_t);
ALOGV("%s: Camera %d: Creating recording heap with %d buffers of "
- "size %d bytes", __FUNCTION__, client->getCameraId(),
+ "size %d bytes", __FUNCTION__, mId,
mRecordingHeapCount, bufferSize);
mRecordingHeap = new Camera2Heap(bufferSize, mRecordingHeapCount,
"Camera2Client::RecordingHeap");
if (mRecordingHeap->mHeap->getSize() == 0) {
ALOGE("%s: Camera %d: Unable to allocate memory for recording",
- __FUNCTION__, client->getCameraId());
+ __FUNCTION__, mId);
mRecordingConsumer->releaseBuffer(imgBuffer);
return;
}
@@ -513,7 +543,7 @@ void StreamingProcessor::onFrameAvailable() {
if (mRecordingBuffers[i].mBuf !=
BufferItemConsumer::INVALID_BUFFER_SLOT) {
ALOGE("%s: Camera %d: Non-empty recording buffers list!",
- __FUNCTION__, client->getCameraId());
+ __FUNCTION__, mId);
}
}
mRecordingBuffers.clear();
@@ -526,7 +556,7 @@ void StreamingProcessor::onFrameAvailable() {
if ( mRecordingHeapFree == 0) {
ALOGE("%s: Camera %d: No free recording buffers, dropping frame",
- __FUNCTION__, client->getCameraId());
+ __FUNCTION__, mId);
mRecordingConsumer->releaseBuffer(imgBuffer);
return;
}
@@ -536,7 +566,7 @@ void StreamingProcessor::onFrameAvailable() {
mRecordingHeapFree--;
ALOGV("%s: Camera %d: Timestamp %lld",
- __FUNCTION__, client->getCameraId(), timestamp);
+ __FUNCTION__, mId, timestamp);
ssize_t offset;
size_t size;
@@ -549,7 +579,7 @@ void StreamingProcessor::onFrameAvailable() {
*((uint32_t*)data) = type;
*((buffer_handle_t*)(data + 4)) = imgBuffer.mGraphicBuffer->handle;
ALOGV("%s: Camera %d: Sending out buffer_handle_t %p",
- __FUNCTION__, client->getCameraId(),
+ __FUNCTION__, mId,
imgBuffer.mGraphicBuffer->handle);
mRecordingBuffers.replaceAt(imgBuffer, heapIdx);
recordingHeap = mRecordingHeap;
@@ -568,9 +598,6 @@ void StreamingProcessor::releaseRecordingFrame(const sp<IMemory>& mem) {
ATRACE_CALL();
status_t res;
- sp<Camera2Client> client = mClient.promote();
- if (client == 0) return;
-
Mutex::Autolock m(mMutex);
// Make sure this is for the current heap
ssize_t offset;
@@ -578,7 +605,7 @@ void StreamingProcessor::releaseRecordingFrame(const sp<IMemory>& mem) {
sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
if (heap->getHeapID() != mRecordingHeap->mHeap->getHeapID()) {
ALOGW("%s: Camera %d: Mismatched heap ID, ignoring release "
- "(got %x, expected %x)", __FUNCTION__, client->getCameraId(),
+ "(got %x, expected %x)", __FUNCTION__, mId,
heap->getHeapID(), mRecordingHeap->mHeap->getHeapID());
return;
}
@@ -586,7 +613,7 @@ void StreamingProcessor::releaseRecordingFrame(const sp<IMemory>& mem) {
uint32_t type = *(uint32_t*)data;
if (type != kMetadataBufferTypeGrallocSource) {
ALOGE("%s: Camera %d: Recording frame type invalid (got %x, expected %x)",
- __FUNCTION__, client->getCameraId(), type,
+ __FUNCTION__, mId, type,
kMetadataBufferTypeGrallocSource);
return;
}
@@ -606,19 +633,19 @@ void StreamingProcessor::releaseRecordingFrame(const sp<IMemory>& mem) {
}
if (itemIndex == mRecordingBuffers.size()) {
ALOGE("%s: Camera %d: Can't find buffer_handle_t %p in list of "
- "outstanding buffers", __FUNCTION__, client->getCameraId(),
+ "outstanding buffers", __FUNCTION__, mId,
imgHandle);
return;
}
ALOGV("%s: Camera %d: Freeing buffer_handle_t %p", __FUNCTION__,
- client->getCameraId(), imgHandle);
+ mId, imgHandle);
res = mRecordingConsumer->releaseBuffer(mRecordingBuffers[itemIndex]);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to free recording frame "
"(buffer_handle_t: %p): %s (%d)", __FUNCTION__,
- client->getCameraId(), imgHandle, strerror(-res), res);
+ mId, imgHandle, strerror(-res), res);
return;
}
mRecordingBuffers.replaceAt(itemIndex);
diff --git a/services/camera/libcameraservice/camera2/StreamingProcessor.h b/services/camera/libcameraservice/camera2/StreamingProcessor.h
index e5732ad..643114e 100644
--- a/services/camera/libcameraservice/camera2/StreamingProcessor.h
+++ b/services/camera/libcameraservice/camera2/StreamingProcessor.h
@@ -27,6 +27,7 @@
namespace android {
class Camera2Client;
+class CameraDeviceBase;
class IMemory;
namespace camera2 {
@@ -38,7 +39,7 @@ class Camera2Heap;
*/
class StreamingProcessor: public BufferItemConsumer::FrameAvailableListener {
public:
- StreamingProcessor(wp<Camera2Client> client);
+ StreamingProcessor(sp<Camera2Client> client);
~StreamingProcessor();
status_t setPreviewWindow(sp<ANativeWindow> window);
@@ -86,6 +87,8 @@ class StreamingProcessor: public BufferItemConsumer::FrameAvailableListener {
};
wp<Camera2Client> mClient;
+ wp<CameraDeviceBase> mDevice;
+ int mId;
StreamType mActiveRequest;
diff --git a/services/camera/libcameraservice/camera2/ZslProcessor.cpp b/services/camera/libcameraservice/camera2/ZslProcessor.cpp
index 769d9bd..2c12fb0 100644
--- a/services/camera/libcameraservice/camera2/ZslProcessor.cpp
+++ b/services/camera/libcameraservice/camera2/ZslProcessor.cpp
@@ -38,12 +38,14 @@ namespace android {
namespace camera2 {
ZslProcessor::ZslProcessor(
- wp<Camera2Client> client,
+ sp<Camera2Client> client,
wp<CaptureSequencer> sequencer):
Thread(false),
mState(RUNNING),
mClient(client),
+ mDevice(client->getCameraDevice()),
mSequencer(sequencer),
+ mId(client->getCameraId()),
mZslBufferAvailable(false),
mZslStreamId(NO_STREAM),
mZslReprocessStreamId(NO_STREAM),
@@ -69,7 +71,8 @@ void ZslProcessor::onFrameAvailable() {
}
}
-void ZslProcessor::onFrameAvailable(int32_t /*frameId*/, const CameraMetadata &frame) {
+void ZslProcessor::onFrameAvailable(int32_t /*frameId*/,
+ const CameraMetadata &frame) {
Mutex::Autolock l(mInputMutex);
camera_metadata_ro_entry_t entry;
entry = frame.find(ANDROID_SENSOR_TIMESTAMP);
@@ -113,8 +116,15 @@ status_t ZslProcessor::updateStream(const Parameters &params) {
Mutex::Autolock l(mInputMutex);
sp<Camera2Client> client = mClient.promote();
- if (client == 0) return OK;
- sp<CameraDeviceBase> device = client->getCameraDevice();
+ if (client == 0) {
+ ALOGE("%s: Camera %d: Client does not exist", __FUNCTION__, mId);
+ return INVALID_OPERATION;
+ }
+ sp<CameraDeviceBase> device = mDevice.promote();
+ if (device == 0) {
+ ALOGE("%s: Camera %d: Device does not exist", __FUNCTION__, mId);
+ return INVALID_OPERATION;
+ }
if (mZslConsumer == 0) {
// Create CPU buffer queue endpoint
@@ -136,7 +146,7 @@ status_t ZslProcessor::updateStream(const Parameters &params) {
if (res != OK) {
ALOGE("%s: Camera %d: Error querying capture output stream info: "
"%s (%d)", __FUNCTION__,
- client->getCameraId(), strerror(-res), res);
+ mId, strerror(-res), res);
return res;
}
if (currentWidth != (uint32_t)params.fastInfo.arrayWidth ||
@@ -145,16 +155,16 @@ status_t ZslProcessor::updateStream(const Parameters &params) {
if (res != OK) {
ALOGE("%s: Camera %d: Unable to delete old reprocess stream "
"for ZSL: %s (%d)", __FUNCTION__,
- client->getCameraId(), strerror(-res), res);
+ mId, strerror(-res), res);
return res;
}
ALOGV("%s: Camera %d: Deleting stream %d since the buffer dimensions changed",
- __FUNCTION__, client->getCameraId(), mZslStreamId);
+ __FUNCTION__, mId, mZslStreamId);
res = device->deleteStream(mZslStreamId);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to delete old output stream "
"for ZSL: %s (%d)", __FUNCTION__,
- client->getCameraId(), strerror(-res), res);
+ mId, strerror(-res), res);
return res;
}
mZslStreamId = NO_STREAM;
@@ -173,7 +183,7 @@ status_t ZslProcessor::updateStream(const Parameters &params) {
&mZslStreamId);
if (res != OK) {
ALOGE("%s: Camera %d: Can't create output stream for ZSL: "
- "%s (%d)", __FUNCTION__, client->getCameraId(),
+ "%s (%d)", __FUNCTION__, mId,
strerror(-res), res);
return res;
}
@@ -181,7 +191,7 @@ status_t ZslProcessor::updateStream(const Parameters &params) {
&mZslReprocessStreamId);
if (res != OK) {
ALOGE("%s: Camera %d: Can't create reprocess stream for ZSL: "
- "%s (%d)", __FUNCTION__, client->getCameraId(),
+ "%s (%d)", __FUNCTION__, mId,
strerror(-res), res);
return res;
}
@@ -200,14 +210,18 @@ status_t ZslProcessor::deleteStream() {
Mutex::Autolock l(mInputMutex);
if (mZslStreamId != NO_STREAM) {
- sp<Camera2Client> client = mClient.promote();
- if (client == 0) return OK;
- sp<CameraDeviceBase> device = client->getCameraDevice();
+ sp<CameraDeviceBase> device = mDevice.promote();
+ if (device == 0) {
+ ALOGE("%s: Camera %d: Device does not exist", __FUNCTION__, mId);
+ return INVALID_OPERATION;
+ }
+
+ clearZslQueueLocked();
res = device->deleteReprocessStream(mZslReprocessStreamId);
if (res != OK) {
ALOGE("%s: Camera %d: Cannot delete ZSL reprocessing stream %d: "
- "%s (%d)", __FUNCTION__, client->getCameraId(),
+ "%s (%d)", __FUNCTION__, mId,
mZslReprocessStreamId, strerror(-res), res);
return res;
}
@@ -216,7 +230,7 @@ status_t ZslProcessor::deleteStream() {
res = device->deleteStream(mZslStreamId);
if (res != OK) {
ALOGE("%s: Camera %d: Cannot delete ZSL output stream %d: "
- "%s (%d)", __FUNCTION__, client->getCameraId(),
+ "%s (%d)", __FUNCTION__, mId,
mZslStreamId, strerror(-res), res);
return res;
}
@@ -246,7 +260,10 @@ status_t ZslProcessor::pushToReprocess(int32_t requestId) {
status_t res;
sp<Camera2Client> client = mClient.promote();
- if (client == 0) return INVALID_OPERATION;
+ if (client == 0) {
+ ALOGE("%s: Camera %d: Client does not exist", __FUNCTION__, mId);
+ return INVALID_OPERATION;
+ }
IF_ALOGV() {
dumpZslQueue(-1);
@@ -309,7 +326,7 @@ status_t ZslProcessor::pushToReprocess(int32_t requestId) {
if (res != OK) {
ALOGE("%s: Camera %d: Unable to stop preview for ZSL capture: "
"%s (%d)",
- __FUNCTION__, client->getCameraId(), strerror(-res), res);
+ __FUNCTION__, mId, strerror(-res), res);
return INVALID_OPERATION;
}
// TODO: have push-and-clear be atomic
@@ -328,7 +345,7 @@ status_t ZslProcessor::pushToReprocess(int32_t requestId) {
if (res != OK) {
ALOGE("%s: Camera %d: Unable to update JPEG entries of ZSL "
"capture request: %s (%d)", __FUNCTION__,
- client->getCameraId(),
+ mId,
strerror(-res), res);
return res;
}
@@ -397,26 +414,29 @@ bool ZslProcessor::threadLoop() {
}
do {
- sp<Camera2Client> client = mClient.promote();
- if (client == 0) return false;
- res = processNewZslBuffer(client);
+ res = processNewZslBuffer();
} while (res == OK);
return true;
}
-status_t ZslProcessor::processNewZslBuffer(sp<Camera2Client> &client) {
+status_t ZslProcessor::processNewZslBuffer() {
ATRACE_CALL();
status_t res;
-
+ sp<BufferItemConsumer> zslConsumer;
+ {
+ Mutex::Autolock l(mInputMutex);
+ if (mZslConsumer == 0) return OK;
+ zslConsumer = mZslConsumer;
+ }
ALOGVV("Trying to get next buffer");
BufferItemConsumer::BufferItem item;
- res = mZslConsumer->acquireBuffer(&item);
+ res = zslConsumer->acquireBuffer(&item);
if (res != OK) {
if (res != BufferItemConsumer::NO_BUFFER_AVAILABLE) {
ALOGE("%s: Camera %d: Error receiving ZSL image buffer: "
"%s (%d)", __FUNCTION__,
- client->getCameraId(), strerror(-res), res);
+ mId, strerror(-res), res);
} else {
ALOGVV(" No buffer");
}
@@ -427,7 +447,7 @@ status_t ZslProcessor::processNewZslBuffer(sp<Camera2Client> &client) {
if (mState == LOCKED) {
ALOGVV("In capture, discarding new ZSL buffers");
- mZslConsumer->releaseBuffer(item);
+ zslConsumer->releaseBuffer(item);
return OK;
}
@@ -435,7 +455,7 @@ status_t ZslProcessor::processNewZslBuffer(sp<Camera2Client> &client) {
if ( (mZslQueueHead + 1) % kZslBufferDepth == mZslQueueTail) {
ALOGVV("Releasing oldest buffer");
- mZslConsumer->releaseBuffer(mZslQueue[mZslQueueTail].buffer);
+ zslConsumer->releaseBuffer(mZslQueue[mZslQueueTail].buffer);
mZslQueue.replaceAt(mZslQueueTail);
mZslQueueTail = (mZslQueueTail + 1) % kZslBufferDepth;
}
diff --git a/services/camera/libcameraservice/camera2/ZslProcessor.h b/services/camera/libcameraservice/camera2/ZslProcessor.h
index b2cf5b1..ee3bcd6 100644
--- a/services/camera/libcameraservice/camera2/ZslProcessor.h
+++ b/services/camera/libcameraservice/camera2/ZslProcessor.h
@@ -46,7 +46,7 @@ class ZslProcessor:
virtual public FrameProcessor::FilteredListener,
virtual public CameraDeviceBase::BufferReleasedListener {
public:
- ZslProcessor(wp<Camera2Client> client, wp<CaptureSequencer> sequencer);
+ ZslProcessor(sp<Camera2Client> client, wp<CaptureSequencer> sequencer);
~ZslProcessor();
// From mZslConsumer
@@ -74,7 +74,9 @@ class ZslProcessor:
} mState;
wp<Camera2Client> mClient;
+ wp<CameraDeviceBase> mDevice;
wp<CaptureSequencer> mSequencer;
+ int mId;
mutable Mutex mInputMutex;
bool mZslBufferAvailable;
@@ -109,7 +111,7 @@ class ZslProcessor:
virtual bool threadLoop();
- status_t processNewZslBuffer(sp<Camera2Client> &client);
+ status_t processNewZslBuffer();
// Match up entries from frame list to buffers in ZSL queue
void findMatchesLocked();