blob: e2bec84a18ab5a060208891a47cb4a0d2ec30438 [file] [log] [blame]
Jacopo Mondi667d8ea2019-05-10 17:40:02 +02001/* SPDX-License-Identifier: LGPL-2.1-or-later */
2/*
3 * Copyright (C) 2019, Google Inc.
4 *
5 * camera_device.cpp - libcamera Android Camera Device
6 */
7
8#include "camera_device.h"
9
Jacopo Mondi667d8ea2019-05-10 17:40:02 +020010#include "log.h"
Laurent Pinchart39860092019-09-05 03:12:34 +030011#include "utils.h"
Jacopo Mondi667d8ea2019-05-10 17:40:02 +020012
Laurent Pinchart39860092019-09-05 03:12:34 +030013#include "camera_metadata.h"
Jacopo Mondi667d8ea2019-05-10 17:40:02 +020014#include "thread_rpc.h"
15
16using namespace libcamera;
17
18LOG_DECLARE_CATEGORY(HAL);
19
20/*
21 * \struct Camera3RequestDescriptor
22 *
23 * A utility structure that groups information about a capture request to be
24 * later re-used at request complete time to notify the framework.
25 */
26
27CameraDevice::Camera3RequestDescriptor::Camera3RequestDescriptor(
28 unsigned int frameNumber, unsigned int numBuffers)
29 : frameNumber(frameNumber), numBuffers(numBuffers)
30{
31 buffers = new camera3_stream_buffer_t[numBuffers];
32}
33
34CameraDevice::Camera3RequestDescriptor::~Camera3RequestDescriptor()
35{
36 delete[] buffers;
37}
38
39/*
40 * \class CameraDevice
41 *
42 * The CameraDevice class wraps a libcamera::Camera instance, and implements
43 * the camera_device_t interface by handling RPC requests received from its
44 * associated CameraProxy.
45 *
46 * It translate parameters and operations from Camera HALv3 API to the libcamera
47 * ones to provide static information for a Camera, create request templates
48 * for it, process capture requests and then deliver capture results back
49 * to the framework using the designated callbacks.
50 */
51
Laurent Pinchart0ed40d22019-08-18 01:45:01 +030052CameraDevice::CameraDevice(unsigned int id, const std::shared_ptr<Camera> &camera)
Jacopo Mondi667d8ea2019-05-10 17:40:02 +020053 : running_(false), camera_(camera), staticMetadata_(nullptr),
54 requestTemplate_(nullptr)
55{
56 camera_->requestCompleted.connect(this, &CameraDevice::requestComplete);
57}
58
59CameraDevice::~CameraDevice()
60{
61 if (staticMetadata_)
Laurent Pinchart39860092019-09-05 03:12:34 +030062 delete staticMetadata_;
Jacopo Mondi667d8ea2019-05-10 17:40:02 +020063
64 if (requestTemplate_)
Laurent Pinchart39860092019-09-05 03:12:34 +030065 delete requestTemplate_;
Jacopo Mondi667d8ea2019-05-10 17:40:02 +020066}
67
68/*
69 * Handle RPC request received from the associated proxy.
70 */
Laurent Pinchart0c324332019-08-12 05:30:06 +030071void CameraDevice::call(ThreadRpc *rpc)
Jacopo Mondi667d8ea2019-05-10 17:40:02 +020072{
Jacopo Mondi667d8ea2019-05-10 17:40:02 +020073 switch (rpc->tag) {
74 case ThreadRpc::ProcessCaptureRequest:
75 processCaptureRequest(rpc->request);
76 break;
77 case ThreadRpc::Close:
78 close();
79 break;
80 default:
81 LOG(HAL, Error) << "Unknown RPC operation: " << rpc->tag;
82 }
83
84 rpc->notifyReception();
85}
86
87int CameraDevice::open()
88{
89 int ret = camera_->acquire();
90 if (ret) {
91 LOG(HAL, Error) << "Failed to acquire the camera";
92 return ret;
93 }
94
95 return 0;
96}
97
98void CameraDevice::close()
99{
100 camera_->stop();
101
102 camera_->freeBuffers();
103 camera_->release();
104
105 running_ = false;
106}
107
108void CameraDevice::setCallbacks(const camera3_callback_ops_t *callbacks)
109{
110 callbacks_ = callbacks;
111}
112
113/*
114 * Return static information for the camera.
115 */
116camera_metadata_t *CameraDevice::getStaticMetadata()
117{
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200118 if (staticMetadata_)
Laurent Pinchart39860092019-09-05 03:12:34 +0300119 return staticMetadata_->get();
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200120
121 /*
122 * The here reported metadata are enough to implement a basic capture
123 * example application, but a real camera implementation will require
124 * more.
125 */
126
Jacopo Mondi48504ba2019-09-04 16:18:19 +0200127 /*
128 * \todo Keep this in sync with the actual number of entries.
Laurent Pinchart39860092019-09-05 03:12:34 +0300129 * Currently: 47 entries, 390 bytes
Jacopo Mondi48504ba2019-09-04 16:18:19 +0200130 */
Laurent Pinchart39860092019-09-05 03:12:34 +0300131 staticMetadata_ = new CameraMetadata(50, 500);
132 if (!staticMetadata_->isValid()) {
133 LOG(HAL, Error) << "Failed to allocate static metadata";
134 delete staticMetadata_;
135 staticMetadata_ = nullptr;
136 return nullptr;
137 }
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200138
Jacopo Mondib4893fc2019-09-04 16:18:18 +0200139 /* Color correction static metadata. */
140 std::vector<uint8_t> aberrationModes = {
141 ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF,
142 };
Laurent Pinchart39860092019-09-05 03:12:34 +0300143 staticMetadata_->addEntry(ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
144 aberrationModes.data(),
145 aberrationModes.size());
Jacopo Mondib4893fc2019-09-04 16:18:18 +0200146
147 /* Control static metadata. */
148 std::vector<uint8_t> aeAvailableAntiBandingModes = {
149 ANDROID_CONTROL_AE_ANTIBANDING_MODE_OFF,
150 ANDROID_CONTROL_AE_ANTIBANDING_MODE_50HZ,
151 ANDROID_CONTROL_AE_ANTIBANDING_MODE_60HZ,
152 ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO,
153 };
Laurent Pinchart39860092019-09-05 03:12:34 +0300154 staticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
155 aeAvailableAntiBandingModes.data(),
156 aeAvailableAntiBandingModes.size());
Jacopo Mondib4893fc2019-09-04 16:18:18 +0200157
158 std::vector<uint8_t> aeAvailableModes = {
159 ANDROID_CONTROL_AE_MODE_ON,
160 };
Laurent Pinchart39860092019-09-05 03:12:34 +0300161 staticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_MODES,
162 aeAvailableModes.data(),
163 aeAvailableModes.size());
Jacopo Mondib4893fc2019-09-04 16:18:18 +0200164
165 std::vector<int32_t> availableAeFpsTarget = {
166 15, 30,
167 };
Laurent Pinchart39860092019-09-05 03:12:34 +0300168 staticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
169 availableAeFpsTarget.data(),
170 availableAeFpsTarget.size());
Jacopo Mondib4893fc2019-09-04 16:18:18 +0200171
172 std::vector<int32_t> aeCompensationRange = {
173 0, 0,
174 };
Laurent Pinchart39860092019-09-05 03:12:34 +0300175 staticMetadata_->addEntry(ANDROID_CONTROL_AE_COMPENSATION_RANGE,
176 aeCompensationRange.data(),
177 aeCompensationRange.size());
Jacopo Mondib4893fc2019-09-04 16:18:18 +0200178
179 const camera_metadata_rational_t aeCompensationStep[] = {
180 { 0, 1 }
181 };
Laurent Pinchart39860092019-09-05 03:12:34 +0300182 staticMetadata_->addEntry(ANDROID_CONTROL_AE_COMPENSATION_STEP,
183 aeCompensationStep, 1);
Jacopo Mondib4893fc2019-09-04 16:18:18 +0200184
185 std::vector<uint8_t> availableAfModes = {
186 ANDROID_CONTROL_AF_MODE_OFF,
187 };
Laurent Pinchart39860092019-09-05 03:12:34 +0300188 staticMetadata_->addEntry(ANDROID_CONTROL_AF_AVAILABLE_MODES,
189 availableAfModes.data(),
190 availableAfModes.size());
Jacopo Mondib4893fc2019-09-04 16:18:18 +0200191
192 std::vector<uint8_t> availableEffects = {
193 ANDROID_CONTROL_EFFECT_MODE_OFF,
194 };
Laurent Pinchart39860092019-09-05 03:12:34 +0300195 staticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_EFFECTS,
196 availableEffects.data(),
197 availableEffects.size());
Jacopo Mondib4893fc2019-09-04 16:18:18 +0200198
199 std::vector<uint8_t> availableSceneModes = {
200 ANDROID_CONTROL_SCENE_MODE_DISABLED,
201 };
Laurent Pinchart39860092019-09-05 03:12:34 +0300202 staticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_SCENE_MODES,
203 availableSceneModes.data(),
204 availableSceneModes.size());
Jacopo Mondib4893fc2019-09-04 16:18:18 +0200205
206 std::vector<uint8_t> availableStabilizationModes = {
207 ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF,
208 };
Laurent Pinchart39860092019-09-05 03:12:34 +0300209 staticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
210 availableStabilizationModes.data(),
211 availableStabilizationModes.size());
Jacopo Mondib4893fc2019-09-04 16:18:18 +0200212
213 std::vector<uint8_t> availableAwbModes = {
214 ANDROID_CONTROL_AWB_MODE_OFF,
215 };
Laurent Pinchart39860092019-09-05 03:12:34 +0300216 staticMetadata_->addEntry(ANDROID_CONTROL_AWB_AVAILABLE_MODES,
217 availableAwbModes.data(),
218 availableAwbModes.size());
Jacopo Mondib4893fc2019-09-04 16:18:18 +0200219
220 std::vector<int32_t> availableMaxRegions = {
221 0, 0, 0,
222 };
Laurent Pinchart39860092019-09-05 03:12:34 +0300223 staticMetadata_->addEntry(ANDROID_CONTROL_MAX_REGIONS,
224 availableMaxRegions.data(),
225 availableMaxRegions.size());
Jacopo Mondib4893fc2019-09-04 16:18:18 +0200226
227 std::vector<uint8_t> sceneModesOverride = {
228 ANDROID_CONTROL_AE_MODE_ON,
229 ANDROID_CONTROL_AWB_MODE_AUTO,
230 ANDROID_CONTROL_AF_MODE_AUTO,
231 };
Laurent Pinchart39860092019-09-05 03:12:34 +0300232 staticMetadata_->addEntry(ANDROID_CONTROL_SCENE_MODE_OVERRIDES,
233 sceneModesOverride.data(),
234 sceneModesOverride.size());
Jacopo Mondib4893fc2019-09-04 16:18:18 +0200235
236 uint8_t aeLockAvailable = ANDROID_CONTROL_AE_LOCK_AVAILABLE_FALSE;
Laurent Pinchart39860092019-09-05 03:12:34 +0300237 staticMetadata_->addEntry(ANDROID_CONTROL_AE_LOCK_AVAILABLE,
238 &aeLockAvailable, 1);
Jacopo Mondib4893fc2019-09-04 16:18:18 +0200239
240 uint8_t awbLockAvailable = ANDROID_CONTROL_AWB_LOCK_AVAILABLE_FALSE;
Laurent Pinchart39860092019-09-05 03:12:34 +0300241 staticMetadata_->addEntry(ANDROID_CONTROL_AWB_LOCK_AVAILABLE,
242 &awbLockAvailable, 1);
Jacopo Mondib4893fc2019-09-04 16:18:18 +0200243
244 char availableControlModes = ANDROID_CONTROL_MODE_AUTO;
Laurent Pinchart39860092019-09-05 03:12:34 +0300245 staticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_MODES,
246 &availableControlModes, 1);
Jacopo Mondib4893fc2019-09-04 16:18:18 +0200247
248 /* JPEG static metadata. */
249 std::vector<int32_t> availableThumbnailSizes = {
250 0, 0,
251 };
Laurent Pinchart39860092019-09-05 03:12:34 +0300252 staticMetadata_->addEntry(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,
253 availableThumbnailSizes.data(),
254 availableThumbnailSizes.size());
Jacopo Mondib4893fc2019-09-04 16:18:18 +0200255
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200256 /* Sensor static metadata. */
257 int32_t pixelArraySize[] = {
258 2592, 1944,
259 };
Laurent Pinchart39860092019-09-05 03:12:34 +0300260 staticMetadata_->addEntry(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,
261 &pixelArraySize, 2);
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200262
263 int32_t sensorSizes[] = {
264 0, 0, 2560, 1920,
265 };
Laurent Pinchart39860092019-09-05 03:12:34 +0300266 staticMetadata_->addEntry(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,
267 &sensorSizes, 4);
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200268
269 int32_t sensitivityRange[] = {
270 32, 2400,
271 };
Laurent Pinchart39860092019-09-05 03:12:34 +0300272 staticMetadata_->addEntry(ANDROID_SENSOR_INFO_SENSITIVITY_RANGE,
273 &sensitivityRange, 2);
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200274
275 uint16_t filterArr = ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GRBG;
Laurent Pinchart39860092019-09-05 03:12:34 +0300276 staticMetadata_->addEntry(ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT,
277 &filterArr, 1);
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200278
279 int64_t exposureTimeRange[] = {
280 100000, 200000000,
281 };
Laurent Pinchart39860092019-09-05 03:12:34 +0300282 staticMetadata_->addEntry(ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE,
283 &exposureTimeRange, 2);
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200284
285 int32_t orientation = 0;
Laurent Pinchart39860092019-09-05 03:12:34 +0300286 staticMetadata_->addEntry(ANDROID_SENSOR_ORIENTATION,
287 &orientation, 1);
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200288
Jacopo Mondib4893fc2019-09-04 16:18:18 +0200289 std::vector<int32_t> testPatterModes = {
290 ANDROID_SENSOR_TEST_PATTERN_MODE_OFF,
291 };
Laurent Pinchart39860092019-09-05 03:12:34 +0300292 staticMetadata_->addEntry(ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES,
293 testPatterModes.data(),
294 testPatterModes.size());
Jacopo Mondib4893fc2019-09-04 16:18:18 +0200295
296 std::vector<float> physicalSize = {
297 2592, 1944,
298 };
Laurent Pinchart39860092019-09-05 03:12:34 +0300299 staticMetadata_->addEntry(ANDROID_SENSOR_INFO_PHYSICAL_SIZE,
300 physicalSize.data(),
301 physicalSize.size());
Jacopo Mondib4893fc2019-09-04 16:18:18 +0200302
303 uint8_t timestampSource = ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN;
Laurent Pinchart39860092019-09-05 03:12:34 +0300304 staticMetadata_->addEntry(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE,
305 &timestampSource, 1);
Jacopo Mondib4893fc2019-09-04 16:18:18 +0200306
307 /* Statistics static metadata. */
308 uint8_t faceDetectMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;
Laurent Pinchart39860092019-09-05 03:12:34 +0300309 staticMetadata_->addEntry(ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,
310 &faceDetectMode, 1);
Jacopo Mondib4893fc2019-09-04 16:18:18 +0200311
312 int32_t maxFaceCount = 0;
Laurent Pinchart39860092019-09-05 03:12:34 +0300313 staticMetadata_->addEntry(ANDROID_STATISTICS_INFO_MAX_FACE_COUNT,
314 &maxFaceCount, 1);
Jacopo Mondib4893fc2019-09-04 16:18:18 +0200315
316 /* Sync static metadata. */
317 int32_t maxLatency = ANDROID_SYNC_MAX_LATENCY_UNKNOWN;
Laurent Pinchart39860092019-09-05 03:12:34 +0300318 staticMetadata_->addEntry(ANDROID_SYNC_MAX_LATENCY, &maxLatency, 1);
Jacopo Mondib4893fc2019-09-04 16:18:18 +0200319
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200320 /* Flash static metadata. */
321 char flashAvailable = ANDROID_FLASH_INFO_AVAILABLE_FALSE;
Laurent Pinchart39860092019-09-05 03:12:34 +0300322 staticMetadata_->addEntry(ANDROID_FLASH_INFO_AVAILABLE,
323 &flashAvailable, 1);
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200324
325 /* Lens static metadata. */
Jacopo Mondib4893fc2019-09-04 16:18:18 +0200326 std::vector<float> lensApertures = {
327 2.53 / 100,
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200328 };
Laurent Pinchart39860092019-09-05 03:12:34 +0300329 staticMetadata_->addEntry(ANDROID_LENS_INFO_AVAILABLE_APERTURES,
330 lensApertures.data(),
331 lensApertures.size());
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200332
Jacopo Mondib4893fc2019-09-04 16:18:18 +0200333 uint8_t lensFacing = ANDROID_LENS_FACING_FRONT;
Laurent Pinchart39860092019-09-05 03:12:34 +0300334 staticMetadata_->addEntry(ANDROID_LENS_FACING, &lensFacing, 1);
Jacopo Mondib4893fc2019-09-04 16:18:18 +0200335
336 std::vector<float> lensFocalLenghts = {
337 1,
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200338 };
Laurent Pinchart39860092019-09-05 03:12:34 +0300339 staticMetadata_->addEntry(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,
340 lensFocalLenghts.data(),
341 lensFocalLenghts.size());
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200342
Jacopo Mondib4893fc2019-09-04 16:18:18 +0200343 std::vector<uint8_t> opticalStabilizations = {
344 ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF,
345 };
Laurent Pinchart39860092019-09-05 03:12:34 +0300346 staticMetadata_->addEntry(ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
347 opticalStabilizations.data(),
348 opticalStabilizations.size());
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200349
Jacopo Mondib4893fc2019-09-04 16:18:18 +0200350 float hypeFocalDistance = 0;
Laurent Pinchart39860092019-09-05 03:12:34 +0300351 staticMetadata_->addEntry(ANDROID_LENS_INFO_HYPERFOCAL_DISTANCE,
352 &hypeFocalDistance, 1);
Jacopo Mondib4893fc2019-09-04 16:18:18 +0200353
354 float minFocusDistance = 0;
Laurent Pinchart39860092019-09-05 03:12:34 +0300355 staticMetadata_->addEntry(ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE,
356 &minFocusDistance, 1);
Jacopo Mondib4893fc2019-09-04 16:18:18 +0200357
358 /* Noise reduction modes. */
359 uint8_t noiseReductionModes = ANDROID_NOISE_REDUCTION_MODE_OFF;
Laurent Pinchart39860092019-09-05 03:12:34 +0300360 staticMetadata_->addEntry(ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
361 &noiseReductionModes, 1);
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200362
363 /* Scaler static metadata. */
Jacopo Mondib4893fc2019-09-04 16:18:18 +0200364 float maxDigitalZoom = 1;
Laurent Pinchart39860092019-09-05 03:12:34 +0300365 staticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
366 &maxDigitalZoom, 1);
Jacopo Mondib4893fc2019-09-04 16:18:18 +0200367
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200368 std::vector<uint32_t> availableStreamFormats = {
369 ANDROID_SCALER_AVAILABLE_FORMATS_BLOB,
370 ANDROID_SCALER_AVAILABLE_FORMATS_YCbCr_420_888,
371 ANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED,
372 };
Laurent Pinchart39860092019-09-05 03:12:34 +0300373 staticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_FORMATS,
374 availableStreamFormats.data(),
375 availableStreamFormats.size());
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200376
377 std::vector<uint32_t> availableStreamConfigurations = {
378 ANDROID_SCALER_AVAILABLE_FORMATS_BLOB, 2560, 1920,
379 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
380 ANDROID_SCALER_AVAILABLE_FORMATS_YCbCr_420_888, 2560, 1920,
381 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
382 ANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED, 2560, 1920,
383 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
384 };
Laurent Pinchart39860092019-09-05 03:12:34 +0300385 staticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
386 availableStreamConfigurations.data(),
387 availableStreamConfigurations.size());
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200388
389 std::vector<int64_t> availableStallDurations = {
390 ANDROID_SCALER_AVAILABLE_FORMATS_BLOB, 2560, 1920, 33333333,
391 };
Laurent Pinchart39860092019-09-05 03:12:34 +0300392 staticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_STALL_DURATIONS,
393 availableStallDurations.data(),
394 availableStallDurations.size());
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200395
396 std::vector<int64_t> minFrameDurations = {
397 ANDROID_SCALER_AVAILABLE_FORMATS_BLOB, 2560, 1920, 33333333,
398 ANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED, 2560, 1920, 33333333,
399 ANDROID_SCALER_AVAILABLE_FORMATS_YCbCr_420_888, 2560, 1920, 33333333,
400 };
Laurent Pinchart39860092019-09-05 03:12:34 +0300401 staticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,
402 minFrameDurations.data(),
403 minFrameDurations.size());
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200404
Jacopo Mondib4893fc2019-09-04 16:18:18 +0200405 uint8_t croppingType = ANDROID_SCALER_CROPPING_TYPE_CENTER_ONLY;
Laurent Pinchart39860092019-09-05 03:12:34 +0300406 staticMetadata_->addEntry(ANDROID_SCALER_CROPPING_TYPE, &croppingType, 1);
Jacopo Mondib4893fc2019-09-04 16:18:18 +0200407
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200408 /* Info static metadata. */
409 uint8_t supportedHWLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;
Laurent Pinchart39860092019-09-05 03:12:34 +0300410 staticMetadata_->addEntry(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,
411 &supportedHWLevel, 1);
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200412
Jacopo Mondib4893fc2019-09-04 16:18:18 +0200413 /* Request static metadata. */
414 int32_t partialResultCount = 1;
Laurent Pinchart39860092019-09-05 03:12:34 +0300415 staticMetadata_->addEntry(ANDROID_REQUEST_PARTIAL_RESULT_COUNT,
416 &partialResultCount, 1);
Jacopo Mondib4893fc2019-09-04 16:18:18 +0200417
418 uint8_t maxPipelineDepth = 2;
Laurent Pinchart39860092019-09-05 03:12:34 +0300419 staticMetadata_->addEntry(ANDROID_REQUEST_PIPELINE_MAX_DEPTH,
420 &maxPipelineDepth, 1);
Jacopo Mondib4893fc2019-09-04 16:18:18 +0200421
422 std::vector<uint8_t> availableCapabilities = {
423 ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE,
424 };
Laurent Pinchart39860092019-09-05 03:12:34 +0300425 staticMetadata_->addEntry(ANDROID_REQUEST_AVAILABLE_CAPABILITIES,
426 availableCapabilities.data(),
427 availableCapabilities.size());
Jacopo Mondib4893fc2019-09-04 16:18:18 +0200428
Laurent Pinchart39860092019-09-05 03:12:34 +0300429 if (!staticMetadata_->isValid()) {
430 LOG(HAL, Error) << "Failed to construct static metadata";
431 delete staticMetadata_;
432 staticMetadata_ = nullptr;
433 return nullptr;
434 }
435
436 return staticMetadata_->get();
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200437}
438
439/*
440 * Produce a metadata pack to be used as template for a capture request.
441 */
442const camera_metadata_t *CameraDevice::constructDefaultRequestSettings(int type)
443{
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200444 /*
445 * \todo Inspect type and pick the right metadata pack.
446 * As of now just use a single one for all templates.
447 */
448 uint8_t captureIntent;
449 switch (type) {
450 case CAMERA3_TEMPLATE_PREVIEW:
451 captureIntent = ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW;
452 break;
453 case CAMERA3_TEMPLATE_STILL_CAPTURE:
454 captureIntent = ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE;
455 break;
456 case CAMERA3_TEMPLATE_VIDEO_RECORD:
457 captureIntent = ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_RECORD;
458 break;
459 case CAMERA3_TEMPLATE_VIDEO_SNAPSHOT:
460 captureIntent = ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT;
461 break;
462 case CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG:
463 captureIntent = ANDROID_CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG;
464 break;
465 case CAMERA3_TEMPLATE_MANUAL:
466 captureIntent = ANDROID_CONTROL_CAPTURE_INTENT_MANUAL;
467 break;
468 default:
469 LOG(HAL, Error) << "Invalid template request type: " << type;
470 return nullptr;
471 }
472
473 if (requestTemplate_)
Laurent Pinchart39860092019-09-05 03:12:34 +0300474 return requestTemplate_->get();
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200475
Jacopo Mondi63703472019-09-04 16:18:22 +0200476 /*
477 * \todo Keep this in sync with the actual number of entries.
478 * Currently: 12 entries, 15 bytes
479 */
Laurent Pinchart39860092019-09-05 03:12:34 +0300480 requestTemplate_ = new CameraMetadata(15, 20);
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200481 if (!requestTemplate_) {
482 LOG(HAL, Error) << "Failed to allocate template metadata";
Laurent Pinchart39860092019-09-05 03:12:34 +0300483 delete requestTemplate_;
484 requestTemplate_ = nullptr;
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200485 return nullptr;
486 }
487
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200488 uint8_t aeMode = ANDROID_CONTROL_AE_MODE_ON;
Laurent Pinchart39860092019-09-05 03:12:34 +0300489 requestTemplate_->addEntry(ANDROID_CONTROL_AE_MODE,
490 &aeMode, 1);
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200491
492 int32_t aeExposureCompensation = 0;
Laurent Pinchart39860092019-09-05 03:12:34 +0300493 requestTemplate_->addEntry(ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
494 &aeExposureCompensation, 1);
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200495
496 uint8_t aePrecaptureTrigger = ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE;
Laurent Pinchart39860092019-09-05 03:12:34 +0300497 requestTemplate_->addEntry(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
498 &aePrecaptureTrigger, 1);
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200499
500 uint8_t aeLock = ANDROID_CONTROL_AE_LOCK_OFF;
Laurent Pinchart39860092019-09-05 03:12:34 +0300501 requestTemplate_->addEntry(ANDROID_CONTROL_AE_LOCK,
502 &aeLock, 1);
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200503
504 uint8_t afTrigger = ANDROID_CONTROL_AF_TRIGGER_IDLE;
Laurent Pinchart39860092019-09-05 03:12:34 +0300505 requestTemplate_->addEntry(ANDROID_CONTROL_AF_TRIGGER,
506 &afTrigger, 1);
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200507
508 uint8_t awbMode = ANDROID_CONTROL_AWB_MODE_AUTO;
Laurent Pinchart39860092019-09-05 03:12:34 +0300509 requestTemplate_->addEntry(ANDROID_CONTROL_AWB_MODE,
510 &awbMode, 1);
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200511
512 uint8_t awbLock = ANDROID_CONTROL_AWB_LOCK_OFF;
Laurent Pinchart39860092019-09-05 03:12:34 +0300513 requestTemplate_->addEntry(ANDROID_CONTROL_AWB_LOCK,
514 &awbLock, 1);
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200515
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200516 uint8_t flashMode = ANDROID_FLASH_MODE_OFF;
Laurent Pinchart39860092019-09-05 03:12:34 +0300517 requestTemplate_->addEntry(ANDROID_FLASH_MODE,
518 &flashMode, 1);
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200519
520 uint8_t faceDetectMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;
Laurent Pinchart39860092019-09-05 03:12:34 +0300521 requestTemplate_->addEntry(ANDROID_STATISTICS_FACE_DETECT_MODE,
522 &faceDetectMode, 1);
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200523
Jacopo Mondi9b361dc2019-09-04 16:18:21 +0200524 uint8_t noiseReduction = ANDROID_NOISE_REDUCTION_MODE_OFF;
Laurent Pinchart39860092019-09-05 03:12:34 +0300525 requestTemplate_->addEntry(ANDROID_NOISE_REDUCTION_MODE,
526 &noiseReduction, 1);
Jacopo Mondi9b361dc2019-09-04 16:18:21 +0200527
528 uint8_t aberrationMode = ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF;
Laurent Pinchart39860092019-09-05 03:12:34 +0300529 requestTemplate_->addEntry(ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
530 &aberrationMode, 1);
Jacopo Mondi9b361dc2019-09-04 16:18:21 +0200531
Laurent Pinchart39860092019-09-05 03:12:34 +0300532 requestTemplate_->addEntry(ANDROID_CONTROL_CAPTURE_INTENT,
533 &captureIntent, 1);
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200534
Laurent Pinchart39860092019-09-05 03:12:34 +0300535 if (!requestTemplate_->isValid()) {
536 LOG(HAL, Error) << "Failed to construct request template";
537 delete requestTemplate_;
538 requestTemplate_ = nullptr;
539 return nullptr;
540 }
541
542 return requestTemplate_->get();
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200543}
544
545/*
546 * Inspect the stream_list to produce a list of StreamConfiguration to
547 * be use to configure the Camera.
548 */
549int CameraDevice::configureStreams(camera3_stream_configuration_t *stream_list)
550{
551 for (unsigned int i = 0; i < stream_list->num_streams; ++i) {
552 camera3_stream_t *stream = stream_list->streams[i];
553
554 LOG(HAL, Info) << "Stream #" << i
555 << ", direction: " << stream->stream_type
556 << ", width: " << stream->width
557 << ", height: " << stream->height
558 << ", format: " << std::hex << stream->format;
559 }
560
561 /* Hardcode viewfinder role, collecting sizes from the stream config. */
562 if (stream_list->num_streams != 1) {
563 LOG(HAL, Error) << "Only one stream supported";
564 return -EINVAL;
565 }
566
567 StreamRoles roles = { StreamRole::Viewfinder };
568 config_ = camera_->generateConfiguration(roles);
569 if (!config_ || config_->empty()) {
570 LOG(HAL, Error) << "Failed to generate camera configuration";
571 return -EINVAL;
572 }
573
574 /* Only one stream is supported. */
575 camera3_stream_t *camera3Stream = stream_list->streams[0];
576 StreamConfiguration *streamConfiguration = &config_->at(0);
577 streamConfiguration->size.width = camera3Stream->width;
578 streamConfiguration->size.height = camera3Stream->height;
579 streamConfiguration->memoryType = ExternalMemory;
580
581 /*
582 * \todo We'll need to translate from Android defined pixel format codes
583 * to the libcamera image format codes. For now, do not change the
584 * format returned from Camera::generateConfiguration().
585 */
586
587 switch (config_->validate()) {
588 case CameraConfiguration::Valid:
589 break;
590 case CameraConfiguration::Adjusted:
591 LOG(HAL, Info) << "Camera configuration adjusted";
592 config_.reset();
593 return -EINVAL;
594 case CameraConfiguration::Invalid:
595 LOG(HAL, Info) << "Camera configuration invalid";
596 config_.reset();
597 return -EINVAL;
598 }
599
600 camera3Stream->max_buffers = streamConfiguration->bufferCount;
601
602 /*
603 * Once the CameraConfiguration has been adjusted/validated
604 * it can be applied to the camera.
605 */
606 int ret = camera_->configure(config_.get());
607 if (ret) {
608 LOG(HAL, Error) << "Failed to configure camera '"
609 << camera_->name() << "'";
610 return ret;
611 }
612
613 return 0;
614}
615
616int CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Request)
617{
618 StreamConfiguration *streamConfiguration = &config_->at(0);
619 Stream *stream = streamConfiguration->stream();
620
621 if (camera3Request->num_output_buffers != 1) {
622 LOG(HAL, Error) << "Invalid number of output buffers: "
623 << camera3Request->num_output_buffers;
624 return -EINVAL;
625 }
626
627 /* Start the camera if that's the first request we handle. */
628 if (!running_) {
629 int ret = camera_->allocateBuffers();
630 if (ret) {
631 LOG(HAL, Error) << "Failed to allocate buffers";
632 return ret;
633 }
634
635 ret = camera_->start();
636 if (ret) {
637 LOG(HAL, Error) << "Failed to start camera";
638 camera_->freeBuffers();
639 return ret;
640 }
641
642 running_ = true;
643 }
644
645 /*
646 * Queue a request for the Camera with the provided dmabuf file
647 * descriptors.
648 */
649 const camera3_stream_buffer_t *camera3Buffers =
650 camera3Request->output_buffers;
651
652 /*
653 * Save the request descriptors for use at completion time.
654 * The descriptor and the associated memory reserved here are freed
655 * at request complete time.
656 */
657 Camera3RequestDescriptor *descriptor =
658 new Camera3RequestDescriptor(camera3Request->frame_number,
659 camera3Request->num_output_buffers);
660 for (unsigned int i = 0; i < descriptor->numBuffers; ++i) {
661 /*
662 * Keep track of which stream the request belongs to and store
663 * the native buffer handles.
664 *
665 * \todo Currently we only support one capture buffer. Copy
666 * all of them to be ready once we'll support more.
667 */
668 descriptor->buffers[i].stream = camera3Buffers[i].stream;
669 descriptor->buffers[i].buffer = camera3Buffers[i].buffer;
670 }
671
672 /*
673 * Create a libcamera buffer using the dmabuf descriptors of the first
674 * and (currently) only supported request buffer.
675 */
676 const buffer_handle_t camera3Handle = *camera3Buffers[0].buffer;
677 std::array<int, 3> fds = {
678 camera3Handle->data[0],
679 camera3Handle->data[1],
680 camera3Handle->data[2],
681 };
682
683 std::unique_ptr<Buffer> buffer = stream->createBuffer(fds);
684 if (!buffer) {
685 LOG(HAL, Error) << "Failed to create buffer";
686 delete descriptor;
687 return -EINVAL;
688 }
689
690 Request *request =
691 camera_->createRequest(reinterpret_cast<uint64_t>(descriptor));
692 request->addBuffer(std::move(buffer));
693
694 int ret = camera_->queueRequest(request);
695 if (ret) {
696 LOG(HAL, Error) << "Failed to queue request";
697 goto error;
698 }
699
700 return 0;
701
702error:
703 delete request;
704 delete descriptor;
705
706 return ret;
707}
708
709void CameraDevice::requestComplete(Request *request,
710 const std::map<Stream *, Buffer *> &buffers)
711{
712 Buffer *libcameraBuffer = buffers.begin()->second;
713 camera3_buffer_status status = CAMERA3_BUFFER_STATUS_OK;
Laurent Pinchart39860092019-09-05 03:12:34 +0300714 std::unique_ptr<CameraMetadata> resultMetadata;
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200715
716 if (request->status() != Request::RequestComplete) {
717 LOG(HAL, Error) << "Request not succesfully completed: "
718 << request->status();
719 status = CAMERA3_BUFFER_STATUS_ERROR;
720 }
721
722 /* Prepare to call back the Android camera stack. */
723 Camera3RequestDescriptor *descriptor =
724 reinterpret_cast<Camera3RequestDescriptor *>(request->cookie());
725
726 camera3_capture_result_t captureResult = {};
727 captureResult.frame_number = descriptor->frameNumber;
728 captureResult.num_output_buffers = descriptor->numBuffers;
729 for (unsigned int i = 0; i < descriptor->numBuffers; ++i) {
730 /*
731 * \todo Currently we only support one capture buffer. Prepare
732 * all of them to be ready once we'll support more.
733 */
734 descriptor->buffers[i].acquire_fence = -1;
735 descriptor->buffers[i].release_fence = -1;
736 descriptor->buffers[i].status = status;
737 }
738 captureResult.output_buffers =
739 const_cast<const camera3_stream_buffer_t *>(descriptor->buffers);
740
Laurent Pinchart39860092019-09-05 03:12:34 +0300741 if (status == CAMERA3_BUFFER_STATUS_OK) {
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200742 notifyShutter(descriptor->frameNumber,
743 libcameraBuffer->timestamp());
744
745 captureResult.partial_result = 1;
746 resultMetadata = getResultMetadata(descriptor->frameNumber,
747 libcameraBuffer->timestamp());
Laurent Pinchart39860092019-09-05 03:12:34 +0300748 captureResult.result = resultMetadata->get();
749 }
750
751 if (status == CAMERA3_BUFFER_STATUS_ERROR || !captureResult.result) {
752 /* \todo Improve error handling. In case we notify an error
753 * because the metadata generation fails, a shutter event has
754 * already been notified for this frame number before the error
755 * is here signalled. Make sure the error path plays well with
756 * the camera stack state machine.
757 */
758 notifyError(descriptor->frameNumber,
759 descriptor->buffers[0].stream);
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200760 }
761
762 callbacks_->process_capture_result(callbacks_, &captureResult);
763
764 delete descriptor;
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200765}
766
767void CameraDevice::notifyShutter(uint32_t frameNumber, uint64_t timestamp)
768{
769 camera3_notify_msg_t notify = {};
770
771 notify.type = CAMERA3_MSG_SHUTTER;
772 notify.message.shutter.frame_number = frameNumber;
773 notify.message.shutter.timestamp = timestamp;
774
775 callbacks_->notify(callbacks_, &notify);
776}
777
778void CameraDevice::notifyError(uint32_t frameNumber, camera3_stream_t *stream)
779{
780 camera3_notify_msg_t notify = {};
781
782 notify.type = CAMERA3_MSG_ERROR;
783 notify.message.error.error_stream = stream;
784 notify.message.error.frame_number = frameNumber;
785 notify.message.error.error_code = CAMERA3_MSG_ERROR_REQUEST;
786
787 callbacks_->notify(callbacks_, &notify);
788}
789
790/*
791 * Produce a set of fixed result metadata.
792 */
Laurent Pinchart39860092019-09-05 03:12:34 +0300793std::unique_ptr<CameraMetadata> CameraDevice::getResultMetadata(int frame_number,
794 int64_t timestamp)
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200795{
Jacopo Mondi48504ba2019-09-04 16:18:19 +0200796 /*
797 * \todo Keep this in sync with the actual number of entries.
Laurent Pinchart39860092019-09-05 03:12:34 +0300798 * Currently: 12 entries, 36 bytes
Jacopo Mondi48504ba2019-09-04 16:18:19 +0200799 */
Laurent Pinchart39860092019-09-05 03:12:34 +0300800 std::unique_ptr<CameraMetadata> resultMetadata =
801 utils::make_unique<CameraMetadata>(15, 50);
802 if (!resultMetadata->isValid()) {
803 LOG(HAL, Error) << "Failed to allocate static metadata";
804 return nullptr;
805 }
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200806
807 const uint8_t ae_state = ANDROID_CONTROL_AE_STATE_CONVERGED;
Laurent Pinchart39860092019-09-05 03:12:34 +0300808 resultMetadata->addEntry(ANDROID_CONTROL_AE_STATE, &ae_state, 1);
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200809
810 const uint8_t ae_lock = ANDROID_CONTROL_AE_LOCK_OFF;
Laurent Pinchart39860092019-09-05 03:12:34 +0300811 resultMetadata->addEntry(ANDROID_CONTROL_AE_LOCK, &ae_lock, 1);
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200812
813 uint8_t af_state = ANDROID_CONTROL_AF_STATE_INACTIVE;
Laurent Pinchart39860092019-09-05 03:12:34 +0300814 resultMetadata->addEntry(ANDROID_CONTROL_AF_STATE, &af_state, 1);
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200815
816 const uint8_t awb_state = ANDROID_CONTROL_AWB_STATE_CONVERGED;
Laurent Pinchart39860092019-09-05 03:12:34 +0300817 resultMetadata->addEntry(ANDROID_CONTROL_AWB_STATE, &awb_state, 1);
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200818
819 const uint8_t awb_lock = ANDROID_CONTROL_AWB_LOCK_OFF;
Laurent Pinchart39860092019-09-05 03:12:34 +0300820 resultMetadata->addEntry(ANDROID_CONTROL_AWB_LOCK, &awb_lock, 1);
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200821
822 const uint8_t lens_state = ANDROID_LENS_STATE_STATIONARY;
Laurent Pinchart39860092019-09-05 03:12:34 +0300823 resultMetadata->addEntry(ANDROID_LENS_STATE, &lens_state, 1);
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200824
825 int32_t sensorSizes[] = {
826 0, 0, 2560, 1920,
827 };
Laurent Pinchart39860092019-09-05 03:12:34 +0300828 resultMetadata->addEntry(ANDROID_SCALER_CROP_REGION, sensorSizes, 4);
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200829
Laurent Pinchart39860092019-09-05 03:12:34 +0300830 resultMetadata->addEntry(ANDROID_SENSOR_TIMESTAMP, &timestamp, 1);
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200831
832 /* 33.3 msec */
833 const int64_t rolling_shutter_skew = 33300000;
Laurent Pinchart39860092019-09-05 03:12:34 +0300834 resultMetadata->addEntry(ANDROID_SENSOR_ROLLING_SHUTTER_SKEW,
835 &rolling_shutter_skew, 1);
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200836
837 /* 16.6 msec */
838 const int64_t exposure_time = 16600000;
Laurent Pinchart39860092019-09-05 03:12:34 +0300839 resultMetadata->addEntry(ANDROID_SENSOR_EXPOSURE_TIME,
840 &exposure_time, 1);
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200841
842 const uint8_t lens_shading_map_mode =
843 ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF;
Laurent Pinchart39860092019-09-05 03:12:34 +0300844 resultMetadata->addEntry(ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,
845 &lens_shading_map_mode, 1);
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200846
847 const uint8_t scene_flicker = ANDROID_STATISTICS_SCENE_FLICKER_NONE;
Laurent Pinchart39860092019-09-05 03:12:34 +0300848 resultMetadata->addEntry(ANDROID_STATISTICS_SCENE_FLICKER,
849 &scene_flicker, 1);
850
851 /*
852 * Return the result metadata pack even is not valid: get() will return
853 * nullptr.
854 */
855 if (!resultMetadata->isValid()) {
856 LOG(HAL, Error) << "Failed to construct result metadata";
857 }
Jacopo Mondi667d8ea2019-05-10 17:40:02 +0200858
859 return resultMetadata;
860}