1 /*
<lambda>null2 * Copyright 2020 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.integration.adapter
18
19 import android.hardware.camera2.CameraMetadata
20 import android.hardware.camera2.CaptureResult
21 import android.hardware.camera2.TotalCaptureResult
22 import android.os.Build
23 import androidx.camera.camera2.pipe.CameraPipe
24 import androidx.camera.camera2.pipe.FrameInfo
25 import androidx.camera.camera2.pipe.FrameMetadata
26 import androidx.camera.camera2.pipe.FrameNumber
27 import androidx.camera.camera2.pipe.RequestMetadata
28 import androidx.camera.camera2.pipe.UnsafeWrapper
29 import androidx.camera.camera2.pipe.core.Log
30 import androidx.camera.camera2.pipe.integration.impl.CAMERAX_TAG_BUNDLE
31 import androidx.camera.core.impl.CameraCaptureMetaData.AeMode
32 import androidx.camera.core.impl.CameraCaptureMetaData.AeState
33 import androidx.camera.core.impl.CameraCaptureMetaData.AfMode
34 import androidx.camera.core.impl.CameraCaptureMetaData.AfState
35 import androidx.camera.core.impl.CameraCaptureMetaData.AwbMode
36 import androidx.camera.core.impl.CameraCaptureMetaData.AwbState
37 import androidx.camera.core.impl.CameraCaptureMetaData.FlashState
38 import androidx.camera.core.impl.CameraCaptureResult
39 import androidx.camera.core.impl.TagBundle
40 import androidx.camera.core.impl.utils.ExifData
41 import java.nio.BufferUnderflowException
42 import kotlin.reflect.KClass
43
44 public class PartialCaptureResultAdapter(
45 private val requestMetadata: RequestMetadata,
46 private val frameNumber: FrameNumber,
47 private val result: FrameMetadata,
48 ) : CameraCaptureResult, UnsafeWrapper {
49 override fun getAfMode(): AfMode = result.getAfMode()
50
51 override fun getAfState(): AfState = result.getAfState()
52
53 override fun getAeMode(): AeMode = result.getAeMode()
54
55 override fun getAeState(): AeState = result.getAeState()
56
57 override fun getAwbMode(): AwbMode = result.getAwbMode()
58
59 override fun getAwbState(): AwbState = result.getAwbState()
60
61 override fun getFlashState(): FlashState = result.getFlashState()
62
63 override fun getTimestamp(): Long = result.getTimestamp()
64
65 override fun getTagBundle(): TagBundle {
66 return requestMetadata.getOrDefault(CAMERAX_TAG_BUNDLE, TagBundle.emptyBundle())
67 }
68
69 override fun populateExifData(exifBuilder: ExifData.Builder) {
70 super.populateExifData(exifBuilder)
71 result.populateExifData(exifBuilder)
72 }
73
74 override fun getCaptureResult(): CaptureResult =
75 checkNotNull(unwrapAs(CaptureResult::class)) { "Failed to unwrap $this as CaptureResult" }
76
77 override fun <T : Any> unwrapAs(type: KClass<T>): T? = result.unwrapAs(type)
78 }
79
80 /** Adapts the [CameraCaptureResult] interface to [CameraPipe]. */
81 public class CaptureResultAdapter(
82 private val requestMetadata: RequestMetadata,
83 private val frameNumber: FrameNumber,
84 internal val result: FrameInfo
85 ) : CameraCaptureResult, UnsafeWrapper {
getAfModenull86 override fun getAfMode(): AfMode = result.metadata.getAfMode()
87
88 override fun getAfState(): AfState = result.metadata.getAfState()
89
90 override fun getAeMode(): AeMode = result.metadata.getAeMode()
91
92 override fun getAeState(): AeState = result.metadata.getAeState()
93
94 override fun getAwbMode(): AwbMode = result.metadata.getAwbMode()
95
96 override fun getAwbState(): AwbState = result.metadata.getAwbState()
97
98 override fun getFlashState(): FlashState = result.metadata.getFlashState()
99
100 override fun getTimestamp(): Long = result.metadata.getTimestamp()
101
102 override fun getTagBundle(): TagBundle {
103 return requestMetadata.getOrDefault(CAMERAX_TAG_BUNDLE, TagBundle.emptyBundle())
104 }
105
populateExifDatanull106 override fun populateExifData(exifBuilder: ExifData.Builder) {
107 super.populateExifData(exifBuilder)
108 result.metadata.populateExifData(exifBuilder)
109 }
110
getCaptureResultnull111 override fun getCaptureResult(): CaptureResult =
112 checkNotNull(unwrapAs(TotalCaptureResult::class)) {
113 "Failed to unwrap $this as TotalCaptureResult"
114 }
115
116 @Suppress("UNCHECKED_CAST")
unwrapAsnull117 override fun <T : Any> unwrapAs(type: KClass<T>): T? {
118 return when (type) {
119 FrameInfo::class -> result as T
120 else -> result.unwrapAs(type)
121 }
122 }
123 }
124
getAfModenull125 private fun FrameMetadata.getAfMode(): AfMode =
126 when (val mode = this[CaptureResult.CONTROL_AF_MODE]) {
127 CaptureResult.CONTROL_AF_MODE_OFF,
128 CaptureResult.CONTROL_AF_MODE_EDOF -> AfMode.OFF
129 CaptureResult.CONTROL_AF_MODE_AUTO,
130 CaptureResult.CONTROL_AF_MODE_MACRO -> AfMode.ON_MANUAL_AUTO
131 CaptureResult.CONTROL_AF_MODE_CONTINUOUS_PICTURE,
132 CaptureResult.CONTROL_AF_MODE_CONTINUOUS_VIDEO -> AfMode.ON_CONTINUOUS_AUTO
133 null -> AfMode.UNKNOWN
134 else -> {
135 Log.debug { "Unknown AF mode ($mode) for $frameNumber!" }
136 AfMode.UNKNOWN
137 }
138 }
139
getAfStatenull140 private fun FrameMetadata.getAfState(): AfState =
141 when (val state = this[CaptureResult.CONTROL_AF_STATE]) {
142 CaptureResult.CONTROL_AF_STATE_INACTIVE -> AfState.INACTIVE
143 CaptureResult.CONTROL_AF_STATE_ACTIVE_SCAN,
144 CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN -> AfState.SCANNING
145 CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED -> AfState.LOCKED_FOCUSED
146 CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED -> AfState.LOCKED_NOT_FOCUSED
147 CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED -> AfState.PASSIVE_FOCUSED
148 CaptureResult.CONTROL_AF_STATE_PASSIVE_UNFOCUSED -> AfState.PASSIVE_NOT_FOCUSED
149 null -> AfState.UNKNOWN
150 else -> {
151 Log.debug { "Unknown AF state ($state) for $frameNumber!" }
152 AfState.UNKNOWN
153 }
154 }
155
getAeModenull156 private fun FrameMetadata.getAeMode(): AeMode =
157 when (val mode = this[CaptureResult.CONTROL_AE_MODE]) {
158 CaptureResult.CONTROL_AE_MODE_OFF -> AeMode.OFF
159 CaptureResult.CONTROL_AE_MODE_ON -> AeMode.ON
160 CaptureResult.CONTROL_AE_MODE_ON_AUTO_FLASH -> AeMode.ON_AUTO_FLASH
161 CaptureResult.CONTROL_AE_MODE_ON_ALWAYS_FLASH -> AeMode.ON_ALWAYS_FLASH
162 CaptureResult.CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE -> AeMode.ON_AUTO_FLASH_REDEYE
163 null -> AeMode.UNKNOWN
164 else -> {
165 Log.debug { "Unknown AE mode ($mode) for $frameNumber!" }
166 AeMode.UNKNOWN
167 }
168 }
169
getAeStatenull170 private fun FrameMetadata.getAeState(): AeState =
171 when (val state = this[CaptureResult.CONTROL_AE_STATE]) {
172 CaptureResult.CONTROL_AE_STATE_INACTIVE -> AeState.INACTIVE
173 CaptureResult.CONTROL_AE_STATE_SEARCHING,
174 CaptureResult.CONTROL_AE_STATE_PRECAPTURE -> AeState.SEARCHING
175 CaptureResult.CONTROL_AE_STATE_FLASH_REQUIRED -> AeState.FLASH_REQUIRED
176 CaptureResult.CONTROL_AE_STATE_CONVERGED -> AeState.CONVERGED
177 CaptureResult.CONTROL_AE_STATE_LOCKED -> AeState.LOCKED
178 null -> AeState.UNKNOWN
179 else -> {
180 Log.debug { "Unknown AE state ($state) for $frameNumber!" }
181 AeState.UNKNOWN
182 }
183 }
184
getAwbModenull185 private fun FrameMetadata.getAwbMode(): AwbMode =
186 when (val mode = this[CaptureResult.CONTROL_AWB_MODE]) {
187 CaptureResult.CONTROL_AWB_MODE_OFF -> AwbMode.OFF
188 CaptureResult.CONTROL_AWB_MODE_AUTO -> AwbMode.AUTO
189 CaptureResult.CONTROL_AWB_MODE_INCANDESCENT -> AwbMode.INCANDESCENT
190 CaptureResult.CONTROL_AWB_MODE_FLUORESCENT -> AwbMode.FLUORESCENT
191 CaptureResult.CONTROL_AWB_MODE_WARM_FLUORESCENT -> AwbMode.WARM_FLUORESCENT
192 CaptureResult.CONTROL_AWB_MODE_DAYLIGHT -> AwbMode.DAYLIGHT
193 CaptureResult.CONTROL_AWB_MODE_CLOUDY_DAYLIGHT -> AwbMode.CLOUDY_DAYLIGHT
194 CaptureResult.CONTROL_AWB_MODE_TWILIGHT -> AwbMode.TWILIGHT
195 CaptureResult.CONTROL_AWB_MODE_SHADE -> AwbMode.SHADE
196 null -> AwbMode.UNKNOWN
197 else -> {
198 Log.debug { "Unknown AWB mode ($mode) for $frameNumber!" }
199 AwbMode.UNKNOWN
200 }
201 }
202
FrameMetadatanull203 private fun FrameMetadata.getAwbState(): AwbState =
204 when (val state = this[CaptureResult.CONTROL_AWB_STATE]) {
205 CaptureResult.CONTROL_AWB_STATE_INACTIVE -> AwbState.INACTIVE
206 CaptureResult.CONTROL_AWB_STATE_SEARCHING -> AwbState.METERING
207 CaptureResult.CONTROL_AWB_STATE_CONVERGED -> AwbState.CONVERGED
208 CaptureResult.CONTROL_AWB_STATE_LOCKED -> AwbState.LOCKED
209 null -> AwbState.UNKNOWN
210 else -> {
211 Log.debug { "Unknown AWB state ($state) for $frameNumber!" }
212 AwbState.UNKNOWN
213 }
214 }
215
getFlashStatenull216 private fun FrameMetadata.getFlashState(): FlashState =
217 when (val state = this[CaptureResult.FLASH_STATE]) {
218 CaptureResult.FLASH_STATE_UNAVAILABLE,
219 CaptureResult.FLASH_STATE_CHARGING -> FlashState.NONE
220 CaptureResult.FLASH_STATE_READY -> FlashState.READY
221 CaptureResult.FLASH_STATE_FIRED,
222 CaptureResult.FLASH_STATE_PARTIAL -> FlashState.FIRED
223 null -> FlashState.UNKNOWN
224 else -> {
225 Log.debug { "Unknown flash state ($state) for $frameNumber!" }
226 FlashState.UNKNOWN
227 }
228 }
229
getTimestampnull230 private fun FrameMetadata.getTimestamp(): Long = getOrDefault(CaptureResult.SENSOR_TIMESTAMP, -1L)
231
232 private fun FrameMetadata.populateExifData(exifData: ExifData.Builder) {
233 // Set orientation
234 try {
235 this[CaptureResult.JPEG_ORIENTATION]?.let { jpegOrientation ->
236 exifData.setOrientationDegrees(jpegOrientation)
237 }
238 } catch (exception: BufferUnderflowException) {
239 // On certain devices, e.g. Pixel 3 XL API 31, getting JPEG orientation on YUV stream
240 // throws BufferUnderflowException. The value will be overridden in post-processing
241 // anyway, so it's safe to ignore. Please reference: b/240998057
242 // TODO: b/316233308 - Handle the exception inside in CameraPipe.
243 Log.warn { "Failed to get JPEG orientation." }
244 }
245
246 // Set exposure time
247 this[CaptureResult.SENSOR_EXPOSURE_TIME]?.let { exposureTimeNs ->
248 exifData.setExposureTimeNanos(exposureTimeNs)
249 }
250
251 // Set the aperture
252 this[CaptureResult.LENS_APERTURE]?.let { aperture -> exifData.setLensFNumber(aperture) }
253
254 // Set the ISO
255 this[CaptureResult.SENSOR_SENSITIVITY]?.let { iso ->
256 exifData.setIso(iso)
257 if (Build.VERSION.SDK_INT >= 24) {
258 this[CaptureResult.CONTROL_POST_RAW_SENSITIVITY_BOOST]?.let { postRawSensitivityBoost ->
259 exifData.setIso(iso * (postRawSensitivityBoost / 100f).toInt())
260 }
261 }
262 }
263
264 // Set the focal length
265 this[CaptureResult.LENS_FOCAL_LENGTH]?.let { focalLength ->
266 exifData.setFocalLength(focalLength)
267 }
268
269 // Set white balance MANUAL/AUTO
270 this[CaptureResult.CONTROL_AWB_MODE]?.let { whiteBalanceMode ->
271 var wbMode = ExifData.WhiteBalanceMode.AUTO
272 if (whiteBalanceMode == CameraMetadata.CONTROL_AWB_MODE_OFF) {
273 wbMode = ExifData.WhiteBalanceMode.MANUAL
274 }
275 exifData.setWhiteBalanceMode(wbMode)
276 }
277 }
278