blob: 569acfd5104d35daf45c9386b2d30d4c86ef1ed4 [file] [log] [blame]
Yin-Chia Yeh19030592017-10-19 17:30:11 -07001/*
2 * Copyright (C) 2018 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#define LOG_TAG "ExtCamDev@3.4"
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -080018//#define LOG_NDEBUG 0
Yin-Chia Yeh19030592017-10-19 17:30:11 -070019#include <log/log.h>
20
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -080021#include <algorithm>
Yin-Chia Yeh19030592017-10-19 17:30:11 -070022#include <array>
23#include <linux/videodev2.h>
24#include "android-base/macros.h"
25#include "CameraMetadata.h"
26#include "../../3.2/default/include/convert.h"
27#include "ExternalCameraDevice_3_4.h"
28
Yin-Chia Yeh19030592017-10-19 17:30:11 -070029namespace android {
30namespace hardware {
31namespace camera {
32namespace device {
33namespace V3_4 {
34namespace implementation {
35
36namespace {
37// Only support MJPEG for now as it seems to be the one supports higher fps
38// Other formats to consider in the future:
39// * V4L2_PIX_FMT_YVU420 (== YV12)
40// * V4L2_PIX_FMT_YVYU (YVYU: can be converted to YV12 or other YUV420_888 formats)
41const std::array<uint32_t, /*size*/1> kSupportedFourCCs {{
42 V4L2_PIX_FMT_MJPEG
43}}; // double braces required in C++11
44
Yin-Chia Yeh19030592017-10-19 17:30:11 -070045} // anonymous namespace
46
47ExternalCameraDevice::ExternalCameraDevice(const std::string& cameraId) :
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -080048 mCameraId(cameraId),
49 mCfg(ExternalCameraDeviceConfig::loadFromCfg()) {
50
Yin-Chia Yeh19030592017-10-19 17:30:11 -070051 status_t ret = initCameraCharacteristics();
52 if (ret != OK) {
53 ALOGE("%s: init camera characteristics failed: errorno %d", __FUNCTION__, ret);
54 mInitFailed = true;
55 }
56}
57
58ExternalCameraDevice::~ExternalCameraDevice() {}
59
60bool ExternalCameraDevice::isInitFailed() {
61 return mInitFailed;
62}
63
64Return<void> ExternalCameraDevice::getResourceCost(getResourceCost_cb _hidl_cb) {
65 CameraResourceCost resCost;
66 resCost.resourceCost = 100;
67 _hidl_cb(Status::OK, resCost);
68 return Void();
69}
70
71Return<void> ExternalCameraDevice::getCameraCharacteristics(
72 getCameraCharacteristics_cb _hidl_cb) {
73 Mutex::Autolock _l(mLock);
74 V3_2::CameraMetadata hidlChars;
75
76 if (isInitFailed()) {
77 _hidl_cb(Status::INTERNAL_ERROR, hidlChars);
78 return Void();
79 }
80
81 const camera_metadata_t* rawMetadata = mCameraCharacteristics.getAndLock();
82 V3_2::implementation::convertToHidl(rawMetadata, &hidlChars);
83 _hidl_cb(Status::OK, hidlChars);
84 mCameraCharacteristics.unlock(rawMetadata);
85 return Void();
86}
87
88Return<Status> ExternalCameraDevice::setTorchMode(TorchMode) {
89 return Status::METHOD_NOT_SUPPORTED;
90}
91
92Return<void> ExternalCameraDevice::open(
93 const sp<ICameraDeviceCallback>& callback, open_cb _hidl_cb) {
94 Status status = Status::OK;
95 sp<ExternalCameraDeviceSession> session = nullptr;
96
97 if (callback == nullptr) {
98 ALOGE("%s: cannot open camera %s. callback is null!",
99 __FUNCTION__, mCameraId.c_str());
100 _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
101 return Void();
102 }
103
104 if (isInitFailed()) {
105 ALOGE("%s: cannot open camera %s. camera init failed!",
106 __FUNCTION__, mCameraId.c_str());
107 _hidl_cb(Status::INTERNAL_ERROR, nullptr);
108 return Void();
109 }
110
111 mLock.lock();
112
113 ALOGV("%s: Initializing device for camera %s", __FUNCTION__, mCameraId.c_str());
114 session = mSession.promote();
115 if (session != nullptr && !session->isClosed()) {
116 ALOGE("%s: cannot open an already opened camera!", __FUNCTION__);
117 mLock.unlock();
118 _hidl_cb(Status::CAMERA_IN_USE, nullptr);
119 return Void();
120 }
121
122 unique_fd fd(::open(mCameraId.c_str(), O_RDWR));
123 if (fd.get() < 0) {
124 ALOGE("%s: v4l2 device open %s failed: %s",
125 __FUNCTION__, mCameraId.c_str(), strerror(errno));
126 mLock.unlock();
127 _hidl_cb(Status::INTERNAL_ERROR, nullptr);
128 return Void();
129 }
130
131 session = new ExternalCameraDeviceSession(
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800132 callback, mCfg, mSupportedFormats, mCroppingType,
133 mCameraCharacteristics, std::move(fd));
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700134 if (session == nullptr) {
135 ALOGE("%s: camera device session allocation failed", __FUNCTION__);
136 mLock.unlock();
137 _hidl_cb(Status::INTERNAL_ERROR, nullptr);
138 return Void();
139 }
140 if (session->isInitFailed()) {
141 ALOGE("%s: camera device session init failed", __FUNCTION__);
142 session = nullptr;
143 mLock.unlock();
144 _hidl_cb(Status::INTERNAL_ERROR, nullptr);
145 return Void();
146 }
147 mSession = session;
148
149 mLock.unlock();
150
151 _hidl_cb(status, session->getInterface());
152 return Void();
153}
154
155Return<void> ExternalCameraDevice::dumpState(const ::android::hardware::hidl_handle& handle) {
156 Mutex::Autolock _l(mLock);
157 if (handle.getNativeHandle() == nullptr) {
158 ALOGE("%s: handle must not be null", __FUNCTION__);
159 return Void();
160 }
161 if (handle->numFds != 1 || handle->numInts != 0) {
162 ALOGE("%s: handle must contain 1 FD and 0 integers! Got %d FDs and %d ints",
163 __FUNCTION__, handle->numFds, handle->numInts);
164 return Void();
165 }
166 int fd = handle->data[0];
167 if (mSession == nullptr) {
168 dprintf(fd, "No active camera device session instance\n");
169 return Void();
170 }
171 auto session = mSession.promote();
172 if (session == nullptr) {
173 dprintf(fd, "No active camera device session instance\n");
174 return Void();
175 }
176 // Call into active session to dump states
177 session->dumpState(handle);
178 return Void();
179}
180
181
182status_t ExternalCameraDevice::initCameraCharacteristics() {
183 if (mCameraCharacteristics.isEmpty()) {
184 // init camera characteristics
185 unique_fd fd(::open(mCameraId.c_str(), O_RDWR));
186 if (fd.get() < 0) {
187 ALOGE("%s: v4l2 device open %s failed", __FUNCTION__, mCameraId.c_str());
188 return DEAD_OBJECT;
189 }
190
191 status_t ret;
192 ret = initDefaultCharsKeys(&mCameraCharacteristics);
193 if (ret != OK) {
194 ALOGE("%s: init default characteristics key failed: errorno %d", __FUNCTION__, ret);
195 mCameraCharacteristics.clear();
196 return ret;
197 }
198
199 ret = initCameraControlsCharsKeys(fd.get(), &mCameraCharacteristics);
200 if (ret != OK) {
201 ALOGE("%s: init camera control characteristics key failed: errorno %d", __FUNCTION__, ret);
202 mCameraCharacteristics.clear();
203 return ret;
204 }
205
206 ret = initOutputCharsKeys(fd.get(), &mCameraCharacteristics);
207 if (ret != OK) {
208 ALOGE("%s: init output characteristics key failed: errorno %d", __FUNCTION__, ret);
209 mCameraCharacteristics.clear();
210 return ret;
211 }
212 }
213 return OK;
214}
215
216#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
217#define UPDATE(tag, data, size) \
218do { \
219 if (metadata->update((tag), (data), (size))) { \
220 ALOGE("Update " #tag " failed!"); \
221 return -EINVAL; \
222 } \
223} while (0)
224
225status_t ExternalCameraDevice::initDefaultCharsKeys(
226 ::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) {
Yin-Chia Yeh4acd76e2018-01-23 15:29:14 -0800227 const uint8_t hardware_level = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL;
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700228 UPDATE(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL, &hardware_level, 1);
229
230 // android.colorCorrection
231 const uint8_t availableAberrationModes[] = {
232 ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF};
233 UPDATE(ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
234 availableAberrationModes, ARRAY_SIZE(availableAberrationModes));
235
236 // android.control
237 const uint8_t antibandingMode =
238 ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO;
239 UPDATE(ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
240 &antibandingMode, 1);
241
242 const int32_t controlMaxRegions[] = {/*AE*/ 0, /*AWB*/ 0, /*AF*/ 0};
243 UPDATE(ANDROID_CONTROL_MAX_REGIONS, controlMaxRegions,
244 ARRAY_SIZE(controlMaxRegions));
245
246 const uint8_t videoStabilizationMode =
247 ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF;
248 UPDATE(ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
249 &videoStabilizationMode, 1);
250
251 const uint8_t awbAvailableMode = ANDROID_CONTROL_AWB_MODE_AUTO;
252 UPDATE(ANDROID_CONTROL_AWB_AVAILABLE_MODES, &awbAvailableMode, 1);
253
254 const uint8_t aeAvailableMode = ANDROID_CONTROL_AE_MODE_ON;
255 UPDATE(ANDROID_CONTROL_AE_AVAILABLE_MODES, &aeAvailableMode, 1);
256
257 const uint8_t availableFffect = ANDROID_CONTROL_EFFECT_MODE_OFF;
258 UPDATE(ANDROID_CONTROL_AVAILABLE_EFFECTS, &availableFffect, 1);
259
260 const uint8_t controlAvailableModes[] = {ANDROID_CONTROL_MODE_OFF,
261 ANDROID_CONTROL_MODE_AUTO};
262 UPDATE(ANDROID_CONTROL_AVAILABLE_MODES, controlAvailableModes,
263 ARRAY_SIZE(controlAvailableModes));
264
265 // android.edge
266 const uint8_t edgeMode = ANDROID_EDGE_MODE_OFF;
267 UPDATE(ANDROID_EDGE_AVAILABLE_EDGE_MODES, &edgeMode, 1);
268
269 // android.flash
270 const uint8_t flashInfo = ANDROID_FLASH_INFO_AVAILABLE_FALSE;
271 UPDATE(ANDROID_FLASH_INFO_AVAILABLE, &flashInfo, 1);
272
273 // android.hotPixel
274 const uint8_t hotPixelMode = ANDROID_HOT_PIXEL_MODE_OFF;
275 UPDATE(ANDROID_HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES, &hotPixelMode, 1);
276
277 // android.jpeg
278 // TODO: b/72261675 See if we can provide thumbnail size for all jpeg aspect ratios
279 const int32_t jpegAvailableThumbnailSizes[] = {0, 0, 240, 180};
280 UPDATE(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES, jpegAvailableThumbnailSizes,
281 ARRAY_SIZE(jpegAvailableThumbnailSizes));
282
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800283 const int32_t jpegMaxSize = mCfg.maxJpegBufSize;
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700284 UPDATE(ANDROID_JPEG_MAX_SIZE, &jpegMaxSize, 1);
285
286 const uint8_t jpegQuality = 90;
287 UPDATE(ANDROID_JPEG_QUALITY, &jpegQuality, 1);
288 UPDATE(ANDROID_JPEG_THUMBNAIL_QUALITY, &jpegQuality, 1);
289
290 const int32_t jpegOrientation = 0;
291 UPDATE(ANDROID_JPEG_ORIENTATION, &jpegOrientation, 1);
292
293 // android.lens
294 const uint8_t focusDistanceCalibration =
295 ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION_UNCALIBRATED;
296 UPDATE(ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION, &focusDistanceCalibration, 1);
297
298 const uint8_t opticalStabilizationMode =
299 ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF;
300 UPDATE(ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
301 &opticalStabilizationMode, 1);
302
303 const uint8_t facing = ANDROID_LENS_FACING_EXTERNAL;
304 UPDATE(ANDROID_LENS_FACING, &facing, 1);
305
306 // android.noiseReduction
307 const uint8_t noiseReductionMode = ANDROID_NOISE_REDUCTION_MODE_OFF;
308 UPDATE(ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
309 &noiseReductionMode, 1);
310 UPDATE(ANDROID_NOISE_REDUCTION_MODE, &noiseReductionMode, 1);
311
312 // android.request
313 const uint8_t availableCapabilities[] = {
314 ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE};
315 UPDATE(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, availableCapabilities,
316 ARRAY_SIZE(availableCapabilities));
317
318 const int32_t partialResultCount = 1;
319 UPDATE(ANDROID_REQUEST_PARTIAL_RESULT_COUNT, &partialResultCount, 1);
320
321 // This means pipeline latency of X frame intervals. The maximum number is 4.
322 const uint8_t requestPipelineMaxDepth = 4;
323 UPDATE(ANDROID_REQUEST_PIPELINE_MAX_DEPTH, &requestPipelineMaxDepth, 1);
324 UPDATE(ANDROID_REQUEST_PIPELINE_DEPTH, &requestPipelineMaxDepth, 1);
325
326 // Three numbers represent the maximum numbers of different types of output
327 // streams simultaneously. The types are raw sensor, processed (but not
328 // stalling), and processed (but stalling). For usb limited mode, raw sensor
329 // is not supported. Stalling stream is JPEG. Non-stalling streams are
330 // YUV_420_888 or YV12.
331 const int32_t requestMaxNumOutputStreams[] = {
332 /*RAW*/0,
333 /*Processed*/ExternalCameraDeviceSession::kMaxProcessedStream,
334 /*Stall*/ExternalCameraDeviceSession::kMaxStallStream};
335 UPDATE(ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS, requestMaxNumOutputStreams,
336 ARRAY_SIZE(requestMaxNumOutputStreams));
337
338 // Limited mode doesn't support reprocessing.
339 const int32_t requestMaxNumInputStreams = 0;
340 UPDATE(ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS, &requestMaxNumInputStreams,
341 1);
342
343 // android.scaler
344 // TODO: b/72263447 V4L2_CID_ZOOM_*
345 const float scalerAvailableMaxDigitalZoom[] = {1};
346 UPDATE(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
347 scalerAvailableMaxDigitalZoom,
348 ARRAY_SIZE(scalerAvailableMaxDigitalZoom));
349
350 const uint8_t croppingType = ANDROID_SCALER_CROPPING_TYPE_CENTER_ONLY;
351 UPDATE(ANDROID_SCALER_CROPPING_TYPE, &croppingType, 1);
352
353 const int32_t testPatternModes[] = {
354 ANDROID_SENSOR_TEST_PATTERN_MODE_OFF};
355 UPDATE(ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES, testPatternModes,
356 ARRAY_SIZE(testPatternModes));
357 UPDATE(ANDROID_SENSOR_TEST_PATTERN_MODE, &testPatternModes[0], 1);
358
359 const uint8_t timestampSource = ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN;
360 UPDATE(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE, &timestampSource, 1);
361
362 // Orientation probably isn't useful for external facing camera?
363 const int32_t orientation = 0;
364 UPDATE(ANDROID_SENSOR_ORIENTATION, &orientation, 1);
365
366 // android.shading
367 const uint8_t availabeMode = ANDROID_SHADING_MODE_OFF;
368 UPDATE(ANDROID_SHADING_AVAILABLE_MODES, &availabeMode, 1);
369
370 // android.statistics
371 const uint8_t faceDetectMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;
372 UPDATE(ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES, &faceDetectMode,
373 1);
374
375 const int32_t maxFaceCount = 0;
376 UPDATE(ANDROID_STATISTICS_INFO_MAX_FACE_COUNT, &maxFaceCount, 1);
377
378 const uint8_t availableHotpixelMode =
379 ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE_OFF;
380 UPDATE(ANDROID_STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES,
381 &availableHotpixelMode, 1);
382
383 const uint8_t lensShadingMapMode =
384 ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF;
385 UPDATE(ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES,
386 &lensShadingMapMode, 1);
387
388 // android.sync
389 const int32_t maxLatency = ANDROID_SYNC_MAX_LATENCY_UNKNOWN;
390 UPDATE(ANDROID_SYNC_MAX_LATENCY, &maxLatency, 1);
391
392 /* Other sensor/RAW realted keys:
393 * android.sensor.info.colorFilterArrangement -> no need if we don't do RAW
394 * android.sensor.info.physicalSize -> not available
395 * android.sensor.info.whiteLevel -> not available/not needed
396 * android.sensor.info.lensShadingApplied -> not needed
397 * android.sensor.info.preCorrectionActiveArraySize -> not available/not needed
398 * android.sensor.blackLevelPattern -> not available/not needed
399 */
400
401 const int32_t availableRequestKeys[] = {
402 ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
403 ANDROID_CONTROL_AE_ANTIBANDING_MODE,
404 ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
405 ANDROID_CONTROL_AE_LOCK,
406 ANDROID_CONTROL_AE_MODE,
407 ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
408 ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
409 ANDROID_CONTROL_AF_MODE,
410 ANDROID_CONTROL_AF_TRIGGER,
411 ANDROID_CONTROL_AWB_LOCK,
412 ANDROID_CONTROL_AWB_MODE,
413 ANDROID_CONTROL_CAPTURE_INTENT,
414 ANDROID_CONTROL_EFFECT_MODE,
415 ANDROID_CONTROL_MODE,
416 ANDROID_CONTROL_SCENE_MODE,
417 ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
418 ANDROID_FLASH_MODE,
419 ANDROID_JPEG_ORIENTATION,
420 ANDROID_JPEG_QUALITY,
421 ANDROID_JPEG_THUMBNAIL_QUALITY,
422 ANDROID_JPEG_THUMBNAIL_SIZE,
423 ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
424 ANDROID_NOISE_REDUCTION_MODE,
425 ANDROID_SCALER_CROP_REGION,
426 ANDROID_SENSOR_TEST_PATTERN_MODE,
427 ANDROID_STATISTICS_FACE_DETECT_MODE,
428 ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE};
429 UPDATE(ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS, availableRequestKeys,
430 ARRAY_SIZE(availableRequestKeys));
431
432 const int32_t availableResultKeys[] = {
433 ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
434 ANDROID_CONTROL_AE_ANTIBANDING_MODE,
435 ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
436 ANDROID_CONTROL_AE_LOCK,
437 ANDROID_CONTROL_AE_MODE,
438 ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
439 ANDROID_CONTROL_AE_STATE,
440 ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
441 ANDROID_CONTROL_AF_MODE,
442 ANDROID_CONTROL_AF_STATE,
443 ANDROID_CONTROL_AF_TRIGGER,
444 ANDROID_CONTROL_AWB_LOCK,
445 ANDROID_CONTROL_AWB_MODE,
446 ANDROID_CONTROL_AWB_STATE,
447 ANDROID_CONTROL_CAPTURE_INTENT,
448 ANDROID_CONTROL_EFFECT_MODE,
449 ANDROID_CONTROL_MODE,
450 ANDROID_CONTROL_SCENE_MODE,
451 ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
452 ANDROID_FLASH_MODE,
453 ANDROID_FLASH_STATE,
454 ANDROID_JPEG_ORIENTATION,
455 ANDROID_JPEG_QUALITY,
456 ANDROID_JPEG_THUMBNAIL_QUALITY,
457 ANDROID_JPEG_THUMBNAIL_SIZE,
458 ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
459 ANDROID_NOISE_REDUCTION_MODE,
460 ANDROID_REQUEST_PIPELINE_DEPTH,
461 ANDROID_SCALER_CROP_REGION,
462 ANDROID_SENSOR_TIMESTAMP,
463 ANDROID_STATISTICS_FACE_DETECT_MODE,
464 ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE,
465 ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,
466 ANDROID_STATISTICS_SCENE_FLICKER};
467 UPDATE(ANDROID_REQUEST_AVAILABLE_RESULT_KEYS, availableResultKeys,
468 ARRAY_SIZE(availableResultKeys));
469
470 const int32_t availableCharacteristicsKeys[] = {
471 ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
472 ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
473 ANDROID_CONTROL_AE_AVAILABLE_MODES,
474 ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
475 ANDROID_CONTROL_AE_COMPENSATION_RANGE,
476 ANDROID_CONTROL_AE_COMPENSATION_STEP,
477 ANDROID_CONTROL_AE_LOCK_AVAILABLE,
478 ANDROID_CONTROL_AF_AVAILABLE_MODES,
479 ANDROID_CONTROL_AVAILABLE_EFFECTS,
480 ANDROID_CONTROL_AVAILABLE_MODES,
481 ANDROID_CONTROL_AVAILABLE_SCENE_MODES,
482 ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
483 ANDROID_CONTROL_AWB_AVAILABLE_MODES,
484 ANDROID_CONTROL_AWB_LOCK_AVAILABLE,
485 ANDROID_CONTROL_MAX_REGIONS,
486 ANDROID_FLASH_INFO_AVAILABLE,
487 ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,
488 ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,
489 ANDROID_LENS_FACING,
490 ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
491 ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION,
492 ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
493 ANDROID_REQUEST_AVAILABLE_CAPABILITIES,
494 ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS,
495 ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS,
496 ANDROID_REQUEST_PARTIAL_RESULT_COUNT,
497 ANDROID_REQUEST_PIPELINE_MAX_DEPTH,
498 ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
499 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
500 ANDROID_SCALER_CROPPING_TYPE,
501 ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,
502 ANDROID_SENSOR_INFO_MAX_FRAME_DURATION,
503 ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,
504 ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE,
505 ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE,
506 ANDROID_SENSOR_ORIENTATION,
507 ANDROID_SHADING_AVAILABLE_MODES,
508 ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,
509 ANDROID_STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES,
510 ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES,
511 ANDROID_STATISTICS_INFO_MAX_FACE_COUNT,
512 ANDROID_SYNC_MAX_LATENCY};
513 UPDATE(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS,
514 availableCharacteristicsKeys,
515 ARRAY_SIZE(availableCharacteristicsKeys));
516
517 return OK;
518}
519
520status_t ExternalCameraDevice::initCameraControlsCharsKeys(int,
521 ::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) {
522 /**
523 * android.sensor.info.sensitivityRange -> V4L2_CID_ISO_SENSITIVITY
524 * android.sensor.info.exposureTimeRange -> V4L2_CID_EXPOSURE_ABSOLUTE
525 * android.sensor.info.maxFrameDuration -> TBD
526 * android.lens.info.minimumFocusDistance -> V4L2_CID_FOCUS_ABSOLUTE
527 * android.lens.info.hyperfocalDistance
528 * android.lens.info.availableFocalLengths -> not available?
529 */
530
531 // android.control
532 // No AE compensation support for now.
533 // TODO: V4L2_CID_EXPOSURE_BIAS
534 const int32_t controlAeCompensationRange[] = {0, 0};
535 UPDATE(ANDROID_CONTROL_AE_COMPENSATION_RANGE, controlAeCompensationRange,
536 ARRAY_SIZE(controlAeCompensationRange));
537 const camera_metadata_rational_t controlAeCompensationStep[] = {{0, 1}};
538 UPDATE(ANDROID_CONTROL_AE_COMPENSATION_STEP, controlAeCompensationStep,
539 ARRAY_SIZE(controlAeCompensationStep));
540
541
542 // TODO: Check V4L2_CID_AUTO_FOCUS_*.
543 const uint8_t afAvailableModes[] = {ANDROID_CONTROL_AF_MODE_AUTO,
544 ANDROID_CONTROL_AF_MODE_OFF};
545 UPDATE(ANDROID_CONTROL_AF_AVAILABLE_MODES, afAvailableModes,
546 ARRAY_SIZE(afAvailableModes));
547
548 // TODO: V4L2_CID_SCENE_MODE
549 const uint8_t availableSceneMode = ANDROID_CONTROL_SCENE_MODE_DISABLED;
550 UPDATE(ANDROID_CONTROL_AVAILABLE_SCENE_MODES, &availableSceneMode, 1);
551
552 // TODO: V4L2_CID_3A_LOCK
553 const uint8_t aeLockAvailable = ANDROID_CONTROL_AE_LOCK_AVAILABLE_FALSE;
554 UPDATE(ANDROID_CONTROL_AE_LOCK_AVAILABLE, &aeLockAvailable, 1);
555 const uint8_t awbLockAvailable = ANDROID_CONTROL_AWB_LOCK_AVAILABLE_FALSE;
556 UPDATE(ANDROID_CONTROL_AWB_LOCK_AVAILABLE, &awbLockAvailable, 1);
557
558 // TODO: V4L2_CID_ZOOM_*
559 const float scalerAvailableMaxDigitalZoom[] = {1};
560 UPDATE(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
561 scalerAvailableMaxDigitalZoom,
562 ARRAY_SIZE(scalerAvailableMaxDigitalZoom));
563
564 return OK;
565}
566
567status_t ExternalCameraDevice::initOutputCharsKeys(int fd,
568 ::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) {
569 initSupportedFormatsLocked(fd);
570 if (mSupportedFormats.empty()) {
571 ALOGE("%s: Init supported format list failed", __FUNCTION__);
572 return UNKNOWN_ERROR;
573 }
574
575 std::vector<int32_t> streamConfigurations;
576 std::vector<int64_t> minFrameDurations;
577 std::vector<int64_t> stallDurations;
578 int64_t maxFrameDuration = 0;
579 int32_t maxFps = std::numeric_limits<int32_t>::min();
580 int32_t minFps = std::numeric_limits<int32_t>::max();
581 std::set<int32_t> framerates;
582
583 std::array<int, /*size*/3> halFormats{{
584 HAL_PIXEL_FORMAT_BLOB,
585 HAL_PIXEL_FORMAT_YCbCr_420_888,
586 HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED}};
587
588 for (const auto& supportedFormat : mSupportedFormats) {
589 for (const auto& format : halFormats) {
590 streamConfigurations.push_back(format);
591 streamConfigurations.push_back(supportedFormat.width);
592 streamConfigurations.push_back(supportedFormat.height);
593 streamConfigurations.push_back(
594 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT);
595 }
596
597 int64_t min_frame_duration = std::numeric_limits<int64_t>::max();
598 for (const auto& frameRate : supportedFormat.frameRates) {
599 int64_t frame_duration = 1000000000LL / frameRate;
600 if (frame_duration < min_frame_duration) {
601 min_frame_duration = frame_duration;
602 }
603 if (frame_duration > maxFrameDuration) {
604 maxFrameDuration = frame_duration;
605 }
606 int32_t frameRateInt = static_cast<int32_t>(frameRate);
607 if (minFps > frameRateInt) {
608 minFps = frameRateInt;
609 }
610 if (maxFps < frameRateInt) {
611 maxFps = frameRateInt;
612 }
613 framerates.insert(frameRateInt);
614 }
615
616 for (const auto& format : halFormats) {
617 minFrameDurations.push_back(format);
618 minFrameDurations.push_back(supportedFormat.width);
619 minFrameDurations.push_back(supportedFormat.height);
620 minFrameDurations.push_back(min_frame_duration);
621 }
622
623 // The stall duration is 0 for non-jpeg formats. For JPEG format, stall
624 // duration can be 0 if JPEG is small. Here we choose 1 sec for JPEG.
625 // TODO: b/72261675. Maybe set this dynamically
626 for (const auto& format : halFormats) {
627 const int64_t NS_TO_SECOND = 1000000000;
628 int64_t stall_duration =
629 (format == HAL_PIXEL_FORMAT_BLOB) ? NS_TO_SECOND : 0;
630 stallDurations.push_back(format);
631 stallDurations.push_back(supportedFormat.width);
632 stallDurations.push_back(supportedFormat.height);
633 stallDurations.push_back(stall_duration);
634 }
635 }
636
637 // The document in aeAvailableTargetFpsRanges section says the minFps should
638 // not be larger than 15.
639 // We cannot support fixed 30fps but Android requires (min, max) and
640 // (max, max) ranges.
641 // TODO: populate more, right now this does not support 30,30 if the device
642 // has higher than 30 fps modes
643 std::vector<int32_t> fpsRanges;
644 // Variable range
645 fpsRanges.push_back(minFps);
646 fpsRanges.push_back(maxFps);
647 // Fixed ranges
648 for (const auto& framerate : framerates) {
649 fpsRanges.push_back(framerate);
650 fpsRanges.push_back(framerate);
651 }
652 UPDATE(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, fpsRanges.data(),
653 fpsRanges.size());
654
655 UPDATE(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
656 streamConfigurations.data(), streamConfigurations.size());
657
658 UPDATE(ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,
659 minFrameDurations.data(), minFrameDurations.size());
660
661 UPDATE(ANDROID_SCALER_AVAILABLE_STALL_DURATIONS, stallDurations.data(),
662 stallDurations.size());
663
664 UPDATE(ANDROID_SENSOR_INFO_MAX_FRAME_DURATION, &maxFrameDuration, 1);
665
666 SupportedV4L2Format maximumFormat {.width = 0, .height = 0};
667 for (const auto& supportedFormat : mSupportedFormats) {
668 if (supportedFormat.width >= maximumFormat.width &&
669 supportedFormat.height >= maximumFormat.height) {
670 maximumFormat = supportedFormat;
671 }
672 }
673 int32_t activeArraySize[] = {0, 0,
674 static_cast<int32_t>(maximumFormat.width),
675 static_cast<int32_t>(maximumFormat.height)};
676 UPDATE(ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE,
677 activeArraySize, ARRAY_SIZE(activeArraySize));
678 UPDATE(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE, activeArraySize,
679 ARRAY_SIZE(activeArraySize));
680
681 int32_t pixelArraySize[] = {static_cast<int32_t>(maximumFormat.width),
682 static_cast<int32_t>(maximumFormat.height)};
683 UPDATE(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE, pixelArraySize,
684 ARRAY_SIZE(pixelArraySize));
685 return OK;
686}
687
688#undef ARRAY_SIZE
689#undef UPDATE
690
691void ExternalCameraDevice::getFrameRateList(
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800692 int fd, float fpsUpperBound, SupportedV4L2Format* format) {
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700693 format->frameRates.clear();
694
695 v4l2_frmivalenum frameInterval {
696 .pixel_format = format->fourcc,
697 .width = format->width,
698 .height = format->height,
699 .index = 0
700 };
701
702 for (frameInterval.index = 0;
703 TEMP_FAILURE_RETRY(ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frameInterval)) == 0;
704 ++frameInterval.index) {
705 if (frameInterval.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
706 if (frameInterval.discrete.numerator != 0) {
707 float framerate = frameInterval.discrete.denominator /
708 static_cast<float>(frameInterval.discrete.numerator);
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800709 if (framerate > fpsUpperBound) {
710 continue;
711 }
712 ALOGI("index:%d, format:%c%c%c%c, w %d, h %d, framerate %f",
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700713 frameInterval.index,
714 frameInterval.pixel_format & 0xFF,
715 (frameInterval.pixel_format >> 8) & 0xFF,
716 (frameInterval.pixel_format >> 16) & 0xFF,
717 (frameInterval.pixel_format >> 24) & 0xFF,
718 frameInterval.width, frameInterval.height, framerate);
719 format->frameRates.push_back(framerate);
720 }
721 }
722 }
723
724 if (format->frameRates.empty()) {
725 ALOGE("%s: failed to get supported frame rates for format:%c%c%c%c w %d h %d",
726 __FUNCTION__,
727 frameInterval.pixel_format & 0xFF,
728 (frameInterval.pixel_format >> 8) & 0xFF,
729 (frameInterval.pixel_format >> 16) & 0xFF,
730 (frameInterval.pixel_format >> 24) & 0xFF,
731 frameInterval.width, frameInterval.height);
732 }
733}
734
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800735CroppingType ExternalCameraDevice::initCroppingType(
736 /*inout*/std::vector<SupportedV4L2Format>* pSortedFmts) {
737 std::vector<SupportedV4L2Format>& sortedFmts = *pSortedFmts;
738 const auto& maxSize = sortedFmts[sortedFmts.size() - 1];
739 float maxSizeAr = ASPECT_RATIO(maxSize);
740 float minAr = kMaxAspectRatio;
741 float maxAr = kMinAspectRatio;
742 for (const auto& fmt : sortedFmts) {
743 float ar = ASPECT_RATIO(fmt);
744 if (ar < minAr) {
745 minAr = ar;
746 }
747 if (ar > maxAr) {
748 maxAr = ar;
749 }
750 }
751
752 CroppingType ct = VERTICAL;
753 if (isAspectRatioClose(maxSizeAr, maxAr)) {
754 // Ex: 16:9 sensor, cropping horizontally to get to 4:3
755 ct = HORIZONTAL;
756 } else if (isAspectRatioClose(maxSizeAr, minAr)) {
757 // Ex: 4:3 sensor, cropping vertically to get to 16:9
758 ct = VERTICAL;
759 } else {
760 ALOGI("%s: camera maxSizeAr %f is not close to minAr %f or maxAr %f",
761 __FUNCTION__, maxSizeAr, minAr, maxAr);
762 if ((maxSizeAr - minAr) < (maxAr - maxSizeAr)) {
763 ct = VERTICAL;
764 } else {
765 ct = HORIZONTAL;
766 }
767
768 // Remove formats that has aspect ratio not croppable from largest size
769 std::vector<SupportedV4L2Format> out;
770 for (const auto& fmt : sortedFmts) {
771 float ar = ASPECT_RATIO(fmt);
772 if (isAspectRatioClose(ar, maxSizeAr)) {
773 out.push_back(fmt);
774 } else if (ct == HORIZONTAL && ar < maxSizeAr) {
775 out.push_back(fmt);
776 } else if (ct == VERTICAL && ar > maxSizeAr) {
777 out.push_back(fmt);
778 } else {
779 ALOGD("%s: size (%d,%d) is removed due to unable to crop %s from (%d,%d)",
780 __FUNCTION__, fmt.width, fmt.height,
781 ct == VERTICAL ? "vertically" : "horizontally",
782 maxSize.width, maxSize.height);
783 }
784 }
785 sortedFmts = out;
786 }
787 ALOGI("%s: camera croppingType is %s", __FUNCTION__,
788 ct == VERTICAL ? "VERTICAL" : "HORIZONTAL");
789 return ct;
790}
791
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700792void ExternalCameraDevice::initSupportedFormatsLocked(int fd) {
793 struct v4l2_fmtdesc fmtdesc {
794 .index = 0,
795 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE};
796 int ret = 0;
797 while (ret == 0) {
798 ret = TEMP_FAILURE_RETRY(ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc));
799 ALOGD("index:%d,ret:%d, format:%c%c%c%c", fmtdesc.index, ret,
800 fmtdesc.pixelformat & 0xFF,
801 (fmtdesc.pixelformat >> 8) & 0xFF,
802 (fmtdesc.pixelformat >> 16) & 0xFF,
803 (fmtdesc.pixelformat >> 24) & 0xFF);
804 if (ret == 0 && !(fmtdesc.flags & V4L2_FMT_FLAG_EMULATED)) {
805 auto it = std::find (
806 kSupportedFourCCs.begin(), kSupportedFourCCs.end(), fmtdesc.pixelformat);
807 if (it != kSupportedFourCCs.end()) {
808 // Found supported format
809 v4l2_frmsizeenum frameSize {
810 .index = 0,
811 .pixel_format = fmtdesc.pixelformat};
812 for (; TEMP_FAILURE_RETRY(ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frameSize)) == 0;
813 ++frameSize.index) {
814 if (frameSize.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800815 ALOGV("index:%d, format:%c%c%c%c, w %d, h %d", frameSize.index,
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700816 fmtdesc.pixelformat & 0xFF,
817 (fmtdesc.pixelformat >> 8) & 0xFF,
818 (fmtdesc.pixelformat >> 16) & 0xFF,
819 (fmtdesc.pixelformat >> 24) & 0xFF,
820 frameSize.discrete.width, frameSize.discrete.height);
821 // Disregard h > w formats so all aspect ratio (h/w) <= 1.0
822 // This will simplify the crop/scaling logic down the road
823 if (frameSize.discrete.height > frameSize.discrete.width) {
824 continue;
825 }
826 SupportedV4L2Format format {
827 .width = frameSize.discrete.width,
828 .height = frameSize.discrete.height,
829 .fourcc = fmtdesc.pixelformat
830 };
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800831
832 float fpsUpperBound = -1.0;
833 for (const auto& limit : mCfg.fpsLimits) {
834 if (format.width <= limit.size.width &&
835 format.height <= limit.size.height) {
836 fpsUpperBound = limit.fpsUpperBound;
837 break;
838 }
839 }
840 if (fpsUpperBound < 0.f) {
841 continue;
842 }
843
844 getFrameRateList(fd, fpsUpperBound, &format);
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700845 if (!format.frameRates.empty()) {
846 mSupportedFormats.push_back(format);
847 }
848 }
849 }
850 }
851 }
852 fmtdesc.index++;
853 }
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800854
855 std::sort(mSupportedFormats.begin(), mSupportedFormats.end(),
856 [](const SupportedV4L2Format& a, const SupportedV4L2Format& b) -> bool {
857 if (a.width == b.width) {
858 return a.height < b.height;
859 }
860 return a.width < b.width;
861 });
862
863 mCroppingType = initCroppingType(&mSupportedFormats);
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700864}
865
866} // namespace implementation
867} // namespace V3_4
868} // namespace device
869} // namespace camera
870} // namespace hardware
871} // namespace android
872