Loading core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java +63 −3 Original line number Diff line number Diff line Loading @@ -34,7 +34,6 @@ import android.hardware.camera2.params.StreamConfigurationDuration; import android.hardware.camera2.utils.ArrayUtils; import android.hardware.camera2.utils.ListUtils; import android.hardware.camera2.utils.ParamsUtils; import android.hardware.camera2.utils.SizeAreaComparator; import android.util.Log; import android.util.Range; import android.util.Size; Loading Loading @@ -88,6 +87,9 @@ public class LegacyMetadataMapper { static final int UNKNOWN_MODE = -1; // Maximum difference between a preview size aspect ratio and a jpeg size aspect ratio private static final float PREVIEW_ASPECT_RATIO_TOLERANCE = 0.01f; /* * Development hijinks: Lie about not supporting certain capabilities * Loading @@ -103,6 +105,7 @@ public class LegacyMetadataMapper { static final boolean LIE_ABOUT_AWB_STATE = false; static final boolean LIE_ABOUT_AWB = false; /** * Create characteristics for a legacy device by mapping the {@code parameters} * and {@code info} Loading Loading @@ -262,6 +265,64 @@ public class LegacyMetadataMapper { * remapping to public format constants. */ List<Camera.Size> previewSizes = p.getSupportedPreviewSizes(); List<Camera.Size> jpegSizes = p.getSupportedPictureSizes(); /* * Work-around for b/17589233: * - Some HALs's largest preview size aspect ratio does not match the largest JPEG size AR * - This causes a large amount of problems with focus/metering because it's relative to * preview, making the difference between the JPEG and preview viewport inaccessible * - This boils down to metering or focusing areas being "arbitrarily" cropped * in the capture result. * - Work-around the HAL limitations by removing all of the largest preview sizes * until we get one with the same aspect ratio as the jpeg size. */ { SizeAreaComparator areaComparator = new SizeAreaComparator(); // Sort preview to min->max Collections.sort(previewSizes, areaComparator); Camera.Size maxJpegSize = SizeAreaComparator.findLargestByArea(jpegSizes); float jpegAspectRatio = maxJpegSize.width * 1.0f / maxJpegSize.height; if (VERBOSE) { Log.v(TAG, String.format("mapScalerStreamConfigs - largest JPEG area %dx%d, AR=%f", maxJpegSize.width, maxJpegSize.height, jpegAspectRatio)); } // Now remove preview sizes from the end (largest->smallest) until aspect ratio matches while (!previewSizes.isEmpty()) { int index = previewSizes.size() - 1; // max is always at the end Camera.Size size = previewSizes.get(index); float previewAspectRatio = size.width * 1.0f / size.height; if (Math.abs(jpegAspectRatio - previewAspectRatio) >= PREVIEW_ASPECT_RATIO_TOLERANCE) { previewSizes.remove(index); // Assume removing from end is O(1) if (VERBOSE) { Log.v(TAG, String.format( "mapScalerStreamConfigs - removed preview size %dx%d, AR=%f " + "was not the same", size.width, size.height, previewAspectRatio)); } } else { break; } } if (previewSizes.isEmpty()) { // Fall-back to the original faulty behavior, but at least work Log.w(TAG, "mapScalerStreamConfigs - failed to find any preview size matching " + "JPEG aspect ratio " + jpegAspectRatio); previewSizes = p.getSupportedPreviewSizes(); } // Sort again, this time in descending order max->min Collections.sort(previewSizes, Collections.reverseOrder(areaComparator)); } appendStreamConfig(availableStreamConfigs, HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, previewSizes); appendStreamConfig(availableStreamConfigs, Loading @@ -279,7 +340,6 @@ public class LegacyMetadataMapper { } } List<Camera.Size> jpegSizes = p.getSupportedPictureSizes(); appendStreamConfig(availableStreamConfigs, HAL_PIXEL_FORMAT_BLOB, p.getSupportedPictureSizes()); /* Loading Loading @@ -620,7 +680,7 @@ public class LegacyMetadataMapper { if (thumbnailSizes != null) { Size[] sizes = convertSizeListToArray(thumbnailSizes); Arrays.sort(sizes, new SizeAreaComparator()); Arrays.sort(sizes, new android.hardware.camera2.utils.SizeAreaComparator()); m.set(JPEG_AVAILABLE_THUMBNAIL_SIZES, sizes); } } Loading core/java/android/hardware/camera2/legacy/SizeAreaComparator.java 0 → 100644 +72 −0 Original line number Diff line number Diff line /* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package android.hardware.camera2.legacy; import android.hardware.Camera; import java.util.Collections; import java.util.Comparator; import java.util.List; import static com.android.internal.util.Preconditions.*; /** * Comparator for api1 {@link Camera.Size} objects by the area. * * <p>This comparator totally orders by rectangle area. Tie-breaks on width.</p> */ @SuppressWarnings("deprecation") public class SizeAreaComparator implements Comparator<Camera.Size> { /** * {@inheritDoc} */ @Override public int compare(Camera.Size size, Camera.Size size2) { checkNotNull(size, "size must not be null"); checkNotNull(size2, "size2 must not be null"); if (size.equals(size2)) { return 0; } long width = size.width; long width2 = size2.width; long area = width * size.height; long area2 = width2 * size2.height; if (area == area2) { return (width > width2) ? 1 : -1; } return (area > area2) ? 1 : -1; } /** * Get the largest api1 {@code Camera.Size} from the list by comparing each size's area * by each other using {@link SizeAreaComparator}. * * @param sizes a non-{@code null} list of non-{@code null} sizes * @return a non-{@code null} size * * @throws NullPointerException if {@code sizes} or any elements in it were {@code null} */ public static Camera.Size findLargestByArea(List<Camera.Size> sizes) { checkNotNull(sizes, "sizes must not be null"); return Collections.max(sizes, new SizeAreaComparator()); } } Loading
core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java +63 −3 Original line number Diff line number Diff line Loading @@ -34,7 +34,6 @@ import android.hardware.camera2.params.StreamConfigurationDuration; import android.hardware.camera2.utils.ArrayUtils; import android.hardware.camera2.utils.ListUtils; import android.hardware.camera2.utils.ParamsUtils; import android.hardware.camera2.utils.SizeAreaComparator; import android.util.Log; import android.util.Range; import android.util.Size; Loading Loading @@ -88,6 +87,9 @@ public class LegacyMetadataMapper { static final int UNKNOWN_MODE = -1; // Maximum difference between a preview size aspect ratio and a jpeg size aspect ratio private static final float PREVIEW_ASPECT_RATIO_TOLERANCE = 0.01f; /* * Development hijinks: Lie about not supporting certain capabilities * Loading @@ -103,6 +105,7 @@ public class LegacyMetadataMapper { static final boolean LIE_ABOUT_AWB_STATE = false; static final boolean LIE_ABOUT_AWB = false; /** * Create characteristics for a legacy device by mapping the {@code parameters} * and {@code info} Loading Loading @@ -262,6 +265,64 @@ public class LegacyMetadataMapper { * remapping to public format constants. */ List<Camera.Size> previewSizes = p.getSupportedPreviewSizes(); List<Camera.Size> jpegSizes = p.getSupportedPictureSizes(); /* * Work-around for b/17589233: * - Some HALs's largest preview size aspect ratio does not match the largest JPEG size AR * - This causes a large amount of problems with focus/metering because it's relative to * preview, making the difference between the JPEG and preview viewport inaccessible * - This boils down to metering or focusing areas being "arbitrarily" cropped * in the capture result. * - Work-around the HAL limitations by removing all of the largest preview sizes * until we get one with the same aspect ratio as the jpeg size. */ { SizeAreaComparator areaComparator = new SizeAreaComparator(); // Sort preview to min->max Collections.sort(previewSizes, areaComparator); Camera.Size maxJpegSize = SizeAreaComparator.findLargestByArea(jpegSizes); float jpegAspectRatio = maxJpegSize.width * 1.0f / maxJpegSize.height; if (VERBOSE) { Log.v(TAG, String.format("mapScalerStreamConfigs - largest JPEG area %dx%d, AR=%f", maxJpegSize.width, maxJpegSize.height, jpegAspectRatio)); } // Now remove preview sizes from the end (largest->smallest) until aspect ratio matches while (!previewSizes.isEmpty()) { int index = previewSizes.size() - 1; // max is always at the end Camera.Size size = previewSizes.get(index); float previewAspectRatio = size.width * 1.0f / size.height; if (Math.abs(jpegAspectRatio - previewAspectRatio) >= PREVIEW_ASPECT_RATIO_TOLERANCE) { previewSizes.remove(index); // Assume removing from end is O(1) if (VERBOSE) { Log.v(TAG, String.format( "mapScalerStreamConfigs - removed preview size %dx%d, AR=%f " + "was not the same", size.width, size.height, previewAspectRatio)); } } else { break; } } if (previewSizes.isEmpty()) { // Fall-back to the original faulty behavior, but at least work Log.w(TAG, "mapScalerStreamConfigs - failed to find any preview size matching " + "JPEG aspect ratio " + jpegAspectRatio); previewSizes = p.getSupportedPreviewSizes(); } // Sort again, this time in descending order max->min Collections.sort(previewSizes, Collections.reverseOrder(areaComparator)); } appendStreamConfig(availableStreamConfigs, HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, previewSizes); appendStreamConfig(availableStreamConfigs, Loading @@ -279,7 +340,6 @@ public class LegacyMetadataMapper { } } List<Camera.Size> jpegSizes = p.getSupportedPictureSizes(); appendStreamConfig(availableStreamConfigs, HAL_PIXEL_FORMAT_BLOB, p.getSupportedPictureSizes()); /* Loading Loading @@ -620,7 +680,7 @@ public class LegacyMetadataMapper { if (thumbnailSizes != null) { Size[] sizes = convertSizeListToArray(thumbnailSizes); Arrays.sort(sizes, new SizeAreaComparator()); Arrays.sort(sizes, new android.hardware.camera2.utils.SizeAreaComparator()); m.set(JPEG_AVAILABLE_THUMBNAIL_SIZES, sizes); } } Loading
core/java/android/hardware/camera2/legacy/SizeAreaComparator.java 0 → 100644 +72 −0 Original line number Diff line number Diff line /* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package android.hardware.camera2.legacy; import android.hardware.Camera; import java.util.Collections; import java.util.Comparator; import java.util.List; import static com.android.internal.util.Preconditions.*; /** * Comparator for api1 {@link Camera.Size} objects by the area. * * <p>This comparator totally orders by rectangle area. Tie-breaks on width.</p> */ @SuppressWarnings("deprecation") public class SizeAreaComparator implements Comparator<Camera.Size> { /** * {@inheritDoc} */ @Override public int compare(Camera.Size size, Camera.Size size2) { checkNotNull(size, "size must not be null"); checkNotNull(size2, "size2 must not be null"); if (size.equals(size2)) { return 0; } long width = size.width; long width2 = size2.width; long area = width * size.height; long area2 = width2 * size2.height; if (area == area2) { return (width > width2) ? 1 : -1; } return (area > area2) ? 1 : -1; } /** * Get the largest api1 {@code Camera.Size} from the list by comparing each size's area * by each other using {@link SizeAreaComparator}. * * @param sizes a non-{@code null} list of non-{@code null} sizes * @return a non-{@code null} size * * @throws NullPointerException if {@code sizes} or any elements in it were {@code null} */ public static Camera.Size findLargestByArea(List<Camera.Size> sizes) { checkNotNull(sizes, "sizes must not be null"); return Collections.max(sizes, new SizeAreaComparator()); } }