OSDN Git Service

N4 CaptureModule Memory Optimization
authorI-Jong Lin <ijonglin@google.com>
Thu, 12 Feb 2015 21:46:05 +0000 (13:46 -0800)
committerI-Jong Lin <ijonglin@google.com>
Fri, 13 Feb 2015 17:09:53 +0000 (09:09 -0800)
Although functionally correct, there was some processing that was
wasteful of memory in N4 Capture Module.   The two major culprits
are the implicit full-size JPEG decoding for the thumbnail, and
using the capacity (instead of the limit) of the byte buffers when
making a memory copy of the JPEG data.  Fixes include a explicit
subsample value for thumbnail and a tighter memory allocation based on
the limit.

Bug: 19354120
Change-Id: Ibd94c30974753e426254ac002e795b5d1de8bcba

src/com/android/camera/one/v2/imagesaver/JpegImageBackendImageSaver.java
src/com/android/camera/processing/imagebackend/TaskCompressImageToJpeg.java

index 49e69b2..86315d0 100644 (file)
@@ -50,6 +50,9 @@ import javax.annotation.ParametersAreNonnullByDefault;
 public class JpegImageBackendImageSaver implements ImageSaver.Builder {
     private static Log.Tag TAG = new Log.Tag("JpegImgBESaver");
 
+    /** Factor to downsample full-size JPEG image for use in thumbnail bitmap. */
+    private static final int JPEG_DOWNSAMPLE_FOR_FAST_INDICATOR = 4;
+
     @ParametersAreNonnullByDefault
     private static class ImageSaverImpl implements SingleImageSaver {
         private final MainThread mExecutor;
@@ -120,8 +123,13 @@ public class JpegImageBackendImageSaver implements ImageSaver.Builder {
                 TaskImageContainer.CompressedPayload payload) {
             if (task.destination == TaskImageContainer.TaskInfo.Destination.FINAL_IMAGE) {
                 // Just start the thumbnail now, since there's no earlier event.
+
+                // Downsample and convert the JPEG payload to a reasonably-sized Bitmap
+                BitmapFactory.Options options = new BitmapFactory.Options();
+                options.inSampleSize = JPEG_DOWNSAMPLE_FOR_FAST_INDICATOR;
                 final Bitmap bitmap = BitmapFactory.decodeByteArray(payload.data, 0,
-                        payload.data.length);
+                        payload.data.length, options);
+
                 // If the rotation is implemented as an EXIF flag, we need to
                 // pass this information onto the UI call, since the rotation is
                 // NOT applied to the bitmap directly.
index bd7d5f1..9edb158 100644 (file)
@@ -23,7 +23,6 @@ import com.android.camera.Exif;
 import com.android.camera.app.MediaSaver;
 import com.android.camera.app.OrientationManager;
 import com.android.camera.app.OrientationManager.DeviceOrientation;
-import com.android.camera.debug.Log;
 import com.android.camera.exif.ExifInterface;
 import com.android.camera.one.v2.camera2proxy.ImageProxy;
 import com.android.camera.session.CaptureSession;
@@ -68,11 +67,11 @@ public class TaskCompressImageToJpeg extends TaskJpegEncode {
 
     /**
      * Wraps static call to Exif for testability.
-     * @param jpegData  Binary data of the JPEG with EXIF flags
      *
+     * @param jpegData Binary data of the JPEG with EXIF flags
      * @return Degrees of rotation of the EXIF flag
      */
-    public int exifGetOrientation(byte [] jpegData) {
+    public int exifGetOrientation(byte[] jpegData) {
         return Exif.getOrientation(jpegData);
     }
 
@@ -99,7 +98,7 @@ public class TaskCompressImageToJpeg extends TaskJpegEncode {
                     // doesn't work on direct buffers. So, we make a local
                     // copy in a non-direct buffer.
                     ByteBuffer origBuffer = img.proxy.getPlanes().get(0).getBuffer();
-                    compressedData = ByteBuffer.allocate(origBuffer.capacity());
+                    compressedData = ByteBuffer.allocate(origBuffer.limit());
                     origBuffer.rewind();
                     compressedData.put(origBuffer);
                     origBuffer.rewind();
@@ -124,7 +123,7 @@ public class TaskCompressImageToJpeg extends TaskJpegEncode {
 
                 onStart(mId, inputImage, resultImage, TaskInfo.Destination.FINAL_IMAGE);
 
-                numBytes = compressedData.capacity();
+                numBytes = compressedData.limit();
                 break;
             case ImageFormat.YUV_420_888:
                 try {
@@ -210,8 +209,8 @@ public class TaskCompressImageToJpeg extends TaskJpegEncode {
      */
     protected ExifInterface createExif(TaskImage image) {
         ExifInterface exif = new ExifInterface();
-        exif.setTag(exif.buildTag(ExifInterface.TAG_PIXEL_X_DIMENSION, image.width));
-        exif.setTag(exif.buildTag(ExifInterface.TAG_PIXEL_Y_DIMENSION, image.height));
+        exif.setTag(exif.buildTag(ExifInterface.TAG_IMAGE_WIDTH, image.width));
+        exif.setTag(exif.buildTag(ExifInterface.TAG_IMAGE_LENGTH, image.height));
         exif.setTag(exif.buildTag(ExifInterface.TAG_ORIENTATION,
                 ExifInterface.getOrientationValueForRotation(image.orientation.getDegrees())));
         return exif;