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.video;
18 
19 import static android.media.CamcorderProfile.QUALITY_1080P;
20 import static android.media.CamcorderProfile.QUALITY_2160P;
21 import static android.media.CamcorderProfile.QUALITY_480P;
22 import static android.media.CamcorderProfile.QUALITY_720P;
23 import static android.media.CamcorderProfile.QUALITY_HIGH;
24 import static android.media.CamcorderProfile.QUALITY_HIGH_SPEED_1080P;
25 import static android.media.CamcorderProfile.QUALITY_HIGH_SPEED_2160P;
26 import static android.media.CamcorderProfile.QUALITY_HIGH_SPEED_480P;
27 import static android.media.CamcorderProfile.QUALITY_HIGH_SPEED_720P;
28 import static android.media.CamcorderProfile.QUALITY_HIGH_SPEED_HIGH;
29 import static android.media.CamcorderProfile.QUALITY_HIGH_SPEED_LOW;
30 import static android.media.CamcorderProfile.QUALITY_LOW;
31 
32 import static java.util.Arrays.asList;
33 import static java.util.Collections.emptyList;
34 import static java.util.Collections.singletonList;
35 import static java.util.Collections.unmodifiableList;
36 
37 import android.util.Size;
38 
39 import androidx.annotation.IntDef;
40 import androidx.annotation.RestrictTo;
41 import androidx.annotation.RestrictTo.Scope;
42 
43 import com.google.auto.value.AutoValue;
44 
45 import org.jspecify.annotations.NonNull;
46 
47 import java.lang.annotation.Retention;
48 import java.lang.annotation.RetentionPolicy;
49 import java.util.ArrayList;
50 import java.util.HashSet;
51 import java.util.List;
52 import java.util.Set;
53 
54 /**
55  * A class representing video quality constraints that will be used by {@link QualitySelector} to
56  * choose video resolution and appropriate encoding parameters.
57  */
58 public class Quality {
59 
60     // Restrict access to sealed class
Quality()61     private Quality() {
62     }
63 
64     /**
65      * Standard Definition (SD) 480p video quality.
66      *
67      * <p>This video quality usually corresponds to a resolution of 720 x 480 or 640 x 480 (480p)
68      * pixels.
69      */
70     @NonNull
71     public static final Quality SD = ConstantQuality.of(
72             QUALITY_480P,
73             QUALITY_HIGH_SPEED_480P,
74             "SD",
75             unmodifiableList(asList(new Size(720, 480), new Size(640, 480))
76             ));
77 
78     /**
79      * High Definition (HD) video quality.
80      *
81      * <p>This video quality usually corresponds to a resolution of 1280 x 720 (720p) pixels.
82      */
83     @NonNull
84     public static final Quality HD = ConstantQuality.of(
85             QUALITY_720P,
86             QUALITY_HIGH_SPEED_720P,
87             "HD",
88             singletonList(new Size(1280, 720)
89             ));
90 
91     /**
92      * Full High Definition (FHD) 1080p video quality.
93      *
94      * <p>This video quality usually corresponds to a resolution of 1920 x 1080 (1080p) pixels.
95      */
96     @NonNull
97     public static final Quality FHD = ConstantQuality.of(
98             QUALITY_1080P,
99             QUALITY_HIGH_SPEED_1080P,
100             "FHD",
101             singletonList(new Size(1920, 1080)
102             ));
103 
104     /**
105      * Ultra High Definition (UHD) 2160p video quality.
106      *
107      * <p>This video quality usually corresponds to a resolution of 3840 x 2160 (2160p) pixels.
108      */
109     @NonNull
110     public static final Quality UHD = ConstantQuality.of(
111             QUALITY_2160P,
112             QUALITY_HIGH_SPEED_2160P,
113             "UHD",
114             singletonList(new Size(3840, 2160)
115             ));
116 
117     /**
118      * The lowest video quality supported by the video frame producer.
119      */
120     @NonNull
121     public static final Quality LOWEST = ConstantQuality.of(
122             QUALITY_LOW,
123             QUALITY_HIGH_SPEED_LOW,
124             "LOWEST",
125             emptyList()
126     );
127 
128     /**
129      * The highest video quality supported by the video frame producer.
130      */
131     @NonNull
132     public static final Quality HIGHEST = ConstantQuality.of(
133             QUALITY_HIGH,
134             QUALITY_HIGH_SPEED_HIGH,
135             "HIGHEST",
136             emptyList()
137     );
138 
139     static final Quality NONE = ConstantQuality.of(-1, -1, "NONE", emptyList());
140 
141     /** All quality constants. */
142     private static final Set<Quality> QUALITIES =
143             new HashSet<>(asList(LOWEST, HIGHEST, SD, HD, FHD, UHD));
144 
145     /** Quality constants with size from large to small. */
146     private static final List<Quality> QUALITIES_ORDER_BY_SIZE = asList(UHD, FHD, HD, SD);
147 
containsQuality(@onNull Quality quality)148     static boolean containsQuality(@NonNull Quality quality) {
149         return QUALITIES.contains(quality);
150     }
151 
152     @RestrictTo(RestrictTo.Scope.LIBRARY)
153     public static final int QUALITY_SOURCE_REGULAR = 1;
154 
155     @RestrictTo(RestrictTo.Scope.LIBRARY)
156     public static final int QUALITY_SOURCE_HIGH_SPEED = 2;
157 
158     @IntDef({QUALITY_SOURCE_REGULAR, QUALITY_SOURCE_HIGH_SPEED})
159     @Retention(RetentionPolicy.SOURCE)
160     @RestrictTo(RestrictTo.Scope.LIBRARY)
161     public @interface QualitySource {
162     }
163 
164     /**
165      * Gets all video quality constants with clearly defined size sorted from largest to smallest.
166      *
167      * <p>{@link #HIGHEST} and {@link #LOWEST} are not included.
168      */
169     @RestrictTo(Scope.LIBRARY)
getSortedQualities()170     public static @NonNull List<Quality> getSortedQualities() {
171         return new ArrayList<>(QUALITIES_ORDER_BY_SIZE);
172     }
173 
174     @RestrictTo(Scope.LIBRARY)
175     @AutoValue
176     public abstract static class ConstantQuality extends Quality {
of(int value, int highSpeedValue, @NonNull String name, @NonNull List<Size> typicalSizes)177         static ConstantQuality of(int value, int highSpeedValue, @NonNull String name,
178                 @NonNull List<Size> typicalSizes) {
179             return new AutoValue_Quality_ConstantQuality(value, highSpeedValue, name, typicalSizes);
180         }
181 
182         /** Gets the quality value corresponding to CamcorderProfile quality constant. */
getValue()183         abstract int getValue();
184 
185         /** Gets the quality value corresponding to CamcorderProfile high speed quality constant. */
getHighSpeedValue()186         abstract int getHighSpeedValue();
187 
188         /** Gets the quality name. */
getName()189         public abstract @NonNull String getName();
190 
191         /** Gets the typical sizes of the quality. */
192         @SuppressWarnings("AutoValueImmutableFields")
getTypicalSizes()193         public abstract @NonNull List<Size> getTypicalSizes();
194 
195         /** Gets the quality value for the given quality source. */
getQualityValue(@ualitySource int qualitySource)196         public int getQualityValue(@QualitySource int qualitySource) {
197             switch (qualitySource) {
198                 case QUALITY_SOURCE_REGULAR:
199                     return getValue();
200                 case QUALITY_SOURCE_HIGH_SPEED:
201                     return getHighSpeedValue();
202                 default:
203                     throw new AssertionError("Unknown quality source: " + qualitySource);
204 
205             }
206         }
207     }
208 }
209