1 /* 2 * Copyright (C) 2023 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 package com.google.jetpackcamera.core.camera 17 18 import android.content.ContentResolver 19 import android.net.Uri 20 import androidx.camera.core.ImageCapture 21 import androidx.camera.core.SurfaceRequest 22 import com.google.jetpackcamera.settings.model.AspectRatio 23 import com.google.jetpackcamera.settings.model.CameraAppSettings 24 import com.google.jetpackcamera.settings.model.CaptureMode 25 import com.google.jetpackcamera.settings.model.ConcurrentCameraMode 26 import com.google.jetpackcamera.settings.model.DeviceRotation 27 import com.google.jetpackcamera.settings.model.DynamicRange 28 import com.google.jetpackcamera.settings.model.FlashMode 29 import com.google.jetpackcamera.settings.model.ImageOutputFormat 30 import com.google.jetpackcamera.settings.model.LensFacing 31 import com.google.jetpackcamera.settings.model.LowLightBoostState 32 import com.google.jetpackcamera.settings.model.StabilizationMode 33 import com.google.jetpackcamera.settings.model.StreamConfig 34 import com.google.jetpackcamera.settings.model.VideoQuality 35 import kotlinx.coroutines.channels.ReceiveChannel 36 import kotlinx.coroutines.flow.StateFlow 37 38 /** 39 * Data layer for camera. 40 */ 41 interface CameraUseCase { 42 /** 43 * Initializes the camera. 44 * 45 * @return list of available lenses. 46 */ initializenull47 suspend fun initialize( 48 cameraAppSettings: CameraAppSettings, 49 isDebugMode: Boolean = false, 50 cameraPropertiesJSONCallback: (result: String) -> Unit 51 ) 52 53 /** 54 * Starts the camera. 55 * 56 * This will start to configure the camera, but frames won't stream until a [SurfaceRequest] 57 * from [getSurfaceRequest] has been fulfilled. 58 * 59 * The camera will run until the calling coroutine is cancelled. 60 */ 61 suspend fun runCamera() 62 63 suspend fun takePicture(onCaptureStarted: (() -> Unit) = {}) 64 65 /** 66 * Takes a picture with the camera. If ignoreUri is set to true, the picture taken will be saved 67 * at the default directory for pictures on device. Otherwise, it will be saved at the uri 68 * location if the uri is not null. If it is null, an error will be thrown. 69 */ takePicturenull70 suspend fun takePicture( 71 onCaptureStarted: (() -> Unit) = {}, 72 contentResolver: ContentResolver, 73 imageCaptureUri: Uri?, 74 ignoreUri: Boolean = false 75 ): ImageCapture.OutputFileResults 76 startVideoRecordingnull77 suspend fun startVideoRecording( 78 videoCaptureUri: Uri?, 79 shouldUseUri: Boolean, 80 onVideoRecord: (OnVideoRecordEvent) -> Unit 81 ) 82 83 suspend fun pauseVideoRecording() 84 85 suspend fun resumeVideoRecording() 86 87 suspend fun stopVideoRecording() 88 89 fun setZoomScale(scale: Float) 90 91 fun getCurrentCameraState(): StateFlow<CameraState> 92 93 fun getSurfaceRequest(): StateFlow<SurfaceRequest?> 94 95 fun getScreenFlashEvents(): ReceiveChannel<ScreenFlashEvent> 96 97 fun getCurrentSettings(): StateFlow<CameraAppSettings?> 98 99 fun setFlashMode(flashMode: FlashMode) 100 101 fun isScreenFlashEnabled(): Boolean 102 103 suspend fun setAspectRatio(aspectRatio: AspectRatio) 104 105 suspend fun setVideoQuality(videoQuality: VideoQuality) 106 107 suspend fun setLensFacing(lensFacing: LensFacing) 108 109 suspend fun tapToFocus(x: Float, y: Float) 110 111 suspend fun setStreamConfig(streamConfig: StreamConfig) 112 113 suspend fun setDynamicRange(dynamicRange: DynamicRange) 114 115 fun setDeviceRotation(deviceRotation: DeviceRotation) 116 117 suspend fun setConcurrentCameraMode(concurrentCameraMode: ConcurrentCameraMode) 118 119 suspend fun setImageFormat(imageFormat: ImageOutputFormat) 120 121 suspend fun setAudioEnabled(isAudioEnabled: Boolean) 122 123 suspend fun setStabilizationMode(stabilizationMode: StabilizationMode) 124 125 suspend fun setTargetFrameRate(targetFrameRate: Int) 126 127 suspend fun setMaxVideoDuration(durationInMillis: Long) 128 129 suspend fun setCaptureMode(captureMode: CaptureMode) 130 131 /** 132 * Represents the events required for screen flash. 133 */ 134 data class ScreenFlashEvent(val type: Type, val onComplete: () -> Unit) { 135 enum class Type { 136 APPLY_UI, 137 CLEAR_UI 138 } 139 } 140 141 /** 142 * Represents the events for video recording. 143 */ 144 145 sealed interface OnVideoRecordEvent { 146 data class OnVideoRecorded(val savedUri: Uri) : OnVideoRecordEvent 147 148 data class OnVideoRecordError(val error: Throwable) : OnVideoRecordEvent 149 } 150 } 151 152 sealed interface VideoRecordingState { 153 154 /** 155 * [PendingRecording][androidx.camera.video.PendingRecording] has not yet started but is about to. 156 * This state may be used as a signal to start processes just before the recording actually starts. 157 */ 158 data object Starting : VideoRecordingState 159 160 /** 161 * Camera is not currently recording a video 162 */ 163 data class Inactive(val finalElapsedTimeNanos: Long = 0) : VideoRecordingState 164 165 /** 166 * Camera is currently active; paused, stopping, or recording a video 167 */ 168 sealed interface Active : VideoRecordingState { 169 val maxDurationMillis: Long 170 val audioAmplitude: Double 171 val elapsedTimeNanos: Long 172 173 data class Recording( 174 override val maxDurationMillis: Long, 175 override val audioAmplitude: Double, 176 override val elapsedTimeNanos: Long 177 ) : Active 178 179 data class Paused( 180 override val maxDurationMillis: Long, 181 override val audioAmplitude: Double, 182 override val elapsedTimeNanos: Long 183 ) : Active 184 } 185 } 186 187 data class CameraState( 188 val videoRecordingState: VideoRecordingState = VideoRecordingState.Inactive(), 189 val zoomScale: Float = 1f, 190 val sessionFirstFrameTimestamp: Long = 0L, 191 val torchEnabled: Boolean = false, 192 val stabilizationMode: StabilizationMode = StabilizationMode.OFF, 193 val lowLightBoostState: LowLightBoostState = LowLightBoostState.INACTIVE, 194 val debugInfo: DebugInfo = DebugInfo(null, null), 195 val videoQualityInfo: VideoQualityInfo = VideoQualityInfo(VideoQuality.UNSPECIFIED, 0, 0) 196 ) 197 198 data class DebugInfo(val logicalCameraId: String?, val physicalCameraId: String?) 199 200 data class VideoQualityInfo(val quality: VideoQuality, val width: Int, val height: Int) 201