blob: ee7ffaa8d66a8ef33ad4c7aa062f10c3f6421d08 [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 Yeh2d61bfd2018-03-14 13:50:23 -070045constexpr int MAX_RETRY = 5; // Allow retry v4l2 open failures a few times.
46constexpr int OPEN_RETRY_SLEEP_US = 100000; // 100ms * MAX_RETRY = 0.5 seconds
47
Yin-Chia Yeh19030592017-10-19 17:30:11 -070048} // anonymous namespace
49
Yin-Chia Yeh17982492018-02-05 17:41:01 -080050ExternalCameraDevice::ExternalCameraDevice(
51 const std::string& cameraId, const ExternalCameraConfig& cfg) :
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -080052 mCameraId(cameraId),
Yin-Chia Yeh17982492018-02-05 17:41:01 -080053 mCfg(cfg) {
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -080054
Yin-Chia Yeh19030592017-10-19 17:30:11 -070055 status_t ret = initCameraCharacteristics();
56 if (ret != OK) {
57 ALOGE("%s: init camera characteristics failed: errorno %d", __FUNCTION__, ret);
58 mInitFailed = true;
59 }
60}
61
62ExternalCameraDevice::~ExternalCameraDevice() {}
63
64bool ExternalCameraDevice::isInitFailed() {
65 return mInitFailed;
66}
67
68Return<void> ExternalCameraDevice::getResourceCost(getResourceCost_cb _hidl_cb) {
69 CameraResourceCost resCost;
70 resCost.resourceCost = 100;
71 _hidl_cb(Status::OK, resCost);
72 return Void();
73}
74
75Return<void> ExternalCameraDevice::getCameraCharacteristics(
76 getCameraCharacteristics_cb _hidl_cb) {
77 Mutex::Autolock _l(mLock);
78 V3_2::CameraMetadata hidlChars;
79
80 if (isInitFailed()) {
81 _hidl_cb(Status::INTERNAL_ERROR, hidlChars);
82 return Void();
83 }
84
85 const camera_metadata_t* rawMetadata = mCameraCharacteristics.getAndLock();
86 V3_2::implementation::convertToHidl(rawMetadata, &hidlChars);
87 _hidl_cb(Status::OK, hidlChars);
88 mCameraCharacteristics.unlock(rawMetadata);
89 return Void();
90}
91
92Return<Status> ExternalCameraDevice::setTorchMode(TorchMode) {
93 return Status::METHOD_NOT_SUPPORTED;
94}
95
96Return<void> ExternalCameraDevice::open(
97 const sp<ICameraDeviceCallback>& callback, open_cb _hidl_cb) {
98 Status status = Status::OK;
99 sp<ExternalCameraDeviceSession> session = nullptr;
100
101 if (callback == nullptr) {
102 ALOGE("%s: cannot open camera %s. callback is null!",
103 __FUNCTION__, mCameraId.c_str());
104 _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
105 return Void();
106 }
107
108 if (isInitFailed()) {
109 ALOGE("%s: cannot open camera %s. camera init failed!",
110 __FUNCTION__, mCameraId.c_str());
111 _hidl_cb(Status::INTERNAL_ERROR, nullptr);
112 return Void();
113 }
114
115 mLock.lock();
116
117 ALOGV("%s: Initializing device for camera %s", __FUNCTION__, mCameraId.c_str());
118 session = mSession.promote();
119 if (session != nullptr && !session->isClosed()) {
120 ALOGE("%s: cannot open an already opened camera!", __FUNCTION__);
121 mLock.unlock();
122 _hidl_cb(Status::CAMERA_IN_USE, nullptr);
123 return Void();
124 }
125
126 unique_fd fd(::open(mCameraId.c_str(), O_RDWR));
127 if (fd.get() < 0) {
Yin-Chia Yeh2d61bfd2018-03-14 13:50:23 -0700128 int numAttempt = 0;
129 do {
130 ALOGW("%s: v4l2 device %s open failed, wait 33ms and try again",
131 __FUNCTION__, mCameraId.c_str());
132 usleep(OPEN_RETRY_SLEEP_US); // sleep and try again
133 fd.reset(::open(mCameraId.c_str(), O_RDWR));
134 numAttempt++;
135 } while (fd.get() < 0 && numAttempt <= MAX_RETRY);
136
137 if (fd.get() < 0) {
138 ALOGE("%s: v4l2 device open %s failed: %s",
139 __FUNCTION__, mCameraId.c_str(), strerror(errno));
140 mLock.unlock();
141 _hidl_cb(Status::INTERNAL_ERROR, nullptr);
142 return Void();
143 }
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700144 }
145
146 session = new ExternalCameraDeviceSession(
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800147 callback, mCfg, mSupportedFormats, mCroppingType,
Yin-Chia Yeh4a3393c2018-02-14 12:47:16 -0800148 mCameraCharacteristics, mCameraId, std::move(fd));
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700149 if (session == nullptr) {
150 ALOGE("%s: camera device session allocation failed", __FUNCTION__);
151 mLock.unlock();
152 _hidl_cb(Status::INTERNAL_ERROR, nullptr);
153 return Void();
154 }
155 if (session->isInitFailed()) {
156 ALOGE("%s: camera device session init failed", __FUNCTION__);
157 session = nullptr;
158 mLock.unlock();
159 _hidl_cb(Status::INTERNAL_ERROR, nullptr);
160 return Void();
161 }
162 mSession = session;
163
164 mLock.unlock();
165
166 _hidl_cb(status, session->getInterface());
167 return Void();
168}
169
170Return<void> ExternalCameraDevice::dumpState(const ::android::hardware::hidl_handle& handle) {
171 Mutex::Autolock _l(mLock);
172 if (handle.getNativeHandle() == nullptr) {
173 ALOGE("%s: handle must not be null", __FUNCTION__);
174 return Void();
175 }
176 if (handle->numFds != 1 || handle->numInts != 0) {
177 ALOGE("%s: handle must contain 1 FD and 0 integers! Got %d FDs and %d ints",
178 __FUNCTION__, handle->numFds, handle->numInts);
179 return Void();
180 }
181 int fd = handle->data[0];
182 if (mSession == nullptr) {
183 dprintf(fd, "No active camera device session instance\n");
184 return Void();
185 }
186 auto session = mSession.promote();
187 if (session == nullptr) {
188 dprintf(fd, "No active camera device session instance\n");
189 return Void();
190 }
191 // Call into active session to dump states
192 session->dumpState(handle);
193 return Void();
194}
195
196
197status_t ExternalCameraDevice::initCameraCharacteristics() {
198 if (mCameraCharacteristics.isEmpty()) {
199 // init camera characteristics
200 unique_fd fd(::open(mCameraId.c_str(), O_RDWR));
201 if (fd.get() < 0) {
202 ALOGE("%s: v4l2 device open %s failed", __FUNCTION__, mCameraId.c_str());
203 return DEAD_OBJECT;
204 }
205
206 status_t ret;
207 ret = initDefaultCharsKeys(&mCameraCharacteristics);
208 if (ret != OK) {
209 ALOGE("%s: init default characteristics key failed: errorno %d", __FUNCTION__, ret);
210 mCameraCharacteristics.clear();
211 return ret;
212 }
213
214 ret = initCameraControlsCharsKeys(fd.get(), &mCameraCharacteristics);
215 if (ret != OK) {
216 ALOGE("%s: init camera control characteristics key failed: errorno %d", __FUNCTION__, ret);
217 mCameraCharacteristics.clear();
218 return ret;
219 }
220
221 ret = initOutputCharsKeys(fd.get(), &mCameraCharacteristics);
222 if (ret != OK) {
223 ALOGE("%s: init output characteristics key failed: errorno %d", __FUNCTION__, ret);
224 mCameraCharacteristics.clear();
225 return ret;
226 }
227 }
228 return OK;
229}
230
231#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
232#define UPDATE(tag, data, size) \
233do { \
234 if (metadata->update((tag), (data), (size))) { \
235 ALOGE("Update " #tag " failed!"); \
236 return -EINVAL; \
237 } \
238} while (0)
239
240status_t ExternalCameraDevice::initDefaultCharsKeys(
241 ::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) {
Yin-Chia Yeh4acd76e2018-01-23 15:29:14 -0800242 const uint8_t hardware_level = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL;
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700243 UPDATE(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL, &hardware_level, 1);
244
245 // android.colorCorrection
246 const uint8_t availableAberrationModes[] = {
247 ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF};
248 UPDATE(ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
249 availableAberrationModes, ARRAY_SIZE(availableAberrationModes));
250
251 // android.control
252 const uint8_t antibandingMode =
253 ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO;
254 UPDATE(ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
255 &antibandingMode, 1);
256
257 const int32_t controlMaxRegions[] = {/*AE*/ 0, /*AWB*/ 0, /*AF*/ 0};
258 UPDATE(ANDROID_CONTROL_MAX_REGIONS, controlMaxRegions,
259 ARRAY_SIZE(controlMaxRegions));
260
261 const uint8_t videoStabilizationMode =
262 ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF;
263 UPDATE(ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
264 &videoStabilizationMode, 1);
265
266 const uint8_t awbAvailableMode = ANDROID_CONTROL_AWB_MODE_AUTO;
267 UPDATE(ANDROID_CONTROL_AWB_AVAILABLE_MODES, &awbAvailableMode, 1);
268
269 const uint8_t aeAvailableMode = ANDROID_CONTROL_AE_MODE_ON;
270 UPDATE(ANDROID_CONTROL_AE_AVAILABLE_MODES, &aeAvailableMode, 1);
271
272 const uint8_t availableFffect = ANDROID_CONTROL_EFFECT_MODE_OFF;
273 UPDATE(ANDROID_CONTROL_AVAILABLE_EFFECTS, &availableFffect, 1);
274
275 const uint8_t controlAvailableModes[] = {ANDROID_CONTROL_MODE_OFF,
276 ANDROID_CONTROL_MODE_AUTO};
277 UPDATE(ANDROID_CONTROL_AVAILABLE_MODES, controlAvailableModes,
278 ARRAY_SIZE(controlAvailableModes));
279
280 // android.edge
281 const uint8_t edgeMode = ANDROID_EDGE_MODE_OFF;
282 UPDATE(ANDROID_EDGE_AVAILABLE_EDGE_MODES, &edgeMode, 1);
283
284 // android.flash
285 const uint8_t flashInfo = ANDROID_FLASH_INFO_AVAILABLE_FALSE;
286 UPDATE(ANDROID_FLASH_INFO_AVAILABLE, &flashInfo, 1);
287
288 // android.hotPixel
289 const uint8_t hotPixelMode = ANDROID_HOT_PIXEL_MODE_OFF;
290 UPDATE(ANDROID_HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES, &hotPixelMode, 1);
291
292 // android.jpeg
293 // TODO: b/72261675 See if we can provide thumbnail size for all jpeg aspect ratios
294 const int32_t jpegAvailableThumbnailSizes[] = {0, 0, 240, 180};
295 UPDATE(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES, jpegAvailableThumbnailSizes,
296 ARRAY_SIZE(jpegAvailableThumbnailSizes));
297
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800298 const int32_t jpegMaxSize = mCfg.maxJpegBufSize;
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700299 UPDATE(ANDROID_JPEG_MAX_SIZE, &jpegMaxSize, 1);
300
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700301 // android.lens
302 const uint8_t focusDistanceCalibration =
303 ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION_UNCALIBRATED;
304 UPDATE(ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION, &focusDistanceCalibration, 1);
305
306 const uint8_t opticalStabilizationMode =
307 ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF;
308 UPDATE(ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
309 &opticalStabilizationMode, 1);
310
311 const uint8_t facing = ANDROID_LENS_FACING_EXTERNAL;
312 UPDATE(ANDROID_LENS_FACING, &facing, 1);
313
314 // android.noiseReduction
315 const uint8_t noiseReductionMode = ANDROID_NOISE_REDUCTION_MODE_OFF;
316 UPDATE(ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
317 &noiseReductionMode, 1);
318 UPDATE(ANDROID_NOISE_REDUCTION_MODE, &noiseReductionMode, 1);
319
320 // android.request
321 const uint8_t availableCapabilities[] = {
322 ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE};
323 UPDATE(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, availableCapabilities,
324 ARRAY_SIZE(availableCapabilities));
325
326 const int32_t partialResultCount = 1;
327 UPDATE(ANDROID_REQUEST_PARTIAL_RESULT_COUNT, &partialResultCount, 1);
328
329 // This means pipeline latency of X frame intervals. The maximum number is 4.
330 const uint8_t requestPipelineMaxDepth = 4;
331 UPDATE(ANDROID_REQUEST_PIPELINE_MAX_DEPTH, &requestPipelineMaxDepth, 1);
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700332
333 // Three numbers represent the maximum numbers of different types of output
334 // streams simultaneously. The types are raw sensor, processed (but not
335 // stalling), and processed (but stalling). For usb limited mode, raw sensor
336 // is not supported. Stalling stream is JPEG. Non-stalling streams are
337 // YUV_420_888 or YV12.
338 const int32_t requestMaxNumOutputStreams[] = {
339 /*RAW*/0,
340 /*Processed*/ExternalCameraDeviceSession::kMaxProcessedStream,
341 /*Stall*/ExternalCameraDeviceSession::kMaxStallStream};
342 UPDATE(ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS, requestMaxNumOutputStreams,
343 ARRAY_SIZE(requestMaxNumOutputStreams));
344
345 // Limited mode doesn't support reprocessing.
346 const int32_t requestMaxNumInputStreams = 0;
347 UPDATE(ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS, &requestMaxNumInputStreams,
348 1);
349
350 // android.scaler
351 // TODO: b/72263447 V4L2_CID_ZOOM_*
352 const float scalerAvailableMaxDigitalZoom[] = {1};
353 UPDATE(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
354 scalerAvailableMaxDigitalZoom,
355 ARRAY_SIZE(scalerAvailableMaxDigitalZoom));
356
357 const uint8_t croppingType = ANDROID_SCALER_CROPPING_TYPE_CENTER_ONLY;
358 UPDATE(ANDROID_SCALER_CROPPING_TYPE, &croppingType, 1);
359
360 const int32_t testPatternModes[] = {
361 ANDROID_SENSOR_TEST_PATTERN_MODE_OFF};
362 UPDATE(ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES, testPatternModes,
363 ARRAY_SIZE(testPatternModes));
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700364
365 const uint8_t timestampSource = ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN;
366 UPDATE(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE, &timestampSource, 1);
367
368 // Orientation probably isn't useful for external facing camera?
369 const int32_t orientation = 0;
370 UPDATE(ANDROID_SENSOR_ORIENTATION, &orientation, 1);
371
372 // android.shading
373 const uint8_t availabeMode = ANDROID_SHADING_MODE_OFF;
374 UPDATE(ANDROID_SHADING_AVAILABLE_MODES, &availabeMode, 1);
375
376 // android.statistics
377 const uint8_t faceDetectMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;
378 UPDATE(ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES, &faceDetectMode,
379 1);
380
381 const int32_t maxFaceCount = 0;
382 UPDATE(ANDROID_STATISTICS_INFO_MAX_FACE_COUNT, &maxFaceCount, 1);
383
384 const uint8_t availableHotpixelMode =
385 ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE_OFF;
386 UPDATE(ANDROID_STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES,
387 &availableHotpixelMode, 1);
388
389 const uint8_t lensShadingMapMode =
390 ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF;
391 UPDATE(ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES,
392 &lensShadingMapMode, 1);
393
394 // android.sync
395 const int32_t maxLatency = ANDROID_SYNC_MAX_LATENCY_UNKNOWN;
396 UPDATE(ANDROID_SYNC_MAX_LATENCY, &maxLatency, 1);
397
398 /* Other sensor/RAW realted keys:
399 * android.sensor.info.colorFilterArrangement -> no need if we don't do RAW
400 * android.sensor.info.physicalSize -> not available
401 * android.sensor.info.whiteLevel -> not available/not needed
402 * android.sensor.info.lensShadingApplied -> not needed
403 * android.sensor.info.preCorrectionActiveArraySize -> not available/not needed
404 * android.sensor.blackLevelPattern -> not available/not needed
405 */
406
407 const int32_t availableRequestKeys[] = {
408 ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
409 ANDROID_CONTROL_AE_ANTIBANDING_MODE,
410 ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
411 ANDROID_CONTROL_AE_LOCK,
412 ANDROID_CONTROL_AE_MODE,
413 ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
414 ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
415 ANDROID_CONTROL_AF_MODE,
416 ANDROID_CONTROL_AF_TRIGGER,
417 ANDROID_CONTROL_AWB_LOCK,
418 ANDROID_CONTROL_AWB_MODE,
419 ANDROID_CONTROL_CAPTURE_INTENT,
420 ANDROID_CONTROL_EFFECT_MODE,
421 ANDROID_CONTROL_MODE,
422 ANDROID_CONTROL_SCENE_MODE,
423 ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
424 ANDROID_FLASH_MODE,
425 ANDROID_JPEG_ORIENTATION,
426 ANDROID_JPEG_QUALITY,
427 ANDROID_JPEG_THUMBNAIL_QUALITY,
428 ANDROID_JPEG_THUMBNAIL_SIZE,
429 ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
430 ANDROID_NOISE_REDUCTION_MODE,
431 ANDROID_SCALER_CROP_REGION,
432 ANDROID_SENSOR_TEST_PATTERN_MODE,
433 ANDROID_STATISTICS_FACE_DETECT_MODE,
434 ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE};
435 UPDATE(ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS, availableRequestKeys,
436 ARRAY_SIZE(availableRequestKeys));
437
438 const int32_t availableResultKeys[] = {
439 ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
440 ANDROID_CONTROL_AE_ANTIBANDING_MODE,
441 ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
442 ANDROID_CONTROL_AE_LOCK,
443 ANDROID_CONTROL_AE_MODE,
444 ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
445 ANDROID_CONTROL_AE_STATE,
446 ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
447 ANDROID_CONTROL_AF_MODE,
448 ANDROID_CONTROL_AF_STATE,
449 ANDROID_CONTROL_AF_TRIGGER,
450 ANDROID_CONTROL_AWB_LOCK,
451 ANDROID_CONTROL_AWB_MODE,
452 ANDROID_CONTROL_AWB_STATE,
453 ANDROID_CONTROL_CAPTURE_INTENT,
454 ANDROID_CONTROL_EFFECT_MODE,
455 ANDROID_CONTROL_MODE,
456 ANDROID_CONTROL_SCENE_MODE,
457 ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
458 ANDROID_FLASH_MODE,
459 ANDROID_FLASH_STATE,
460 ANDROID_JPEG_ORIENTATION,
461 ANDROID_JPEG_QUALITY,
462 ANDROID_JPEG_THUMBNAIL_QUALITY,
463 ANDROID_JPEG_THUMBNAIL_SIZE,
464 ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
465 ANDROID_NOISE_REDUCTION_MODE,
466 ANDROID_REQUEST_PIPELINE_DEPTH,
467 ANDROID_SCALER_CROP_REGION,
468 ANDROID_SENSOR_TIMESTAMP,
469 ANDROID_STATISTICS_FACE_DETECT_MODE,
470 ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE,
471 ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,
472 ANDROID_STATISTICS_SCENE_FLICKER};
473 UPDATE(ANDROID_REQUEST_AVAILABLE_RESULT_KEYS, availableResultKeys,
474 ARRAY_SIZE(availableResultKeys));
475
476 const int32_t availableCharacteristicsKeys[] = {
477 ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
478 ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
479 ANDROID_CONTROL_AE_AVAILABLE_MODES,
480 ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
481 ANDROID_CONTROL_AE_COMPENSATION_RANGE,
482 ANDROID_CONTROL_AE_COMPENSATION_STEP,
483 ANDROID_CONTROL_AE_LOCK_AVAILABLE,
484 ANDROID_CONTROL_AF_AVAILABLE_MODES,
485 ANDROID_CONTROL_AVAILABLE_EFFECTS,
486 ANDROID_CONTROL_AVAILABLE_MODES,
487 ANDROID_CONTROL_AVAILABLE_SCENE_MODES,
488 ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
489 ANDROID_CONTROL_AWB_AVAILABLE_MODES,
490 ANDROID_CONTROL_AWB_LOCK_AVAILABLE,
491 ANDROID_CONTROL_MAX_REGIONS,
492 ANDROID_FLASH_INFO_AVAILABLE,
493 ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,
494 ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,
495 ANDROID_LENS_FACING,
496 ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
497 ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION,
498 ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
499 ANDROID_REQUEST_AVAILABLE_CAPABILITIES,
500 ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS,
501 ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS,
502 ANDROID_REQUEST_PARTIAL_RESULT_COUNT,
503 ANDROID_REQUEST_PIPELINE_MAX_DEPTH,
504 ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
505 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
506 ANDROID_SCALER_CROPPING_TYPE,
507 ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,
508 ANDROID_SENSOR_INFO_MAX_FRAME_DURATION,
509 ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,
510 ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE,
511 ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE,
512 ANDROID_SENSOR_ORIENTATION,
513 ANDROID_SHADING_AVAILABLE_MODES,
514 ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,
515 ANDROID_STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES,
516 ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES,
517 ANDROID_STATISTICS_INFO_MAX_FACE_COUNT,
518 ANDROID_SYNC_MAX_LATENCY};
519 UPDATE(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS,
520 availableCharacteristicsKeys,
521 ARRAY_SIZE(availableCharacteristicsKeys));
522
523 return OK;
524}
525
526status_t ExternalCameraDevice::initCameraControlsCharsKeys(int,
527 ::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) {
528 /**
529 * android.sensor.info.sensitivityRange -> V4L2_CID_ISO_SENSITIVITY
530 * android.sensor.info.exposureTimeRange -> V4L2_CID_EXPOSURE_ABSOLUTE
531 * android.sensor.info.maxFrameDuration -> TBD
532 * android.lens.info.minimumFocusDistance -> V4L2_CID_FOCUS_ABSOLUTE
533 * android.lens.info.hyperfocalDistance
534 * android.lens.info.availableFocalLengths -> not available?
535 */
536
537 // android.control
538 // No AE compensation support for now.
539 // TODO: V4L2_CID_EXPOSURE_BIAS
540 const int32_t controlAeCompensationRange[] = {0, 0};
541 UPDATE(ANDROID_CONTROL_AE_COMPENSATION_RANGE, controlAeCompensationRange,
542 ARRAY_SIZE(controlAeCompensationRange));
543 const camera_metadata_rational_t controlAeCompensationStep[] = {{0, 1}};
544 UPDATE(ANDROID_CONTROL_AE_COMPENSATION_STEP, controlAeCompensationStep,
545 ARRAY_SIZE(controlAeCompensationStep));
546
547
548 // TODO: Check V4L2_CID_AUTO_FOCUS_*.
549 const uint8_t afAvailableModes[] = {ANDROID_CONTROL_AF_MODE_AUTO,
550 ANDROID_CONTROL_AF_MODE_OFF};
551 UPDATE(ANDROID_CONTROL_AF_AVAILABLE_MODES, afAvailableModes,
552 ARRAY_SIZE(afAvailableModes));
553
554 // TODO: V4L2_CID_SCENE_MODE
555 const uint8_t availableSceneMode = ANDROID_CONTROL_SCENE_MODE_DISABLED;
556 UPDATE(ANDROID_CONTROL_AVAILABLE_SCENE_MODES, &availableSceneMode, 1);
557
558 // TODO: V4L2_CID_3A_LOCK
559 const uint8_t aeLockAvailable = ANDROID_CONTROL_AE_LOCK_AVAILABLE_FALSE;
560 UPDATE(ANDROID_CONTROL_AE_LOCK_AVAILABLE, &aeLockAvailable, 1);
561 const uint8_t awbLockAvailable = ANDROID_CONTROL_AWB_LOCK_AVAILABLE_FALSE;
562 UPDATE(ANDROID_CONTROL_AWB_LOCK_AVAILABLE, &awbLockAvailable, 1);
563
564 // TODO: V4L2_CID_ZOOM_*
565 const float scalerAvailableMaxDigitalZoom[] = {1};
566 UPDATE(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
567 scalerAvailableMaxDigitalZoom,
568 ARRAY_SIZE(scalerAvailableMaxDigitalZoom));
569
570 return OK;
571}
572
573status_t ExternalCameraDevice::initOutputCharsKeys(int fd,
574 ::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) {
575 initSupportedFormatsLocked(fd);
576 if (mSupportedFormats.empty()) {
577 ALOGE("%s: Init supported format list failed", __FUNCTION__);
578 return UNKNOWN_ERROR;
579 }
580
581 std::vector<int32_t> streamConfigurations;
582 std::vector<int64_t> minFrameDurations;
583 std::vector<int64_t> stallDurations;
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700584 int32_t maxFps = std::numeric_limits<int32_t>::min();
585 int32_t minFps = std::numeric_limits<int32_t>::max();
586 std::set<int32_t> framerates;
587
588 std::array<int, /*size*/3> halFormats{{
589 HAL_PIXEL_FORMAT_BLOB,
590 HAL_PIXEL_FORMAT_YCbCr_420_888,
591 HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED}};
592
593 for (const auto& supportedFormat : mSupportedFormats) {
594 for (const auto& format : halFormats) {
595 streamConfigurations.push_back(format);
596 streamConfigurations.push_back(supportedFormat.width);
597 streamConfigurations.push_back(supportedFormat.height);
598 streamConfigurations.push_back(
599 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT);
600 }
601
Yin-Chia Yeh134093a2018-02-12 14:05:48 -0800602 int64_t minFrameDuration = std::numeric_limits<int64_t>::max();
603 for (const auto& fr : supportedFormat.frameRates) {
604 // 1000000000LL < (2^32 - 1) and
605 // fr.durationNumerator is uint32_t, so no overflow here
606 int64_t frameDuration = 1000000000LL * fr.durationNumerator /
607 fr.durationDenominator;
608 if (frameDuration < minFrameDuration) {
609 minFrameDuration = frameDuration;
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700610 }
Yin-Chia Yeh134093a2018-02-12 14:05:48 -0800611 int32_t frameRateInt = static_cast<int32_t>(fr.getDouble());
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700612 if (minFps > frameRateInt) {
613 minFps = frameRateInt;
614 }
615 if (maxFps < frameRateInt) {
616 maxFps = frameRateInt;
617 }
618 framerates.insert(frameRateInt);
619 }
620
621 for (const auto& format : halFormats) {
622 minFrameDurations.push_back(format);
623 minFrameDurations.push_back(supportedFormat.width);
624 minFrameDurations.push_back(supportedFormat.height);
Yin-Chia Yeh134093a2018-02-12 14:05:48 -0800625 minFrameDurations.push_back(minFrameDuration);
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700626 }
627
628 // The stall duration is 0 for non-jpeg formats. For JPEG format, stall
629 // duration can be 0 if JPEG is small. Here we choose 1 sec for JPEG.
630 // TODO: b/72261675. Maybe set this dynamically
631 for (const auto& format : halFormats) {
632 const int64_t NS_TO_SECOND = 1000000000;
633 int64_t stall_duration =
634 (format == HAL_PIXEL_FORMAT_BLOB) ? NS_TO_SECOND : 0;
635 stallDurations.push_back(format);
636 stallDurations.push_back(supportedFormat.width);
637 stallDurations.push_back(supportedFormat.height);
638 stallDurations.push_back(stall_duration);
639 }
640 }
641
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700642 std::vector<int32_t> fpsRanges;
Yin-Chia Yeh8b699aa2018-02-28 15:58:54 -0800643 // FPS ranges
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700644 for (const auto& framerate : framerates) {
Yin-Chia Yeh8b699aa2018-02-28 15:58:54 -0800645 // Empirical: webcams often have close to 2x fps error and cannot support fixed fps range
646 fpsRanges.push_back(framerate / 2);
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700647 fpsRanges.push_back(framerate);
648 }
Yin-Chia Yehc15a1ca2018-03-02 14:16:52 -0800649 minFps /= 2;
650 int64_t maxFrameDuration = 1000000000LL / minFps;
Yin-Chia Yeh8b699aa2018-02-28 15:58:54 -0800651
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700652 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 Yeh3aa9ae92018-02-23 17:21:51 -0800692 int fd, double 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) {
Yin-Chia Yeh134093a2018-02-12 14:05:48 -0800707 SupportedV4L2Format::FrameRate fr = {
708 frameInterval.discrete.numerator,
709 frameInterval.discrete.denominator};
710 double framerate = fr.getDouble();
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800711 if (framerate > fpsUpperBound) {
712 continue;
713 }
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800714 ALOGV("index:%d, format:%c%c%c%c, w %d, h %d, framerate %f",
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700715 frameInterval.index,
716 frameInterval.pixel_format & 0xFF,
717 (frameInterval.pixel_format >> 8) & 0xFF,
718 (frameInterval.pixel_format >> 16) & 0xFF,
719 (frameInterval.pixel_format >> 24) & 0xFF,
720 frameInterval.width, frameInterval.height, framerate);
Yin-Chia Yeh134093a2018-02-12 14:05:48 -0800721 format->frameRates.push_back(fr);
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700722 }
723 }
724 }
725
726 if (format->frameRates.empty()) {
727 ALOGE("%s: failed to get supported frame rates for format:%c%c%c%c w %d h %d",
728 __FUNCTION__,
729 frameInterval.pixel_format & 0xFF,
730 (frameInterval.pixel_format >> 8) & 0xFF,
731 (frameInterval.pixel_format >> 16) & 0xFF,
732 (frameInterval.pixel_format >> 24) & 0xFF,
733 frameInterval.width, frameInterval.height);
734 }
735}
736
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800737void ExternalCameraDevice::trimSupportedFormats(
738 CroppingType cropType,
739 /*inout*/std::vector<SupportedV4L2Format>* pFmts) {
740 std::vector<SupportedV4L2Format>& sortedFmts = *pFmts;
741 if (cropType == VERTICAL) {
742 std::sort(sortedFmts.begin(), sortedFmts.end(),
743 [](const SupportedV4L2Format& a, const SupportedV4L2Format& b) -> bool {
744 if (a.width == b.width) {
745 return a.height < b.height;
746 }
747 return a.width < b.width;
748 });
749 } else {
750 std::sort(sortedFmts.begin(), sortedFmts.end(),
751 [](const SupportedV4L2Format& a, const SupportedV4L2Format& b) -> bool {
752 if (a.height == b.height) {
753 return a.width < b.width;
754 }
755 return a.height < b.height;
756 });
757 }
758
759 if (sortedFmts.size() == 0) {
760 ALOGE("%s: input format list is empty!", __FUNCTION__);
761 return;
762 }
763
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800764 const auto& maxSize = sortedFmts[sortedFmts.size() - 1];
765 float maxSizeAr = ASPECT_RATIO(maxSize);
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800766
767 // Remove formats that has aspect ratio not croppable from largest size
768 std::vector<SupportedV4L2Format> out;
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800769 for (const auto& fmt : sortedFmts) {
770 float ar = ASPECT_RATIO(fmt);
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800771 if (isAspectRatioClose(ar, maxSizeAr)) {
772 out.push_back(fmt);
773 } else if (cropType == HORIZONTAL && ar < maxSizeAr) {
774 out.push_back(fmt);
775 } else if (cropType == VERTICAL && ar > maxSizeAr) {
776 out.push_back(fmt);
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800777 } else {
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800778 ALOGV("%s: size (%d,%d) is removed due to unable to crop %s from (%d,%d)",
779 __FUNCTION__, fmt.width, fmt.height,
780 cropType == VERTICAL ? "vertically" : "horizontally",
781 maxSize.width, maxSize.height);
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800782 }
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800783 }
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800784 sortedFmts = out;
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800785}
786
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800787std::vector<SupportedV4L2Format>
788ExternalCameraDevice::getCandidateSupportedFormatsLocked(
789 int fd, CroppingType cropType,
790 const std::vector<ExternalCameraConfig::FpsLimitation>& fpsLimits) {
791 std::vector<SupportedV4L2Format> outFmts;
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700792 struct v4l2_fmtdesc fmtdesc {
793 .index = 0,
794 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE};
795 int ret = 0;
796 while (ret == 0) {
797 ret = TEMP_FAILURE_RETRY(ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc));
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800798 ALOGV("index:%d,ret:%d, format:%c%c%c%c", fmtdesc.index, ret,
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700799 fmtdesc.pixelformat & 0xFF,
800 (fmtdesc.pixelformat >> 8) & 0xFF,
801 (fmtdesc.pixelformat >> 16) & 0xFF,
802 (fmtdesc.pixelformat >> 24) & 0xFF);
803 if (ret == 0 && !(fmtdesc.flags & V4L2_FMT_FLAG_EMULATED)) {
804 auto it = std::find (
805 kSupportedFourCCs.begin(), kSupportedFourCCs.end(), fmtdesc.pixelformat);
806 if (it != kSupportedFourCCs.end()) {
807 // Found supported format
808 v4l2_frmsizeenum frameSize {
809 .index = 0,
810 .pixel_format = fmtdesc.pixelformat};
811 for (; TEMP_FAILURE_RETRY(ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frameSize)) == 0;
812 ++frameSize.index) {
813 if (frameSize.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800814 ALOGV("index:%d, format:%c%c%c%c, w %d, h %d", frameSize.index,
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700815 fmtdesc.pixelformat & 0xFF,
816 (fmtdesc.pixelformat >> 8) & 0xFF,
817 (fmtdesc.pixelformat >> 16) & 0xFF,
818 (fmtdesc.pixelformat >> 24) & 0xFF,
819 frameSize.discrete.width, frameSize.discrete.height);
820 // Disregard h > w formats so all aspect ratio (h/w) <= 1.0
821 // This will simplify the crop/scaling logic down the road
822 if (frameSize.discrete.height > frameSize.discrete.width) {
823 continue;
824 }
825 SupportedV4L2Format format {
826 .width = frameSize.discrete.width,
827 .height = frameSize.discrete.height,
828 .fourcc = fmtdesc.pixelformat
829 };
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800830
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800831 double fpsUpperBound = -1.0;
832 for (const auto& limit : fpsLimits) {
833 if (cropType == VERTICAL) {
834 if (format.width <= limit.size.width) {
835 fpsUpperBound = limit.fpsUpperBound;
836 break;
837 }
838 } else { // HORIZONTAL
839 if (format.height <= limit.size.height) {
840 fpsUpperBound = limit.fpsUpperBound;
841 break;
842 }
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800843 }
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800844
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800845 }
846 if (fpsUpperBound < 0.f) {
847 continue;
848 }
849
850 getFrameRateList(fd, fpsUpperBound, &format);
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700851 if (!format.frameRates.empty()) {
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800852 outFmts.push_back(format);
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700853 }
854 }
855 }
856 }
857 }
858 fmtdesc.index++;
859 }
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800860 trimSupportedFormats(cropType, &outFmts);
861 return outFmts;
862}
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800863
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800864void ExternalCameraDevice::initSupportedFormatsLocked(int fd) {
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800865
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800866 std::vector<SupportedV4L2Format> horizontalFmts =
867 getCandidateSupportedFormatsLocked(fd, HORIZONTAL, mCfg.fpsLimits);
868 std::vector<SupportedV4L2Format> verticalFmts =
869 getCandidateSupportedFormatsLocked(fd, VERTICAL, mCfg.fpsLimits);
870
871 size_t horiSize = horizontalFmts.size();
872 size_t vertSize = verticalFmts.size();
873
874 if (horiSize == 0 && vertSize == 0) {
875 ALOGE("%s: cannot find suitable cropping type!", __FUNCTION__);
876 return;
877 }
878
879 if (horiSize == 0) {
880 mSupportedFormats = verticalFmts;
881 mCroppingType = VERTICAL;
882 return;
883 } else if (vertSize == 0) {
884 mSupportedFormats = horizontalFmts;
885 mCroppingType = HORIZONTAL;
886 return;
887 }
888
889 const auto& maxHoriSize = horizontalFmts[horizontalFmts.size() - 1];
890 const auto& maxVertSize = verticalFmts[verticalFmts.size() - 1];
891
892 // Try to keep largest possible output size
893 // When they are the same or ambiguous, pick the one support more sizes
894 if (maxHoriSize.width == maxVertSize.width &&
895 maxHoriSize.height == maxVertSize.height) {
896 if (horiSize > vertSize) {
897 mSupportedFormats = horizontalFmts;
898 mCroppingType = HORIZONTAL;
899 } else {
900 mSupportedFormats = verticalFmts;
901 mCroppingType = VERTICAL;
902 }
903 } else if (maxHoriSize.width >= maxVertSize.width &&
904 maxHoriSize.height >= maxVertSize.height) {
905 mSupportedFormats = horizontalFmts;
906 mCroppingType = HORIZONTAL;
907 } else if (maxHoriSize.width <= maxVertSize.width &&
908 maxHoriSize.height <= maxVertSize.height) {
909 mSupportedFormats = verticalFmts;
910 mCroppingType = VERTICAL;
911 } else {
912 if (horiSize > vertSize) {
913 mSupportedFormats = horizontalFmts;
914 mCroppingType = HORIZONTAL;
915 } else {
916 mSupportedFormats = verticalFmts;
917 mCroppingType = VERTICAL;
918 }
919 }
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700920}
921
922} // namespace implementation
923} // namespace V3_4
924} // namespace device
925} // namespace camera
926} // namespace hardware
927} // namespace android
928