diff options
Diffstat (limited to 'services/camera')
23 files changed, 675 insertions, 175 deletions
diff --git a/services/camera/libcameraservice/Android.mk b/services/camera/libcameraservice/Android.mk index 51ba698..2f485b9 100644 --- a/services/camera/libcameraservice/Android.mk +++ b/services/camera/libcameraservice/Android.mk @@ -1,3 +1,17 @@ +# Copyright 2010 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. + LOCAL_PATH:= $(call my-dir) # @@ -53,6 +67,7 @@ LOCAL_SHARED_LIBRARIES:= \ LOCAL_C_INCLUDES += \ system/media/camera/include \ + system/media/private/camera/include \ external/jpeg diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index 5cbbde9..aa2071b 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -1,24 +1,24 @@ /* -** -** Copyright (C) 2008, 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. -*/ + * Copyright (C) 2008 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 "CameraService" //#define LOG_NDEBUG 0 #include <stdio.h> +#include <string.h> #include <sys/types.h> #include <pthread.h> @@ -32,10 +32,13 @@ #include <gui/Surface.h> #include <hardware/hardware.h> #include <media/AudioSystem.h> +#include <media/IMediaHTTPService.h> #include <media/mediaplayer.h> #include <utils/Errors.h> #include <utils/Log.h> #include <utils/String16.h> +#include <utils/Trace.h> +#include <system/camera_vendor_tags.h> #include "CameraService.h" #include "api1/CameraClient.h" @@ -130,6 +133,12 @@ void CameraService::onFirstRef() mModule->set_callbacks(this); } + VendorTagDescriptor::clearGlobalVendorTagDescriptor(); + + if (mModule->common.module_api_version >= CAMERA_MODULE_API_VERSION_2_2) { + setUpVendorTags(); + } + CameraDeviceFactory::registerService(this); } } @@ -141,6 +150,7 @@ CameraService::~CameraService() { } } + VendorTagDescriptor::clearGlobalVendorTagDescriptor(); gCameraService = NULL; } @@ -269,6 +279,22 @@ status_t CameraService::getCameraCharacteristics(int cameraId, return ret; } +status_t CameraService::getCameraVendorTagDescriptor(/*out*/sp<VendorTagDescriptor>& desc) { + if (!mModule) { + ALOGE("%s: camera hardware module doesn't exist", __FUNCTION__); + return -ENODEV; + } + + if (mModule->common.module_api_version < CAMERA_MODULE_API_VERSION_2_2) { + // TODO: Remove this check once HAL1 shim is in place. + ALOGW("%s: Only HAL module version V2.2 or higher supports vendor tags", __FUNCTION__); + return -EOPNOTSUPP; + } + + desc = VendorTagDescriptor::getGlobalVendorTagDescriptor(); + return OK; +} + int CameraService::getDeviceVersion(int cameraId, int* facing) { struct camera_info info; if (mModule->get_camera_info(cameraId, &info) != OK) { @@ -306,6 +332,44 @@ bool CameraService::isValidCameraId(int cameraId) { return false; } +bool CameraService::setUpVendorTags() { + vendor_tag_ops_t vOps = vendor_tag_ops_t(); + + // Check if vendor operations have been implemented + if (mModule->get_vendor_tag_ops == NULL) { + ALOGI("%s: No vendor tags defined for this device.", __FUNCTION__); + return false; + } + + ATRACE_BEGIN("camera3->get_metadata_vendor_tag_ops"); + mModule->get_vendor_tag_ops(&vOps); + ATRACE_END(); + + // Ensure all vendor operations are present + if (vOps.get_tag_count == NULL || vOps.get_all_tags == NULL || + vOps.get_section_name == NULL || vOps.get_tag_name == NULL || + vOps.get_tag_type == NULL) { + ALOGE("%s: Vendor tag operations not fully defined. Ignoring definitions." + , __FUNCTION__); + return false; + } + + // Read all vendor tag definitions into a descriptor + sp<VendorTagDescriptor> desc; + status_t res; + if ((res = VendorTagDescriptor::createDescriptorFromOps(&vOps, /*out*/desc)) + != OK) { + ALOGE("%s: Could not generate descriptor from vendor tag operations," + "received error %s (%d). Camera clients will not be able to use" + "vendor tags", __FUNCTION__, strerror(res), res); + return false; + } + + // Set the global descriptor to use with camera metadata + VendorTagDescriptor::setAsGlobalVendorTagDescriptor(desc); + return true; +} + status_t CameraService::validateConnect(int cameraId, /*inout*/ int& clientUid) const { @@ -876,7 +940,7 @@ void CameraService::setCameraFree(int cameraId) { MediaPlayer* CameraService::newMediaPlayer(const char *file) { MediaPlayer* mp = new MediaPlayer(); - if (mp->setDataSource(file, NULL) == NO_ERROR) { + if (mp->setDataSource(NULL /* httpService */, file, NULL) == NO_ERROR) { mp->setAudioStreamType(AUDIO_STREAM_ENFORCED_AUDIBLE); mp->prepare(); } else { diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h index ad6a582..8853e48 100644 --- a/services/camera/libcameraservice/CameraService.h +++ b/services/camera/libcameraservice/CameraService.h @@ -1,19 +1,18 @@ /* -** -** Copyright (C) 2008, 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. -*/ + * Copyright (C) 2008 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_CAMERASERVICE_H #define ANDROID_SERVERS_CAMERA_CAMERASERVICE_H @@ -31,6 +30,7 @@ #include <camera/IProCameraCallbacks.h> #include <camera/camera2/ICameraDeviceUser.h> #include <camera/camera2/ICameraDeviceCallbacks.h> +#include <camera/VendorTagDescriptor.h> #include <camera/ICameraServiceListener.h> @@ -73,6 +73,7 @@ public: struct CameraInfo* cameraInfo); virtual status_t getCameraCharacteristics(int cameraId, CameraMetadata* cameraInfo); + virtual status_t getCameraVendorTagDescriptor(/*out*/ sp<VendorTagDescriptor>& desc); virtual status_t connect(const sp<ICameraClient>& cameraClient, int cameraId, const String16& clientPackageName, int clientUid, @@ -387,6 +388,8 @@ private: // Helpers bool isValidCameraId(int cameraId); + + bool setUpVendorTags(); }; } // namespace android diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp index af23557..80b7cd4 100644 --- a/services/camera/libcameraservice/api1/Camera2Client.cpp +++ b/services/camera/libcameraservice/api1/Camera2Client.cpp @@ -238,7 +238,7 @@ status_t Camera2Client::dump(int fd, const Vector<String16>& args) { result.append(" Scene mode: "); switch (p.sceneMode) { - case ANDROID_CONTROL_SCENE_MODE_UNSUPPORTED: + case ANDROID_CONTROL_SCENE_MODE_DISABLED: result.append("AUTO\n"); break; CASE_APPEND_ENUM(ANDROID_CONTROL_SCENE_MODE_ACTION) CASE_APPEND_ENUM(ANDROID_CONTROL_SCENE_MODE_PORTRAIT) @@ -816,6 +816,8 @@ status_t Camera2Client::startPreviewL(Parameters ¶ms, bool restart) { return res; } outputStreams.push(getZslStreamId()); + } else { + mZslProcessor->deleteStream(); } outputStreams.push(getPreviewStreamId()); @@ -1162,7 +1164,7 @@ status_t Camera2Client::autoFocus() { * Handle quirk mode for AF in scene modes */ if (l.mParameters.quirks.triggerAfWithAuto && - l.mParameters.sceneMode != ANDROID_CONTROL_SCENE_MODE_UNSUPPORTED && + l.mParameters.sceneMode != ANDROID_CONTROL_SCENE_MODE_DISABLED && l.mParameters.focusMode != Parameters::FOCUS_MODE_AUTO && !l.mParameters.focusingAreas[0].isEmpty()) { ALOGV("%s: Quirk: Switching from focusMode %d to AUTO", diff --git a/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp b/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp index d2ac79c..c266213 100644 --- a/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp +++ b/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp @@ -110,11 +110,13 @@ status_t CallbackProcessor::updateStream(const Parameters ¶ms) { if (!mCallbackToApp && mCallbackConsumer == 0) { // Create CPU buffer queue endpoint, since app hasn't given us one // Make it async to avoid disconnect deadlocks - sp<BufferQueue> bq = new BufferQueue(); - mCallbackConsumer = new CpuConsumer(bq, kCallbackHeapCount); + sp<IGraphicBufferProducer> producer; + sp<IGraphicBufferConsumer> consumer; + BufferQueue::createBufferQueue(&producer, &consumer); + mCallbackConsumer = new CpuConsumer(consumer, kCallbackHeapCount); mCallbackConsumer->setFrameAvailableListener(this); mCallbackConsumer->setName(String8("Camera2Client::CallbackConsumer")); - mCallbackWindow = new Surface(bq); + mCallbackWindow = new Surface(producer); } if (mCallbackStreamId != NO_STREAM) { diff --git a/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp b/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp index 2de7a2b..964d278 100644 --- a/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp +++ b/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp @@ -83,11 +83,13 @@ status_t JpegProcessor::updateStream(const Parameters ¶ms) { if (mCaptureConsumer == 0) { // Create CPU buffer queue endpoint - sp<BufferQueue> bq = new BufferQueue(); - mCaptureConsumer = new CpuConsumer(bq, 1); + sp<IGraphicBufferProducer> producer; + sp<IGraphicBufferConsumer> consumer; + BufferQueue::createBufferQueue(&producer, &consumer); + mCaptureConsumer = new CpuConsumer(consumer, 1); mCaptureConsumer->setFrameAvailableListener(this); mCaptureConsumer->setName(String8("Camera2Client::CaptureConsumer")); - mCaptureWindow = new Surface(bq); + mCaptureWindow = new Surface(producer); // Create memory for API consumption mCaptureHeap = new MemoryHeapBase(maxJpegSize.data.i32[0], 0, "Camera2Client::CaptureHeap"); diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp index ee0fad2..d5be58c 100644 --- a/services/camera/libcameraservice/api1/client2/Parameters.cpp +++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp @@ -16,7 +16,7 @@ #define LOG_TAG "Camera2-Parameters" #define ATRACE_TAG ATRACE_TAG_CAMERA -//#define LOG_NDEBUG 0 +// #define LOG_NDEBUG 0 #include <utils/Log.h> #include <utils/Trace.h> @@ -92,26 +92,6 @@ status_t Parameters::initialize(const CameraMetadata *info) { staticInfo(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, 2); if (!availableFpsRanges.count) return NO_INIT; - previewFpsRange[0] = availableFpsRanges.data.i32[0]; - previewFpsRange[1] = availableFpsRanges.data.i32[1]; - - params.set(CameraParameters::KEY_PREVIEW_FPS_RANGE, - String8::format("%d,%d", - previewFpsRange[0] * kFpsToApiScale, - previewFpsRange[1] * kFpsToApiScale)); - - { - String8 supportedPreviewFpsRange; - for (size_t i=0; i < availableFpsRanges.count; i += 2) { - if (i != 0) supportedPreviewFpsRange += ","; - supportedPreviewFpsRange += String8::format("(%d,%d)", - availableFpsRanges.data.i32[i] * kFpsToApiScale, - availableFpsRanges.data.i32[i+1] * kFpsToApiScale); - } - params.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE, - supportedPreviewFpsRange); - } - previewFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP; params.set(CameraParameters::KEY_PREVIEW_FORMAT, formatEnumToString(previewFormat)); // NV21 @@ -179,6 +159,9 @@ status_t Parameters::initialize(const CameraMetadata *info) { supportedPreviewFormats); } + previewFpsRange[0] = availableFpsRanges.data.i32[0]; + previewFpsRange[1] = availableFpsRanges.data.i32[1]; + // PREVIEW_FRAME_RATE / SUPPORTED_PREVIEW_FRAME_RATES are deprecated, but // still have to do something sane for them @@ -187,6 +170,27 @@ status_t Parameters::initialize(const CameraMetadata *info) { params.set(CameraParameters::KEY_PREVIEW_FRAME_RATE, previewFps); + // PREVIEW_FPS_RANGE + // -- Order matters. Set range after single value to so that a roundtrip + // of setParameters(getParameters()) would keep the FPS range in higher + // order. + params.set(CameraParameters::KEY_PREVIEW_FPS_RANGE, + String8::format("%d,%d", + previewFpsRange[0] * kFpsToApiScale, + previewFpsRange[1] * kFpsToApiScale)); + + { + String8 supportedPreviewFpsRange; + for (size_t i=0; i < availableFpsRanges.count; i += 2) { + if (i != 0) supportedPreviewFpsRange += ","; + supportedPreviewFpsRange += String8::format("(%d,%d)", + availableFpsRanges.data.i32[i] * kFpsToApiScale, + availableFpsRanges.data.i32[i+1] * kFpsToApiScale); + } + params.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE, + supportedPreviewFpsRange); + } + { SortedVector<int32_t> sortedPreviewFrameRates; @@ -466,7 +470,7 @@ status_t Parameters::initialize(const CameraMetadata *info) { supportedAntibanding); } - sceneMode = ANDROID_CONTROL_SCENE_MODE_UNSUPPORTED; + sceneMode = ANDROID_CONTROL_SCENE_MODE_DISABLED; params.set(CameraParameters::KEY_SCENE_MODE, CameraParameters::SCENE_MODE_AUTO); @@ -482,7 +486,7 @@ status_t Parameters::initialize(const CameraMetadata *info) { if (addComma) supportedSceneModes += ","; addComma = true; switch (availableSceneModes.data.u8[i]) { - case ANDROID_CONTROL_SCENE_MODE_UNSUPPORTED: + case ANDROID_CONTROL_SCENE_MODE_DISABLED: noSceneModes = true; break; case ANDROID_CONTROL_SCENE_MODE_FACE_PRIORITY: @@ -664,13 +668,13 @@ status_t Parameters::initialize(const CameraMetadata *info) { focusState = ANDROID_CONTROL_AF_STATE_INACTIVE; shadowFocusMode = FOCUS_MODE_INVALID; - camera_metadata_ro_entry_t max3aRegions = - staticInfo(ANDROID_CONTROL_MAX_REGIONS, 1, 1); - if (!max3aRegions.count) return NO_INIT; + camera_metadata_ro_entry_t max3aRegions = staticInfo(ANDROID_CONTROL_MAX_REGIONS, + Parameters::NUM_REGION, Parameters::NUM_REGION); + if (max3aRegions.count != Parameters::NUM_REGION) return NO_INIT; int32_t maxNumFocusAreas = 0; if (focusMode != Parameters::FOCUS_MODE_FIXED) { - maxNumFocusAreas = max3aRegions.data.i32[0]; + maxNumFocusAreas = max3aRegions.data.i32[Parameters::REGION_AF]; } params.set(CameraParameters::KEY_MAX_NUM_FOCUS_AREAS, maxNumFocusAreas); params.set(CameraParameters::KEY_FOCUS_AREAS, @@ -730,7 +734,7 @@ status_t Parameters::initialize(const CameraMetadata *info) { meteringAreas.add(Parameters::Area(0, 0, 0, 0, 0)); params.set(CameraParameters::KEY_MAX_NUM_METERING_AREAS, - max3aRegions.data.i32[0]); + max3aRegions.data.i32[Parameters::REGION_AE]); params.set(CameraParameters::KEY_METERING_AREAS, "(0,0,0,0,0)"); @@ -1127,29 +1131,72 @@ status_t Parameters::set(const String8& paramString) { // RECORDING_HINT (always supported) validatedParams.recordingHint = boolFromString( newParams.get(CameraParameters::KEY_RECORDING_HINT) ); - bool recordingHintChanged = validatedParams.recordingHint != recordingHint; - ALOGV_IF(recordingHintChanged, "%s: Recording hint changed to %d", - __FUNCTION__, recordingHintChanged); + IF_ALOGV() { // Avoid unused variable warning + bool recordingHintChanged = + validatedParams.recordingHint != recordingHint; + if (recordingHintChanged) { + ALOGV("%s: Recording hint changed to %d", + __FUNCTION__, validatedParams.recordingHint); + } + } // PREVIEW_FPS_RANGE - bool fpsRangeChanged = false; - int32_t lastSetFpsRange[2]; - params.getPreviewFpsRange(&lastSetFpsRange[0], &lastSetFpsRange[1]); - lastSetFpsRange[0] /= kFpsToApiScale; - lastSetFpsRange[1] /= kFpsToApiScale; + /** + * Use the single FPS value if it was set later than the range. + * Otherwise, use the range value. + */ + bool fpsUseSingleValue; + { + const char *fpsRange, *fpsSingle; + + fpsRange = params.get(CameraParameters::KEY_PREVIEW_FRAME_RATE); + fpsSingle = params.get(CameraParameters::KEY_PREVIEW_FPS_RANGE); + /** + * Pick either the range or the single key if only one was set. + * + * If both are set, pick the one that has greater set order. + */ + if (fpsRange == NULL && fpsSingle == NULL) { + ALOGE("%s: FPS was not set. One of %s or %s must be set.", + __FUNCTION__, CameraParameters::KEY_PREVIEW_FRAME_RATE, + CameraParameters::KEY_PREVIEW_FPS_RANGE); + return BAD_VALUE; + } else if (fpsRange == NULL) { + fpsUseSingleValue = true; + ALOGV("%s: FPS range not set, using FPS single value", + __FUNCTION__); + } else if (fpsSingle == NULL) { + fpsUseSingleValue = false; + ALOGV("%s: FPS single not set, using FPS range value", + __FUNCTION__); + } else { + int fpsKeyOrder; + res = params.compareSetOrder( + CameraParameters::KEY_PREVIEW_FRAME_RATE, + CameraParameters::KEY_PREVIEW_FPS_RANGE, + &fpsKeyOrder); + LOG_ALWAYS_FATAL_IF(res != OK, "Impossibly bad FPS keys"); + + fpsUseSingleValue = (fpsKeyOrder > 0); + + } + + ALOGV("%s: Preview FPS value is used from '%s'", + __FUNCTION__, fpsUseSingleValue ? "single" : "range"); + } newParams.getPreviewFpsRange(&validatedParams.previewFpsRange[0], &validatedParams.previewFpsRange[1]); validatedParams.previewFpsRange[0] /= kFpsToApiScale; validatedParams.previewFpsRange[1] /= kFpsToApiScale; - // Compare the FPS range value from the last set() to the current set() - // to determine if the client has changed it - if (validatedParams.previewFpsRange[0] != lastSetFpsRange[0] || - validatedParams.previewFpsRange[1] != lastSetFpsRange[1]) { + // Ignore the FPS range if the FPS single has higher precedence + if (!fpsUseSingleValue) { + ALOGV("%s: Preview FPS range (%d, %d)", __FUNCTION__, + validatedParams.previewFpsRange[0], + validatedParams.previewFpsRange[1]); - fpsRangeChanged = true; camera_metadata_ro_entry_t availablePreviewFpsRanges = staticInfo(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, 2); for (i = 0; i < availablePreviewFpsRanges.count; i += 2) { @@ -1200,14 +1247,13 @@ status_t Parameters::set(const String8& paramString) { } } - // PREVIEW_FRAME_RATE Deprecated, only use if the preview fps range is - // unchanged this time. The single-value FPS is the same as the minimum of - // the range. To detect whether the application has changed the value of - // previewFps, compare against their last-set preview FPS. - if (!fpsRangeChanged) { + // PREVIEW_FRAME_RATE Deprecated + // - Use only if the single FPS value was set later than the FPS range + if (fpsUseSingleValue) { int previewFps = newParams.getPreviewFrameRate(); - int lastSetPreviewFps = params.getPreviewFrameRate(); - if (previewFps != lastSetPreviewFps || recordingHintChanged) { + ALOGV("%s: Preview FPS single value requested: %d", + __FUNCTION__, previewFps); + { camera_metadata_ro_entry_t availableFrameRates = staticInfo(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES); /** @@ -1276,6 +1322,35 @@ status_t Parameters::set(const String8& paramString) { } } + /** + * Update Preview FPS and Preview FPS ranges based on + * what we actually set. + * + * This updates the API-visible (Camera.Parameters#getParameters) values of + * the FPS fields, not only the internal versions. + * + * Order matters: The value that was set last takes precedence. + * - If the client does a setParameters(getParameters()) we retain + * the same order for preview FPS. + */ + if (!fpsUseSingleValue) { + // Set fps single, then fps range (range wins) + validatedParams.params.setPreviewFrameRate( + fpsFromRange(/*min*/validatedParams.previewFpsRange[0], + /*max*/validatedParams.previewFpsRange[1])); + validatedParams.params.setPreviewFpsRange( + validatedParams.previewFpsRange[0], + validatedParams.previewFpsRange[1]); + } else { + // Set fps range, then fps single (single wins) + validatedParams.params.setPreviewFpsRange( + validatedParams.previewFpsRange[0], + validatedParams.previewFpsRange[1]); + validatedParams.params.setPreviewFrameRate( + fpsFromRange(/*min*/validatedParams.previewFpsRange[0], + /*max*/validatedParams.previewFpsRange[1])); + } + // PICTURE_SIZE newParams.getPictureSize(&validatedParams.pictureWidth, &validatedParams.pictureHeight); @@ -1446,7 +1521,7 @@ status_t Parameters::set(const String8& paramString) { newParams.get(CameraParameters::KEY_SCENE_MODE) ); if (validatedParams.sceneMode != sceneMode && validatedParams.sceneMode != - ANDROID_CONTROL_SCENE_MODE_UNSUPPORTED) { + ANDROID_CONTROL_SCENE_MODE_DISABLED) { camera_metadata_ro_entry_t availableSceneModes = staticInfo(ANDROID_CONTROL_AVAILABLE_SCENE_MODES); for (i = 0; i < availableSceneModes.count; i++) { @@ -1461,7 +1536,7 @@ status_t Parameters::set(const String8& paramString) { } } bool sceneModeSet = - validatedParams.sceneMode != ANDROID_CONTROL_SCENE_MODE_UNSUPPORTED; + validatedParams.sceneMode != ANDROID_CONTROL_SCENE_MODE_DISABLED; // FLASH_MODE if (sceneModeSet) { @@ -1591,10 +1666,11 @@ status_t Parameters::set(const String8& paramString) { // FOCUS_AREAS res = parseAreas(newParams.get(CameraParameters::KEY_FOCUS_AREAS), &validatedParams.focusingAreas); - size_t max3aRegions = - (size_t)staticInfo(ANDROID_CONTROL_MAX_REGIONS, 1, 1).data.i32[0]; + size_t maxAfRegions = (size_t)staticInfo(ANDROID_CONTROL_MAX_REGIONS, + Parameters::NUM_REGION, Parameters::NUM_REGION). + data.i32[Parameters::REGION_AF]; if (res == OK) res = validateAreas(validatedParams.focusingAreas, - max3aRegions, AREA_KIND_FOCUS); + maxAfRegions, AREA_KIND_FOCUS); if (res != OK) { ALOGE("%s: Requested focus areas are malformed: %s", __FUNCTION__, newParams.get(CameraParameters::KEY_FOCUS_AREAS)); @@ -1624,10 +1700,13 @@ status_t Parameters::set(const String8& paramString) { newParams.get(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK)); // METERING_AREAS + size_t maxAeRegions = (size_t)staticInfo(ANDROID_CONTROL_MAX_REGIONS, + Parameters::NUM_REGION, Parameters::NUM_REGION). + data.i32[Parameters::REGION_AE]; res = parseAreas(newParams.get(CameraParameters::KEY_METERING_AREAS), &validatedParams.meteringAreas); if (res == OK) { - res = validateAreas(validatedParams.meteringAreas, max3aRegions, + res = validateAreas(validatedParams.meteringAreas, maxAeRegions, AREA_KIND_METERING); } if (res != OK) { @@ -1776,7 +1855,7 @@ status_t Parameters::updateRequest(CameraMetadata *request) const { // (face detection statistics and face priority scene mode). Map from other // to the other. bool sceneModeActive = - sceneMode != (uint8_t)ANDROID_CONTROL_SCENE_MODE_UNSUPPORTED; + sceneMode != (uint8_t)ANDROID_CONTROL_SCENE_MODE_DISABLED; uint8_t reqControlMode = ANDROID_CONTROL_MODE_AUTO; if (enableFaceDetect || sceneModeActive) { reqControlMode = ANDROID_CONTROL_MODE_USE_SCENE_MODE; @@ -1788,7 +1867,7 @@ status_t Parameters::updateRequest(CameraMetadata *request) const { uint8_t reqSceneMode = sceneModeActive ? sceneMode : enableFaceDetect ? (uint8_t)ANDROID_CONTROL_SCENE_MODE_FACE_PRIORITY : - (uint8_t)ANDROID_CONTROL_SCENE_MODE_UNSUPPORTED; + (uint8_t)ANDROID_CONTROL_SCENE_MODE_DISABLED; res = request->update(ANDROID_CONTROL_SCENE_MODE, &reqSceneMode, 1); if (res != OK) return res; @@ -1909,6 +1988,23 @@ status_t Parameters::updateRequest(CameraMetadata *request) const { reqMeteringAreas, reqMeteringAreasSize); if (res != OK) return res; + // Set awb regions to be the same as the metering regions if allowed + size_t maxAwbRegions = (size_t)staticInfo(ANDROID_CONTROL_MAX_REGIONS, + Parameters::NUM_REGION, Parameters::NUM_REGION). + data.i32[Parameters::REGION_AWB]; + if (maxAwbRegions > 0) { + if (maxAwbRegions >= meteringAreas.size()) { + res = request->update(ANDROID_CONTROL_AWB_REGIONS, + reqMeteringAreas, reqMeteringAreasSize); + } else { + // Ensure the awb regions are zeroed if the region count is too high. + int32_t zeroedAwbAreas[5] = {0, 0, 0, 0, 0}; + res = request->update(ANDROID_CONTROL_AWB_REGIONS, + zeroedAwbAreas, sizeof(zeroedAwbAreas)/sizeof(int32_t)); + } + if (res != OK) return res; + } + delete[] reqMeteringAreas; /* don't include jpeg thumbnail size - it's valid for @@ -2149,9 +2245,9 @@ int Parameters::abModeStringToEnum(const char *abMode) { int Parameters::sceneModeStringToEnum(const char *sceneMode) { return !sceneMode ? - ANDROID_CONTROL_SCENE_MODE_UNSUPPORTED : + ANDROID_CONTROL_SCENE_MODE_DISABLED : !strcmp(sceneMode, CameraParameters::SCENE_MODE_AUTO) ? - ANDROID_CONTROL_SCENE_MODE_UNSUPPORTED : + ANDROID_CONTROL_SCENE_MODE_DISABLED : !strcmp(sceneMode, CameraParameters::SCENE_MODE_ACTION) ? ANDROID_CONTROL_SCENE_MODE_ACTION : !strcmp(sceneMode, CameraParameters::SCENE_MODE_PORTRAIT) ? diff --git a/services/camera/libcameraservice/api1/client2/Parameters.h b/services/camera/libcameraservice/api1/client2/Parameters.h index 32dbd42..60c4687 100644 --- a/services/camera/libcameraservice/api1/client2/Parameters.h +++ b/services/camera/libcameraservice/api1/client2/Parameters.h @@ -113,6 +113,14 @@ struct Parameters { bool autoExposureLock; bool autoWhiteBalanceLock; + // 3A region types, for use with ANDROID_CONTROL_MAX_REGIONS + enum region_t { + REGION_AE = 0, + REGION_AWB, + REGION_AF, + NUM_REGION // Number of region types + } region; + Vector<Area> meteringAreas; int zoom; diff --git a/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp b/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp index 77ae7ec..2064e2c 100644 --- a/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp +++ b/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp @@ -319,13 +319,15 @@ status_t StreamingProcessor::updateRecordingStream(const Parameters ¶ms) { // Create CPU buffer queue endpoint. We need one more buffer here so that we can // always acquire and free a buffer when the heap is full; otherwise the consumer // will have buffers in flight we'll never clear out. - sp<BufferQueue> bq = new BufferQueue(); - mRecordingConsumer = new BufferItemConsumer(bq, + sp<IGraphicBufferProducer> producer; + sp<IGraphicBufferConsumer> consumer; + BufferQueue::createBufferQueue(&producer, &consumer); + mRecordingConsumer = new BufferItemConsumer(consumer, GRALLOC_USAGE_HW_VIDEO_ENCODER, mRecordingHeapCount + 1); mRecordingConsumer->setFrameAvailableListener(this); mRecordingConsumer->setName(String8("Camera2-RecordingConsumer")); - mRecordingWindow = new Surface(bq); + mRecordingWindow = new Surface(producer); newConsumer = true; // Allocate memory later, since we don't know buffer size until receipt } diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp index 130f81a..6ab9e1a 100644 --- a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp +++ b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp @@ -130,13 +130,15 @@ status_t ZslProcessor::updateStream(const Parameters ¶ms) { if (mZslConsumer == 0) { // Create CPU buffer queue endpoint - sp<BufferQueue> bq = new BufferQueue(); - mZslConsumer = new BufferItemConsumer(bq, + sp<IGraphicBufferProducer> producer; + sp<IGraphicBufferConsumer> consumer; + BufferQueue::createBufferQueue(&producer, &consumer); + mZslConsumer = new BufferItemConsumer(consumer, GRALLOC_USAGE_HW_CAMERA_ZSL, kZslBufferDepth); mZslConsumer->setFrameAvailableListener(this); mZslConsumer->setName(String8("Camera2Client::ZslConsumer")); - mZslWindow = new Surface(bq); + mZslWindow = new Surface(producer); } if (mZslStreamId != NO_STREAM) { diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor3.cpp b/services/camera/libcameraservice/api1/client2/ZslProcessor3.cpp index 2fce2b6..3949b90 100644 --- a/services/camera/libcameraservice/api1/client2/ZslProcessor3.cpp +++ b/services/camera/libcameraservice/api1/client2/ZslProcessor3.cpp @@ -275,6 +275,15 @@ status_t ZslProcessor3::pushToReprocess(int32_t requestId) { return INVALID_OPERATION; } + // Flush device to clear out all in-flight requests pending in HAL. + res = client->getCameraDevice()->flush(); + if (res != OK) { + ALOGE("%s: Camera %d: Failed to flush device: " + "%s (%d)", + __FUNCTION__, client->getCameraId(), strerror(-res), res); + return res; + } + // Update JPEG settings { SharedParameters::Lock l(client->getParameters()); diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp index 142da9e..1c9a342 100644 --- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp +++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp @@ -159,7 +159,7 @@ status_t CameraDeviceClient::submitRequest(sp<CaptureRequest> request, int32_t requestId = mRequestIdCounter++; metadata.update(ANDROID_REQUEST_ID, &requestId, /*size*/1); - ALOGV("%s: Camera %d: Submitting request with ID %d", + ALOGV("%s: Camera %d: Creating request with ID %d", __FUNCTION__, mCameraId, requestId); if (streaming) { @@ -186,6 +186,116 @@ status_t CameraDeviceClient::submitRequest(sp<CaptureRequest> request, return res; } +status_t CameraDeviceClient::submitRequestList(List<sp<CaptureRequest> > requests, + bool streaming) { + ATRACE_CALL(); + ALOGV("%s-start of function", __FUNCTION__); + + status_t res; + if ( (res = checkPid(__FUNCTION__) ) != OK) return res; + + Mutex::Autolock icl(mBinderSerializationLock); + + if (!mDevice.get()) return DEAD_OBJECT; + + if (requests.empty()) { + ALOGE("%s: Camera %d: Sent null request. Rejecting request.", + __FUNCTION__, mCameraId); + return BAD_VALUE; + } + + List<const CameraMetadata> metadataRequestList; + int32_t requestId = mRequestIdCounter; + uint32_t loopCounter = 0; + + for (List<sp<CaptureRequest> >::iterator it = requests.begin(); it != requests.end(); ++it) { + sp<CaptureRequest> request = *it; + if (request == 0) { + ALOGE("%s: Camera %d: Sent null request.", + __FUNCTION__, mCameraId); + return BAD_VALUE; + } + + CameraMetadata metadata(request->mMetadata); + if (metadata.isEmpty()) { + ALOGE("%s: Camera %d: Sent empty metadata packet. Rejecting request.", + __FUNCTION__, mCameraId); + return BAD_VALUE; + } else if (request->mSurfaceList.isEmpty()) { + ALOGE("%s: Camera %d: Requests must have at least one surface target. " + "Rejecting request.", __FUNCTION__, mCameraId); + return BAD_VALUE; + } + + if (!enforceRequestPermissions(metadata)) { + // Callee logs + return PERMISSION_DENIED; + } + + /** + * Write in the output stream IDs which we calculate from + * the capture request's list of surface targets + */ + Vector<int32_t> outputStreamIds; + outputStreamIds.setCapacity(request->mSurfaceList.size()); + for (Vector<sp<Surface> >::iterator surfaceIt = 0; + surfaceIt != request->mSurfaceList.end(); ++surfaceIt) { + sp<Surface> surface = *surfaceIt; + if (surface == 0) continue; + + sp<IGraphicBufferProducer> gbp = surface->getIGraphicBufferProducer(); + int idx = mStreamMap.indexOfKey(gbp->asBinder()); + + // Trying to submit request with surface that wasn't created + if (idx == NAME_NOT_FOUND) { + ALOGE("%s: Camera %d: Tried to submit a request with a surface that" + " we have not called createStream on", + __FUNCTION__, mCameraId); + return BAD_VALUE; + } + + int streamId = mStreamMap.valueAt(idx); + outputStreamIds.push_back(streamId); + ALOGV("%s: Camera %d: Appending output stream %d to request", + __FUNCTION__, mCameraId, streamId); + } + + metadata.update(ANDROID_REQUEST_OUTPUT_STREAMS, &outputStreamIds[0], + outputStreamIds.size()); + + metadata.update(ANDROID_REQUEST_ID, &requestId, /*size*/1); + loopCounter++; // loopCounter starts from 1 + ALOGV("%s: Camera %d: Creating request with ID %d (%d of %d)", + __FUNCTION__, mCameraId, requestId, loopCounter, requests.size()); + + metadataRequestList.push_back(metadata); + } + mRequestIdCounter++; + + if (streaming) { + res = mDevice->setStreamingRequestList(metadataRequestList); + if (res != OK) { + ALOGE("%s: Camera %d: Got error %d after trying to set streaming " + "request", __FUNCTION__, mCameraId, res); + } else { + mStreamingRequestList.push_back(requestId); + } + } else { + res = mDevice->captureList(metadataRequestList); + if (res != OK) { + ALOGE("%s: Camera %d: Got error %d after trying to set capture", + __FUNCTION__, mCameraId, res); + } + } + + ALOGV("%s: Camera %d: End of function", __FUNCTION__, mCameraId); + if (res == OK) { + return requestId; + } + + return res; +} + status_t CameraDeviceClient::cancelRequest(int requestId) { ATRACE_CALL(); ALOGV("%s, requestId = %d", __FUNCTION__, requestId); @@ -635,26 +745,56 @@ status_t CameraDeviceClient::getRotationTransformLocked(int32_t* transform) { return INVALID_OPERATION; } + camera_metadata_ro_entry_t entryFacing = staticInfo.find(ANDROID_LENS_FACING); + if (entry.count == 0) { + ALOGE("%s: Camera %d: Can't find android.lens.facing in " + "static metadata!", __FUNCTION__, mCameraId); + return INVALID_OPERATION; + } + int32_t& flags = *transform; + bool mirror = (entryFacing.data.u8[0] == ANDROID_LENS_FACING_FRONT); int orientation = entry.data.i32[0]; - switch (orientation) { - case 0: - flags = 0; - break; - case 90: - flags = NATIVE_WINDOW_TRANSFORM_ROT_90; - break; - case 180: - flags = NATIVE_WINDOW_TRANSFORM_ROT_180; - break; - case 270: - flags = NATIVE_WINDOW_TRANSFORM_ROT_270; - break; - default: - ALOGE("%s: Invalid HAL android.sensor.orientation value: %d", - __FUNCTION__, orientation); - return INVALID_OPERATION; + if (!mirror) { + switch (orientation) { + case 0: + flags = 0; + break; + case 90: + flags = NATIVE_WINDOW_TRANSFORM_ROT_90; + break; + case 180: + flags = NATIVE_WINDOW_TRANSFORM_ROT_180; + break; + case 270: + flags = NATIVE_WINDOW_TRANSFORM_ROT_270; + break; + default: + ALOGE("%s: Invalid HAL android.sensor.orientation value: %d", + __FUNCTION__, orientation); + return INVALID_OPERATION; + } + } else { + switch (orientation) { + case 0: + flags = HAL_TRANSFORM_FLIP_H; + break; + case 90: + flags = HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_ROT_90; + break; + case 180: + flags = HAL_TRANSFORM_FLIP_V; + break; + case 270: + flags = HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_ROT_90; + break; + default: + ALOGE("%s: Invalid HAL android.sensor.orientation value: %d", + __FUNCTION__, orientation); + return INVALID_OPERATION; + } + } /** diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h index b9c16aa..e96e1ae 100644 --- a/services/camera/libcameraservice/api2/CameraDeviceClient.h +++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h @@ -63,8 +63,11 @@ public: */ // Note that the callee gets a copy of the metadata. - virtual int submitRequest(sp<CaptureRequest> request, - bool streaming = false); + virtual status_t submitRequest(sp<CaptureRequest> request, + bool streaming = false); + // List of requests are copied. + virtual status_t submitRequestList(List<sp<CaptureRequest> > requests, + bool streaming = false); virtual status_t cancelRequest(int requestId); // Returns -EBUSY if device is not idle diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h index e80abf1..a4ae179 100644 --- a/services/camera/libcameraservice/common/CameraDeviceBase.h +++ b/services/camera/libcameraservice/common/CameraDeviceBase.h @@ -22,6 +22,7 @@ #include <utils/String16.h> #include <utils/Vector.h> #include <utils/Timers.h> +#include <utils/List.h> #include "hardware/camera2.h" #include "camera/CameraMetadata.h" @@ -58,12 +59,22 @@ class CameraDeviceBase : public virtual RefBase { virtual status_t capture(CameraMetadata &request) = 0; /** + * Submit a list of requests. + */ + virtual status_t captureList(const List<const CameraMetadata> &requests) = 0; + + /** * Submit request for streaming. The CameraDevice makes a copy of the * passed-in buffer and the caller retains ownership. */ virtual status_t setStreamingRequest(const CameraMetadata &request) = 0; /** + * Submit a list of requests for streaming. + */ + virtual status_t setStreamingRequestList(const List<const CameraMetadata> &requests) = 0; + + /** * Clear the streaming request slot. */ virtual status_t clearStreamingRequest() = 0; diff --git a/services/camera/libcameraservice/device2/Camera2Device.cpp b/services/camera/libcameraservice/device2/Camera2Device.cpp index 2966d82..0cc3a04 100644 --- a/services/camera/libcameraservice/device2/Camera2Device.cpp +++ b/services/camera/libcameraservice/device2/Camera2Device.cpp @@ -112,20 +112,6 @@ status_t Camera2Device::initialize(camera_module_t *module) return res; } - res = device->ops->get_metadata_vendor_tag_ops(device, &mVendorTagOps); - if (res != OK ) { - ALOGE("%s: Camera %d: Unable to retrieve tag ops from device: %s (%d)", - __FUNCTION__, mId, strerror(-res), res); - device->common.close(&device->common); - return res; - } - res = set_camera_metadata_vendor_tag_ops(mVendorTagOps); - if (res != OK) { - ALOGE("%s: Camera %d: Unable to set tag ops: %s (%d)", - __FUNCTION__, mId, strerror(-res), res); - device->common.close(&device->common); - return res; - } res = device->ops->set_notify_callback(device, notificationCallback, NULL); if (res != OK) { @@ -221,6 +207,12 @@ status_t Camera2Device::capture(CameraMetadata &request) { return OK; } +status_t Camera2Device::captureList(const List<const CameraMetadata> &requests) { + ATRACE_CALL(); + ALOGE("%s: Camera2Device burst capture not implemented", __FUNCTION__); + return INVALID_OPERATION; +} + status_t Camera2Device::setStreamingRequest(const CameraMetadata &request) { ATRACE_CALL(); @@ -229,6 +221,12 @@ status_t Camera2Device::setStreamingRequest(const CameraMetadata &request) { return mRequestQueue.setStreamSlot(streamRequest.release()); } +status_t Camera2Device::setStreamingRequestList(const List<const CameraMetadata> &requests) { + ATRACE_CALL(); + ALOGE("%s, Camera2Device streaming burst not implemented", __FUNCTION__); + return INVALID_OPERATION; +} + status_t Camera2Device::clearStreamingRequest() { ATRACE_CALL(); return mRequestQueue.setStreamSlot(NULL); diff --git a/services/camera/libcameraservice/device2/Camera2Device.h b/services/camera/libcameraservice/device2/Camera2Device.h index 1f53c56..61bfd1a 100644 --- a/services/camera/libcameraservice/device2/Camera2Device.h +++ b/services/camera/libcameraservice/device2/Camera2Device.h @@ -48,7 +48,9 @@ class Camera2Device: public CameraDeviceBase { virtual status_t dump(int fd, const Vector<String16>& args); virtual const CameraMetadata& info() const; virtual status_t capture(CameraMetadata &request); + virtual status_t captureList(const List<const CameraMetadata> &requests); virtual status_t setStreamingRequest(const CameraMetadata &request); + virtual status_t setStreamingRequestList(const List<const CameraMetadata> &requests); virtual status_t clearStreamingRequest(); virtual status_t waitUntilRequestReceived(int32_t requestId, nsecs_t timeout); virtual status_t createStream(sp<ANativeWindow> consumer, @@ -78,7 +80,6 @@ class Camera2Device: public CameraDeviceBase { camera2_device_t *mHal2Device; CameraMetadata mDeviceInfo; - vendor_tag_query_ops_t *mVendorTagOps; /** * Queue class for both sending requests to a camera2 device, and for diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp index 7e11a3b..cc192c8 100644 --- a/services/camera/libcameraservice/device3/Camera3Device.cpp +++ b/services/camera/libcameraservice/device3/Camera3Device.cpp @@ -102,8 +102,10 @@ status_t Camera3Device::initialize(camera_module_t *module) camera3_device_t *device; + ATRACE_BEGIN("camera3->open"); res = module->common.methods->open(&module->common, deviceName.string(), reinterpret_cast<hw_device_t**>(&device)); + ATRACE_END(); if (res != OK) { SET_ERR_L("Could not open camera: %s (%d)", strerror(-res), res); @@ -146,24 +148,6 @@ status_t Camera3Device::initialize(camera_module_t *module) return BAD_VALUE; } - /** Get vendor metadata tags */ - - mVendorTagOps.get_camera_vendor_section_name = NULL; - - ATRACE_BEGIN("camera3->get_metadata_vendor_tag_ops"); - device->ops->get_metadata_vendor_tag_ops(device, &mVendorTagOps); - ATRACE_END(); - - if (mVendorTagOps.get_camera_vendor_section_name != NULL) { - res = set_camera_metadata_vendor_tag_ops(&mVendorTagOps); - if (res != OK) { - SET_ERR_L("Unable to set tag ops: %s (%d)", - strerror(-res), res); - device->common.close(&device->common); - return res; - } - } - /** Start up status tracker thread */ mStatusTracker = new StatusTracker(this); res = mStatusTracker->run(String8::format("C3Dev-%d-Status", mId).string()); @@ -271,7 +255,9 @@ status_t Camera3Device::disconnect() { mStatusTracker.clear(); if (mHal3Device != NULL) { + ATRACE_BEGIN("camera3->close"); mHal3Device->common.close(&mHal3Device->common); + ATRACE_END(); mHal3Device = NULL; } @@ -386,6 +372,45 @@ const CameraMetadata& Camera3Device::info() const { return mDeviceInfo; } +status_t Camera3Device::checkStatusOkToCaptureLocked() { + switch (mStatus) { + case STATUS_ERROR: + CLOGE("Device has encountered a serious error"); + return INVALID_OPERATION; + case STATUS_UNINITIALIZED: + CLOGE("Device not initialized"); + return INVALID_OPERATION; + case STATUS_UNCONFIGURED: + case STATUS_CONFIGURED: + case STATUS_ACTIVE: + // OK + break; + default: + SET_ERR_L("Unexpected status: %d", mStatus); + return INVALID_OPERATION; + } + return OK; +} + +status_t Camera3Device::convertMetadataListToRequestListLocked( + const List<const CameraMetadata> &metadataList, RequestList *requestList) { + if (requestList == NULL) { + CLOGE("requestList cannot be NULL."); + return BAD_VALUE; + } + + for (List<const CameraMetadata>::const_iterator it = metadataList.begin(); + it != metadataList.end(); ++it) { + sp<CaptureRequest> newRequest = setUpRequestLocked(*it); + if (newRequest == 0) { + CLOGE("Can't create capture request"); + return BAD_VALUE; + } + requestList->push_back(newRequest); + } + return OK; +} + status_t Camera3Device::capture(CameraMetadata &request) { ATRACE_CALL(); status_t res; @@ -426,10 +451,59 @@ status_t Camera3Device::capture(CameraMetadata &request) { kActiveTimeout/1e9); } ALOGV("Camera %d: Capture request enqueued", mId); + } else { + CLOGE("Cannot queue request. Impossible."); // queueRequest always returns OK. + return BAD_VALUE; } return res; } +status_t Camera3Device::submitRequestsHelper( + const List<const CameraMetadata> &requests, bool repeating) { + ATRACE_CALL(); + Mutex::Autolock il(mInterfaceLock); + Mutex::Autolock l(mLock); + + status_t res = checkStatusOkToCaptureLocked(); + if (res != OK) { + // error logged by previous call + return res; + } + + RequestList requestList; + + res = convertMetadataListToRequestListLocked(requests, /*out*/&requestList); + if (res != OK) { + // error logged by previous call + return res; + } + + if (repeating) { + res = mRequestThread->setRepeatingRequests(requestList); + } else { + res = mRequestThread->queueRequestList(requestList); + } + + if (res == OK) { + waitUntilStateThenRelock(/*active*/true, kActiveTimeout); + if (res != OK) { + SET_ERR_L("Can't transition to active in %f seconds!", + kActiveTimeout/1e9); + } + ALOGV("Camera %d: Capture request enqueued", mId); + } else { + CLOGE("Cannot queue request. Impossible."); + return BAD_VALUE; + } + + return res; +} + +status_t Camera3Device::captureList(const List<const CameraMetadata> &requests) { + ATRACE_CALL(); + + return submitRequestsHelper(requests, /*repeating*/false); +} status_t Camera3Device::setStreamingRequest(const CameraMetadata &request) { ATRACE_CALL(); @@ -476,6 +550,11 @@ status_t Camera3Device::setStreamingRequest(const CameraMetadata &request) { return res; } +status_t Camera3Device::setStreamingRequestList(const List<const CameraMetadata> &requests) { + ATRACE_CALL(); + + return submitRequestsHelper(requests, /*repeating*/true); +} sp<Camera3Device::CaptureRequest> Camera3Device::setUpRequestLocked( const CameraMetadata &request) { @@ -838,16 +917,20 @@ status_t Camera3Device::deleteStream(int id) { } sp<Camera3StreamInterface> deletedStream; + ssize_t outputStreamIdx = mOutputStreams.indexOfKey(id); if (mInputStream != NULL && id == mInputStream->getId()) { deletedStream = mInputStream; mInputStream.clear(); } else { - ssize_t idx = mOutputStreams.indexOfKey(id); - if (idx == NAME_NOT_FOUND) { + if (outputStreamIdx == NAME_NOT_FOUND) { CLOGE("Stream %d does not exist", id); return BAD_VALUE; } - deletedStream = mOutputStreams.editValueAt(idx); + } + + // Delete output stream or the output part of a bi-directional stream. + if (outputStreamIdx != NAME_NOT_FOUND) { + deletedStream = mOutputStreams.editValueAt(outputStreamIdx); mOutputStreams.removeItem(id); } @@ -1122,7 +1205,14 @@ status_t Camera3Device::flush() { Mutex::Autolock l(mLock); mRequestThread->clear(); - return mHal3Device->ops->flush(mHal3Device); + status_t res; + if (mHal3Device->common.version >= CAMERA_DEVICE_API_VERSION_3_1) { + res = mHal3Device->ops->flush(mHal3Device); + } else { + res = waitUntilDrained(); + } + + return res; } /** @@ -1666,8 +1756,10 @@ void Camera3Device::processCaptureResult(const camera3_capture_result *result) { return; } - // Check if everything has arrived for this result (buffers and metadata) - if (request.haveResultMetadata && request.numBuffersLeft == 0) { + // Check if everything has arrived for this result (buffers and metadata), remove it from + // InFlightMap if both arrived or HAL reports error for this request (i.e. during flush). + if ((request.requestStatus != OK) || + (request.haveResultMetadata && request.numBuffersLeft == 0)) { ATRACE_ASYNC_END("frame capture", frameNumber); mInFlightMap.removeItemsAt(idx, 1); } @@ -1898,6 +1990,19 @@ status_t Camera3Device::RequestThread::queueRequest( return OK; } +status_t Camera3Device::RequestThread::queueRequestList( + List<sp<CaptureRequest> > &requests) { + Mutex::Autolock l(mRequestLock); + for (List<sp<CaptureRequest> >::iterator it = requests.begin(); it != requests.end(); + ++it) { + mRequestQueue.push_back(*it); + } + + unpauseForNewRequests(); + + return OK; +} + status_t Camera3Device::RequestThread::queueTrigger( RequestTrigger trigger[], diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h index 468f641..44c6260 100644 --- a/services/camera/libcameraservice/device3/Camera3Device.h +++ b/services/camera/libcameraservice/device3/Camera3Device.h @@ -79,7 +79,9 @@ class Camera3Device : // Capture and setStreamingRequest will configure streams if currently in // idle state virtual status_t capture(CameraMetadata &request); + virtual status_t captureList(const List<const CameraMetadata> &requests); virtual status_t setStreamingRequest(const CameraMetadata &request); + virtual status_t setStreamingRequestList(const List<const CameraMetadata> &requests); virtual status_t clearStreamingRequest(); virtual status_t waitUntilRequestReceived(int32_t requestId, nsecs_t timeout); @@ -157,7 +159,6 @@ class Camera3Device : camera3_device_t *mHal3Device; CameraMetadata mDeviceInfo; - vendor_tag_query_ops_t mVendorTagOps; enum Status { STATUS_ERROR, @@ -202,6 +203,14 @@ class Camera3Device : }; typedef List<sp<CaptureRequest> > RequestList; + status_t checkStatusOkToCaptureLocked(); + + status_t convertMetadataListToRequestListLocked( + const List<const CameraMetadata> &metadataList, + /*out*/RequestList *requestList); + + status_t submitRequestsHelper(const List<const CameraMetadata> &requests, bool repeating); + /** * Get the last request submitted to the hal by the request thread. * @@ -313,6 +322,8 @@ class Camera3Device : status_t queueRequest(sp<CaptureRequest> request); + status_t queueRequestList(List<sp<CaptureRequest> > &requests); + /** * Remove all queued and repeating requests, and pending triggers */ diff --git a/services/camera/libcameraservice/device3/Camera3InputStream.cpp b/services/camera/libcameraservice/device3/Camera3InputStream.cpp index 5aa9a3e..dd7fb6c 100644 --- a/services/camera/libcameraservice/device3/Camera3InputStream.cpp +++ b/services/camera/libcameraservice/device3/Camera3InputStream.cpp @@ -199,14 +199,36 @@ status_t Camera3InputStream::configureQueueLocked() { assert(mMaxSize == 0); assert(camera3_stream::format != HAL_PIXEL_FORMAT_BLOB); - mTotalBufferCount = BufferQueue::MIN_UNDEQUEUED_BUFFERS + - camera3_stream::max_buffers; mDequeuedBufferCount = 0; mFrameCount = 0; if (mConsumer.get() == 0) { - sp<BufferQueue> bq = new BufferQueue(); - mConsumer = new BufferItemConsumer(bq, camera3_stream::usage, + sp<IGraphicBufferProducer> producer; + sp<IGraphicBufferConsumer> consumer; + BufferQueue::createBufferQueue(&producer, &consumer); + + int minUndequeuedBuffers = 0; + res = producer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBuffers); + if (res != OK || minUndequeuedBuffers < 0) { + ALOGE("%s: Stream %d: Could not query min undequeued buffers (error %d, bufCount %d)", + __FUNCTION__, mId, res, minUndequeuedBuffers); + return res; + } + size_t minBufs = static_cast<size_t>(minUndequeuedBuffers); + /* + * We promise never to 'acquire' more than camera3_stream::max_buffers + * at any one time. + * + * Boost the number up to meet the minimum required buffer count. + * + * (Note that this sets consumer-side buffer count only, + * and not the sum of producer+consumer side as in other camera streams). + */ + mTotalBufferCount = camera3_stream::max_buffers > minBufs ? + camera3_stream::max_buffers : minBufs; + // TODO: somehow set the total buffer count when producer connects? + + mConsumer = new BufferItemConsumer(consumer, camera3_stream::usage, mTotalBufferCount); mConsumer->setName(String8::format("Camera3-InputStream-%d", mId)); } diff --git a/services/camera/libcameraservice/device3/Camera3InputStream.h b/services/camera/libcameraservice/device3/Camera3InputStream.h index 681d684..ae49467 100644 --- a/services/camera/libcameraservice/device3/Camera3InputStream.h +++ b/services/camera/libcameraservice/device3/Camera3InputStream.h @@ -44,6 +44,8 @@ class Camera3InputStream : public Camera3IOStreamBase { virtual void dump(int fd, const Vector<String16> &args) const; + // TODO: expose an interface to get the IGraphicBufferProducer + private: typedef BufferItemConsumer::BufferItem BufferItem; diff --git a/services/camera/libcameraservice/device3/Camera3ZslStream.cpp b/services/camera/libcameraservice/device3/Camera3ZslStream.cpp index 44d8188..09e14c5 100644 --- a/services/camera/libcameraservice/device3/Camera3ZslStream.cpp +++ b/services/camera/libcameraservice/device3/Camera3ZslStream.cpp @@ -111,15 +111,17 @@ struct TimestampFinder : public RingBufferConsumer::RingBufferComparator { } // namespace anonymous Camera3ZslStream::Camera3ZslStream(int id, uint32_t width, uint32_t height, - int depth) : + int bufferCount) : Camera3OutputStream(id, CAMERA3_STREAM_BIDIRECTIONAL, width, height, HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED), - mDepth(depth) { + mDepth(bufferCount) { - sp<BufferQueue> bq = new BufferQueue(); - mProducer = new RingBufferConsumer(bq, GRALLOC_USAGE_HW_CAMERA_ZSL, depth); - mConsumer = new Surface(bq); + sp<IGraphicBufferProducer> producer; + sp<IGraphicBufferConsumer> consumer; + BufferQueue::createBufferQueue(&producer, &consumer); + mProducer = new RingBufferConsumer(consumer, GRALLOC_USAGE_HW_CAMERA_ZSL, bufferCount); + mConsumer = new Surface(producer); } Camera3ZslStream::~Camera3ZslStream() { diff --git a/services/camera/libcameraservice/device3/Camera3ZslStream.h b/services/camera/libcameraservice/device3/Camera3ZslStream.h index c7f4490..6721832 100644 --- a/services/camera/libcameraservice/device3/Camera3ZslStream.h +++ b/services/camera/libcameraservice/device3/Camera3ZslStream.h @@ -37,10 +37,10 @@ class Camera3ZslStream : public Camera3OutputStream { public: /** - * Set up a ZSL stream of a given resolution. Depth is the number of buffers + * Set up a ZSL stream of a given resolution. bufferCount is the number of buffers * cached within the stream that can be retrieved for input. */ - Camera3ZslStream(int id, uint32_t width, uint32_t height, int depth); + Camera3ZslStream(int id, uint32_t width, uint32_t height, int bufferCount); ~Camera3ZslStream(); virtual void dump(int fd, const Vector<String16> &args) const; diff --git a/services/camera/libcameraservice/gui/RingBufferConsumer.h b/services/camera/libcameraservice/gui/RingBufferConsumer.h index b4ad824..a03736d 100644 --- a/services/camera/libcameraservice/gui/RingBufferConsumer.h +++ b/services/camera/libcameraservice/gui/RingBufferConsumer.h @@ -64,7 +64,7 @@ class RingBufferConsumer : public ConsumerBase, // bufferCount parameter specifies how many buffers can be pinned for user // access at the same time. RingBufferConsumer(const sp<IGraphicBufferConsumer>& consumer, uint32_t consumerUsage, - int bufferCount = BufferQueue::MIN_UNDEQUEUED_BUFFERS); + int bufferCount); virtual ~RingBufferConsumer(); |