Merge "Fix 5156702: rotate thumbnails"
diff --git a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
index aa0a2e9..d7b8eaa 100644
--- a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
+++ b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
@@ -3758,65 +3758,33 @@
 
     /**
      * This method extracts a frame from the input file
-     * and returns the frame as a bitmap
-     *
-     * @param inputFile The inputFile
-     * @param width The width of the output frame
-     * @param height The height of the output frame
-     * @param timeMS The time in ms at which the frame has to be extracted
+     * and returns the frame as a bitmap. See getPixelsList() for more information.
      */
-    Bitmap getPixels(String inputFile, int width, int height, long timeMS) {
-        if (inputFile == null) {
-            throw new IllegalArgumentException("Invalid input file");
-        }
-
-        /* Make width and height as even */
-        final int newWidth = (width + 1) & 0xFFFFFFFE;
-        final int newHeight = (height + 1) & 0xFFFFFFFE;
-
-        /* Create a temp bitmap for resized thumbnails */
-        Bitmap tempBitmap = null;
-        if ((newWidth != width) || (newHeight != height)) {
-             tempBitmap = Bitmap.createBitmap(newWidth, newHeight, Bitmap.Config.ARGB_8888);
-        }
-
-        IntBuffer rgb888 = IntBuffer.allocate(newWidth * newHeight * 4);
-        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
-        nativeGetPixels(inputFile, rgb888.array(), newWidth, newHeight, timeMS);
-
-        if ((newWidth == width) && (newHeight == height)) {
-            bitmap.copyPixelsFromBuffer(rgb888);
-        } else {
-            /* Create a temp bitmap to be used for resize */
-            tempBitmap.copyPixelsFromBuffer(rgb888);
-
-            /* Create a canvas to resize */
-            final Canvas canvas = new Canvas(bitmap);
-            canvas.drawBitmap(tempBitmap, new Rect(0, 0, newWidth, newHeight),
-                                          new Rect(0, 0, width, height), sResizePaint);
-            canvas.setBitmap(null);
-        }
-
-        if (tempBitmap != null) {
-            tempBitmap.recycle();
-        }
-
-        return bitmap;
+    Bitmap getPixels(String filename, int width, int height, long timeMs,
+            int videoRotation) {
+        final Bitmap result[] = new Bitmap[1];
+        getPixelsList(filename, width, height, timeMs, timeMs, 1, new int[] {0},
+                new MediaItem.GetThumbnailListCallback() {
+            public void onThumbnail(Bitmap bitmap, int index) {
+                result[0] = bitmap;
+            }
+        }, videoRotation);
+        return result[0];
     }
 
     /**
      * This method extracts a list of frame from the
      * input file and returns the frame in bitmap array
      *
-     * @param filename The inputFile
-     * @param width The width of the output frame
-     * @param height The height of the output frame
+     * @param filename The input file name
+     * @param width The width of the output frame, before rotation
+     * @param height The height of the output frame, before rotation
      * @param startMs The starting time in ms
      * @param endMs The end time in ms
      * @param thumbnailCount The number of frames to be extracted
      * @param indices The indices of thumbnails wanted
      * @param callback The callback used to pass back the bitmaps
-     * from startMs to endMs
+     * @param videoRotation The rotation degree need to be done for the bitmap
      *
      * @return The frames as bitmaps in bitmap array
      **/
@@ -3824,62 +3792,69 @@
             long startMs, long endMs, int thumbnailCount, int[] indices,
             final MediaItem.GetThumbnailListCallback callback,
             final int videoRotation) {
-        /* Make width and height as even */
-        final int newWidth = (width + 1) & 0xFFFFFFFE;
-        final int newHeight = (height + 1) & 0xFFFFFFFE;
-        final int thumbnailSize = newWidth * newHeight;
 
-        /* Create a temp bitmap for resized thumbnails */
-        final Bitmap tempBitmap =
-                (newWidth != width || newHeight != height)
-                ? Bitmap.createBitmap(newWidth, newHeight, Bitmap.Config.ARGB_8888)
+        // The decoder needs output width and height as even
+        final int decWidth = (width + 1) & 0xFFFFFFFE;
+        final int decHeight = (height + 1) & 0xFFFFFFFE;
+        final int thumbnailSize = decWidth * decHeight;
+
+        // We convert the decoder output (in int[]) to a bitmap by first
+        // copy it into an IntBuffer, then use Bitmap.copyPixelsFromBuffer to
+        // copy it to the bitmap.
+        final int[] decArray = new int[thumbnailSize];
+        final IntBuffer decBuffer = IntBuffer.allocate(thumbnailSize);
+
+        // If we need to resize and/or rotate the decoder output, we need a
+        // temporary bitmap to hold the decoded output.
+        final boolean needToMassage =
+                (decWidth != width || decHeight != height || videoRotation != 0);
+        final Bitmap tmpBitmap = needToMassage
+                ? Bitmap.createBitmap(decWidth, decHeight, Bitmap.Config.ARGB_8888)
                 : null;
 
-        final int[] rgb888 = new int[thumbnailSize];
-        final IntBuffer tmpBuffer = IntBuffer.allocate(thumbnailSize);
-        nativeGetPixelsList(filename, rgb888, newWidth, newHeight,
-                thumbnailCount, videoRotation, startMs, endMs, indices,
+        // The final output bitmap width/height may swap because of rotation.
+        final boolean needToSwapWH = (videoRotation == 90 || videoRotation == 270);
+        final int outWidth = needToSwapWH ? height : width;
+        final int outHeight = needToSwapWH ? width : height;
+
+        nativeGetPixelsList(filename, decArray, decWidth, decHeight,
+                thumbnailCount, startMs, endMs, indices,
                 new NativeGetPixelsListCallback() {
             public void onThumbnail(int index) {
-                Bitmap bitmap = Bitmap.createBitmap(
-                        width, height, Bitmap.Config.ARGB_8888);
-                tmpBuffer.put(rgb888, 0, thumbnailSize);
-                tmpBuffer.rewind();
+                // This is the bitmap we will output to the client
+                Bitmap outBitmap = Bitmap.createBitmap(
+                        outWidth, outHeight, Bitmap.Config.ARGB_8888);
 
-                if ((newWidth == width) && (newHeight == height)) {
-                    bitmap.copyPixelsFromBuffer(tmpBuffer);
+                // Copy int[] to IntBuffer
+                decBuffer.put(decArray, 0, thumbnailSize);
+                decBuffer.rewind();
+
+                if (!needToMassage) {
+                    // We can directly read the decoded result to output bitmap
+                    outBitmap.copyPixelsFromBuffer(decBuffer);
                 } else {
-                    /* Copy the out rgb buffer to temp bitmap */
-                    tempBitmap.copyPixelsFromBuffer(tmpBuffer);
+                    // Copy the decoded result to an intermediate bitmap first
+                    tmpBitmap.copyPixelsFromBuffer(decBuffer);
 
-                    /* Create a canvas to resize */
-                    final Canvas canvas = new Canvas(bitmap);
-                    canvas.drawBitmap(tempBitmap,
-                            new Rect(0, 0, newWidth, newHeight),
-                            new Rect(0, 0, width, height), sResizePaint);
-
-                    canvas.setBitmap(null);
+                    // Create a canvas to resize/rotate the bitmap
+                    // First scale the decoded bitmap to (0,0)-(1,1), rotate it
+                    // with (0.5, 0.5) as center, then scale it to
+                    // (outWidth, outHeight).
+                    final Canvas canvas = new Canvas(outBitmap);
+                    Matrix m = new Matrix();
+                    float sx = 1f / decWidth;
+                    float sy = 1f / decHeight;
+                    m.postScale(sx, sy);
+                    m.postRotate(videoRotation, 0.5f, 0.5f);
+                    m.postScale(outWidth, outHeight);
+                    canvas.drawBitmap(tmpBitmap, m, sResizePaint);
                 }
-
-                if (videoRotation == 0) {
-                    callback.onThumbnail(bitmap, index);
-                } else {
-                    Matrix mtx = new Matrix();
-                    mtx.postRotate(videoRotation);
-                    Bitmap rotatedBmp =
-                        Bitmap.createBitmap(bitmap, 0, 0, width, height, mtx, false);
-                    callback.onThumbnail(rotatedBmp, index);
-
-                    if (bitmap != null) {
-                        bitmap.recycle();
-                    }
-                }
-
+                callback.onThumbnail(outBitmap, index);
             }
         });
 
-        if (tempBitmap != null) {
-            tempBitmap.recycle();
+        if (tmpBitmap != null) {
+            tmpBitmap.recycle();
         }
     }
 
@@ -3996,7 +3971,7 @@
             long timeMS);
 
     private native int nativeGetPixelsList(String fileName, int[] pixelArray,
-            int width, int height, int nosofTN, int videoRotation, long startTimeMs,
+            int width, int height, int nosofTN, long startTimeMs,
             long endTimeMs, int[] indices, NativeGetPixelsListCallback callback);
 
     /**
diff --git a/media/java/android/media/videoeditor/MediaImageItem.java b/media/java/android/media/videoeditor/MediaImageItem.java
index 65a9e19..a862d00 100755
--- a/media/java/android/media/videoeditor/MediaImageItem.java
+++ b/media/java/android/media/videoeditor/MediaImageItem.java
@@ -606,7 +606,7 @@
     public Bitmap getThumbnail(int width, int height, long timeMs) throws IOException {
         if (getGeneratedImageClip() != null) {
             return mMANativeHelper.getPixels(getGeneratedImageClip(),
-                width, height,timeMs);
+                width, height, timeMs, 0);
         } else {
             return scaleImage(mFilename, width, height);
         }
diff --git a/media/java/android/media/videoeditor/MediaVideoItem.java b/media/java/android/media/videoeditor/MediaVideoItem.java
index 2ce857c..bbcdf57 100755
--- a/media/java/android/media/videoeditor/MediaVideoItem.java
+++ b/media/java/android/media/videoeditor/MediaVideoItem.java
@@ -293,7 +293,14 @@
             throw new IllegalArgumentException("Invalid Dimensions");
         }
 
-        return mMANativeHelper.getPixels(super.getFilename(), width, height,timeMs);
+        if (mVideoRotationDegree == 90 || mVideoRotationDegree == 270) {
+            int temp = width;
+            width = height;
+            height = temp;
+        }
+
+        return mMANativeHelper.getPixels(
+                getFilename(), width, height, timeMs, mVideoRotationDegree);
     }
 
     /*
@@ -318,8 +325,14 @@
             throw new IllegalArgumentException("Invalid dimension");
         }
 
-        mMANativeHelper.getPixelsList(super.getFilename(), width,
-                height, startMs, endMs, thumbnailCount, indices, callback,
+        if (mVideoRotationDegree == 90 || mVideoRotationDegree == 270) {
+            int temp = width;
+            width = height;
+            height = temp;
+        }
+
+        mMANativeHelper.getPixelsList(getFilename(), width, height,
+                startMs, endMs, thumbnailCount, indices, callback,
                 mVideoRotationDegree);
     }
 
diff --git a/media/java/android/media/videoeditor/VideoEditorImpl.java b/media/java/android/media/videoeditor/VideoEditorImpl.java
index f18dd88..2446c2f 100755
--- a/media/java/android/media/videoeditor/VideoEditorImpl.java
+++ b/media/java/android/media/videoeditor/VideoEditorImpl.java
@@ -1825,27 +1825,10 @@
         if (mMediaItems.size() > 0) {
             MediaItem mI = mMediaItems.get(0);
             /*
-             * Lets initialize the width for default aspect ratio i.e 16:9
+             * Keep aspect ratio of the image
              */
             int height = 480;
-            int width = 854;
-            switch (mI.getAspectRatio()) {
-                case MediaProperties.ASPECT_RATIO_3_2:
-                    width = 720;
-                    break;
-                case MediaProperties.ASPECT_RATIO_4_3:
-                    width = 640;
-                    break;
-                case MediaProperties.ASPECT_RATIO_5_3:
-                    width = 800;
-                    break;
-                case MediaProperties.ASPECT_RATIO_11_9:
-                    width = 586;
-                    break;
-                case MediaProperties.ASPECT_RATIO_16_9:
-                case MediaProperties.ASPECT_RATIO_UNDEFINED:
-                    break;
-            }
+            int width = mI.getWidth() * height / mI.getHeight();
 
             Bitmap projectBitmap = null;
             String filename = mI.getFilename();
diff --git a/media/jni/mediaeditor/VideoEditorMain.cpp b/media/jni/mediaeditor/VideoEditorMain.cpp
index 4e73581..4e954fc 100755
--- a/media/jni/mediaeditor/VideoEditorMain.cpp
+++ b/media/jni/mediaeditor/VideoEditorMain.cpp
@@ -185,7 +185,6 @@
                                      M4OSA_UInt32             width,
                                      M4OSA_UInt32             height,
                                      M4OSA_UInt32             noOfThumbnails,
-                                     M4OSA_UInt32             videoRotation,
                                      jlong                    startTime,
                                      jlong                    endTime,
                                      jintArray                indexArray,
@@ -292,7 +291,7 @@
                                 (void *)videoEditor_release            },
     {"nativeGetPixels",         "(Ljava/lang/String;[IIIJ)I",
                                 (void*)videoEditor_getPixels               },
-    {"nativeGetPixelsList",     "(Ljava/lang/String;[IIIIIJJ[ILandroid/media/videoeditor/MediaArtistNativeHelper$NativeGetPixelsListCallback;)I",
+    {"nativeGetPixelsList",     "(Ljava/lang/String;[IIIIJJ[ILandroid/media/videoeditor/MediaArtistNativeHelper$NativeGetPixelsListCallback;)I",
                                 (void*)videoEditor_getPixelsList           },
     {"getMediaProperties",
     "(Ljava/lang/String;)Landroid/media/videoeditor/MediaArtistNativeHelper$Properties;",
@@ -2286,7 +2285,6 @@
                 M4OSA_UInt32            width,
                 M4OSA_UInt32            height,
                 M4OSA_UInt32            noOfThumbnails,
-                M4OSA_UInt32            videoRotation,
                 jlong                   startTime,
                 jlong                   endTime,
                 jintArray               indexArray,