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.camera2.pipe.config 18 19 import android.content.Context 20 import androidx.camera.camera2.pipe.CameraBackend 21 import androidx.camera.camera2.pipe.CameraBackends 22 import androidx.camera.camera2.pipe.CameraContext 23 import androidx.camera.camera2.pipe.CameraController 24 import androidx.camera.camera2.pipe.CameraGraph 25 import androidx.camera.camera2.pipe.CameraGraphId 26 import androidx.camera.camera2.pipe.CameraMetadata 27 import androidx.camera.camera2.pipe.CameraSurfaceManager 28 import androidx.camera.camera2.pipe.Request 29 import androidx.camera.camera2.pipe.StreamGraph 30 import androidx.camera.camera2.pipe.SurfaceTracker 31 import androidx.camera.camera2.pipe.core.Threads 32 import androidx.camera.camera2.pipe.graph.CameraGraphImpl 33 import androidx.camera.camera2.pipe.graph.GraphListener 34 import androidx.camera.camera2.pipe.graph.GraphProcessor 35 import androidx.camera.camera2.pipe.graph.GraphProcessorImpl 36 import androidx.camera.camera2.pipe.graph.Listener3A 37 import androidx.camera.camera2.pipe.graph.StreamGraphImpl 38 import androidx.camera.camera2.pipe.graph.SurfaceGraph 39 import androidx.camera.camera2.pipe.internal.CameraGraphParametersImpl 40 import androidx.camera.camera2.pipe.internal.FrameCaptureQueue 41 import androidx.camera.camera2.pipe.internal.FrameDistributor 42 import androidx.camera.camera2.pipe.internal.ImageSourceMap 43 import dagger.Binds 44 import dagger.Module 45 import dagger.Provides 46 import dagger.Subcomponent 47 import javax.inject.Provider 48 import javax.inject.Qualifier 49 import javax.inject.Scope 50 import kotlinx.coroutines.CoroutineName 51 import kotlinx.coroutines.CoroutineScope 52 53 @Scope internal annotation class CameraGraphScope 54 55 @Qualifier internal annotation class ForCameraGraph 56 57 @Qualifier internal annotation class CameraGraphContext 58 59 @CameraGraphScope 60 @Subcomponent( 61 modules = 62 [ 63 SharedCameraGraphModules::class, 64 InternalCameraGraphModules::class, 65 CameraGraphConfigModule::class, 66 ] 67 ) 68 internal interface CameraGraphComponent { cameraGraphnull69 fun cameraGraph(): CameraGraph 70 71 @Subcomponent.Builder 72 interface Builder { 73 fun cameraGraphConfigModule(config: CameraGraphConfigModule): Builder 74 75 fun build(): CameraGraphComponent 76 } 77 } 78 79 @Module 80 internal class CameraGraphConfigModule(private val config: CameraGraph.Config) { provideCameraGraphConfignull81 @Provides fun provideCameraGraphConfig(): CameraGraph.Config = config 82 } 83 84 @Module 85 internal abstract class SharedCameraGraphModules { 86 @Binds abstract fun bindCameraGraph(cameraGraph: CameraGraphImpl): CameraGraph 87 88 @Binds abstract fun bindGraphProcessor(graphProcessor: GraphProcessorImpl): GraphProcessor 89 90 @Binds abstract fun bindGraphListener(graphProcessor: GraphProcessorImpl): GraphListener 91 92 @Binds 93 @CameraGraphContext 94 abstract fun bindCameraGraphContext(@CameraPipeContext cameraPipeContext: Context): Context 95 96 @Binds abstract fun bindStreamGraph(streamGraph: StreamGraphImpl): StreamGraph 97 98 @CameraGraphScope 99 @Binds 100 abstract fun bindSurfaceTracker(surfaceGraph: SurfaceGraph): SurfaceTracker 101 102 @Binds 103 abstract fun bindCameraGraphParameters( 104 parameters: CameraGraphParametersImpl 105 ): CameraGraph.Parameters 106 107 companion object { 108 @CameraGraphScope 109 @Provides 110 fun provideCameraGraphId(): CameraGraphId { 111 return CameraGraphId.nextId() 112 } 113 114 @CameraGraphScope 115 @Provides 116 @ForCameraGraph 117 fun provideCameraGraphCoroutineScope(threads: Threads): CoroutineScope { 118 return CoroutineScope(threads.lightweightDispatcher.plus(CoroutineName("CXCP-Graph"))) 119 } 120 121 @CameraGraphScope 122 @Provides 123 @ForCameraGraph 124 fun provideRequestListeners( 125 graphConfig: CameraGraph.Config, 126 listener3A: Listener3A, 127 frameDistributor: FrameDistributor 128 ): List<@JvmSuppressWildcards Request.Listener> { 129 val listeners = mutableListOf<Request.Listener>(listener3A) 130 131 // Order slightly matters, add internal listeners first, and external listeners second. 132 listeners.add(listener3A) 133 134 // FrameDistributor is responsible for all image grouping and distribution. 135 listeners.add(frameDistributor) 136 137 // Listeners in CameraGraph.Config can de defined outside of the CameraPipe library, 138 // and since we iterate thought the listeners in order and invoke them, it appears 139 // beneficial to add the internal listeners first and then the graph config listeners. 140 listeners.addAll(graphConfig.defaultListeners) 141 return listeners 142 } 143 144 @CameraGraphScope 145 @Provides 146 fun provideSurfaceGraph( 147 streamGraphImpl: StreamGraphImpl, 148 cameraController: Provider<CameraController>, 149 cameraSurfaceManager: CameraSurfaceManager, 150 imageSourceMap: ImageSourceMap 151 ): SurfaceGraph { 152 return SurfaceGraph( 153 streamGraphImpl, 154 cameraController, 155 cameraSurfaceManager, 156 imageSourceMap.imageSources 157 ) 158 } 159 160 @CameraGraphScope 161 @Provides 162 fun provideFrameDistributor( 163 imageSourceMap: ImageSourceMap, 164 frameCaptureQueue: FrameCaptureQueue 165 ): FrameDistributor { 166 return FrameDistributor(imageSourceMap.imageSources, frameCaptureQueue) {} 167 } 168 } 169 } 170 171 @Module 172 internal abstract class InternalCameraGraphModules { 173 companion object { 174 @CameraGraphScope 175 @Provides provideCameraBackendnull176 fun provideCameraBackend( 177 cameraBackends: CameraBackends, 178 graphConfig: CameraGraph.Config, 179 cameraContext: CameraContext 180 ): CameraBackend { 181 val customCameraBackend = graphConfig.customCameraBackend 182 if (customCameraBackend != null) { 183 return customCameraBackend.create(cameraContext) 184 } 185 186 val cameraBackendId = graphConfig.cameraBackendId 187 if (cameraBackendId != null) { 188 return checkNotNull(cameraBackends[cameraBackendId]) { 189 "Failed to initialize $cameraBackendId from $graphConfig" 190 } 191 } 192 return cameraBackends.default 193 } 194 195 @CameraGraphScope 196 @Provides provideCameraMetadatanull197 fun provideCameraMetadata( 198 graphConfig: CameraGraph.Config, 199 cameraBackend: CameraBackend 200 ): CameraMetadata { 201 // TODO: It might be a good idea to cache and go through caches for some of these calls 202 // instead of reading it directly from the backend. 203 return checkNotNull(cameraBackend.awaitCameraMetadata(graphConfig.camera)) { 204 "Failed to load metadata for ${graphConfig.camera}!" 205 } 206 } 207 208 @CameraGraphScope 209 @Provides provideCameraControllernull210 fun provideCameraController( 211 graphId: CameraGraphId, 212 graphConfig: CameraGraph.Config, 213 cameraBackend: CameraBackend, 214 cameraContext: CameraContext, 215 graphProcessor: GraphProcessorImpl, 216 streamGraph: StreamGraph, 217 surfaceTracker: SurfaceTracker, 218 ): CameraController { 219 return cameraBackend.createCameraController( 220 cameraContext, 221 graphId, 222 graphConfig, 223 graphProcessor, 224 streamGraph, 225 surfaceTracker, 226 ) 227 } 228 } 229 } 230