summaryrefslogtreecommitdiffstats
path: root/services/camera
diff options
context:
space:
mode:
authorZhijun He <zhijunhe@google.com>2014-04-24 13:27:56 -0700
committerZhijun He <zhijunhe@google.com>2014-04-25 18:12:52 -0700
commitf7da096db8655531c2f2b7bddccd1064b1021155 (patch)
treeae0c3ba796b2da3f069c1f13dc23c49f1838f695 /services/camera
parent67ee990d324229ab0565ce632bd5a04297e16a01 (diff)
downloadframeworks_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/camera')
-rw-r--r--services/camera/libcameraservice/device3/Camera3Device.cpp58
-rw-r--r--services/camera/libcameraservice/device3/Camera3Device.h11
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;