diff options
author | Eino-Ville Talvala <etalvala@google.com> | 2012-08-28 01:25:43 -0700 |
---|---|---|
committer | Eino-Ville Talvala <etalvala@google.com> | 2012-08-30 09:50:41 -0700 |
commit | ea0d51b5ed0b474433b02414f9133b835f972569 (patch) | |
tree | 66b873f5a3c2834a54a2ec16018bc6b6d2505206 /services/camera/libcameraservice/Camera2Client.cpp | |
parent | 6524b7e1e6aae7dc1fe650119ec4bcf96b5a3f6b (diff) | |
download | frameworks_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.cpp | 175 |
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 ¶ms) { return OK; } - -status_t Camera2Client::updateCaptureStream(const Parameters ¶ms) { - 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, - ¤tWidth, ¤tHeight, 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 ¶ms) { ATRACE_CALL(); status_t res; |