summaryrefslogtreecommitdiffstats
path: root/services/camera/libcameraservice/Camera2Client.cpp
diff options
context:
space:
mode:
authorEino-Ville Talvala <etalvala@google.com>2012-08-28 01:25:43 -0700
committerEino-Ville Talvala <etalvala@google.com>2012-08-30 09:50:41 -0700
commitea0d51b5ed0b474433b02414f9133b835f972569 (patch)
tree66b873f5a3c2834a54a2ec16018bc6b6d2505206 /services/camera/libcameraservice/Camera2Client.cpp
parent6524b7e1e6aae7dc1fe650119ec4bcf96b5a3f6b (diff)
downloadframeworks_av-ea0d51b5ed0b474433b02414f9133b835f972569.zip
frameworks_av-ea0d51b5ed0b474433b02414f9133b835f972569.tar.gz
frameworks_av-ea0d51b5ed0b474433b02414f9133b835f972569.tar.bz2
Camera2: Move still capture processing to separate thread.
To avoid stalling HAL when it queues up new buffers for still capture, process still captures in a separate thread. Also move Camera2Heap to its own class so it can be used by the CaptureProcessor. Bug: 6243944 Change-Id: Id38e2a52367c0985812fcd4fd9af3ef90beef43f
Diffstat (limited to 'services/camera/libcameraservice/Camera2Client.cpp')
-rw-r--r--services/camera/libcameraservice/Camera2Client.cpp175
1 files changed, 25 insertions, 150 deletions
diff --git a/services/camera/libcameraservice/Camera2Client.cpp b/services/camera/libcameraservice/Camera2Client.cpp
index 4edb49f..d296445 100644
--- a/services/camera/libcameraservice/Camera2Client.cpp
+++ b/services/camera/libcameraservice/Camera2Client.cpp
@@ -52,11 +52,11 @@ Camera2Client::Camera2Client(const sp<CameraService>& cameraService,
int clientPid):
Client(cameraService, cameraClient,
cameraId, cameraFacing, clientPid),
+ mSharedCameraClient(cameraClient),
mParameters(cameraId, cameraFacing),
mPreviewStreamId(NO_STREAM),
mCallbackStreamId(NO_STREAM),
mCallbackHeapId(0),
- mCaptureStreamId(NO_STREAM),
mRecordingStreamId(NO_STREAM),
mRecordingHeapCount(kDefaultRecordingHeapCount)
{
@@ -84,11 +84,6 @@ status_t Camera2Client::initialize(camera_module_t *module)
ALOGV("%s: Initializing client for camera %d", __FUNCTION__, mCameraId);
status_t res;
- mFrameProcessor = new FrameProcessor(this);
- String8 frameThreadName = String8::format("Camera2Client[%d]::FrameProcessor",
- mCameraId);
- mFrameProcessor->run(frameThreadName.string());
-
res = mDevice->initialize(module);
if (res != OK) {
ALOGE("%s: Camera %d: unable to initialize device: %s (%d)",
@@ -107,6 +102,16 @@ status_t Camera2Client::initialize(camera_module_t *module)
return NO_INIT;
}
+ mFrameProcessor = new FrameProcessor(this);
+ String8 frameThreadName = String8::format("Camera2Client[%d]::FrameProcessor",
+ mCameraId);
+ mFrameProcessor->run(frameThreadName.string());
+
+ mCaptureProcessor = new CaptureProcessor(this);
+ String8 captureThreadName =
+ String8::format("Camera2Client[%d]::CaptureProcessor", mCameraId);
+ mCaptureProcessor->run(captureThreadName.string());
+
if (gLogLevel >= 1) {
ALOGD("%s: Default parameters converted from camera %d:", __FUNCTION__,
mCameraId);
@@ -292,7 +297,8 @@ status_t Camera2Client::dump(int fd, const Vector<String16>& args) {
result.append(" Current streams:\n");
result.appendFormat(" Preview stream ID: %d\n", mPreviewStreamId);
- result.appendFormat(" Capture stream ID: %d\n", mCaptureStreamId);
+ result.appendFormat(" Capture stream ID: %d\n",
+ mCaptureProcessor->getStreamId());
result.appendFormat(" Recording stream ID: %d\n", mRecordingStreamId);
result.append(" Current requests:\n");
@@ -357,10 +363,7 @@ void Camera2Client::disconnect() {
mPreviewStreamId = NO_STREAM;
}
- if (mCaptureStreamId != NO_STREAM) {
- mDevice->deleteStream(mCaptureStreamId);
- mCaptureStreamId = NO_STREAM;
- }
+ mCaptureProcessor->deleteStream();
if (mRecordingStreamId != NO_STREAM) {
mDevice->deleteStream(mRecordingStreamId);
@@ -1028,7 +1031,7 @@ status_t Camera2Client::takePicture(int msgType) {
ALOGV("%s: Camera %d: Starting picture capture", __FUNCTION__, mCameraId);
- res = updateCaptureStream(l.mParameters);
+ res = mCaptureProcessor->updateStream(l.mParameters);
if (res != OK) {
ALOGE("%s: Camera %d: Can't set up still image stream: %s (%d)",
__FUNCTION__, mCameraId, strerror(-res), res);
@@ -1048,32 +1051,34 @@ status_t Camera2Client::takePicture(int msgType) {
CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK;
bool recordingEnabled = (l.mParameters.state == Parameters::RECORD);
+ int captureStreamId = mCaptureProcessor->getStreamId();
+
int streamSwitch = (callbacksEnabled ? 0x2 : 0x0) +
(recordingEnabled ? 0x1 : 0x0);
switch ( streamSwitch ) {
case 0: { // No recording, callbacks
- uint8_t streamIds[2] = { mPreviewStreamId, mCaptureStreamId };
+ uint8_t streamIds[2] = { mPreviewStreamId, captureStreamId };
res = mCaptureRequest.update(ANDROID_REQUEST_OUTPUT_STREAMS,
streamIds, 2);
break;
}
case 1: { // Recording
uint8_t streamIds[3] = { mPreviewStreamId, mRecordingStreamId,
- mCaptureStreamId };
+ captureStreamId };
res = mCaptureRequest.update(ANDROID_REQUEST_OUTPUT_STREAMS,
streamIds, 3);
break;
}
case 2: { // Callbacks
uint8_t streamIds[3] = { mPreviewStreamId, mCallbackStreamId,
- mCaptureStreamId };
+ captureStreamId };
res = mCaptureRequest.update(ANDROID_REQUEST_OUTPUT_STREAMS,
streamIds, 3);
break;
}
case 3: { // Both
uint8_t streamIds[4] = { mPreviewStreamId, mCallbackStreamId,
- mRecordingStreamId, mCaptureStreamId };
+ mRecordingStreamId, captureStreamId };
res = mCaptureRequest.update(ANDROID_REQUEST_OUTPUT_STREAMS,
streamIds, 4);
break;
@@ -1511,6 +1516,10 @@ Camera2Client::SharedCameraClient::Lock::~Lock() {
mSharedClient.mCameraClientLock.unlock();
}
+Camera2Client::SharedCameraClient::SharedCameraClient(const sp<ICameraClient>&client):
+ mCameraClient(client) {
+}
+
Camera2Client::SharedCameraClient& Camera2Client::SharedCameraClient::operator=(
const sp<ICameraClient>&client) {
Mutex::Autolock l(mCameraClientLock);
@@ -1650,71 +1659,6 @@ void Camera2Client::onCallbackAvailable() {
ALOGV("%s: exit", __FUNCTION__);
}
-void Camera2Client::onCaptureAvailable() {
- ATRACE_CALL();
- status_t res;
- sp<Camera2Heap> captureHeap;
- ALOGV("%s: Camera %d: Still capture available", __FUNCTION__, mCameraId);
-
- {
- SharedParameters::Lock l(mParameters);
- CpuConsumer::LockedBuffer imgBuffer;
-
- res = mCaptureConsumer->lockNextBuffer(&imgBuffer);
- if (res != OK) {
- ALOGE("%s: Camera %d: Error receiving still image buffer: %s (%d)",
- __FUNCTION__, mCameraId, strerror(-res), res);
- return;
- }
-
- // TODO: Signal errors here upstream
- if (l.mParameters.state != Parameters::STILL_CAPTURE &&
- l.mParameters.state != Parameters::VIDEO_SNAPSHOT) {
- ALOGE("%s: Camera %d: Still image produced unexpectedly!",
- __FUNCTION__, mCameraId);
- mCaptureConsumer->unlockBuffer(imgBuffer);
- return;
- }
-
- if (imgBuffer.format != HAL_PIXEL_FORMAT_BLOB) {
- ALOGE("%s: Camera %d: Unexpected format for still image: "
- "%x, expected %x", __FUNCTION__, mCameraId,
- imgBuffer.format,
- HAL_PIXEL_FORMAT_BLOB);
- mCaptureConsumer->unlockBuffer(imgBuffer);
- return;
- }
-
- // TODO: Optimize this to avoid memcopy
- void* captureMemory = mCaptureHeap->mHeap->getBase();
- size_t size = mCaptureHeap->mHeap->getSize();
- memcpy(captureMemory, imgBuffer.data, size);
-
- mCaptureConsumer->unlockBuffer(imgBuffer);
-
- switch (l.mParameters.state) {
- case Parameters::STILL_CAPTURE:
- l.mParameters.state = Parameters::STOPPED;
- break;
- case Parameters::VIDEO_SNAPSHOT:
- l.mParameters.state = Parameters::RECORD;
- break;
- default:
- ALOGE("%s: Camera %d: Unexpected state %d", __FUNCTION__,
- mCameraId, l.mParameters.state);
- break;
- }
-
- captureHeap = mCaptureHeap;
- }
- // Call outside parameter locks to allow re-entrancy from notification
- SharedCameraClient::Lock l(mSharedCameraClient);
- if (l.mCameraClient != 0) {
- l.mCameraClient->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE,
- captureHeap->mBuffers[0], NULL);
- }
-}
-
void Camera2Client::onRecordingFrameAvailable() {
ATRACE_CALL();
status_t res;
@@ -1998,75 +1942,6 @@ status_t Camera2Client::updateCallbackStream(const Parameters &params) {
return OK;
}
-
-status_t Camera2Client::updateCaptureStream(const Parameters &params) {
- ATRACE_CALL();
- status_t res;
- // Find out buffer size for JPEG
- camera_metadata_ro_entry_t maxJpegSize =
- mParameters.staticInfo(ANDROID_JPEG_MAX_SIZE);
- if (maxJpegSize.count == 0) {
- ALOGE("%s: Camera %d: Can't find ANDROID_JPEG_MAX_SIZE!",
- __FUNCTION__, mCameraId);
- return INVALID_OPERATION;
- }
-
- if (mCaptureConsumer == 0) {
- // Create CPU buffer queue endpoint
- mCaptureConsumer = new CpuConsumer(1);
- mCaptureConsumer->setFrameAvailableListener(new CaptureWaiter(this));
- mCaptureConsumer->setName(String8("Camera2Client::CaptureConsumer"));
- mCaptureWindow = new SurfaceTextureClient(
- mCaptureConsumer->getProducerInterface());
- // Create memory for API consumption
- mCaptureHeap = new Camera2Heap(maxJpegSize.data.i32[0], 1,
- "Camera2Client::CaptureHeap");
- if (mCaptureHeap->mHeap->getSize() == 0) {
- ALOGE("%s: Camera %d: Unable to allocate memory for capture",
- __FUNCTION__, mCameraId);
- return NO_MEMORY;
- }
- }
-
- if (mCaptureStreamId != NO_STREAM) {
- // Check if stream parameters have to change
- uint32_t currentWidth, currentHeight;
- res = mDevice->getStreamInfo(mCaptureStreamId,
- &currentWidth, &currentHeight, 0);
- if (res != OK) {
- ALOGE("%s: Camera %d: Error querying capture output stream info: "
- "%s (%d)", __FUNCTION__, mCameraId, strerror(-res), res);
- return res;
- }
- if (currentWidth != (uint32_t)params.pictureWidth ||
- currentHeight != (uint32_t)params.pictureHeight) {
- res = mDevice->deleteStream(mCaptureStreamId);
- if (res != OK) {
- ALOGE("%s: Camera %d: Unable to delete old output stream "
- "for capture: %s (%d)", __FUNCTION__, mCameraId,
- strerror(-res), res);
- return res;
- }
- mCaptureStreamId = NO_STREAM;
- }
- }
-
- if (mCaptureStreamId == NO_STREAM) {
- // Create stream for HAL production
- res = mDevice->createStream(mCaptureWindow,
- params.pictureWidth, params.pictureHeight,
- HAL_PIXEL_FORMAT_BLOB, maxJpegSize.data.i32[0],
- &mCaptureStreamId);
- if (res != OK) {
- ALOGE("%s: Camera %d: Can't create output stream for capture: "
- "%s (%d)", __FUNCTION__, mCameraId, strerror(-res), res);
- return res;
- }
-
- }
- return OK;
-}
-
status_t Camera2Client::updateCaptureRequest(const Parameters &params) {
ATRACE_CALL();
status_t res;