blob: e7361dd46351f8dcd1df728825f98533b0816c51 [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) {
Yin-Chia Yehbbc046e2018-08-28 10:52:43 -070093 return Status::OPERATION_NOT_SUPPORTED;
Yin-Chia Yeh19030592017-10-19 17:30:11 -070094}
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
chenhg564cdae2018-06-20 14:21:20 -0700293 const int32_t jpegAvailableThumbnailSizes[] = {0, 0,
294 176, 144,
295 240, 144,
296 256, 144,
297 240, 160,
298 256, 154,
299 240, 240,
300 320, 240};
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700301 UPDATE(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES, jpegAvailableThumbnailSizes,
302 ARRAY_SIZE(jpegAvailableThumbnailSizes));
303
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800304 const int32_t jpegMaxSize = mCfg.maxJpegBufSize;
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700305 UPDATE(ANDROID_JPEG_MAX_SIZE, &jpegMaxSize, 1);
306
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700307 // android.lens
308 const uint8_t focusDistanceCalibration =
309 ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION_UNCALIBRATED;
310 UPDATE(ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION, &focusDistanceCalibration, 1);
311
312 const uint8_t opticalStabilizationMode =
313 ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF;
314 UPDATE(ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
315 &opticalStabilizationMode, 1);
316
317 const uint8_t facing = ANDROID_LENS_FACING_EXTERNAL;
318 UPDATE(ANDROID_LENS_FACING, &facing, 1);
319
320 // android.noiseReduction
321 const uint8_t noiseReductionMode = ANDROID_NOISE_REDUCTION_MODE_OFF;
322 UPDATE(ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
323 &noiseReductionMode, 1);
324 UPDATE(ANDROID_NOISE_REDUCTION_MODE, &noiseReductionMode, 1);
325
326 // android.request
327 const uint8_t availableCapabilities[] = {
328 ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE};
329 UPDATE(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, availableCapabilities,
330 ARRAY_SIZE(availableCapabilities));
331
332 const int32_t partialResultCount = 1;
333 UPDATE(ANDROID_REQUEST_PARTIAL_RESULT_COUNT, &partialResultCount, 1);
334
335 // This means pipeline latency of X frame intervals. The maximum number is 4.
336 const uint8_t requestPipelineMaxDepth = 4;
337 UPDATE(ANDROID_REQUEST_PIPELINE_MAX_DEPTH, &requestPipelineMaxDepth, 1);
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700338
339 // Three numbers represent the maximum numbers of different types of output
340 // streams simultaneously. The types are raw sensor, processed (but not
341 // stalling), and processed (but stalling). For usb limited mode, raw sensor
342 // is not supported. Stalling stream is JPEG. Non-stalling streams are
343 // YUV_420_888 or YV12.
344 const int32_t requestMaxNumOutputStreams[] = {
345 /*RAW*/0,
346 /*Processed*/ExternalCameraDeviceSession::kMaxProcessedStream,
347 /*Stall*/ExternalCameraDeviceSession::kMaxStallStream};
348 UPDATE(ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS, requestMaxNumOutputStreams,
349 ARRAY_SIZE(requestMaxNumOutputStreams));
350
351 // Limited mode doesn't support reprocessing.
352 const int32_t requestMaxNumInputStreams = 0;
353 UPDATE(ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS, &requestMaxNumInputStreams,
354 1);
355
356 // android.scaler
357 // TODO: b/72263447 V4L2_CID_ZOOM_*
358 const float scalerAvailableMaxDigitalZoom[] = {1};
359 UPDATE(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
360 scalerAvailableMaxDigitalZoom,
361 ARRAY_SIZE(scalerAvailableMaxDigitalZoom));
362
363 const uint8_t croppingType = ANDROID_SCALER_CROPPING_TYPE_CENTER_ONLY;
364 UPDATE(ANDROID_SCALER_CROPPING_TYPE, &croppingType, 1);
365
366 const int32_t testPatternModes[] = {
367 ANDROID_SENSOR_TEST_PATTERN_MODE_OFF};
368 UPDATE(ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES, testPatternModes,
369 ARRAY_SIZE(testPatternModes));
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700370
371 const uint8_t timestampSource = ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN;
372 UPDATE(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE, &timestampSource, 1);
373
374 // Orientation probably isn't useful for external facing camera?
375 const int32_t orientation = 0;
376 UPDATE(ANDROID_SENSOR_ORIENTATION, &orientation, 1);
377
378 // android.shading
379 const uint8_t availabeMode = ANDROID_SHADING_MODE_OFF;
380 UPDATE(ANDROID_SHADING_AVAILABLE_MODES, &availabeMode, 1);
381
382 // android.statistics
383 const uint8_t faceDetectMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;
384 UPDATE(ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES, &faceDetectMode,
385 1);
386
387 const int32_t maxFaceCount = 0;
388 UPDATE(ANDROID_STATISTICS_INFO_MAX_FACE_COUNT, &maxFaceCount, 1);
389
390 const uint8_t availableHotpixelMode =
391 ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE_OFF;
392 UPDATE(ANDROID_STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES,
393 &availableHotpixelMode, 1);
394
395 const uint8_t lensShadingMapMode =
396 ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF;
397 UPDATE(ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES,
398 &lensShadingMapMode, 1);
399
400 // android.sync
401 const int32_t maxLatency = ANDROID_SYNC_MAX_LATENCY_UNKNOWN;
402 UPDATE(ANDROID_SYNC_MAX_LATENCY, &maxLatency, 1);
403
404 /* Other sensor/RAW realted keys:
405 * android.sensor.info.colorFilterArrangement -> no need if we don't do RAW
406 * android.sensor.info.physicalSize -> not available
407 * android.sensor.info.whiteLevel -> not available/not needed
408 * android.sensor.info.lensShadingApplied -> not needed
409 * android.sensor.info.preCorrectionActiveArraySize -> not available/not needed
410 * android.sensor.blackLevelPattern -> not available/not needed
411 */
412
413 const int32_t availableRequestKeys[] = {
414 ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
415 ANDROID_CONTROL_AE_ANTIBANDING_MODE,
416 ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
417 ANDROID_CONTROL_AE_LOCK,
418 ANDROID_CONTROL_AE_MODE,
419 ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
420 ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
421 ANDROID_CONTROL_AF_MODE,
422 ANDROID_CONTROL_AF_TRIGGER,
423 ANDROID_CONTROL_AWB_LOCK,
424 ANDROID_CONTROL_AWB_MODE,
425 ANDROID_CONTROL_CAPTURE_INTENT,
426 ANDROID_CONTROL_EFFECT_MODE,
427 ANDROID_CONTROL_MODE,
428 ANDROID_CONTROL_SCENE_MODE,
429 ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
430 ANDROID_FLASH_MODE,
431 ANDROID_JPEG_ORIENTATION,
432 ANDROID_JPEG_QUALITY,
433 ANDROID_JPEG_THUMBNAIL_QUALITY,
434 ANDROID_JPEG_THUMBNAIL_SIZE,
435 ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
436 ANDROID_NOISE_REDUCTION_MODE,
437 ANDROID_SCALER_CROP_REGION,
438 ANDROID_SENSOR_TEST_PATTERN_MODE,
439 ANDROID_STATISTICS_FACE_DETECT_MODE,
440 ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE};
441 UPDATE(ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS, availableRequestKeys,
442 ARRAY_SIZE(availableRequestKeys));
443
444 const int32_t availableResultKeys[] = {
445 ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
446 ANDROID_CONTROL_AE_ANTIBANDING_MODE,
447 ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
448 ANDROID_CONTROL_AE_LOCK,
449 ANDROID_CONTROL_AE_MODE,
450 ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
451 ANDROID_CONTROL_AE_STATE,
452 ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
453 ANDROID_CONTROL_AF_MODE,
454 ANDROID_CONTROL_AF_STATE,
455 ANDROID_CONTROL_AF_TRIGGER,
456 ANDROID_CONTROL_AWB_LOCK,
457 ANDROID_CONTROL_AWB_MODE,
458 ANDROID_CONTROL_AWB_STATE,
459 ANDROID_CONTROL_CAPTURE_INTENT,
460 ANDROID_CONTROL_EFFECT_MODE,
461 ANDROID_CONTROL_MODE,
462 ANDROID_CONTROL_SCENE_MODE,
463 ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
464 ANDROID_FLASH_MODE,
465 ANDROID_FLASH_STATE,
466 ANDROID_JPEG_ORIENTATION,
467 ANDROID_JPEG_QUALITY,
468 ANDROID_JPEG_THUMBNAIL_QUALITY,
469 ANDROID_JPEG_THUMBNAIL_SIZE,
470 ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
471 ANDROID_NOISE_REDUCTION_MODE,
472 ANDROID_REQUEST_PIPELINE_DEPTH,
473 ANDROID_SCALER_CROP_REGION,
474 ANDROID_SENSOR_TIMESTAMP,
475 ANDROID_STATISTICS_FACE_DETECT_MODE,
476 ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE,
477 ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,
478 ANDROID_STATISTICS_SCENE_FLICKER};
479 UPDATE(ANDROID_REQUEST_AVAILABLE_RESULT_KEYS, availableResultKeys,
480 ARRAY_SIZE(availableResultKeys));
481
482 const int32_t availableCharacteristicsKeys[] = {
483 ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
484 ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
485 ANDROID_CONTROL_AE_AVAILABLE_MODES,
486 ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
487 ANDROID_CONTROL_AE_COMPENSATION_RANGE,
488 ANDROID_CONTROL_AE_COMPENSATION_STEP,
489 ANDROID_CONTROL_AE_LOCK_AVAILABLE,
490 ANDROID_CONTROL_AF_AVAILABLE_MODES,
491 ANDROID_CONTROL_AVAILABLE_EFFECTS,
492 ANDROID_CONTROL_AVAILABLE_MODES,
493 ANDROID_CONTROL_AVAILABLE_SCENE_MODES,
494 ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
495 ANDROID_CONTROL_AWB_AVAILABLE_MODES,
496 ANDROID_CONTROL_AWB_LOCK_AVAILABLE,
497 ANDROID_CONTROL_MAX_REGIONS,
498 ANDROID_FLASH_INFO_AVAILABLE,
499 ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,
500 ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,
501 ANDROID_LENS_FACING,
502 ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
503 ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION,
504 ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
505 ANDROID_REQUEST_AVAILABLE_CAPABILITIES,
506 ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS,
507 ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS,
508 ANDROID_REQUEST_PARTIAL_RESULT_COUNT,
509 ANDROID_REQUEST_PIPELINE_MAX_DEPTH,
510 ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
511 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
512 ANDROID_SCALER_CROPPING_TYPE,
513 ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,
514 ANDROID_SENSOR_INFO_MAX_FRAME_DURATION,
515 ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,
516 ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE,
517 ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE,
518 ANDROID_SENSOR_ORIENTATION,
519 ANDROID_SHADING_AVAILABLE_MODES,
520 ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,
521 ANDROID_STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES,
522 ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES,
523 ANDROID_STATISTICS_INFO_MAX_FACE_COUNT,
524 ANDROID_SYNC_MAX_LATENCY};
525 UPDATE(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS,
526 availableCharacteristicsKeys,
527 ARRAY_SIZE(availableCharacteristicsKeys));
528
529 return OK;
530}
531
532status_t ExternalCameraDevice::initCameraControlsCharsKeys(int,
533 ::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) {
534 /**
535 * android.sensor.info.sensitivityRange -> V4L2_CID_ISO_SENSITIVITY
536 * android.sensor.info.exposureTimeRange -> V4L2_CID_EXPOSURE_ABSOLUTE
537 * android.sensor.info.maxFrameDuration -> TBD
538 * android.lens.info.minimumFocusDistance -> V4L2_CID_FOCUS_ABSOLUTE
539 * android.lens.info.hyperfocalDistance
540 * android.lens.info.availableFocalLengths -> not available?
541 */
542
543 // android.control
544 // No AE compensation support for now.
545 // TODO: V4L2_CID_EXPOSURE_BIAS
546 const int32_t controlAeCompensationRange[] = {0, 0};
547 UPDATE(ANDROID_CONTROL_AE_COMPENSATION_RANGE, controlAeCompensationRange,
548 ARRAY_SIZE(controlAeCompensationRange));
549 const camera_metadata_rational_t controlAeCompensationStep[] = {{0, 1}};
550 UPDATE(ANDROID_CONTROL_AE_COMPENSATION_STEP, controlAeCompensationStep,
551 ARRAY_SIZE(controlAeCompensationStep));
552
553
554 // TODO: Check V4L2_CID_AUTO_FOCUS_*.
555 const uint8_t afAvailableModes[] = {ANDROID_CONTROL_AF_MODE_AUTO,
556 ANDROID_CONTROL_AF_MODE_OFF};
557 UPDATE(ANDROID_CONTROL_AF_AVAILABLE_MODES, afAvailableModes,
558 ARRAY_SIZE(afAvailableModes));
559
560 // TODO: V4L2_CID_SCENE_MODE
561 const uint8_t availableSceneMode = ANDROID_CONTROL_SCENE_MODE_DISABLED;
562 UPDATE(ANDROID_CONTROL_AVAILABLE_SCENE_MODES, &availableSceneMode, 1);
563
564 // TODO: V4L2_CID_3A_LOCK
565 const uint8_t aeLockAvailable = ANDROID_CONTROL_AE_LOCK_AVAILABLE_FALSE;
566 UPDATE(ANDROID_CONTROL_AE_LOCK_AVAILABLE, &aeLockAvailable, 1);
567 const uint8_t awbLockAvailable = ANDROID_CONTROL_AWB_LOCK_AVAILABLE_FALSE;
568 UPDATE(ANDROID_CONTROL_AWB_LOCK_AVAILABLE, &awbLockAvailable, 1);
569
570 // TODO: V4L2_CID_ZOOM_*
571 const float scalerAvailableMaxDigitalZoom[] = {1};
572 UPDATE(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
573 scalerAvailableMaxDigitalZoom,
574 ARRAY_SIZE(scalerAvailableMaxDigitalZoom));
575
576 return OK;
577}
578
579status_t ExternalCameraDevice::initOutputCharsKeys(int fd,
580 ::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) {
581 initSupportedFormatsLocked(fd);
582 if (mSupportedFormats.empty()) {
583 ALOGE("%s: Init supported format list failed", __FUNCTION__);
584 return UNKNOWN_ERROR;
585 }
586
587 std::vector<int32_t> streamConfigurations;
588 std::vector<int64_t> minFrameDurations;
589 std::vector<int64_t> stallDurations;
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700590 int32_t maxFps = std::numeric_limits<int32_t>::min();
591 int32_t minFps = std::numeric_limits<int32_t>::max();
592 std::set<int32_t> framerates;
593
594 std::array<int, /*size*/3> halFormats{{
595 HAL_PIXEL_FORMAT_BLOB,
596 HAL_PIXEL_FORMAT_YCbCr_420_888,
597 HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED}};
598
599 for (const auto& supportedFormat : mSupportedFormats) {
600 for (const auto& format : halFormats) {
601 streamConfigurations.push_back(format);
602 streamConfigurations.push_back(supportedFormat.width);
603 streamConfigurations.push_back(supportedFormat.height);
604 streamConfigurations.push_back(
605 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT);
606 }
607
Yin-Chia Yeh134093a2018-02-12 14:05:48 -0800608 int64_t minFrameDuration = std::numeric_limits<int64_t>::max();
609 for (const auto& fr : supportedFormat.frameRates) {
610 // 1000000000LL < (2^32 - 1) and
611 // fr.durationNumerator is uint32_t, so no overflow here
612 int64_t frameDuration = 1000000000LL * fr.durationNumerator /
613 fr.durationDenominator;
614 if (frameDuration < minFrameDuration) {
615 minFrameDuration = frameDuration;
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700616 }
Yin-Chia Yeh134093a2018-02-12 14:05:48 -0800617 int32_t frameRateInt = static_cast<int32_t>(fr.getDouble());
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700618 if (minFps > frameRateInt) {
619 minFps = frameRateInt;
620 }
621 if (maxFps < frameRateInt) {
622 maxFps = frameRateInt;
623 }
624 framerates.insert(frameRateInt);
625 }
626
627 for (const auto& format : halFormats) {
628 minFrameDurations.push_back(format);
629 minFrameDurations.push_back(supportedFormat.width);
630 minFrameDurations.push_back(supportedFormat.height);
Yin-Chia Yeh134093a2018-02-12 14:05:48 -0800631 minFrameDurations.push_back(minFrameDuration);
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700632 }
633
634 // The stall duration is 0 for non-jpeg formats. For JPEG format, stall
635 // duration can be 0 if JPEG is small. Here we choose 1 sec for JPEG.
636 // TODO: b/72261675. Maybe set this dynamically
637 for (const auto& format : halFormats) {
638 const int64_t NS_TO_SECOND = 1000000000;
639 int64_t stall_duration =
640 (format == HAL_PIXEL_FORMAT_BLOB) ? NS_TO_SECOND : 0;
641 stallDurations.push_back(format);
642 stallDurations.push_back(supportedFormat.width);
643 stallDurations.push_back(supportedFormat.height);
644 stallDurations.push_back(stall_duration);
645 }
646 }
647
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700648 std::vector<int32_t> fpsRanges;
Yin-Chia Yeh8b699aa2018-02-28 15:58:54 -0800649 // FPS ranges
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700650 for (const auto& framerate : framerates) {
Yin-Chia Yeh8b699aa2018-02-28 15:58:54 -0800651 // Empirical: webcams often have close to 2x fps error and cannot support fixed fps range
652 fpsRanges.push_back(framerate / 2);
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700653 fpsRanges.push_back(framerate);
654 }
Yin-Chia Yehc15a1ca2018-03-02 14:16:52 -0800655 minFps /= 2;
656 int64_t maxFrameDuration = 1000000000LL / minFps;
Yin-Chia Yeh8b699aa2018-02-28 15:58:54 -0800657
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700658 UPDATE(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, fpsRanges.data(),
659 fpsRanges.size());
660
661 UPDATE(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
662 streamConfigurations.data(), streamConfigurations.size());
663
664 UPDATE(ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,
665 minFrameDurations.data(), minFrameDurations.size());
666
667 UPDATE(ANDROID_SCALER_AVAILABLE_STALL_DURATIONS, stallDurations.data(),
668 stallDurations.size());
669
670 UPDATE(ANDROID_SENSOR_INFO_MAX_FRAME_DURATION, &maxFrameDuration, 1);
671
672 SupportedV4L2Format maximumFormat {.width = 0, .height = 0};
673 for (const auto& supportedFormat : mSupportedFormats) {
674 if (supportedFormat.width >= maximumFormat.width &&
675 supportedFormat.height >= maximumFormat.height) {
676 maximumFormat = supportedFormat;
677 }
678 }
679 int32_t activeArraySize[] = {0, 0,
680 static_cast<int32_t>(maximumFormat.width),
681 static_cast<int32_t>(maximumFormat.height)};
682 UPDATE(ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE,
683 activeArraySize, ARRAY_SIZE(activeArraySize));
684 UPDATE(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE, activeArraySize,
685 ARRAY_SIZE(activeArraySize));
686
687 int32_t pixelArraySize[] = {static_cast<int32_t>(maximumFormat.width),
688 static_cast<int32_t>(maximumFormat.height)};
689 UPDATE(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE, pixelArraySize,
690 ARRAY_SIZE(pixelArraySize));
691 return OK;
692}
693
694#undef ARRAY_SIZE
695#undef UPDATE
696
697void ExternalCameraDevice::getFrameRateList(
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800698 int fd, double fpsUpperBound, SupportedV4L2Format* format) {
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700699 format->frameRates.clear();
700
701 v4l2_frmivalenum frameInterval {
702 .pixel_format = format->fourcc,
703 .width = format->width,
704 .height = format->height,
705 .index = 0
706 };
707
708 for (frameInterval.index = 0;
709 TEMP_FAILURE_RETRY(ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frameInterval)) == 0;
710 ++frameInterval.index) {
711 if (frameInterval.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
712 if (frameInterval.discrete.numerator != 0) {
Yin-Chia Yeh134093a2018-02-12 14:05:48 -0800713 SupportedV4L2Format::FrameRate fr = {
714 frameInterval.discrete.numerator,
715 frameInterval.discrete.denominator};
716 double framerate = fr.getDouble();
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800717 if (framerate > fpsUpperBound) {
718 continue;
719 }
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800720 ALOGV("index:%d, format:%c%c%c%c, w %d, h %d, framerate %f",
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700721 frameInterval.index,
722 frameInterval.pixel_format & 0xFF,
723 (frameInterval.pixel_format >> 8) & 0xFF,
724 (frameInterval.pixel_format >> 16) & 0xFF,
725 (frameInterval.pixel_format >> 24) & 0xFF,
726 frameInterval.width, frameInterval.height, framerate);
Yin-Chia Yeh134093a2018-02-12 14:05:48 -0800727 format->frameRates.push_back(fr);
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700728 }
729 }
730 }
731
732 if (format->frameRates.empty()) {
733 ALOGE("%s: failed to get supported frame rates for format:%c%c%c%c w %d h %d",
734 __FUNCTION__,
735 frameInterval.pixel_format & 0xFF,
736 (frameInterval.pixel_format >> 8) & 0xFF,
737 (frameInterval.pixel_format >> 16) & 0xFF,
738 (frameInterval.pixel_format >> 24) & 0xFF,
739 frameInterval.width, frameInterval.height);
740 }
741}
742
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800743void ExternalCameraDevice::trimSupportedFormats(
744 CroppingType cropType,
745 /*inout*/std::vector<SupportedV4L2Format>* pFmts) {
746 std::vector<SupportedV4L2Format>& sortedFmts = *pFmts;
747 if (cropType == VERTICAL) {
748 std::sort(sortedFmts.begin(), sortedFmts.end(),
749 [](const SupportedV4L2Format& a, const SupportedV4L2Format& b) -> bool {
750 if (a.width == b.width) {
751 return a.height < b.height;
752 }
753 return a.width < b.width;
754 });
755 } else {
756 std::sort(sortedFmts.begin(), sortedFmts.end(),
757 [](const SupportedV4L2Format& a, const SupportedV4L2Format& b) -> bool {
758 if (a.height == b.height) {
759 return a.width < b.width;
760 }
761 return a.height < b.height;
762 });
763 }
764
765 if (sortedFmts.size() == 0) {
766 ALOGE("%s: input format list is empty!", __FUNCTION__);
767 return;
768 }
769
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800770 const auto& maxSize = sortedFmts[sortedFmts.size() - 1];
771 float maxSizeAr = ASPECT_RATIO(maxSize);
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800772
773 // Remove formats that has aspect ratio not croppable from largest size
774 std::vector<SupportedV4L2Format> out;
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800775 for (const auto& fmt : sortedFmts) {
776 float ar = ASPECT_RATIO(fmt);
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800777 if (isAspectRatioClose(ar, maxSizeAr)) {
778 out.push_back(fmt);
779 } else if (cropType == HORIZONTAL && ar < maxSizeAr) {
780 out.push_back(fmt);
781 } else if (cropType == VERTICAL && ar > maxSizeAr) {
782 out.push_back(fmt);
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800783 } else {
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800784 ALOGV("%s: size (%d,%d) is removed due to unable to crop %s from (%d,%d)",
785 __FUNCTION__, fmt.width, fmt.height,
786 cropType == VERTICAL ? "vertically" : "horizontally",
787 maxSize.width, maxSize.height);
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800788 }
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800789 }
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800790 sortedFmts = out;
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800791}
792
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800793std::vector<SupportedV4L2Format>
794ExternalCameraDevice::getCandidateSupportedFormatsLocked(
795 int fd, CroppingType cropType,
chenhgf2a6c472018-06-22 13:27:50 -0700796 const std::vector<ExternalCameraConfig::FpsLimitation>& fpsLimits,
797 const Size& minStreamSize) {
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800798 std::vector<SupportedV4L2Format> outFmts;
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700799 struct v4l2_fmtdesc fmtdesc {
800 .index = 0,
801 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE};
802 int ret = 0;
803 while (ret == 0) {
804 ret = TEMP_FAILURE_RETRY(ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc));
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800805 ALOGV("index:%d,ret:%d, format:%c%c%c%c", fmtdesc.index, ret,
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700806 fmtdesc.pixelformat & 0xFF,
807 (fmtdesc.pixelformat >> 8) & 0xFF,
808 (fmtdesc.pixelformat >> 16) & 0xFF,
809 (fmtdesc.pixelformat >> 24) & 0xFF);
810 if (ret == 0 && !(fmtdesc.flags & V4L2_FMT_FLAG_EMULATED)) {
811 auto it = std::find (
812 kSupportedFourCCs.begin(), kSupportedFourCCs.end(), fmtdesc.pixelformat);
813 if (it != kSupportedFourCCs.end()) {
814 // Found supported format
815 v4l2_frmsizeenum frameSize {
816 .index = 0,
817 .pixel_format = fmtdesc.pixelformat};
818 for (; TEMP_FAILURE_RETRY(ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frameSize)) == 0;
819 ++frameSize.index) {
820 if (frameSize.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800821 ALOGV("index:%d, format:%c%c%c%c, w %d, h %d", frameSize.index,
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700822 fmtdesc.pixelformat & 0xFF,
823 (fmtdesc.pixelformat >> 8) & 0xFF,
824 (fmtdesc.pixelformat >> 16) & 0xFF,
825 (fmtdesc.pixelformat >> 24) & 0xFF,
826 frameSize.discrete.width, frameSize.discrete.height);
827 // Disregard h > w formats so all aspect ratio (h/w) <= 1.0
828 // This will simplify the crop/scaling logic down the road
829 if (frameSize.discrete.height > frameSize.discrete.width) {
830 continue;
831 }
chenhgf2a6c472018-06-22 13:27:50 -0700832 // Discard all formats which is smaller than minStreamSize
833 if (frameSize.discrete.width < minStreamSize.width
834 || frameSize.discrete.height < minStreamSize.height) {
835 continue;
836 }
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700837 SupportedV4L2Format format {
838 .width = frameSize.discrete.width,
839 .height = frameSize.discrete.height,
840 .fourcc = fmtdesc.pixelformat
841 };
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800842
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800843 double fpsUpperBound = -1.0;
844 for (const auto& limit : fpsLimits) {
845 if (cropType == VERTICAL) {
846 if (format.width <= limit.size.width) {
847 fpsUpperBound = limit.fpsUpperBound;
848 break;
849 }
850 } else { // HORIZONTAL
851 if (format.height <= limit.size.height) {
852 fpsUpperBound = limit.fpsUpperBound;
853 break;
854 }
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800855 }
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800856
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800857 }
858 if (fpsUpperBound < 0.f) {
859 continue;
860 }
861
862 getFrameRateList(fd, fpsUpperBound, &format);
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700863 if (!format.frameRates.empty()) {
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800864 outFmts.push_back(format);
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700865 }
866 }
867 }
868 }
869 }
870 fmtdesc.index++;
871 }
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800872 trimSupportedFormats(cropType, &outFmts);
873 return outFmts;
874}
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800875
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800876void ExternalCameraDevice::initSupportedFormatsLocked(int fd) {
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800877
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800878 std::vector<SupportedV4L2Format> horizontalFmts =
chenhgf2a6c472018-06-22 13:27:50 -0700879 getCandidateSupportedFormatsLocked(fd, HORIZONTAL, mCfg.fpsLimits, mCfg.minStreamSize);
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800880 std::vector<SupportedV4L2Format> verticalFmts =
chenhgf2a6c472018-06-22 13:27:50 -0700881 getCandidateSupportedFormatsLocked(fd, VERTICAL, mCfg.fpsLimits, mCfg.minStreamSize);
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800882
883 size_t horiSize = horizontalFmts.size();
884 size_t vertSize = verticalFmts.size();
885
886 if (horiSize == 0 && vertSize == 0) {
887 ALOGE("%s: cannot find suitable cropping type!", __FUNCTION__);
888 return;
889 }
890
891 if (horiSize == 0) {
892 mSupportedFormats = verticalFmts;
893 mCroppingType = VERTICAL;
894 return;
895 } else if (vertSize == 0) {
896 mSupportedFormats = horizontalFmts;
897 mCroppingType = HORIZONTAL;
898 return;
899 }
900
901 const auto& maxHoriSize = horizontalFmts[horizontalFmts.size() - 1];
902 const auto& maxVertSize = verticalFmts[verticalFmts.size() - 1];
903
904 // Try to keep largest possible output size
905 // When they are the same or ambiguous, pick the one support more sizes
906 if (maxHoriSize.width == maxVertSize.width &&
907 maxHoriSize.height == maxVertSize.height) {
908 if (horiSize > vertSize) {
909 mSupportedFormats = horizontalFmts;
910 mCroppingType = HORIZONTAL;
911 } else {
912 mSupportedFormats = verticalFmts;
913 mCroppingType = VERTICAL;
914 }
915 } else if (maxHoriSize.width >= maxVertSize.width &&
916 maxHoriSize.height >= maxVertSize.height) {
917 mSupportedFormats = horizontalFmts;
918 mCroppingType = HORIZONTAL;
919 } else if (maxHoriSize.width <= maxVertSize.width &&
920 maxHoriSize.height <= maxVertSize.height) {
921 mSupportedFormats = verticalFmts;
922 mCroppingType = VERTICAL;
923 } else {
924 if (horiSize > vertSize) {
925 mSupportedFormats = horizontalFmts;
926 mCroppingType = HORIZONTAL;
927 } else {
928 mSupportedFormats = verticalFmts;
929 mCroppingType = VERTICAL;
930 }
931 }
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700932}
933
934} // namespace implementation
935} // namespace V3_4
936} // namespace device
937} // namespace camera
938} // namespace hardware
939} // namespace android
940