Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a040e444 authored by Igor Murashkin's avatar Igor Murashkin Committed by Android Git Automerger
Browse files

am c79b145f: Merge "camera2-legacy: Workaround max jpeg/preview size AR mismatch" into lmp-dev

* commit 'c79b145f0216d2f9b099a409fee2c154de1f7019':
  camera2-legacy: Workaround max jpeg/preview size AR mismatch
parents 5a94fd7c 4f17981f
Loading
Loading
Loading
Loading
+63 −3
Original line number Diff line number Diff line
@@ -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;
@@ -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
     *
@@ -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}
@@ -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,
@@ -279,7 +340,6 @@ public class LegacyMetadataMapper {
            }
        }

        List<Camera.Size> jpegSizes = p.getSupportedPictureSizes();
        appendStreamConfig(availableStreamConfigs,
                HAL_PIXEL_FORMAT_BLOB, p.getSupportedPictureSizes());
        /*
@@ -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);
        }
    }
+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());
    }
}