• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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&lt;OutputConfiguration&gt;)}
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