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

Commit 6a6a0b2f authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Camera: Add support for session parameters"

parents 14cddc46 75a5570f
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -15488,6 +15488,7 @@ package android.hardware.camera2 {
    method public <T> T get(android.hardware.camera2.CameraCharacteristics.Key<T>);
    method public java.util.List<android.hardware.camera2.CaptureRequest.Key<?>> getAvailableCaptureRequestKeys();
    method public java.util.List<android.hardware.camera2.CaptureResult.Key<?>> getAvailableCaptureResultKeys();
    method public java.util.List<android.hardware.camera2.CaptureRequest.Key<?>> getAvailableSessionKeys();
    method public java.util.List<android.hardware.camera2.CameraCharacteristics.Key<?>> getKeys();
    field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES;
    field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> CONTROL_AE_AVAILABLE_ANTIBANDING_MODES;
@@ -15586,6 +15587,7 @@ package android.hardware.camera2 {
    method public abstract void close();
    method public abstract android.hardware.camera2.CaptureRequest.Builder createCaptureRequest(int) throws android.hardware.camera2.CameraAccessException;
    method public abstract void createCaptureSession(java.util.List<android.view.Surface>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
    method public void createCaptureSession(android.hardware.camera2.params.SessionConfiguration) throws android.hardware.camera2.CameraAccessException;
    method public abstract void createCaptureSessionByOutputConfigurations(java.util.List<android.hardware.camera2.params.OutputConfiguration>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
    method public abstract void createConstrainedHighSpeedCaptureSession(java.util.List<android.view.Surface>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
    method public abstract android.hardware.camera2.CaptureRequest.Builder createReprocessCaptureRequest(android.hardware.camera2.TotalCaptureResult) throws android.hardware.camera2.CameraAccessException;
@@ -16129,6 +16131,20 @@ package android.hardware.camera2.params {
    field public static final int RED = 0; // 0x0
  }
  public final class SessionConfiguration {
    ctor public SessionConfiguration(int, java.util.List<android.hardware.camera2.params.OutputConfiguration>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler);
    method public android.os.Handler getHandler();
    method public android.hardware.camera2.params.InputConfiguration getInputConfiguration();
    method public java.util.List<android.hardware.camera2.params.OutputConfiguration> getOutputConfigurations();
    method public android.hardware.camera2.CaptureRequest getSessionParameters();
    method public int getSessionType();
    method public android.hardware.camera2.CameraCaptureSession.StateCallback getStateCallback();
    method public void setInputConfiguration(android.hardware.camera2.params.InputConfiguration);
    method public void setSessionParameters(android.hardware.camera2.CaptureRequest);
    field public static final int SESSION_HIGH_SPEED = 1; // 0x1
    field public static final int SESSION_REGULAR = 0; // 0x0
  }
  public final class StreamConfigurationMap {
    method public android.util.Size[] getHighResolutionOutputSizes(int);
    method public android.util.Range<java.lang.Integer>[] getHighSpeedVideoFpsRanges();
+105 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.annotation.Nullable;
import android.hardware.camera2.impl.CameraMetadataNative;
import android.hardware.camera2.impl.PublicKey;
import android.hardware.camera2.impl.SyntheticKey;
import android.hardware.camera2.params.SessionConfiguration;
import android.hardware.camera2.utils.TypeReference;
import android.util.Rational;

@@ -169,6 +170,7 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
    private final CameraMetadataNative mProperties;
    private List<CameraCharacteristics.Key<?>> mKeys;
    private List<CaptureRequest.Key<?>> mAvailableRequestKeys;
    private List<CaptureRequest.Key<?>> mAvailableSessionKeys;
    private List<CaptureResult.Key<?>> mAvailableResultKeys;

    /**
@@ -250,6 +252,67 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
        return mKeys;
    }

    /**
     * <p>Returns a subset of {@link #getAvailableCaptureRequestKeys} keys that the
     * camera device can pass as part of the capture session initialization.</p>
     *
     * <p>This list includes keys that are difficult to apply per-frame and
     * can result in unexpected delays when modified during the capture session
     * lifetime. Typical examples include parameters that require a
     * time-consuming hardware re-configuration or internal camera pipeline
     * change. For performance reasons we suggest clients to pass their initial
     * values as part of {@link SessionConfiguration#setSessionParameters}. Once
     * the camera capture session is enabled it is also recommended to avoid
     * changing them from their initial values set in
     * {@link SessionConfiguration#setSessionParameters }.
     * Control over session parameters can still be exerted in capture requests
     * but clients should be aware and expect delays during their application.
     * An example usage scenario could look like this:</p>
     * <ul>
     * <li>The camera client starts by quering the session parameter key list via
     *   {@link android.hardware.camera2.CameraCharacteristics#getAvailableSessionKeys }.</li>
     * <li>Before triggering the capture session create sequence, a capture request
     *   must be built via {@link CameraDevice#createCaptureRequest } using an
     *   appropriate template matching the particular use case.</li>
     * <li>The client should go over the list of session parameters and check
     *   whether some of the keys listed matches with the parameters that
     *   they intend to modify as part of the first capture request.</li>
     * <li>If there is no such match, the capture request can be  passed
     *   unmodified to {@link SessionConfiguration#setSessionParameters }.</li>
     * <li>If matches do exist, the client should update the respective values
     *   and pass the request to {@link SessionConfiguration#setSessionParameters }.</li>
     * <li>After the capture session initialization completes the session parameter
     *   key list can continue to serve as reference when posting or updating
     *   further requests. As mentioned above further changes to session
     *   parameters should ideally be avoided, if updates are necessary
     *   however clients could expect a delay/glitch during the
     *   parameter switch.</li>
     * </ul>
     *
     * <p>The list returned is not modifiable, so any attempts to modify it will throw
     * a {@code UnsupportedOperationException}.</p>
     *
     * <p>Each key is only listed once in the list. The order of the keys is undefined.</p>
     *
     * @return List of keys that can be passed during capture session initialization. In case the
     * camera device doesn't support such keys the list can be null.
     */
    @SuppressWarnings({"unchecked"})
    public List<CaptureRequest.Key<?>> getAvailableSessionKeys() {
        if (mAvailableSessionKeys == null) {
            Object crKey = CaptureRequest.Key.class;
            Class<CaptureRequest.Key<?>> crKeyTyped = (Class<CaptureRequest.Key<?>>)crKey;

            int[] filterTags = get(REQUEST_AVAILABLE_SESSION_KEYS);
            if (filterTags == null) {
                return null;
            }
            mAvailableSessionKeys =
                    getAvailableKeyList(CaptureRequest.class, crKeyTyped, filterTags);
        }
        return mAvailableSessionKeys;
    }

    /**
     * Returns the list of keys supported by this {@link CameraDevice} for querying
     * with a {@link CaptureRequest}.
@@ -1570,6 +1633,48 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
    public static final Key<int[]> REQUEST_AVAILABLE_CHARACTERISTICS_KEYS =
            new Key<int[]>("android.request.availableCharacteristicsKeys", int[].class);

    /**
     * <p>A subset of the available request keys that the camera device
     * can pass as part of the capture session initialization.</p>
     * <p>This is a subset of android.request.availableRequestKeys which
     * contains a list of keys that are difficult to apply per-frame and
     * can result in unexpected delays when modified during the capture session
     * lifetime. Typical examples include parameters that require a
     * time-consuming hardware re-configuration or internal camera pipeline
     * change. For performance reasons we advise clients to pass their initial
     * values as part of {@link SessionConfiguration#setSessionParameters }. Once
     * the camera capture session is enabled it is also recommended to avoid
     * changing them from their initial values set in
     * {@link SessionConfiguration#setSessionParameters }.
     * Control over session parameters can still be exerted in capture requests
     * but clients should be aware and expect delays during their application.
     * An example usage scenario could look like this:</p>
     * <ul>
     * <li>The camera client starts by quering the session parameter key list via
     *   {@link android.hardware.camera2.CameraCharacteristics#getAvailableSessionKeys }.</li>
     * <li>Before triggering the capture session create sequence, a capture request
     *   must be built via {@link CameraDevice#createCaptureRequest } using an
     *   appropriate template matching the particular use case.</li>
     * <li>The client should go over the list of session parameters and check
     *   whether some of the keys listed matches with the parameters that
     *   they intend to modify as part of the first capture request.</li>
     * <li>If there is no such match, the capture request can be  passed
     *   unmodified to {@link SessionConfiguration#setSessionParameters }.</li>
     * <li>If matches do exist, the client should update the respective values
     *   and pass the request to {@link SessionConfiguration#setSessionParameters }.</li>
     * <li>After the capture session initialization completes the session parameter
     *   key list can continue to serve as reference when posting or updating
     *   further requests. As mentioned above further changes to session
     *   parameters should ideally be avoided, if updates are necessary
     *   however clients could expect a delay/glitch during the
     *   parameter switch.</li>
     * </ul>
     * <p>This key is available on all devices.</p>
     * @hide
     */
    public static final Key<int[]> REQUEST_AVAILABLE_SESSION_KEYS =
            new Key<int[]>("android.request.availableSessionKeys", int[].class);

    /**
     * <p>The list of image formats that are supported by this
     * camera device for output streams.</p>
+21 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import static android.hardware.camera2.ICameraDeviceUser.CONSTRAINED_HIGH_SPEED_
import android.hardware.camera2.params.InputConfiguration;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.hardware.camera2.params.OutputConfiguration;
import android.hardware.camera2.params.SessionConfiguration;
import android.os.Handler;
import android.view.Surface;

@@ -810,6 +811,26 @@ public abstract class CameraDevice implements AutoCloseable {
            @Nullable Handler handler)
            throws CameraAccessException;

    /**
     * <p>Create a new {@link CameraCaptureSession} using a {@link SessionConfiguration} helper
     * object that aggregates all supported parameters.</p>
     *
     * @param config A session configuration (see {@link SessionConfiguration}).
     *
     * @throws IllegalArgumentException In case the session configuration is invalid; or the output
     *                                  configurations are empty.
     * @throws CameraAccessException In case the camera device is no longer connected or has
     *                               encountered a fatal error.
     * @see #createCaptureSession(List, CameraCaptureSession.StateCallback, Handler)
     * @see #createCaptureSessionByOutputConfigurations
     * @see #createReprocessableCaptureSession
     * @see #createConstrainedHighSpeedCaptureSession
     */
    public void createCaptureSession(
            SessionConfiguration config) throws CameraAccessException {
        throw new UnsupportedOperationException("No default implementation");
    }

    /**
     * <p>Create a {@link CaptureRequest.Builder} for new capture requests,
     * initialized with template for a target use case. The settings are chosen
+2 −1
Original line number Diff line number Diff line
@@ -800,7 +800,8 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession
                try {
                    // begin transition to unconfigured
                    mDeviceImpl.configureStreamsChecked(/*inputConfig*/null, /*outputs*/null,
                            /*operatingMode*/ ICameraDeviceUser.NORMAL_MODE);
                            /*operatingMode*/ ICameraDeviceUser.NORMAL_MODE,
                            /*sessionParams*/ null);
                } catch (CameraAccessException e) {
                    // OK: do not throw checked exceptions.
                    Log.e(TAG, mIdString + "Exception while unconfiguring outputs: ", e);
+44 −15
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import android.hardware.camera2.TotalCaptureResult;
import android.hardware.camera2.params.InputConfiguration;
import android.hardware.camera2.params.OutputConfiguration;
import android.hardware.camera2.params.ReprocessFormatsMap;
import android.hardware.camera2.params.SessionConfiguration;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.hardware.camera2.utils.SubmitInfo;
import android.hardware.camera2.utils.SurfaceUtils;
@@ -362,7 +363,7 @@ public class CameraDeviceImpl extends CameraDevice
            outputConfigs.add(new OutputConfiguration(s));
        }
        configureStreamsChecked(/*inputConfig*/null, outputConfigs,
                /*operatingMode*/ICameraDeviceUser.NORMAL_MODE);
                /*operatingMode*/ICameraDeviceUser.NORMAL_MODE, /*sessionParams*/ null);

    }

@@ -382,12 +383,13 @@ public class CameraDeviceImpl extends CameraDevice
     * @param outputs a list of one or more surfaces, or {@code null} to unconfigure
     * @param operatingMode If the stream configuration is for a normal session,
     *     a constrained high speed session, or something else.
     * @param sessionParams Session parameters.
     * @return whether or not the configuration was successful
     *
     * @throws CameraAccessException if there were any unexpected problems during configuration
     */
    public boolean configureStreamsChecked(InputConfiguration inputConfig,
            List<OutputConfiguration> outputs, int operatingMode)
            List<OutputConfiguration> outputs, int operatingMode, CaptureRequest sessionParams)
                    throws CameraAccessException {
        // Treat a null input the same an empty list
        if (outputs == null) {
@@ -463,7 +465,11 @@ public class CameraDeviceImpl extends CameraDevice
                    }
                }

                mRemoteDevice.endConfigure(operatingMode);
                if (sessionParams != null) {
                    mRemoteDevice.endConfigure(operatingMode, sessionParams.getNativeCopy());
                } else {
                    mRemoteDevice.endConfigure(operatingMode, null);
                }

                success = true;
            } catch (IllegalArgumentException e) {
@@ -499,7 +505,7 @@ public class CameraDeviceImpl extends CameraDevice
            outConfigurations.add(new OutputConfiguration(surface));
        }
        createCaptureSessionInternal(null, outConfigurations, callback, handler,
                /*operatingMode*/ICameraDeviceUser.NORMAL_MODE);
                /*operatingMode*/ICameraDeviceUser.NORMAL_MODE, /*sessionParams*/ null);
    }

    @Override
@@ -515,7 +521,7 @@ public class CameraDeviceImpl extends CameraDevice
        List<OutputConfiguration> currentOutputs = new ArrayList<>(outputConfigurations);

        createCaptureSessionInternal(null, currentOutputs, callback, handler,
                /*operatingMode*/ICameraDeviceUser.NORMAL_MODE);
                /*operatingMode*/ICameraDeviceUser.NORMAL_MODE, /*sessionParams*/null);
    }

    @Override
@@ -535,7 +541,7 @@ public class CameraDeviceImpl extends CameraDevice
            outConfigurations.add(new OutputConfiguration(surface));
        }
        createCaptureSessionInternal(inputConfig, outConfigurations, callback, handler,
                /*operatingMode*/ICameraDeviceUser.NORMAL_MODE);
                /*operatingMode*/ICameraDeviceUser.NORMAL_MODE, /*sessionParams*/ null);
    }

    @Override
@@ -563,7 +569,8 @@ public class CameraDeviceImpl extends CameraDevice
            currentOutputs.add(new OutputConfiguration(output));
        }
        createCaptureSessionInternal(inputConfig, currentOutputs,
                callback, handler, /*operatingMode*/ICameraDeviceUser.NORMAL_MODE);
                callback, handler, /*operatingMode*/ICameraDeviceUser.NORMAL_MODE,
                /*sessionParams*/ null);
    }

    @Override
@@ -574,16 +581,13 @@ public class CameraDeviceImpl extends CameraDevice
            throw new IllegalArgumentException(
                    "Output surface list must not be null and the size must be no more than 2");
        }
        StreamConfigurationMap config =
                getCharacteristics().get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
        SurfaceUtils.checkConstrainedHighSpeedSurfaces(outputs, /*fpsRange*/null, config);

        List<OutputConfiguration> outConfigurations = new ArrayList<>(outputs.size());
        for (Surface surface : outputs) {
            outConfigurations.add(new OutputConfiguration(surface));
        }
        createCaptureSessionInternal(null, outConfigurations, callback, handler,
                /*operatingMode*/ICameraDeviceUser.CONSTRAINED_HIGH_SPEED_MODE);
                /*operatingMode*/ICameraDeviceUser.CONSTRAINED_HIGH_SPEED_MODE,
                /*sessionParams*/ null);
    }

    @Override
@@ -596,13 +600,30 @@ public class CameraDeviceImpl extends CameraDevice
        for (OutputConfiguration output : outputs) {
            currentOutputs.add(new OutputConfiguration(output));
        }
        createCaptureSessionInternal(inputConfig, currentOutputs, callback, handler, operatingMode);
        createCaptureSessionInternal(inputConfig, currentOutputs, callback, handler, operatingMode,
                /*sessionParams*/ null);
    }

    @Override
    public void createCaptureSession(SessionConfiguration config)
            throws CameraAccessException {
        if (config == null) {
            throw new IllegalArgumentException("Invalid session configuration");
        }

        List<OutputConfiguration> outputConfigs = config.getOutputConfigurations();
        if (outputConfigs == null) {
            throw new IllegalArgumentException("Invalid output configurations");
        }
        createCaptureSessionInternal(config.getInputConfiguration(), outputConfigs,
                config.getStateCallback(), config.getHandler(), config.getSessionType(),
                config.getSessionParameters());
    }

    private void createCaptureSessionInternal(InputConfiguration inputConfig,
            List<OutputConfiguration> outputConfigurations,
            CameraCaptureSession.StateCallback callback, Handler handler,
            int operatingMode) throws CameraAccessException {
            int operatingMode, CaptureRequest sessionParams) throws CameraAccessException {
        synchronized(mInterfaceLock) {
            if (DEBUG) {
                Log.d(TAG, "createCaptureSessionInternal");
@@ -630,7 +651,7 @@ public class CameraDeviceImpl extends CameraDevice
            try {
                // configure streams and then block until IDLE
                configureSuccess = configureStreamsChecked(inputConfig, outputConfigurations,
                        operatingMode);
                        operatingMode, sessionParams);
                if (configureSuccess == true && inputConfig != null) {
                    input = mRemoteDevice.getInputSurface();
                }
@@ -646,6 +667,14 @@ public class CameraDeviceImpl extends CameraDevice
            // Fire onConfigured if configureOutputs succeeded, fire onConfigureFailed otherwise.
            CameraCaptureSessionCore newSession = null;
            if (isConstrainedHighSpeed) {
                ArrayList<Surface> surfaces = new ArrayList<>(outputConfigurations.size());
                for (OutputConfiguration outConfig : outputConfigurations) {
                    surfaces.add(outConfig.getSurface());
                }
                StreamConfigurationMap config =
                    getCharacteristics().get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
                SurfaceUtils.checkConstrainedHighSpeedSurfaces(surfaces, /*fpsRange*/null, config);

                newSession = new CameraConstrainedHighSpeedCaptureSessionImpl(mNextSessionId++,
                        callback, handler, this, mDeviceHandler, configureSuccess,
                        mCharacteristics);
Loading