1
+ package com.foke.together.external.camera.internal
2
+
3
+ import android.content.Context
4
+ import android.graphics.Bitmap
5
+ import android.graphics.Matrix
6
+ import android.hardware.camera2.CaptureRequest
7
+ import android.os.SystemClock
8
+ import android.util.Log
9
+ import android.util.Range
10
+ import android.util.Size
11
+ import androidx.annotation.OptIn
12
+ import androidx.camera.camera2.Camera2Config
13
+ import androidx.camera.camera2.interop.Camera2Interop
14
+ import androidx.camera.camera2.interop.ExperimentalCamera2Interop
15
+ import androidx.camera.core.AspectRatio
16
+ import androidx.camera.core.CameraSelector
17
+ import androidx.camera.core.CameraXConfig
18
+ import androidx.camera.core.ImageAnalysis
19
+ import androidx.camera.lifecycle.ProcessCameraProvider
20
+ import dagger.Module
21
+ import dagger.Provides
22
+ import dagger.hilt.InstallIn
23
+ import dagger.hilt.components.SingletonComponent
24
+ import kotlinx.coroutines.flow.Flow
25
+ import kotlinx.coroutines.flow.flow
26
+ import java.util.concurrent.ExecutorService
27
+ import java.util.concurrent.Executors
28
+ import java.util.concurrent.TimeUnit
29
+ import javax.inject.Singleton
30
+
31
+ @Module
32
+ @InstallIn(SingletonComponent ::class )
33
+ object CameraModule {
34
+ private val TAG = CameraModule ::class .java.simpleName
35
+ private var cameraExecutorService : ExecutorService ? = null
36
+
37
+
38
+ // CameraX ImageAnalyzer용 백그라운드 서비스
39
+ @Provides
40
+ @Singleton
41
+ fun clearCameraExecutor (): Boolean {
42
+ cameraExecutorService?.shutdown()
43
+ cameraExecutorService?.awaitTermination(Long .MAX_VALUE , TimeUnit .NANOSECONDS )
44
+ cameraExecutorService = null
45
+ return cameraExecutorService == null
46
+ }
47
+
48
+ @Provides
49
+ @Singleton
50
+ fun provideCameraSelector (cameraIdx : Int ): CameraSelector {
51
+ return CameraSelector .Builder ()
52
+ .requireLensFacing(cameraIdx)
53
+ .build()
54
+ }
55
+
56
+ @Provides
57
+ @Singleton
58
+ fun provideCameraProvider (
59
+ context : Context ,
60
+ ): ProcessCameraProvider {
61
+ return ProcessCameraProvider .getInstance(context).get()
62
+ }
63
+
64
+ @OptIn(ExperimentalCamera2Interop ::class )
65
+ @Provides
66
+ @Singleton
67
+ fun provideImageAnalysis (
68
+ rotation : Int
69
+ ): ImageAnalysis {
70
+ val iaBuilder = ImageAnalysis .Builder ()
71
+ .setBackpressureStrategy(ImageAnalysis .STRATEGY_KEEP_ONLY_LATEST )
72
+ .setOutputImageFormat(ImageAnalysis .OUTPUT_IMAGE_FORMAT_RGBA_8888 )
73
+ .setTargetRotation(rotation)
74
+ .setTargetAspectRatio(AspectRatio .RATIO_4_3 )
75
+ return iaBuilder.build()
76
+ }
77
+
78
+ @Provides
79
+ @Singleton
80
+ fun provideCameraExecutor (): ExecutorService {
81
+ if (cameraExecutorService == null ){
82
+ cameraExecutorService = Executors .newSingleThreadExecutor()
83
+ }
84
+ return cameraExecutorService!!
85
+ }
86
+
87
+ fun shutdown (){
88
+ if (cameraExecutorService != null ) {
89
+ cameraExecutorService?.shutdown()
90
+ cameraExecutorService?.awaitTermination(Long .MAX_VALUE , TimeUnit .NANOSECONDS )
91
+ cameraExecutorService = null
92
+ }
93
+ }
94
+
95
+ @Provides
96
+ @Singleton
97
+ fun provideCameraXConfig (): CameraXConfig {
98
+ return CameraXConfig .Builder
99
+ .fromConfig(Camera2Config .defaultConfig())
100
+ .setMinimumLoggingLevel(Log .ERROR )
101
+ .build()
102
+ }
103
+
104
+ @Provides
105
+ @Singleton
106
+ fun provideCameraStatus (): Flow <Boolean > = flow {
107
+ emit(cameraExecutorService != null )
108
+ }
109
+
110
+ // 미디어 파이프 제공하기 위함
111
+ // @Provides
112
+ // @Singleton
113
+ // fun provideMPImageAnalyzer(
114
+ // handLandMarker: HandLandmarker,
115
+ // setCameraFrame: (Bitmap) -> Unit,
116
+ // cameraCropScale: Float = DEFAULT_CROP_SCALE,
117
+ // drawCameraInIndicator: Boolean = false
118
+ // ) = ImageAnalysis.Analyzer{ imageProxy ->
119
+ // val frameTime = SystemClock.uptimeMillis()
120
+ // // Copy out RGB bits from the frame to a bitmap buffer
121
+ // val bitmapBuffer =
122
+ // Bitmap.createBitmap(
123
+ // imageProxy.width,
124
+ // imageProxy.height,
125
+ // Bitmap.Config.ARGB_8888
126
+ // )
127
+ // imageProxy.use { bitmapBuffer.copyPixelsFromBuffer(imageProxy.planes[0].buffer) }
128
+ // imageProxy.close()
129
+ // val newWidth = imageProxy.width / cameraCropScale
130
+ // val newHeight = imageProxy.height / cameraCropScale
131
+ // val newX = ( imageProxy.width - newWidth ) / 2
132
+ // val newY = ( imageProxy.height - newHeight ) / 2
133
+ // // if crop scale = 1.0f , not use new bitmap
134
+ // var crop = bitmapBuffer
135
+ // if ( cameraCropScale > 1.5f ) {
136
+ // crop = Bitmap.createBitmap( bitmapBuffer, newX.toInt(), newY.toInt(), newWidth.toInt(), newHeight.toInt() )
137
+ // }
138
+ //
139
+ // // Convert the input Bitmap object to an MPImage object to run inference
140
+ // val mpImage = BitmapImageBuilder(crop).build()
141
+ // handLandMarker.detectAsync(mpImage, frameTime)
142
+ // }
143
+ }
0 commit comments