1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419
|
/*
* 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
}
/**
* This method is called when an image capture has fully completed and all the
* result metadata is available.
*
* <p>This callback will only be called in case
* {@link CameraExtensionCharacteristics#getAvailableCaptureResultKeys} returns a valid
* non-empty list.</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
* @param result The total output metadata from the capture, which only includes the
* capture result keys advertised as supported in
* {@link CameraExtensionCharacteristics#getAvailableCaptureResultKeys}.
*
* @see #capture
* @see #setRepeatingRequest
* @see CameraExtensionCharacteristics#getAvailableCaptureResultKeys
*/
public void onCaptureResultAvailable(@NonNull CameraExtensionSession session,
@NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
// 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 controls advertised in
* {@link CameraExtensionCharacteristics#getAvailableCaptureRequestKeys}.
* 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>Starting with Android {@link android.os.Build.VERSION_CODES#TIRAMISU} single capture
* requests will also support the preview {@link android.graphics.ImageFormat#PRIVATE} target
* surface. These can typically be used for enabling AF/AE triggers. Do note, that single
* capture requests referencing both output surfaces remain unsupported.</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 except for controls advertised in
* {@link CameraExtensionCharacteristics#getAvailableCaptureRequestKeys}.
* 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
* 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");
}
}
|