1 /* 2 * Copyright 2025 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.extensions.internal.sessionprocessor 18 19 import android.hardware.camera2.CameraCharacteristics 20 import android.hardware.camera2.CaptureRequest 21 import android.hardware.camera2.CaptureResult 22 import android.os.Build 23 import android.util.Pair 24 import android.util.Size 25 import androidx.annotation.GuardedBy 26 import androidx.annotation.RequiresApi 27 import androidx.camera.core.CameraInfo 28 import androidx.camera.core.impl.AdapterCameraInfo 29 import androidx.camera.core.impl.CameraCaptureCallback 30 import androidx.camera.core.impl.CameraCaptureResult 31 import androidx.camera.core.impl.CameraInfoInternal 32 import androidx.camera.core.impl.Config 33 import androidx.camera.core.impl.OutputSurfaceConfiguration 34 import androidx.camera.core.impl.RequestProcessor 35 import androidx.camera.core.impl.SessionConfig 36 import androidx.camera.core.impl.SessionProcessor 37 import androidx.camera.core.impl.SessionProcessor.CaptureSessionRequestProcessor 38 import androidx.camera.core.impl.TagBundle 39 import androidx.camera.core.impl.utils.executor.CameraXExecutors 40 import androidx.camera.extensions.CameraExtensionsControl 41 import androidx.camera.extensions.CameraExtensionsInfo 42 import androidx.camera.extensions.ExtensionMode 43 import androidx.camera.extensions.internal.Camera2ExtensionsUtil.convertCamera2ModeToCameraXMode 44 import androidx.camera.extensions.internal.Camera2ExtensionsUtil.convertCameraXModeToCamera2Mode 45 import androidx.camera.extensions.internal.ExtensionsUtils 46 import androidx.camera.extensions.internal.VendorExtender 47 import androidx.lifecycle.LiveData 48 import androidx.lifecycle.MutableLiveData 49 import java.util.concurrent.atomic.AtomicInteger 50 51 @RequiresApi(31) 52 public class Camera2ExtensionsSessionProcessor( 53 private val availableCaptureRequestKeys: List<CaptureRequest.Key<*>>, 54 @ExtensionMode.Mode private val mode: Int, 55 private val vendorExtender: VendorExtender 56 ) : SessionProcessor, CameraExtensionsInfo, CameraExtensionsControl { 57 58 private val camera2ExtensionMode = convertCameraXModeToCamera2Mode(mode) 59 60 private var extensionStrengthLiveData: MutableLiveData<Int>? = null 61 private var currentExtensionTypeLiveData: MutableLiveData<Int>? = null 62 private val extensionStrength: AtomicInteger = AtomicInteger(100) 63 private val currentExtensionType: AtomicInteger = AtomicInteger(mode) 64 65 @AdapterCameraInfo.CameraOperation 66 private val supportedCameraOperations: Set<Int> = 67 ExtensionsUtils.getSupportedCameraOperations(availableCaptureRequestKeys) 68 69 private var cameraInfoInternal: CameraInfoInternal? = null 70 private var cameraCaptureCallback: CameraCaptureCallback? = null 71 72 private val lock = Any() 73 74 @GuardedBy("lock") 75 private var captureSessionRequestProcessor: CaptureSessionRequestProcessor? = null 76 77 init { 78 if (isCurrentExtensionModeAvailable()) { 79 currentExtensionTypeLiveData = MutableLiveData<Int>(mode) 80 } 81 if (isExtensionStrengthAvailable()) { 82 extensionStrengthLiveData = MutableLiveData<Int>(100) 83 } 84 } 85 initSessionnull86 override fun initSession( 87 cameraInfo: CameraInfo, 88 outputSurfaceConfig: OutputSurfaceConfiguration? 89 ): SessionConfig? { 90 cameraInfoInternal = cameraInfo as CameraInfoInternal 91 // Sets up the CameraCaptureCallback to receive the extensions related info 92 cameraCaptureCallback = 93 object : CameraCaptureCallback() { 94 override fun onCaptureCompleted( 95 captureConfigId: Int, 96 cameraCaptureResult: CameraCaptureResult 97 ) { 98 if ( 99 Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE && 100 isCurrentExtensionModeAvailable() 101 ) { 102 cameraCaptureResult.captureResult 103 ?.get(CaptureResult.EXTENSION_CURRENT_TYPE) 104 ?.let { 105 val cameraXMode = convertCamera2ModeToCameraXMode(it) 106 if (currentExtensionType.getAndSet(cameraXMode) != cameraXMode) { 107 extensionStrengthLiveData?.postValue(it) 108 } 109 } 110 } 111 112 if ( 113 Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE && 114 isExtensionStrengthAvailable() 115 ) { 116 cameraCaptureResult.captureResult 117 ?.get(CaptureResult.EXTENSION_STRENGTH) 118 ?.let { 119 if (extensionStrength.getAndSet(it) != it) { 120 extensionStrengthLiveData?.postValue(it) 121 } 122 } 123 } 124 } 125 } 126 127 cameraInfoInternal!!.addSessionCaptureCallback( 128 CameraXExecutors.directExecutor(), 129 cameraCaptureCallback!! 130 ) 131 132 return null 133 } 134 deInitSessionnull135 override fun deInitSession() { 136 cameraInfoInternal?.apply { 137 cameraCaptureCallback?.let { removeSessionCaptureCallback(it) } 138 } 139 } 140 getSupportedPostviewSizenull141 override fun getSupportedPostviewSize(captureSize: Size): Map<Int, List<Size>> { 142 return vendorExtender.getSupportedPostviewResolutions(captureSize) 143 } 144 getSupportedCameraOperationsnull145 override fun getSupportedCameraOperations(): Set<Int> { 146 return supportedCameraOperations 147 } 148 getAvailableCharacteristicsKeyValuesnull149 override fun getAvailableCharacteristicsKeyValues(): 150 List<Pair<CameraCharacteristics.Key<*>, in Any>> { 151 return vendorExtender.availableCharacteristicsKeyValues 152 } 153 getExtensionAvailableStabilizationModesnull154 override fun getExtensionAvailableStabilizationModes(): IntArray? { 155 return super.getExtensionAvailableStabilizationModes() 156 } 157 getImplementationTypenull158 override fun getImplementationType(): Pair<Int, Int> { 159 return Pair.create(SessionProcessor.TYPE_CAMERA2_EXTENSION, camera2ExtensionMode) 160 } 161 setParametersnull162 override fun setParameters(config: Config) { 163 throw UnsupportedOperationException( 164 "Camera2ExtensionsSessionProcessor#setParameters should not be invoked!" 165 ) 166 } 167 onCaptureSessionStartnull168 override fun onCaptureSessionStart(requestProcessor: RequestProcessor) { 169 throw UnsupportedOperationException( 170 "Camera2ExtensionsSessionProcessor#onCaptureSessionStart should not be invoked!" 171 ) 172 } 173 onCaptureSessionEndnull174 override fun onCaptureSessionEnd() { 175 throw UnsupportedOperationException( 176 "Camera2ExtensionsSessionProcessor#onCaptureSessionEnd should not be invoked!" 177 ) 178 } 179 startRepeatingnull180 override fun startRepeating( 181 tagBundle: TagBundle, 182 callback: SessionProcessor.CaptureCallback 183 ): Int { 184 throw UnsupportedOperationException( 185 "Camera2ExtensionsSessionProcessor#startRepeating should not be invoked!" 186 ) 187 } 188 stopRepeatingnull189 override fun stopRepeating() { 190 throw UnsupportedOperationException( 191 "Camera2ExtensionsSessionProcessor#stopRepeating should not be invoked!" 192 ) 193 } 194 startCapturenull195 override fun startCapture( 196 postviewEnabled: Boolean, 197 tagBundle: TagBundle, 198 callback: SessionProcessor.CaptureCallback 199 ): Int { 200 throw UnsupportedOperationException( 201 "Camera2ExtensionsSessionProcessor#startCapture should not be invoked!" 202 ) 203 } 204 abortCapturenull205 override fun abortCapture(captureSequenceId: Int) { 206 throw UnsupportedOperationException( 207 "Camera2ExtensionsSessionProcessor#abortCapture should not be invoked!" 208 ) 209 } 210 isExtensionStrengthAvailablenull211 override fun isExtensionStrengthAvailable(): Boolean = 212 vendorExtender.isExtensionStrengthAvailable 213 214 override fun getExtensionStrength(): LiveData<Int>? = extensionStrengthLiveData 215 216 override fun isCurrentExtensionModeAvailable(): Boolean = 217 vendorExtender.isCurrentExtensionModeAvailable 218 219 override fun getCurrentExtensionMode(): LiveData<Int>? = currentExtensionTypeLiveData 220 221 override fun getRealtimeCaptureLatency(): Pair<Long, Long>? { 222 synchronized(lock) { 223 return captureSessionRequestProcessor?.realtimeStillCaptureLatency 224 } 225 } 226 setExtensionStrengthnull227 override fun setExtensionStrength(strength: Int) { 228 synchronized(lock) { captureSessionRequestProcessor?.setExtensionStrength(strength) } 229 } 230 setCaptureSessionRequestProcessornull231 override fun setCaptureSessionRequestProcessor(processor: CaptureSessionRequestProcessor?) { 232 synchronized(lock) { captureSessionRequestProcessor = processor } 233 } 234 } 235