1 /* 2 * Copyright 2019 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 static androidx.camera.core.impl.CameraMode.ULTRA_HIGH_RESOLUTION_CAMERA; 20 21 import android.graphics.ImageFormat; 22 import android.hardware.camera2.CameraCaptureSession.StateCallback; 23 import android.os.Handler; 24 import android.util.Size; 25 26 import androidx.camera.core.internal.utils.SizeUtil; 27 28 import com.google.auto.value.AutoValue; 29 30 import org.jspecify.annotations.NonNull; 31 32 import java.util.List; 33 34 /** 35 * Surface configuration type and size pair 36 * 37 * <p>{@link android.hardware.camera2.CameraDevice#createCaptureSession} defines the default 38 * guaranteed stream combinations for different hardware level devices. It defines what combination 39 * of surface configuration type and size pairs can be supported for different hardware level camera 40 * devices. 41 */ 42 @AutoValue 43 public abstract class SurfaceConfig { 44 public static final long DEFAULT_STREAM_USE_CASE_VALUE = 0; 45 /** Prevent subclassing */ SurfaceConfig()46 SurfaceConfig() { 47 } 48 49 /** 50 * Creates a new instance of SurfaceConfig with the given parameters. 51 */ create(@onNull ConfigType type, @NonNull ConfigSize size)52 public static @NonNull SurfaceConfig create(@NonNull ConfigType type, 53 @NonNull ConfigSize size) { 54 return new AutoValue_SurfaceConfig(type, size, DEFAULT_STREAM_USE_CASE_VALUE); 55 } 56 57 /** 58 * Creates a new instance of SurfaceConfig with the given parameters. 59 */ create(@onNull ConfigType type, @NonNull ConfigSize size, long streamUseCase)60 public static @NonNull SurfaceConfig create(@NonNull ConfigType type, @NonNull ConfigSize size, 61 long streamUseCase) { 62 return new AutoValue_SurfaceConfig(type, size, streamUseCase); 63 } 64 65 /** Returns the configuration type. */ getConfigType()66 public abstract @NonNull ConfigType getConfigType(); 67 68 /** Returns the configuration size. */ getConfigSize()69 public abstract @NonNull ConfigSize getConfigSize(); 70 71 /** 72 * Returns the stream use case. 73 * <p>Stream use case constants are implementation-specific constants that allow the 74 * implementation to optimize power and quality characteristics of a stream depending on how 75 * it will be used. 76 * <p> Stream use case is an int flag used to specify the purpose of the stream associated 77 * with this surface. Use cases for the camera2 implementation that are available on devices can 78 * be found in 79 * {@link android.hardware.camera2.CameraCharacteristics#SCALER_AVAILABLE_STREAM_USE_CASES} 80 * 81 * <p>See {@link android.hardware.camera2.params.OutputConfiguration#setStreamUseCase} 82 * to see how Camera2 framework uses this. 83 */ getStreamUseCase()84 public abstract long getStreamUseCase(); 85 86 /** 87 * Check whether the input surface configuration has a smaller size than this object and can be 88 * supported 89 * 90 * @param surfaceConfig the surface configuration to be compared 91 * @return the check result that whether it could be supported 92 */ isSupported(@onNull SurfaceConfig surfaceConfig)93 public final boolean isSupported(@NonNull SurfaceConfig surfaceConfig) { 94 boolean isSupported = false; 95 ConfigType configType = surfaceConfig.getConfigType(); 96 ConfigSize configSize = surfaceConfig.getConfigSize(); 97 98 // Check size and type to make sure it could be supported 99 if (configSize.getId() <= getConfigSize().getId() && configType == getConfigType()) { 100 isSupported = true; 101 } 102 return isSupported; 103 } 104 105 /** 106 * Gets {@link ConfigType} from image format. 107 * 108 * <p> PRIV refers to any target whose available sizes are found using 109 * StreamConfigurationMap.getOutputSizes(Class) with no direct application-visible format, 110 * YUV refers to a target Surface using the ImageFormat.YUV_420_888 format, JPEG refers to 111 * the ImageFormat.JPEG or ImageFormat.JPEG_R format, and RAW refers to the 112 * ImageFormat.RAW_SENSOR format. 113 */ getConfigType(int imageFormat)114 public static SurfaceConfig.@NonNull ConfigType getConfigType(int imageFormat) { 115 if (imageFormat == ImageFormat.YUV_420_888) { 116 return SurfaceConfig.ConfigType.YUV; 117 } else if (imageFormat == ImageFormat.JPEG) { 118 return SurfaceConfig.ConfigType.JPEG; 119 } else if (imageFormat == ImageFormat.JPEG_R) { 120 return SurfaceConfig.ConfigType.JPEG_R; 121 } else if (imageFormat == ImageFormat.RAW_SENSOR) { 122 return SurfaceConfig.ConfigType.RAW; 123 } else { 124 return SurfaceConfig.ConfigType.PRIV; 125 } 126 } 127 128 /** 129 * Transform to a SurfaceConfig object with image format and size info 130 * 131 * @param cameraMode the working camera mode. 132 * @param imageFormat the image format info for the surface configuration object 133 * @param size the size info for the surface configuration object 134 * @param surfaceSizeDefinition the surface definition for the surface configuration object 135 * @return new {@link SurfaceConfig} object 136 */ transformSurfaceConfig( @ameraMode.Mode int cameraMode, int imageFormat, @NonNull Size size, @NonNull SurfaceSizeDefinition surfaceSizeDefinition)137 public static @NonNull SurfaceConfig transformSurfaceConfig( 138 @CameraMode.Mode int cameraMode, 139 int imageFormat, 140 @NonNull Size size, 141 @NonNull SurfaceSizeDefinition surfaceSizeDefinition) { 142 ConfigType configType = 143 SurfaceConfig.getConfigType(imageFormat); 144 ConfigSize configSize = ConfigSize.NOT_SUPPORT; 145 146 // Compare with surface size definition to determine the surface configuration size 147 int sizeArea = SizeUtil.getArea(size); 148 149 if (cameraMode == CameraMode.CONCURRENT_CAMERA) { 150 if (sizeArea <= SizeUtil.getArea(surfaceSizeDefinition.getS720pSize(imageFormat))) { 151 configSize = ConfigSize.s720p; 152 } else if (sizeArea <= SizeUtil.getArea(surfaceSizeDefinition.getS1440pSize( 153 imageFormat))) { 154 configSize = ConfigSize.s1440p; 155 } 156 } else { 157 if (sizeArea <= SizeUtil.getArea(surfaceSizeDefinition.getAnalysisSize())) { 158 configSize = ConfigSize.VGA; 159 } else if (sizeArea <= SizeUtil.getArea(surfaceSizeDefinition.getPreviewSize())) { 160 configSize = ConfigSize.PREVIEW; 161 } else if (sizeArea <= SizeUtil.getArea(surfaceSizeDefinition.getRecordSize())) { 162 configSize = ConfigSize.RECORD; 163 } else { 164 Size maximumSize = surfaceSizeDefinition.getMaximumSize(imageFormat); 165 Size ultraMaximumSize = surfaceSizeDefinition.getUltraMaximumSize(imageFormat); 166 // On some devices, when extensions is on, some extra formats might be supported 167 // for extensions. But those formats are not supported in the normal mode. In 168 // that case, MaximumSize could be null. Directly make configSize as MAXIMUM for 169 // the case. 170 if ((maximumSize == null || sizeArea <= SizeUtil.getArea(maximumSize)) 171 && cameraMode != ULTRA_HIGH_RESOLUTION_CAMERA) { 172 configSize = ConfigSize.MAXIMUM; 173 } else if (ultraMaximumSize != null && sizeArea <= SizeUtil.getArea( 174 ultraMaximumSize)) { 175 configSize = ConfigSize.ULTRA_MAXIMUM; 176 } 177 } 178 } 179 180 return SurfaceConfig.create(configType, configSize); 181 } 182 183 /** 184 * The Camera2 configuration type for the surface. 185 * 186 * <p>These are the enumerations defined in {@link 187 * android.hardware.camera2.CameraDevice#createCaptureSession(List, StateCallback, Handler)}. 188 */ 189 public enum ConfigType { 190 PRIV, 191 YUV, 192 JPEG, 193 JPEG_R, 194 RAW 195 } 196 197 /** 198 * The Camera2 stream sizes for the surface. 199 * 200 * <p>These are the enumerations defined in {@link 201 * android.hardware.camera2.CameraDevice#createCaptureSession(List, StateCallback, Handler)}. 202 */ 203 public enum ConfigSize { 204 /** Default VGA size is 640x480, which is the default size of Image Analysis. */ 205 VGA(0), 206 /** 207 * s720p refers to the best size match to the device's screen resolution, or to 720p 208 * (1280x720), whichever is smaller. 209 */ 210 s720p(1), 211 /** 212 * PREVIEW refers to the best size match to the device's screen resolution, or to 1080p 213 * (1920x1080), whichever is smaller. 214 */ 215 PREVIEW(2), 216 /** 217 * s1440p refers to the best size match to the device's screen resolution, or to 1440p 218 * (1920x1440), whichever is smaller. 219 */ 220 s1440p(3), 221 /** 222 * RECORD refers to the camera device's maximum supported recording resolution, as 223 * determined by CamcorderProfile. 224 */ 225 RECORD(4), 226 /** 227 * MAXIMUM refers to the camera device's maximum output resolution for that format or 228 * target from StreamConfigurationMap.getOutputSizes() or getHighResolutionOutputSizes() 229 * in the default sensor pixel mode. 230 */ 231 MAXIMUM(5), 232 /** 233 * ULTRA_MAXIMUM refers to the camera device's maximum output resolution for that format or 234 * target from StreamConfigurationMap.getOutputSizes() or getHighResolutionOutputSizes() 235 * in the maximum resolution sensor pixel mode. 236 */ 237 ULTRA_MAXIMUM(6), 238 /** NOT_SUPPORT is for the size larger than MAXIMUM */ 239 NOT_SUPPORT(7); 240 241 final int mId; 242 ConfigSize(int id)243 ConfigSize(int id) { 244 mId = id; 245 } 246 getId()247 int getId() { 248 return mId; 249 } 250 } 251 } 252