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.resolutionselector;
18 
19 import static androidx.camera.core.AspectRatio.RATIO_16_9;
20 import static androidx.camera.core.AspectRatio.RATIO_4_3;
21 
22 import androidx.annotation.IntDef;
23 import androidx.annotation.RestrictTo;
24 import androidx.camera.core.AspectRatio;
25 import androidx.camera.core.CameraSelector;
26 import androidx.camera.core.UseCase;
27 import androidx.lifecycle.LifecycleOwner;
28 
29 import org.jspecify.annotations.NonNull;
30 
31 import java.lang.annotation.Retention;
32 import java.lang.annotation.RetentionPolicy;
33 
34 /**
35  * The aspect ratio strategy defines the sequence of aspect ratios that are used to select the
36  * best size for a particular image.
37  *
38  * <p>Applications can create a {@link ResolutionSelector} with a proper AspectRatioStrategy to
39  * choose a resolution that matches the preferred aspect ratio.
40  *
41  * <p>By default, CameraX supports the common 4:3 and 16:9 aspect ratio settings. Some devices may
42  * offer additional output sizes. To access these, you'll need to create a
43  * {@link ResolutionSelector} with a {@link ResolutionFilter} to find and select those specific
44  * sizes.
45  */
46 public final class AspectRatioStrategy {
47     /**
48      * CameraX doesn't fall back to select sizes of any other aspect ratio when this fallback
49      * rule is used.
50      *
51      * <p>Note that an AspectRatioStrategy with more restricted settings may result in that no
52      * resolution can be selected to use. Applications will receive
53      * {@link IllegalArgumentException} when binding the {@link UseCase}s with such kind of
54      * AspectRatioStrategy.
55      */
56     public static final int FALLBACK_RULE_NONE = 0;
57     /**
58      * CameraX automatically chooses the next best aspect ratio which contains the closest field
59      * of view (FOV) of the camera sensor, from the remaining options.
60      */
61     public static final int FALLBACK_RULE_AUTO = 1;
62 
63     /**
64      * Defines the available fallback rules for AspectRatioStrategy.
65      */
66     @Retention(RetentionPolicy.SOURCE)
67     @IntDef({FALLBACK_RULE_NONE,
68             FALLBACK_RULE_AUTO
69     })
70     @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
71     public @interface AspectRatioFallbackRule {
72     }
73 
74     /**
75      * The pre-defined default aspect ratio strategy that selects sizes with
76      * {@link AspectRatio#RATIO_4_3} in priority. Then, selects sizes with other aspect ratios
77      * according to which aspect ratio can contain the closest FOV of the camera sensor.
78      *
79      * <p>Please see the
80      * <a href="https://source.android.com/docs/core/camera/camera3_crop_reprocess">Output streams,
81      * Cropping, and Zoom</a> introduction to know more about the camera FOV.
82      */
83     public static final @NonNull AspectRatioStrategy RATIO_4_3_FALLBACK_AUTO_STRATEGY =
84             new AspectRatioStrategy(RATIO_4_3, FALLBACK_RULE_AUTO);
85 
86     /**
87      * The pre-defined aspect ratio strategy that selects sizes with
88      * {@link AspectRatio#RATIO_16_9} in priority. Then, selects sizes with other aspect ratios
89      * according to which aspect ratio can contain the closest FOV of the camera sensor.
90      *
91      * <p>Please see the
92      * <a href="https://source.android.com/docs/core/camera/camera3_crop_reprocess">Output streams,
93      * Cropping, and Zoom</a> introduction to know more about the camera FOV.
94      */
95     public static final @NonNull AspectRatioStrategy RATIO_16_9_FALLBACK_AUTO_STRATEGY =
96             new AspectRatioStrategy(RATIO_16_9, FALLBACK_RULE_AUTO);
97 
98     @AspectRatio.Ratio
99     private final int mPreferredAspectRatio;
100     @AspectRatioFallbackRule
101     private final int mFallbackRule;
102 
103     /**
104      * Creates a new AspectRatioStrategy instance, configured with the specified preferred aspect
105      * ratio and fallback rule.
106      *
107      * <p>OEMs might make the width or height of the supported output sizes be mod 16 aligned for
108      * performance reasons. This means that the device might support 1920x1088 instead of
109      * 1920x1080, even though a 16:9 aspect ratio size is 1920x1080. CameraX can select these mod
110      * 16 aligned sizes when applications specify the preferred aspect ratio as
111      * {@link AspectRatio#RATIO_16_9}.
112      *
113      * <p>Some devices may have issues using sizes of the preferred aspect ratios. CameraX
114      * recommends that applications use the {@link #FALLBACK_RULE_AUTO} setting to avoid no
115      * resolution being available, as an {@link IllegalArgumentException} may be thrown when
116      * calling
117      * {@link androidx.camera.lifecycle.ProcessCameraProvider#bindToLifecycle(LifecycleOwner, CameraSelector, UseCase...)}
118      * to bind {@link UseCase}s with the AspectRatioStrategy specified in the
119      * {@link ResolutionSelector}.
120      *
121      * @param preferredAspectRatio the preferred aspect ratio to select first which can be either
122      * {@link AspectRatio#RATIO_4_3} or {@link AspectRatio#RATIO_16_9}.
123      * @param fallbackRule the rule to follow when the preferred aspect ratio is unavailable.
124      *                     This can be either {@link AspectRatioStrategy#FALLBACK_RULE_AUTO} or
125      *                     {@link AspectRatioStrategy#FALLBACK_RULE_NONE}.
126      */
AspectRatioStrategy(@spectRatio.Ratio int preferredAspectRatio, @AspectRatioFallbackRule int fallbackRule)127     public AspectRatioStrategy(@AspectRatio.Ratio int preferredAspectRatio,
128             @AspectRatioFallbackRule int fallbackRule) {
129         mPreferredAspectRatio = preferredAspectRatio;
130         mFallbackRule = fallbackRule;
131     }
132 
133     /**
134      * Returns the specified preferred aspect ratio.
135      */
136     @AspectRatio.Ratio
getPreferredAspectRatio()137     public int getPreferredAspectRatio() {
138         return mPreferredAspectRatio;
139     }
140 
141     /**
142      * Returns the specified fallback rule for choosing the aspect ratio when the preferred aspect
143      * ratio is not available.
144      */
145     @AspectRatioFallbackRule
getFallbackRule()146     public int getFallbackRule() {
147         return mFallbackRule;
148     }
149 }
150