diff options
author | Zhijun He <zhijunhe@google.com> | 2014-04-24 13:27:56 -0700 |
---|---|---|
committer | Zhijun He <zhijunhe@google.com> | 2014-04-25 18:12:52 -0700 |
commit | f7da096db8655531c2f2b7bddccd1064b1021155 (patch) | |
tree | ae0c3ba796b2da3f069c1f13dc23c49f1838f695 /services | |
parent | 67ee990d324229ab0565ce632bd5a04297e16a01 (diff) | |
download | frameworks_av-f7da096db8655531c2f2b7bddccd1064b1021155.zip frameworks_av-f7da096db8655531c2f2b7bddccd1064b1021155.tar.gz frameworks_av-f7da096db8655531c2f2b7bddccd1064b1021155.tar.bz2 |
Camera3: scale the max jpeg buffer size based on resolutions
The max jpeg buffer size was always the android.jpeg.maxSize, regardless of
the actual jpeg capture size. This creates a huge memory waste especially
for smaller size jpeg capture. Now the max jpeg buffer is linearly scaled based
on the resolution.
Bug: 14288983
Change-Id: I8a971b8e2f4fc7fec0154547bdb688579af71a47
Diffstat (limited to 'services')
-rw-r--r-- | services/camera/libcameraservice/device3/Camera3Device.cpp | 58 | ||||
-rw-r--r-- | services/camera/libcameraservice/device3/Camera3Device.h | 11 |
2 files changed, 67 insertions, 2 deletions
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp index c7abe3a..2f874f5 100644 --- a/services/camera/libcameraservice/device3/Camera3Device.cpp +++ b/services/camera/libcameraservice/device3/Camera3Device.cpp @@ -284,6 +284,53 @@ 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). + 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 (!foundMax) { + 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) { + ALOGE("%s: Camera %d: Can't find maximum JPEG size in static metadata!", __FUNCTION__, mId); + return BAD_VALUE; + } + maxJpegBufferSize = jpegMaxSize.data.i32[0]; + + // Calculate final jpeg buffer size for the given resolution. + float scaleFactor = ((float) (width * height)) / (maxJpegWidth * maxJpegHeight); + ssize_t jpegBufferSize = scaleFactor * maxJpegBufferSize; + // Bound the buffer size to [MIN_JPEG_BUFFER_SIZE, maxJpegBufferSize]. + if (jpegBufferSize > maxJpegBufferSize) { + jpegBufferSize = maxJpegBufferSize; + } else if (jpegBufferSize < kMinJpegBufferSize) { + jpegBufferSize = kMinJpegBufferSize; + } + + return jpegBufferSize; +} + status_t Camera3Device::dump(int fd, const Vector<String16> &args) { ATRACE_CALL(); (void)args; @@ -741,8 +788,17 @@ status_t Camera3Device::createStream(sp<ANativeWindow> consumer, sp<Camera3OutputStream> newStream; if (format == HAL_PIXEL_FORMAT_BLOB) { + ssize_t jpegBufferSize = getJpegBufferSize(width, height); + if (jpegBufferSize > 0) { + ALOGV("%s: Overwrite Jpeg output buffer size from %zu to %zu", + __FUNCTION__, size, jpegBufferSize); + } else { + SET_ERR_L("Invalid jpeg buffer size %zd", jpegBufferSize); + return BAD_VALUE; + } + newStream = new Camera3OutputStream(mNextStreamId, consumer, - width, height, size, format); + width, height, jpegBufferSize, format); } else { newStream = new Camera3OutputStream(mNextStreamId, consumer, width, height, format); diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h index 3ef39f3..00ae771 100644 --- a/services/camera/libcameraservice/device3/Camera3Device.h +++ b/services/camera/libcameraservice/device3/Camera3Device.h @@ -93,7 +93,8 @@ class Camera3Device : // Actual stream creation/deletion is delayed until first request is submitted // If adding streams while actively capturing, will pause device before adding - // stream, reconfiguring device, and unpausing. + // stream, reconfiguring device, and unpausing. Note that, for JPEG stream, the + // buffer size may be overwritten by an more accurate value calculated by Camera3Device. virtual status_t createStream(sp<ANativeWindow> consumer, uint32_t width, uint32_t height, int format, size_t size, int *id); @@ -144,6 +145,8 @@ class Camera3Device : static const nsecs_t kShutdownTimeout = 5000000000; // 5 sec static const nsecs_t kActiveTimeout = 500000000; // 500 ms struct RequestTrigger; + // minimal jpeg buffer size: 256KB + blob header + static const ssize_t kMinJpegBufferSize = 256 * 1024 + sizeof(camera3_jpeg_blob); // A lock to enforce serialization on the input/configure side // of the public interface. @@ -294,6 +297,12 @@ class Camera3Device : */ bool tryLockSpinRightRound(Mutex& lock); + /** + * Get Jpeg buffer size for a given jpeg resolution. + * Negative values are error codes. + */ + ssize_t getJpegBufferSize(uint32_t width, uint32_t height) const; + struct RequestTrigger { // Metadata tag number, e.g. android.control.aePrecaptureTrigger uint32_t metadataTag; |