1 /*
<lambda>null2 * Copyright 2021 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.impl
18
19 import android.hardware.camera2.CameraCaptureSession
20 import android.hardware.camera2.CameraCaptureSession.CaptureCallback
21 import android.hardware.camera2.CameraDevice
22 import android.hardware.camera2.CaptureRequest
23 import androidx.annotation.RestrictTo
24 import androidx.camera.camera2.pipe.integration.interop.CaptureRequestOptions
25 import androidx.camera.camera2.pipe.integration.interop.CaptureRequestOptions.Builder.Companion.from
26 import androidx.camera.camera2.pipe.integration.interop.ExperimentalCamera2Interop
27 import androidx.camera.core.ExtendableBuilder
28 import androidx.camera.core.impl.Config
29 import androidx.camera.core.impl.MutableConfig
30 import androidx.camera.core.impl.MutableOptionsBundle
31 import androidx.camera.core.impl.OptionsBundle
32
33 internal const val CAPTURE_REQUEST_ID_STEM = "camera2.captureRequest.option."
34 internal val TEMPLATE_TYPE_OPTION: Config.Option<Int> =
35 Config.Option.create("camera2.captureRequest.templateType", Int::class.javaPrimitiveType!!)
36 internal val DEVICE_STATE_CALLBACK_OPTION: Config.Option<CameraDevice.StateCallback> =
37 Config.Option.create(
38 "camera2.cameraDevice.stateCallback",
39 CameraDevice.StateCallback::class.java
40 )
41 internal val SESSION_STATE_CALLBACK_OPTION: Config.Option<CameraCaptureSession.StateCallback> =
42 Config.Option.create(
43 "camera2.cameraCaptureSession.stateCallback",
44 CameraCaptureSession.StateCallback::class.java
45 )
46 internal val SESSION_CAPTURE_CALLBACK_OPTION: Config.Option<CaptureCallback> =
47 Config.Option.create(
48 "camera2.cameraCaptureSession.captureCallback",
49 CaptureCallback::class.java
50 )
51 internal val STREAM_USE_CASE_OPTION: Config.Option<Long> =
52 Config.Option.create(
53 "camera2.cameraCaptureSession.streamUseCase",
54 Long::class.javaPrimitiveType!!
55 )
56 internal val STREAM_USE_HINT_OPTION: Config.Option<Long> =
57 Config.Option.create(
58 "camera2.cameraCaptureSession.streamUseHint",
59 Long::class.javaPrimitiveType!!
60 )
61 internal val CAPTURE_REQUEST_TAG_OPTION: Config.Option<Any> =
62 Config.Option.create("camera2.captureRequest.tag", Any::class.java)
63 internal val SESSION_PHYSICAL_CAMERA_ID_OPTION: Config.Option<String> =
64 Config.Option.create("camera2.cameraCaptureSession.physicalCameraId", String::class.java)
65
66 /**
67 * Internal shared implementation details for camera 2 interop.
68 *
69 * @constructor Creates a Camera2ImplConfig for reading Camera2 options from the given config.
70 * @property config The config that potentially contains Camera2 options.
71 */
72 @OptIn(ExperimentalCamera2Interop::class)
73 public class Camera2ImplConfig(config: Config) : CaptureRequestOptions(config) {
74
75 /** Returns all capture request options contained in this configuration. */
76 @get:RestrictTo(RestrictTo.Scope.LIBRARY)
77 public val captureRequestOptions: CaptureRequestOptions
78 get() = from(config).build()
79
80 /**
81 * Returns the CameraDevice template from the given configuration.
82 *
83 * See [CameraDevice] for valid template types. For example, [CameraDevice.TEMPLATE_PREVIEW].
84 *
85 * @param valueIfMissing The value to return if this configuration option has not been set.
86 * @return The stored value or `valueIfMissing` if the value does not exist in this
87 * configuration.
88 */
89 public fun getCaptureRequestTemplate(valueIfMissing: Int): Int {
90 return config.retrieveOption(TEMPLATE_TYPE_OPTION, valueIfMissing)!!
91 }
92
93 /**
94 * Returns a CameraDevice template on the given configuration. Requires API 33 or above.
95 *
96 * @param valueIfMissing The value to return if this configuration option has not been set.
97 * @return The stored value or `valueIfMissing` if the value does not exist in this
98 * configuration.
99 * @see [android.hardware.camera2.CameraMetadata] for valid stream use cases.
100 * @see [android.hardware.camera2.params.OutputConfiguration] to see how camera2 framework uses
101 * this.
102 */
103 public fun getStreamUseCase(valueIfMissing: Long? = null): Long? {
104 return config.retrieveOption(STREAM_USE_CASE_OPTION, valueIfMissing)
105 }
106
107 /**
108 * Returns a CameraDevice template on the given configuration.
109 *
110 * @param valueIfMissing The value to return if this configuration option has not been set.
111 * @return The stored value or `valueIfMissing` if the value does not exist in this
112 * configuration.
113 * @see [android.hardware.camera2.CameraMetadata] for valid stream use cases.
114 * @see [android.hardware.camera2.params.OutputConfiguration] to see how camera2 framework uses
115 * this.
116 */
117 public fun getStreamUseHint(valueIfMissing: Long? = null): Long? {
118 return config.retrieveOption(STREAM_USE_HINT_OPTION, valueIfMissing)
119 }
120
121 /**
122 * Returns the stored [CameraDevice.StateCallback].
123 *
124 * @param valueIfMissing The value to return if this configuration option has not been set.
125 * Defaults to `null`.
126 * @return The stored value or `valueIfMissing` if the value does not exist in this
127 * configuration.
128 */
129 public fun getDeviceStateCallback(
130 valueIfMissing: CameraDevice.StateCallback? = null
131 ): CameraDevice.StateCallback? {
132 return config.retrieveOption(DEVICE_STATE_CALLBACK_OPTION, valueIfMissing)
133 }
134
135 /**
136 * Returns the stored [CameraCaptureSession.StateCallback].
137 *
138 * @param valueIfMissing The value to return if this configuration option has not been set.
139 * Defaults to `null`.
140 * @return The stored value or `valueIfMissing` if the value does not exist in this
141 * configuration.
142 */
143 public fun getSessionStateCallback(
144 valueIfMissing: CameraCaptureSession.StateCallback? = null
145 ): CameraCaptureSession.StateCallback? {
146 return config.retrieveOption(SESSION_STATE_CALLBACK_OPTION, valueIfMissing)
147 }
148
149 /**
150 * Returns the stored [CameraCaptureSession.CaptureCallback].
151 *
152 * @param valueIfMissing The value to return if this configuration option has not been set.
153 * Defaults to `null`.
154 * @return The stored value or `valueIfMissing` if the value does not exist in this
155 * configuration.
156 */
157 public fun getSessionCaptureCallback(
158 valueIfMissing: CaptureCallback? = null
159 ): CaptureCallback? {
160 return config.retrieveOption(SESSION_CAPTURE_CALLBACK_OPTION, valueIfMissing)
161 }
162
163 /**
164 * Returns the capture request tag.
165 *
166 * @param valueIfMissing The value to return if this configuration option has not been set.
167 * Defaults to `null`.
168 * @return The stored value or `valueIfMissing` if the value does not exist in this
169 * configuration.
170 */
171 public fun getCaptureRequestTag(valueIfMissing: Any? = null): Any? {
172 return config.retrieveOption(CAPTURE_REQUEST_TAG_OPTION, valueIfMissing)
173 }
174
175 /**
176 * Returns the physical camera ID.
177 *
178 * @param valueIfMissing The value to return if this configuration option has not been set.
179 * Defaults to `null`.
180 * @return The stored value or `valueIfMissing` if the value does not exist in this
181 * configuration.
182 */
183 public fun getPhysicalCameraId(valueIfMissing: String? = null): String? {
184 return config.retrieveOption(SESSION_PHYSICAL_CAMERA_ID_OPTION, valueIfMissing)
185 }
186
187 /**
188 * Builder for creating [Camera2ImplConfig] instance.
189 *
190 * Use [Builder] for creating [Config] which contains camera2 options only. And use
191 * [androidx.camera.camera2.pipe.integration.interop.Camera2Interop.Extender] to add Camera2
192 * options on existing other [ExtendableBuilder].
193 */
194 public class Builder : ExtendableBuilder<Camera2ImplConfig?> {
195
196 private val mutableOptionsBundle = MutableOptionsBundle.create()
197
198 override fun getMutableConfig(): MutableConfig {
199 return mutableOptionsBundle
200 }
201
202 /** Inserts new capture request option with specific [CaptureRequest.Key] setting. */
203 public fun <ValueT> setCaptureRequestOption(
204 key: CaptureRequest.Key<ValueT>,
205 value: ValueT
206 ): Builder {
207 val opt = key.createCaptureRequestOption()
208 mutableOptionsBundle.insertOption(opt, value)
209 return this
210 }
211
212 /**
213 * Inserts new capture request option with specific [CaptureRequest.Key] setting and
214 * [Config.OptionPriority].
215 */
216 public fun <ValueT> setCaptureRequestOptionWithPriority(
217 key: CaptureRequest.Key<ValueT>,
218 value: ValueT,
219 priority: Config.OptionPriority
220 ): Builder {
221 val opt = key.createCaptureRequestOption()
222 mutableOptionsBundle.insertOption(opt, priority, value)
223 return this
224 }
225
226 /**
227 * Inserts all capture request options in the map to the setting with
228 * [Config.OptionPriority].
229 */
230 public fun addAllCaptureRequestOptionsWithPriority(
231 values: Map<CaptureRequest.Key<*>, Any>,
232 priority: Config.OptionPriority
233 ): Builder {
234 values.forEach { (key, value) ->
235 val opt = key.createCaptureRequestOption()
236 mutableOptionsBundle.insertOption(opt, priority, value)
237 }
238 return this
239 }
240
241 /** Inserts options from other [Config] objects. */
242 public fun insertAllOptions(config: Config): Builder {
243 for (option in config.listOptions()) {
244 // Options/values and priority are being copied directly
245 @Suppress("UNCHECKED_CAST") val objectOpt = option as Config.Option<Any>
246 mutableOptionsBundle.insertOption(
247 objectOpt,
248 config.getOptionPriority(option),
249 config.retrieveOption(objectOpt)
250 )
251 }
252 return this
253 }
254
255 /**
256 * Builds an immutable [Camera2ImplConfig] from the current state.
257 *
258 * @return A [Camera2ImplConfig] populated with the current state.
259 */
260 override fun build(): Camera2ImplConfig {
261 return Camera2ImplConfig(OptionsBundle.from(mutableOptionsBundle))
262 }
263 }
264 }
265
createCaptureRequestOptionnull266 internal fun CaptureRequest.Key<*>.createCaptureRequestOption(): Config.Option<Any> {
267 /**
268 * Unfortunately, we can't get the Class<T> from the CaptureRequest.Key, so we're forced to
269 * erase the type. This shouldn't be a problem as long as we are only using these options within
270 * the Camera2ImplConfig and Camera2ImplConfig.Builder classes.
271 */
272 return Config.Option.create(CAPTURE_REQUEST_ID_STEM + name, Any::class.java, this)
273 }
274
275 /** Convert the Config to the CaptureRequest key-value map. */
toParametersnull276 public fun Config.toParameters(): Map<CaptureRequest.Key<*>, Any> {
277 val parameters = mutableMapOf<CaptureRequest.Key<*>, Any>()
278 for (configOption in listOptions()) {
279 val requestKey = configOption.token as? CaptureRequest.Key<*> ?: continue
280 val value = retrieveOption(configOption) ?: continue
281 parameters[requestKey] = value
282 }
283
284 return parameters
285 }
286