• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2024 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.hardware.camera2.CameraCharacteristics
19 import android.hardware.camera2.CameraMetadata
20 import androidx.annotation.OptIn
21 import androidx.camera.camera2.interop.Camera2CameraInfo
22 import androidx.camera.camera2.interop.ExperimentalCamera2Interop
23 import androidx.camera.core.CameraInfo
24 import androidx.camera.core.CameraSelector
25 import androidx.camera.core.DynamicRange as CXDynamicRange
26 import androidx.camera.core.ImageCapture
27 import androidx.camera.core.Preview
28 import androidx.camera.core.UseCase
29 import androidx.camera.core.UseCaseGroup
30 import androidx.camera.video.Quality
31 import androidx.camera.video.Recorder
32 import androidx.camera.video.VideoCapture
33 import com.google.jetpackcamera.settings.model.DynamicRange
34 import com.google.jetpackcamera.settings.model.ImageOutputFormat
35 import com.google.jetpackcamera.settings.model.LensFacing
36 import com.google.jetpackcamera.settings.model.VideoQuality
37 import com.google.jetpackcamera.settings.model.VideoQuality.FHD
38 import com.google.jetpackcamera.settings.model.VideoQuality.HD
39 import com.google.jetpackcamera.settings.model.VideoQuality.SD
40 import com.google.jetpackcamera.settings.model.VideoQuality.UHD
41 import com.google.jetpackcamera.settings.model.VideoQuality.UNSPECIFIED
42 
43 val CameraInfo.appLensFacing: LensFacing
44     get() = when (this.lensFacing) {
45         CameraSelector.LENS_FACING_FRONT -> LensFacing.FRONT
46         CameraSelector.LENS_FACING_BACK -> LensFacing.BACK
47         else -> throw IllegalArgumentException(
48             "Unknown CameraSelector.LensFacing -> LensFacing mapping. " +
49                 "[CameraSelector.LensFacing: ${this.lensFacing}]"
50         )
51     }
52 
toSupportedAppDynamicRangenull53 fun CXDynamicRange.toSupportedAppDynamicRange(): DynamicRange? {
54     return when (this) {
55         CXDynamicRange.SDR -> DynamicRange.SDR
56         CXDynamicRange.HLG_10_BIT -> DynamicRange.HLG10
57         // All other dynamic ranges unsupported. Return null.
58         else -> null
59     }
60 }
61 
toCXDynamicRangenull62 fun DynamicRange.toCXDynamicRange(): CXDynamicRange {
63     return when (this) {
64         com.google.jetpackcamera.settings.model.DynamicRange.SDR -> CXDynamicRange.SDR
65         com.google.jetpackcamera.settings.model.DynamicRange.HLG10 -> CXDynamicRange.HLG_10_BIT
66     }
67 }
68 
toCameraSelectornull69 fun LensFacing.toCameraSelector(): CameraSelector = when (this) {
70     LensFacing.FRONT -> CameraSelector.DEFAULT_FRONT_CAMERA
71     LensFacing.BACK -> CameraSelector.DEFAULT_BACK_CAMERA
72 }
73 
74 val CameraInfo.sensorLandscapeRatio: Float
75     @OptIn(ExperimentalCamera2Interop::class)
76     get() = Camera2CameraInfo.from(this)
77         .getCameraCharacteristic(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE)
sensorRectnull78         ?.let { sensorRect ->
79             if (sensorRect.width() > sensorRect.height()) {
80                 sensorRect.width().toFloat() / sensorRect.height()
81             } else {
82                 sensorRect.height().toFloat() / sensorRect.width()
83             }
84         } ?: Float.NaN
85 
toAppImageFormatnull86 fun Int.toAppImageFormat(): ImageOutputFormat? {
87     return when (this) {
88         ImageCapture.OUTPUT_FORMAT_JPEG -> ImageOutputFormat.JPEG
89         ImageCapture.OUTPUT_FORMAT_JPEG_ULTRA_HDR -> ImageOutputFormat.JPEG_ULTRA_HDR
90         // All other output formats unsupported. Return null.
91         else -> null
92     }
93 }
94 
VideoQualitynull95 fun VideoQuality.toQuality(): Quality? {
96     return when (this) {
97         SD -> Quality.SD
98         HD -> Quality.HD
99         FHD -> Quality.FHD
100         UHD -> Quality.UHD
101         UNSPECIFIED -> null
102     }
103 }
104 
Qualitynull105 fun Quality.toVideoQuality(): VideoQuality {
106     return when (this) {
107         Quality.SD -> SD
108         Quality.HD -> HD
109         Quality.FHD -> FHD
110         Quality.UHD -> UHD
111         else -> UNSPECIFIED
112     }
113 }
114 
115 /**
116  * Checks if preview stabilization is supported by the device.
117  *
118  */
119 val CameraInfo.isPreviewStabilizationSupported: Boolean
120     get() = Preview.getPreviewCapabilities(this).isStabilizationSupported
121 
122 /**
123  * Checks if video stabilization is supported by the device.
124  *
125  */
126 val CameraInfo.isVideoStabilizationSupported: Boolean
127     get() = Recorder.getVideoCapabilities(this).isStabilizationSupported
128 
129 /** Checks if optical image stabilization (OIS) is supported by the device. */
130 val CameraInfo.isOpticalStabilizationSupported: Boolean
131     @OptIn(ExperimentalCamera2Interop::class)
132     get() = Camera2CameraInfo.from(this)
133         .getCameraCharacteristic(CameraCharacteristics.LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION)
134         ?.contains(
135             CameraMetadata.LENS_OPTICAL_STABILIZATION_MODE_ON
136         ) ?: false
137 
138 val CameraInfo.isLowLightBoostSupported: Boolean
139     @OptIn(ExperimentalCamera2Interop::class)
140     get() = Camera2CameraInfo.from(this)
141         .getCameraCharacteristic(CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES)
142         ?.contains(
143             CameraMetadata.CONTROL_AE_MODE_ON_LOW_LIGHT_BOOST_BRIGHTNESS_PRIORITY
144         ) ?: false
145 
CameraInfonull146 fun CameraInfo.filterSupportedFixedFrameRates(desired: Set<Int>): Set<Int> {
147     return buildSet {
148         this@filterSupportedFixedFrameRates.supportedFrameRateRanges.forEach { e ->
149             if (e.upper == e.lower && desired.contains(e.upper)) {
150                 add(e.upper)
151             }
152         }
153     }
154 }
155 
156 val CameraInfo.supportedImageFormats: Set<ImageOutputFormat>
157     get() = ImageCapture.getImageCaptureCapabilities(this).supportedOutputFormats
158         .mapNotNull(Int::toAppImageFormat)
159         .toSet()
160 
UseCaseGroupnull161 fun UseCaseGroup.getVideoCapture() = getUseCaseOrNull<VideoCapture<Recorder>>()
162 fun UseCaseGroup.getImageCapture() = getUseCaseOrNull<ImageCapture>()
163 
164 private inline fun <reified T : UseCase> UseCaseGroup.getUseCaseOrNull(): T? {
165     return useCases.filterIsInstance<T>().singleOrNull()
166 }
167