OSDN Git Service

Preview vs Video Camera Resolution Mismatch
authorI-Jong Lin <ijonglin@google.com>
Fri, 10 Oct 2014 23:34:34 +0000 (16:34 -0700)
committerI-Jong Lin <ijonglin@google.com>
Tue, 14 Oct 2014 17:22:34 +0000 (10:22 -0700)
  Bug: 17458889

This bug is programmatic and reproduces on all devices.   Basically,
the current app defaults to the highest resolution preview that
matches the aspect ratio of the recording, even if the recording
video resolution is lower.  Since it is more important to be WYSIWYG,
in the cases where the preview show at the same resolution of
the recording video resolution, we should preview at same resolution
for truest (but not necessarily best) quality that most faithfully
represents the content that is to be recorded under the constraint
of the UI resolution.

Change-Id: I0ec5a76834cbffa59f0e144f1fe271de25e92523

src/com/android/camera/VideoModule.java
src/com/android/camera/util/CameraUtil.java

index ce53dc2..a99fcb4 100644 (file)
@@ -596,6 +596,7 @@ public class VideoModule extends CameraModule
         mMeteringAreaSupported =
                 mCameraCapabilities.supports(CameraCapabilities.Feature.METERING_AREA);
         readVideoPreferences();
+        updateDesiredPreviewSize();
         resizeForPreviewAspectRatio();
         initializeFocusManager();
         // TODO: Having focus overlay manager caching the parameters is prone to error,
@@ -765,17 +766,28 @@ public class VideoModule extends CameraModule
         }
         mProfile = CamcorderProfile.get(mCameraId, quality);
         mPreferenceRead = true;
+    }
+
+    /**
+     * Calculates and sets local class variables for Desired Preview sizes.
+     * This function should be called after every change in preview camera
+     * resolution and/or before the preview starts. Note that these values still
+     * need to be pushed to the CameraSettings to actually change the preview
+     * resolution.  Does nothing when camera pointer is null.
+     */
+    private void updateDesiredPreviewSize() {
         if (mCameraDevice == null) {
             return;
         }
+
         mCameraSettings = mCameraDevice.getSettings();
         Point desiredPreviewSize = getDesiredPreviewSize(mAppController.getAndroidContext(),
                 mCameraSettings, mCameraCapabilities, mProfile, mUI.getPreviewScreenSize());
         mDesiredPreviewWidth = desiredPreviewSize.x;
         mDesiredPreviewHeight = desiredPreviewSize.y;
         mUI.setPreviewSize(mDesiredPreviewWidth, mDesiredPreviewHeight);
-        Log.v(TAG, "mDesiredPreviewWidth=" + mDesiredPreviewWidth +
-                ". mDesiredPreviewHeight=" + mDesiredPreviewHeight);
+        Log.v(TAG, "Updated DesiredPreview=" + mDesiredPreviewWidth + "x"
+                + mDesiredPreviewHeight);
     }
 
     @TargetApi(Build.VERSION_CODES.HONEYCOMB)
@@ -787,7 +799,9 @@ public class VideoModule extends CameraModule
      * com.android.camera.cameradevice.CameraCapabilities#getPreferredPreviewSizeForVideo()}
      * but also considers the current preview area size on screen and make sure
      * the final preview size will not be smaller than 1/2 of the current
-     * on screen preview area in terms of their short sides.</p>
+     * on screen preview area in terms of their short sides.  This function has
+     * highest priority of WYSIWYG, 1:1 matching as its best match, even if
+     * there's a larger preview that meets the condition above. </p>
      *
      * @return The preferred preview size or {@code null} if the camera is not
      *         opened yet.
@@ -817,6 +831,19 @@ public class VideoModule extends CameraModule
                 it.remove();
             }
         }
+
+        // Take highest priority for WYSIWYG when the preview exactly matches
+        // video frame size.  The variable sizes is assumed to be filtered
+        // for sizes beyond the UI size.
+        for (Size size : sizes) {
+            if (size.width() == profile.videoFrameWidth
+                    && size.height() == profile.videoFrameHeight) {
+                Log.v(TAG, "Selected =" + size.width() + "x" + size.height()
+                           + " on WYSIWYG Priority");
+                return new Point(profile.videoFrameWidth, profile.videoFrameHeight);
+            }
+        }
+
         Size optimalSize = CameraUtil.getOptimalPreviewSize(context, sizes,
                 (double) profile.videoFrameWidth / profile.videoFrameHeight);
         return new Point(optimalSize.width(), optimalSize.height());
@@ -1589,6 +1616,9 @@ public class VideoModule extends CameraModule
     private void setCameraParameters() {
         SettingsManager settingsManager = mActivity.getSettingsManager();
 
+        // Update Desired Preview size in case video camera resolution has changed.
+        updateDesiredPreviewSize();
+
         mCameraSettings.setPreviewSize(new Size(mDesiredPreviewWidth, mDesiredPreviewHeight));
         // This is required for Samsung SGH-I337 and probably other Samsung S4 versions
         if (Build.BRAND.toLowerCase().contains("samsung")) {
@@ -1623,7 +1653,7 @@ public class VideoModule extends CameraModule
         // here we determine the picture size based on the preview size.
         List<Size> supported = mCameraCapabilities.getSupportedPhotoSizes();
         Size optimalSize = CameraUtil.getOptimalVideoSnapshotPictureSize(supported,
-                (double) mDesiredPreviewWidth / mDesiredPreviewHeight);
+                mDesiredPreviewWidth, mDesiredPreviewHeight);
         Size original = new Size(mCameraSettings.getCurrentPhotoSize());
         if (!original.equals(optimalSize)) {
             mCameraSettings.setPhotoSize(optimalSize);
index b415901..658e73b 100644 (file)
@@ -563,12 +563,24 @@ public class CameraUtil {
                 }
             }
         }
+
         return optimalSizeIndex;
     }
 
-    /** Returns the largest picture size which matches the given aspect ratio. */
+    /**
+     * Returns the largest picture size which matches the given aspect ratio,
+     * except for the special WYSIWYG case where the picture size exactly matches
+     * the target size.
+     *
+     * @param sizes        a list of candidate sizes, available for use
+     * @param targetWidth  the ideal width of the video snapshot
+     * @param targetHeight the ideal height of the video snapshot
+     * @return the Optimal Video Snapshot Picture Size
+     */
     public static com.android.ex.camera2.portability.Size getOptimalVideoSnapshotPictureSize(
-            List<com.android.ex.camera2.portability.Size> sizes, double targetRatio) {
+            List<com.android.ex.camera2.portability.Size> sizes, int targetWidth,
+            int targetHeight) {
+
         // Use a very small tolerance because we want an exact match.
         final double ASPECT_TOLERANCE = 0.001;
         if (sizes == null) {
@@ -577,7 +589,17 @@ public class CameraUtil {
 
         com.android.ex.camera2.portability.Size optimalSize = null;
 
+        //  WYSIWYG Override
+        //  We assume that physical display constraints have already been
+        //  imposed on the variables sizes
+        for (com.android.ex.camera2.portability.Size size : sizes) {
+            if (size.height() == targetHeight && size.width() == targetWidth) {
+                return size;
+            }
+        }
+
         // Try to find a size matches aspect ratio and has the largest width
+        final double targetRatio = (double) targetWidth / targetHeight;
         for (com.android.ex.camera2.portability.Size size : sizes) {
             double ratio = (double) size.width() / size.height();
             if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) {