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