1 /*
2  * Copyright 2023 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;
18 
19 import org.jspecify.annotations.NonNull;
20 
21 import java.util.Objects;
22 
23 /**
24  * An immutable representation of the estimated duration an image capture will take
25  * capturing and processing the current scene according to the scene's lighting condition and/or
26  * camera configuration.
27  *
28  * <p>The latency estimate is produced by {@link ImageCapture#getRealtimeCaptureLatencyEstimate()}.
29  *
30  * <p>The estimate is comprised of two components: {@link #getCaptureLatencyMillis()},
31  * {@link #getProcessingLatencyMillis()}.
32  */
33 public class ImageCaptureLatencyEstimate {
34     /** The capture latency is unsupported or undefined */
35     public static final long UNDEFINED_CAPTURE_LATENCY = -1;
36 
37     /** The processing latency is unsupported or undefined */
38     public static final long UNDEFINED_PROCESSING_LATENCY = -1;
39 
40     /** The image capture latency estimate is unsupported or undefined */
41     public static final @NonNull ImageCaptureLatencyEstimate UNDEFINED_IMAGE_CAPTURE_LATENCY =
42             new ImageCaptureLatencyEstimate(UNDEFINED_CAPTURE_LATENCY,
43                     UNDEFINED_PROCESSING_LATENCY);
44 
45     private final long mCaptureLatencyMillis;
46     private final long mProcessingLatencyMillis;
47     private final long mTotalCaptureLatencyMillis;
48 
49     /**
50      * Created by {@link ImageCapture#getRealtimeCaptureLatencyEstimate()} when querying for the
51      * current realtime latency estimate. This can also be used for testing. It is not necessary to
52      * explicitly construct this in any other scenario.
53      *
54      * @param captureLatencyMillis The estimated duration in milliseconds from when the camera
55      *                             begins capturing frames to the moment the camera has completed
56      *                             capturing frames.
57      * @param processingLatencyMillis The estimated duration in milliseconds from when the
58      *                                processing begins until the processing has completed and the
59      *                                final processed capture is available.
60      */
ImageCaptureLatencyEstimate(long captureLatencyMillis, long processingLatencyMillis)61     public ImageCaptureLatencyEstimate(long captureLatencyMillis, long processingLatencyMillis) {
62         mCaptureLatencyMillis = captureLatencyMillis;
63         mProcessingLatencyMillis = processingLatencyMillis;
64         mTotalCaptureLatencyMillis = computeTotalCaptureLatencyMillis(captureLatencyMillis,
65                 processingLatencyMillis);
66     }
67 
68     /**
69      * Returns the estimated duration in milliseconds from when the camera begins capturing
70      * frames to the moment the camera has completed capturing frames. If this estimate is not
71      * supported or not available then it will be {@link #UNDEFINED_CAPTURE_LATENCY}.
72      */
getCaptureLatencyMillis()73     public long getCaptureLatencyMillis() {
74         return mCaptureLatencyMillis;
75     }
76 
77     /**
78      * Returns the estimated duration in milliseconds from when the processing begins until the
79      * processing has completed and the final processed capture is available. If this estimate is
80      * not supported or not available then it will be {@link #UNDEFINED_PROCESSING_LATENCY}.
81      */
getProcessingLatencyMillis()82     public long getProcessingLatencyMillis() {
83         return mProcessingLatencyMillis;
84     }
85 
86     /**
87      * Returns the total estimated capture duration in milliseconds. This includes time spent in
88      * capturing and processing.
89      *
90      * <p>If either the capture latency or processing latency is undefined then the total estimate
91      * is {@link #UNDEFINED_CAPTURE_LATENCY}.
92      */
getTotalCaptureLatencyMillis()93     public long getTotalCaptureLatencyMillis() {
94         return mTotalCaptureLatencyMillis;
95     }
96 
97     @Override
equals(Object o)98     public boolean equals(Object o) {
99         if (this == o) return true;
100         if (!(o instanceof ImageCaptureLatencyEstimate)) return false;
101         ImageCaptureLatencyEstimate that = (ImageCaptureLatencyEstimate) o;
102         return mCaptureLatencyMillis == that.getCaptureLatencyMillis()
103                 && mProcessingLatencyMillis == that.getProcessingLatencyMillis()
104                 && mTotalCaptureLatencyMillis == that.getTotalCaptureLatencyMillis();
105     }
106 
107     @Override
hashCode()108     public int hashCode() {
109         return Objects.hash(mCaptureLatencyMillis, mProcessingLatencyMillis,
110                 mTotalCaptureLatencyMillis);
111     }
112 
113     @Override
toString()114     public @NonNull String toString() {
115         return "captureLatencyMillis=" + mCaptureLatencyMillis
116                 + ", processingLatencyMillis=" + mProcessingLatencyMillis
117                 + ", totalCaptureLatencyMillis=" + mTotalCaptureLatencyMillis;
118     }
119 
computeTotalCaptureLatencyMillis(long captureLatencyMillis, long processingLatencyMillis)120     private long computeTotalCaptureLatencyMillis(long captureLatencyMillis,
121             long processingLatencyMillis) {
122         if (captureLatencyMillis == UNDEFINED_PROCESSING_LATENCY
123                 || processingLatencyMillis == UNDEFINED_CAPTURE_LATENCY) {
124             return UNDEFINED_CAPTURE_LATENCY;
125         }
126         return captureLatencyMillis + processingLatencyMillis;
127     }
128 }
129