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.IntDef; 24 import android.annotation.NonNull; 25 import android.annotation.Nullable; 26 import android.hardware.camera2.CameraCaptureSession; 27 import android.hardware.camera2.CameraCharacteristics; 28 import android.hardware.camera2.CameraDevice; 29 import android.hardware.camera2.CaptureRequest; 30 import android.hardware.camera2.params.InputConfiguration; 31 import android.hardware.camera2.params.OutputConfiguration; 32 import android.hardware.camera2.utils.HashCodeHelpers; 33 import android.os.Parcel; 34 import android.os.Parcelable; 35 import android.util.Log; 36 37 import java.lang.annotation.Retention; 38 import java.lang.annotation.RetentionPolicy; 39 import java.util.ArrayList; 40 import java.util.Collections; 41 import java.util.List; 42 import java.util.concurrent.Executor; 43 44 /** 45 * A helper class that aggregates all supported arguments for capture session initialization. 46 */ 47 public final class SessionConfiguration implements Parcelable { 48 private static final String TAG = "SessionConfiguration"; 49 50 /** 51 * A regular session type containing instances of {@link OutputConfiguration} running 52 * at regular non high speed FPS ranges and optionally {@link InputConfiguration} for 53 * reprocessable sessions. 54 * 55 * @see CameraDevice#createCaptureSession 56 * @see CameraDevice#createReprocessableCaptureSession 57 */ 58 public static final int SESSION_REGULAR = CameraDevice.SESSION_OPERATION_MODE_NORMAL; 59 60 /** 61 * A high speed session type that can only contain instances of {@link OutputConfiguration}. 62 * The outputs can run using high speed FPS ranges. Calls to {@link #setInputConfiguration} 63 * are not supported. 64 * <p> 65 * When using this type, the CameraCaptureSession returned by 66 * {@link android.hardware.camera2.CameraCaptureSession.StateCallback} can be cast to a 67 * {@link android.hardware.camera2.CameraConstrainedHighSpeedCaptureSession} to access the extra 68 * methods for constrained high speed recording. 69 * </p> 70 * 71 * @see CameraDevice#createConstrainedHighSpeedCaptureSession 72 */ 73 public static final int SESSION_HIGH_SPEED = 74 CameraDevice.SESSION_OPERATION_MODE_CONSTRAINED_HIGH_SPEED; 75 76 /** 77 * First vendor-specific session mode 78 * @hide 79 */ 80 public static final int SESSION_VENDOR_START = 81 CameraDevice.SESSION_OPERATION_MODE_VENDOR_START; 82 83 /** @hide */ 84 @Retention(RetentionPolicy.SOURCE) 85 @IntDef(prefix = {"SESSION_"}, value = 86 {SESSION_REGULAR, 87 SESSION_HIGH_SPEED }) 88 public @interface SessionMode {}; 89 90 // Camera capture session related parameters. 91 private List<OutputConfiguration> mOutputConfigurations; 92 private CameraCaptureSession.StateCallback mStateCallback; 93 private int mSessionType; 94 private Executor mExecutor = null; 95 private InputConfiguration mInputConfig = null; 96 private CaptureRequest mSessionParameters = null; 97 98 /** 99 * Create a new {@link SessionConfiguration}. 100 * 101 * @param sessionType The session type. 102 * @param outputs A list of output configurations for the capture session. 103 * @param executor The executor which should be used to invoke the callback. In general it is 104 * recommended that camera operations are not done on the main (UI) thread. 105 * @param cb A state callback interface implementation. 106 * 107 * @see #SESSION_REGULAR 108 * @see #SESSION_HIGH_SPEED 109 * @see CameraDevice#createCaptureSession(List, CameraCaptureSession.StateCallback, Handler) 110 * @see CameraDevice#createCaptureSessionByOutputConfigurations 111 * @see CameraDevice#createReprocessableCaptureSession 112 * @see CameraDevice#createConstrainedHighSpeedCaptureSession 113 */ SessionConfiguration(@essionMode int sessionType, @NonNull List<OutputConfiguration> outputs, @NonNull @CallbackExecutor Executor executor, @NonNull CameraCaptureSession.StateCallback cb)114 public SessionConfiguration(@SessionMode int sessionType, 115 @NonNull List<OutputConfiguration> outputs, 116 @NonNull @CallbackExecutor Executor executor, 117 @NonNull CameraCaptureSession.StateCallback cb) { 118 mSessionType = sessionType; 119 mOutputConfigurations = Collections.unmodifiableList(new ArrayList<>(outputs)); 120 mStateCallback = cb; 121 mExecutor = executor; 122 } 123 124 /** 125 * Create a SessionConfiguration from Parcel. 126 * No support for parcelable 'mStateCallback', 'mExecutor' and 'mSessionParameters' yet. 127 */ SessionConfiguration(@onNull Parcel source)128 private SessionConfiguration(@NonNull Parcel source) { 129 int sessionType = source.readInt(); 130 int inputWidth = source.readInt(); 131 int inputHeight = source.readInt(); 132 int inputFormat = source.readInt(); 133 boolean isInputMultiResolution = source.readBoolean(); 134 ArrayList<OutputConfiguration> outConfigs = new ArrayList<OutputConfiguration>(); 135 source.readTypedList(outConfigs, OutputConfiguration.CREATOR); 136 137 if ((inputWidth > 0) && (inputHeight > 0) && (inputFormat != -1)) { 138 mInputConfig = new InputConfiguration(inputWidth, inputHeight, 139 inputFormat, isInputMultiResolution); 140 } 141 mSessionType = sessionType; 142 mOutputConfigurations = outConfigs; 143 } 144 145 public static final @android.annotation.NonNull Parcelable.Creator<SessionConfiguration> CREATOR = 146 new Parcelable.Creator<SessionConfiguration> () { 147 @Override 148 public SessionConfiguration createFromParcel(Parcel source) { 149 return new SessionConfiguration(source); 150 } 151 152 @Override 153 public SessionConfiguration[] newArray(int size) { 154 return new SessionConfiguration[size]; 155 } 156 }; 157 158 @Override writeToParcel(Parcel dest, int flags)159 public void writeToParcel(Parcel dest, int flags) { 160 if (dest == null) { 161 throw new IllegalArgumentException("dest must not be null"); 162 } 163 dest.writeInt(mSessionType); 164 if (mInputConfig != null) { 165 dest.writeInt(mInputConfig.getWidth()); 166 dest.writeInt(mInputConfig.getHeight()); 167 dest.writeInt(mInputConfig.getFormat()); 168 dest.writeBoolean(mInputConfig.isMultiResolution()); 169 } else { 170 dest.writeInt(/*inputWidth*/ 0); 171 dest.writeInt(/*inputHeight*/ 0); 172 dest.writeInt(/*inputFormat*/ -1); 173 dest.writeBoolean(/*isMultiResolution*/ false); 174 } 175 dest.writeTypedList(mOutputConfigurations); 176 } 177 178 @Override describeContents()179 public int describeContents() { 180 return 0; 181 } 182 183 /** 184 * Check if this {@link SessionConfiguration} is equal to another {@link SessionConfiguration}. 185 * 186 * <p>Two output session configurations are only equal if and only if the underlying input 187 * configuration, output configurations, and session type are equal. </p> 188 * 189 * @return {@code true} if the objects were equal, {@code false} otherwise 190 */ 191 @Override equals(@ullable Object obj)192 public boolean equals(@Nullable Object obj) { 193 if (obj == null) { 194 return false; 195 } else if (this == obj) { 196 return true; 197 } else if (obj instanceof SessionConfiguration) { 198 final SessionConfiguration other = (SessionConfiguration) obj; 199 if (mInputConfig != other.mInputConfig || mSessionType != other.mSessionType || 200 mOutputConfigurations.size() != other.mOutputConfigurations.size()) { 201 return false; 202 } 203 204 for (int i = 0; i < mOutputConfigurations.size(); i++) { 205 if (!mOutputConfigurations.get(i).equals(other.mOutputConfigurations.get(i))) 206 return false; 207 } 208 209 return true; 210 } 211 212 return false; 213 } 214 215 /** 216 * {@inheritDoc} 217 */ 218 @Override hashCode()219 public int hashCode() { 220 return HashCodeHelpers.hashCode(mOutputConfigurations.hashCode(), mInputConfig.hashCode(), 221 mSessionType); 222 } 223 224 /** 225 * Retrieve the type of the capture session. 226 * 227 * @return The capture session type. 228 */ getSessionType()229 public @SessionMode int getSessionType() { 230 return mSessionType; 231 } 232 233 /** 234 * Retrieve the {@link OutputConfiguration} list for the capture session. 235 * 236 * @return A list of output configurations for the capture session. 237 */ getOutputConfigurations()238 public List<OutputConfiguration> getOutputConfigurations() { 239 return mOutputConfigurations; 240 } 241 242 /** 243 * Retrieve the {@link CameraCaptureSession.StateCallback} for the capture session. 244 * 245 * @return A state callback interface implementation. 246 */ getStateCallback()247 public CameraCaptureSession.StateCallback getStateCallback() { 248 return mStateCallback; 249 } 250 251 /** 252 * Retrieve the {@link java.util.concurrent.Executor} for the capture session. 253 * 254 * @return The Executor on which the callback will be invoked. 255 */ getExecutor()256 public Executor getExecutor() { 257 return mExecutor; 258 } 259 260 /** 261 * Sets the {@link InputConfiguration} for a reprocessable session. Input configuration are not 262 * supported for {@link #SESSION_HIGH_SPEED}. 263 * 264 * @param input Input configuration. 265 * @throws UnsupportedOperationException In case it is called for {@link #SESSION_HIGH_SPEED} 266 * type session configuration. 267 */ setInputConfiguration(@onNull InputConfiguration input)268 public void setInputConfiguration(@NonNull InputConfiguration input) { 269 if (mSessionType != SESSION_HIGH_SPEED) { 270 mInputConfig = input; 271 } else { 272 throw new UnsupportedOperationException("Method not supported for high speed session" + 273 " types"); 274 } 275 } 276 277 /** 278 * Retrieve the {@link InputConfiguration}. 279 * 280 * @return The capture session input configuration. 281 */ getInputConfiguration()282 public InputConfiguration getInputConfiguration() { 283 return mInputConfig; 284 } 285 286 /** 287 * Sets the session wide camera parameters (see {@link CaptureRequest}). This argument can 288 * be set for every supported session type and will be passed to the camera device as part 289 * of the capture session initialization. Session parameters are a subset of the available 290 * capture request parameters (see {@link CameraCharacteristics#getAvailableSessionKeys}) 291 * and their application can introduce internal camera delays. To improve camera performance 292 * it is suggested to change them sparingly within the lifetime of the capture session and 293 * to pass their initial values as part of this method. 294 * 295 * @param params A capture request that includes the initial values for any available 296 * session wide capture keys. Tags (see {@link CaptureRequest.Builder#setTag}) and 297 * output targets (see {@link CaptureRequest.Builder#addTarget}) are ignored if 298 * set. Parameter values not part of 299 * {@link CameraCharacteristics#getAvailableSessionKeys} will also be ignored. It 300 * is recommended to build the session parameters using the same template type as 301 * the initial capture request, so that the session and initial request parameters 302 * match as much as possible. 303 */ setSessionParameters(CaptureRequest params)304 public void setSessionParameters(CaptureRequest params) { 305 mSessionParameters = params; 306 } 307 308 /** 309 * Retrieve the session wide camera parameters (see {@link CaptureRequest}). 310 * 311 * @return A capture request that includes the initial values for any available 312 * session wide capture keys. 313 */ getSessionParameters()314 public CaptureRequest getSessionParameters() { 315 return mSessionParameters; 316 } 317 } 318