Merge "Don't purge effects we're about to start using" into jb-mr2-dev
diff --git a/services/camera/libcameraservice/camera2/CallbackProcessor.cpp b/services/camera/libcameraservice/camera2/CallbackProcessor.cpp
index a3d6cb2..5e88102 100644
--- a/services/camera/libcameraservice/camera2/CallbackProcessor.cpp
+++ b/services/camera/libcameraservice/camera2/CallbackProcessor.cpp
@@ -411,35 +411,61 @@
     size_t dstChromaGap = dstCStride - chromaWidth;
 
     if (previewFormat == HAL_PIXEL_FORMAT_YCrCb_420_SP) {
-        // NV21
+        // Flexible YUV chroma to NV21 chroma
         uint8_t *vuDst = yDst;
-        for (size_t row = 0; row < chromaHeight; row++) {
-            for (size_t col = 0; col < chromaWidth; col++) {
-                *(vuDst++) = *vSrc;
-                *(vuDst++) = *uSrc;
-                vSrc += src.chromaStep;
-                uSrc += src.chromaStep;
+        // Check for shortcuts
+        if (uSrc == vSrc + 1 && src.chromaStep == 2) {
+            // Source has semiplanar CrCb chroma layout, can copy by rows
+            for (size_t row = 0; row < chromaHeight; row++) {
+                memcpy(vuDst, uSrc, src.width);
+                vuDst += src.width;
+                uSrc += src.chromaStride;
             }
-            vSrc += chromaGap;
-            uSrc += chromaGap;
+        } else {
+            // Generic copy, always works but not very efficient
+            for (size_t row = 0; row < chromaHeight; row++) {
+                for (size_t col = 0; col < chromaWidth; col++) {
+                    *(vuDst++) = *vSrc;
+                    *(vuDst++) = *uSrc;
+                    vSrc += src.chromaStep;
+                    uSrc += src.chromaStep;
+                }
+                vSrc += chromaGap;
+                uSrc += chromaGap;
+            }
         }
     } else {
-        // YV12
+        // flexible YUV chroma to YV12 chroma
         ALOG_ASSERT(previewFormat == HAL_PIXEL_FORMAT_YV12,
                 "Unexpected preview format 0x%x", previewFormat);
         uint8_t *vDst = yDst;
         uint8_t *uDst = yDst + chromaHeight * dstCStride;
-        for (size_t row = 0; row < chromaHeight; row++) {
-            for (size_t col = 0; col < chromaWidth; col++) {
-                *(vDst++) = *vSrc;
-                *(uDst++) = *uSrc;
-                vSrc += src.chromaStep;
-                uSrc += src.chromaStep;
+        if (src.chromaStep == 1) {
+            // Source has planar chroma layout, can copy by row
+            for (size_t row = 0; row < chromaHeight; row++) {
+                memcpy(vDst, vSrc, chromaWidth);
+                vDst += dstCStride;
+                vSrc += src.chromaStride;
             }
-            vSrc += chromaGap;
-            uSrc += chromaGap;
-            vDst += dstChromaGap;
-            uDst += dstChromaGap;
+            for (size_t row = 0; row < chromaHeight; row++) {
+                memcpy(uDst, uSrc, chromaWidth);
+                uDst += dstCStride;
+                uSrc += src.chromaStride;
+            }
+        } else {
+            // Generic copy, always works but not very efficient
+            for (size_t row = 0; row < chromaHeight; row++) {
+                for (size_t col = 0; col < chromaWidth; col++) {
+                    *(vDst++) = *vSrc;
+                    *(uDst++) = *uSrc;
+                    vSrc += src.chromaStep;
+                    uSrc += src.chromaStep;
+                }
+                vSrc += chromaGap;
+                uSrc += chromaGap;
+                vDst += dstChromaGap;
+                uDst += dstChromaGap;
+            }
         }
     }
 
diff --git a/services/camera/libcameraservice/camera2/Parameters.cpp b/services/camera/libcameraservice/camera2/Parameters.cpp
index 910aa19..49fc3d8 100644
--- a/services/camera/libcameraservice/camera2/Parameters.cpp
+++ b/services/camera/libcameraservice/camera2/Parameters.cpp
@@ -2559,27 +2559,24 @@
      * stream cropping.
      */
     if (quirks.meteringCropRegion) {
-        /**
-         * All streams are the same in height, so narrower aspect ratios will
-         * get cropped on the sides.  First find the largest (widest) aspect
-         * ratio, then calculate the crop of the still FOV based on that.
-         */
-        float cropAspect = arrayAspect;
-        float aspects[] = {
-            stillAspect,
-            static_cast<float>(previewWidth) / previewHeight,
-            static_cast<float>(videoWidth) / videoHeight
-        };
-        for (size_t i = 0; i < sizeof(aspects)/sizeof(aspects[0]); i++) {
-            if (cropAspect < aspects[i]) cropAspect = aspects[i];
+        // Use max of preview and video as first crop
+        float previewAspect = static_cast<float>(previewWidth) / previewHeight;
+        float videoAspect = static_cast<float>(videoWidth) / videoHeight;
+        if (videoAspect > previewAspect) {
+            previewAspect = videoAspect;
         }
-        ALOGV("Widest crop aspect: %f", cropAspect);
-        // Horizontal crop of still is done based on fitting in the widest
-        // aspect ratio
-        horizCropFactor = stillAspect / cropAspect;
-        // Vertical crop is a function of the array aspect ratio and the
-        // widest aspect ratio.
-        vertCropFactor = arrayAspect / cropAspect;
+        // First crop sensor to preview aspect ratio
+        if (arrayAspect < previewAspect) {
+            vertCropFactor = arrayAspect / previewAspect;
+        } else {
+            horizCropFactor = previewAspect / arrayAspect;
+        }
+        // Second crop to still aspect ratio
+        if (stillAspect < previewAspect) {
+            horizCropFactor *= stillAspect / previewAspect;
+        } else {
+            vertCropFactor *= previewAspect / stillAspect;
+        }
     } else {
         /**
          * Crop are just a function of just the still/array relative aspect
diff --git a/services/camera/libcameraservice/camera3/Camera3OutputStream.cpp b/services/camera/libcameraservice/camera3/Camera3OutputStream.cpp
index 9693346..055913a 100644
--- a/services/camera/libcameraservice/camera3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/camera3/Camera3OutputStream.cpp
@@ -361,11 +361,6 @@
         return res;
     }
 
-    res = setTransformLocked(0);
-    if (res != OK) {
-        return res;
-    }
-
     if (mMaxSize == 0) {
         // For buffers of known size
         res = native_window_set_buffers_geometry(mConsumer.get(),