diff options
author | Yin-Chia Yeh <yinchiayeh@google.com> | 2014-06-18 10:51:34 -0700 |
---|---|---|
committer | Yin-Chia Yeh <yinchiayeh@google.com> | 2014-06-20 15:27:33 -0700 |
commit | cd8fce8fbe0f515e53a0ea0f50b739cf42ee57a4 (patch) | |
tree | 1ae578c40cd358b4dd59dc9f4dbb4a9cc1d2418b /services | |
parent | f5fe801c6e00d99e5dcf15cdbfd3bc5402715089 (diff) | |
download | frameworks_av-cd8fce8fbe0f515e53a0ea0f50b739cf42ee57a4.zip frameworks_av-cd8fce8fbe0f515e53a0ea0f50b739cf42ee57a4.tar.gz frameworks_av-cd8fce8fbe0f515e53a0ea0f50b739cf42ee57a4.tar.bz2 |
Camera2: get stream configs by device verison
Starting from device version 3.2, the following tags:
ANDROID_SCALER_AVAILABLE_FORMATS
ANDROID_SCALER_AVAILABLE_JPEG_MIN_DURATIONS
ANDROID_SCALER_AVAILABLE_JPEG_SIZES
ANDROID_SCALER_AVAILABLE_PROCESSED_MIN_DURATIONS
ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES
ANDROID_SCALER_AVAILABLE_RAW_MIN_DURATIONS
ANDROID_SCALER_AVAILABLE_RAW_SIZES
are deprecated and replaced by:
ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS
Change-Id: Iadc34af0ea985a16a25759d7a9a3eb4845c486fd
Diffstat (limited to 'services')
9 files changed, 231 insertions, 82 deletions
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index 109b891..648e82c 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -689,8 +689,7 @@ status_t CameraService::connectHelperLocked(const sp<ICameraClient>& cameraClien case CAMERA_DEVICE_API_VERSION_3_2: client = new Camera2Client(this, cameraClient, clientPackageName, cameraId, - facing, callingPid, clientUid, getpid(), - deviceVersion); + facing, callingPid, clientUid, getpid()); break; case -1: ALOGE("Invalid camera id %d", cameraId); diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp index 0447979..a6f5a6c 100644 --- a/services/camera/libcameraservice/api1/Camera2Client.cpp +++ b/services/camera/libcameraservice/api1/Camera2Client.cpp @@ -53,12 +53,10 @@ Camera2Client::Camera2Client(const sp<CameraService>& cameraService, int cameraFacing, int clientPid, uid_t clientUid, - int servicePid, - int deviceVersion): + int servicePid): Camera2ClientBase(cameraService, cameraClient, clientPackageName, cameraId, cameraFacing, clientPid, clientUid, servicePid), - mParameters(cameraId, cameraFacing), - mDeviceVersion(deviceVersion) + mParameters(cameraId, cameraFacing) { ATRACE_CALL(); @@ -80,7 +78,7 @@ status_t Camera2Client::initialize(camera_module_t *module) { SharedParameters::Lock l(mParameters); - res = l.mParameters.initialize(&(mDevice->info())); + res = l.mParameters.initialize(&(mDevice->info()), mDeviceVersion); if (res != OK) { ALOGE("%s: Camera %d: unable to build defaults: %s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); diff --git a/services/camera/libcameraservice/api1/Camera2Client.h b/services/camera/libcameraservice/api1/Camera2Client.h index fe0bf74..0e06195 100644 --- a/services/camera/libcameraservice/api1/Camera2Client.h +++ b/services/camera/libcameraservice/api1/Camera2Client.h @@ -89,8 +89,7 @@ public: int cameraFacing, int clientPid, uid_t clientUid, - int servicePid, - int deviceVersion); + int servicePid); virtual ~Camera2Client(); @@ -170,7 +169,6 @@ private: void setPreviewCallbackFlagL(Parameters ¶ms, int flag); status_t updateRequests(Parameters ¶ms); - int mDeviceVersion; // Used with stream IDs static const int NO_STREAM = -1; diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp index 51b1980..6459300 100644 --- a/services/camera/libcameraservice/api1/client2/Parameters.cpp +++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp @@ -29,6 +29,7 @@ #include "Parameters.h" #include "system/camera.h" +#include "hardware/camera_common.h" #include <media/MediaProfiles.h> #include <media/mediarecorder.h> @@ -45,7 +46,7 @@ Parameters::Parameters(int cameraId, Parameters::~Parameters() { } -status_t Parameters::initialize(const CameraMetadata *info) { +status_t Parameters::initialize(const CameraMetadata *info, int deviceVersion) { status_t res; if (info->entryCount() == 0) { @@ -53,6 +54,7 @@ status_t Parameters::initialize(const CameraMetadata *info) { return BAD_VALUE; } Parameters::info = info; + mDeviceVersion = deviceVersion; res = buildFastInfo(); if (res != OK) return res; @@ -140,16 +142,14 @@ status_t Parameters::initialize(const CameraMetadata *info) { previewTransform = degToTransform(0, cameraFacing == CAMERA_FACING_FRONT); - camera_metadata_ro_entry_t availableFormats = - staticInfo(ANDROID_SCALER_AVAILABLE_FORMATS); - { String8 supportedPreviewFormats; + SortedVector<int32_t> outputFormats = getAvailableOutputFormats(); bool addComma = false; - for (size_t i=0; i < availableFormats.count; i++) { + for (size_t i=0; i < outputFormats.size(); i++) { if (addComma) supportedPreviewFormats += ","; addComma = true; - switch (availableFormats.data.i32[i]) { + switch (outputFormats[i]) { case HAL_PIXEL_FORMAT_YCbCr_422_SP: supportedPreviewFormats += CameraParameters::PIXEL_FORMAT_YUV422SP; @@ -191,7 +191,7 @@ status_t Parameters::initialize(const CameraMetadata *info) { default: ALOGW("%s: Camera %d: Unknown preview format: %x", - __FUNCTION__, cameraId, availableFormats.data.i32[i]); + __FUNCTION__, cameraId, outputFormats[i]); addComma = false; break; } @@ -239,24 +239,23 @@ status_t Parameters::initialize(const CameraMetadata *info) { supportedPreviewFrameRates); } - camera_metadata_ro_entry_t availableJpegSizes = - staticInfo(ANDROID_SCALER_AVAILABLE_JPEG_SIZES, 2); - if (!availableJpegSizes.count) return NO_INIT; + Vector<Size> availableJpegSizes = getAvailableJpegSizes(); + if (!availableJpegSizes.size()) return NO_INIT; // TODO: Pick maximum - pictureWidth = availableJpegSizes.data.i32[0]; - pictureHeight = availableJpegSizes.data.i32[1]; + pictureWidth = availableJpegSizes[0].width; + pictureHeight = availableJpegSizes[0].height; params.setPictureSize(pictureWidth, pictureHeight); { String8 supportedPictureSizes; - for (size_t i=0; i < availableJpegSizes.count; i += 2) { + for (size_t i=0; i < availableJpegSizes.size(); i++) { if (i != 0) supportedPictureSizes += ","; supportedPictureSizes += String8::format("%dx%d", - availableJpegSizes.data.i32[i], - availableJpegSizes.data.i32[i+1]); + availableJpegSizes[i].width, + availableJpegSizes[i].height); } params.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, supportedPictureSizes); @@ -952,9 +951,8 @@ status_t Parameters::buildFastInfo() { staticInfo(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS); if (!availableFocalLengths.count) return NO_INIT; - camera_metadata_ro_entry_t availableFormats = - staticInfo(ANDROID_SCALER_AVAILABLE_FORMATS); - if (!availableFormats.count) return NO_INIT; + SortedVector<int32_t> availableFormats = getAvailableOutputFormats(); + if (!availableFormats.size()) return NO_INIT; if (sceneModeOverrides.count > 0) { @@ -1038,8 +1036,8 @@ status_t Parameters::buildFastInfo() { // Check if the HAL supports HAL_PIXEL_FORMAT_YCbCr_420_888 fastInfo.useFlexibleYuv = false; - for (size_t i = 0; i < availableFormats.count; i++) { - if (availableFormats.data.i32[i] == HAL_PIXEL_FORMAT_YCbCr_420_888) { + for (size_t i = 0; i < availableFormats.size(); i++) { + if (availableFormats[i] == HAL_PIXEL_FORMAT_YCbCr_420_888) { fastInfo.useFlexibleYuv = true; break; } @@ -1198,8 +1196,7 @@ status_t Parameters::set(const String8& paramString) { "is active!", __FUNCTION__); return BAD_VALUE; } - camera_metadata_ro_entry_t availableFormats = - staticInfo(ANDROID_SCALER_AVAILABLE_FORMATS); + SortedVector<int32_t> availableFormats = getAvailableOutputFormats(); // If using flexible YUV, always support NV21/YV12. Otherwise, check // HAL's list. if (! (fastInfo.useFlexibleYuv && @@ -1208,11 +1205,10 @@ status_t Parameters::set(const String8& paramString) { validatedParams.previewFormat == HAL_PIXEL_FORMAT_YV12) ) ) { // Not using flexible YUV format, so check explicitly - for (i = 0; i < availableFormats.count; i++) { - if (availableFormats.data.i32[i] == - validatedParams.previewFormat) break; + for (i = 0; i < availableFormats.size(); i++) { + if (availableFormats[i] == validatedParams.previewFormat) break; } - if (i == availableFormats.count) { + if (i == availableFormats.size()) { ALOGE("%s: Requested preview format %s (0x%x) is not supported", __FUNCTION__, newParams.getPreviewFormat(), validatedParams.previewFormat); @@ -1302,15 +1298,14 @@ status_t Parameters::set(const String8& paramString) { &validatedParams.pictureHeight); if (validatedParams.pictureWidth == pictureWidth || validatedParams.pictureHeight == pictureHeight) { - camera_metadata_ro_entry_t availablePictureSizes = - staticInfo(ANDROID_SCALER_AVAILABLE_JPEG_SIZES); - for (i = 0; i < availablePictureSizes.count; i+=2) { - if ((availablePictureSizes.data.i32[i] == + Vector<Size> availablePictureSizes = getAvailableJpegSizes(); + for (i = 0; i < availablePictureSizes.size(); i++) { + if ((availablePictureSizes[i].width == validatedParams.pictureWidth) && - (availablePictureSizes.data.i32[i+1] == + (availablePictureSizes[i].height == validatedParams.pictureHeight)) break; } - if (i == availablePictureSizes.count) { + if (i == availablePictureSizes.size()) { ALOGE("%s: Requested picture size %d x %d is not supported", __FUNCTION__, validatedParams.pictureWidth, validatedParams.pictureHeight); @@ -2527,22 +2522,37 @@ status_t Parameters::getFilteredSizes(Size limit, Vector<Size> *sizes) { ALOGE("%s: Input size is null", __FUNCTION__); return BAD_VALUE; } - - const size_t SIZE_COUNT = sizeof(Size) / sizeof(int); - camera_metadata_ro_entry_t availableProcessedSizes = - staticInfo(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES, SIZE_COUNT); - if (availableProcessedSizes.count < SIZE_COUNT) return BAD_VALUE; - - Size filteredSize; - for (size_t i = 0; i < availableProcessedSizes.count; i += SIZE_COUNT) { - filteredSize.width = availableProcessedSizes.data.i32[i]; - filteredSize.height = availableProcessedSizes.data.i32[i+1]; - // Need skip the preview sizes that are too large. - if (filteredSize.width <= limit.width && - filteredSize.height <= limit.height) { - sizes->push(filteredSize); + sizes->clear(); + + if (mDeviceVersion >= CAMERA_DEVICE_API_VERSION_3_2) { + Vector<StreamConfiguration> scs = getStreamConfigurations(); + for (size_t i=0; i < scs.size(); i++) { + const StreamConfiguration &sc = scs[i]; + if (sc.isInput == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT && + sc.format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED && + sc.width <= limit.width && sc.height <= limit.height) { + Size sz = {sc.width, sc.height}; + sizes->push(sz); } + } + } else { + const size_t SIZE_COUNT = sizeof(Size) / sizeof(int); + camera_metadata_ro_entry_t availableProcessedSizes = + staticInfo(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES, SIZE_COUNT); + if (availableProcessedSizes.count < SIZE_COUNT) return BAD_VALUE; + + Size filteredSize; + for (size_t i = 0; i < availableProcessedSizes.count; i += SIZE_COUNT) { + filteredSize.width = availableProcessedSizes.data.i32[i]; + filteredSize.height = availableProcessedSizes.data.i32[i+1]; + // Need skip the preview sizes that are too large. + if (filteredSize.width <= limit.width && + filteredSize.height <= limit.height) { + sizes->push(filteredSize); + } + } } + if (sizes->isEmpty()) { ALOGE("generated preview size list is empty!!"); return BAD_VALUE; @@ -2576,6 +2586,78 @@ Parameters::Size Parameters::getMaxSizeForRatio( return maxSize; } +Vector<Parameters::StreamConfiguration> Parameters::getStreamConfigurations() { + const int STREAM_CONFIGURATION_SIZE = 4; + const int STREAM_FORMAT_OFFSET = 0; + const int STREAM_WIDTH_OFFSET = 1; + const int STREAM_HEIGHT_OFFSET = 2; + const int STREAM_IS_INPUT_OFFSET = 3; + Vector<StreamConfiguration> scs; + if (mDeviceVersion < CAMERA_DEVICE_API_VERSION_3_2) { + ALOGE("StreamConfiguration is only valid after device HAL 3.2!"); + return scs; + } + + camera_metadata_ro_entry_t availableStreamConfigs = + staticInfo(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS); + for (size_t i=0; i < availableStreamConfigs.count; i+= STREAM_CONFIGURATION_SIZE) { + int32_t format = availableStreamConfigs.data.i32[i + STREAM_FORMAT_OFFSET]; + int32_t width = availableStreamConfigs.data.i32[i + STREAM_WIDTH_OFFSET]; + int32_t height = availableStreamConfigs.data.i32[i + STREAM_HEIGHT_OFFSET]; + int32_t isInput = availableStreamConfigs.data.i32[i + STREAM_IS_INPUT_OFFSET]; + StreamConfiguration sc = {format, width, height, isInput}; + scs.add(sc); + } + return scs; +} + +SortedVector<int32_t> Parameters::getAvailableOutputFormats() { + SortedVector<int32_t> outputFormats; // Non-duplicated output formats + if (mDeviceVersion >= CAMERA_DEVICE_API_VERSION_3_2) { + Vector<StreamConfiguration> scs = getStreamConfigurations(); + for (size_t i=0; i < scs.size(); i++) { + const StreamConfiguration &sc = scs[i]; + if (sc.isInput == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT) { + outputFormats.add(sc.format); + } + } + } else { + camera_metadata_ro_entry_t availableFormats = staticInfo(ANDROID_SCALER_AVAILABLE_FORMATS); + for (size_t i=0; i < availableFormats.count; i++) { + outputFormats.add(availableFormats.data.i32[i]); + } + } + return outputFormats; +} + +Vector<Parameters::Size> Parameters::getAvailableJpegSizes() { + Vector<Parameters::Size> jpegSizes; + if (mDeviceVersion >= CAMERA_DEVICE_API_VERSION_3_2) { + Vector<StreamConfiguration> scs = getStreamConfigurations(); + for (size_t i=0; i < scs.size(); i++) { + const StreamConfiguration &sc = scs[i]; + if (sc.isInput == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT && + sc.format == HAL_PIXEL_FORMAT_BLOB) { + Size sz = {sc.width, sc.height}; + jpegSizes.add(sz); + } + } + } else { + const int JPEG_SIZE_ENTRY_COUNT = 2; + const int WIDTH_OFFSET = 0; + const int HEIGHT_OFFSET = 1; + camera_metadata_ro_entry_t availableJpegSizes = + staticInfo(ANDROID_SCALER_AVAILABLE_JPEG_SIZES); + for (size_t i=0; i < availableJpegSizes.count; i+= JPEG_SIZE_ENTRY_COUNT) { + int width = availableJpegSizes.data.i32[i + WIDTH_OFFSET]; + int height = availableJpegSizes.data.i32[i + HEIGHT_OFFSET]; + Size sz = {width, height}; + jpegSizes.add(sz); + } + } + return jpegSizes; +} + Parameters::CropRegion Parameters::calculateCropRegion( Parameters::CropRegion::Outputs outputs) const { diff --git a/services/camera/libcameraservice/api1/client2/Parameters.h b/services/camera/libcameraservice/api1/client2/Parameters.h index 28dd788..f95c69a 100644 --- a/services/camera/libcameraservice/api1/client2/Parameters.h +++ b/services/camera/libcameraservice/api1/client2/Parameters.h @@ -226,7 +226,7 @@ struct Parameters { ~Parameters(); // Sets up default parameters - status_t initialize(const CameraMetadata *info); + status_t initialize(const CameraMetadata *info, int deviceVersion); // Build fast-access device static info from static info status_t buildFastInfo(); @@ -346,6 +346,24 @@ private: status_t getFilteredSizes(Size limit, Vector<Size> *sizes); // Get max size (from the size array) that matches the given aspect ratio. Size getMaxSizeForRatio(float ratio, const int32_t* sizeArray, size_t count); + + struct StreamConfiguration { + int32_t format; + int32_t width; + int32_t height; + int32_t isInput; + }; + // Helper function extract available stream configuration + // Only valid since device HAL version 3.2 + // returns an empty Vector if device HAL version does support it + Vector<StreamConfiguration> getStreamConfigurations(); + + // Helper function to get non-duplicated available output formats + SortedVector<int32_t> getAvailableOutputFormats(); + // Helper function to get available output jpeg sizes + Vector<Size> getAvailableJpegSizes(); + + int mDeviceVersion; }; // This class encapsulates the Parameters class so that it can only be accessed diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp index 19efd30..13c9f48 100644 --- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp +++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp @@ -54,7 +54,8 @@ Camera2ClientBase<TClientBase>::Camera2ClientBase( int servicePid): TClientBase(cameraService, remoteCallback, clientPackageName, cameraId, cameraFacing, clientPid, clientUid, servicePid), - mSharedCameraCallbacks(remoteCallback) + mSharedCameraCallbacks(remoteCallback), + mDeviceVersion(cameraService->getDeviceVersion(cameraId)) { ALOGI("Camera %d: Opened", cameraId); @@ -280,6 +281,11 @@ int Camera2ClientBase<TClientBase>::getCameraId() const { } template <typename TClientBase> +int Camera2ClientBase<TClientBase>::getCameraDeviceVersion() const { + return mDeviceVersion; +} + +template <typename TClientBase> const sp<CameraDeviceBase>& Camera2ClientBase<TClientBase>::getCameraDevice() { return mDevice; } diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.h b/services/camera/libcameraservice/common/Camera2ClientBase.h index 9feca93..f57d204 100644 --- a/services/camera/libcameraservice/common/Camera2ClientBase.h +++ b/services/camera/libcameraservice/common/Camera2ClientBase.h @@ -76,6 +76,7 @@ public: int getCameraId() const; const sp<CameraDeviceBase>& getCameraDevice(); + int getCameraDeviceVersion() const; const sp<CameraService>& getCameraService(); @@ -122,6 +123,7 @@ protected: /** CameraDeviceBase instance wrapping HAL2+ entry */ + const int mDeviceVersion; sp<CameraDeviceBase> mDevice; /** Utility members */ diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp index a5839ae..24df819 100644 --- a/services/camera/libcameraservice/device3/Camera3Device.cpp +++ b/services/camera/libcameraservice/device3/Camera3Device.cpp @@ -113,7 +113,6 @@ status_t Camera3Device::initialize(camera_module_t *module) } /** Cross-check device version */ - if (device->common.version < CAMERA_DEVICE_API_VERSION_3_0) { SET_ERR_L("Could not open camera: " "Camera device should be at least %x, reports %x instead", @@ -173,6 +172,7 @@ status_t Camera3Device::initialize(camera_module_t *module) /** Everything is good to go */ + mDeviceVersion = device->common.version; mDeviceInfo = info.static_camera_characteristics; mHal3Device = device; mStatus = STATUS_UNCONFIGURED; @@ -284,42 +284,74 @@ bool Camera3Device::tryLockSpinRightRound(Mutex& lock) { return gotLock; } -ssize_t Camera3Device::getJpegBufferSize(uint32_t width, uint32_t height) const { - // TODO: replace below with availableStreamConfiguration for HAL3.2+. - camera_metadata_ro_entry availableJpegSizes = - mDeviceInfo.find(ANDROID_SCALER_AVAILABLE_JPEG_SIZES); - if (availableJpegSizes.count == 0 || availableJpegSizes.count % 2 != 0) { - ALOGE("%s: Camera %d: Can't find find valid available jpeg sizes in static metadata!", - __FUNCTION__, mId); - return BAD_VALUE; - } - - // Get max jpeg size (area-wise). +Camera3Device::Size Camera3Device::getMaxJpegResolution() const { int32_t maxJpegWidth = 0, maxJpegHeight = 0; - bool foundMax = false; - for (size_t i = 0; i < availableJpegSizes.count; i += 2) { - if ((availableJpegSizes.data.i32[i] * availableJpegSizes.data.i32[i + 1]) - > (maxJpegWidth * maxJpegHeight)) { - maxJpegWidth = availableJpegSizes.data.i32[i]; - maxJpegHeight = availableJpegSizes.data.i32[i + 1]; - foundMax = true; + if (mDeviceVersion >= CAMERA_DEVICE_API_VERSION_3_2) { + const int STREAM_CONFIGURATION_SIZE = 4; + const int STREAM_FORMAT_OFFSET = 0; + const int STREAM_WIDTH_OFFSET = 1; + const int STREAM_HEIGHT_OFFSET = 2; + const int STREAM_IS_INPUT_OFFSET = 3; + camera_metadata_ro_entry_t availableStreamConfigs = + mDeviceInfo.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS); + if (availableStreamConfigs.count == 0 || + availableStreamConfigs.count % STREAM_CONFIGURATION_SIZE != 0) { + return Size(0, 0); + } + + // Get max jpeg size (area-wise). + for (size_t i=0; i < availableStreamConfigs.count; i+= STREAM_CONFIGURATION_SIZE) { + int32_t format = availableStreamConfigs.data.i32[i + STREAM_FORMAT_OFFSET]; + int32_t width = availableStreamConfigs.data.i32[i + STREAM_WIDTH_OFFSET]; + int32_t height = availableStreamConfigs.data.i32[i + STREAM_HEIGHT_OFFSET]; + int32_t isInput = availableStreamConfigs.data.i32[i + STREAM_IS_INPUT_OFFSET]; + if (isInput == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT + && format == HAL_PIXEL_FORMAT_BLOB && + (width * height > maxJpegWidth * maxJpegHeight)) { + maxJpegWidth = width; + maxJpegHeight = height; + } + } + } else { + camera_metadata_ro_entry availableJpegSizes = + mDeviceInfo.find(ANDROID_SCALER_AVAILABLE_JPEG_SIZES); + if (availableJpegSizes.count == 0 || availableJpegSizes.count % 2 != 0) { + return Size(0, 0); + } + + // Get max jpeg size (area-wise). + for (size_t i = 0; i < availableJpegSizes.count; i += 2) { + if ((availableJpegSizes.data.i32[i] * availableJpegSizes.data.i32[i + 1]) + > (maxJpegWidth * maxJpegHeight)) { + maxJpegWidth = availableJpegSizes.data.i32[i]; + maxJpegHeight = availableJpegSizes.data.i32[i + 1]; + } } } - if (!foundMax) { + return Size(maxJpegWidth, maxJpegHeight); +} + +ssize_t Camera3Device::getJpegBufferSize(uint32_t width, uint32_t height) const { + // Get max jpeg size (area-wise). + Size maxJpegResolution = getMaxJpegResolution(); + if (maxJpegResolution.width == 0) { + ALOGE("%s: Camera %d: Can't find find valid available jpeg sizes in static metadata!", + __FUNCTION__, mId); return BAD_VALUE; } // Get max jpeg buffer size ssize_t maxJpegBufferSize = 0; - camera_metadata_ro_entry jpegMaxSize = mDeviceInfo.find(ANDROID_JPEG_MAX_SIZE); - if (jpegMaxSize.count == 0) { + camera_metadata_ro_entry jpegBufMaxSize = mDeviceInfo.find(ANDROID_JPEG_MAX_SIZE); + if (jpegBufMaxSize.count == 0) { ALOGE("%s: Camera %d: Can't find maximum JPEG size in static metadata!", __FUNCTION__, mId); return BAD_VALUE; } - maxJpegBufferSize = jpegMaxSize.data.i32[0]; + maxJpegBufferSize = jpegBufMaxSize.data.i32[0]; // Calculate final jpeg buffer size for the given resolution. - float scaleFactor = ((float) (width * height)) / (maxJpegWidth * maxJpegHeight); + float scaleFactor = ((float) (width * height)) / + (maxJpegResolution.width * maxJpegResolution.height); ssize_t jpegBufferSize = scaleFactor * maxJpegBufferSize; // Bound the buffer size to [MIN_JPEG_BUFFER_SIZE, maxJpegBufferSize]. if (jpegBufferSize > maxJpegBufferSize) { diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h index 8e238e5..61e6572 100644 --- a/services/camera/libcameraservice/device3/Camera3Device.h +++ b/services/camera/libcameraservice/device3/Camera3Device.h @@ -168,6 +168,8 @@ class Camera3Device : CameraMetadata mDeviceInfo; + int mDeviceVersion; + enum Status { STATUS_ERROR, STATUS_UNINITIALIZED, @@ -297,6 +299,18 @@ class Camera3Device : */ bool tryLockSpinRightRound(Mutex& lock); + struct Size { + int width; + int height; + Size(int w, int h) : width(w), height(h){} + }; + + /** + * Helper function to get the largest Jpeg resolution (in area) + * Return Size(0, 0) if static metatdata is invalid + */ + Size getMaxJpegResolution() const; + /** * Get Jpeg buffer size for a given jpeg resolution. * Negative values are error codes. |