1510 lines
85 KiB
Java
1510 lines
85 KiB
Java
![]() |
/*
|
||
|
* 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;
|
||
|
|
||
|
import android.annotation.CallbackExecutor;
|
||
|
import android.annotation.NonNull;
|
||
|
import android.annotation.Nullable;
|
||
|
import android.hardware.camera2.CameraOfflineSession;
|
||
|
import android.hardware.camera2.CameraOfflineSession.CameraOfflineSessionCallback;
|
||
|
import android.hardware.camera2.params.OutputConfiguration;
|
||
|
import android.os.Handler;
|
||
|
import android.view.Surface;
|
||
|
|
||
|
import java.util.Collection;
|
||
|
import java.util.List;
|
||
|
import java.util.concurrent.Executor;
|
||
|
|
||
|
/**
|
||
|
* A configured capture session for a {@link CameraDevice}, used for capturing images from the
|
||
|
* camera or reprocessing images captured from the camera in the same session previously.
|
||
|
*
|
||
|
* <p>A CameraCaptureSession is created by providing a set of target output surfaces to
|
||
|
* {@link CameraDevice#createCaptureSession createCaptureSession}, or by providing an
|
||
|
* {@link android.hardware.camera2.params.InputConfiguration} and a set of target output surfaces to
|
||
|
* {@link CameraDevice#createReprocessableCaptureSession createReprocessableCaptureSession} for a
|
||
|
* reprocessable capture session. Once created, the session is active until a new session is
|
||
|
* created by the camera device, or the camera device is closed.</p>
|
||
|
*
|
||
|
* <p>All capture sessions can be used for capturing images from the camera but only reprocessable
|
||
|
* capture sessions can reprocess images captured from the camera in the same session previously.
|
||
|
* </p>
|
||
|
*
|
||
|
* <p>Creating a session is an expensive operation and can take several hundred milliseconds, since
|
||
|
* it requires configuring the camera device's internal pipelines and allocating memory buffers for
|
||
|
* sending images to the desired targets. Therefore the setup is done asynchronously, and
|
||
|
* {@link CameraDevice#createCaptureSession createCaptureSession} and
|
||
|
* {@link CameraDevice#createReprocessableCaptureSession createReprocessableCaptureSession} will
|
||
|
* send the ready-to-use CameraCaptureSession to the provided listener's
|
||
|
* {@link CameraCaptureSession.StateCallback#onConfigured onConfigured} callback. If configuration
|
||
|
* cannot be completed, then the
|
||
|
* {@link CameraCaptureSession.StateCallback#onConfigureFailed onConfigureFailed} is called, and the
|
||
|
* session will not become active.</p>
|
||
|
*<!--
|
||
|
* <p>Any capture requests (repeating or non-repeating) submitted before the session is ready will
|
||
|
* be queued up and will begin capture once the session becomes ready. In case the session cannot be
|
||
|
* configured and {@link StateCallback#onConfigureFailed onConfigureFailed} is called, all queued
|
||
|
* capture requests are discarded.</p>
|
||
|
*-->
|
||
|
* <p>If a new session is created by the camera device, then the previous session is closed, and its
|
||
|
* associated {@link StateCallback#onClosed onClosed} callback will be invoked. All
|
||
|
* of the session methods will throw an IllegalStateException if called once the session is
|
||
|
* closed.</p>
|
||
|
*
|
||
|
* <p>A closed session clears any repeating requests (as if {@link #stopRepeating} had been called),
|
||
|
* but will still complete all of its in-progress capture requests as normal, before a newly
|
||
|
* created session takes over and reconfigures the camera device.</p>
|
||
|
*/
|
||
|
public abstract class CameraCaptureSession implements AutoCloseable {
|
||
|
|
||
|
/**
|
||
|
* Used to identify invalid session ID.
|
||
|
* @hide
|
||
|
*/
|
||
|
public static final int SESSION_ID_NONE = -1;
|
||
|
|
||
|
/**
|
||
|
* Get the camera device that this session is created for.
|
||
|
*/
|
||
|
@NonNull
|
||
|
public abstract CameraDevice getDevice();
|
||
|
|
||
|
/**
|
||
|
* <p>Pre-allocate all buffers for an output Surface.</p>
|
||
|
*
|
||
|
* <p>Normally, the image buffers for a given output Surface are allocated on-demand,
|
||
|
* to minimize startup latency and memory overhead.</p>
|
||
|
*
|
||
|
* <p>However, in some cases, it may be desirable for the buffers to be allocated before
|
||
|
* any requests targeting the Surface are actually submitted to the device. Large buffers
|
||
|
* may take some time to allocate, which can result in delays in submitting requests until
|
||
|
* sufficient buffers are allocated to reach steady-state behavior. Such delays can cause
|
||
|
* bursts to take longer than desired, or cause skips or stutters in preview output.</p>
|
||
|
*
|
||
|
* <p>The prepare() method can be used to perform this preallocation. It may only be called for
|
||
|
* a given output Surface before that Surface is used as a target for a request. The number of
|
||
|
* buffers allocated is the sum of the count needed by the consumer providing the output
|
||
|
* Surface, and the maximum number needed by the camera device to fill its pipeline. Since this
|
||
|
* may be a larger number than what is actually required for steady-state operation, using
|
||
|
* prepare may result in higher memory consumption than the normal on-demand behavior results
|
||
|
* in. Prepare() will also delay the time to first output to a given Surface, in exchange for
|
||
|
* smoother frame rate once the allocation is complete.</p>
|
||
|
*
|
||
|
* <p>For example, an application that creates an
|
||
|
* {@link android.media.ImageReader#newInstance ImageReader} with a maxImages argument of 10,
|
||
|
* but only uses 3 simultaneous Images at once would normally only cause those 3 images to be
|
||
|
* allocated (plus what is needed by the camera device for smooth operation). But using
|
||
|
* prepare() on the ImageReader Surface will result in all 10 Images being allocated. So
|
||
|
* applications using this method should take care to request only the number of buffers
|
||
|
* actually necessary for their application.</p>
|
||
|
*
|
||
|
* <p>If the same output Surface is used in consecutive sessions (without closing the first
|
||
|
* session explicitly), then its already-allocated buffers are carried over, and if it was
|
||
|
* used as a target of a capture request in the first session, prepare cannot be called on it
|
||
|
* in the second session.</p>
|
||
|
*
|
||
|
* <p>Once allocation is complete, {@link StateCallback#onSurfacePrepared} will be invoked with
|
||
|
* the Surface provided to this method. Between the prepare call and the onSurfacePrepared call,
|
||
|
* the Surface provided to prepare must not be used as a target of a CaptureRequest submitted
|
||
|
* to this session.</p>
|
||
|
*
|
||
|
* <p>Note that if 2 surfaces share the same stream via {@link
|
||
|
* OutputConfiguration#enableSurfaceSharing} and {@link OutputConfiguration#addSurface},
|
||
|
* prepare() only needs to be called on one surface, and {@link
|
||
|
* StateCallback#onSurfacePrepared} will be triggered for both surfaces.</p>
|
||
|
*
|
||
|
* <p>{@link android.hardware.camera2.CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY LEGACY}
|
||
|
* devices cannot pre-allocate output buffers; for those devices,
|
||
|
* {@link StateCallback#onSurfacePrepared} will be immediately called, and no preallocation is
|
||
|
* done.</p>
|
||
|
*
|
||
|
* @param surface the output Surface for which buffers should be pre-allocated. Must be one of
|
||
|
* the output Surfaces used to create this session.
|
||
|
*
|
||
|
* @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 Surface is invalid, not part of this Session, or has
|
||
|
* already been used as a target of a CaptureRequest in this
|
||
|
* session or immediately prior sessions.
|
||
|
*
|
||
|
* @see StateCallback#onSurfacePrepared
|
||
|
*/
|
||
|
public abstract void prepare(@NonNull Surface surface) throws CameraAccessException;
|
||
|
|
||
|
/**
|
||
|
* <p>Pre-allocate at most maxCount buffers for an output Surface.</p>
|
||
|
*
|
||
|
* <p>Like the {@link #prepare(Surface)} method, this method can be used to allocate output
|
||
|
* buffers for a given Surface. However, while the {@link #prepare(Surface)} method allocates
|
||
|
* the maximum possible buffer count, this method allocates at most maxCount buffers.</p>
|
||
|
*
|
||
|
* <p>If maxCount is greater than the possible maximum count (which is the sum of the buffer
|
||
|
* count requested by the creator of the Surface and the count requested by the camera device),
|
||
|
* only the possible maximum count is allocated, in which case the function acts exactly like
|
||
|
* {@link #prepare(Surface)}.</p>
|
||
|
*
|
||
|
* <p>The restrictions on when this method can be called are the same as for
|
||
|
* {@link #prepare(Surface)}.</p>
|
||
|
*
|
||
|
* <p>Repeated calls to this method are allowed, and a mix of {@link #prepare(Surface)} and
|
||
|
* this method is also allowed. Note that after the first call to {@link #prepare(Surface)},
|
||
|
* subsequent calls to either prepare method are effectively no-ops. In addition, this method
|
||
|
* is not additive in terms of buffer count. This means calling it twice with maxCount = 2
|
||
|
* will only allocate 2 buffers, not 4 (assuming the possible maximum is at least 2); to
|
||
|
* allocate two buffers on the first call and two on the second, the application needs to call
|
||
|
* prepare with prepare(surface, 2) and prepare(surface, 4).</p>
|
||
|
*
|
||
|
* @param maxCount the buffer count to try to allocate. If this is greater than the possible
|
||
|
* maximum for this output, the possible maximum is allocated instead. If
|
||
|
* maxCount buffers are already allocated, then prepare will do nothing.
|
||
|
* @param surface the output Surface for which buffers should be pre-allocated.
|
||
|
*
|
||
|
* @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 Surface is invalid, not part of this Session,
|
||
|
* or has already been used as a target of a CaptureRequest in
|
||
|
* this session or immediately prior sessions without an
|
||
|
* intervening tearDown call.
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
@SuppressWarnings("HiddenAbstractMethod")
|
||
|
public abstract void prepare(int maxCount, @NonNull Surface surface)
|
||
|
throws CameraAccessException;
|
||
|
|
||
|
/**
|
||
|
* <p>Free all buffers allocated for an output Surface.</p>
|
||
|
*
|
||
|
* <p>Normally, once allocated, the image buffers for a given output Surface remain allocated
|
||
|
* for the lifetime of the capture session, to minimize latency of captures and to reduce
|
||
|
* memory allocation overhead.</p>
|
||
|
*
|
||
|
* <p>However, in some cases, it may be desirable for allocated buffers to be freed to reduce
|
||
|
* the application's memory consumption, if the particular output Surface will not be used by
|
||
|
* the application for some time.</p>
|
||
|
*
|
||
|
* <p>The tearDown() method can be used to perform this operation. After the call finishes, all
|
||
|
* unfilled image buffers will have been freed. Any future use of the target Surface may require
|
||
|
* allocation of additional buffers, as if the session had just been created. Buffers being
|
||
|
* held by the application (either explicitly as Image objects from ImageReader, or implicitly
|
||
|
* as the current texture in a SurfaceTexture or the current contents of a RS Allocation, will
|
||
|
* remain valid and allocated even when tearDown is invoked.</p>
|
||
|
*
|
||
|
* <p>A Surface that has had tearDown() called on it is eligible to have prepare() invoked on it
|
||
|
* again even if it was used as a request target before the tearDown() call, as long as it
|
||
|
* doesn't get used as a target of a request between the tearDown() and prepare() calls.</p>
|
||
|
*
|
||
|
* @param surface the output Surface for which buffers should be freed. Must be one of the
|
||
|
* the output Surfaces used to create this session.
|
||
|
*
|
||
|
* @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 Surface is invalid, not part of this Session, or has
|
||
|
* already been used as a target of a CaptureRequest in this
|
||
|
* session or immediately prior sessions.
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
@SuppressWarnings("HiddenAbstractMethod")
|
||
|
public abstract void tearDown(@NonNull Surface surface) throws CameraAccessException;
|
||
|
|
||
|
/**
|
||
|
* <p>Finalize the output configurations that now have their deferred and/or extra Surfaces
|
||
|
* included.</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. For example, if the
|
||
|
* preview Surface is obtained from {@link android.view.SurfaceView}, the SurfaceView will only
|
||
|
* be ready after the UI layout is done, potentially delaying camera startup.</p>
|
||
|
*
|
||
|
* <p>To speed up camera startup time, the application can configure the
|
||
|
* {@link CameraCaptureSession} with the eventual preview size (via
|
||
|
* {@link OutputConfiguration#OutputConfiguration(Size,Class) a deferred OutputConfiguration}),
|
||
|
* and defer the preview output configuration until the Surface is ready. After the
|
||
|
* {@link CameraCaptureSession} is created successfully with this deferred output and other
|
||
|
* normal outputs, the application can start submitting requests as long as they do not include
|
||
|
* deferred output Surfaces. Once a deferred Surface is ready, the application can add the
|
||
|
* Surface to the deferred output configuration with the
|
||
|
* {@link OutputConfiguration#addSurface} method, and then update the deferred output
|
||
|
* configuration via this method, before it can submit capture requests with this output
|
||
|
* target.</p>
|
||
|
*
|
||
|
* <p>This function can also be called in case where multiple surfaces share the same
|
||
|
* OutputConfiguration, and one of the surfaces becomes available after the {@link
|
||
|
* CameraCaptureSession} is created. In that case, the application must first create the
|
||
|
* OutputConfiguration with the available Surface, then enable further surface sharing via
|
||
|
* {@link OutputConfiguration#enableSurfaceSharing}, before creating the CameraCaptureSession.
|
||
|
* After the CameraCaptureSession is created, and once the extra Surface becomes available, the
|
||
|
* application must then call {@link OutputConfiguration#addSurface} before finalizing the
|
||
|
* configuration with this method.</p>
|
||
|
*
|
||
|
* <p>If the provided OutputConfigurations are unchanged from session creation, this function
|
||
|
* call has no effect. This function must only be called once for a particular output
|
||
|
* configuration. </p>
|
||
|
*
|
||
|
* <p>The output Surfaces included by this list of
|
||
|
* {@link OutputConfiguration OutputConfigurations} can be used as {@link CaptureRequest}
|
||
|
* targets as soon as this call returns.</p>
|
||
|
*
|
||
|
* <p>This method is not supported by
|
||
|
* {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY LEGACY}-level devices.</p>
|
||
|
*
|
||
|
* @param outputConfigs a list of {@link OutputConfiguration OutputConfigurations} that
|
||
|
* have had {@link OutputConfiguration#addSurface addSurface} invoked with a valid
|
||
|
* output Surface after {@link CameraDevice#createCaptureSessionByOutputConfigurations}.
|
||
|
* @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 for invalid output configurations, including ones where the
|
||
|
* source of the Surface is no longer valid or the Surface is from a unsupported
|
||
|
* source. Or if one of the output configuration was already finished with an
|
||
|
* included surface in a prior call.
|
||
|
*/
|
||
|
public abstract void finalizeOutputConfigurations(
|
||
|
List<OutputConfiguration> outputConfigs) throws CameraAccessException;
|
||
|
|
||
|
/**
|
||
|
* <p>Submit a request for an image to be captured by the camera device.</p>
|
||
|
*
|
||
|
* <p>The request defines all the parameters for capturing the single image,
|
||
|
* including sensor, lens, flash, and post-processing settings.</p>
|
||
|
*
|
||
|
* <p>Each request will produce one {@link CaptureResult} and produce new frames for one or more
|
||
|
* target Surfaces, set with the CaptureRequest builder's
|
||
|
* {@link CaptureRequest.Builder#addTarget} method. The target surfaces (set with
|
||
|
* {@link CaptureRequest.Builder#addTarget}) must be a subset of the surfaces provided when this
|
||
|
* capture session was created.</p>
|
||
|
*
|
||
|
* <p>Multiple regular and reprocess requests can be in progress at once. If there are only
|
||
|
* regular requests or reprocess requests in progress, they are processed in first-in,
|
||
|
* first-out order. If there are both regular and reprocess requests in progress, regular
|
||
|
* requests are processed in first-in, first-out order and reprocess requests are processed in
|
||
|
* first-in, first-out order, respectively. However, the processing order of a regular request
|
||
|
* and a reprocess request in progress is not specified. In other words, a regular request
|
||
|
* will always be processed before regular requests that are submitted later. A reprocess
|
||
|
* request will always be processed before reprocess requests that are submitted later. However,
|
||
|
* a regular request may not be processed before reprocess requests that are submitted later.<p>
|
||
|
*
|
||
|
* <p>Requests submitted through this method have higher priority than
|
||
|
* those submitted through {@link #setRepeatingRequest} or
|
||
|
* {@link #setRepeatingBurst}, and will be processed as soon as the current
|
||
|
* repeat/repeatBurst processing completes.</p>
|
||
|
*
|
||
|
* <p>All capture sessions can be used for capturing images from the camera but only capture
|
||
|
* sessions created by
|
||
|
* {@link CameraDevice#createReprocessableCaptureSession createReprocessableCaptureSession}
|
||
|
* can submit reprocess capture requests. Submitting a reprocess request to a regular capture
|
||
|
* session will result in an {@link IllegalArgumentException}.</p>
|
||
|
*
|
||
|
* <p>Submitting a request that targets Surfaces with an unsupported dynamic range combination
|
||
|
* will result in an {@link IllegalArgumentException}.</p>
|
||
|
*
|
||
|
* @param request the settings for this capture
|
||
|
* @param listener The callback object to notify once this request has been
|
||
|
* processed. If null, no metadata will be produced for this capture,
|
||
|
* although image data will still be produced.
|
||
|
* @param handler the handler on which the listener should be invoked, or
|
||
|
* {@code null} to use the current thread's {@link android.os.Looper
|
||
|
* looper}.
|
||
|
*
|
||
|
* @return int A unique capture sequence ID used by
|
||
|
* {@link CaptureCallback#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 in a reprocessable capture session; or a
|
||
|
* reprocess capture request is submitted in a
|
||
|
* non-reprocessable capture session; or the reprocess capture
|
||
|
* request was created with a {@link TotalCaptureResult} from
|
||
|
* a different session; or the capture targets a Surface in
|
||
|
* the middle of being {@link #prepare prepared}; or the
|
||
|
* handler is null, the listener is not null, and the calling
|
||
|
* thread has no looper; or the request targets Surfaces with
|
||
|
* an unsupported dynamic range combination
|
||
|
*
|
||
|
* @see #captureBurst
|
||
|
* @see #setRepeatingRequest
|
||
|
* @see #setRepeatingBurst
|
||
|
* @see #abortCaptures
|
||
|
* @see CameraDevice#createReprocessableCaptureSession
|
||
|
* @see android.hardware.camera2.params.DynamicRangeProfiles#getProfileCaptureRequestConstraints
|
||
|
*/
|
||
|
public abstract int capture(@NonNull CaptureRequest request,
|
||
|
@Nullable CaptureCallback listener, @Nullable Handler handler)
|
||
|
throws CameraAccessException;
|
||
|
|
||
|
/**
|
||
|
* <p>Submit a request for an image to be captured by the camera device.</p>
|
||
|
*
|
||
|
* <p>The behavior of this method matches that of
|
||
|
* {@link #capture(CaptureRequest, CaptureCallback, Handler)},
|
||
|
* except that it uses {@link java.util.concurrent.Executor} as an argument
|
||
|
* instead of {@link android.os.Handler}.</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 CaptureCallback#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 in a reprocessable capture session; or a
|
||
|
* reprocess capture request is submitted in a
|
||
|
* non-reprocessable capture session; or the reprocess capture
|
||
|
* request was created with a {@link TotalCaptureResult} from
|
||
|
* a different session; or the capture targets a Surface in
|
||
|
* the middle of being {@link #prepare prepared}; or the
|
||
|
* executor is null, or the listener is not null;
|
||
|
* or the request targets Surfaces with an unsupported dynamic
|
||
|
* range combination;
|
||
|
*
|
||
|
* @see #captureBurst
|
||
|
* @see #setRepeatingRequest
|
||
|
* @see #setRepeatingBurst
|
||
|
* @see #abortCaptures
|
||
|
* @see CameraDevice#createReprocessableCaptureSession
|
||
|
* @see android.hardware.camera2.params.DynamicRangeProfiles#getProfileCaptureRequestConstraints
|
||
|
*/
|
||
|
public int captureSingleRequest(@NonNull CaptureRequest request,
|
||
|
@NonNull @CallbackExecutor Executor executor, @NonNull CaptureCallback listener)
|
||
|
throws CameraAccessException {
|
||
|
throw new UnsupportedOperationException("Subclasses must override this method");
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Submit a list of requests to be captured in sequence as a burst. The
|
||
|
* burst will be captured in the minimum amount of time possible, and will
|
||
|
* not be interleaved with requests submitted by other capture or repeat
|
||
|
* calls.
|
||
|
*
|
||
|
* <p>Regular and reprocess requests can be mixed together in a single burst. Regular requests
|
||
|
* will be captured in order and reprocess requests will be processed in order, respectively.
|
||
|
* However, the processing order between a regular request and a reprocess request is not
|
||
|
* specified. Each capture produces one {@link CaptureResult} and image buffers for one or more
|
||
|
* target {@link android.view.Surface surfaces}. The target surfaces (set with
|
||
|
* {@link CaptureRequest.Builder#addTarget}) must be a subset of the surfaces provided when
|
||
|
* this capture session was created.</p>
|
||
|
*
|
||
|
* <p>The main difference between this method and simply calling
|
||
|
* {@link #capture} repeatedly is that this method guarantees that no
|
||
|
* other requests will be interspersed with the burst.</p>
|
||
|
*
|
||
|
* <p>All capture sessions can be used for capturing images from the camera but only capture
|
||
|
* sessions created by
|
||
|
* {@link CameraDevice#createReprocessableCaptureSession createReprocessableCaptureSession}
|
||
|
* can submit reprocess capture requests. Submitting a reprocess request to a regular
|
||
|
* capture session will result in an {@link IllegalArgumentException}.</p>
|
||
|
*
|
||
|
* <p>Submitting a request that targets Surfaces with an unsupported dynamic range combination
|
||
|
* will result in an {@link IllegalArgumentException}.</p>
|
||
|
*
|
||
|
* @param requests the list of settings for this burst capture
|
||
|
* @param listener The callback object to notify each time one of the
|
||
|
* requests in the burst has been processed. If null, no metadata will be
|
||
|
* produced for any requests in this burst, although image data will still
|
||
|
* be produced.
|
||
|
* @param handler the handler on which the listener should be invoked, or
|
||
|
* {@code null} to use the current thread's {@link android.os.Looper
|
||
|
* looper}.
|
||
|
*
|
||
|
* @return int A unique capture sequence ID used by
|
||
|
* {@link CaptureCallback#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 requests target no Surfaces, or the requests target
|
||
|
* Surfaces not currently configured as outputs; or one of the
|
||
|
* requests targets a set of Surfaces that cannot be submitted
|
||
|
* simultaneously in a reprocessable capture session; or a
|
||
|
* reprocess capture request is submitted in a
|
||
|
* non-reprocessable capture session; or one of the reprocess
|
||
|
* capture requests was created with a
|
||
|
* {@link TotalCaptureResult} from a different session; or one
|
||
|
* of the captures targets a Surface in the middle of being
|
||
|
* {@link #prepare prepared}; or if the handler is null, the
|
||
|
* listener is not null, and the calling thread has no looper;
|
||
|
* or the request targets Surfaces with an unsupported dynamic
|
||
|
* range combination.
|
||
|
*
|
||
|
* @see #capture
|
||
|
* @see #setRepeatingRequest
|
||
|
* @see #setRepeatingBurst
|
||
|
* @see #abortCaptures
|
||
|
* @see android.hardware.camera2.params.DynamicRangeProfiles#getProfileCaptureRequestConstraints
|
||
|
*/
|
||
|
public abstract int captureBurst(@NonNull List<CaptureRequest> requests,
|
||
|
@Nullable CaptureCallback listener, @Nullable Handler handler)
|
||
|
throws CameraAccessException;
|
||
|
|
||
|
/**
|
||
|
* Submit a list of requests to be captured in sequence as a burst. The
|
||
|
* burst will be captured in the minimum amount of time possible, and will
|
||
|
* not be interleaved with requests submitted by other capture or repeat
|
||
|
* calls.
|
||
|
*
|
||
|
* <p>The behavior of this method matches that of
|
||
|
* {@link #captureBurst(List, CaptureCallback, Handler)},
|
||
|
* except that it uses {@link java.util.concurrent.Executor} as an argument
|
||
|
* instead of {@link android.os.Handler}.</p>
|
||
|
*
|
||
|
* @param requests the list of settings for this burst capture
|
||
|
* @param executor the executor which will be used for invoking the listener.
|
||
|
* @param listener The callback object to notify each time one of the
|
||
|
* requests in the burst has been processed.
|
||
|
*
|
||
|
* @return int A unique capture sequence ID used by
|
||
|
* {@link CaptureCallback#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 requests target no Surfaces, or the requests target
|
||
|
* Surfaces not currently configured as outputs; or one of the
|
||
|
* requests targets a set of Surfaces that cannot be submitted
|
||
|
* simultaneously in a reprocessable capture session; or a
|
||
|
* reprocess capture request is submitted in a
|
||
|
* non-reprocessable capture session; or one of the reprocess
|
||
|
* capture requests was created with a
|
||
|
* {@link TotalCaptureResult} from a different session; or one
|
||
|
* of the captures targets a Surface in the middle of being
|
||
|
* {@link #prepare prepared}; or if the executor is null; or if
|
||
|
* the listener is null;
|
||
|
* or the request targets Surfaces with an unsupported dynamic
|
||
|
* range combination.
|
||
|
*
|
||
|
* @see #capture
|
||
|
* @see #setRepeatingRequest
|
||
|
* @see #setRepeatingBurst
|
||
|
* @see #abortCaptures
|
||
|
* @see android.hardware.camera2.params.DynamicRangeProfiles#getProfileCaptureRequestConstraints
|
||
|
*/
|
||
|
public int captureBurstRequests(@NonNull List<CaptureRequest> requests,
|
||
|
@NonNull @CallbackExecutor Executor executor, @NonNull CaptureCallback listener)
|
||
|
throws CameraAccessException {
|
||
|
throw new UnsupportedOperationException("Subclasses must override this method");
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Request endlessly repeating capture of images by this capture session.
|
||
|
*
|
||
|
* <p>With this method, the camera device will continually capture images
|
||
|
* using the settings in the provided {@link CaptureRequest}, at the maximum
|
||
|
* rate possible.</p>
|
||
|
*
|
||
|
* <p>Repeating requests are a simple way for an application to maintain a
|
||
|
* preview or other continuous stream of frames, without having to
|
||
|
* continually submit identical requests through {@link #capture}.</p>
|
||
|
*
|
||
|
* <p>Repeat requests have lower priority than those submitted
|
||
|
* through {@link #capture} or {@link #captureBurst}, 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}. Calling
|
||
|
* {@link #abortCaptures} will also clear the request.</p>
|
||
|
*
|
||
|
* <p>Calling this method will replace any earlier repeating request or
|
||
|
* burst set up by this method or {@link #setRepeatingBurst}, although any
|
||
|
* in-progress burst will be completed before the new repeat request will be
|
||
|
* used.</p>
|
||
|
*
|
||
|
* <p>This method does not support reprocess capture requests because each reprocess
|
||
|
* {@link CaptureRequest} must be created from the {@link TotalCaptureResult} that matches
|
||
|
* the input image to be reprocessed. This is either the {@link TotalCaptureResult} of capture
|
||
|
* that is sent for reprocessing, or one of the {@link TotalCaptureResult TotalCaptureResults}
|
||
|
* of a set of captures, when data from the whole set is combined by the application into a
|
||
|
* single reprocess input image. The request must be capturing images from the camera. If a
|
||
|
* reprocess capture request is submitted, this method will throw IllegalArgumentException.</p>
|
||
|
*
|
||
|
* <p>Submitting a request that targets Surfaces with an unsupported dynamic range combination
|
||
|
* will result in an {@link IllegalArgumentException}.</p>
|
||
|
*
|
||
|
* @param request the request to repeat indefinitely
|
||
|
* @param listener The callback object to notify every time the
|
||
|
* request finishes processing. If null, no metadata will be
|
||
|
* produced for this stream of requests, although image data will
|
||
|
* still be produced.
|
||
|
* @param handler the handler on which the listener should be invoked, or
|
||
|
* {@code null} to use the current thread's {@link android.os.Looper
|
||
|
* looper}.
|
||
|
*
|
||
|
* @return int A unique capture sequence ID used by
|
||
|
* {@link CaptureCallback#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; or the request
|
||
|
* is a reprocess capture request; or the capture targets a
|
||
|
* Surface in the middle of being {@link #prepare prepared}; or
|
||
|
* the handler is null, the listener is not null, and the
|
||
|
* calling thread has no looper; or no requests were passed in;
|
||
|
* or the request targets Surfaces with an unsupported dynamic
|
||
|
* range combination.
|
||
|
*
|
||
|
* @see #capture
|
||
|
* @see #captureBurst
|
||
|
* @see #setRepeatingBurst
|
||
|
* @see #stopRepeating
|
||
|
* @see #abortCaptures
|
||
|
* @see android.hardware.camera2.params.DynamicRangeProfiles#getProfileCaptureRequestConstraints
|
||
|
*/
|
||
|
public abstract int setRepeatingRequest(@NonNull CaptureRequest request,
|
||
|
@Nullable CaptureCallback listener, @Nullable Handler handler)
|
||
|
throws CameraAccessException;
|
||
|
|
||
|
/**
|
||
|
* Request endlessly repeating capture of images by this capture session.
|
||
|
*
|
||
|
* <p>The behavior of this method matches that of
|
||
|
* {@link #setRepeatingRequest(CaptureRequest, CaptureCallback, Handler)},
|
||
|
* except that it uses {@link java.util.concurrent.Executor} as an argument
|
||
|
* instead of {@link android.os.Handler}.</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 CaptureCallback#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; or the request
|
||
|
* is a reprocess capture request; or the capture targets a
|
||
|
* Surface in the middle of being {@link #prepare prepared}; or
|
||
|
* the executor is null; or the listener is null;
|
||
|
* or the request targets Surfaces with an unsupported dynamic
|
||
|
* range combination.
|
||
|
*
|
||
|
* @see #capture
|
||
|
* @see #captureBurst
|
||
|
* @see #setRepeatingBurst
|
||
|
* @see #stopRepeating
|
||
|
* @see #abortCaptures
|
||
|
* @see android.hardware.camera2.params.DynamicRangeProfiles#getProfileCaptureRequestConstraints
|
||
|
*/
|
||
|
public int setSingleRepeatingRequest(@NonNull CaptureRequest request,
|
||
|
@NonNull @CallbackExecutor Executor executor, @NonNull CaptureCallback listener)
|
||
|
throws CameraAccessException {
|
||
|
throw new UnsupportedOperationException("Subclasses must override this method");
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* <p>Request endlessly repeating capture of a sequence of images by this
|
||
|
* capture session.</p>
|
||
|
*
|
||
|
* <p>With this method, the camera device will continually capture images,
|
||
|
* cycling through the settings in the provided list of
|
||
|
* {@link CaptureRequest CaptureRequests}, at the maximum rate possible.</p>
|
||
|
*
|
||
|
* <p>If a request is submitted through {@link #capture} or
|
||
|
* {@link #captureBurst}, the current repetition of the request list will be
|
||
|
* completed before the higher-priority request is handled. This guarantees
|
||
|
* that the application always receives a complete repeat burst captured in
|
||
|
* minimal time, instead of bursts interleaved with higher-priority
|
||
|
* captures, or incomplete captures.</p>
|
||
|
*
|
||
|
* <p>Repeating burst requests are a simple way for an application to
|
||
|
* maintain a preview or other continuous stream of frames where each
|
||
|
* request is different in a predictable way, without having to continually
|
||
|
* submit requests through {@link #captureBurst}.</p>
|
||
|
*
|
||
|
* <p>To stop the repeating capture, call {@link #stopRepeating}. Any
|
||
|
* ongoing burst will still be completed, however. Calling
|
||
|
* {@link #abortCaptures} will also clear the request.</p>
|
||
|
*
|
||
|
* <p>Calling this method will replace a previously-set repeating request or
|
||
|
* burst set up by this method or {@link #setRepeatingRequest}, although any
|
||
|
* in-progress burst will be completed before the new repeat burst will be
|
||
|
* used.</p>
|
||
|
*
|
||
|
* <p>This method does not support reprocess capture requests because each reprocess
|
||
|
* {@link CaptureRequest} must be created from the {@link TotalCaptureResult} that matches
|
||
|
* the input image to be reprocessed. This is either the {@link TotalCaptureResult} of capture
|
||
|
* that is sent for reprocessing, or one of the {@link TotalCaptureResult TotalCaptureResults}
|
||
|
* of a set of captures, when data from the whole set is combined by the application into a
|
||
|
* single reprocess input image. The request must be capturing images from the camera. If a
|
||
|
* reprocess capture request is submitted, this method will throw IllegalArgumentException.</p>
|
||
|
*
|
||
|
* <p>Submitting a request that targets Surfaces with an unsupported dynamic range combination
|
||
|
* will result in an {@link IllegalArgumentException}.</p>
|
||
|
*
|
||
|
* @param requests the list of requests to cycle through indefinitely
|
||
|
* @param listener The callback object to notify each time one of the
|
||
|
* requests in the repeating bursts has finished processing. If null, no
|
||
|
* metadata will be produced for this stream of requests, although image
|
||
|
* data will still be produced.
|
||
|
* @param handler the handler on which the listener should be invoked, or
|
||
|
* {@code null} to use the current thread's {@link android.os.Looper
|
||
|
* looper}.
|
||
|
*
|
||
|
* @return int A unique capture sequence ID used by
|
||
|
* {@link CaptureCallback#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 requests reference no Surfaces or reference Surfaces
|
||
|
* not currently configured as outputs; or one of the requests
|
||
|
* is a reprocess capture request; or one of the captures
|
||
|
* targets a Surface in the middle of being
|
||
|
* {@link #prepare prepared}; or the handler is null, the
|
||
|
* listener is not null, and the calling thread has no looper;
|
||
|
* or no requests were passed in;
|
||
|
* or the request targets Surfaces with an unsupported dynamic
|
||
|
* range combination.
|
||
|
*
|
||
|
* @see #capture
|
||
|
* @see #captureBurst
|
||
|
* @see #setRepeatingRequest
|
||
|
* @see #stopRepeating
|
||
|
* @see #abortCaptures
|
||
|
* @see android.hardware.camera2.params.DynamicRangeProfiles#getProfileCaptureRequestConstraints
|
||
|
*/
|
||
|
public abstract int setRepeatingBurst(@NonNull List<CaptureRequest> requests,
|
||
|
@Nullable CaptureCallback listener, @Nullable Handler handler)
|
||
|
throws CameraAccessException;
|
||
|
|
||
|
/**
|
||
|
* <p>Request endlessly repeating capture of a sequence of images by this
|
||
|
* capture session.</p>
|
||
|
*
|
||
|
* <p>The behavior of this method matches that of
|
||
|
* {@link #setRepeatingBurst(List, CaptureCallback, Handler)},
|
||
|
* except that it uses {@link java.util.concurrent.Executor} as an argument
|
||
|
* instead of {@link android.os.Handler}.</p>
|
||
|
*
|
||
|
* @param requests the list of requests to cycle through indefinitely
|
||
|
* @param executor the executor which will be used for invoking the listener.
|
||
|
* @param listener The callback object to notify each time one of the
|
||
|
* requests in the repeating bursts has finished processing.
|
||
|
*
|
||
|
* @return int A unique capture sequence ID used by
|
||
|
* {@link CaptureCallback#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 requests reference no Surfaces or reference Surfaces
|
||
|
* not currently configured as outputs; or one of the requests
|
||
|
* is a reprocess capture request; or one of the captures
|
||
|
* targets a Surface in the middle of being
|
||
|
* {@link #prepare prepared}; or the executor is null; or the
|
||
|
* listener is null;
|
||
|
* or the request targets Surfaces with an unsupported dynamic
|
||
|
* range combination.
|
||
|
*
|
||
|
* @see #capture
|
||
|
* @see #captureBurst
|
||
|
* @see #setRepeatingRequest
|
||
|
* @see #stopRepeating
|
||
|
* @see #abortCaptures
|
||
|
* @see android.hardware.camera2.params.DynamicRangeProfiles#getProfileCaptureRequestConstraints
|
||
|
*/
|
||
|
public int setRepeatingBurstRequests(@NonNull List<CaptureRequest> requests,
|
||
|
@NonNull @CallbackExecutor Executor executor, @NonNull CaptureCallback listener)
|
||
|
throws CameraAccessException {
|
||
|
throw new UnsupportedOperationException("Subclasses must override this method");
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* <p>Cancel any ongoing repeating capture set by either
|
||
|
* {@link #setRepeatingRequest setRepeatingRequest} or
|
||
|
* {@link #setRepeatingBurst}. Has no effect on requests submitted through
|
||
|
* {@link #capture capture} or {@link #captureBurst captureBurst}.</p>
|
||
|
*
|
||
|
* <p>Any currently in-flight captures will still complete, as will any burst that is
|
||
|
* mid-capture. To ensure that the device has finished processing all of its capture requests
|
||
|
* and is in ready state, wait for the {@link StateCallback#onReady} callback after
|
||
|
* calling this method.</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
|
||
|
* @see #setRepeatingBurst
|
||
|
* @see StateCallback#onReady
|
||
|
*/
|
||
|
public abstract void stopRepeating() throws CameraAccessException;
|
||
|
|
||
|
/**
|
||
|
* Discard all captures currently pending and in-progress as fast as possible.
|
||
|
*
|
||
|
* <p>The camera device will discard all of its current work as fast as possible. Some in-flight
|
||
|
* captures may complete successfully and call {@link CaptureCallback#onCaptureCompleted}, while
|
||
|
* others will trigger their {@link CaptureCallback#onCaptureFailed} callbacks. If a repeating
|
||
|
* request or a repeating burst is set, it will be cleared.</p>
|
||
|
*
|
||
|
* <p>This method is the fastest way to switch the camera device to a new session with
|
||
|
* {@link CameraDevice#createCaptureSession} or
|
||
|
* {@link CameraDevice#createReprocessableCaptureSession}, at the cost of discarding in-progress
|
||
|
* work. It must be called before the new session is created. Once all pending requests are
|
||
|
* either completed or thrown away, the {@link StateCallback#onReady} callback will be called,
|
||
|
* if the session has not been closed. Otherwise, the {@link StateCallback#onClosed}
|
||
|
* callback will be fired when a new session is created by the camera device.</p>
|
||
|
*
|
||
|
* <p>Cancelling will introduce at least a brief pause in the stream of data from the camera
|
||
|
* device, since once the camera device is emptied, the first new request has to make it through
|
||
|
* the entire camera pipeline before new output buffers are produced.</p>
|
||
|
*
|
||
|
* <p>This means that using {@code abortCaptures()} to simply remove pending requests is not
|
||
|
* recommended; it's best used for quickly switching output configurations, or for cancelling
|
||
|
* long in-progress requests (such as a multi-second capture).</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
|
||
|
* @see #setRepeatingBurst
|
||
|
* @see CameraDevice#createCaptureSession
|
||
|
* @see CameraDevice#createReprocessableCaptureSession
|
||
|
*/
|
||
|
public abstract void abortCaptures() throws CameraAccessException;
|
||
|
|
||
|
/**
|
||
|
* Return if the application can submit reprocess capture requests with this camera capture
|
||
|
* session.
|
||
|
*
|
||
|
* @return {@code true} if the application can submit reprocess capture requests with this
|
||
|
* camera capture session. {@code false} otherwise.
|
||
|
*
|
||
|
* @see CameraDevice#createReprocessableCaptureSession
|
||
|
*/
|
||
|
public abstract boolean isReprocessable();
|
||
|
|
||
|
/**
|
||
|
* Get the input Surface associated with a reprocessable capture session.
|
||
|
*
|
||
|
* <p>Each reprocessable capture session has an input {@link Surface} where the reprocess
|
||
|
* capture requests get the input images from, rather than the camera device. The application
|
||
|
* can create a {@link android.media.ImageWriter ImageWriter} with this input {@link Surface}
|
||
|
* and use it to provide input images for reprocess capture requests. When the reprocessable
|
||
|
* capture session is closed, the input {@link Surface} is abandoned and becomes invalid.</p>
|
||
|
*
|
||
|
* @return The {@link Surface} where reprocessing capture requests get the input images from. If
|
||
|
* this is not a reprocess capture session, {@code null} will be returned.
|
||
|
*
|
||
|
* @see CameraDevice#createReprocessableCaptureSession
|
||
|
* @see android.media.ImageWriter
|
||
|
* @see android.media.ImageReader
|
||
|
*/
|
||
|
@Nullable
|
||
|
public abstract Surface getInputSurface();
|
||
|
|
||
|
/**
|
||
|
* Update {@link OutputConfiguration} after configuration finalization see
|
||
|
* {@link #finalizeOutputConfigurations}.
|
||
|
*
|
||
|
* <p>Any {@link OutputConfiguration} that has been modified via calls to
|
||
|
* {@link OutputConfiguration#addSurface} or {@link OutputConfiguration#removeSurface} must be
|
||
|
* updated. After the update call returns without throwing exceptions any newly added surfaces
|
||
|
* can be referenced in subsequent capture requests.</p>
|
||
|
*
|
||
|
* <p>Surfaces that get removed must not be part of any active repeating or single/burst
|
||
|
* request or have any pending results. Consider updating any repeating requests first via
|
||
|
* {@link #setRepeatingRequest} or {@link #setRepeatingBurst} and then wait for the last frame
|
||
|
* number when the sequence completes {@link CaptureCallback#onCaptureSequenceCompleted}
|
||
|
* before calling updateOutputConfiguration to remove a previously active Surface.</p>
|
||
|
*
|
||
|
* <p>Surfaces that get added must not be part of any other registered
|
||
|
* {@link OutputConfiguration}.</p>
|
||
|
*
|
||
|
* @param config Modified output configuration.
|
||
|
*
|
||
|
* @throws CameraAccessException if the camera device is no longer connected or has
|
||
|
* encountered a fatal error.
|
||
|
* @throws IllegalArgumentException if an attempt was made to add a {@link Surface} already
|
||
|
* in use by another buffer-producing API, such as MediaCodec or
|
||
|
* a different camera device or {@link OutputConfiguration}; or
|
||
|
* new surfaces are not compatible (see
|
||
|
* {@link OutputConfiguration#enableSurfaceSharing}); or a
|
||
|
* {@link Surface} that was removed from the modified
|
||
|
* {@link OutputConfiguration} still has pending requests.
|
||
|
* @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.
|
||
|
*/
|
||
|
public void updateOutputConfiguration(OutputConfiguration config)
|
||
|
throws CameraAccessException {
|
||
|
throw new UnsupportedOperationException("Subclasses must override this method");
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Switch the current capture session and a given set of registered camera surfaces
|
||
|
* to offline processing mode.
|
||
|
*
|
||
|
* <p>Devices support this method will report
|
||
|
* {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_OFFLINE_PROCESSING OFFLINE_PROCESSING}
|
||
|
* capability in {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES}. When this method
|
||
|
* is supported, applications can use it to improve the latency of closing camera or recreating
|
||
|
* capture session without losing the in progress capture request outputs.</p>
|
||
|
*
|
||
|
* <p>Offline processing mode and the corresponding {@link CameraOfflineSession} differ from
|
||
|
* a regular online camera capture session in several ways. Successful offline switches will
|
||
|
* close the currently active camera capture session. Camera clients are also allowed
|
||
|
* to call {@link CameraDevice#close} while offline processing of selected capture
|
||
|
* requests is still in progress. Such side effects free device close is only possible
|
||
|
* when the offline session moves to the ready state. Once this happens, closing the camera
|
||
|
* device will not affect the pending offline requests and they must complete as normal.</p>
|
||
|
*
|
||
|
* <p>Offline processing mode switches may need several hundred milliseconds to complete
|
||
|
* as the underlying camera implementation must abort all currently active repeating requests
|
||
|
* as well as all other pending requests not specified by the client. Additionally the switch
|
||
|
* will be blocked until all requests that continue processing within the offline session
|
||
|
* acquire their initial input frame from camera sensor. The call to {@link #switchToOffline}
|
||
|
* itself is not blocking and will only trigger the offline switch sequence. Clients will
|
||
|
* be notified via {@link CameraOfflineSessionCallback#onReady} once the entire sequence is
|
||
|
* complete.</p>
|
||
|
*
|
||
|
* <p>Please note that after a successful call to this method the currently active capture
|
||
|
* session will no longer be valid and clients will begin receiving capture
|
||
|
* callbacks with a corresponding {@link CameraOfflineSession} passed as a session
|
||
|
* argument.</p>
|
||
|
*
|
||
|
* @param offlineSurfaces Client-specified collection of input/output camera registered surfaces
|
||
|
* that need to be switched to offline mode along with their pending
|
||
|
* capture requests. Do note that not all camera registered
|
||
|
* surfaces can be switched to offline mode. Offline processing
|
||
|
* support for individual surfaces can be queried using
|
||
|
* {@link #supportsOfflineProcessing}. Additionally offline mode
|
||
|
* switches are not available for shared surfaces
|
||
|
* {@link OutputConfiguration#enableSurfaceSharing} and surfaces
|
||
|
* as part of a surface group.
|
||
|
*
|
||
|
* @param executor The executor which will be used for invoking the offline callback listener.
|
||
|
*
|
||
|
* @param listener The callback object to notify for offline session events.
|
||
|
*
|
||
|
* @return camera offline session which in case of successful offline switch will move in ready
|
||
|
* state after clients receive {@link CameraOfflineSessionCallback#onReady}. In case the
|
||
|
* offline switch was not successful clients will receive respective
|
||
|
* {@link CameraOfflineSessionCallback#onSwitchFailed} notification.
|
||
|
*
|
||
|
* @throws IllegalArgumentException if an attempt was made to pass a {@link Surface} that was
|
||
|
* not registered with this capture session or a shared
|
||
|
* surface {@link OutputConfiguration#enableSurfaceSharing} or
|
||
|
* surface as part of a surface group. The current capture
|
||
|
* session will remain valid and active in case of this
|
||
|
* exception.
|
||
|
*
|
||
|
* @throws CameraAccessException if the camera device is no longer connected or has
|
||
|
* encountered a fatal error.
|
||
|
*
|
||
|
* @see CameraOfflineSession
|
||
|
* @see CameraOfflineSessionCallback
|
||
|
* @see #supportsOfflineProcessing
|
||
|
* @see CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_OFFLINE_PROCESSING
|
||
|
*/
|
||
|
@Nullable
|
||
|
public CameraOfflineSession switchToOffline(@NonNull Collection<Surface> offlineSurfaces,
|
||
|
@NonNull @CallbackExecutor Executor executor,
|
||
|
@NonNull CameraOfflineSessionCallback listener)
|
||
|
throws CameraAccessException {
|
||
|
throw new UnsupportedOperationException("Subclasses must override this method");
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* <p>Query whether a given Surface is able to support offline mode. </p>
|
||
|
*
|
||
|
* <p>Surfaces that support offline mode can be passed as arguments to {@link #switchToOffline}.
|
||
|
* </p>
|
||
|
*
|
||
|
* @param surface An input/output surface that was used to create this session or the result of
|
||
|
* {@link #getInputSurface}.
|
||
|
*
|
||
|
* @return {@code true} if the surface can support offline mode and can be passed as argument to
|
||
|
* {@link #switchToOffline}. {@code false} otherwise.
|
||
|
*
|
||
|
* @throws IllegalArgumentException if an attempt was made to pass a {@link Surface} that was
|
||
|
* not registered with this capture session.
|
||
|
* @throws UnsupportedOperationException if an attempt was made to call this method using
|
||
|
* unsupported camera capture session like
|
||
|
* {@link CameraConstrainedHighSpeedCaptureSession} or
|
||
|
* {@link CameraOfflineSession}.
|
||
|
*
|
||
|
* @see #switchToOffline
|
||
|
*/
|
||
|
public boolean supportsOfflineProcessing(@NonNull Surface surface) {
|
||
|
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 for common usage scenarios like creating a new session or closing the camera
|
||
|
* device, it is faster to call respective APIs directly (see below for more details) without
|
||
|
* calling into this method. This API is only useful when application wants to unconfigure the
|
||
|
* camera but keep the device open for later use.</p>
|
||
|
*
|
||
|
* <p>Creating a new capture session with {@link CameraDevice#createCaptureSession}
|
||
|
* will close any existing capture session automatically, and call the older session listener's
|
||
|
* {@link StateCallback#onClosed} callback. Using {@link CameraDevice#createCaptureSession}
|
||
|
* 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>Closing the device with {@link CameraDevice#close} directly without calling this API is
|
||
|
* also recommended for quickly closing the camera.</p>
|
||
|
*
|
||
|
* <p>Once a session is closed, all methods on it will throw an IllegalStateException, and any
|
||
|
* repeating requests or bursts are stopped (as if {@link #stopRepeating()} was called).
|
||
|
* However, any in-progress capture requests submitted to the session will be completed as
|
||
|
* normal; once all captures have completed and the session has been torn down,
|
||
|
* {@link StateCallback#onClosed} will be called.</p>
|
||
|
*
|
||
|
* <p>Closing a session is idempotent; closing more than once has no effect.</p>
|
||
|
*/
|
||
|
@Override
|
||
|
public abstract void close();
|
||
|
|
||
|
/**
|
||
|
* A callback object for receiving updates about the state of a camera capture 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 there are capture requests already queued with the session, they will start
|
||
|
* processing once this callback is invoked, and the session will call {@link #onActive}
|
||
|
* right after this callback is invoked.</p>
|
||
|
*
|
||
|
* <p>If no capture requests have been submitted, then the session will invoke
|
||
|
* {@link #onReady} right after this callback.</p>
|
||
|
*
|
||
|
* <p>If the camera device configuration fails, then {@link #onConfigureFailed} will
|
||
|
* be invoked instead of this callback.</p>
|
||
|
*
|
||
|
* @param session the successfully configured session instance
|
||
|
*/
|
||
|
public abstract void onConfigured(@NonNull CameraCaptureSession 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,
|
||
|
* or too many outputs are requested at once.</p>
|
||
|
*
|
||
|
* <p>The session is considered to be closed, and all methods called on it after this
|
||
|
* callback is invoked will throw an IllegalStateException. Any capture requests submitted
|
||
|
* to the session prior to this callback will be discarded and will not produce any
|
||
|
* callbacks on their listeners.</p>
|
||
|
*
|
||
|
* @param session the session instance that failed during configuration
|
||
|
*/
|
||
|
public abstract void onConfigureFailed(@NonNull CameraCaptureSession session);
|
||
|
|
||
|
/**
|
||
|
* This method is called every time the session has no more capture requests to process.
|
||
|
*
|
||
|
* <p>During the creation of a new session, this callback is invoked right after
|
||
|
* {@link #onConfigured} if no capture requests were submitted to the session prior to it
|
||
|
* completing configuration.</p>
|
||
|
*
|
||
|
* <p>Otherwise, this callback will be invoked any time the session finishes processing
|
||
|
* all of its active capture requests, and no repeating request or burst is set up.</p>
|
||
|
*
|
||
|
* @param session the session returned by {@link #onConfigured}
|
||
|
*
|
||
|
*/
|
||
|
public void onReady(@NonNull CameraCaptureSession session) {
|
||
|
// default empty implementation
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This method is called when the session starts actively processing capture requests.
|
||
|
*
|
||
|
* <p>If capture requests are submitted prior to {@link #onConfigured} being called,
|
||
|
* then the session will start processing those requests immediately after the callback,
|
||
|
* and this method will be immediately called after {@link #onConfigured}.
|
||
|
*
|
||
|
* <p>If the session runs out of capture requests to process and calls {@link #onReady},
|
||
|
* then this callback will be invoked again once new requests are submitted for capture.</p>
|
||
|
*
|
||
|
* @param session the session returned by {@link #onConfigured}
|
||
|
*/
|
||
|
public void onActive(@NonNull CameraCaptureSession session) {
|
||
|
// default empty implementation
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This method is called when camera device's input capture queue becomes empty,
|
||
|
* and is ready to accept the next request.
|
||
|
*
|
||
|
* <p>Pending capture requests exist in one of two queues: the in-flight queue where requests
|
||
|
* are already in different stages of processing pipeline, and an input queue where requests
|
||
|
* wait to enter the in-flight queue. The input queue is needed because more requests may be
|
||
|
* submitted than the current camera device pipeline depth.</p>
|
||
|
*
|
||
|
* <p>This callback is fired when the input queue becomes empty, and the camera device may
|
||
|
* have to fall back to the repeating request if set, or completely skip the next frame from
|
||
|
* the sensor. This can cause glitches to camera preview output, for example. This callback
|
||
|
* will only fire after requests queued by capture() or captureBurst(), not after a
|
||
|
* repeating request or burst enters the in-flight queue. For example, in the common case
|
||
|
* of a repeating request and a single-shot JPEG capture, this callback only fires when the
|
||
|
* JPEG request has entered the in-flight queue for capture.</p>
|
||
|
*
|
||
|
* <p>By only sending a new {@link #capture} or {@link #captureBurst} when the input
|
||
|
* queue is empty, pipeline latency can be minimized.</p>
|
||
|
*
|
||
|
* <p>This callback is not fired when the session is first created. It is different from
|
||
|
* {@link #onReady}, which is fired when all requests in both queues have been processed.</p>
|
||
|
*
|
||
|
* @param session
|
||
|
* The session returned by {@link #onConfigured}
|
||
|
*/
|
||
|
public void onCaptureQueueEmpty(@NonNull CameraCaptureSession session) {
|
||
|
// default empty implementation
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 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 or bursts 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 returned by {@link #onConfigured}
|
||
|
*/
|
||
|
public void onClosed(@NonNull CameraCaptureSession session) {
|
||
|
// default empty implementation
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This method is called when the buffer pre-allocation for an output Surface is complete.
|
||
|
*
|
||
|
* <p>Buffer pre-allocation for an output Surface is started by the {@link #prepare} call.
|
||
|
* While allocation is underway, the Surface must not be used as a capture target.
|
||
|
* Once this callback fires, the output Surface provided can again be used as a target for
|
||
|
* a capture request.</p>
|
||
|
*
|
||
|
* <p>In case of a error during pre-allocation (such as running out of suitable memory),
|
||
|
* this callback is still invoked after the error is encountered, though some buffers may
|
||
|
* not have been successfully pre-allocated.</p>
|
||
|
*
|
||
|
* @param session the session returned by {@link #onConfigured}
|
||
|
* @param surface the Surface that was used with the {@link #prepare} call.
|
||
|
*/
|
||
|
public void onSurfacePrepared(@NonNull CameraCaptureSession session,
|
||
|
@NonNull Surface surface) {
|
||
|
// default empty implementation
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* <p>A callback object for tracking the progress of a {@link CaptureRequest} submitted to the
|
||
|
* camera device.</p>
|
||
|
*
|
||
|
* <p>This callback is invoked when a request triggers a capture to start,
|
||
|
* and when the capture is complete. In case on an error capturing an image,
|
||
|
* the error method is triggered instead of the completion method.</p>
|
||
|
*
|
||
|
* @see #capture
|
||
|
* @see #captureBurst
|
||
|
* @see #setRepeatingRequest
|
||
|
* @see #setRepeatingBurst
|
||
|
*/
|
||
|
public static abstract class CaptureCallback {
|
||
|
|
||
|
/**
|
||
|
* This constant is used to indicate that no images were captured for
|
||
|
* the request.
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
public static final int NO_FRAMES_CAPTURED = -1;
|
||
|
|
||
|
/**
|
||
|
* This method is called when the camera device has started capturing
|
||
|
* the output image for the request, at the beginning of image exposure, or
|
||
|
* when the camera device has started processing an input image for a reprocess
|
||
|
* request.
|
||
|
*
|
||
|
* <p>For a regular capture request, 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. For a reprocess
|
||
|
* request, this timestamp will be the input image's start of exposure
|
||
|
* which matches {@link CaptureResult#SENSOR_TIMESTAMP the result timestamp field}
|
||
|
* of the {@link TotalCaptureResult} that was used to
|
||
|
* {@link CameraDevice#createReprocessCaptureRequest create the reprocess request}.
|
||
|
* This timestamp matches the timestamps that will be
|
||
|
* included in {@link CaptureResult#SENSOR_TIMESTAMP the result timestamp field},
|
||
|
* and in the buffers sent to each output Surface. These buffer
|
||
|
* timestamps are accessible through, for example,
|
||
|
* {@link android.media.Image#getTimestamp() Image.getTimestamp()} or
|
||
|
* {@link android.graphics.SurfaceTexture#getTimestamp()}.
|
||
|
* The frame number included is equal to the frame number that will be included in
|
||
|
* {@link CaptureResult#getFrameNumber}.</p>
|
||
|
*
|
||
|
* <p>For the simplest way to play a shutter sound camera shutter or a
|
||
|
* video recording start/stop sound, see the
|
||
|
* {@link android.media.MediaActionSound} class.</p>
|
||
|
*
|
||
|
* <p>The default implementation of this method does nothing.</p>
|
||
|
*
|
||
|
* @param session the session returned by {@link CameraDevice#createCaptureSession}
|
||
|
* @param request the request for the capture that just begun
|
||
|
* @param timestamp the timestamp at start of capture for a regular request, or
|
||
|
* the timestamp at the input image's start of capture for a
|
||
|
* reprocess request, in nanoseconds.
|
||
|
* @param frameNumber the frame number for this capture
|
||
|
*
|
||
|
* @see android.media.MediaActionSound
|
||
|
*/
|
||
|
public void onCaptureStarted(@NonNull CameraCaptureSession session,
|
||
|
@NonNull CaptureRequest request, long timestamp, long frameNumber) {
|
||
|
// default empty implementation
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This method is called when the camera device has started reading out the output
|
||
|
* image for the request, at the beginning of the sensor image readout.
|
||
|
*
|
||
|
* <p>For a capture request, this callback is invoked right after
|
||
|
* {@link #onCaptureStarted}. Unlike {@link #onCaptureStarted}, instead of passing
|
||
|
* a timestamp of start of exposure, this callback passes a timestamp of start of
|
||
|
* camera data readout. This is useful because for a camera running at fixed frame
|
||
|
* rate, the start of readout is at fixed interval, which is not necessarily true for
|
||
|
* the start of exposure, particularly when autoexposure is changing exposure duration
|
||
|
* between frames.</p>
|
||
|
*
|
||
|
* <p>The timestamps match the timestamps of the output surfaces with readout timestamp
|
||
|
* enabled (via {@link OutputConfiguration#setReadoutTimestampEnabled}) if:</p>
|
||
|
* <ul>
|
||
|
* <li> Timestamp base is {@link OutputConfiguration#TIMESTAMP_BASE_DEFAULT} and the
|
||
|
* output
|
||
|
* <ul>
|
||
|
* <li> is not a SurfaceView surface, and </li>
|
||
|
* <li> is not a MediaRecoder, MediaCodec, or ImageReader surface with {@link
|
||
|
* android.hardware.HardwareBuffer#USAGE_VIDEO_ENCODE} usage flag or the device's {@link
|
||
|
* CameraCharacteristics#SENSOR_INFO_TIMESTAMP_SOURCE} is {@code UNKNOWN}</li>
|
||
|
* </ul>
|
||
|
* </li>
|
||
|
* <li> Timestamp base is {@link OutputConfiguration#TIMESTAMP_BASE_SENSOR},</li>
|
||
|
* <li> Timestamp base is {@link OutputConfiguration#TIMESTAMP_BASE_MONOTONIC} and the
|
||
|
* device's {@link CameraCharacteristics#SENSOR_INFO_TIMESTAMP_SOURCE} is {@code
|
||
|
* UNKNOWN},</li>
|
||
|
* <li> Timestamp base is {@link OutputConfiguration#TIMESTAMP_BASE_REALTIME} and the
|
||
|
* device's {@link CameraCharacteristics#SENSOR_INFO_TIMESTAMP_SOURCE} is {@code REALTIME}
|
||
|
* </li>
|
||
|
* </ul>
|
||
|
* <p>Otherwise, the timestamps won't match the timestamp of the output surfaces. See
|
||
|
* the possible parameters for {@link OutputConfiguration#setTimestampBase} for details.</p>
|
||
|
*
|
||
|
* <p>This callback will be called only if {@link
|
||
|
* CameraCharacteristics#SENSOR_READOUT_TIMESTAMP} is
|
||
|
* {@link CameraMetadata#SENSOR_READOUT_TIMESTAMP_HARDWARE}, and it's called
|
||
|
* right after {@link #onCaptureStarted}.</p>
|
||
|
*
|
||
|
* @param session the session returned by {@link CameraDevice#createCaptureSession}
|
||
|
* @param request the request for the readout that just began
|
||
|
* @param timestamp the timestamp at start of readout for a regular request, or
|
||
|
* the timestamp at the input image's start of readout for a
|
||
|
* reprocess request, in nanoseconds.
|
||
|
* @param frameNumber the frame number for this capture
|
||
|
*/
|
||
|
public void onReadoutStarted(@NonNull CameraCaptureSession session,
|
||
|
@NonNull CaptureRequest request, long timestamp, long frameNumber) {
|
||
|
// default empty implementation
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This method is called when some results from an image capture are
|
||
|
* available.
|
||
|
*
|
||
|
* <p>The result provided here will contain some subset of the fields of
|
||
|
* a full result. Multiple onCapturePartial calls may happen per
|
||
|
* capture; a given result field will only be present in one partial
|
||
|
* capture at most. The final onCaptureCompleted call will always
|
||
|
* contain all the fields, whether onCapturePartial was called or
|
||
|
* not.</p>
|
||
|
*
|
||
|
* <p>The default implementation of this method does nothing.</p>
|
||
|
*
|
||
|
* @param session the session returned by {@link CameraDevice#createCaptureSession}
|
||
|
* @param request The request that was given to the CameraDevice
|
||
|
* @param result The partial output metadata from the capture, which
|
||
|
* includes a subset of the CaptureResult fields.
|
||
|
*
|
||
|
* @see #capture
|
||
|
* @see #captureBurst
|
||
|
* @see #setRepeatingRequest
|
||
|
* @see #setRepeatingBurst
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
public void onCapturePartial(CameraCaptureSession session,
|
||
|
CaptureRequest request, CaptureResult result) {
|
||
|
// default empty implementation
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This method is called when an image capture makes partial forward progress; some
|
||
|
* (but not all) results from an image capture are available.
|
||
|
*
|
||
|
* <p>The result provided here will contain some subset of the fields of
|
||
|
* a full result. Multiple {@link #onCaptureProgressed} calls may happen per
|
||
|
* capture; a given result field will only be present in one partial
|
||
|
* capture at most. The final {@link #onCaptureCompleted} call will always
|
||
|
* contain all the fields (in particular, the union of all the fields of all
|
||
|
* the partial results composing the total result).</p>
|
||
|
*
|
||
|
* <p>For each request, some result data might be available earlier than others. The typical
|
||
|
* delay between each partial result (per request) is a single frame interval.
|
||
|
* For performance-oriented use-cases, applications should query the metadata they need
|
||
|
* to make forward progress from the partial results and avoid waiting for the completed
|
||
|
* result.</p>
|
||
|
*
|
||
|
* <p>For a particular request, {@link #onCaptureProgressed} may happen before or after
|
||
|
* {@link #onCaptureStarted}.</p>
|
||
|
*
|
||
|
* <p>Each request will generate at least {@code 1} partial results, and at most
|
||
|
* {@link CameraCharacteristics#REQUEST_PARTIAL_RESULT_COUNT} partial results.</p>
|
||
|
*
|
||
|
* <p>Depending on the request settings, the number of partial results per request
|
||
|
* will vary, although typically the partial count could be the same as long as the
|
||
|
* camera device subsystems enabled stay the same.</p>
|
||
|
*
|
||
|
* <p>The default implementation of this method does nothing.</p>
|
||
|
*
|
||
|
* @param session the session returned by {@link CameraDevice#createCaptureSession}
|
||
|
* @param request The request that was given to the CameraDevice
|
||
|
* @param partialResult The partial output metadata from the capture, which
|
||
|
* includes a subset of the {@link TotalCaptureResult} fields.
|
||
|
*
|
||
|
* @see #capture
|
||
|
* @see #captureBurst
|
||
|
* @see #setRepeatingRequest
|
||
|
* @see #setRepeatingBurst
|
||
|
*/
|
||
|
public void onCaptureProgressed(@NonNull CameraCaptureSession session,
|
||
|
@NonNull CaptureRequest request, @NonNull CaptureResult partialResult) {
|
||
|
// default empty implementation
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This method is called when an image capture has fully completed and all the
|
||
|
* result metadata is available.
|
||
|
*
|
||
|
* <p>This callback will always fire after the last {@link #onCaptureProgressed};
|
||
|
* in other words, no more partial results will be delivered once the completed result
|
||
|
* is available.</p>
|
||
|
*
|
||
|
* <p>For performance-intensive use-cases where latency is a factor, consider
|
||
|
* using {@link #onCaptureProgressed} instead.</p>
|
||
|
*
|
||
|
* <p>The default implementation of this method does nothing.</p>
|
||
|
*
|
||
|
* @param session the session returned by {@link CameraDevice#createCaptureSession}
|
||
|
* @param request The request that was given to the CameraDevice
|
||
|
* @param result The total output metadata from the capture, including the
|
||
|
* final capture parameters and the state of the camera system during
|
||
|
* capture.
|
||
|
*
|
||
|
* @see #capture
|
||
|
* @see #captureBurst
|
||
|
* @see #setRepeatingRequest
|
||
|
* @see #setRepeatingBurst
|
||
|
*/
|
||
|
public void onCaptureCompleted(@NonNull CameraCaptureSession session,
|
||
|
@NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
|
||
|
// default empty implementation
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This method is called instead of {@link #onCaptureCompleted} when the
|
||
|
* camera device failed to produce a {@link CaptureResult} for the
|
||
|
* request.
|
||
|
*
|
||
|
* <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>If a logical multi-camera fails to generate capture result for one of
|
||
|
* its physical cameras, this method will be called with a {@link CaptureFailure}
|
||
|
* for that physical camera. In such cases, as long as the logical camera capture
|
||
|
* result is valid, {@link #onCaptureCompleted} will still be called.</p>
|
||
|
*
|
||
|
* <p>The default implementation of this method does nothing.</p>
|
||
|
*
|
||
|
* @param session
|
||
|
* The session returned by {@link CameraDevice#createCaptureSession}
|
||
|
* @param request
|
||
|
* The request that was given to the CameraDevice
|
||
|
* @param failure
|
||
|
* The output failure from the capture, including the failure reason
|
||
|
* and the frame number.
|
||
|
*
|
||
|
* @see #capture
|
||
|
* @see #captureBurst
|
||
|
* @see #setRepeatingRequest
|
||
|
* @see #setRepeatingBurst
|
||
|
*/
|
||
|
public void onCaptureFailed(@NonNull CameraCaptureSession session,
|
||
|
@NonNull CaptureRequest request, @NonNull CaptureFailure failure) {
|
||
|
// default empty implementation
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This method is called independently of the others in CaptureCallback,
|
||
|
* when a capture sequence finishes and all {@link CaptureResult}
|
||
|
* or {@link CaptureFailure} for it have been returned via this listener.
|
||
|
*
|
||
|
* <p>In total, there will be at least one result/failure returned by this listener
|
||
|
* before this callback is invoked. If the capture sequence is aborted before any
|
||
|
* requests have been processed, {@link #onCaptureSequenceAborted} is invoked instead.</p>
|
||
|
*
|
||
|
* <p>The default implementation does nothing.</p>
|
||
|
*
|
||
|
* @param session
|
||
|
* The session returned by {@link CameraDevice#createCaptureSession}
|
||
|
* @param sequenceId
|
||
|
* A sequence ID returned by the {@link #capture} family of functions.
|
||
|
* @param frameNumber
|
||
|
* The last frame number (returned by {@link CaptureResult#getFrameNumber}
|
||
|
* or {@link CaptureFailure#getFrameNumber}) in the capture sequence.
|
||
|
*
|
||
|
* @see CaptureResult#getFrameNumber()
|
||
|
* @see CaptureFailure#getFrameNumber()
|
||
|
* @see CaptureResult#getSequenceId()
|
||
|
* @see CaptureFailure#getSequenceId()
|
||
|
* @see #onCaptureSequenceAborted
|
||
|
*/
|
||
|
public void onCaptureSequenceCompleted(@NonNull CameraCaptureSession session,
|
||
|
int sequenceId, long frameNumber) {
|
||
|
// default empty implementation
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This method is called independently of the others in CaptureCallback,
|
||
|
* when a capture sequence aborts before any {@link CaptureResult}
|
||
|
* or {@link CaptureFailure} for it have been returned via this listener.
|
||
|
*
|
||
|
* <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 CameraCaptureSession#stopRepeating} or
|
||
|
* {@link CameraCaptureSession#abortCaptures}. When such an event happens,
|
||
|
* {@link #onCaptureSequenceCompleted} will not be called.</p>
|
||
|
*
|
||
|
* <p>The default implementation does nothing.</p>
|
||
|
*
|
||
|
* @param session
|
||
|
* The session returned by {@link CameraDevice#createCaptureSession}
|
||
|
* @param sequenceId
|
||
|
* A sequence ID returned by the {@link #capture} family of functions.
|
||
|
*
|
||
|
* @see CaptureResult#getFrameNumber()
|
||
|
* @see CaptureFailure#getFrameNumber()
|
||
|
* @see CaptureResult#getSequenceId()
|
||
|
* @see CaptureFailure#getSequenceId()
|
||
|
* @see #onCaptureSequenceCompleted
|
||
|
*/
|
||
|
public void onCaptureSequenceAborted(@NonNull CameraCaptureSession session,
|
||
|
int sequenceId) {
|
||
|
// default empty implementation
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* <p>This method is called if a single buffer for a capture could not be sent to its
|
||
|
* destination surface.</p>
|
||
|
*
|
||
|
* <p>If the whole capture failed, then {@link #onCaptureFailed} will be called instead. If
|
||
|
* some but not all buffers were captured but the result metadata will not be available,
|
||
|
* then onCaptureFailed will be invoked with {@link CaptureFailure#wasImageCaptured}
|
||
|
* returning true, along with one or more calls to {@link #onCaptureBufferLost} for the
|
||
|
* failed outputs.</p>
|
||
|
*
|
||
|
* @param session
|
||
|
* The session returned by {@link CameraDevice#createCaptureSession}
|
||
|
* @param request
|
||
|
* The request that was given to the CameraDevice
|
||
|
* @param target
|
||
|
* The target Surface that the buffer will not be produced for
|
||
|
* @param frameNumber
|
||
|
* The frame number for the request
|
||
|
*/
|
||
|
public void onCaptureBufferLost(@NonNull CameraCaptureSession session,
|
||
|
@NonNull CaptureRequest request, @NonNull Surface target, long frameNumber) {
|
||
|
// default empty implementation
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|