Merge "Implement the source->sink(!) keep alive the wfd specs mandate..." into jb-mr1-dev
diff --git a/services/audioflinger/AudioBufferProvider.h b/include/media/AudioBufferProvider.h
similarity index 100%
rename from services/audioflinger/AudioBufferProvider.h
rename to include/media/AudioBufferProvider.h
diff --git a/services/audioflinger/ExtendedAudioBufferProvider.h b/include/media/ExtendedAudioBufferProvider.h
similarity index 95%
rename from services/audioflinger/ExtendedAudioBufferProvider.h
rename to include/media/ExtendedAudioBufferProvider.h
index 88279b4..00c4444 100644
--- a/services/audioflinger/ExtendedAudioBufferProvider.h
+++ b/include/media/ExtendedAudioBufferProvider.h
@@ -17,7 +17,7 @@
#ifndef ANDROID_EXTENDED_AUDIO_BUFFER_PROVIDER_H
#define ANDROID_EXTENDED_AUDIO_BUFFER_PROVIDER_H
-#include "AudioBufferProvider.h"
+#include <media/AudioBufferProvider.h>
namespace android {
diff --git a/services/audioflinger/AudioBufferProviderSource.h b/include/media/nbaio/AudioBufferProviderSource.h
similarity index 97%
rename from services/audioflinger/AudioBufferProviderSource.h
rename to include/media/nbaio/AudioBufferProviderSource.h
index 1435a84..2c4aaff 100644
--- a/services/audioflinger/AudioBufferProviderSource.h
+++ b/include/media/nbaio/AudioBufferProviderSource.h
@@ -20,7 +20,7 @@
#define ANDROID_AUDIO_BUFFER_PROVIDER_SOURCE_H
#include "NBAIO.h"
-#include "AudioBufferProvider.h"
+#include <media/AudioBufferProvider.h>
namespace android {
diff --git a/services/audioflinger/AudioStreamInSource.h b/include/media/nbaio/AudioStreamInSource.h
similarity index 100%
rename from services/audioflinger/AudioStreamInSource.h
rename to include/media/nbaio/AudioStreamInSource.h
diff --git a/services/audioflinger/AudioStreamOutSink.h b/include/media/nbaio/AudioStreamOutSink.h
similarity index 100%
rename from services/audioflinger/AudioStreamOutSink.h
rename to include/media/nbaio/AudioStreamOutSink.h
diff --git a/services/audioflinger/LibsndfileSink.h b/include/media/nbaio/LibsndfileSink.h
similarity index 100%
rename from services/audioflinger/LibsndfileSink.h
rename to include/media/nbaio/LibsndfileSink.h
diff --git a/services/audioflinger/LibsndfileSource.h b/include/media/nbaio/LibsndfileSource.h
similarity index 100%
rename from services/audioflinger/LibsndfileSource.h
rename to include/media/nbaio/LibsndfileSource.h
diff --git a/services/audioflinger/MonoPipe.h b/include/media/nbaio/MonoPipe.h
similarity index 100%
rename from services/audioflinger/MonoPipe.h
rename to include/media/nbaio/MonoPipe.h
diff --git a/services/audioflinger/MonoPipeReader.h b/include/media/nbaio/MonoPipeReader.h
similarity index 100%
rename from services/audioflinger/MonoPipeReader.h
rename to include/media/nbaio/MonoPipeReader.h
diff --git a/services/audioflinger/NBAIO.h b/include/media/nbaio/NBAIO.h
similarity index 100%
rename from services/audioflinger/NBAIO.h
rename to include/media/nbaio/NBAIO.h
diff --git a/services/audioflinger/Pipe.h b/include/media/nbaio/Pipe.h
similarity index 100%
rename from services/audioflinger/Pipe.h
rename to include/media/nbaio/Pipe.h
diff --git a/services/audioflinger/PipeReader.h b/include/media/nbaio/PipeReader.h
similarity index 100%
rename from services/audioflinger/PipeReader.h
rename to include/media/nbaio/PipeReader.h
diff --git a/services/audioflinger/SourceAudioBufferProvider.h b/include/media/nbaio/SourceAudioBufferProvider.h
similarity index 97%
rename from services/audioflinger/SourceAudioBufferProvider.h
rename to include/media/nbaio/SourceAudioBufferProvider.h
index 85ccbb2..c08331b 100644
--- a/services/audioflinger/SourceAudioBufferProvider.h
+++ b/include/media/nbaio/SourceAudioBufferProvider.h
@@ -20,7 +20,7 @@
#define ANDROID_SOURCE_AUDIO_BUFFER_PROVIDER_H
#include "NBAIO.h"
-#include "ExtendedAudioBufferProvider.h"
+#include <media/ExtendedAudioBufferProvider.h>
namespace android {
diff --git a/services/audioflinger/roundup.h b/include/media/nbaio/roundup.h
similarity index 100%
rename from services/audioflinger/roundup.h
rename to include/media/nbaio/roundup.h
diff --git a/libvideoeditor/lvpp/VideoEditorSRC.h b/libvideoeditor/lvpp/VideoEditorSRC.h
index 2b7e9b6..1707d4d 100755
--- a/libvideoeditor/lvpp/VideoEditorSRC.h
+++ b/libvideoeditor/lvpp/VideoEditorSRC.h
@@ -17,7 +17,7 @@
#include <stdint.h>
#include <media/stagefright/MediaSource.h>
-#include "AudioBufferProvider.h"
+#include <media/AudioBufferProvider.h>
#include "AudioResampler.h"
namespace android {
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index 32ee89e..d4be9fa 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -1011,6 +1011,8 @@
LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "Effect_setConfig")
if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+ ActiveParams.SampleRate = SampleRate;
+
LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "Effect_setConfig")
diff --git a/media/libnbaio/Android.mk b/media/libnbaio/Android.mk
new file mode 100644
index 0000000..757272f
--- /dev/null
+++ b/media/libnbaio/Android.mk
@@ -0,0 +1,32 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ AudioBufferProviderSource.cpp \
+ AudioStreamOutSink.cpp \
+ AudioStreamInSource.cpp \
+ NBAIO.cpp \
+ MonoPipe.cpp \
+ MonoPipeReader.cpp \
+ Pipe.cpp \
+ PipeReader.cpp \
+ roundup.c \
+ SourceAudioBufferProvider.cpp
+
+# libsndfile license is incompatible; uncomment to use for local debug only
+#LOCAL_SRC_FILES += LibsndfileSink.cpp LibsndfileSource.cpp
+#LOCAL_C_INCLUDES += path/to/libsndfile/src
+#LOCAL_STATIC_LIBRARIES += libsndfile
+
+# uncomment for systrace
+# LOCAL_CFLAGS += -DATRACE_TAG=ATRACE_TAG_AUDIO
+
+LOCAL_MODULE := libnbaio
+
+LOCAL_SHARED_LIBRARIES := \
+ libcommon_time_client \
+ libcutils \
+ libutils
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/services/audioflinger/AudioBufferProviderSource.cpp b/media/libnbaio/AudioBufferProviderSource.cpp
similarity index 98%
rename from services/audioflinger/AudioBufferProviderSource.cpp
rename to media/libnbaio/AudioBufferProviderSource.cpp
index 613e924..74a6fdb 100644
--- a/services/audioflinger/AudioBufferProviderSource.cpp
+++ b/media/libnbaio/AudioBufferProviderSource.cpp
@@ -19,7 +19,7 @@
#include <cutils/compiler.h>
#include <utils/Log.h>
-#include "AudioBufferProviderSource.h"
+#include <media/nbaio/AudioBufferProviderSource.h>
namespace android {
diff --git a/services/audioflinger/AudioStreamInSource.cpp b/media/libnbaio/AudioStreamInSource.cpp
similarity index 97%
rename from services/audioflinger/AudioStreamInSource.cpp
rename to media/libnbaio/AudioStreamInSource.cpp
index 8b4bebf..05273f6 100644
--- a/services/audioflinger/AudioStreamInSource.cpp
+++ b/media/libnbaio/AudioStreamInSource.cpp
@@ -19,7 +19,7 @@
#include <cutils/compiler.h>
#include <utils/Log.h>
-#include "AudioStreamInSource.h"
+#include <media/nbaio/AudioStreamInSource.h>
namespace android {
diff --git a/services/audioflinger/AudioStreamOutSink.cpp b/media/libnbaio/AudioStreamOutSink.cpp
similarity index 97%
rename from services/audioflinger/AudioStreamOutSink.cpp
rename to media/libnbaio/AudioStreamOutSink.cpp
index bc2d15b..6f525e5 100644
--- a/services/audioflinger/AudioStreamOutSink.cpp
+++ b/media/libnbaio/AudioStreamOutSink.cpp
@@ -18,7 +18,7 @@
//#define LOG_NDEBUG 0
#include <utils/Log.h>
-#include "AudioStreamOutSink.h"
+#include <media/nbaio/AudioStreamOutSink.h>
namespace android {
diff --git a/services/audioflinger/LibsndfileSink.cpp b/media/libnbaio/LibsndfileSink.cpp
similarity index 96%
rename from services/audioflinger/LibsndfileSink.cpp
rename to media/libnbaio/LibsndfileSink.cpp
index efc1c8f..77debc0 100644
--- a/services/audioflinger/LibsndfileSink.cpp
+++ b/media/libnbaio/LibsndfileSink.cpp
@@ -19,7 +19,7 @@
#include <utils/Errors.h>
#include <utils/Log.h>
-#include "LibsndfileSink.h"
+#include <media/nbaio/LibsndfileSink.h>
namespace android {
diff --git a/services/audioflinger/LibsndfileSource.cpp b/media/libnbaio/LibsndfileSource.cpp
similarity index 97%
rename from services/audioflinger/LibsndfileSource.cpp
rename to media/libnbaio/LibsndfileSource.cpp
index 28317d6..98610e0 100644
--- a/services/audioflinger/LibsndfileSource.cpp
+++ b/media/libnbaio/LibsndfileSource.cpp
@@ -19,7 +19,7 @@
#include <utils/Errors.h>
#include <utils/Log.h>
-#include "LibsndfileSource.h"
+#include <media/nbaio/LibsndfileSource.h>
namespace android {
diff --git a/services/audioflinger/MonoPipe.cpp b/media/libnbaio/MonoPipe.cpp
similarity index 98%
rename from services/audioflinger/MonoPipe.cpp
rename to media/libnbaio/MonoPipe.cpp
index bd876b4..c426efb 100644
--- a/services/audioflinger/MonoPipe.cpp
+++ b/media/libnbaio/MonoPipe.cpp
@@ -23,9 +23,9 @@
#include <utils/LinearTransform.h>
#include <utils/Log.h>
#include <utils/Trace.h>
-#include "AudioBufferProvider.h"
-#include "MonoPipe.h"
-#include "roundup.h"
+#include <media/AudioBufferProvider.h>
+#include <media/nbaio/MonoPipe.h>
+#include <media/nbaio/roundup.h>
namespace android {
diff --git a/services/audioflinger/MonoPipeReader.cpp b/media/libnbaio/MonoPipeReader.cpp
similarity index 98%
rename from services/audioflinger/MonoPipeReader.cpp
rename to media/libnbaio/MonoPipeReader.cpp
index 39a07de..394f6ac 100644
--- a/services/audioflinger/MonoPipeReader.cpp
+++ b/media/libnbaio/MonoPipeReader.cpp
@@ -19,7 +19,7 @@
#include <cutils/compiler.h>
#include <utils/Log.h>
-#include "MonoPipeReader.h"
+#include <media/nbaio/MonoPipeReader.h>
namespace android {
diff --git a/services/audioflinger/NBAIO.cpp b/media/libnbaio/NBAIO.cpp
similarity index 98%
rename from services/audioflinger/NBAIO.cpp
rename to media/libnbaio/NBAIO.cpp
index 2c07ebf..00d2017 100644
--- a/services/audioflinger/NBAIO.cpp
+++ b/media/libnbaio/NBAIO.cpp
@@ -18,7 +18,7 @@
//#define LOG_NDEBUG 0
#include <utils/Log.h>
-#include "NBAIO.h"
+#include <media/nbaio/NBAIO.h>
namespace android {
diff --git a/services/audioflinger/Pipe.cpp b/media/libnbaio/Pipe.cpp
similarity index 96%
rename from services/audioflinger/Pipe.cpp
rename to media/libnbaio/Pipe.cpp
index e5b3561..1c21f9c 100644
--- a/services/audioflinger/Pipe.cpp
+++ b/media/libnbaio/Pipe.cpp
@@ -20,8 +20,8 @@
#include <cutils/atomic.h>
#include <cutils/compiler.h>
#include <utils/Log.h>
-#include "Pipe.h"
-#include "roundup.h"
+#include <media/nbaio/Pipe.h>
+#include <media/nbaio/roundup.h>
namespace android {
diff --git a/services/audioflinger/PipeReader.cpp b/media/libnbaio/PipeReader.cpp
similarity index 98%
rename from services/audioflinger/PipeReader.cpp
rename to media/libnbaio/PipeReader.cpp
index 529d478..d786b84 100644
--- a/services/audioflinger/PipeReader.cpp
+++ b/media/libnbaio/PipeReader.cpp
@@ -19,7 +19,7 @@
#include <cutils/compiler.h>
#include <utils/Log.h>
-#include "PipeReader.h"
+#include <media/nbaio/PipeReader.h>
namespace android {
diff --git a/services/audioflinger/SourceAudioBufferProvider.cpp b/media/libnbaio/SourceAudioBufferProvider.cpp
similarity index 98%
rename from services/audioflinger/SourceAudioBufferProvider.cpp
rename to media/libnbaio/SourceAudioBufferProvider.cpp
index 3343b53..d11a86c 100644
--- a/services/audioflinger/SourceAudioBufferProvider.cpp
+++ b/media/libnbaio/SourceAudioBufferProvider.cpp
@@ -18,7 +18,7 @@
//#define LOG_NDEBUG 0
#include <utils/Log.h>
-#include "SourceAudioBufferProvider.h"
+#include <media/nbaio/SourceAudioBufferProvider.h>
namespace android {
diff --git a/services/audioflinger/roundup.c b/media/libnbaio/roundup.c
similarity index 96%
rename from services/audioflinger/roundup.c
rename to media/libnbaio/roundup.c
index 4f9af6a..1d552d1 100644
--- a/services/audioflinger/roundup.c
+++ b/media/libnbaio/roundup.c
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "roundup.h"
+#include <media/nbaio/roundup.h>
unsigned roundup(unsigned v)
{
diff --git a/media/libstagefright/SurfaceMediaSource.cpp b/media/libstagefright/SurfaceMediaSource.cpp
index f5c8c93..c478b28 100644
--- a/media/libstagefright/SurfaceMediaSource.cpp
+++ b/media/libstagefright/SurfaceMediaSource.cpp
@@ -52,7 +52,7 @@
ALOGE("Invalid dimensions %dx%d", bufferWidth, bufferHeight);
}
- mBufferQueue = new BufferQueue(true, MIN_UNDEQUEUED_BUFFERS);
+ mBufferQueue = new BufferQueue(true);
mBufferQueue->setDefaultBufferSize(bufferWidth, bufferHeight);
mBufferQueue->setSynchronousMode(true);
mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_HW_VIDEO_ENCODER |
@@ -136,10 +136,32 @@
{
ALOGV("start");
+ Mutex::Autolock lock(mMutex);
+
mStartTimeNs = 0;
int64_t startTimeUs;
- if (params && params->findInt64(kKeyTime, &startTimeUs)) {
- mStartTimeNs = startTimeUs * 1000;
+ int32_t bufferCount = 0;
+ if (params) {
+ if (params->findInt64(kKeyTime, &startTimeUs)) {
+ mStartTimeNs = startTimeUs * 1000;
+ }
+
+ if (!params->findInt32(kKeyNumBuffers, &bufferCount)) {
+ ALOGE("Failed to find the advertised buffer count");
+ return UNKNOWN_ERROR;
+ }
+
+ if (bufferCount <= 1) {
+ ALOGE("bufferCount %d is too small", bufferCount);
+ return BAD_VALUE;
+ }
+ }
+
+ if (bufferCount != 0) {
+ status_t err = mBufferQueue->setMaxAcquiredBufferCount(bufferCount);
+ if (err != OK) {
+ return err;
+ }
}
return OK;
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
index c2d2790..66759d1 100644
--- a/services/audioflinger/Android.mk
+++ b/services/audioflinger/Android.mk
@@ -13,32 +13,6 @@
include $(CLEAR_VARS)
-LOCAL_SRC_FILES := \
- AudioBufferProviderSource.cpp \
- AudioStreamOutSink.cpp \
- AudioStreamInSource.cpp \
- NBAIO.cpp \
- MonoPipe.cpp \
- MonoPipeReader.cpp \
- Pipe.cpp \
- PipeReader.cpp \
- roundup.c \
- SourceAudioBufferProvider.cpp
-
-# libsndfile license is incompatible; uncomment to use for local debug only
-#LOCAL_SRC_FILES += LibsndfileSink.cpp LibsndfileSource.cpp
-#LOCAL_C_INCLUDES += path/to/libsndfile/src
-#LOCAL_STATIC_LIBRARIES += libsndfile
-
-# uncomment for systrace
-# LOCAL_CFLAGS += -DATRACE_TAG=ATRACE_TAG_AUDIO
-
-LOCAL_MODULE := libnbaio
-
-include $(BUILD_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
-
LOCAL_SRC_FILES:= \
AudioFlinger.cpp \
AudioMixer.cpp.arm \
@@ -66,6 +40,7 @@
libbinder \
libmedia \
libmedia_native \
+ libnbaio \
libhardware \
libhardware_legacy \
libeffects \
@@ -74,7 +49,6 @@
LOCAL_STATIC_LIBRARIES := \
libscheduling_policy \
- libnbaio \
libcpustats \
libmedia_helper
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 7126006..1a37f4f 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -76,12 +76,12 @@
#include "FastMixer.h"
// NBAIO implementations
-#include "AudioStreamOutSink.h"
-#include "MonoPipe.h"
-#include "MonoPipeReader.h"
-#include "Pipe.h"
-#include "PipeReader.h"
-#include "SourceAudioBufferProvider.h"
+#include <media/nbaio/AudioStreamOutSink.h>
+#include <media/nbaio/MonoPipe.h>
+#include <media/nbaio/MonoPipeReader.h>
+#include <media/nbaio/Pipe.h>
+#include <media/nbaio/PipeReader.h>
+#include <media/nbaio/SourceAudioBufferProvider.h>
#include "SchedulingPolicyService.h"
@@ -6359,6 +6359,7 @@
status_t AudioFlinger::RecordThread::setSyncEvent(const sp<SyncEvent>& event)
{
+#if 0 // This branch is currently dead code, but is preserved in case it will be needed in future
if (!isValidSyncEvent(event)) {
return BAD_VALUE;
}
@@ -6376,6 +6377,9 @@
}
}
return ret;
+#else
+ return BAD_VALUE;
+#endif
}
void AudioFlinger::RecordThread::RecordTrack::destroy()
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 682d61d..b4aefc1 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -45,10 +45,10 @@
#include <hardware/audio.h>
#include <hardware/audio_policy.h>
-#include "AudioBufferProvider.h"
-#include "ExtendedAudioBufferProvider.h"
+#include <media/AudioBufferProvider.h>
+#include <media/ExtendedAudioBufferProvider.h>
#include "FastMixer.h"
-#include "NBAIO.h"
+#include <media/nbaio/NBAIO.h>
#include "AudioWatchdog.h"
#include <powermanager/IPowerManager.h>
diff --git a/services/audioflinger/AudioMixer.h b/services/audioflinger/AudioMixer.h
index 46deae7..6e34cd1 100644
--- a/services/audioflinger/AudioMixer.h
+++ b/services/audioflinger/AudioMixer.h
@@ -23,7 +23,7 @@
#include <utils/threads.h>
-#include "AudioBufferProvider.h"
+#include <media/AudioBufferProvider.h>
#include "AudioResampler.h"
#include <audio_effects/effect_downmix.h>
diff --git a/services/audioflinger/AudioResampler.h b/services/audioflinger/AudioResampler.h
index 1610e00..dc696d8 100644
--- a/services/audioflinger/AudioResampler.h
+++ b/services/audioflinger/AudioResampler.h
@@ -20,7 +20,7 @@
#include <stdint.h>
#include <sys/types.h>
-#include "AudioBufferProvider.h"
+#include <media/AudioBufferProvider.h>
namespace android {
// ----------------------------------------------------------------------------
diff --git a/services/audioflinger/FastMixerState.h b/services/audioflinger/FastMixerState.h
index bc69c9c..6e53f21 100644
--- a/services/audioflinger/FastMixerState.h
+++ b/services/audioflinger/FastMixerState.h
@@ -18,8 +18,8 @@
#define ANDROID_AUDIO_FAST_MIXER_STATE_H
#include <system/audio.h>
-#include "ExtendedAudioBufferProvider.h"
-#include "NBAIO.h"
+#include <media/ExtendedAudioBufferProvider.h>
+#include <media/nbaio/NBAIO.h>
namespace android {
diff --git a/services/camera/libcameraservice/Android.mk b/services/camera/libcameraservice/Android.mk
index eac6163..1370c62 100644
--- a/services/camera/libcameraservice/Android.mk
+++ b/services/camera/libcameraservice/Android.mk
@@ -13,7 +13,9 @@
Camera2Device.cpp \
camera2/CameraMetadata.cpp \
camera2/Parameters.cpp \
- camera2/FrameProcessor.cpp
+ camera2/FrameProcessor.cpp \
+ camera2/CaptureProcessor.cpp \
+ camera2/CallbackProcessor.cpp
LOCAL_SHARED_LIBRARIES:= \
libui \
diff --git a/services/camera/libcameraservice/Camera2Client.cpp b/services/camera/libcameraservice/Camera2Client.cpp
index 4edb49f..acd290d 100644
--- a/services/camera/libcameraservice/Camera2Client.cpp
+++ b/services/camera/libcameraservice/Camera2Client.cpp
@@ -52,11 +52,9 @@
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 +82,6 @@
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 +100,21 @@
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());
+
+ mCallbackProcessor = new CallbackProcessor(this);
+ String8 callbackThreadName =
+ String8::format("Camera2Client[%d]::CallbackProcessor", mCameraId);
+ mCallbackProcessor->run(callbackThreadName.string());
+
if (gLogLevel >= 1) {
ALOGD("%s: Default parameters converted from camera %d:", __FUNCTION__,
mCameraId);
@@ -292,7 +300,8 @@
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,20 +366,14 @@
mPreviewStreamId = NO_STREAM;
}
- if (mCaptureStreamId != NO_STREAM) {
- mDevice->deleteStream(mCaptureStreamId);
- mCaptureStreamId = NO_STREAM;
- }
+ mCaptureProcessor->deleteStream();
if (mRecordingStreamId != NO_STREAM) {
mDevice->deleteStream(mRecordingStreamId);
mRecordingStreamId = NO_STREAM;
}
- if (mCallbackStreamId != NO_STREAM) {
- mDevice->deleteStream(mCallbackStreamId);
- mCallbackStreamId = NO_STREAM;
- }
+ mCallbackProcessor->deleteStream();
mDevice.clear();
SharedParameters::Lock l(mParameters);
@@ -613,7 +616,7 @@
bool callbacksEnabled = params.previewCallbackFlags &
CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK;
if (callbacksEnabled) {
- res = updateCallbackStream(params);
+ res = mCallbackProcessor->updateStream(params);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to update callback stream: %s (%d)",
__FUNCTION__, mCameraId, strerror(-res), res);
@@ -632,7 +635,7 @@
if (callbacksEnabled) {
uint8_t outputStreams[2] =
- { mPreviewStreamId, mCallbackStreamId };
+ { mPreviewStreamId, mCallbackProcessor->getStreamId() };
res = mPreviewRequest.update(
ANDROID_REQUEST_OUTPUT_STREAMS,
outputStreams, 2);
@@ -796,7 +799,7 @@
bool callbacksEnabled = params.previewCallbackFlags &
CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK;
if (callbacksEnabled) {
- res = updateCallbackStream(params);
+ res = mCallbackProcessor->updateStream(params);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to update callback stream: %s (%d)",
__FUNCTION__, mCameraId, strerror(-res), res);
@@ -815,7 +818,8 @@
if (callbacksEnabled) {
uint8_t outputStreams[3] =
- { mPreviewStreamId, mRecordingStreamId, mCallbackStreamId };
+ { mPreviewStreamId, mRecordingStreamId,
+ mCallbackProcessor->getStreamId() };
res = mRecordingRequest.update(
ANDROID_REQUEST_OUTPUT_STREAMS,
outputStreams, 3);
@@ -1028,7 +1032,7 @@
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 +1052,47 @@
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 };
+ uint8_t streamIds[3] = {
+ mPreviewStreamId,
+ mRecordingStreamId,
+ captureStreamId
+ };
res = mCaptureRequest.update(ANDROID_REQUEST_OUTPUT_STREAMS,
streamIds, 3);
break;
}
case 2: { // Callbacks
- uint8_t streamIds[3] = { mPreviewStreamId, mCallbackStreamId,
- mCaptureStreamId };
+ uint8_t streamIds[3] = {
+ mPreviewStreamId,
+ mCallbackProcessor->getStreamId(),
+ captureStreamId
+ };
res = mCaptureRequest.update(ANDROID_REQUEST_OUTPUT_STREAMS,
streamIds, 3);
break;
}
case 3: { // Both
- uint8_t streamIds[4] = { mPreviewStreamId, mCallbackStreamId,
- mRecordingStreamId, mCaptureStreamId };
+ uint8_t streamIds[4] = {
+ mPreviewStreamId,
+ mCallbackProcessor->getStreamId(),
+ mRecordingStreamId,
+ captureStreamId
+ };
res = mCaptureRequest.update(ANDROID_REQUEST_OUTPUT_STREAMS,
streamIds, 4);
break;
@@ -1511,6 +1530,10 @@
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);
@@ -1523,198 +1546,6 @@
mCameraClient.clear();
}
-void Camera2Client::onCallbackAvailable() {
- ATRACE_CALL();
- status_t res;
- ALOGV("%s: Camera %d: Preview callback available", __FUNCTION__, mCameraId);
-
- int callbackHeapId;
- sp<Camera2Heap> callbackHeap;
- size_t heapIdx;
-
- CpuConsumer::LockedBuffer imgBuffer;
- ALOGV("%s: Getting buffer", __FUNCTION__);
- res = mCallbackConsumer->lockNextBuffer(&imgBuffer);
- if (res != OK) {
- ALOGE("%s: Camera %d: Error receiving next callback buffer: "
- "%s (%d)", __FUNCTION__, mCameraId, strerror(-res), res);
- return;
- }
-
- {
- SharedParameters::Lock l(mParameters);
-
- if ( l.mParameters.state != Parameters::PREVIEW
- && l.mParameters.state != Parameters::RECORD
- && l.mParameters.state != Parameters::VIDEO_SNAPSHOT) {
- ALOGV("%s: Camera %d: No longer streaming",
- __FUNCTION__, mCameraId);
- mCallbackConsumer->unlockBuffer(imgBuffer);
- return;
- }
-
- if (! (l.mParameters.previewCallbackFlags &
- CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK) ) {
- ALOGV("%s: No longer enabled, dropping", __FUNCTION__);
- mCallbackConsumer->unlockBuffer(imgBuffer);
- return;
- }
- if ((l.mParameters.previewCallbackFlags &
- CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK) &&
- !l.mParameters.previewCallbackOneShot) {
- ALOGV("%s: One shot mode, already sent, dropping", __FUNCTION__);
- mCallbackConsumer->unlockBuffer(imgBuffer);
- return;
- }
-
- if (imgBuffer.format != l.mParameters.previewFormat) {
- ALOGE("%s: Camera %d: Unexpected format for callback: "
- "%x, expected %x", __FUNCTION__, mCameraId,
- imgBuffer.format, l.mParameters.previewFormat);
- mCallbackConsumer->unlockBuffer(imgBuffer);
- return;
- }
-
- size_t bufferSize = calculateBufferSize(imgBuffer.width, imgBuffer.height,
- imgBuffer.format, imgBuffer.stride);
- size_t currentBufferSize = (mCallbackHeap == 0) ?
- 0 : (mCallbackHeap->mHeap->getSize() / kCallbackHeapCount);
- if (bufferSize != currentBufferSize) {
- mCallbackHeap.clear();
- mCallbackHeap = new Camera2Heap(bufferSize, kCallbackHeapCount,
- "Camera2Client::CallbackHeap");
- if (mCallbackHeap->mHeap->getSize() == 0) {
- ALOGE("%s: Camera %d: Unable to allocate memory for callbacks",
- __FUNCTION__, mCameraId);
- mCallbackConsumer->unlockBuffer(imgBuffer);
- return;
- }
-
- mCallbackHeapHead = 0;
- mCallbackHeapFree = kCallbackHeapCount;
- mCallbackHeapId++;
- }
-
- if (mCallbackHeapFree == 0) {
- ALOGE("%s: Camera %d: No free callback buffers, dropping frame",
- __FUNCTION__, mCameraId);
- mCallbackConsumer->unlockBuffer(imgBuffer);
- return;
- }
- heapIdx = mCallbackHeapHead;
- callbackHeap = mCallbackHeap;
- callbackHeapId = mCallbackHeapId;
-
- mCallbackHeapHead = (mCallbackHeapHead + 1) & kCallbackHeapCount;
- mCallbackHeapFree--;
-
- // TODO: Get rid of this memcpy by passing the gralloc queue all the way
- // to app
-
- ssize_t offset;
- size_t size;
- sp<IMemoryHeap> heap =
- mCallbackHeap->mBuffers[heapIdx]->getMemory(&offset,
- &size);
- uint8_t *data = (uint8_t*)heap->getBase() + offset;
- memcpy(data, imgBuffer.data, bufferSize);
-
- ALOGV("%s: Freeing buffer", __FUNCTION__);
- mCallbackConsumer->unlockBuffer(imgBuffer);
-
- // In one-shot mode, stop sending callbacks after the first one
- if (l.mParameters.previewCallbackFlags &
- CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK) {
- ALOGV("%s: clearing oneshot", __FUNCTION__);
- l.mParameters.previewCallbackOneShot = false;
- }
- }
-
- // Call outside parameter lock to allow re-entrancy from notification
- {
- SharedCameraClient::Lock l(mSharedCameraClient);
- if (l.mCameraClient != 0) {
- ALOGV("%s: Camera %d: Invoking client data callback",
- __FUNCTION__, mCameraId);
- l.mCameraClient->dataCallback(CAMERA_MSG_PREVIEW_FRAME,
- callbackHeap->mBuffers[heapIdx], NULL);
- }
- }
-
- SharedParameters::Lock l(mParameters);
- // Only increment free if we're still using the same heap
- if (mCallbackHeapId == callbackHeapId) {
- mCallbackHeapFree++;
- }
-
- 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;
@@ -1941,132 +1772,6 @@
return OK;
}
-status_t Camera2Client::updateCallbackStream(const Parameters ¶ms) {
- status_t res;
-
- if (mCallbackConsumer == 0) {
- // Create CPU buffer queue endpoint
- mCallbackConsumer = new CpuConsumer(kCallbackHeapCount);
- mCallbackWaiter = new CallbackWaiter(this);
- mCallbackConsumer->setFrameAvailableListener(mCallbackWaiter);
- mCallbackConsumer->setName(String8("Camera2Client::CallbackConsumer"));
- mCallbackWindow = new SurfaceTextureClient(
- mCallbackConsumer->getProducerInterface());
- }
-
- if (mCallbackStreamId != NO_STREAM) {
- // Check if stream parameters have to change
- uint32_t currentWidth, currentHeight, currentFormat;
- res = mDevice->getStreamInfo(mCallbackStreamId,
- ¤tWidth, ¤tHeight, ¤tFormat);
- if (res != OK) {
- ALOGE("%s: Camera %d: Error querying callback output stream info: "
- "%s (%d)", __FUNCTION__, mCameraId, strerror(-res), res);
- return res;
- }
- if (currentWidth != (uint32_t)params.previewWidth ||
- currentHeight != (uint32_t)params.previewHeight ||
- currentFormat != (uint32_t)params.previewFormat) {
- // Since size should only change while preview is not running,
- // assuming that all existing use of old callback stream is
- // completed.
- res = mDevice->deleteStream(mCallbackStreamId);
- if (res != OK) {
- ALOGE("%s: Camera %d: Unable to delete old output stream "
- "for callbacks: %s (%d)", __FUNCTION__, mCameraId,
- strerror(-res), res);
- return res;
- }
- mCallbackStreamId = NO_STREAM;
- }
- }
-
- if (mCallbackStreamId == NO_STREAM) {
- ALOGV("Creating callback stream: %d %d format 0x%x",
- params.previewWidth, params.previewHeight,
- params.previewFormat);
- res = mDevice->createStream(mCallbackWindow,
- params.previewWidth, params.previewHeight,
- params.previewFormat, 0, &mCallbackStreamId);
- if (res != OK) {
- ALOGE("%s: Camera %d: Can't create output stream for callbacks: "
- "%s (%d)", __FUNCTION__, mCameraId, strerror(-res), res);
- return res;
- }
- }
-
- 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;
diff --git a/services/camera/libcameraservice/Camera2Client.h b/services/camera/libcameraservice/Camera2Client.h
index 3195f94..b2fd636 100644
--- a/services/camera/libcameraservice/Camera2Client.h
+++ b/services/camera/libcameraservice/Camera2Client.h
@@ -21,6 +21,8 @@
#include "CameraService.h"
#include "camera2/Parameters.h"
#include "camera2/FrameProcessor.h"
+#include "camera2/CaptureProcessor.h"
+#include "camera2/CallbackProcessor.h"
#include <binder/MemoryBase.h>
#include <binder/MemoryHeapBase.h>
#include <gui/CpuConsumer.h>
@@ -37,7 +39,9 @@
public Camera2Device::NotificationListener
{
public:
- // ICamera interface (see ICamera for details)
+ /**
+ * ICamera interface (see ICamera for details)
+ */
virtual void disconnect();
virtual status_t connect(const sp<ICameraClient>& client);
@@ -62,7 +66,9 @@
virtual String8 getParameters() const;
virtual status_t sendCommand(int32_t cmd, int32_t arg1, int32_t arg2);
- // Interface used by CameraService
+ /**
+ * Interface used by CameraService
+ */
Camera2Client(const sp<CameraService>& cameraService,
const sp<ICameraClient>& cameraClient,
@@ -75,7 +81,9 @@
virtual status_t dump(int fd, const Vector<String16>& args);
- // Interface used by CameraDevice
+ /**
+ * Interface used by Camera2Device
+ */
virtual void notifyError(int errorCode, int arg1, int arg2);
virtual void notifyShutter(int frameNumber, nsecs_t timestamp);
@@ -83,7 +91,9 @@
virtual void notifyAutoExposure(uint8_t newState, int triggerId);
virtual void notifyAutoWhitebalance(uint8_t newState, int triggerId);
- // Interface used by independent components of Camera2Client.
+ /**
+ * Interface used by independent components of Camera2Client.
+ */
int getCameraId();
const sp<Camera2Device>& getCameraDevice();
@@ -102,6 +112,7 @@
private:
SharedCameraClient &mSharedClient;
};
+ SharedCameraClient(const sp<ICameraClient>& client);
SharedCameraClient& operator=(const sp<ICameraClient>& client);
void clear();
private:
@@ -109,6 +120,9 @@
mutable Mutex mCameraClientLock;
} mSharedCameraClient;
+ static size_t calculateBufferSize(int width, int height,
+ int format, int stride);
+
private:
/** ICamera interface-related private members */
@@ -145,8 +159,6 @@
/** Camera device-related private members */
- class Camera2Heap;
-
void setPreviewCallbackFlagL(Parameters ¶ms, int flag);
status_t updateRequests(const Parameters ¶ms);
@@ -167,50 +179,13 @@
/** Preview callback related members */
- int mCallbackStreamId;
- static const size_t kCallbackHeapCount = 6;
- sp<CpuConsumer> mCallbackConsumer;
- sp<ANativeWindow> mCallbackWindow;
- // Simple listener that forwards frame available notifications from
- // a CPU consumer to the callback notification
- class CallbackWaiter: public CpuConsumer::FrameAvailableListener {
- public:
- CallbackWaiter(Camera2Client *parent) : mParent(parent) {}
- void onFrameAvailable() { mParent->onCallbackAvailable(); }
- private:
- Camera2Client *mParent;
- };
- sp<CallbackWaiter> mCallbackWaiter;
- sp<Camera2Heap> mCallbackHeap;
- int mCallbackHeapId;
- size_t mCallbackHeapHead, mCallbackHeapFree;
- // Handle callback image buffers
- void onCallbackAvailable();
-
- status_t updateCallbackStream(const Parameters ¶ms);
+ sp<camera2::CallbackProcessor> mCallbackProcessor;
/* Still image capture related members */
- int mCaptureStreamId;
- sp<CpuConsumer> mCaptureConsumer;
- sp<ANativeWindow> mCaptureWindow;
- // Simple listener that forwards frame available notifications from
- // a CPU consumer to the capture notification
- class CaptureWaiter: public CpuConsumer::FrameAvailableListener {
- public:
- CaptureWaiter(Camera2Client *parent) : mParent(parent) {}
- void onFrameAvailable() { mParent->onCaptureAvailable(); }
- private:
- Camera2Client *mParent;
- };
- sp<CaptureWaiter> mCaptureWaiter;
+ sp<camera2::CaptureProcessor> mCaptureProcessor;
CameraMetadata mCaptureRequest;
- sp<Camera2Heap> mCaptureHeap;
- // Handle captured image buffers
- void onCaptureAvailable();
-
status_t updateCaptureRequest(const Parameters ¶ms);
- status_t updateCaptureStream(const Parameters ¶ms);
/* Recording related members */
@@ -229,7 +204,7 @@
};
sp<RecordingWaiter> mRecordingWaiter;
CameraMetadata mRecordingRequest;
- sp<Camera2Heap> mRecordingHeap;
+ sp<camera2::Camera2Heap> mRecordingHeap;
static const size_t kDefaultRecordingHeapCount = 8;
size_t mRecordingHeapCount;
@@ -254,32 +229,6 @@
// Verify that caller is the owner of the camera
status_t checkPid(const char *checkLocation) const;
- // Utility class for managing a set of IMemory blocks
- class Camera2Heap : public RefBase {
- public:
- Camera2Heap(size_t buf_size, uint_t num_buffers = 1,
- const char *name = NULL) :
- mBufSize(buf_size),
- mNumBufs(num_buffers) {
- mHeap = new MemoryHeapBase(buf_size * num_buffers, 0, name);
- mBuffers = new sp<MemoryBase>[mNumBufs];
- for (uint_t i = 0; i < mNumBufs; i++)
- mBuffers[i] = new MemoryBase(mHeap,
- i * mBufSize,
- mBufSize);
- }
-
- virtual ~Camera2Heap()
- {
- delete [] mBuffers;
- }
-
- size_t mBufSize;
- uint_t mNumBufs;
- sp<MemoryHeapBase> mHeap;
- sp<MemoryBase> *mBuffers;
- };
-
// Update parameters all requests use, based on mParameters
status_t updateRequestCommon(CameraMetadata *request, const Parameters ¶ms) const;
@@ -291,9 +240,6 @@
int arrayXToNormalized(int width) const;
int arrayYToNormalized(int height) const;
-
- static size_t calculateBufferSize(int width, int height,
- int format, int stride);
};
}; // namespace android
diff --git a/services/camera/libcameraservice/camera2/CallbackProcessor.cpp b/services/camera/libcameraservice/camera2/CallbackProcessor.cpp
new file mode 100644
index 0000000..854b890
--- /dev/null
+++ b/services/camera/libcameraservice/camera2/CallbackProcessor.cpp
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Camera2Client::CallbackProcessor"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+//#define LOG_NDEBUG 0
+
+#include <utils/Log.h>
+#include <utils/Trace.h>
+
+#include "CallbackProcessor.h"
+#include <gui/SurfaceTextureClient.h>
+#include "../Camera2Device.h"
+#include "../Camera2Client.h"
+
+
+namespace android {
+namespace camera2 {
+
+CallbackProcessor::CallbackProcessor(wp<Camera2Client> client):
+ Thread(false),
+ mClient(client),
+ mCallbackAvailable(false),
+ mCallbackStreamId(NO_STREAM) {
+}
+
+CallbackProcessor::~CallbackProcessor() {
+ ALOGV("%s: Exit", __FUNCTION__);
+}
+
+void CallbackProcessor::onFrameAvailable() {
+ Mutex::Autolock l(mInputMutex);
+ if (!mCallbackAvailable) {
+ mCallbackAvailable = true;
+ mCallbackAvailableSignal.signal();
+ }
+}
+
+status_t CallbackProcessor::updateStream(const Parameters ¶ms) {
+ ATRACE_CALL();
+ status_t res;
+
+ Mutex::Autolock l(mInputMutex);
+
+ sp<Camera2Client> client = mClient.promote();
+ if (client == 0) return OK;
+ sp<Camera2Device> device = client->getCameraDevice();
+
+ if (mCallbackConsumer == 0) {
+ // Create CPU buffer queue endpoint
+ mCallbackConsumer = new CpuConsumer(kCallbackHeapCount);
+ mCallbackConsumer->setFrameAvailableListener(this);
+ mCallbackConsumer->setName(String8("Camera2Client::CallbackConsumer"));
+ mCallbackWindow = new SurfaceTextureClient(
+ mCallbackConsumer->getProducerInterface());
+ }
+
+ if (mCallbackStreamId != NO_STREAM) {
+ // Check if stream parameters have to change
+ uint32_t currentWidth, currentHeight, currentFormat;
+ res = device->getStreamInfo(mCallbackStreamId,
+ ¤tWidth, ¤tHeight, ¤tFormat);
+ if (res != OK) {
+ ALOGE("%s: Camera %d: Error querying callback output stream info: "
+ "%s (%d)", __FUNCTION__, client->getCameraId(),
+ strerror(-res), res);
+ return res;
+ }
+ if (currentWidth != (uint32_t)params.previewWidth ||
+ currentHeight != (uint32_t)params.previewHeight ||
+ currentFormat != (uint32_t)params.previewFormat) {
+ // Since size should only change while preview is not running,
+ // assuming that all existing use of old callback stream is
+ // completed.
+ 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);
+ return res;
+ }
+ mCallbackStreamId = NO_STREAM;
+ }
+ }
+
+ if (mCallbackStreamId == NO_STREAM) {
+ ALOGV("Creating callback stream: %d %d format 0x%x",
+ params.previewWidth, params.previewHeight,
+ params.previewFormat);
+ res = device->createStream(mCallbackWindow,
+ params.previewWidth, params.previewHeight,
+ params.previewFormat, 0, &mCallbackStreamId);
+ if (res != OK) {
+ ALOGE("%s: Camera %d: Can't create output stream for callbacks: "
+ "%s (%d)", __FUNCTION__, client->getCameraId(),
+ strerror(-res), res);
+ return res;
+ }
+ }
+
+ return OK;
+}
+
+status_t CallbackProcessor::deleteStream() {
+ ATRACE_CALL();
+ status_t res;
+
+ Mutex::Autolock l(mInputMutex);
+
+ if (mCallbackStreamId != NO_STREAM) {
+ sp<Camera2Client> client = mClient.promote();
+ if (client == 0) return OK;
+ sp<Camera2Device> device = client->getCameraDevice();
+
+ device->deleteStream(mCallbackStreamId);
+ mCallbackStreamId = NO_STREAM;
+ }
+ return OK;
+}
+
+int CallbackProcessor::getStreamId() const {
+ Mutex::Autolock l(mInputMutex);
+ return mCallbackStreamId;
+}
+
+void CallbackProcessor::dump(int fd, const Vector<String16>& args) {
+}
+
+bool CallbackProcessor::threadLoop() {
+ status_t res;
+
+ {
+ Mutex::Autolock l(mInputMutex);
+ while (!mCallbackAvailable) {
+ res = mCallbackAvailableSignal.waitRelative(mInputMutex,
+ kWaitDuration);
+ if (res == TIMED_OUT) return true;
+ }
+ mCallbackAvailable = false;
+ }
+
+ do {
+ sp<Camera2Client> client = mClient.promote();
+ if (client == 0) return false;
+ res = processNewCallback(client);
+ } while (res == OK);
+
+ return true;
+}
+
+status_t CallbackProcessor::processNewCallback(sp<Camera2Client> &client) {
+ ATRACE_CALL();
+ status_t res;
+
+ int callbackHeapId;
+ sp<Camera2Heap> callbackHeap;
+ size_t heapIdx;
+
+ CpuConsumer::LockedBuffer imgBuffer;
+ ALOGV("%s: Getting buffer", __FUNCTION__);
+ res = mCallbackConsumer->lockNextBuffer(&imgBuffer);
+ if (res != OK) {
+ if (res != BAD_VALUE) {
+ ALOGE("%s: Camera %d: Error receiving next callback buffer: "
+ "%s (%d)", __FUNCTION__, client->getCameraId(), strerror(-res), res);
+ }
+ return res;
+ }
+ ALOGV("%s: Camera %d: Preview callback available", __FUNCTION__,
+ client->getCameraId());
+
+ {
+ SharedParameters::Lock l(client->getParameters());
+
+ if ( l.mParameters.state != Parameters::PREVIEW
+ && l.mParameters.state != Parameters::RECORD
+ && l.mParameters.state != Parameters::VIDEO_SNAPSHOT) {
+ ALOGV("%s: Camera %d: No longer streaming",
+ __FUNCTION__, client->getCameraId());
+ mCallbackConsumer->unlockBuffer(imgBuffer);
+ return OK;
+ }
+
+ if (! (l.mParameters.previewCallbackFlags &
+ CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK) ) {
+ ALOGV("%s: No longer enabled, dropping", __FUNCTION__);
+ mCallbackConsumer->unlockBuffer(imgBuffer);
+ return OK;
+ }
+ if ((l.mParameters.previewCallbackFlags &
+ CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK) &&
+ !l.mParameters.previewCallbackOneShot) {
+ ALOGV("%s: One shot mode, already sent, dropping", __FUNCTION__);
+ mCallbackConsumer->unlockBuffer(imgBuffer);
+ return OK;
+ }
+
+ if (imgBuffer.format != l.mParameters.previewFormat) {
+ ALOGE("%s: Camera %d: Unexpected format for callback: "
+ "%x, expected %x", __FUNCTION__, client->getCameraId(),
+ imgBuffer.format, l.mParameters.previewFormat);
+ mCallbackConsumer->unlockBuffer(imgBuffer);
+ return INVALID_OPERATION;
+ }
+
+ // In one-shot mode, stop sending callbacks after the first one
+ if (l.mParameters.previewCallbackFlags &
+ CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK) {
+ ALOGV("%s: clearing oneshot", __FUNCTION__);
+ l.mParameters.previewCallbackOneShot = false;
+ }
+ }
+
+ size_t bufferSize = Camera2Client::calculateBufferSize(
+ imgBuffer.width, imgBuffer.height,
+ imgBuffer.format, imgBuffer.stride);
+ size_t currentBufferSize = (mCallbackHeap == 0) ?
+ 0 : (mCallbackHeap->mHeap->getSize() / kCallbackHeapCount);
+ if (bufferSize != currentBufferSize) {
+ mCallbackHeap.clear();
+ mCallbackHeap = new Camera2Heap(bufferSize, kCallbackHeapCount,
+ "Camera2Client::CallbackHeap");
+ if (mCallbackHeap->mHeap->getSize() == 0) {
+ ALOGE("%s: Camera %d: Unable to allocate memory for callbacks",
+ __FUNCTION__, client->getCameraId());
+ mCallbackConsumer->unlockBuffer(imgBuffer);
+ return INVALID_OPERATION;
+ }
+
+ mCallbackHeapHead = 0;
+ mCallbackHeapFree = kCallbackHeapCount;
+ }
+
+ if (mCallbackHeapFree == 0) {
+ ALOGE("%s: Camera %d: No free callback buffers, dropping frame",
+ __FUNCTION__, client->getCameraId());
+ mCallbackConsumer->unlockBuffer(imgBuffer);
+ return OK;
+ }
+
+ heapIdx = mCallbackHeapHead;
+
+ mCallbackHeapHead = (mCallbackHeapHead + 1) & kCallbackHeapCount;
+ mCallbackHeapFree--;
+
+ // TODO: Get rid of this memcpy by passing the gralloc queue all the way
+ // to app
+
+ ssize_t offset;
+ size_t size;
+ sp<IMemoryHeap> heap =
+ mCallbackHeap->mBuffers[heapIdx]->getMemory(&offset,
+ &size);
+ uint8_t *data = (uint8_t*)heap->getBase() + offset;
+ memcpy(data, imgBuffer.data, bufferSize);
+
+ ALOGV("%s: Freeing buffer", __FUNCTION__);
+ mCallbackConsumer->unlockBuffer(imgBuffer);
+
+ // Call outside parameter lock to allow re-entrancy from notification
+ {
+ Camera2Client::SharedCameraClient::Lock l(client->mSharedCameraClient);
+ if (l.mCameraClient != 0) {
+ ALOGV("%s: Camera %d: Invoking client data callback",
+ __FUNCTION__, client->getCameraId());
+ l.mCameraClient->dataCallback(CAMERA_MSG_PREVIEW_FRAME,
+ mCallbackHeap->mBuffers[heapIdx], NULL);
+ }
+ }
+
+ // Only increment free if we're still using the same heap
+ mCallbackHeapFree++;
+
+ ALOGV("%s: exit", __FUNCTION__);
+
+ return OK;
+}
+
+}; // namespace camera2
+}; // namespace android
diff --git a/services/camera/libcameraservice/camera2/CallbackProcessor.h b/services/camera/libcameraservice/camera2/CallbackProcessor.h
new file mode 100644
index 0000000..36c51a3
--- /dev/null
+++ b/services/camera/libcameraservice/camera2/CallbackProcessor.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SERVERS_CAMERA_CAMERA2_CALLBACKPROCESSOR_H
+#define ANDROID_SERVERS_CAMERA_CAMERA2_CALLBACKPROCESSOR_H
+
+#include <utils/Thread.h>
+#include <utils/String16.h>
+#include <utils/Vector.h>
+#include <utils/Mutex.h>
+#include <utils/Condition.h>
+#include <gui/CpuConsumer.h>
+#include "Parameters.h"
+#include "CameraMetadata.h"
+#include "Camera2Heap.h"
+
+namespace android {
+
+class Camera2Client;
+
+namespace camera2 {
+
+/***
+ * Still image capture output image processing
+ */
+class CallbackProcessor:
+ public Thread, public CpuConsumer::FrameAvailableListener {
+ public:
+ CallbackProcessor(wp<Camera2Client> client);
+ ~CallbackProcessor();
+
+ void onFrameAvailable();
+
+ status_t updateStream(const Parameters ¶ms);
+ status_t deleteStream();
+ int getStreamId() const;
+
+ void dump(int fd, const Vector<String16>& args);
+ private:
+ static const nsecs_t kWaitDuration = 10000000; // 10 ms
+ wp<Camera2Client> mClient;
+
+ mutable Mutex mInputMutex;
+ bool mCallbackAvailable;
+ Condition mCallbackAvailableSignal;
+
+ enum {
+ NO_STREAM = -1
+ };
+
+ int mCallbackStreamId;
+ static const size_t kCallbackHeapCount = 6;
+ sp<CpuConsumer> mCallbackConsumer;
+ sp<ANativeWindow> mCallbackWindow;
+ sp<Camera2Heap> mCallbackHeap;
+ int mCallbackHeapId;
+ size_t mCallbackHeapHead, mCallbackHeapFree;
+
+ virtual bool threadLoop();
+
+ status_t processNewCallback(sp<Camera2Client> &client);
+
+};
+
+
+}; //namespace camera2
+}; //namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/camera2/Camera2Heap.h b/services/camera/libcameraservice/camera2/Camera2Heap.h
new file mode 100644
index 0000000..9c72d76
--- /dev/null
+++ b/services/camera/libcameraservice/camera2/Camera2Heap.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROiD_SERVERS_CAMERA_CAMERA2HEAP_H
+#define ANDROiD_SERVERS_CAMERA_CAMERA2HEAP_H
+
+#include <binder/MemoryBase.h>
+#include <binder/MemoryHeapBase.h>
+
+namespace android {
+namespace camera2 {
+
+// Utility class for managing a set of IMemory blocks
+class Camera2Heap : public RefBase {
+ public:
+ Camera2Heap(size_t buf_size, uint_t num_buffers = 1,
+ const char *name = NULL) :
+ mBufSize(buf_size),
+ mNumBufs(num_buffers) {
+ mHeap = new MemoryHeapBase(buf_size * num_buffers, 0, name);
+ mBuffers = new sp<MemoryBase>[mNumBufs];
+ for (uint_t i = 0; i < mNumBufs; i++)
+ mBuffers[i] = new MemoryBase(mHeap,
+ i * mBufSize,
+ mBufSize);
+ }
+
+ virtual ~Camera2Heap()
+ {
+ delete [] mBuffers;
+ }
+
+ size_t mBufSize;
+ uint_t mNumBufs;
+ sp<MemoryHeapBase> mHeap;
+ sp<MemoryBase> *mBuffers;
+};
+
+}; // namespace camera2
+}; // namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/camera2/CaptureProcessor.cpp b/services/camera/libcameraservice/camera2/CaptureProcessor.cpp
new file mode 100644
index 0000000..b17f9d2
--- /dev/null
+++ b/services/camera/libcameraservice/camera2/CaptureProcessor.cpp
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Camera2Client::CaptureProcessor"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+//#define LOG_NDEBUG 0
+
+#include <utils/Log.h>
+#include <utils/Trace.h>
+
+#include "CaptureProcessor.h"
+#include <gui/SurfaceTextureClient.h>
+#include "../Camera2Device.h"
+#include "../Camera2Client.h"
+
+
+namespace android {
+namespace camera2 {
+
+CaptureProcessor::CaptureProcessor(wp<Camera2Client> client):
+ Thread(false),
+ mClient(client),
+ mCaptureAvailable(false),
+ mCaptureStreamId(NO_STREAM) {
+}
+
+CaptureProcessor::~CaptureProcessor() {
+ ALOGV("%s: Exit", __FUNCTION__);
+}
+
+void CaptureProcessor::onFrameAvailable() {
+ Mutex::Autolock l(mInputMutex);
+ if (!mCaptureAvailable) {
+ mCaptureAvailable = true;
+ mCaptureAvailableSignal.signal();
+ }
+}
+
+status_t CaptureProcessor::updateStream(const Parameters ¶ms) {
+ ATRACE_CALL();
+ ALOGV("%s", __FUNCTION__);
+ status_t res;
+
+ Mutex::Autolock l(mInputMutex);
+
+ sp<Camera2Client> client = mClient.promote();
+ if (client == 0) return OK;
+ sp<Camera2Device> device = client->getCameraDevice();
+
+ // 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());
+ return INVALID_OPERATION;
+ }
+
+ if (mCaptureConsumer == 0) {
+ // Create CPU buffer queue endpoint
+ mCaptureConsumer = new CpuConsumer(1);
+ mCaptureConsumer->setFrameAvailableListener(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__, client->getCameraId());
+ return NO_MEMORY;
+ }
+ }
+
+ if (mCaptureStreamId != NO_STREAM) {
+ // Check if stream parameters have to change
+ uint32_t currentWidth, currentHeight;
+ res = device->getStreamInfo(mCaptureStreamId,
+ ¤tWidth, ¤tHeight, 0);
+ if (res != OK) {
+ ALOGE("%s: Camera %d: Error querying capture output stream info: "
+ "%s (%d)", __FUNCTION__,
+ client->getCameraId(), strerror(-res), res);
+ return res;
+ }
+ if (currentWidth != (uint32_t)params.pictureWidth ||
+ currentHeight != (uint32_t)params.pictureHeight) {
+ 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);
+ return res;
+ }
+ mCaptureStreamId = NO_STREAM;
+ }
+ }
+
+ if (mCaptureStreamId == NO_STREAM) {
+ // Create stream for HAL production
+ res = device->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__, client->getCameraId(),
+ strerror(-res), res);
+ return res;
+ }
+
+ }
+ return OK;
+}
+
+status_t CaptureProcessor::deleteStream() {
+ ATRACE_CALL();
+ status_t res;
+
+ Mutex::Autolock l(mInputMutex);
+
+ if (mCaptureStreamId != NO_STREAM) {
+ sp<Camera2Client> client = mClient.promote();
+ if (client == 0) return OK;
+ sp<Camera2Device> device = client->getCameraDevice();
+
+ device->deleteStream(mCaptureStreamId);
+ mCaptureStreamId = NO_STREAM;
+ }
+ return OK;
+}
+
+int CaptureProcessor::getStreamId() const {
+ Mutex::Autolock l(mInputMutex);
+ return mCaptureStreamId;
+}
+
+void CaptureProcessor::dump(int fd, const Vector<String16>& args) {
+}
+
+bool CaptureProcessor::threadLoop() {
+ status_t res;
+
+ {
+ Mutex::Autolock l(mInputMutex);
+ while (!mCaptureAvailable) {
+ res = mCaptureAvailableSignal.waitRelative(mInputMutex,
+ kWaitDuration);
+ if (res == TIMED_OUT) return true;
+ }
+ mCaptureAvailable = false;
+ }
+
+ do {
+ sp<Camera2Client> client = mClient.promote();
+ if (client == 0) return false;
+ res = processNewCapture(client);
+ } while (res == OK);
+
+ return true;
+}
+
+status_t CaptureProcessor::processNewCapture(sp<Camera2Client> &client) {
+ ATRACE_CALL();
+ status_t res;
+ sp<Camera2Heap> captureHeap;
+
+ CpuConsumer::LockedBuffer imgBuffer;
+
+ res = mCaptureConsumer->lockNextBuffer(&imgBuffer);
+ if (res != OK) {
+ if (res != BAD_VALUE) {
+ ALOGE("%s: Camera %d: Error receiving still image buffer: "
+ "%s (%d)", __FUNCTION__,
+ client->getCameraId(), strerror(-res), res);
+ }
+ return res;
+ }
+
+ ALOGV("%s: Camera %d: Still capture available", __FUNCTION__,
+ client->getCameraId());
+
+ // TODO: Signal errors here upstream
+ {
+ SharedParameters::Lock l(client->getParameters());
+
+ 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: Still image produced unexpectedly "
+ "in state %s!",
+ __FUNCTION__, client->getCameraId(),
+ Parameters::getStateName(l.mParameters.state));
+ mCaptureConsumer->unlockBuffer(imgBuffer);
+ return BAD_VALUE;
+ }
+ }
+
+ if (imgBuffer.format != HAL_PIXEL_FORMAT_BLOB) {
+ ALOGE("%s: Camera %d: Unexpected format for still image: "
+ "%x, expected %x", __FUNCTION__, client->getCameraId(),
+ imgBuffer.format,
+ HAL_PIXEL_FORMAT_BLOB);
+ mCaptureConsumer->unlockBuffer(imgBuffer);
+ return OK;
+ }
+
+ // 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);
+
+ captureHeap = mCaptureHeap;
+
+ Camera2Client::SharedCameraClient::Lock l(client->mSharedCameraClient);
+ ALOGV("%s: Sending still image to client", __FUNCTION__);
+ if (l.mCameraClient != 0) {
+ l.mCameraClient->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE,
+ captureHeap->mBuffers[0], NULL);
+ } else {
+ ALOGV("%s: No client!", __FUNCTION__);
+ }
+ return OK;
+}
+
+}; // namespace camera2
+}; // namespace android
diff --git a/services/camera/libcameraservice/camera2/CaptureProcessor.h b/services/camera/libcameraservice/camera2/CaptureProcessor.h
new file mode 100644
index 0000000..8e35739
--- /dev/null
+++ b/services/camera/libcameraservice/camera2/CaptureProcessor.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SERVERS_CAMERA_CAMERA2_CAPTUREPROCESSOR_H
+#define ANDROID_SERVERS_CAMERA_CAMERA2_CAPTUREPROCESSOR_H
+
+#include <utils/Thread.h>
+#include <utils/String16.h>
+#include <utils/Vector.h>
+#include <utils/Mutex.h>
+#include <utils/Condition.h>
+#include <gui/CpuConsumer.h>
+#include "Parameters.h"
+#include "CameraMetadata.h"
+#include "Camera2Heap.h"
+
+namespace android {
+
+class Camera2Client;
+
+namespace camera2 {
+
+/***
+ * Still image capture output image processing
+ */
+class CaptureProcessor:
+ public Thread, public CpuConsumer::FrameAvailableListener {
+ public:
+ CaptureProcessor(wp<Camera2Client> client);
+ ~CaptureProcessor();
+
+ void onFrameAvailable();
+
+ status_t updateStream(const Parameters ¶ms);
+ status_t deleteStream();
+ int getStreamId() const;
+
+ void dump(int fd, const Vector<String16>& args);
+ private:
+ static const nsecs_t kWaitDuration = 10000000; // 10 ms
+ wp<Camera2Client> mClient;
+
+ mutable Mutex mInputMutex;
+ bool mCaptureAvailable;
+ Condition mCaptureAvailableSignal;
+
+ enum {
+ NO_STREAM = -1
+ };
+
+ int mCaptureStreamId;
+ sp<CpuConsumer> mCaptureConsumer;
+ sp<ANativeWindow> mCaptureWindow;
+ sp<Camera2Heap> mCaptureHeap;
+
+ virtual bool threadLoop();
+
+ status_t processNewCapture(sp<Camera2Client> &client);
+
+};
+
+
+}; //namespace camera2
+}; //namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/camera2/Parameters.cpp b/services/camera/libcameraservice/camera2/Parameters.cpp
index 91c5141..2f7d023 100644
--- a/services/camera/libcameraservice/camera2/Parameters.cpp
+++ b/services/camera/libcameraservice/camera2/Parameters.cpp
@@ -208,7 +208,7 @@
CameraParameters::PIXEL_FORMAT_JPEG);
camera_metadata_ro_entry_t availableJpegThumbnailSizes =
- staticInfo(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES, 2);
+ staticInfo(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES, 4);
if (!availableJpegThumbnailSizes.count) return NO_INIT;
// TODO: Pick default thumbnail size sensibly