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