blob: 0f236570cde99f1d68c0d287f8a0a01796c671a3 [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(
Yin-Chia Yehee238402018-11-04 16:30:11 -080051 const std::string& cameraId, const ExternalCameraConfig& cfg) :
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -080052 mCameraId(cameraId),
Yin-Chia Yehee238402018-11-04 16:30:11 -080053 mCfg(cfg) {}
Yin-Chia Yeh19030592017-10-19 17:30:11 -070054
55ExternalCameraDevice::~ExternalCameraDevice() {}
56
57bool ExternalCameraDevice::isInitFailed() {
Yin-Chia Yehee238402018-11-04 16:30:11 -080058 Mutex::Autolock _l(mLock);
59 return isInitFailedLocked();
60}
61
62bool ExternalCameraDevice::isInitFailedLocked() {
63 if (!mInitialized) {
64 status_t ret = initCameraCharacteristics();
65 if (ret != OK) {
66 ALOGE("%s: init camera characteristics failed: errorno %d", __FUNCTION__, ret);
67 mInitFailed = true;
68 }
69 mInitialized = true;
70 }
Yin-Chia Yeh19030592017-10-19 17:30:11 -070071 return mInitFailed;
72}
73
Yin-Chia Yehee238402018-11-04 16:30:11 -080074Return<void> ExternalCameraDevice::getResourceCost(
75 ICameraDevice::getResourceCost_cb _hidl_cb) {
Yin-Chia Yeh19030592017-10-19 17:30:11 -070076 CameraResourceCost resCost;
77 resCost.resourceCost = 100;
78 _hidl_cb(Status::OK, resCost);
79 return Void();
80}
81
82Return<void> ExternalCameraDevice::getCameraCharacteristics(
Yin-Chia Yehee238402018-11-04 16:30:11 -080083 ICameraDevice::getCameraCharacteristics_cb _hidl_cb) {
Yin-Chia Yeh19030592017-10-19 17:30:11 -070084 Mutex::Autolock _l(mLock);
85 V3_2::CameraMetadata hidlChars;
86
Yin-Chia Yehee238402018-11-04 16:30:11 -080087 if (isInitFailedLocked()) {
Yin-Chia Yeh19030592017-10-19 17:30:11 -070088 _hidl_cb(Status::INTERNAL_ERROR, hidlChars);
89 return Void();
90 }
91
92 const camera_metadata_t* rawMetadata = mCameraCharacteristics.getAndLock();
93 V3_2::implementation::convertToHidl(rawMetadata, &hidlChars);
94 _hidl_cb(Status::OK, hidlChars);
95 mCameraCharacteristics.unlock(rawMetadata);
96 return Void();
97}
98
99Return<Status> ExternalCameraDevice::setTorchMode(TorchMode) {
Yin-Chia Yehbbc046e2018-08-28 10:52:43 -0700100 return Status::OPERATION_NOT_SUPPORTED;
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700101}
102
103Return<void> ExternalCameraDevice::open(
Yin-Chia Yehee238402018-11-04 16:30:11 -0800104 const sp<ICameraDeviceCallback>& callback, ICameraDevice::open_cb _hidl_cb) {
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700105 Status status = Status::OK;
106 sp<ExternalCameraDeviceSession> session = nullptr;
107
108 if (callback == nullptr) {
109 ALOGE("%s: cannot open camera %s. callback is null!",
110 __FUNCTION__, mCameraId.c_str());
111 _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
112 return Void();
113 }
114
115 if (isInitFailed()) {
116 ALOGE("%s: cannot open camera %s. camera init failed!",
117 __FUNCTION__, mCameraId.c_str());
118 _hidl_cb(Status::INTERNAL_ERROR, nullptr);
119 return Void();
120 }
121
122 mLock.lock();
123
124 ALOGV("%s: Initializing device for camera %s", __FUNCTION__, mCameraId.c_str());
125 session = mSession.promote();
126 if (session != nullptr && !session->isClosed()) {
127 ALOGE("%s: cannot open an already opened camera!", __FUNCTION__);
128 mLock.unlock();
129 _hidl_cb(Status::CAMERA_IN_USE, nullptr);
130 return Void();
131 }
132
133 unique_fd fd(::open(mCameraId.c_str(), O_RDWR));
134 if (fd.get() < 0) {
Yin-Chia Yeh2d61bfd2018-03-14 13:50:23 -0700135 int numAttempt = 0;
136 do {
137 ALOGW("%s: v4l2 device %s open failed, wait 33ms and try again",
138 __FUNCTION__, mCameraId.c_str());
139 usleep(OPEN_RETRY_SLEEP_US); // sleep and try again
140 fd.reset(::open(mCameraId.c_str(), O_RDWR));
141 numAttempt++;
142 } while (fd.get() < 0 && numAttempt <= MAX_RETRY);
143
144 if (fd.get() < 0) {
145 ALOGE("%s: v4l2 device open %s failed: %s",
146 __FUNCTION__, mCameraId.c_str(), strerror(errno));
147 mLock.unlock();
148 _hidl_cb(Status::INTERNAL_ERROR, nullptr);
149 return Void();
150 }
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700151 }
152
Yin-Chia Yehee238402018-11-04 16:30:11 -0800153 session = createSession(
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800154 callback, mCfg, mSupportedFormats, mCroppingType,
Yin-Chia Yeh4a3393c2018-02-14 12:47:16 -0800155 mCameraCharacteristics, mCameraId, std::move(fd));
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700156 if (session == nullptr) {
157 ALOGE("%s: camera device session allocation failed", __FUNCTION__);
158 mLock.unlock();
159 _hidl_cb(Status::INTERNAL_ERROR, nullptr);
160 return Void();
161 }
162 if (session->isInitFailed()) {
163 ALOGE("%s: camera device session init failed", __FUNCTION__);
164 session = nullptr;
165 mLock.unlock();
166 _hidl_cb(Status::INTERNAL_ERROR, nullptr);
167 return Void();
168 }
169 mSession = session;
170
171 mLock.unlock();
172
173 _hidl_cb(status, session->getInterface());
174 return Void();
175}
176
177Return<void> ExternalCameraDevice::dumpState(const ::android::hardware::hidl_handle& handle) {
178 Mutex::Autolock _l(mLock);
179 if (handle.getNativeHandle() == nullptr) {
180 ALOGE("%s: handle must not be null", __FUNCTION__);
181 return Void();
182 }
183 if (handle->numFds != 1 || handle->numInts != 0) {
184 ALOGE("%s: handle must contain 1 FD and 0 integers! Got %d FDs and %d ints",
185 __FUNCTION__, handle->numFds, handle->numInts);
186 return Void();
187 }
188 int fd = handle->data[0];
189 if (mSession == nullptr) {
190 dprintf(fd, "No active camera device session instance\n");
191 return Void();
192 }
193 auto session = mSession.promote();
194 if (session == nullptr) {
195 dprintf(fd, "No active camera device session instance\n");
196 return Void();
197 }
198 // Call into active session to dump states
199 session->dumpState(handle);
200 return Void();
201}
202
203
204status_t ExternalCameraDevice::initCameraCharacteristics() {
205 if (mCameraCharacteristics.isEmpty()) {
206 // init camera characteristics
207 unique_fd fd(::open(mCameraId.c_str(), O_RDWR));
208 if (fd.get() < 0) {
209 ALOGE("%s: v4l2 device open %s failed", __FUNCTION__, mCameraId.c_str());
210 return DEAD_OBJECT;
211 }
212
213 status_t ret;
214 ret = initDefaultCharsKeys(&mCameraCharacteristics);
215 if (ret != OK) {
216 ALOGE("%s: init default characteristics key failed: errorno %d", __FUNCTION__, ret);
217 mCameraCharacteristics.clear();
218 return ret;
219 }
220
221 ret = initCameraControlsCharsKeys(fd.get(), &mCameraCharacteristics);
222 if (ret != OK) {
223 ALOGE("%s: init camera control characteristics key failed: errorno %d", __FUNCTION__, ret);
224 mCameraCharacteristics.clear();
225 return ret;
226 }
227
228 ret = initOutputCharsKeys(fd.get(), &mCameraCharacteristics);
229 if (ret != OK) {
230 ALOGE("%s: init output characteristics key failed: errorno %d", __FUNCTION__, ret);
231 mCameraCharacteristics.clear();
232 return ret;
233 }
234 }
235 return OK;
236}
237
238#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
239#define UPDATE(tag, data, size) \
240do { \
241 if (metadata->update((tag), (data), (size))) { \
242 ALOGE("Update " #tag " failed!"); \
243 return -EINVAL; \
244 } \
245} while (0)
246
247status_t ExternalCameraDevice::initDefaultCharsKeys(
248 ::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) {
Yin-Chia Yeh4acd76e2018-01-23 15:29:14 -0800249 const uint8_t hardware_level = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL;
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700250 UPDATE(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL, &hardware_level, 1);
251
252 // android.colorCorrection
253 const uint8_t availableAberrationModes[] = {
254 ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF};
255 UPDATE(ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
256 availableAberrationModes, ARRAY_SIZE(availableAberrationModes));
257
258 // android.control
259 const uint8_t antibandingMode =
260 ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO;
261 UPDATE(ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
262 &antibandingMode, 1);
263
264 const int32_t controlMaxRegions[] = {/*AE*/ 0, /*AWB*/ 0, /*AF*/ 0};
265 UPDATE(ANDROID_CONTROL_MAX_REGIONS, controlMaxRegions,
266 ARRAY_SIZE(controlMaxRegions));
267
268 const uint8_t videoStabilizationMode =
269 ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF;
270 UPDATE(ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
271 &videoStabilizationMode, 1);
272
273 const uint8_t awbAvailableMode = ANDROID_CONTROL_AWB_MODE_AUTO;
274 UPDATE(ANDROID_CONTROL_AWB_AVAILABLE_MODES, &awbAvailableMode, 1);
275
276 const uint8_t aeAvailableMode = ANDROID_CONTROL_AE_MODE_ON;
277 UPDATE(ANDROID_CONTROL_AE_AVAILABLE_MODES, &aeAvailableMode, 1);
278
279 const uint8_t availableFffect = ANDROID_CONTROL_EFFECT_MODE_OFF;
280 UPDATE(ANDROID_CONTROL_AVAILABLE_EFFECTS, &availableFffect, 1);
281
282 const uint8_t controlAvailableModes[] = {ANDROID_CONTROL_MODE_OFF,
283 ANDROID_CONTROL_MODE_AUTO};
284 UPDATE(ANDROID_CONTROL_AVAILABLE_MODES, controlAvailableModes,
285 ARRAY_SIZE(controlAvailableModes));
286
287 // android.edge
288 const uint8_t edgeMode = ANDROID_EDGE_MODE_OFF;
289 UPDATE(ANDROID_EDGE_AVAILABLE_EDGE_MODES, &edgeMode, 1);
290
291 // android.flash
292 const uint8_t flashInfo = ANDROID_FLASH_INFO_AVAILABLE_FALSE;
293 UPDATE(ANDROID_FLASH_INFO_AVAILABLE, &flashInfo, 1);
294
295 // android.hotPixel
296 const uint8_t hotPixelMode = ANDROID_HOT_PIXEL_MODE_OFF;
297 UPDATE(ANDROID_HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES, &hotPixelMode, 1);
298
299 // android.jpeg
chenhg564cdae2018-06-20 14:21:20 -0700300 const int32_t jpegAvailableThumbnailSizes[] = {0, 0,
301 176, 144,
302 240, 144,
303 256, 144,
304 240, 160,
305 256, 154,
306 240, 240,
307 320, 240};
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700308 UPDATE(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES, jpegAvailableThumbnailSizes,
309 ARRAY_SIZE(jpegAvailableThumbnailSizes));
310
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800311 const int32_t jpegMaxSize = mCfg.maxJpegBufSize;
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700312 UPDATE(ANDROID_JPEG_MAX_SIZE, &jpegMaxSize, 1);
313
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700314 // android.lens
315 const uint8_t focusDistanceCalibration =
316 ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION_UNCALIBRATED;
317 UPDATE(ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION, &focusDistanceCalibration, 1);
318
319 const uint8_t opticalStabilizationMode =
320 ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF;
321 UPDATE(ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
322 &opticalStabilizationMode, 1);
323
324 const uint8_t facing = ANDROID_LENS_FACING_EXTERNAL;
325 UPDATE(ANDROID_LENS_FACING, &facing, 1);
326
327 // android.noiseReduction
328 const uint8_t noiseReductionMode = ANDROID_NOISE_REDUCTION_MODE_OFF;
329 UPDATE(ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
330 &noiseReductionMode, 1);
331 UPDATE(ANDROID_NOISE_REDUCTION_MODE, &noiseReductionMode, 1);
332
333 // android.request
334 const uint8_t availableCapabilities[] = {
335 ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE};
336 UPDATE(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, availableCapabilities,
337 ARRAY_SIZE(availableCapabilities));
338
339 const int32_t partialResultCount = 1;
340 UPDATE(ANDROID_REQUEST_PARTIAL_RESULT_COUNT, &partialResultCount, 1);
341
342 // This means pipeline latency of X frame intervals. The maximum number is 4.
343 const uint8_t requestPipelineMaxDepth = 4;
344 UPDATE(ANDROID_REQUEST_PIPELINE_MAX_DEPTH, &requestPipelineMaxDepth, 1);
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700345
346 // Three numbers represent the maximum numbers of different types of output
347 // streams simultaneously. The types are raw sensor, processed (but not
348 // stalling), and processed (but stalling). For usb limited mode, raw sensor
349 // is not supported. Stalling stream is JPEG. Non-stalling streams are
350 // YUV_420_888 or YV12.
351 const int32_t requestMaxNumOutputStreams[] = {
352 /*RAW*/0,
353 /*Processed*/ExternalCameraDeviceSession::kMaxProcessedStream,
354 /*Stall*/ExternalCameraDeviceSession::kMaxStallStream};
355 UPDATE(ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS, requestMaxNumOutputStreams,
356 ARRAY_SIZE(requestMaxNumOutputStreams));
357
358 // Limited mode doesn't support reprocessing.
359 const int32_t requestMaxNumInputStreams = 0;
360 UPDATE(ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS, &requestMaxNumInputStreams,
361 1);
362
363 // android.scaler
364 // TODO: b/72263447 V4L2_CID_ZOOM_*
365 const float scalerAvailableMaxDigitalZoom[] = {1};
366 UPDATE(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
367 scalerAvailableMaxDigitalZoom,
368 ARRAY_SIZE(scalerAvailableMaxDigitalZoom));
369
370 const uint8_t croppingType = ANDROID_SCALER_CROPPING_TYPE_CENTER_ONLY;
371 UPDATE(ANDROID_SCALER_CROPPING_TYPE, &croppingType, 1);
372
373 const int32_t testPatternModes[] = {
374 ANDROID_SENSOR_TEST_PATTERN_MODE_OFF};
375 UPDATE(ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES, testPatternModes,
376 ARRAY_SIZE(testPatternModes));
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700377
378 const uint8_t timestampSource = ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN;
379 UPDATE(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE, &timestampSource, 1);
380
Yin-Chia Yeh1c30a5e2018-11-28 16:00:16 -0800381 // Orientation is a bit odd for external camera, but consider it as the orientation
382 // between the external camera sensor (which is usually landscape) and the device's
383 // natural display orientation. For devices with natural landscape display (ex: tablet/TV), the
384 // orientation should be 0. For devices with natural portrait display (phone), the orientation
385 // should be 270.
386 const int32_t orientation = mCfg.orientation;
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700387 UPDATE(ANDROID_SENSOR_ORIENTATION, &orientation, 1);
388
389 // android.shading
390 const uint8_t availabeMode = ANDROID_SHADING_MODE_OFF;
391 UPDATE(ANDROID_SHADING_AVAILABLE_MODES, &availabeMode, 1);
392
393 // android.statistics
394 const uint8_t faceDetectMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;
395 UPDATE(ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES, &faceDetectMode,
396 1);
397
398 const int32_t maxFaceCount = 0;
399 UPDATE(ANDROID_STATISTICS_INFO_MAX_FACE_COUNT, &maxFaceCount, 1);
400
401 const uint8_t availableHotpixelMode =
402 ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE_OFF;
403 UPDATE(ANDROID_STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES,
404 &availableHotpixelMode, 1);
405
406 const uint8_t lensShadingMapMode =
407 ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF;
408 UPDATE(ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES,
409 &lensShadingMapMode, 1);
410
411 // android.sync
412 const int32_t maxLatency = ANDROID_SYNC_MAX_LATENCY_UNKNOWN;
413 UPDATE(ANDROID_SYNC_MAX_LATENCY, &maxLatency, 1);
414
415 /* Other sensor/RAW realted keys:
416 * android.sensor.info.colorFilterArrangement -> no need if we don't do RAW
417 * android.sensor.info.physicalSize -> not available
418 * android.sensor.info.whiteLevel -> not available/not needed
419 * android.sensor.info.lensShadingApplied -> not needed
420 * android.sensor.info.preCorrectionActiveArraySize -> not available/not needed
421 * android.sensor.blackLevelPattern -> not available/not needed
422 */
423
424 const int32_t availableRequestKeys[] = {
425 ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
426 ANDROID_CONTROL_AE_ANTIBANDING_MODE,
427 ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
428 ANDROID_CONTROL_AE_LOCK,
429 ANDROID_CONTROL_AE_MODE,
430 ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
431 ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
432 ANDROID_CONTROL_AF_MODE,
433 ANDROID_CONTROL_AF_TRIGGER,
434 ANDROID_CONTROL_AWB_LOCK,
435 ANDROID_CONTROL_AWB_MODE,
436 ANDROID_CONTROL_CAPTURE_INTENT,
437 ANDROID_CONTROL_EFFECT_MODE,
438 ANDROID_CONTROL_MODE,
439 ANDROID_CONTROL_SCENE_MODE,
440 ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
441 ANDROID_FLASH_MODE,
442 ANDROID_JPEG_ORIENTATION,
443 ANDROID_JPEG_QUALITY,
444 ANDROID_JPEG_THUMBNAIL_QUALITY,
445 ANDROID_JPEG_THUMBNAIL_SIZE,
446 ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
447 ANDROID_NOISE_REDUCTION_MODE,
448 ANDROID_SCALER_CROP_REGION,
449 ANDROID_SENSOR_TEST_PATTERN_MODE,
450 ANDROID_STATISTICS_FACE_DETECT_MODE,
451 ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE};
452 UPDATE(ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS, availableRequestKeys,
453 ARRAY_SIZE(availableRequestKeys));
454
455 const int32_t availableResultKeys[] = {
456 ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
457 ANDROID_CONTROL_AE_ANTIBANDING_MODE,
458 ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
459 ANDROID_CONTROL_AE_LOCK,
460 ANDROID_CONTROL_AE_MODE,
461 ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
462 ANDROID_CONTROL_AE_STATE,
463 ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
464 ANDROID_CONTROL_AF_MODE,
465 ANDROID_CONTROL_AF_STATE,
466 ANDROID_CONTROL_AF_TRIGGER,
467 ANDROID_CONTROL_AWB_LOCK,
468 ANDROID_CONTROL_AWB_MODE,
469 ANDROID_CONTROL_AWB_STATE,
470 ANDROID_CONTROL_CAPTURE_INTENT,
471 ANDROID_CONTROL_EFFECT_MODE,
472 ANDROID_CONTROL_MODE,
473 ANDROID_CONTROL_SCENE_MODE,
474 ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
475 ANDROID_FLASH_MODE,
476 ANDROID_FLASH_STATE,
477 ANDROID_JPEG_ORIENTATION,
478 ANDROID_JPEG_QUALITY,
479 ANDROID_JPEG_THUMBNAIL_QUALITY,
480 ANDROID_JPEG_THUMBNAIL_SIZE,
481 ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
482 ANDROID_NOISE_REDUCTION_MODE,
483 ANDROID_REQUEST_PIPELINE_DEPTH,
484 ANDROID_SCALER_CROP_REGION,
485 ANDROID_SENSOR_TIMESTAMP,
486 ANDROID_STATISTICS_FACE_DETECT_MODE,
487 ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE,
488 ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,
489 ANDROID_STATISTICS_SCENE_FLICKER};
490 UPDATE(ANDROID_REQUEST_AVAILABLE_RESULT_KEYS, availableResultKeys,
491 ARRAY_SIZE(availableResultKeys));
492
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700493 UPDATE(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS,
Yin-Chia Yehee238402018-11-04 16:30:11 -0800494 AVAILABLE_CHARACTERISTICS_KEYS_3_4.data(),
495 AVAILABLE_CHARACTERISTICS_KEYS_3_4.size());
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700496
497 return OK;
498}
499
500status_t ExternalCameraDevice::initCameraControlsCharsKeys(int,
501 ::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) {
502 /**
503 * android.sensor.info.sensitivityRange -> V4L2_CID_ISO_SENSITIVITY
504 * android.sensor.info.exposureTimeRange -> V4L2_CID_EXPOSURE_ABSOLUTE
505 * android.sensor.info.maxFrameDuration -> TBD
506 * android.lens.info.minimumFocusDistance -> V4L2_CID_FOCUS_ABSOLUTE
507 * android.lens.info.hyperfocalDistance
508 * android.lens.info.availableFocalLengths -> not available?
509 */
510
511 // android.control
512 // No AE compensation support for now.
513 // TODO: V4L2_CID_EXPOSURE_BIAS
514 const int32_t controlAeCompensationRange[] = {0, 0};
515 UPDATE(ANDROID_CONTROL_AE_COMPENSATION_RANGE, controlAeCompensationRange,
516 ARRAY_SIZE(controlAeCompensationRange));
517 const camera_metadata_rational_t controlAeCompensationStep[] = {{0, 1}};
518 UPDATE(ANDROID_CONTROL_AE_COMPENSATION_STEP, controlAeCompensationStep,
519 ARRAY_SIZE(controlAeCompensationStep));
520
521
522 // TODO: Check V4L2_CID_AUTO_FOCUS_*.
523 const uint8_t afAvailableModes[] = {ANDROID_CONTROL_AF_MODE_AUTO,
524 ANDROID_CONTROL_AF_MODE_OFF};
525 UPDATE(ANDROID_CONTROL_AF_AVAILABLE_MODES, afAvailableModes,
526 ARRAY_SIZE(afAvailableModes));
527
528 // TODO: V4L2_CID_SCENE_MODE
529 const uint8_t availableSceneMode = ANDROID_CONTROL_SCENE_MODE_DISABLED;
530 UPDATE(ANDROID_CONTROL_AVAILABLE_SCENE_MODES, &availableSceneMode, 1);
531
532 // TODO: V4L2_CID_3A_LOCK
533 const uint8_t aeLockAvailable = ANDROID_CONTROL_AE_LOCK_AVAILABLE_FALSE;
534 UPDATE(ANDROID_CONTROL_AE_LOCK_AVAILABLE, &aeLockAvailable, 1);
535 const uint8_t awbLockAvailable = ANDROID_CONTROL_AWB_LOCK_AVAILABLE_FALSE;
536 UPDATE(ANDROID_CONTROL_AWB_LOCK_AVAILABLE, &awbLockAvailable, 1);
537
538 // TODO: V4L2_CID_ZOOM_*
539 const float scalerAvailableMaxDigitalZoom[] = {1};
540 UPDATE(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
541 scalerAvailableMaxDigitalZoom,
542 ARRAY_SIZE(scalerAvailableMaxDigitalZoom));
543
544 return OK;
545}
546
547status_t ExternalCameraDevice::initOutputCharsKeys(int fd,
548 ::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) {
549 initSupportedFormatsLocked(fd);
550 if (mSupportedFormats.empty()) {
551 ALOGE("%s: Init supported format list failed", __FUNCTION__);
552 return UNKNOWN_ERROR;
553 }
554
555 std::vector<int32_t> streamConfigurations;
556 std::vector<int64_t> minFrameDurations;
557 std::vector<int64_t> stallDurations;
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700558 int32_t maxFps = std::numeric_limits<int32_t>::min();
559 int32_t minFps = std::numeric_limits<int32_t>::max();
560 std::set<int32_t> framerates;
561
562 std::array<int, /*size*/3> halFormats{{
563 HAL_PIXEL_FORMAT_BLOB,
564 HAL_PIXEL_FORMAT_YCbCr_420_888,
565 HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED}};
566
567 for (const auto& supportedFormat : mSupportedFormats) {
568 for (const auto& format : halFormats) {
569 streamConfigurations.push_back(format);
570 streamConfigurations.push_back(supportedFormat.width);
571 streamConfigurations.push_back(supportedFormat.height);
572 streamConfigurations.push_back(
573 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT);
574 }
575
Yin-Chia Yeh134093a2018-02-12 14:05:48 -0800576 int64_t minFrameDuration = std::numeric_limits<int64_t>::max();
577 for (const auto& fr : supportedFormat.frameRates) {
578 // 1000000000LL < (2^32 - 1) and
579 // fr.durationNumerator is uint32_t, so no overflow here
580 int64_t frameDuration = 1000000000LL * fr.durationNumerator /
581 fr.durationDenominator;
582 if (frameDuration < minFrameDuration) {
583 minFrameDuration = frameDuration;
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700584 }
Yin-Chia Yeh134093a2018-02-12 14:05:48 -0800585 int32_t frameRateInt = static_cast<int32_t>(fr.getDouble());
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700586 if (minFps > frameRateInt) {
587 minFps = frameRateInt;
588 }
589 if (maxFps < frameRateInt) {
590 maxFps = frameRateInt;
591 }
592 framerates.insert(frameRateInt);
593 }
594
595 for (const auto& format : halFormats) {
596 minFrameDurations.push_back(format);
597 minFrameDurations.push_back(supportedFormat.width);
598 minFrameDurations.push_back(supportedFormat.height);
Yin-Chia Yeh134093a2018-02-12 14:05:48 -0800599 minFrameDurations.push_back(minFrameDuration);
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700600 }
601
602 // The stall duration is 0 for non-jpeg formats. For JPEG format, stall
603 // duration can be 0 if JPEG is small. Here we choose 1 sec for JPEG.
604 // TODO: b/72261675. Maybe set this dynamically
605 for (const auto& format : halFormats) {
606 const int64_t NS_TO_SECOND = 1000000000;
607 int64_t stall_duration =
608 (format == HAL_PIXEL_FORMAT_BLOB) ? NS_TO_SECOND : 0;
609 stallDurations.push_back(format);
610 stallDurations.push_back(supportedFormat.width);
611 stallDurations.push_back(supportedFormat.height);
612 stallDurations.push_back(stall_duration);
613 }
614 }
615
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700616 std::vector<int32_t> fpsRanges;
Yin-Chia Yeh8b699aa2018-02-28 15:58:54 -0800617 // FPS ranges
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700618 for (const auto& framerate : framerates) {
Yin-Chia Yeh8b699aa2018-02-28 15:58:54 -0800619 // Empirical: webcams often have close to 2x fps error and cannot support fixed fps range
620 fpsRanges.push_back(framerate / 2);
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700621 fpsRanges.push_back(framerate);
622 }
Yin-Chia Yehc15a1ca2018-03-02 14:16:52 -0800623 minFps /= 2;
624 int64_t maxFrameDuration = 1000000000LL / minFps;
Yin-Chia Yeh8b699aa2018-02-28 15:58:54 -0800625
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700626 UPDATE(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, fpsRanges.data(),
627 fpsRanges.size());
628
629 UPDATE(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
630 streamConfigurations.data(), streamConfigurations.size());
631
632 UPDATE(ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,
633 minFrameDurations.data(), minFrameDurations.size());
634
635 UPDATE(ANDROID_SCALER_AVAILABLE_STALL_DURATIONS, stallDurations.data(),
636 stallDurations.size());
637
638 UPDATE(ANDROID_SENSOR_INFO_MAX_FRAME_DURATION, &maxFrameDuration, 1);
639
640 SupportedV4L2Format maximumFormat {.width = 0, .height = 0};
641 for (const auto& supportedFormat : mSupportedFormats) {
642 if (supportedFormat.width >= maximumFormat.width &&
643 supportedFormat.height >= maximumFormat.height) {
644 maximumFormat = supportedFormat;
645 }
646 }
647 int32_t activeArraySize[] = {0, 0,
648 static_cast<int32_t>(maximumFormat.width),
649 static_cast<int32_t>(maximumFormat.height)};
650 UPDATE(ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE,
651 activeArraySize, ARRAY_SIZE(activeArraySize));
652 UPDATE(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE, activeArraySize,
653 ARRAY_SIZE(activeArraySize));
654
655 int32_t pixelArraySize[] = {static_cast<int32_t>(maximumFormat.width),
656 static_cast<int32_t>(maximumFormat.height)};
657 UPDATE(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE, pixelArraySize,
658 ARRAY_SIZE(pixelArraySize));
659 return OK;
660}
661
662#undef ARRAY_SIZE
663#undef UPDATE
664
665void ExternalCameraDevice::getFrameRateList(
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800666 int fd, double fpsUpperBound, SupportedV4L2Format* format) {
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700667 format->frameRates.clear();
668
669 v4l2_frmivalenum frameInterval {
670 .pixel_format = format->fourcc,
671 .width = format->width,
672 .height = format->height,
673 .index = 0
674 };
675
676 for (frameInterval.index = 0;
677 TEMP_FAILURE_RETRY(ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frameInterval)) == 0;
678 ++frameInterval.index) {
679 if (frameInterval.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
680 if (frameInterval.discrete.numerator != 0) {
Yin-Chia Yeh134093a2018-02-12 14:05:48 -0800681 SupportedV4L2Format::FrameRate fr = {
682 frameInterval.discrete.numerator,
683 frameInterval.discrete.denominator};
684 double framerate = fr.getDouble();
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800685 if (framerate > fpsUpperBound) {
686 continue;
687 }
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800688 ALOGV("index:%d, format:%c%c%c%c, w %d, h %d, framerate %f",
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700689 frameInterval.index,
690 frameInterval.pixel_format & 0xFF,
691 (frameInterval.pixel_format >> 8) & 0xFF,
692 (frameInterval.pixel_format >> 16) & 0xFF,
693 (frameInterval.pixel_format >> 24) & 0xFF,
694 frameInterval.width, frameInterval.height, framerate);
Yin-Chia Yeh134093a2018-02-12 14:05:48 -0800695 format->frameRates.push_back(fr);
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700696 }
697 }
698 }
699
700 if (format->frameRates.empty()) {
701 ALOGE("%s: failed to get supported frame rates for format:%c%c%c%c w %d h %d",
702 __FUNCTION__,
703 frameInterval.pixel_format & 0xFF,
704 (frameInterval.pixel_format >> 8) & 0xFF,
705 (frameInterval.pixel_format >> 16) & 0xFF,
706 (frameInterval.pixel_format >> 24) & 0xFF,
707 frameInterval.width, frameInterval.height);
708 }
709}
710
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800711void ExternalCameraDevice::trimSupportedFormats(
712 CroppingType cropType,
713 /*inout*/std::vector<SupportedV4L2Format>* pFmts) {
714 std::vector<SupportedV4L2Format>& sortedFmts = *pFmts;
715 if (cropType == VERTICAL) {
716 std::sort(sortedFmts.begin(), sortedFmts.end(),
717 [](const SupportedV4L2Format& a, const SupportedV4L2Format& b) -> bool {
718 if (a.width == b.width) {
719 return a.height < b.height;
720 }
721 return a.width < b.width;
722 });
723 } else {
724 std::sort(sortedFmts.begin(), sortedFmts.end(),
725 [](const SupportedV4L2Format& a, const SupportedV4L2Format& b) -> bool {
726 if (a.height == b.height) {
727 return a.width < b.width;
728 }
729 return a.height < b.height;
730 });
731 }
732
733 if (sortedFmts.size() == 0) {
734 ALOGE("%s: input format list is empty!", __FUNCTION__);
735 return;
736 }
737
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800738 const auto& maxSize = sortedFmts[sortedFmts.size() - 1];
739 float maxSizeAr = ASPECT_RATIO(maxSize);
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800740
741 // Remove formats that has aspect ratio not croppable from largest size
742 std::vector<SupportedV4L2Format> out;
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800743 for (const auto& fmt : sortedFmts) {
744 float ar = ASPECT_RATIO(fmt);
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800745 if (isAspectRatioClose(ar, maxSizeAr)) {
746 out.push_back(fmt);
747 } else if (cropType == HORIZONTAL && ar < maxSizeAr) {
748 out.push_back(fmt);
749 } else if (cropType == VERTICAL && ar > maxSizeAr) {
750 out.push_back(fmt);
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800751 } else {
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800752 ALOGV("%s: size (%d,%d) is removed due to unable to crop %s from (%d,%d)",
753 __FUNCTION__, fmt.width, fmt.height,
754 cropType == VERTICAL ? "vertically" : "horizontally",
755 maxSize.width, maxSize.height);
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800756 }
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800757 }
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800758 sortedFmts = out;
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800759}
760
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800761std::vector<SupportedV4L2Format>
762ExternalCameraDevice::getCandidateSupportedFormatsLocked(
763 int fd, CroppingType cropType,
chenhgf2a6c472018-06-22 13:27:50 -0700764 const std::vector<ExternalCameraConfig::FpsLimitation>& fpsLimits,
765 const Size& minStreamSize) {
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800766 std::vector<SupportedV4L2Format> outFmts;
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700767 struct v4l2_fmtdesc fmtdesc {
768 .index = 0,
769 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE};
770 int ret = 0;
771 while (ret == 0) {
772 ret = TEMP_FAILURE_RETRY(ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc));
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800773 ALOGV("index:%d,ret:%d, format:%c%c%c%c", fmtdesc.index, ret,
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700774 fmtdesc.pixelformat & 0xFF,
775 (fmtdesc.pixelformat >> 8) & 0xFF,
776 (fmtdesc.pixelformat >> 16) & 0xFF,
777 (fmtdesc.pixelformat >> 24) & 0xFF);
778 if (ret == 0 && !(fmtdesc.flags & V4L2_FMT_FLAG_EMULATED)) {
779 auto it = std::find (
780 kSupportedFourCCs.begin(), kSupportedFourCCs.end(), fmtdesc.pixelformat);
781 if (it != kSupportedFourCCs.end()) {
782 // Found supported format
783 v4l2_frmsizeenum frameSize {
784 .index = 0,
785 .pixel_format = fmtdesc.pixelformat};
786 for (; TEMP_FAILURE_RETRY(ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frameSize)) == 0;
787 ++frameSize.index) {
788 if (frameSize.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800789 ALOGV("index:%d, format:%c%c%c%c, w %d, h %d", frameSize.index,
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700790 fmtdesc.pixelformat & 0xFF,
791 (fmtdesc.pixelformat >> 8) & 0xFF,
792 (fmtdesc.pixelformat >> 16) & 0xFF,
793 (fmtdesc.pixelformat >> 24) & 0xFF,
794 frameSize.discrete.width, frameSize.discrete.height);
795 // Disregard h > w formats so all aspect ratio (h/w) <= 1.0
796 // This will simplify the crop/scaling logic down the road
797 if (frameSize.discrete.height > frameSize.discrete.width) {
798 continue;
799 }
chenhgf2a6c472018-06-22 13:27:50 -0700800 // Discard all formats which is smaller than minStreamSize
801 if (frameSize.discrete.width < minStreamSize.width
802 || frameSize.discrete.height < minStreamSize.height) {
803 continue;
804 }
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700805 SupportedV4L2Format format {
806 .width = frameSize.discrete.width,
807 .height = frameSize.discrete.height,
808 .fourcc = fmtdesc.pixelformat
809 };
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800810
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800811 double fpsUpperBound = -1.0;
812 for (const auto& limit : fpsLimits) {
813 if (cropType == VERTICAL) {
814 if (format.width <= limit.size.width) {
815 fpsUpperBound = limit.fpsUpperBound;
816 break;
817 }
818 } else { // HORIZONTAL
819 if (format.height <= limit.size.height) {
820 fpsUpperBound = limit.fpsUpperBound;
821 break;
822 }
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800823 }
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800824
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800825 }
826 if (fpsUpperBound < 0.f) {
827 continue;
828 }
829
830 getFrameRateList(fd, fpsUpperBound, &format);
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700831 if (!format.frameRates.empty()) {
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800832 outFmts.push_back(format);
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700833 }
834 }
835 }
836 }
837 }
838 fmtdesc.index++;
839 }
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800840 trimSupportedFormats(cropType, &outFmts);
841 return outFmts;
842}
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800843
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800844void ExternalCameraDevice::initSupportedFormatsLocked(int fd) {
Yin-Chia Yeh53f4cb12018-01-29 10:31:45 -0800845
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800846 std::vector<SupportedV4L2Format> horizontalFmts =
chenhgf2a6c472018-06-22 13:27:50 -0700847 getCandidateSupportedFormatsLocked(fd, HORIZONTAL, mCfg.fpsLimits, mCfg.minStreamSize);
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800848 std::vector<SupportedV4L2Format> verticalFmts =
chenhgf2a6c472018-06-22 13:27:50 -0700849 getCandidateSupportedFormatsLocked(fd, VERTICAL, mCfg.fpsLimits, mCfg.minStreamSize);
Yin-Chia Yeh3aa9ae92018-02-23 17:21:51 -0800850
851 size_t horiSize = horizontalFmts.size();
852 size_t vertSize = verticalFmts.size();
853
854 if (horiSize == 0 && vertSize == 0) {
855 ALOGE("%s: cannot find suitable cropping type!", __FUNCTION__);
856 return;
857 }
858
859 if (horiSize == 0) {
860 mSupportedFormats = verticalFmts;
861 mCroppingType = VERTICAL;
862 return;
863 } else if (vertSize == 0) {
864 mSupportedFormats = horizontalFmts;
865 mCroppingType = HORIZONTAL;
866 return;
867 }
868
869 const auto& maxHoriSize = horizontalFmts[horizontalFmts.size() - 1];
870 const auto& maxVertSize = verticalFmts[verticalFmts.size() - 1];
871
872 // Try to keep largest possible output size
873 // When they are the same or ambiguous, pick the one support more sizes
874 if (maxHoriSize.width == maxVertSize.width &&
875 maxHoriSize.height == maxVertSize.height) {
876 if (horiSize > vertSize) {
877 mSupportedFormats = horizontalFmts;
878 mCroppingType = HORIZONTAL;
879 } else {
880 mSupportedFormats = verticalFmts;
881 mCroppingType = VERTICAL;
882 }
883 } else if (maxHoriSize.width >= maxVertSize.width &&
884 maxHoriSize.height >= maxVertSize.height) {
885 mSupportedFormats = horizontalFmts;
886 mCroppingType = HORIZONTAL;
887 } else if (maxHoriSize.width <= maxVertSize.width &&
888 maxHoriSize.height <= maxVertSize.height) {
889 mSupportedFormats = verticalFmts;
890 mCroppingType = VERTICAL;
891 } else {
892 if (horiSize > vertSize) {
893 mSupportedFormats = horizontalFmts;
894 mCroppingType = HORIZONTAL;
895 } else {
896 mSupportedFormats = verticalFmts;
897 mCroppingType = VERTICAL;
898 }
899 }
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700900}
901
Yin-Chia Yehee238402018-11-04 16:30:11 -0800902sp<ExternalCameraDeviceSession> ExternalCameraDevice::createSession(
903 const sp<ICameraDeviceCallback>& cb,
904 const ExternalCameraConfig& cfg,
905 const std::vector<SupportedV4L2Format>& sortedFormats,
906 const CroppingType& croppingType,
907 const common::V1_0::helper::CameraMetadata& chars,
908 const std::string& cameraId,
909 unique_fd v4l2Fd) {
910 return new ExternalCameraDeviceSession(
911 cb, cfg, sortedFormats, croppingType, chars, cameraId, std::move(v4l2Fd));
912}
913
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700914} // namespace implementation
915} // namespace V3_4
916} // namespace device
917} // namespace camera
918} // namespace hardware
919} // namespace android
920