1 /*
2  * Copyright 2021 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 package androidx.camera.core.impl;
18 
19 import android.hardware.camera2.CameraCharacteristics;
20 import android.hardware.camera2.CameraExtensionSession;
21 import android.media.ImageReader;
22 import android.os.Build;
23 import android.util.Pair;
24 import android.util.Range;
25 import android.util.Size;
26 
27 import androidx.annotation.IntRange;
28 import androidx.camera.core.CameraInfo;
29 
30 import org.jspecify.annotations.NonNull;
31 import org.jspecify.annotations.Nullable;
32 
33 import java.util.Collections;
34 import java.util.List;
35 import java.util.Map;
36 import java.util.Set;
37 
38 /**
39  * A processor for (1) transforming the surfaces used in Preview/ImageCapture/ImageAnalysis
40  * into final session configuration where intermediate {@link ImageReader}s could be created for
41  * processing the image and writing the result to output surfaces (2) performing repeating request
42  * and still image capture by using {@link RequestProcessor}.
43  *
44  * <p>A {@link RequestProcessor} will be passed to the {@link SessionProcessor} when
45  * {@link SessionProcessor#onCaptureSessionStart(RequestProcessor)} is called to execute camera
46  * requests. When being requested to execute repeating request or still capture, the
47  * SessionProcessor can set any target surfaces and parameters it needs. It can also send
48  * multiple requests if necessary.
49  *
50  * <p>The SessionProcessor is expected to release all intermediate {@link ImageReader}s when
51  * {@link #deInitSession()} is called.
52  */
53 public interface SessionProcessor {
54     /**
55      * The session processor is used for CameraX extension modes that will directly access the
56      * vendor library implementation.
57      */
58     int TYPE_VENDOR_LIBRARY = 0;
59 
60     /**
61      * The session processor is used for Camera2 extension modes that should create the capture
62      * session via Camera2 Extensions API.
63      */
64     int TYPE_CAMERA2_EXTENSION = 1;
65 
66     /**
67      * Initializes the session and returns a transformed {@link SessionConfig} which should be
68      * used to configure the camera instead of original one.
69      *
70      * <p>Output surfaces of preview, image capture and imageAnalysis should be passed in. The
71      * SessionProcessor is responsible to write the output to this given output surfaces.
72      *
73      * @param cameraInfo                 cameraInfo for querying the camera info
74      * @param outputSurfaceConfig output surface configuration for preview, image capture,
75      *                                  image analysis and the postview. This can be null under
76      *                                  Camera2 Extensions implementation mode. In that case, this
77      *                                  function is invoked to setup the necessary stuffs only.
78      * @return a {@link SessionConfig} that contains the surfaces and the session parameters and
79      * should be used to configure the camera session. Return null when the input
80      * <code>outputSurfaceConfig</code> is null.
81      */
initSession(@onNull CameraInfo cameraInfo, @Nullable OutputSurfaceConfiguration outputSurfaceConfig)82     @Nullable SessionConfig initSession(@NonNull CameraInfo cameraInfo,
83             @Nullable OutputSurfaceConfiguration outputSurfaceConfig);
84 
85     /**
86      * De-initializes the session. This is called after the camera session is closed.
87      */
deInitSession()88     void deInitSession();
89 
90     /**
91      * Sets the camera parameters to be enabled in every single and repeating request.
92      */
setParameters(@onNull Config config)93     void setParameters(@NonNull Config config);
94 
95     /**
96      * Notifies the SessionProcessor that the camera session is just started. A
97      * {@link RequestProcessor} is provided to execute camera requests.
98      */
onCaptureSessionStart( @onNull RequestProcessor requestProcessor)99     void onCaptureSessionStart(
100             @NonNull RequestProcessor requestProcessor);
101 
102     /**
103      * Notifies the SessionProcessor that the camera session is going to be closed.
104      * {@link RequestProcessor} will no longer accept any requests
105      * after onCaptureSessionEnd() returns.
106      */
onCaptureSessionEnd()107     void onCaptureSessionEnd();
108 
109     /**
110      * Requests the SessionProcessor to start the repeating request that enables
111      * preview and image analysis.
112      *
113      * @param tagBundle the {@link TagBundle} to be attached to the {@link CameraCaptureResult} in
114      *                  {@link CaptureCallback#onCaptureCompleted(long, int, CameraCaptureResult)}.
115      * @param callback callback to notify the status.
116      * @return the id of the capture sequence.
117      */
startRepeating(@onNull TagBundle tagBundle, @NonNull CaptureCallback callback)118     int startRepeating(@NonNull TagBundle tagBundle, @NonNull CaptureCallback callback);
119 
120     /**
121      * Stop the repeating request.
122      */
stopRepeating()123     void stopRepeating();
124 
125     /**
126      * Requests the SessionProcessor to start the still image capture. The capture task can only
127      * perform one at a time.
128      *
129      * @param postviewEnabled if postview is enabled or not.
130      * @param tagBundle the {@link TagBundle} to be attached to the {@link CameraCaptureResult} in
131      *                  {@link CaptureCallback#onCaptureCompleted(long, int, CameraCaptureResult)}.
132      * @param callback callback to notify the status.
133      * @return the id of the capture sequence.
134      */
startCapture(boolean postviewEnabled, @NonNull TagBundle tagBundle, @NonNull CaptureCallback callback)135     int startCapture(boolean postviewEnabled, @NonNull TagBundle tagBundle,
136             @NonNull CaptureCallback callback);
137 
138     /**
139      * Aborts the pending capture.
140      */
abortCapture(int captureSequenceId)141     void abortCapture(int captureSequenceId);
142 
143     /**
144      * Sends trigger-type single request such as AF/AE triggers.
145      * @param config the {@link Config} that contains the parameters to be set in the trigger.
146      * @param tagBundle the {@link TagBundle} to be attached to the {@link CameraCaptureResult} in
147      *                  {@link CaptureCallback#onCaptureCompleted(long, int, CameraCaptureResult)}.
148      * @param callback callback to notify the status
149      * @return the id of the capture sequence.
150      */
startTrigger(@onNull Config config, @NonNull TagBundle tagBundle, @NonNull CaptureCallback callback)151     default int startTrigger(@NonNull Config config,  @NonNull TagBundle tagBundle,
152             @NonNull CaptureCallback callback) {
153         return -1;
154     }
155 
156     /**
157      * Returns supported output format/size map for postview image. The API is provided
158      * for camera-core to query the supported postview sizes from SessionProcessor.
159      */
getSupportedPostviewSize(@onNull Size captureSize)160     default @NonNull Map<Integer, List<Size>> getSupportedPostviewSize(@NonNull Size captureSize) {
161         return Collections.emptyMap();
162     }
163 
164     /**
165      * Returns the supported camera operations when the SessionProcessor is enabled.
166      */
167     default @AdapterCameraInfo.CameraOperation @NonNull Set<Integer>
getSupportedCameraOperations()168             getSupportedCameraOperations() {
169         return Collections.emptySet();
170     }
171 
172     default @NonNull List<Pair<CameraCharacteristics.Key, Object>>
getAvailableCharacteristicsKeyValues()173             getAvailableCharacteristicsKeyValues() {
174         return Collections.emptyList();
175     }
176 
177     /**
178      * Returns the extensions-specific zoom range
179      */
180     @SuppressWarnings("unchecked")
getExtensionZoomRange()181     default @Nullable Range<Float> getExtensionZoomRange() {
182         if (Build.VERSION.SDK_INT >= 30) {
183             List<Pair<CameraCharacteristics.Key, Object>> keyValues =
184                     getAvailableCharacteristicsKeyValues();
185             for (Pair<CameraCharacteristics.Key, Object> keyValue : keyValues) {
186                 if (keyValue.first.equals(CameraCharacteristics.CONTROL_ZOOM_RATIO_RANGE)) {
187                     return (Range<Float>) keyValue.second;
188                 }
189             }
190         }
191         return null;
192     }
193 
194     /**
195      * Returns the extensions-specific available stabilization modes.
196      */
197     @SuppressWarnings("unchecked")
getExtensionAvailableStabilizationModes()198     default int @Nullable [] getExtensionAvailableStabilizationModes() {
199         List<Pair<CameraCharacteristics.Key, Object>> keyValues =
200                 getAvailableCharacteristicsKeyValues();
201         for (Pair<CameraCharacteristics.Key, Object> keyValue : keyValues) {
202             if (keyValue.first.equals(
203                     CameraCharacteristics.CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES)) {
204                 return (int[]) keyValue.second;
205             }
206         }
207         return null;
208     }
209 
210     /**
211      * Returns the dynamically calculated capture latency pair in milliseconds.
212      *
213      * The measurement is expected to take in to account dynamic parameters such as the current
214      * scene, the state of 3A algorithms, the state of internal HW modules and return a more
215      * accurate assessment of the capture and/or processing latency.</p>
216      *
217      * @return pair that includes the estimated input frame/frames camera capture latency as the
218      * first field. This is the time between {@link CaptureCallback#onCaptureStarted} and
219      * {@link CaptureCallback#onCaptureProcessStarted}. The second field value includes the
220      * estimated post-processing latency. This is the time between
221      * {@link CaptureCallback#onCaptureProcessStarted} until the processed frame returns back to the
222      * client registered surface.
223      * Both first and second values will be in milliseconds. The total still capture latency will be
224      * the sum of both the first and second values of the pair.
225      * The pair is expected to be null if the dynamic latency estimation is not supported.
226      * If clients have not configured a still capture output, then this method can also return a
227      * null pair.
228      */
getRealtimeCaptureLatency()229     default @Nullable Pair<Long, Long> getRealtimeCaptureLatency() {
230         return null;
231     }
232 
233     /**
234      * Returns the implementation type info composited by the extension impl type and the
235      * extension mode.
236      *
237      * <p>The first value of the returned {@link Pair} can be {@link #TYPE_VENDOR_LIBRARY} or
238      * {@link #TYPE_CAMERA2_EXTENSION} that can let the caller know how to use the
239      * SessionProcessor to create the capture session. The second value is the mode under the impl
240      * type.
241      *
242      * @return a {@link Pair} composited by the extension impl type and the extension mode.
243      */
244     @NonNull
getImplementationType()245     default Pair<Integer, Integer> getImplementationType() {
246         return Pair.create(TYPE_VENDOR_LIBRARY, 0 /* ExtensionMode.None */);
247     }
248 
249     /**
250      * Sets a {@link CaptureSessionRequestProcessor} for retrieving specific information from the
251      * camera capture session or submitting requests.
252      *
253      * <p>This is used for the SessionProcessor implementation that needs to directly interact
254      * with the camera capture session to retrieve specific information or submit requests.
255      *
256      * <p>Callers should clear this by calling with null to avoid the session processor to hold
257      * the camera capture session related resources.
258      */
setCaptureSessionRequestProcessor( @ullable CaptureSessionRequestProcessor processor)259     default void setCaptureSessionRequestProcessor(
260             @Nullable CaptureSessionRequestProcessor processor) {
261     }
262 
263     /**
264      * Callback for {@link #startRepeating} and {@link #startCapture}.
265      */
266     interface CaptureCallback {
267         /**
268          * This method is called when the camera has started capturing the initial input
269          * image.
270          *
271          * For a multi-frame capture, the method is called when the onCaptureStarted of first
272          * frame is called and its timestamp is directly forwarded to timestamp parameter of
273          * this method.
274          *
275          * @param captureSequenceId id of the current capture sequence
276          * @param timestamp         the timestamp at start of capture for repeating
277          *                          request or the timestamp at start of capture of the
278          *                          first frame in a multi-frame capture, in nanoseconds.
279          */
onCaptureStarted(int captureSequenceId, long timestamp)280         default void onCaptureStarted(int captureSequenceId, long timestamp) {}
281 
282         /**
283          * This method is called when an image (or images in case of multi-frame
284          * capture) is captured and device-specific extension processing is triggered.
285          *
286          * @param captureSequenceId id of the current capture sequence
287          */
onCaptureProcessStarted(int captureSequenceId)288         default void onCaptureProcessStarted(int captureSequenceId) {}
289 
290         /**
291          * This method is called instead of {@link #onCaptureProcessStarted} when the camera
292          * device failed to produce the required input image. The cause could be a failed camera
293          * capture request, a failed capture result or dropped camera frame.
294          *
295          * @param captureSequenceId id of the current capture sequence
296          */
onCaptureFailed(int captureSequenceId)297         default void onCaptureFailed(int captureSequenceId) {}
298 
299         /**
300          * This method is called independently of the others in the CaptureCallback, when a capture
301          * sequence finishes.
302          *
303          * <p>In total, there will be at least one {@link #onCaptureProcessStarted}/
304          * {@link #onCaptureFailed} invocation before this callback is triggered. If the capture
305          * sequence is aborted before any requests have begun processing,
306          * {@link #onCaptureSequenceAborted} is invoked instead.</p>
307          *
308          * @param captureSequenceId id of the current capture sequence
309          */
onCaptureSequenceCompleted(int captureSequenceId)310         default void onCaptureSequenceCompleted(int captureSequenceId) {}
311 
312         /**
313          * This method is called when a capture sequence aborts.
314          *
315          * @param captureSequenceId id of the current capture sequence
316          */
onCaptureSequenceAborted(int captureSequenceId)317         default void onCaptureSequenceAborted(int captureSequenceId) {}
318 
319         /**
320          * Capture result callback that needs to be called when the process capture results are
321          * ready as part of frame post-processing.
322          *
323          * This callback will fire after {@link #onCaptureStarted}, {@link #onCaptureProcessStarted}
324          * and before {@link #onCaptureSequenceCompleted}. The callback is not expected to fire
325          * in case of capture failure  {@link #onCaptureFailed} or capture abort
326          * {@link #onCaptureSequenceAborted}.
327          *
328          * @param timestamp            The timestamp at start of capture. The same timestamp value
329          *                             passed to {@link #onCaptureStarted}.
330          * @param captureSequenceId    the capture id of the request that generated the capture
331          *                             results. This is the return value of either
332          *                             {@link #startRepeating} or {@link #startCapture}.
333          * @param captureResult        the capture result that contains the metadata and the
334          *                             timestamp of the capture.
335          */
onCaptureCompleted(long timestamp, int captureSequenceId, @NonNull CameraCaptureResult captureResult)336         default void onCaptureCompleted(long timestamp, int captureSequenceId,
337                 @NonNull CameraCaptureResult captureResult) {}
338 
339         /**
340          * Capture progress callback that needs to be called when the process capture is
341          * ongoing and includes the estimated progress of the processing.
342          *
343          * <p>Extensions must ensure that they always call this callback with monotonically
344          * increasing values.</p>
345          *
346          * <p>Extensions are allowed to trigger this callback multiple times but at the minimum the
347          * callback is expected to be called once when processing is done with value 100.</p>
348          *
349          * @param progress             Value between 0 and 100.
350          */
onCaptureProcessProgressed(int progress)351         default void onCaptureProcessProgressed(int progress) {}
352     }
353 
354     /**
355      * An interface for retrieving specific information from the camera capture session or
356      * submitting requests.
357      */
358     interface CaptureSessionRequestProcessor {
359         /**
360          * Returns the realtime still capture latency information.
361          *
362          * @see CameraExtensionSession#getRealtimeStillCaptureLatency()
363          */
364         @Nullable
getRealtimeStillCaptureLatency()365         Pair<Long, Long> getRealtimeStillCaptureLatency();
366 
367         /**
368          * Sets the strength of the extension post-processing effect.
369          *
370          * @param strength the new extension strength value
371          * @see android.hardware.camera2.CaptureRequest#EXTENSION_STRENGTH
372          */
setExtensionStrength(@ntRangefrom = 0, to = 100) int strength)373         void setExtensionStrength(@IntRange(from = 0, to = 100) int strength);
374     }
375 }
376