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

Commit e8526a01 authored by Zhijun He's avatar Zhijun He Committed by Android (Google) Code Review
Browse files

Merge "Camera2: add deferred output config support" into nyc-mr1-dev

parents fa790104 c8b181e9
Loading
Loading
Loading
Loading
+48 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package android.hardware.camera2;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.hardware.camera2.params.OutputConfiguration;
import android.os.Handler;
import android.view.Surface;

@@ -219,6 +220,53 @@ public abstract class CameraCaptureSession implements AutoCloseable {
     */
    public abstract void tearDown(@NonNull Surface surface) throws CameraAccessException;

    /**
     * <p>
     * Finish the deferred output configurations where the output Surface was not configured before.
     * </p>
     * <p>
     * For camera use cases where a preview and other output configurations need to be configured,
     * it can take some time for the preview Surface to be ready (e.g., if the preview Surface is
     * obtained from {@link android.view.SurfaceView}, the SurfaceView is ready after the UI layout
     * is done, then it takes some time to get the preview Surface).
     * </p>
     * <p>
     * To speed up camera startup time, the application can configure the
     * {@link CameraCaptureSession} with the desired preview size, and defer the preview output
     * configuration until the Surface is ready. After the {@link CameraCaptureSession} is created
     * successfully with this deferred configuration and other normal configurations, the
     * application can submit requests that don't include deferred output Surfaces. Once the
     * deferred Surface is ready, the application can set the Surface to the same deferred output
     * configuration with the {@link OutputConfiguration#setDeferredSurface} method, and then finish
     * the deferred output configuration via this method, before it can submit requests with this
     * output target.
     * </p>
     * <p>
     * The output Surfaces included by this list of deferred {@link OutputConfiguration
     * OutputConfigurations} can be used as {@link CaptureRequest} targets as soon as this call
     * returns;
     * </p>
     * <p>
     * This method is not supported by Legacy devices.
     * </p>
     *
     * @param deferredOutputConfigs a list of {@link OutputConfiguration OutputConfigurations} that
     *            have had {@link OutputConfiguration#setDeferredSurface setDeferredSurface} invoked
     *            with a valid output Surface.
     * @throws CameraAccessException if the camera device is no longer connected or has encountered
     *             a fatal error.
     * @throws IllegalStateException if this session is no longer active, either because the session
     *             was explicitly closed, a new session has been created or the camera device has
     *             been closed. Or if this output configuration was already finished with the
     *             included surface before.
     * @throws IllegalArgumentException for invalid output configurations, including ones where the
     *             source of the Surface is no longer valid or the Surface is from a unsupported
     *             source.
     * @hide
     */
    public abstract void finishDeferredConfiguration(
            List<OutputConfiguration> deferredOutputConfigs) throws CameraAccessException;

    /**
     * <p>Submit a request for an image to be captured by the camera device.</p>
     *
+7 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.hardware.camera2.dispatch.BroadcastDispatcher;
import android.hardware.camera2.dispatch.DuckTypingDispatcher;
import android.hardware.camera2.dispatch.HandlerDispatcher;
import android.hardware.camera2.dispatch.InvokeDispatcher;
import android.hardware.camera2.params.OutputConfiguration;
import android.hardware.camera2.utils.TaskDrainer;
import android.hardware.camera2.utils.TaskSingleDrainer;
import android.os.Handler;
@@ -155,6 +156,12 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession
        mDeviceImpl.tearDown(surface);
    }

    @Override
    public void finishDeferredConfiguration(
            List<OutputConfiguration> deferredOutputConfigs) throws CameraAccessException {
        mDeviceImpl.finishDeferredConfig(deferredOutputConfigs);
    }

    @Override
    public synchronized int capture(CaptureRequest request, CaptureCallback callback,
            Handler handler) throws CameraAccessException {
+13 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraConstrainedHighSpeedCaptureSession;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.params.OutputConfiguration;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.hardware.camera2.utils.SurfaceUtils;
import android.os.Handler;
@@ -256,6 +257,12 @@ public class CameraConstrainedHighSpeedCaptureSessionImpl
        return mSessionImpl.isAborting();
    }

    @Override
    public void finishDeferredConfiguration(List<OutputConfiguration> deferredOutputConfigs)
            throws CameraAccessException {
        mSessionImpl.finishDeferredConfiguration(deferredOutputConfigs);
    }

    private class WrapperCallback extends StateCallback {
        private final StateCallback mCallback;

@@ -263,26 +270,32 @@ public class CameraConstrainedHighSpeedCaptureSessionImpl
            mCallback = callback;
        }

        @Override
        public void onConfigured(CameraCaptureSession session) {
            mCallback.onConfigured(CameraConstrainedHighSpeedCaptureSessionImpl.this);
        }

        @Override
        public void onConfigureFailed(CameraCaptureSession session) {
            mCallback.onConfigureFailed(CameraConstrainedHighSpeedCaptureSessionImpl.this);
        }

        @Override
        public void onReady(CameraCaptureSession session) {
            mCallback.onReady(CameraConstrainedHighSpeedCaptureSessionImpl.this);
        }

        @Override
        public void onActive(CameraCaptureSession session) {
            mCallback.onActive(CameraConstrainedHighSpeedCaptureSessionImpl.this);
        }

        @Override
        public void onClosed(CameraCaptureSession session) {
            mCallback.onClosed(CameraConstrainedHighSpeedCaptureSessionImpl.this);
        }

        @Override
        public void onSurfacePrepared(CameraCaptureSession session, Surface surface) {
            mCallback.onSurfacePrepared(CameraConstrainedHighSpeedCaptureSessionImpl.this,
                    surface);
+36 −1
Original line number Diff line number Diff line
@@ -407,7 +407,10 @@ public class CameraDeviceImpl extends CameraDevice
                int streamId = mConfiguredOutputs.keyAt(i);
                OutputConfiguration outConfig = mConfiguredOutputs.valueAt(i);

                if (!outputs.contains(outConfig)) {
                if (!outputs.contains(outConfig) || outConfig.isDeferredConfiguration()) {
                    // Always delete the deferred output configuration when the session
                    // is created, as the deferred output configuration doesn't have unique surface
                    // related identifies.
                    deleteList.add(streamId);
                } else {
                    addSet.remove(outConfig);  // Don't create a stream previously created
@@ -744,6 +747,37 @@ public class CameraDeviceImpl extends CameraDevice
        }
    }

    public void finishDeferredConfig(List<OutputConfiguration> deferredConfigs)
            throws CameraAccessException {
        if (deferredConfigs == null || deferredConfigs.size() == 0) {
            throw new IllegalArgumentException("deferred config is null or empty");
        }

        synchronized(mInterfaceLock) {
            for (OutputConfiguration config : deferredConfigs) {
                int streamId = -1;
                for (int i = 0; i < mConfiguredOutputs.size(); i++) {
                    // Have to use equal here, as createCaptureSessionByOutputConfigurations() and
                    // createReprocessableCaptureSessionByConfigurations() do a copy of the configs.
                    if (config.equals(mConfiguredOutputs.valueAt(i))) {
                        streamId = mConfiguredOutputs.keyAt(i);
                        break;
                    }
                }
                if (streamId == -1) {
                    throw new IllegalArgumentException("Deferred config is not part of this "
                            + "session");
                }

                if (config.getSurface() == null) {
                    throw new IllegalArgumentException("The deferred config for stream " + streamId
                            + " must have a non-null surface");
                }
                mRemoteDevice.setDeferredConfiguration(streamId, config);
            }
        }
    }

    public int capture(CaptureRequest request, CaptureCallback callback, Handler handler)
            throws CameraAccessException {
        if (DEBUG) {
@@ -2037,6 +2071,7 @@ public class CameraDeviceImpl extends CameraDevice
     *
     * <p> Handle binder death for ICameraDeviceUser. Trigger onError.</p>
     */
    @Override
    public void binderDied() {
        Log.w(TAG, "CameraDevice " + mCameraId + " died unexpectedly");

+9 −0
Original line number Diff line number Diff line
@@ -215,5 +215,14 @@ public class ICameraDeviceUserWrapper {
        }
    }

    public void setDeferredConfiguration(int streamId, OutputConfiguration deferredConfig)
            throws CameraAccessException {
        try {
            mRemoteDevice.setDeferredConfiguration(streamId, deferredConfig);
        } catch (Throwable t) {
            CameraManager.throwAsPublicException(t);
            throw new UnsupportedOperationException("Unexpected exception", t);
        }
    }

}
Loading