1 /* 2 * Copyright 2022 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.integration.core.util 18 19 import android.hardware.camera2.CameraCaptureSession 20 import android.hardware.camera2.CameraCharacteristics 21 import android.hardware.camera2.CameraDevice 22 import android.hardware.camera2.CaptureRequest 23 import android.os.Build 24 import androidx.annotation.OptIn 25 import androidx.camera.camera2.Camera2Config 26 import androidx.camera.camera2.interop.Camera2CameraControl 27 import androidx.camera.camera2.interop.Camera2CameraInfo 28 import androidx.camera.camera2.interop.Camera2Interop 29 import androidx.camera.camera2.interop.CaptureRequestOptions 30 import androidx.camera.camera2.interop.ExperimentalCamera2Interop 31 import androidx.camera.camera2.pipe.integration.CameraPipeConfig 32 import androidx.camera.camera2.pipe.integration.interop.Camera2CameraControl as CPCamera2CameraControl 33 import androidx.camera.camera2.pipe.integration.interop.Camera2CameraInfo as CPCamera2CameraInfo 34 import androidx.camera.camera2.pipe.integration.interop.Camera2Interop as CPCamera2Interop 35 import androidx.camera.camera2.pipe.integration.interop.CaptureRequestOptions as CPCaptureRequestOptions 36 import androidx.camera.camera2.pipe.integration.interop.ExperimentalCamera2Interop as CPExperimentalCamera2Interop 37 import androidx.camera.core.CameraControl 38 import androidx.camera.core.CameraInfo 39 import androidx.camera.core.ExtendableBuilder 40 import com.google.common.util.concurrent.ListenableFuture 41 42 @kotlin.OptIn(CPExperimentalCamera2Interop::class) 43 @OptIn(markerClass = [ExperimentalCamera2Interop::class]) 44 object Camera2InteropUtil { 45 46 @JvmStatic setCamera2InteropOptionsnull47 fun <T> setCamera2InteropOptions( 48 implName: String, 49 builder: ExtendableBuilder<T>, 50 captureCallback: CameraCaptureSession.CaptureCallback? = null, 51 deviceStateCallback: CameraDevice.StateCallback? = null, 52 sessionStateCallback: CameraCaptureSession.StateCallback? = null, 53 physicalCameraId: String? = null 54 ) { 55 if (implName == CameraPipeConfig::class.simpleName) { 56 val extendedBuilder = CPCamera2Interop.Extender(builder) 57 captureCallback?.let { extendedBuilder.setSessionCaptureCallback(it) } 58 deviceStateCallback?.let { extendedBuilder.setDeviceStateCallback(it) } 59 sessionStateCallback?.let { extendedBuilder.setSessionStateCallback(it) } 60 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && physicalCameraId != null) { 61 extendedBuilder.setPhysicalCameraId(physicalCameraId) 62 } 63 } else { 64 val extendedBuilder = Camera2Interop.Extender(builder) 65 captureCallback?.let { extendedBuilder.setSessionCaptureCallback(it) } 66 deviceStateCallback?.let { extendedBuilder.setDeviceStateCallback(it) } 67 sessionStateCallback?.let { extendedBuilder.setSessionStateCallback(it) } 68 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && physicalCameraId != null) { 69 extendedBuilder.setPhysicalCameraId(physicalCameraId) 70 } 71 } 72 } 73 74 @JvmStatic setCameraCaptureSessionCallbacknull75 fun <T> setCameraCaptureSessionCallback( 76 implName: String, 77 builder: ExtendableBuilder<T>, 78 captureCallback: CameraCaptureSession.CaptureCallback 79 ) { 80 setCamera2InteropOptions( 81 implName = implName, 82 builder = builder, 83 captureCallback = captureCallback 84 ) 85 } 86 87 @JvmStatic setDeviceStateCallbacknull88 fun <T> setDeviceStateCallback( 89 implName: String, 90 builder: ExtendableBuilder<T>, 91 stateCallback: CameraDevice.StateCallback 92 ) { 93 setCamera2InteropOptions( 94 implName = implName, 95 builder = builder, 96 deviceStateCallback = stateCallback 97 ) 98 } 99 100 @JvmStatic setSessionStateCallbacknull101 fun <T> setSessionStateCallback( 102 implName: String, 103 builder: ExtendableBuilder<T>, 104 stateCallback: CameraCaptureSession.StateCallback 105 ) { 106 setCamera2InteropOptions( 107 implName = implName, 108 builder = builder, 109 sessionStateCallback = stateCallback 110 ) 111 } 112 113 @JvmStatic getCameraIdnull114 fun getCameraId(implName: String, cameraInfo: CameraInfo): String = 115 if (implName == CameraPipeConfig::class.simpleName) { 116 CPCamera2CameraInfo.from(cameraInfo).getCameraId() 117 } else { 118 Camera2CameraInfo.from(cameraInfo).cameraId 119 } 120 121 @JvmStatic getCamera2CameraInfoCharacteristicsnull122 fun <T> getCamera2CameraInfoCharacteristics( 123 implName: String, 124 cameraInfo: CameraInfo, 125 key: CameraCharacteristics.Key<T> 126 ): T? = 127 if (implName == Camera2Config::class.simpleName) { 128 Camera2CameraInfo.from(cameraInfo).getCameraCharacteristic(key) 129 } else { 130 CPCamera2CameraInfo.from(cameraInfo).getCameraCharacteristic(key) 131 } 132 133 interface Camera2CameraInfoWrapper { getCameraCharacteristicnull134 fun <T> getCameraCharacteristic(key: CameraCharacteristics.Key<T>): T? 135 136 companion object 137 } 138 139 interface Camera2CameraControlWrapper { 140 fun setCaptureRequestOptions(bundle: CaptureRequestOptionsWrapper): ListenableFuture<Void?> 141 142 fun clearCaptureRequestOptions(): ListenableFuture<Void?> 143 144 companion object 145 } 146 147 @JvmStatic Camera2CameraInfoWrappernull148 fun Camera2CameraInfoWrapper.Companion.from( 149 implName: String, 150 cameraInfo: CameraInfo 151 ): Camera2CameraInfoWrapper { 152 return when (implName) { 153 CameraPipeConfig::class.simpleName -> 154 object : Camera2CameraInfoWrapper { 155 private val wrappedCameraInfo = CPCamera2CameraInfo.from(cameraInfo) 156 157 override fun <T> getCameraCharacteristic( 158 key: CameraCharacteristics.Key<T> 159 ): T? { 160 return wrappedCameraInfo.getCameraCharacteristic(key) 161 } 162 } 163 Camera2Config::class.simpleName -> 164 object : Camera2CameraInfoWrapper { 165 private val wrappedCameraInfo = Camera2CameraInfo.from(cameraInfo) 166 167 override fun <T> getCameraCharacteristic( 168 key: CameraCharacteristics.Key<T> 169 ): T? { 170 return wrappedCameraInfo.getCameraCharacteristic(key) 171 } 172 } 173 else -> throw IllegalArgumentException("Unexpected implementation: $implName") 174 } 175 } 176 177 interface CaptureRequestOptionsWrapper { 178 unwrapnull179 fun unwrap(): Any 180 181 interface Builder { 182 fun <ValueT : Any> setCaptureRequestOption( 183 key: CaptureRequest.Key<ValueT>, 184 value: ValueT 185 ): Builder 186 187 fun build(): CaptureRequestOptionsWrapper 188 } 189 190 companion object 191 } 192 193 @JvmStatic CaptureRequestOptionsWrappernull194 fun CaptureRequestOptionsWrapper.Companion.builder( 195 implName: String 196 ): CaptureRequestOptionsWrapper.Builder { 197 return when (implName) { 198 CameraPipeConfig::class.simpleName -> 199 object : CaptureRequestOptionsWrapper.Builder { 200 private val wrappedBuilder = CPCaptureRequestOptions.Builder() 201 202 override fun <ValueT : Any> setCaptureRequestOption( 203 key: CaptureRequest.Key<ValueT>, 204 value: ValueT 205 ): CaptureRequestOptionsWrapper.Builder { 206 wrappedBuilder.setCaptureRequestOption(key, value) 207 return this 208 } 209 210 override fun build(): CaptureRequestOptionsWrapper { 211 val wrappedOptions = wrappedBuilder.build() 212 return object : CaptureRequestOptionsWrapper { 213 override fun unwrap() = wrappedOptions 214 } 215 } 216 } 217 Camera2Config::class.simpleName -> 218 object : CaptureRequestOptionsWrapper.Builder { 219 private val wrappedBuilder = CaptureRequestOptions.Builder() 220 221 override fun <ValueT : Any> setCaptureRequestOption( 222 key: CaptureRequest.Key<ValueT>, 223 value: ValueT 224 ): CaptureRequestOptionsWrapper.Builder { 225 wrappedBuilder.setCaptureRequestOption(key, value) 226 return this 227 } 228 229 override fun build(): CaptureRequestOptionsWrapper { 230 val wrappedOptions = wrappedBuilder.build() 231 return object : CaptureRequestOptionsWrapper { 232 override fun unwrap() = wrappedOptions 233 } 234 } 235 } 236 else -> throw IllegalArgumentException("Unexpected implementation: $implName") 237 } 238 } 239 240 @JvmStatic fromnull241 fun Camera2CameraControlWrapper.Companion.from( 242 implName: String, 243 cameraControl: CameraControl 244 ): Camera2CameraControlWrapper { 245 return when (implName) { 246 CameraPipeConfig::class.simpleName -> 247 object : Camera2CameraControlWrapper { 248 private val wrappedCameraControl = CPCamera2CameraControl.from(cameraControl) 249 250 override fun setCaptureRequestOptions( 251 bundle: CaptureRequestOptionsWrapper 252 ): ListenableFuture<Void?> { 253 return wrappedCameraControl.setCaptureRequestOptions( 254 bundle.unwrap() as CPCaptureRequestOptions 255 ) 256 } 257 258 override fun clearCaptureRequestOptions(): ListenableFuture<Void?> { 259 return wrappedCameraControl.clearCaptureRequestOptions() 260 } 261 } 262 Camera2Config::class.simpleName -> 263 object : Camera2CameraControlWrapper { 264 private val wrappedCameraControl = Camera2CameraControl.from(cameraControl) 265 266 override fun setCaptureRequestOptions( 267 bundle: CaptureRequestOptionsWrapper 268 ): ListenableFuture<Void?> { 269 return wrappedCameraControl.setCaptureRequestOptions( 270 bundle.unwrap() as CaptureRequestOptions 271 ) 272 } 273 274 override fun clearCaptureRequestOptions(): ListenableFuture<Void?> { 275 return wrappedCameraControl.clearCaptureRequestOptions() 276 } 277 } 278 else -> throw IllegalArgumentException("Unexpected implementation: $implName") 279 } 280 } 281 } 282