am 5e91151d: am 900d0072: am bda40b57: am e3ad6ff8: am c79b145f: Merge "camera2-legacy: Workaround max jpeg/preview size AR mismatch" into lmp-dev

* commit '5e91151d0f88e87055ffdfcd764c71ffa72df37e':
  camera2-legacy: Workaround max jpeg/preview size AR mismatch
This commit is contained in:
Igor Murashkin
2014-09-24 17:16:46 +00:00
committed by Android Git Automerger
2 changed files with 135 additions and 3 deletions

View File

@@ -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);
}
}

View File

@@ -0,0 +1,72 @@
/*
* 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());
}
}