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

Commit 0ec04655 authored by Eino-Ville Talvala's avatar Eino-Ville Talvala Committed by android-build-merger
Browse files

Merge "Camera2: StreamConfigurationMap#isOutputSupportedFor(Surface)" into lmp-mr1-dev

automerge: 7fde5e5b

* commit '7fde5e5b':
  Camera2: StreamConfigurationMap#isOutputSupportedFor(Surface)
parents 5cb31f21 7fde5e5b
Loading
Loading
Loading
Loading
+15 −13
Original line number Diff line number Diff line
@@ -147,20 +147,20 @@ public abstract class CameraDevice implements AutoCloseable {
     * <ul>
     *
     * <li>For drawing to a {@link android.view.SurfaceView SurfaceView}: Once the SurfaceView's
     *   Surface is {@link android.view.SurfaceHolder.Callback#surfaceCreated created}, set the
     *   size of the Surface with {@link android.view.SurfaceHolder#setFixedSize} to be one of the
     *   sizes returned by
     *   {@link StreamConfigurationMap#getOutputSizes(Class) getOutputSizes(SurfaceHolder.class)}
     *   and then obtain the Surface by calling {@link android.view.SurfaceHolder#getSurface}.</li>
     *
     * <li>For accessing through an OpenGL texture via a
     *   {@link android.graphics.SurfaceTexture SurfaceTexture}: Set the size of
     *   the SurfaceTexture with
     *   {@link android.graphics.SurfaceTexture#setDefaultBufferSize} to be one
     *   of the sizes returned by
     *   Surface is {@link android.view.SurfaceHolder.Callback#surfaceCreated created}, set the size
     *   of the Surface with {@link android.view.SurfaceHolder#setFixedSize} to be one of the sizes
     *   returned by {@link StreamConfigurationMap#getOutputSizes(Class)
     *   getOutputSizes(SurfaceHolder.class)} and then obtain the Surface by calling {@link
     *   android.view.SurfaceHolder#getSurface}. If the size is not set by the application, it will
     *   be rounded to the nearest supported size less than 1080p, by the camera device.</li>
     *
     * <li>For accessing through an OpenGL texture via a {@link android.graphics.SurfaceTexture
     *   SurfaceTexture}: Set the size of the SurfaceTexture with {@link
     *   android.graphics.SurfaceTexture#setDefaultBufferSize} to be one of the sizes returned by
     *   {@link StreamConfigurationMap#getOutputSizes(Class) getOutputSizes(SurfaceTexture.class)}
     *   before creating a Surface from the SurfaceTexture with
     *   {@link Surface#Surface}.</li>
     *   before creating a Surface from the SurfaceTexture with {@link Surface#Surface}. If the size
     *   is not set by the application, it will be set to be the smallest supported size less than
     *   1080p, by the camera device.</li>
     *
     * <li>For recording with {@link android.media.MediaCodec}: Call
     *   {@link android.media.MediaCodec#createInputSurface} after configuring
@@ -189,6 +189,8 @@ public abstract class CameraDevice implements AutoCloseable {
     *   corresponding supported sizes by passing the chosen output format into
     *   {@link StreamConfigurationMap#getOutputSizes(int)}. Then obtain a
     *   {@link android.view.Surface} from it with {@link android.media.ImageReader#getSurface()}.
     *   If the ImageReader size is not set to a supported size, it will be rounded to a supported
     *   size less than 1080p by the camera device.
     *   </li>
     *
     * </ul>
+23 −11
Original line number Diff line number Diff line
@@ -85,7 +85,7 @@ public class LegacyCameraDevice implements AutoCloseable {
    private static final int GRALLOC_USAGE_HW_COMPOSER = 0x00000800;
    private static final int GRALLOC_USAGE_HW_VIDEO_ENCODER = 0x00010000;

    private static final int MAX_DIMEN_FOR_ROUNDING = 1080; // maximum allowed width for rounding
    public static final int MAX_DIMEN_FOR_ROUNDING = 1080; // maximum allowed width for rounding

    private CaptureResultExtras getExtrasFromRequest(RequestHolder holder) {
        if (holder == null) {
@@ -299,15 +299,8 @@ public class LegacyCameraDevice implements AutoCloseable {
                try {
                    Size s = getSurfaceSize(output);
                    int surfaceType = detectSurfaceType(output);
                    int usageFlags = detectSurfaceUsageFlags(output);

                    // Keep up to date with allowed consumer types in
                    // frameworks/av/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
                    int disallowedFlags = GRALLOC_USAGE_HW_VIDEO_ENCODER | GRALLOC_USAGE_RENDERSCRIPT;
                    int allowedFlags = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_OFTEN |
                            GRALLOC_USAGE_HW_COMPOSER;
                    boolean flexibleConsumer = ((usageFlags & disallowedFlags) == 0 &&
                            (usageFlags & allowedFlags) != 0);
                    boolean flexibleConsumer = isFlexibleConsumer(output);

                    Size[] sizes = streamConfigurations.getOutputSizes(surfaceType);
                    if (sizes == null) {
@@ -531,7 +524,7 @@ public class LegacyCameraDevice implements AutoCloseable {
     * @throws NullPointerException if the {@code surface} was {@code null}
     * @throws IllegalStateException if the {@code surface} was invalid
     */
    static Size getSurfaceSize(Surface surface) throws BufferQueueAbandonedException {
    public static Size getSurfaceSize(Surface surface) throws BufferQueueAbandonedException {
        checkNotNull(surface);

        int[] dimens = new int[2];
@@ -540,12 +533,31 @@ public class LegacyCameraDevice implements AutoCloseable {
        return new Size(dimens[0], dimens[1]);
    }

    public static boolean isFlexibleConsumer(Surface output) {
        int usageFlags = detectSurfaceUsageFlags(output);

        // Keep up to date with allowed consumer types in
        // frameworks/av/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
        int disallowedFlags = GRALLOC_USAGE_HW_VIDEO_ENCODER | GRALLOC_USAGE_RENDERSCRIPT;
        int allowedFlags = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_OFTEN |
            GRALLOC_USAGE_HW_COMPOSER;
        boolean flexibleConsumer = ((usageFlags & disallowedFlags) == 0 &&
                (usageFlags & allowedFlags) != 0);
        return flexibleConsumer;
    }

    /**
     * Query the surface for its currently configured usage flags
     */
    static int detectSurfaceUsageFlags(Surface surface) {
        checkNotNull(surface);
        return nativeDetectSurfaceUsageFlags(surface);
    }

    static int detectSurfaceType(Surface surface) throws BufferQueueAbandonedException {
    /**
     * Query the surface for its currently configured format
     */
    public static int detectSurfaceType(Surface surface) throws BufferQueueAbandonedException {
        checkNotNull(surface);
        return LegacyExceptionUtils.throwOnError(nativeDetectSurfaceType(surface));
    }
+48 −4
Original line number Diff line number Diff line
@@ -22,6 +22,9 @@ import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.utils.HashCodeHelpers;
import android.hardware.camera2.legacy.LegacyCameraDevice;
import android.hardware.camera2.legacy.LegacyMetadataMapper;
import android.hardware.camera2.legacy.LegacyExceptionUtils.BufferQueueAbandonedException;
import android.view.Surface;
import android.util.Log;
import android.util.Range;
@@ -292,13 +295,21 @@ public final class StreamConfigurationMap {
     * </li>
     * </ul>
     *
     * This is not an exhaustive list; see the particular class's documentation for further
     * <p>Surfaces from flexible sources will return true even if the exact size of the Surface does
     * not match a camera-supported size, as long as the format (or class) is supported and the
     * camera device supports a size that is equal to or less than 1080p in that format. If such as
     * Surface is used to create a capture session, it will have its size rounded to the nearest
     * supported size, below or equal to 1080p. Flexible sources include SurfaceView, SurfaceTexture,
     * and ImageReader.</p>
     *
     * <p>This is not an exhaustive list; see the particular class's documentation for further
     * possible reasons of incompatibility.</p>
     *
     * @param surface a non-{@code null} {@link Surface} object reference
     * @return {@code true} if this is supported, {@code false} otherwise
     *
     * @throws NullPointerException if {@code surface} was {@code null}
     * @throws IllegalArgumentException if the Surface endpoint is no longer valid
     *
     * @see CameraDevice#createCaptureSession
     * @see #isOutputSupportedFor(Class)
@@ -306,9 +317,37 @@ public final class StreamConfigurationMap {
    public boolean isOutputSupportedFor(Surface surface) {
        checkNotNull(surface, "surface must not be null");

        throw new UnsupportedOperationException("Not implemented yet");
        Size surfaceSize;
        int surfaceFormat = -1;
        try {
            surfaceSize = LegacyCameraDevice.getSurfaceSize(surface);
            surfaceFormat = LegacyCameraDevice.detectSurfaceType(surface);
        } catch(BufferQueueAbandonedException e) {
            throw new IllegalArgumentException("Abandoned surface", e);
        }

        // See if consumer is flexible.
        boolean isFlexible = LegacyCameraDevice.isFlexibleConsumer(surface);

        // TODO: JNI function that checks the Surface's IGraphicBufferProducer state
        // Override RGB formats to IMPLEMENTATION_DEFINED, b/9487482
        if ((surfaceFormat >= LegacyMetadataMapper.HAL_PIXEL_FORMAT_RGBA_8888 &&
                        surfaceFormat <= LegacyMetadataMapper.HAL_PIXEL_FORMAT_BGRA_8888)) {
            surfaceFormat = LegacyMetadataMapper.HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
        }

        for (StreamConfiguration config : mConfigurations) {
            if (config.getFormat() == surfaceFormat && config.isOutput()) {
                // Mathing format, either need exact size match, or a flexible consumer
                // and a size no bigger than MAX_DIMEN_FOR_ROUNDING
                if (config.getSize().equals(surfaceSize)) {
                    return true;
                } else if (isFlexible &&
                        (config.getSize().getWidth() <= LegacyCameraDevice.MAX_DIMEN_FOR_ROUNDING)) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
@@ -1027,7 +1066,8 @@ public final class StreamConfigurationMap {
        int i = 0;

        for (int format : getFormatsMap(output).keySet()) {
            if (format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
            if (format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED &&
                format != HAL_PIXEL_FORMAT_RAW_OPAQUE) {
                formats[i++] = format;
            }
        }
@@ -1089,6 +1129,10 @@ public final class StreamConfigurationMap {
        if (formatsMap.containsKey(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED)) {
            size -= 1;
        }
        if (formatsMap.containsKey(HAL_PIXEL_FORMAT_RAW_OPAQUE)) {
            size -= 1;
        }

        return size;
    }