1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 18 package android.hardware.camera2.params; 19 20 import android.annotation.CallbackExecutor; 21 import android.annotation.FlaggedApi; 22 import android.annotation.IntDef; 23 import android.annotation.NonNull; 24 import android.annotation.Nullable; 25 import android.annotation.SuppressLint; 26 import android.annotation.SystemApi; 27 import android.graphics.ColorSpace; 28 import android.hardware.camera2.CameraCaptureSession; 29 import android.hardware.camera2.CameraCharacteristics; 30 import android.hardware.camera2.CameraDevice; 31 import android.hardware.camera2.CameraDevice.CameraDeviceSetup; 32 import android.hardware.camera2.CaptureRequest; 33 import android.hardware.camera2.impl.CameraMetadataNative; 34 import android.hardware.camera2.utils.HashCodeHelpers; 35 import android.media.ImageReader; 36 import android.os.Parcel; 37 import android.os.Parcelable; 38 39 import com.android.internal.camera.flags.Flags; 40 41 import java.lang.annotation.Retention; 42 import java.lang.annotation.RetentionPolicy; 43 import java.util.ArrayList; 44 import java.util.Collections; 45 import java.util.List; 46 import java.util.Objects; 47 import java.util.concurrent.Executor; 48 49 /** 50 * A helper class that aggregates all supported arguments for capture session initialization. 51 */ 52 public final class SessionConfiguration implements Parcelable { 53 private static final String TAG = "SessionConfiguration"; 54 55 /** 56 * A regular session type containing instances of {@link OutputConfiguration} running 57 * at regular non high speed FPS ranges and optionally {@link InputConfiguration} for 58 * reprocessable sessions. 59 * 60 * @see CameraDevice#createCaptureSession(SessionConfiguration) 61 * @see CameraDevice#createReprocessableCaptureSession 62 */ 63 public static final int SESSION_REGULAR = CameraDevice.SESSION_OPERATION_MODE_NORMAL; 64 65 /** 66 * A high speed session type that can only contain instances of {@link OutputConfiguration}. 67 * The outputs can run using high speed FPS ranges. Calls to {@link #setInputConfiguration} 68 * are not supported. 69 * <p> 70 * When using this type, the CameraCaptureSession returned by 71 * {@link android.hardware.camera2.CameraCaptureSession.StateCallback} can be cast to a 72 * {@link android.hardware.camera2.CameraConstrainedHighSpeedCaptureSession} to access the extra 73 * methods for constrained high speed recording. 74 * </p> 75 * 76 * @see CameraDevice#createConstrainedHighSpeedCaptureSession 77 */ 78 public static final int SESSION_HIGH_SPEED = 79 CameraDevice.SESSION_OPERATION_MODE_CONSTRAINED_HIGH_SPEED; 80 81 /** 82 * A shared session type containing instances of {@link OutputConfiguration} from a set of 83 * predefined stream configurations. A shared session can be shared among multiple clients. 84 * Shared session does not have any {@link InputConfiguration} as it does not support 85 * reprocessable sessions. 86 * 87 * @see CameraDevice#createCaptureSession(SessionConfiguration) 88 * @hide 89 */ 90 @FlaggedApi(Flags.FLAG_CAMERA_MULTI_CLIENT) 91 @SystemApi 92 public static final int SESSION_SHARED = CameraDevice.SESSION_OPERATION_MODE_SHARED; 93 94 /** 95 * First vendor-specific session mode 96 * @hide 97 */ 98 public static final int SESSION_VENDOR_START = 99 CameraDevice.SESSION_OPERATION_MODE_VENDOR_START; 100 101 /** @hide */ 102 @Retention(RetentionPolicy.SOURCE) 103 @IntDef(prefix = {"SESSION_"}, value = 104 {SESSION_REGULAR, 105 SESSION_HIGH_SPEED }) 106 public @interface SessionMode {}; 107 108 // Camera capture session related parameters. 109 private final @NonNull List<OutputConfiguration> mOutputConfigurations; 110 private CameraCaptureSession.StateCallback mStateCallback = null; 111 private int mSessionType; 112 private Executor mExecutor = null; 113 private InputConfiguration mInputConfig = null; 114 private CaptureRequest mSessionParameters = null; 115 private int mColorSpace; 116 117 /** 118 * Create a new {@link SessionConfiguration}. 119 * 120 * @param sessionType The session type. 121 * @param outputs A list of output configurations for the capture session. 122 * @param executor The executor which should be used to invoke the callback. In general it is 123 * recommended that camera operations are not done on the main (UI) thread. 124 * @param cb A state callback interface implementation. 125 * 126 * @see #SESSION_REGULAR 127 * @see #SESSION_HIGH_SPEED 128 * @see CameraDevice#createCaptureSession(SessionConfiguration) 129 */ SessionConfiguration(@essionMode int sessionType, @NonNull List<OutputConfiguration> outputs, @NonNull @CallbackExecutor Executor executor, @NonNull CameraCaptureSession.StateCallback cb)130 public SessionConfiguration(@SessionMode int sessionType, 131 @NonNull List<OutputConfiguration> outputs, 132 @NonNull @CallbackExecutor Executor executor, 133 @NonNull CameraCaptureSession.StateCallback cb) { 134 mSessionType = sessionType; 135 mOutputConfigurations = Collections.unmodifiableList(new ArrayList<>(outputs)); 136 mStateCallback = cb; 137 mExecutor = executor; 138 } 139 140 /** 141 * Create a new {@link SessionConfiguration} with sessionType and output configurations. 142 * 143 * <p>The SessionConfiguration objects created by this constructor can be used by 144 * {@link CameraDeviceSetup#isSessionConfigurationSupported} and {@link 145 * CameraDeviceSetup#getSessionCharacteristics} to query a camera device's feature 146 * combination support and session specific characteristics. For the SessionConfiguration 147 * object to be used to create a capture session, {@link #setStateCallback} must be called to 148 * specify the state callback function, and any incomplete OutputConfigurations must be 149 * completed via {@link OutputConfiguration#addSurface} or 150 * {@link OutputConfiguration#setSurfacesForMultiResolutionOutput} as appropriate.</p> 151 * 152 * @param sessionType The session type. 153 * @param outputs A list of output configurations for the capture session. 154 * 155 * @see #SESSION_REGULAR 156 * @see #SESSION_HIGH_SPEED 157 * @see CameraDevice#createCaptureSession(SessionConfiguration) 158 * @see CameraDeviceSetup#isSessionConfigurationSupported 159 * @see CameraDeviceSetup#getSessionCharacteristics 160 */ 161 @FlaggedApi(Flags.FLAG_CAMERA_DEVICE_SETUP) SessionConfiguration(@essionMode int sessionType, @NonNull List<OutputConfiguration> outputs)162 public SessionConfiguration(@SessionMode int sessionType, 163 @NonNull List<OutputConfiguration> outputs) { 164 mSessionType = sessionType; 165 mOutputConfigurations = Collections.unmodifiableList(new ArrayList<>(outputs)); 166 } 167 168 /** 169 * Create a SessionConfiguration from Parcel. 170 * No support for parcelable 'mStateCallback' and 'mExecutor' yet. 171 */ SessionConfiguration(@onNull Parcel source)172 private SessionConfiguration(@NonNull Parcel source) { 173 int sessionType = source.readInt(); 174 int inputWidth = source.readInt(); 175 int inputHeight = source.readInt(); 176 int inputFormat = source.readInt(); 177 boolean isInputMultiResolution = source.readBoolean(); 178 ArrayList<OutputConfiguration> outConfigs = new ArrayList<OutputConfiguration>(); 179 source.readTypedList(outConfigs, OutputConfiguration.CREATOR); 180 // Ignore the values for hasSessionParameters and settings because we cannot reconstruct 181 // the CaptureRequest object. 182 boolean hasSessionParameters = source.readBoolean(); 183 if (hasSessionParameters) { 184 CameraMetadataNative settings = new CameraMetadataNative(); 185 settings.readFromParcel(source); 186 } 187 188 if ((inputWidth > 0) && (inputHeight > 0) && (inputFormat != -1)) { 189 mInputConfig = new InputConfiguration(inputWidth, inputHeight, 190 inputFormat, isInputMultiResolution); 191 } 192 mSessionType = sessionType; 193 mOutputConfigurations = outConfigs; 194 } 195 196 public static final @android.annotation.NonNull Parcelable.Creator<SessionConfiguration> CREATOR = 197 new Parcelable.Creator<SessionConfiguration> () { 198 @Override 199 public SessionConfiguration createFromParcel(Parcel source) { 200 return new SessionConfiguration(source); 201 } 202 203 @Override 204 public SessionConfiguration[] newArray(int size) { 205 return new SessionConfiguration[size]; 206 } 207 }; 208 209 @Override writeToParcel(Parcel dest, int flags)210 public void writeToParcel(Parcel dest, int flags) { 211 if (dest == null) { 212 throw new IllegalArgumentException("dest must not be null"); 213 } 214 dest.writeInt(mSessionType); 215 if (mInputConfig != null) { 216 dest.writeInt(mInputConfig.getWidth()); 217 dest.writeInt(mInputConfig.getHeight()); 218 dest.writeInt(mInputConfig.getFormat()); 219 dest.writeBoolean(mInputConfig.isMultiResolution()); 220 } else { 221 dest.writeInt(/*inputWidth*/ 0); 222 dest.writeInt(/*inputHeight*/ 0); 223 dest.writeInt(/*inputFormat*/ -1); 224 dest.writeBoolean(/*isMultiResolution*/ false); 225 } 226 dest.writeTypedList(mOutputConfigurations); 227 if (mSessionParameters != null) { 228 dest.writeBoolean(/*hasSessionParameters*/true); 229 CameraMetadataNative metadata = mSessionParameters.getNativeCopy(); 230 metadata.writeToParcel(dest, /*flags*/0); 231 } else { 232 dest.writeBoolean(/*hasSessionParameters*/false); 233 } 234 } 235 236 @Override describeContents()237 public int describeContents() { 238 return 0; 239 } 240 241 /** 242 * Check if this {@link SessionConfiguration} is equal to another {@link SessionConfiguration}. 243 * 244 * <p>Two output session configurations are only equal if and only if the underlying input 245 * configuration, output configurations, and session type are equal. </p> 246 * 247 * @return {@code true} if the objects were equal, {@code false} otherwise 248 */ 249 @Override equals(@ullable Object obj)250 public boolean equals(@Nullable Object obj) { 251 if (obj == null) { 252 return false; 253 } else if (this == obj) { 254 return true; 255 } else if (obj instanceof SessionConfiguration) { 256 final SessionConfiguration other = (SessionConfiguration) obj; 257 if (mInputConfig != other.mInputConfig || mSessionType != other.mSessionType || 258 mOutputConfigurations.size() != other.mOutputConfigurations.size()) { 259 return false; 260 } 261 262 for (int i = 0; i < mOutputConfigurations.size(); i++) { 263 if (!mOutputConfigurations.get(i).equals(other.mOutputConfigurations.get(i))) 264 return false; 265 } 266 267 return true; 268 } 269 270 return false; 271 } 272 273 /** 274 * {@inheritDoc} 275 */ 276 @Override hashCode()277 public int hashCode() { 278 return HashCodeHelpers.hashCode(mOutputConfigurations.hashCode(), 279 Objects.hashCode(mInputConfig), 280 mSessionType); 281 } 282 283 /** 284 * Retrieve the type of the capture session. 285 * 286 * @return The capture session type. 287 */ getSessionType()288 public @SessionMode int getSessionType() { 289 return mSessionType; 290 } 291 292 /** 293 * Retrieve the {@link OutputConfiguration} list for the capture session. 294 * 295 * @return A list of output configurations for the capture session. 296 */ getOutputConfigurations()297 public List<OutputConfiguration> getOutputConfigurations() { 298 return mOutputConfigurations; 299 } 300 301 /** 302 * Retrieve the {@link CameraCaptureSession.StateCallback} for the capture session. 303 * 304 * @return A state callback interface implementation. 305 */ getStateCallback()306 public CameraCaptureSession.StateCallback getStateCallback() { 307 return mStateCallback; 308 } 309 310 /** 311 * Retrieve the {@link java.util.concurrent.Executor} for the capture session. 312 * 313 * @return The Executor on which the callback will be invoked. 314 */ getExecutor()315 public Executor getExecutor() { 316 return mExecutor; 317 } 318 319 /** 320 * Sets the {@link InputConfiguration} for a reprocessable session. Input configuration are not 321 * supported for {@link #SESSION_HIGH_SPEED}. 322 * 323 * @param input Input configuration. 324 * @throws UnsupportedOperationException In case it is called for {@link #SESSION_HIGH_SPEED} 325 * type session configuration. 326 */ setInputConfiguration(@onNull InputConfiguration input)327 public void setInputConfiguration(@NonNull InputConfiguration input) { 328 if (mSessionType != SESSION_HIGH_SPEED) { 329 mInputConfig = input; 330 } else { 331 throw new UnsupportedOperationException("Method not supported for high speed session" + 332 " types"); 333 } 334 } 335 336 /** 337 * Retrieve the {@link InputConfiguration}. 338 * 339 * @return The capture session input configuration. 340 */ getInputConfiguration()341 public InputConfiguration getInputConfiguration() { 342 return mInputConfig; 343 } 344 345 /** 346 * Sets the session wide camera parameters (see {@link CaptureRequest}). This argument can 347 * be set for every supported session type and will be passed to the camera device as part 348 * of the capture session initialization. Session parameters are a subset of the available 349 * capture request parameters (see {@link CameraCharacteristics#getAvailableSessionKeys}) 350 * and their application can introduce internal camera delays. To improve camera performance 351 * it is suggested to change them sparingly within the lifetime of the capture session and 352 * to pass their initial values as part of this method. 353 * 354 * @param params A capture request that includes the initial values for any available 355 * session wide capture keys. Tags (see {@link CaptureRequest.Builder#setTag}) and 356 * output targets (see {@link CaptureRequest.Builder#addTarget}) are ignored if 357 * set. Parameter values not part of 358 * {@link CameraCharacteristics#getAvailableSessionKeys} will also be ignored. It 359 * is recommended to build the session parameters using the same template type as 360 * the initial capture request, so that the session and initial request parameters 361 * match as much as possible. 362 */ setSessionParameters(CaptureRequest params)363 public void setSessionParameters(CaptureRequest params) { 364 mSessionParameters = params; 365 } 366 367 /** 368 * Retrieve the session wide camera parameters (see {@link CaptureRequest}). 369 * 370 * @return A capture request that includes the initial values for any available 371 * session wide capture keys. 372 */ getSessionParameters()373 public CaptureRequest getSessionParameters() { 374 return mSessionParameters; 375 } 376 377 /** 378 * Set a specific device-supported color space. 379 * 380 * <p>Clients can choose from any profile advertised as supported in 381 * {@link CameraCharacteristics#REQUEST_AVAILABLE_COLOR_SPACE_PROFILES} 382 * queried using {@link ColorSpaceProfiles#getSupportedColorSpaces}. 383 * When set, the colorSpace will override the default color spaces of the output targets, 384 * or the color space implied by the dataSpace passed into an {@link ImageReader}'s 385 * constructor.</p> 386 */ setColorSpace(@onNull ColorSpace.Named colorSpace)387 public void setColorSpace(@NonNull ColorSpace.Named colorSpace) { 388 mColorSpace = colorSpace.ordinal(); 389 for (OutputConfiguration outputConfiguration : mOutputConfigurations) { 390 outputConfiguration.setColorSpace(colorSpace); 391 } 392 } 393 394 /** 395 * Clear the color space, such that the default color space will be used. 396 */ clearColorSpace()397 public void clearColorSpace() { 398 mColorSpace = ColorSpaceProfiles.UNSPECIFIED; 399 for (OutputConfiguration outputConfiguration : mOutputConfigurations) { 400 outputConfiguration.clearColorSpace(); 401 } 402 } 403 404 /** 405 * Return the current color space. 406 * 407 * @return the currently set color space 408 */ 409 @SuppressLint("MethodNameUnits") getColorSpace()410 public @Nullable ColorSpace getColorSpace() { 411 if (mColorSpace != ColorSpaceProfiles.UNSPECIFIED) { 412 return ColorSpace.get(ColorSpace.Named.values()[mColorSpace]); 413 } else { 414 return null; 415 } 416 } 417 418 /** 419 * Set the state callback and executor. 420 * 421 * <p>This function must be called for the SessionConfiguration object created via {@link 422 * #SessionConfiguration(int, List) SessionConfiguration(int, List<OutputConfiguration>)} 423 * before it's used to create a capture session.</p> 424 * 425 * @param executor The executor which should be used to invoke the callback. In general it is 426 * recommended that camera operations are not done on the main (UI) thread. 427 * @param cb A state callback interface implementation. 428 */ 429 @FlaggedApi(Flags.FLAG_CAMERA_DEVICE_SETUP) setStateCallback( @onNull @allbackExecutor Executor executor, @NonNull CameraCaptureSession.StateCallback cb)430 public void setStateCallback( 431 @NonNull @CallbackExecutor Executor executor, 432 @NonNull CameraCaptureSession.StateCallback cb) { 433 mStateCallback = cb; 434 mExecutor = executor; 435 } 436 } 437