blob: 5892f682dd494cb26960c81f3ecd0898cbdd72fd [file] [log] [blame]
/*
* Copyright (C) 2020 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;
import android.annotation.NonNull;
import java.util.concurrent.Executor;
/**
* A camera capture session that enables access to device-specific camera extensions, which
* often use multi-frame bursts and sophisticated post-process algorithms for image capture.
*
* <p>The capture session will be returned after a successful call to
* {@link CameraDevice#createExtensionSession} as part of the argument
* in the registered state callback {@link StateCallback#onConfigured}
* method. </p>
*
* <p>Note that CameraExtensionSession is currently limited to a maximum of two output
* surfaces for continuous repeating and multi-frame processing respectively. Some
* features such as capture settings will not be supported as the device-specific
* Extension is allowed to override all capture parameters.</p>
*
* <p>Information about support for specific device-specific extensions can be queried
* from {@link CameraExtensionCharacteristics}. </p>
*/
public abstract class CameraExtensionSession implements AutoCloseable {
/** @hide */
public CameraExtensionSession () {}
/**
* A callback object for tracking the progress of a
* {@link CaptureRequest} submitted to the camera device.
*
* <p>This callback is invoked when a request triggers a capture to start,
* and when the device-specific Extension post processing begins. In case of an
* error capturing an image, the error method is triggered instead of
* the completion method.</p>
*
* @see #capture
* @see #setRepeatingRequest
*/
public static abstract class ExtensionCaptureCallback {
/**
* This method is called when the camera device has started
* capturing the initial input image of the device-specific extension
* post-process request.
*
* <p>This callback is invoked right as the capture of a frame begins,
* so it is the most appropriate time for playing a shutter sound,
* or triggering UI indicators of capture.</p>
*
* <p>The request that is being used for this capture is provided,
* along with the actual timestamp for the start of exposure.</p>
*
* <p>The default implementation of this method does nothing.</p>
*
* @param session the session received during
* {@link StateCallback#onConfigured(CameraExtensionSession)}
* @param request the request for the capture that just begun
* @param timestamp the timestamp at start of capture for repeating
* request or the timestamp at start of capture of the
* first frame in a multi-frame capture.
*/
public void onCaptureStarted(@NonNull CameraExtensionSession session,
@NonNull CaptureRequest request, long timestamp) {
// default empty implementation
}
/**
* This method is called when an image (or images in case of multi-frame
* capture) is captured and device-specific extension
* processing is triggered.
*
* <p>Each request will generate at most {@code 1}
* {@link #onCaptureProcessStarted}.</p>
*
* <p>The default implementation of this method does nothing.</p>
*
* @param session the session received during
* {@link StateCallback#onConfigured(CameraExtensionSession)}
* @param request The request that was given to the CameraExtensionSession
*
* @see #capture
* @see #setRepeatingRequest
*/
public void onCaptureProcessStarted(@NonNull CameraExtensionSession session,
@NonNull CaptureRequest request) {
// default empty implementation
}
/**
* This method is called instead of
* {@link #onCaptureProcessStarted} when the camera device failed
* to produce the required input for the device-specific extension. The
* cause could be a failed camera capture request, a failed
* capture result or dropped camera frame.
*
* <p>Other requests are unaffected, and some or all image buffers
* from the capture may have been pushed to their respective output
* streams.</p>
*
* <p>The default implementation of this method does nothing.</p>
*
* @param session the session received during
* {@link StateCallback#onConfigured(CameraExtensionSession)}
* @param request The request that was given to the CameraDevice
*
* @see #capture
* @see #setRepeatingRequest
*/
public void onCaptureFailed(@NonNull CameraExtensionSession session,
@NonNull CaptureRequest request) {
// default empty implementation
}
/**
* This method is called independently of the others in
* ExtensionCaptureCallback, when a capture sequence finishes.
*
* <p>In total, there will be at least one
* {@link #onCaptureProcessStarted}/{@link #onCaptureFailed}
* invocation before this callback is triggered. If the capture
* sequence is aborted before any requests have begun processing,
* {@link #onCaptureSequenceAborted} is invoked instead.</p>
*
* <p>The default implementation does nothing.</p>
*
* @param session the session received during
* {@link StateCallback#onConfigured(CameraExtensionSession)}
* @param sequenceId A sequence ID returned by the {@link #capture}
* family of functions.
* @see #onCaptureSequenceAborted
*/
public void onCaptureSequenceCompleted(@NonNull CameraExtensionSession session,
int sequenceId) {
// default empty implementation
}
/**
* This method is called when a capture sequence aborts.
*
* <p>Due to the asynchronous nature of the camera device, not all
* submitted captures are immediately processed. It is possible to
* clear out the pending requests by a variety of operations such
* as {@link CameraExtensionSession#stopRepeating}. When such an event
* happens, {@link #onCaptureProcessStarted} will not be called.</p>
*
* <p>The default implementation does nothing.</p>
*
* @param session the session received during
* {@link StateCallback#onConfigured(CameraExtensionSession)}
* @param sequenceId A sequence ID returned by the {@link #capture}
* family of functions.
* @see #onCaptureProcessStarted
*/
public void onCaptureSequenceAborted(@NonNull CameraExtensionSession session,
int sequenceId) {
// default empty implementation
}
}
/**
* A callback object for receiving updates about the state of a camera extension session.
*
*/
public static abstract class StateCallback {
/**
* This method is called when the camera device has finished configuring itself, and the
* session can start processing capture requests.
*
* <p>If the camera device configuration fails, then {@link #onConfigureFailed} will
* be invoked instead of this callback.</p>
*
* @param session A valid extension session
*/
public abstract void onConfigured(@NonNull CameraExtensionSession session);
/**
* This method is called if the session cannot be configured as requested.
*
* <p>This can happen if the set of requested outputs contains unsupported sizes,
* too many outputs are requested at once or when trying to initialize multiple
* concurrent extension sessions from two (or more) separate camera devices
* or the camera device encounters an unrecoverable error during configuration.</p>
*
* <p>The session is considered to be closed, and all methods called on it after this
* callback is invoked will throw an IllegalStateException.</p>
*
* @param session the session instance that failed to configure
*/
public abstract void onConfigureFailed(@NonNull CameraExtensionSession session);
/**
* This method is called when the session is closed.
*
* <p>A session is closed when a new session is created by the parent camera device,
* or when the parent camera device is closed (either by the user closing the device,
* or due to a camera device disconnection or fatal error).</p>
*
* <p>Once a session is closed, all methods on it will throw an IllegalStateException, and
* any repeating requests are stopped (as if {@link #stopRepeating()} was called).
* However, any in-progress capture requests submitted to the session will be completed
* as normal.</p>
*
* @param session the session received during
* {@link StateCallback#onConfigured(CameraExtensionSession)}
*/
public void onClosed(@NonNull CameraExtensionSession session) {
// default empty implementation
}
}
/**
* Get the camera device that this session is created for.
*/
@NonNull
public android.hardware.camera2.CameraDevice getDevice() {
throw new UnsupportedOperationException("Subclasses must override this method");
}
/**
* Submit a request for device-specific processing using input
* from the camera device, to produce a single high-quality output result.
*
* <p>Note that single capture requests currently do not support
* client parameters except for {@link CaptureRequest#JPEG_ORIENTATION orientation} and
* {@link CaptureRequest#JPEG_QUALITY quality} in case of ImageFormat.JPEG output target.
* The rest of the settings included in the request will be entirely overridden by
* the device-specific extension. </p>
*
* <p>The {@link CaptureRequest.Builder#addTarget} supports only one
* ImageFormat.YUV_420_888 or ImageFormat.JPEG target surface. {@link CaptureRequest}
* arguments that include further targets will cause
* IllegalArgumentException to be thrown. </p>
*
* <p>Each request will produce one new frame for one target Surface, set
* with the CaptureRequest builder's
* {@link CaptureRequest.Builder#addTarget} method.</p>
*
* <p>Multiple requests can be in progress at once. Requests are
* processed in first-in, first-out order.</p>
*
* <p>Requests submitted through this method have higher priority than
* those submitted through {@link #setRepeatingRequest}, and will be
* processed as soon as the current repeat processing completes.</p>
*
* @param request the settings for this capture
* @param executor the executor which will be used for invoking the
* listener.
* @param listener The callback object to notify once this request has
* been processed.
* @return int A unique capture sequence ID used by
* {@link ExtensionCaptureCallback#onCaptureSequenceCompleted}.
* @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.
* @throws IllegalArgumentException if the request targets no Surfaces
* or Surfaces that are not configured as outputs for this
* session; or the request targets a set of Surfaces that
* cannot be submitted simultaneously.
*/
public int capture(@NonNull CaptureRequest request,
@NonNull Executor executor,
@NonNull ExtensionCaptureCallback listener) throws CameraAccessException {
throw new UnsupportedOperationException("Subclasses must override this method");
}
/**
* Request endlessly repeating device-specific extension processing of
* camera images.
*
* <p>With this method, the camera device will continually capture images
* and process them using the device-specific extension at the maximum
* rate possible.</p>
*
* <p>Note that repeating capture requests currently do not support
* client parameters. Settings included in the request will
* be completely overridden by the device-specific extension.</p>
*
* <p>The {@link CaptureRequest.Builder#addTarget} supports only one
* target surface. {@link CaptureRequest} arguments that include further
* targets will cause IllegalArgumentException to be thrown.</p>
*
* <p>Repeating requests are a simple way for an application to maintain a
* preview or other continuous stream of frames.</p>
*
* <p>Repeat requests have lower priority than those submitted
* through {@link #capture}, so if {@link #capture} is called when a
* repeating request is active, the capture request will be processed
* before any further repeating requests are processed.</p>
*
* <p>To stop the repeating capture, call {@link #stopRepeating}.</p>
*
* <p>Calling this method will replace any earlier repeating request.</p>
*
* @param request the request to repeat indefinitely
* @param executor the executor which will be used for invoking the
* listener.
* @param listener The callback object to notify every time the
* request finishes processing.
* @return int A unique capture sequence ID used by
* {@link ExtensionCaptureCallback#onCaptureSequenceCompleted}.
* @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.
* @throws IllegalArgumentException If the request references no
* Surfaces or references Surfaces that are not currently
* configured as outputs.
* @see #capture
*/
public int setRepeatingRequest(@NonNull CaptureRequest request,
@NonNull Executor executor,
@NonNull ExtensionCaptureCallback listener) throws CameraAccessException {
throw new UnsupportedOperationException("Subclasses must override this method");
}
/**
* Cancel any ongoing repeating capture set by
* {@link #setRepeatingRequest setRepeatingRequest}. Has no effect on
* requests submitted through {@link #capture capture}.
*
* <p>Any currently in-flight captures will still complete.</p>
*
* @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.
* @see #setRepeatingRequest
*/
public void stopRepeating() throws CameraAccessException {
throw new UnsupportedOperationException("Subclasses must override this method");
}
/**
* Close this capture session asynchronously.
*
* <p>Closing a session frees up the target output Surfaces of the session
* for reuse with either a new session, or to other APIs that can draw
* to Surfaces.</p>
*
* <p>Note that creating a new capture session with
* {@link android.hardware.camera2.CameraDevice#createCaptureSession} or
* {@link android.hardware.camera2.CameraDevice#createExtensionSession}
* will close any existing capture session automatically, and call the
* older session listener's {@link StateCallback#onClosed} callback.
* Using
* {@link android.hardware.camera2.CameraDevice#createCaptureSession} or
* {@link android.hardware.camera2.CameraDevice#createExtensionSession}
* directly without closing is the recommended approach for quickly
* switching to a new session, since unchanged target outputs can be
* reused more efficiently.</p>
*
* <p>Once a session is closed, all methods on it will throw an
* IllegalStateException, and any repeating requests are
* stopped (as if {@link #stopRepeating()} was called).</p>
*
* <p>Closing a session is idempotent; closing more than once has no
* effect.</p>
*/
public void close() throws CameraAccessException {
throw new UnsupportedOperationException("Subclasses must override this method");
}
}