1*4d7e907cSAndroid Build Coastguard Worker /*
2*4d7e907cSAndroid Build Coastguard Worker * Copyright (C) 2018 The Android Open Source Project
3*4d7e907cSAndroid Build Coastguard Worker *
4*4d7e907cSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*4d7e907cSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*4d7e907cSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*4d7e907cSAndroid Build Coastguard Worker *
8*4d7e907cSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*4d7e907cSAndroid Build Coastguard Worker *
10*4d7e907cSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*4d7e907cSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*4d7e907cSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*4d7e907cSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*4d7e907cSAndroid Build Coastguard Worker * limitations under the License.
15*4d7e907cSAndroid Build Coastguard Worker */
16*4d7e907cSAndroid Build Coastguard Worker
17*4d7e907cSAndroid Build Coastguard Worker #define LOG_TAG "[email protected]"
18*4d7e907cSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
19*4d7e907cSAndroid Build Coastguard Worker #include <log/log.h>
20*4d7e907cSAndroid Build Coastguard Worker
21*4d7e907cSAndroid Build Coastguard Worker #include <algorithm>
22*4d7e907cSAndroid Build Coastguard Worker #include <array>
23*4d7e907cSAndroid Build Coastguard Worker #include <regex>
24*4d7e907cSAndroid Build Coastguard Worker #include <linux/videodev2.h>
25*4d7e907cSAndroid Build Coastguard Worker #include "android-base/macros.h"
26*4d7e907cSAndroid Build Coastguard Worker #include "CameraMetadata.h"
27*4d7e907cSAndroid Build Coastguard Worker #include "../../3.2/default/include/convert.h"
28*4d7e907cSAndroid Build Coastguard Worker #include "ExternalCameraDevice_3_4.h"
29*4d7e907cSAndroid Build Coastguard Worker
30*4d7e907cSAndroid Build Coastguard Worker namespace android {
31*4d7e907cSAndroid Build Coastguard Worker namespace hardware {
32*4d7e907cSAndroid Build Coastguard Worker namespace camera {
33*4d7e907cSAndroid Build Coastguard Worker namespace device {
34*4d7e907cSAndroid Build Coastguard Worker namespace V3_4 {
35*4d7e907cSAndroid Build Coastguard Worker namespace implementation {
36*4d7e907cSAndroid Build Coastguard Worker
37*4d7e907cSAndroid Build Coastguard Worker namespace {
38*4d7e907cSAndroid Build Coastguard Worker // Only support MJPEG for now as it seems to be the one supports higher fps
39*4d7e907cSAndroid Build Coastguard Worker // Other formats to consider in the future:
40*4d7e907cSAndroid Build Coastguard Worker // * V4L2_PIX_FMT_YVU420 (== YV12)
41*4d7e907cSAndroid Build Coastguard Worker // * V4L2_PIX_FMT_YVYU (YVYU: can be converted to YV12 or other YUV420_888 formats)
42*4d7e907cSAndroid Build Coastguard Worker const std::array<uint32_t, /*size*/ 2> kSupportedFourCCs{
43*4d7e907cSAndroid Build Coastguard Worker {V4L2_PIX_FMT_MJPEG, V4L2_PIX_FMT_Z16}}; // double braces required in C++11
44*4d7e907cSAndroid Build Coastguard Worker
45*4d7e907cSAndroid Build Coastguard Worker constexpr int MAX_RETRY = 5; // Allow retry v4l2 open failures a few times.
46*4d7e907cSAndroid Build Coastguard Worker constexpr int OPEN_RETRY_SLEEP_US = 100000; // 100ms * MAX_RETRY = 0.5 seconds
47*4d7e907cSAndroid Build Coastguard Worker
48*4d7e907cSAndroid Build Coastguard Worker } // anonymous namespace
49*4d7e907cSAndroid Build Coastguard Worker
50*4d7e907cSAndroid Build Coastguard Worker const std::regex kDevicePathRE("/dev/video([0-9]+)");
51*4d7e907cSAndroid Build Coastguard Worker
ExternalCameraDevice(const std::string & devicePath,const ExternalCameraConfig & cfg)52*4d7e907cSAndroid Build Coastguard Worker ExternalCameraDevice::ExternalCameraDevice(
53*4d7e907cSAndroid Build Coastguard Worker const std::string& devicePath, const ExternalCameraConfig& cfg) :
54*4d7e907cSAndroid Build Coastguard Worker mCameraId("-1"),
55*4d7e907cSAndroid Build Coastguard Worker mDevicePath(devicePath),
56*4d7e907cSAndroid Build Coastguard Worker mCfg(cfg) {
57*4d7e907cSAndroid Build Coastguard Worker std::smatch sm;
58*4d7e907cSAndroid Build Coastguard Worker if (std::regex_match(mDevicePath, sm, kDevicePathRE)) {
59*4d7e907cSAndroid Build Coastguard Worker mCameraId = std::to_string(mCfg.cameraIdOffset + std::stoi(sm[1]));
60*4d7e907cSAndroid Build Coastguard Worker } else {
61*4d7e907cSAndroid Build Coastguard Worker ALOGE("%s: device path match failed for %s", __FUNCTION__, mDevicePath.c_str());
62*4d7e907cSAndroid Build Coastguard Worker }
63*4d7e907cSAndroid Build Coastguard Worker }
64*4d7e907cSAndroid Build Coastguard Worker
~ExternalCameraDevice()65*4d7e907cSAndroid Build Coastguard Worker ExternalCameraDevice::~ExternalCameraDevice() {}
66*4d7e907cSAndroid Build Coastguard Worker
isInitFailed()67*4d7e907cSAndroid Build Coastguard Worker bool ExternalCameraDevice::isInitFailed() {
68*4d7e907cSAndroid Build Coastguard Worker Mutex::Autolock _l(mLock);
69*4d7e907cSAndroid Build Coastguard Worker return isInitFailedLocked();
70*4d7e907cSAndroid Build Coastguard Worker }
71*4d7e907cSAndroid Build Coastguard Worker
isInitFailedLocked()72*4d7e907cSAndroid Build Coastguard Worker bool ExternalCameraDevice::isInitFailedLocked() {
73*4d7e907cSAndroid Build Coastguard Worker if (!mInitialized) {
74*4d7e907cSAndroid Build Coastguard Worker status_t ret = initCameraCharacteristics();
75*4d7e907cSAndroid Build Coastguard Worker if (ret != OK) {
76*4d7e907cSAndroid Build Coastguard Worker ALOGE("%s: init camera characteristics failed: errorno %d", __FUNCTION__, ret);
77*4d7e907cSAndroid Build Coastguard Worker mInitFailed = true;
78*4d7e907cSAndroid Build Coastguard Worker }
79*4d7e907cSAndroid Build Coastguard Worker mInitialized = true;
80*4d7e907cSAndroid Build Coastguard Worker }
81*4d7e907cSAndroid Build Coastguard Worker return mInitFailed;
82*4d7e907cSAndroid Build Coastguard Worker }
83*4d7e907cSAndroid Build Coastguard Worker
getResourceCost(ICameraDevice::getResourceCost_cb _hidl_cb)84*4d7e907cSAndroid Build Coastguard Worker Return<void> ExternalCameraDevice::getResourceCost(
85*4d7e907cSAndroid Build Coastguard Worker ICameraDevice::getResourceCost_cb _hidl_cb) {
86*4d7e907cSAndroid Build Coastguard Worker CameraResourceCost resCost;
87*4d7e907cSAndroid Build Coastguard Worker resCost.resourceCost = 100;
88*4d7e907cSAndroid Build Coastguard Worker _hidl_cb(Status::OK, resCost);
89*4d7e907cSAndroid Build Coastguard Worker return Void();
90*4d7e907cSAndroid Build Coastguard Worker }
91*4d7e907cSAndroid Build Coastguard Worker
getCameraCharacteristics(ICameraDevice::getCameraCharacteristics_cb _hidl_cb)92*4d7e907cSAndroid Build Coastguard Worker Return<void> ExternalCameraDevice::getCameraCharacteristics(
93*4d7e907cSAndroid Build Coastguard Worker ICameraDevice::getCameraCharacteristics_cb _hidl_cb) {
94*4d7e907cSAndroid Build Coastguard Worker Mutex::Autolock _l(mLock);
95*4d7e907cSAndroid Build Coastguard Worker V3_2::CameraMetadata hidlChars;
96*4d7e907cSAndroid Build Coastguard Worker
97*4d7e907cSAndroid Build Coastguard Worker if (isInitFailedLocked()) {
98*4d7e907cSAndroid Build Coastguard Worker _hidl_cb(Status::INTERNAL_ERROR, hidlChars);
99*4d7e907cSAndroid Build Coastguard Worker return Void();
100*4d7e907cSAndroid Build Coastguard Worker }
101*4d7e907cSAndroid Build Coastguard Worker
102*4d7e907cSAndroid Build Coastguard Worker const camera_metadata_t* rawMetadata = mCameraCharacteristics.getAndLock();
103*4d7e907cSAndroid Build Coastguard Worker V3_2::implementation::convertToHidl(rawMetadata, &hidlChars);
104*4d7e907cSAndroid Build Coastguard Worker _hidl_cb(Status::OK, hidlChars);
105*4d7e907cSAndroid Build Coastguard Worker mCameraCharacteristics.unlock(rawMetadata);
106*4d7e907cSAndroid Build Coastguard Worker return Void();
107*4d7e907cSAndroid Build Coastguard Worker }
108*4d7e907cSAndroid Build Coastguard Worker
setTorchMode(TorchMode)109*4d7e907cSAndroid Build Coastguard Worker Return<Status> ExternalCameraDevice::setTorchMode(TorchMode) {
110*4d7e907cSAndroid Build Coastguard Worker return Status::OPERATION_NOT_SUPPORTED;
111*4d7e907cSAndroid Build Coastguard Worker }
112*4d7e907cSAndroid Build Coastguard Worker
open(const sp<ICameraDeviceCallback> & callback,ICameraDevice::open_cb _hidl_cb)113*4d7e907cSAndroid Build Coastguard Worker Return<void> ExternalCameraDevice::open(
114*4d7e907cSAndroid Build Coastguard Worker const sp<ICameraDeviceCallback>& callback, ICameraDevice::open_cb _hidl_cb) {
115*4d7e907cSAndroid Build Coastguard Worker Status status = Status::OK;
116*4d7e907cSAndroid Build Coastguard Worker sp<ExternalCameraDeviceSession> session = nullptr;
117*4d7e907cSAndroid Build Coastguard Worker
118*4d7e907cSAndroid Build Coastguard Worker if (callback == nullptr) {
119*4d7e907cSAndroid Build Coastguard Worker ALOGE("%s: cannot open camera %s. callback is null!",
120*4d7e907cSAndroid Build Coastguard Worker __FUNCTION__, mCameraId.c_str());
121*4d7e907cSAndroid Build Coastguard Worker _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
122*4d7e907cSAndroid Build Coastguard Worker return Void();
123*4d7e907cSAndroid Build Coastguard Worker }
124*4d7e907cSAndroid Build Coastguard Worker
125*4d7e907cSAndroid Build Coastguard Worker if (isInitFailed()) {
126*4d7e907cSAndroid Build Coastguard Worker ALOGE("%s: cannot open camera %s. camera init failed!",
127*4d7e907cSAndroid Build Coastguard Worker __FUNCTION__, mCameraId.c_str());
128*4d7e907cSAndroid Build Coastguard Worker _hidl_cb(Status::INTERNAL_ERROR, nullptr);
129*4d7e907cSAndroid Build Coastguard Worker return Void();
130*4d7e907cSAndroid Build Coastguard Worker }
131*4d7e907cSAndroid Build Coastguard Worker
132*4d7e907cSAndroid Build Coastguard Worker mLock.lock();
133*4d7e907cSAndroid Build Coastguard Worker
134*4d7e907cSAndroid Build Coastguard Worker ALOGV("%s: Initializing device for camera %s", __FUNCTION__, mCameraId.c_str());
135*4d7e907cSAndroid Build Coastguard Worker session = mSession.promote();
136*4d7e907cSAndroid Build Coastguard Worker if (session != nullptr && !session->isClosed()) {
137*4d7e907cSAndroid Build Coastguard Worker ALOGE("%s: cannot open an already opened camera!", __FUNCTION__);
138*4d7e907cSAndroid Build Coastguard Worker mLock.unlock();
139*4d7e907cSAndroid Build Coastguard Worker _hidl_cb(Status::CAMERA_IN_USE, nullptr);
140*4d7e907cSAndroid Build Coastguard Worker return Void();
141*4d7e907cSAndroid Build Coastguard Worker }
142*4d7e907cSAndroid Build Coastguard Worker
143*4d7e907cSAndroid Build Coastguard Worker unique_fd fd(::open(mDevicePath.c_str(), O_RDWR));
144*4d7e907cSAndroid Build Coastguard Worker if (fd.get() < 0) {
145*4d7e907cSAndroid Build Coastguard Worker int numAttempt = 0;
146*4d7e907cSAndroid Build Coastguard Worker do {
147*4d7e907cSAndroid Build Coastguard Worker ALOGW("%s: v4l2 device %s open failed, wait 33ms and try again",
148*4d7e907cSAndroid Build Coastguard Worker __FUNCTION__, mDevicePath.c_str());
149*4d7e907cSAndroid Build Coastguard Worker usleep(OPEN_RETRY_SLEEP_US); // sleep and try again
150*4d7e907cSAndroid Build Coastguard Worker fd.reset(::open(mDevicePath.c_str(), O_RDWR));
151*4d7e907cSAndroid Build Coastguard Worker numAttempt++;
152*4d7e907cSAndroid Build Coastguard Worker } while (fd.get() < 0 && numAttempt <= MAX_RETRY);
153*4d7e907cSAndroid Build Coastguard Worker
154*4d7e907cSAndroid Build Coastguard Worker if (fd.get() < 0) {
155*4d7e907cSAndroid Build Coastguard Worker ALOGE("%s: v4l2 device open %s failed: %s",
156*4d7e907cSAndroid Build Coastguard Worker __FUNCTION__, mDevicePath.c_str(), strerror(errno));
157*4d7e907cSAndroid Build Coastguard Worker mLock.unlock();
158*4d7e907cSAndroid Build Coastguard Worker _hidl_cb(Status::INTERNAL_ERROR, nullptr);
159*4d7e907cSAndroid Build Coastguard Worker return Void();
160*4d7e907cSAndroid Build Coastguard Worker }
161*4d7e907cSAndroid Build Coastguard Worker }
162*4d7e907cSAndroid Build Coastguard Worker
163*4d7e907cSAndroid Build Coastguard Worker session = createSession(
164*4d7e907cSAndroid Build Coastguard Worker callback, mCfg, mSupportedFormats, mCroppingType,
165*4d7e907cSAndroid Build Coastguard Worker mCameraCharacteristics, mCameraId, std::move(fd));
166*4d7e907cSAndroid Build Coastguard Worker if (session == nullptr) {
167*4d7e907cSAndroid Build Coastguard Worker ALOGE("%s: camera device session allocation failed", __FUNCTION__);
168*4d7e907cSAndroid Build Coastguard Worker mLock.unlock();
169*4d7e907cSAndroid Build Coastguard Worker _hidl_cb(Status::INTERNAL_ERROR, nullptr);
170*4d7e907cSAndroid Build Coastguard Worker return Void();
171*4d7e907cSAndroid Build Coastguard Worker }
172*4d7e907cSAndroid Build Coastguard Worker if (session->isInitFailed()) {
173*4d7e907cSAndroid Build Coastguard Worker ALOGE("%s: camera device session init failed", __FUNCTION__);
174*4d7e907cSAndroid Build Coastguard Worker session = nullptr;
175*4d7e907cSAndroid Build Coastguard Worker mLock.unlock();
176*4d7e907cSAndroid Build Coastguard Worker _hidl_cb(Status::INTERNAL_ERROR, nullptr);
177*4d7e907cSAndroid Build Coastguard Worker return Void();
178*4d7e907cSAndroid Build Coastguard Worker }
179*4d7e907cSAndroid Build Coastguard Worker mSession = session;
180*4d7e907cSAndroid Build Coastguard Worker
181*4d7e907cSAndroid Build Coastguard Worker mLock.unlock();
182*4d7e907cSAndroid Build Coastguard Worker
183*4d7e907cSAndroid Build Coastguard Worker _hidl_cb(status, session->getInterface());
184*4d7e907cSAndroid Build Coastguard Worker return Void();
185*4d7e907cSAndroid Build Coastguard Worker }
186*4d7e907cSAndroid Build Coastguard Worker
dumpState(const::android::hardware::hidl_handle & handle)187*4d7e907cSAndroid Build Coastguard Worker Return<void> ExternalCameraDevice::dumpState(const ::android::hardware::hidl_handle& handle) {
188*4d7e907cSAndroid Build Coastguard Worker Mutex::Autolock _l(mLock);
189*4d7e907cSAndroid Build Coastguard Worker if (handle.getNativeHandle() == nullptr) {
190*4d7e907cSAndroid Build Coastguard Worker ALOGE("%s: handle must not be null", __FUNCTION__);
191*4d7e907cSAndroid Build Coastguard Worker return Void();
192*4d7e907cSAndroid Build Coastguard Worker }
193*4d7e907cSAndroid Build Coastguard Worker if (handle->numFds != 1 || handle->numInts != 0) {
194*4d7e907cSAndroid Build Coastguard Worker ALOGE("%s: handle must contain 1 FD and 0 integers! Got %d FDs and %d ints",
195*4d7e907cSAndroid Build Coastguard Worker __FUNCTION__, handle->numFds, handle->numInts);
196*4d7e907cSAndroid Build Coastguard Worker return Void();
197*4d7e907cSAndroid Build Coastguard Worker }
198*4d7e907cSAndroid Build Coastguard Worker int fd = handle->data[0];
199*4d7e907cSAndroid Build Coastguard Worker if (mSession == nullptr) {
200*4d7e907cSAndroid Build Coastguard Worker dprintf(fd, "No active camera device session instance\n");
201*4d7e907cSAndroid Build Coastguard Worker return Void();
202*4d7e907cSAndroid Build Coastguard Worker }
203*4d7e907cSAndroid Build Coastguard Worker auto session = mSession.promote();
204*4d7e907cSAndroid Build Coastguard Worker if (session == nullptr) {
205*4d7e907cSAndroid Build Coastguard Worker dprintf(fd, "No active camera device session instance\n");
206*4d7e907cSAndroid Build Coastguard Worker return Void();
207*4d7e907cSAndroid Build Coastguard Worker }
208*4d7e907cSAndroid Build Coastguard Worker // Call into active session to dump states
209*4d7e907cSAndroid Build Coastguard Worker session->dumpState(handle);
210*4d7e907cSAndroid Build Coastguard Worker return Void();
211*4d7e907cSAndroid Build Coastguard Worker }
212*4d7e907cSAndroid Build Coastguard Worker
213*4d7e907cSAndroid Build Coastguard Worker
initCameraCharacteristics()214*4d7e907cSAndroid Build Coastguard Worker status_t ExternalCameraDevice::initCameraCharacteristics() {
215*4d7e907cSAndroid Build Coastguard Worker if (mCameraCharacteristics.isEmpty()) {
216*4d7e907cSAndroid Build Coastguard Worker // init camera characteristics
217*4d7e907cSAndroid Build Coastguard Worker unique_fd fd(::open(mDevicePath.c_str(), O_RDWR));
218*4d7e907cSAndroid Build Coastguard Worker if (fd.get() < 0) {
219*4d7e907cSAndroid Build Coastguard Worker ALOGE("%s: v4l2 device open %s failed", __FUNCTION__, mDevicePath.c_str());
220*4d7e907cSAndroid Build Coastguard Worker return DEAD_OBJECT;
221*4d7e907cSAndroid Build Coastguard Worker }
222*4d7e907cSAndroid Build Coastguard Worker
223*4d7e907cSAndroid Build Coastguard Worker status_t ret;
224*4d7e907cSAndroid Build Coastguard Worker ret = initDefaultCharsKeys(&mCameraCharacteristics);
225*4d7e907cSAndroid Build Coastguard Worker if (ret != OK) {
226*4d7e907cSAndroid Build Coastguard Worker ALOGE("%s: init default characteristics key failed: errorno %d", __FUNCTION__, ret);
227*4d7e907cSAndroid Build Coastguard Worker mCameraCharacteristics.clear();
228*4d7e907cSAndroid Build Coastguard Worker return ret;
229*4d7e907cSAndroid Build Coastguard Worker }
230*4d7e907cSAndroid Build Coastguard Worker
231*4d7e907cSAndroid Build Coastguard Worker ret = initCameraControlsCharsKeys(fd.get(), &mCameraCharacteristics);
232*4d7e907cSAndroid Build Coastguard Worker if (ret != OK) {
233*4d7e907cSAndroid Build Coastguard Worker ALOGE("%s: init camera control characteristics key failed: errorno %d", __FUNCTION__, ret);
234*4d7e907cSAndroid Build Coastguard Worker mCameraCharacteristics.clear();
235*4d7e907cSAndroid Build Coastguard Worker return ret;
236*4d7e907cSAndroid Build Coastguard Worker }
237*4d7e907cSAndroid Build Coastguard Worker
238*4d7e907cSAndroid Build Coastguard Worker ret = initOutputCharsKeys(fd.get(), &mCameraCharacteristics);
239*4d7e907cSAndroid Build Coastguard Worker if (ret != OK) {
240*4d7e907cSAndroid Build Coastguard Worker ALOGE("%s: init output characteristics key failed: errorno %d", __FUNCTION__, ret);
241*4d7e907cSAndroid Build Coastguard Worker mCameraCharacteristics.clear();
242*4d7e907cSAndroid Build Coastguard Worker return ret;
243*4d7e907cSAndroid Build Coastguard Worker }
244*4d7e907cSAndroid Build Coastguard Worker
245*4d7e907cSAndroid Build Coastguard Worker ret = initAvailableCapabilities(&mCameraCharacteristics);
246*4d7e907cSAndroid Build Coastguard Worker if (ret != OK) {
247*4d7e907cSAndroid Build Coastguard Worker ALOGE("%s: init available capabilities key failed: errorno %d", __FUNCTION__, ret);
248*4d7e907cSAndroid Build Coastguard Worker mCameraCharacteristics.clear();
249*4d7e907cSAndroid Build Coastguard Worker return ret;
250*4d7e907cSAndroid Build Coastguard Worker }
251*4d7e907cSAndroid Build Coastguard Worker }
252*4d7e907cSAndroid Build Coastguard Worker return OK;
253*4d7e907cSAndroid Build Coastguard Worker }
254*4d7e907cSAndroid Build Coastguard Worker
255*4d7e907cSAndroid Build Coastguard Worker #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
256*4d7e907cSAndroid Build Coastguard Worker #define UPDATE(tag, data, size) \
257*4d7e907cSAndroid Build Coastguard Worker do { \
258*4d7e907cSAndroid Build Coastguard Worker if (metadata->update((tag), (data), (size))) { \
259*4d7e907cSAndroid Build Coastguard Worker ALOGE("Update " #tag " failed!"); \
260*4d7e907cSAndroid Build Coastguard Worker return -EINVAL; \
261*4d7e907cSAndroid Build Coastguard Worker } \
262*4d7e907cSAndroid Build Coastguard Worker } while (0)
263*4d7e907cSAndroid Build Coastguard Worker
initAvailableCapabilities(::android::hardware::camera::common::V1_0::helper::CameraMetadata * metadata)264*4d7e907cSAndroid Build Coastguard Worker status_t ExternalCameraDevice::initAvailableCapabilities(
265*4d7e907cSAndroid Build Coastguard Worker ::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) {
266*4d7e907cSAndroid Build Coastguard Worker
267*4d7e907cSAndroid Build Coastguard Worker if (mSupportedFormats.empty()) {
268*4d7e907cSAndroid Build Coastguard Worker ALOGE("%s: Supported formats list is empty", __FUNCTION__);
269*4d7e907cSAndroid Build Coastguard Worker return UNKNOWN_ERROR;
270*4d7e907cSAndroid Build Coastguard Worker }
271*4d7e907cSAndroid Build Coastguard Worker
272*4d7e907cSAndroid Build Coastguard Worker bool hasDepth = false;
273*4d7e907cSAndroid Build Coastguard Worker bool hasColor = false;
274*4d7e907cSAndroid Build Coastguard Worker for (const auto& fmt : mSupportedFormats) {
275*4d7e907cSAndroid Build Coastguard Worker switch (fmt.fourcc) {
276*4d7e907cSAndroid Build Coastguard Worker case V4L2_PIX_FMT_Z16: hasDepth = true; break;
277*4d7e907cSAndroid Build Coastguard Worker case V4L2_PIX_FMT_MJPEG: hasColor = true; break;
278*4d7e907cSAndroid Build Coastguard Worker default: ALOGW("%s: Unsupported format found", __FUNCTION__);
279*4d7e907cSAndroid Build Coastguard Worker }
280*4d7e907cSAndroid Build Coastguard Worker }
281*4d7e907cSAndroid Build Coastguard Worker
282*4d7e907cSAndroid Build Coastguard Worker std::vector<uint8_t> availableCapabilities;
283*4d7e907cSAndroid Build Coastguard Worker if (hasDepth) {
284*4d7e907cSAndroid Build Coastguard Worker availableCapabilities.push_back(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT);
285*4d7e907cSAndroid Build Coastguard Worker }
286*4d7e907cSAndroid Build Coastguard Worker if (hasColor) {
287*4d7e907cSAndroid Build Coastguard Worker availableCapabilities.push_back(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
288*4d7e907cSAndroid Build Coastguard Worker }
289*4d7e907cSAndroid Build Coastguard Worker if(!availableCapabilities.empty()) {
290*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, availableCapabilities.data(),
291*4d7e907cSAndroid Build Coastguard Worker availableCapabilities.size());
292*4d7e907cSAndroid Build Coastguard Worker }
293*4d7e907cSAndroid Build Coastguard Worker
294*4d7e907cSAndroid Build Coastguard Worker return OK;
295*4d7e907cSAndroid Build Coastguard Worker }
296*4d7e907cSAndroid Build Coastguard Worker
initDefaultCharsKeys(::android::hardware::camera::common::V1_0::helper::CameraMetadata * metadata)297*4d7e907cSAndroid Build Coastguard Worker status_t ExternalCameraDevice::initDefaultCharsKeys(
298*4d7e907cSAndroid Build Coastguard Worker ::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) {
299*4d7e907cSAndroid Build Coastguard Worker const uint8_t hardware_level = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL;
300*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL, &hardware_level, 1);
301*4d7e907cSAndroid Build Coastguard Worker
302*4d7e907cSAndroid Build Coastguard Worker // android.colorCorrection
303*4d7e907cSAndroid Build Coastguard Worker const uint8_t availableAberrationModes[] = {
304*4d7e907cSAndroid Build Coastguard Worker ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF};
305*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
306*4d7e907cSAndroid Build Coastguard Worker availableAberrationModes, ARRAY_SIZE(availableAberrationModes));
307*4d7e907cSAndroid Build Coastguard Worker
308*4d7e907cSAndroid Build Coastguard Worker // android.control
309*4d7e907cSAndroid Build Coastguard Worker const uint8_t antibandingMode =
310*4d7e907cSAndroid Build Coastguard Worker ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO;
311*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
312*4d7e907cSAndroid Build Coastguard Worker &antibandingMode, 1);
313*4d7e907cSAndroid Build Coastguard Worker
314*4d7e907cSAndroid Build Coastguard Worker const int32_t controlMaxRegions[] = {/*AE*/ 0, /*AWB*/ 0, /*AF*/ 0};
315*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_CONTROL_MAX_REGIONS, controlMaxRegions,
316*4d7e907cSAndroid Build Coastguard Worker ARRAY_SIZE(controlMaxRegions));
317*4d7e907cSAndroid Build Coastguard Worker
318*4d7e907cSAndroid Build Coastguard Worker const uint8_t videoStabilizationMode =
319*4d7e907cSAndroid Build Coastguard Worker ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF;
320*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
321*4d7e907cSAndroid Build Coastguard Worker &videoStabilizationMode, 1);
322*4d7e907cSAndroid Build Coastguard Worker
323*4d7e907cSAndroid Build Coastguard Worker const uint8_t awbAvailableMode = ANDROID_CONTROL_AWB_MODE_AUTO;
324*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_CONTROL_AWB_AVAILABLE_MODES, &awbAvailableMode, 1);
325*4d7e907cSAndroid Build Coastguard Worker
326*4d7e907cSAndroid Build Coastguard Worker const uint8_t aeAvailableMode = ANDROID_CONTROL_AE_MODE_ON;
327*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_CONTROL_AE_AVAILABLE_MODES, &aeAvailableMode, 1);
328*4d7e907cSAndroid Build Coastguard Worker
329*4d7e907cSAndroid Build Coastguard Worker const uint8_t availableFffect = ANDROID_CONTROL_EFFECT_MODE_OFF;
330*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_CONTROL_AVAILABLE_EFFECTS, &availableFffect, 1);
331*4d7e907cSAndroid Build Coastguard Worker
332*4d7e907cSAndroid Build Coastguard Worker const uint8_t controlAvailableModes[] = {ANDROID_CONTROL_MODE_OFF,
333*4d7e907cSAndroid Build Coastguard Worker ANDROID_CONTROL_MODE_AUTO};
334*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_CONTROL_AVAILABLE_MODES, controlAvailableModes,
335*4d7e907cSAndroid Build Coastguard Worker ARRAY_SIZE(controlAvailableModes));
336*4d7e907cSAndroid Build Coastguard Worker
337*4d7e907cSAndroid Build Coastguard Worker // android.edge
338*4d7e907cSAndroid Build Coastguard Worker const uint8_t edgeMode = ANDROID_EDGE_MODE_OFF;
339*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_EDGE_AVAILABLE_EDGE_MODES, &edgeMode, 1);
340*4d7e907cSAndroid Build Coastguard Worker
341*4d7e907cSAndroid Build Coastguard Worker // android.flash
342*4d7e907cSAndroid Build Coastguard Worker const uint8_t flashInfo = ANDROID_FLASH_INFO_AVAILABLE_FALSE;
343*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_FLASH_INFO_AVAILABLE, &flashInfo, 1);
344*4d7e907cSAndroid Build Coastguard Worker
345*4d7e907cSAndroid Build Coastguard Worker // android.hotPixel
346*4d7e907cSAndroid Build Coastguard Worker const uint8_t hotPixelMode = ANDROID_HOT_PIXEL_MODE_OFF;
347*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES, &hotPixelMode, 1);
348*4d7e907cSAndroid Build Coastguard Worker
349*4d7e907cSAndroid Build Coastguard Worker // android.jpeg
350*4d7e907cSAndroid Build Coastguard Worker const int32_t jpegAvailableThumbnailSizes[] = {0, 0,
351*4d7e907cSAndroid Build Coastguard Worker 176, 144,
352*4d7e907cSAndroid Build Coastguard Worker 240, 144,
353*4d7e907cSAndroid Build Coastguard Worker 256, 144,
354*4d7e907cSAndroid Build Coastguard Worker 240, 160,
355*4d7e907cSAndroid Build Coastguard Worker 256, 154,
356*4d7e907cSAndroid Build Coastguard Worker 240, 180};
357*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES, jpegAvailableThumbnailSizes,
358*4d7e907cSAndroid Build Coastguard Worker ARRAY_SIZE(jpegAvailableThumbnailSizes));
359*4d7e907cSAndroid Build Coastguard Worker
360*4d7e907cSAndroid Build Coastguard Worker const int32_t jpegMaxSize = mCfg.maxJpegBufSize;
361*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_JPEG_MAX_SIZE, &jpegMaxSize, 1);
362*4d7e907cSAndroid Build Coastguard Worker
363*4d7e907cSAndroid Build Coastguard Worker // android.lens
364*4d7e907cSAndroid Build Coastguard Worker const uint8_t focusDistanceCalibration =
365*4d7e907cSAndroid Build Coastguard Worker ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION_UNCALIBRATED;
366*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION, &focusDistanceCalibration, 1);
367*4d7e907cSAndroid Build Coastguard Worker
368*4d7e907cSAndroid Build Coastguard Worker const uint8_t opticalStabilizationMode =
369*4d7e907cSAndroid Build Coastguard Worker ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF;
370*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
371*4d7e907cSAndroid Build Coastguard Worker &opticalStabilizationMode, 1);
372*4d7e907cSAndroid Build Coastguard Worker
373*4d7e907cSAndroid Build Coastguard Worker const uint8_t facing = ANDROID_LENS_FACING_EXTERNAL;
374*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_LENS_FACING, &facing, 1);
375*4d7e907cSAndroid Build Coastguard Worker
376*4d7e907cSAndroid Build Coastguard Worker // android.noiseReduction
377*4d7e907cSAndroid Build Coastguard Worker const uint8_t noiseReductionMode = ANDROID_NOISE_REDUCTION_MODE_OFF;
378*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
379*4d7e907cSAndroid Build Coastguard Worker &noiseReductionMode, 1);
380*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_NOISE_REDUCTION_MODE, &noiseReductionMode, 1);
381*4d7e907cSAndroid Build Coastguard Worker
382*4d7e907cSAndroid Build Coastguard Worker const int32_t partialResultCount = 1;
383*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_REQUEST_PARTIAL_RESULT_COUNT, &partialResultCount, 1);
384*4d7e907cSAndroid Build Coastguard Worker
385*4d7e907cSAndroid Build Coastguard Worker // This means pipeline latency of X frame intervals. The maximum number is 4.
386*4d7e907cSAndroid Build Coastguard Worker const uint8_t requestPipelineMaxDepth = 4;
387*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_REQUEST_PIPELINE_MAX_DEPTH, &requestPipelineMaxDepth, 1);
388*4d7e907cSAndroid Build Coastguard Worker
389*4d7e907cSAndroid Build Coastguard Worker // Three numbers represent the maximum numbers of different types of output
390*4d7e907cSAndroid Build Coastguard Worker // streams simultaneously. The types are raw sensor, processed (but not
391*4d7e907cSAndroid Build Coastguard Worker // stalling), and processed (but stalling). For usb limited mode, raw sensor
392*4d7e907cSAndroid Build Coastguard Worker // is not supported. Stalling stream is JPEG. Non-stalling streams are
393*4d7e907cSAndroid Build Coastguard Worker // YUV_420_888 or YV12.
394*4d7e907cSAndroid Build Coastguard Worker const int32_t requestMaxNumOutputStreams[] = {
395*4d7e907cSAndroid Build Coastguard Worker /*RAW*/0,
396*4d7e907cSAndroid Build Coastguard Worker /*Processed*/ExternalCameraDeviceSession::kMaxProcessedStream,
397*4d7e907cSAndroid Build Coastguard Worker /*Stall*/ExternalCameraDeviceSession::kMaxStallStream};
398*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS, requestMaxNumOutputStreams,
399*4d7e907cSAndroid Build Coastguard Worker ARRAY_SIZE(requestMaxNumOutputStreams));
400*4d7e907cSAndroid Build Coastguard Worker
401*4d7e907cSAndroid Build Coastguard Worker // Limited mode doesn't support reprocessing.
402*4d7e907cSAndroid Build Coastguard Worker const int32_t requestMaxNumInputStreams = 0;
403*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS, &requestMaxNumInputStreams,
404*4d7e907cSAndroid Build Coastguard Worker 1);
405*4d7e907cSAndroid Build Coastguard Worker
406*4d7e907cSAndroid Build Coastguard Worker // android.scaler
407*4d7e907cSAndroid Build Coastguard Worker // TODO: b/72263447 V4L2_CID_ZOOM_*
408*4d7e907cSAndroid Build Coastguard Worker const float scalerAvailableMaxDigitalZoom[] = {1};
409*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
410*4d7e907cSAndroid Build Coastguard Worker scalerAvailableMaxDigitalZoom,
411*4d7e907cSAndroid Build Coastguard Worker ARRAY_SIZE(scalerAvailableMaxDigitalZoom));
412*4d7e907cSAndroid Build Coastguard Worker
413*4d7e907cSAndroid Build Coastguard Worker const uint8_t croppingType = ANDROID_SCALER_CROPPING_TYPE_CENTER_ONLY;
414*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_SCALER_CROPPING_TYPE, &croppingType, 1);
415*4d7e907cSAndroid Build Coastguard Worker
416*4d7e907cSAndroid Build Coastguard Worker const int32_t testPatternModes[] = {ANDROID_SENSOR_TEST_PATTERN_MODE_OFF,
417*4d7e907cSAndroid Build Coastguard Worker ANDROID_SENSOR_TEST_PATTERN_MODE_SOLID_COLOR};
418*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES, testPatternModes,
419*4d7e907cSAndroid Build Coastguard Worker ARRAY_SIZE(testPatternModes));
420*4d7e907cSAndroid Build Coastguard Worker
421*4d7e907cSAndroid Build Coastguard Worker const uint8_t timestampSource = ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN;
422*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE, ×tampSource, 1);
423*4d7e907cSAndroid Build Coastguard Worker
424*4d7e907cSAndroid Build Coastguard Worker // Orientation is a bit odd for external camera, but consider it as the orientation
425*4d7e907cSAndroid Build Coastguard Worker // between the external camera sensor (which is usually landscape) and the device's
426*4d7e907cSAndroid Build Coastguard Worker // natural display orientation. For devices with natural landscape display (ex: tablet/TV), the
427*4d7e907cSAndroid Build Coastguard Worker // orientation should be 0. For devices with natural portrait display (phone), the orientation
428*4d7e907cSAndroid Build Coastguard Worker // should be 270.
429*4d7e907cSAndroid Build Coastguard Worker const int32_t orientation = mCfg.orientation;
430*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_SENSOR_ORIENTATION, &orientation, 1);
431*4d7e907cSAndroid Build Coastguard Worker
432*4d7e907cSAndroid Build Coastguard Worker // android.shading
433*4d7e907cSAndroid Build Coastguard Worker const uint8_t availabeMode = ANDROID_SHADING_MODE_OFF;
434*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_SHADING_AVAILABLE_MODES, &availabeMode, 1);
435*4d7e907cSAndroid Build Coastguard Worker
436*4d7e907cSAndroid Build Coastguard Worker // android.statistics
437*4d7e907cSAndroid Build Coastguard Worker const uint8_t faceDetectMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;
438*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES, &faceDetectMode,
439*4d7e907cSAndroid Build Coastguard Worker 1);
440*4d7e907cSAndroid Build Coastguard Worker
441*4d7e907cSAndroid Build Coastguard Worker const int32_t maxFaceCount = 0;
442*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_STATISTICS_INFO_MAX_FACE_COUNT, &maxFaceCount, 1);
443*4d7e907cSAndroid Build Coastguard Worker
444*4d7e907cSAndroid Build Coastguard Worker const uint8_t availableHotpixelMode =
445*4d7e907cSAndroid Build Coastguard Worker ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE_OFF;
446*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES,
447*4d7e907cSAndroid Build Coastguard Worker &availableHotpixelMode, 1);
448*4d7e907cSAndroid Build Coastguard Worker
449*4d7e907cSAndroid Build Coastguard Worker const uint8_t lensShadingMapMode =
450*4d7e907cSAndroid Build Coastguard Worker ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF;
451*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES,
452*4d7e907cSAndroid Build Coastguard Worker &lensShadingMapMode, 1);
453*4d7e907cSAndroid Build Coastguard Worker
454*4d7e907cSAndroid Build Coastguard Worker // android.sync
455*4d7e907cSAndroid Build Coastguard Worker const int32_t maxLatency = ANDROID_SYNC_MAX_LATENCY_UNKNOWN;
456*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_SYNC_MAX_LATENCY, &maxLatency, 1);
457*4d7e907cSAndroid Build Coastguard Worker
458*4d7e907cSAndroid Build Coastguard Worker /* Other sensor/RAW realted keys:
459*4d7e907cSAndroid Build Coastguard Worker * android.sensor.info.colorFilterArrangement -> no need if we don't do RAW
460*4d7e907cSAndroid Build Coastguard Worker * android.sensor.info.physicalSize -> not available
461*4d7e907cSAndroid Build Coastguard Worker * android.sensor.info.whiteLevel -> not available/not needed
462*4d7e907cSAndroid Build Coastguard Worker * android.sensor.info.lensShadingApplied -> not needed
463*4d7e907cSAndroid Build Coastguard Worker * android.sensor.info.preCorrectionActiveArraySize -> not available/not needed
464*4d7e907cSAndroid Build Coastguard Worker * android.sensor.blackLevelPattern -> not available/not needed
465*4d7e907cSAndroid Build Coastguard Worker */
466*4d7e907cSAndroid Build Coastguard Worker
467*4d7e907cSAndroid Build Coastguard Worker const int32_t availableRequestKeys[] = {
468*4d7e907cSAndroid Build Coastguard Worker ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
469*4d7e907cSAndroid Build Coastguard Worker ANDROID_CONTROL_AE_ANTIBANDING_MODE,
470*4d7e907cSAndroid Build Coastguard Worker ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
471*4d7e907cSAndroid Build Coastguard Worker ANDROID_CONTROL_AE_LOCK,
472*4d7e907cSAndroid Build Coastguard Worker ANDROID_CONTROL_AE_MODE,
473*4d7e907cSAndroid Build Coastguard Worker ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
474*4d7e907cSAndroid Build Coastguard Worker ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
475*4d7e907cSAndroid Build Coastguard Worker ANDROID_CONTROL_AF_MODE,
476*4d7e907cSAndroid Build Coastguard Worker ANDROID_CONTROL_AF_TRIGGER,
477*4d7e907cSAndroid Build Coastguard Worker ANDROID_CONTROL_AWB_LOCK,
478*4d7e907cSAndroid Build Coastguard Worker ANDROID_CONTROL_AWB_MODE,
479*4d7e907cSAndroid Build Coastguard Worker ANDROID_CONTROL_CAPTURE_INTENT,
480*4d7e907cSAndroid Build Coastguard Worker ANDROID_CONTROL_EFFECT_MODE,
481*4d7e907cSAndroid Build Coastguard Worker ANDROID_CONTROL_MODE,
482*4d7e907cSAndroid Build Coastguard Worker ANDROID_CONTROL_SCENE_MODE,
483*4d7e907cSAndroid Build Coastguard Worker ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
484*4d7e907cSAndroid Build Coastguard Worker ANDROID_FLASH_MODE,
485*4d7e907cSAndroid Build Coastguard Worker ANDROID_JPEG_ORIENTATION,
486*4d7e907cSAndroid Build Coastguard Worker ANDROID_JPEG_QUALITY,
487*4d7e907cSAndroid Build Coastguard Worker ANDROID_JPEG_THUMBNAIL_QUALITY,
488*4d7e907cSAndroid Build Coastguard Worker ANDROID_JPEG_THUMBNAIL_SIZE,
489*4d7e907cSAndroid Build Coastguard Worker ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
490*4d7e907cSAndroid Build Coastguard Worker ANDROID_NOISE_REDUCTION_MODE,
491*4d7e907cSAndroid Build Coastguard Worker ANDROID_SCALER_CROP_REGION,
492*4d7e907cSAndroid Build Coastguard Worker ANDROID_SENSOR_TEST_PATTERN_MODE,
493*4d7e907cSAndroid Build Coastguard Worker ANDROID_STATISTICS_FACE_DETECT_MODE,
494*4d7e907cSAndroid Build Coastguard Worker ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE};
495*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS, availableRequestKeys,
496*4d7e907cSAndroid Build Coastguard Worker ARRAY_SIZE(availableRequestKeys));
497*4d7e907cSAndroid Build Coastguard Worker
498*4d7e907cSAndroid Build Coastguard Worker const int32_t availableResultKeys[] = {
499*4d7e907cSAndroid Build Coastguard Worker ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
500*4d7e907cSAndroid Build Coastguard Worker ANDROID_CONTROL_AE_ANTIBANDING_MODE,
501*4d7e907cSAndroid Build Coastguard Worker ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
502*4d7e907cSAndroid Build Coastguard Worker ANDROID_CONTROL_AE_LOCK,
503*4d7e907cSAndroid Build Coastguard Worker ANDROID_CONTROL_AE_MODE,
504*4d7e907cSAndroid Build Coastguard Worker ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
505*4d7e907cSAndroid Build Coastguard Worker ANDROID_CONTROL_AE_STATE,
506*4d7e907cSAndroid Build Coastguard Worker ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
507*4d7e907cSAndroid Build Coastguard Worker ANDROID_CONTROL_AF_MODE,
508*4d7e907cSAndroid Build Coastguard Worker ANDROID_CONTROL_AF_STATE,
509*4d7e907cSAndroid Build Coastguard Worker ANDROID_CONTROL_AF_TRIGGER,
510*4d7e907cSAndroid Build Coastguard Worker ANDROID_CONTROL_AWB_LOCK,
511*4d7e907cSAndroid Build Coastguard Worker ANDROID_CONTROL_AWB_MODE,
512*4d7e907cSAndroid Build Coastguard Worker ANDROID_CONTROL_AWB_STATE,
513*4d7e907cSAndroid Build Coastguard Worker ANDROID_CONTROL_CAPTURE_INTENT,
514*4d7e907cSAndroid Build Coastguard Worker ANDROID_CONTROL_EFFECT_MODE,
515*4d7e907cSAndroid Build Coastguard Worker ANDROID_CONTROL_MODE,
516*4d7e907cSAndroid Build Coastguard Worker ANDROID_CONTROL_SCENE_MODE,
517*4d7e907cSAndroid Build Coastguard Worker ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
518*4d7e907cSAndroid Build Coastguard Worker ANDROID_FLASH_MODE,
519*4d7e907cSAndroid Build Coastguard Worker ANDROID_FLASH_STATE,
520*4d7e907cSAndroid Build Coastguard Worker ANDROID_JPEG_ORIENTATION,
521*4d7e907cSAndroid Build Coastguard Worker ANDROID_JPEG_QUALITY,
522*4d7e907cSAndroid Build Coastguard Worker ANDROID_JPEG_THUMBNAIL_QUALITY,
523*4d7e907cSAndroid Build Coastguard Worker ANDROID_JPEG_THUMBNAIL_SIZE,
524*4d7e907cSAndroid Build Coastguard Worker ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
525*4d7e907cSAndroid Build Coastguard Worker ANDROID_NOISE_REDUCTION_MODE,
526*4d7e907cSAndroid Build Coastguard Worker ANDROID_REQUEST_PIPELINE_DEPTH,
527*4d7e907cSAndroid Build Coastguard Worker ANDROID_SCALER_CROP_REGION,
528*4d7e907cSAndroid Build Coastguard Worker ANDROID_SENSOR_TIMESTAMP,
529*4d7e907cSAndroid Build Coastguard Worker ANDROID_STATISTICS_FACE_DETECT_MODE,
530*4d7e907cSAndroid Build Coastguard Worker ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE,
531*4d7e907cSAndroid Build Coastguard Worker ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,
532*4d7e907cSAndroid Build Coastguard Worker ANDROID_STATISTICS_SCENE_FLICKER};
533*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_REQUEST_AVAILABLE_RESULT_KEYS, availableResultKeys,
534*4d7e907cSAndroid Build Coastguard Worker ARRAY_SIZE(availableResultKeys));
535*4d7e907cSAndroid Build Coastguard Worker
536*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS,
537*4d7e907cSAndroid Build Coastguard Worker AVAILABLE_CHARACTERISTICS_KEYS_3_4.data(),
538*4d7e907cSAndroid Build Coastguard Worker AVAILABLE_CHARACTERISTICS_KEYS_3_4.size());
539*4d7e907cSAndroid Build Coastguard Worker
540*4d7e907cSAndroid Build Coastguard Worker return OK;
541*4d7e907cSAndroid Build Coastguard Worker }
542*4d7e907cSAndroid Build Coastguard Worker
initCameraControlsCharsKeys(int,::android::hardware::camera::common::V1_0::helper::CameraMetadata * metadata)543*4d7e907cSAndroid Build Coastguard Worker status_t ExternalCameraDevice::initCameraControlsCharsKeys(int,
544*4d7e907cSAndroid Build Coastguard Worker ::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) {
545*4d7e907cSAndroid Build Coastguard Worker /**
546*4d7e907cSAndroid Build Coastguard Worker * android.sensor.info.sensitivityRange -> V4L2_CID_ISO_SENSITIVITY
547*4d7e907cSAndroid Build Coastguard Worker * android.sensor.info.exposureTimeRange -> V4L2_CID_EXPOSURE_ABSOLUTE
548*4d7e907cSAndroid Build Coastguard Worker * android.sensor.info.maxFrameDuration -> TBD
549*4d7e907cSAndroid Build Coastguard Worker * android.lens.info.minimumFocusDistance -> V4L2_CID_FOCUS_ABSOLUTE
550*4d7e907cSAndroid Build Coastguard Worker * android.lens.info.hyperfocalDistance
551*4d7e907cSAndroid Build Coastguard Worker * android.lens.info.availableFocalLengths -> not available?
552*4d7e907cSAndroid Build Coastguard Worker */
553*4d7e907cSAndroid Build Coastguard Worker
554*4d7e907cSAndroid Build Coastguard Worker // android.control
555*4d7e907cSAndroid Build Coastguard Worker // No AE compensation support for now.
556*4d7e907cSAndroid Build Coastguard Worker // TODO: V4L2_CID_EXPOSURE_BIAS
557*4d7e907cSAndroid Build Coastguard Worker const int32_t controlAeCompensationRange[] = {0, 0};
558*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_CONTROL_AE_COMPENSATION_RANGE, controlAeCompensationRange,
559*4d7e907cSAndroid Build Coastguard Worker ARRAY_SIZE(controlAeCompensationRange));
560*4d7e907cSAndroid Build Coastguard Worker const camera_metadata_rational_t controlAeCompensationStep[] = {{0, 1}};
561*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_CONTROL_AE_COMPENSATION_STEP, controlAeCompensationStep,
562*4d7e907cSAndroid Build Coastguard Worker ARRAY_SIZE(controlAeCompensationStep));
563*4d7e907cSAndroid Build Coastguard Worker
564*4d7e907cSAndroid Build Coastguard Worker
565*4d7e907cSAndroid Build Coastguard Worker // TODO: Check V4L2_CID_AUTO_FOCUS_*.
566*4d7e907cSAndroid Build Coastguard Worker const uint8_t afAvailableModes[] = {ANDROID_CONTROL_AF_MODE_AUTO,
567*4d7e907cSAndroid Build Coastguard Worker ANDROID_CONTROL_AF_MODE_OFF};
568*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_CONTROL_AF_AVAILABLE_MODES, afAvailableModes,
569*4d7e907cSAndroid Build Coastguard Worker ARRAY_SIZE(afAvailableModes));
570*4d7e907cSAndroid Build Coastguard Worker
571*4d7e907cSAndroid Build Coastguard Worker // TODO: V4L2_CID_SCENE_MODE
572*4d7e907cSAndroid Build Coastguard Worker const uint8_t availableSceneMode = ANDROID_CONTROL_SCENE_MODE_DISABLED;
573*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_CONTROL_AVAILABLE_SCENE_MODES, &availableSceneMode, 1);
574*4d7e907cSAndroid Build Coastguard Worker
575*4d7e907cSAndroid Build Coastguard Worker // TODO: V4L2_CID_3A_LOCK
576*4d7e907cSAndroid Build Coastguard Worker const uint8_t aeLockAvailable = ANDROID_CONTROL_AE_LOCK_AVAILABLE_FALSE;
577*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_CONTROL_AE_LOCK_AVAILABLE, &aeLockAvailable, 1);
578*4d7e907cSAndroid Build Coastguard Worker const uint8_t awbLockAvailable = ANDROID_CONTROL_AWB_LOCK_AVAILABLE_FALSE;
579*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_CONTROL_AWB_LOCK_AVAILABLE, &awbLockAvailable, 1);
580*4d7e907cSAndroid Build Coastguard Worker
581*4d7e907cSAndroid Build Coastguard Worker // TODO: V4L2_CID_ZOOM_*
582*4d7e907cSAndroid Build Coastguard Worker const float scalerAvailableMaxDigitalZoom[] = {1};
583*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
584*4d7e907cSAndroid Build Coastguard Worker scalerAvailableMaxDigitalZoom,
585*4d7e907cSAndroid Build Coastguard Worker ARRAY_SIZE(scalerAvailableMaxDigitalZoom));
586*4d7e907cSAndroid Build Coastguard Worker
587*4d7e907cSAndroid Build Coastguard Worker return OK;
588*4d7e907cSAndroid Build Coastguard Worker }
589*4d7e907cSAndroid Build Coastguard Worker
590*4d7e907cSAndroid Build Coastguard Worker template <size_t SIZE>
initOutputCharskeysByFormat(::android::hardware::camera::common::V1_0::helper::CameraMetadata * metadata,uint32_t fourcc,const std::array<int,SIZE> & halFormats,int streamConfigTag,int streamConfiguration,int minFrameDuration,int stallDuration)591*4d7e907cSAndroid Build Coastguard Worker status_t ExternalCameraDevice::initOutputCharskeysByFormat(
592*4d7e907cSAndroid Build Coastguard Worker ::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata,
593*4d7e907cSAndroid Build Coastguard Worker uint32_t fourcc, const std::array<int, SIZE>& halFormats,
594*4d7e907cSAndroid Build Coastguard Worker int streamConfigTag, int streamConfiguration, int minFrameDuration, int stallDuration) {
595*4d7e907cSAndroid Build Coastguard Worker if (mSupportedFormats.empty()) {
596*4d7e907cSAndroid Build Coastguard Worker ALOGE("%s: Init supported format list failed", __FUNCTION__);
597*4d7e907cSAndroid Build Coastguard Worker return UNKNOWN_ERROR;
598*4d7e907cSAndroid Build Coastguard Worker }
599*4d7e907cSAndroid Build Coastguard Worker
600*4d7e907cSAndroid Build Coastguard Worker std::vector<int32_t> streamConfigurations;
601*4d7e907cSAndroid Build Coastguard Worker std::vector<int64_t> minFrameDurations;
602*4d7e907cSAndroid Build Coastguard Worker std::vector<int64_t> stallDurations;
603*4d7e907cSAndroid Build Coastguard Worker
604*4d7e907cSAndroid Build Coastguard Worker for (const auto& supportedFormat : mSupportedFormats) {
605*4d7e907cSAndroid Build Coastguard Worker if (supportedFormat.fourcc != fourcc) {
606*4d7e907cSAndroid Build Coastguard Worker // Skip 4CCs not meant for the halFormats
607*4d7e907cSAndroid Build Coastguard Worker continue;
608*4d7e907cSAndroid Build Coastguard Worker }
609*4d7e907cSAndroid Build Coastguard Worker for (const auto& format : halFormats) {
610*4d7e907cSAndroid Build Coastguard Worker streamConfigurations.push_back(format);
611*4d7e907cSAndroid Build Coastguard Worker streamConfigurations.push_back(supportedFormat.width);
612*4d7e907cSAndroid Build Coastguard Worker streamConfigurations.push_back(supportedFormat.height);
613*4d7e907cSAndroid Build Coastguard Worker streamConfigurations.push_back(streamConfigTag);
614*4d7e907cSAndroid Build Coastguard Worker }
615*4d7e907cSAndroid Build Coastguard Worker
616*4d7e907cSAndroid Build Coastguard Worker int64_t minFrameDuration = std::numeric_limits<int64_t>::max();
617*4d7e907cSAndroid Build Coastguard Worker for (const auto& fr : supportedFormat.frameRates) {
618*4d7e907cSAndroid Build Coastguard Worker // 1000000000LL < (2^32 - 1) and
619*4d7e907cSAndroid Build Coastguard Worker // fr.durationNumerator is uint32_t, so no overflow here
620*4d7e907cSAndroid Build Coastguard Worker int64_t frameDuration = 1000000000LL * fr.durationNumerator /
621*4d7e907cSAndroid Build Coastguard Worker fr.durationDenominator;
622*4d7e907cSAndroid Build Coastguard Worker if (frameDuration < minFrameDuration) {
623*4d7e907cSAndroid Build Coastguard Worker minFrameDuration = frameDuration;
624*4d7e907cSAndroid Build Coastguard Worker }
625*4d7e907cSAndroid Build Coastguard Worker }
626*4d7e907cSAndroid Build Coastguard Worker
627*4d7e907cSAndroid Build Coastguard Worker for (const auto& format : halFormats) {
628*4d7e907cSAndroid Build Coastguard Worker minFrameDurations.push_back(format);
629*4d7e907cSAndroid Build Coastguard Worker minFrameDurations.push_back(supportedFormat.width);
630*4d7e907cSAndroid Build Coastguard Worker minFrameDurations.push_back(supportedFormat.height);
631*4d7e907cSAndroid Build Coastguard Worker minFrameDurations.push_back(minFrameDuration);
632*4d7e907cSAndroid Build Coastguard Worker }
633*4d7e907cSAndroid Build Coastguard Worker
634*4d7e907cSAndroid Build Coastguard Worker // The stall duration is 0 for non-jpeg formats. For JPEG format, stall
635*4d7e907cSAndroid Build Coastguard Worker // duration can be 0 if JPEG is small. Here we choose 1 sec for JPEG.
636*4d7e907cSAndroid Build Coastguard Worker // TODO: b/72261675. Maybe set this dynamically
637*4d7e907cSAndroid Build Coastguard Worker for (const auto& format : halFormats) {
638*4d7e907cSAndroid Build Coastguard Worker const int64_t NS_TO_SECOND = 1000000000;
639*4d7e907cSAndroid Build Coastguard Worker int64_t stall_duration =
640*4d7e907cSAndroid Build Coastguard Worker (format == HAL_PIXEL_FORMAT_BLOB) ? NS_TO_SECOND : 0;
641*4d7e907cSAndroid Build Coastguard Worker stallDurations.push_back(format);
642*4d7e907cSAndroid Build Coastguard Worker stallDurations.push_back(supportedFormat.width);
643*4d7e907cSAndroid Build Coastguard Worker stallDurations.push_back(supportedFormat.height);
644*4d7e907cSAndroid Build Coastguard Worker stallDurations.push_back(stall_duration);
645*4d7e907cSAndroid Build Coastguard Worker }
646*4d7e907cSAndroid Build Coastguard Worker }
647*4d7e907cSAndroid Build Coastguard Worker
648*4d7e907cSAndroid Build Coastguard Worker UPDATE(streamConfiguration, streamConfigurations.data(), streamConfigurations.size());
649*4d7e907cSAndroid Build Coastguard Worker
650*4d7e907cSAndroid Build Coastguard Worker UPDATE(minFrameDuration, minFrameDurations.data(), minFrameDurations.size());
651*4d7e907cSAndroid Build Coastguard Worker
652*4d7e907cSAndroid Build Coastguard Worker UPDATE(stallDuration, stallDurations.data(), stallDurations.size());
653*4d7e907cSAndroid Build Coastguard Worker
654*4d7e907cSAndroid Build Coastguard Worker return true;
655*4d7e907cSAndroid Build Coastguard Worker }
656*4d7e907cSAndroid Build Coastguard Worker
calculateMinFps(::android::hardware::camera::common::V1_0::helper::CameraMetadata * metadata)657*4d7e907cSAndroid Build Coastguard Worker bool ExternalCameraDevice::calculateMinFps(
658*4d7e907cSAndroid Build Coastguard Worker ::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) {
659*4d7e907cSAndroid Build Coastguard Worker std::set<int32_t> framerates;
660*4d7e907cSAndroid Build Coastguard Worker int32_t minFps = std::numeric_limits<int32_t>::max();
661*4d7e907cSAndroid Build Coastguard Worker
662*4d7e907cSAndroid Build Coastguard Worker for (const auto& supportedFormat : mSupportedFormats) {
663*4d7e907cSAndroid Build Coastguard Worker for (const auto& fr : supportedFormat.frameRates) {
664*4d7e907cSAndroid Build Coastguard Worker int32_t frameRateInt = static_cast<int32_t>(fr.getDouble());
665*4d7e907cSAndroid Build Coastguard Worker if (minFps > frameRateInt) {
666*4d7e907cSAndroid Build Coastguard Worker minFps = frameRateInt;
667*4d7e907cSAndroid Build Coastguard Worker }
668*4d7e907cSAndroid Build Coastguard Worker framerates.insert(frameRateInt);
669*4d7e907cSAndroid Build Coastguard Worker }
670*4d7e907cSAndroid Build Coastguard Worker }
671*4d7e907cSAndroid Build Coastguard Worker
672*4d7e907cSAndroid Build Coastguard Worker std::vector<int32_t> fpsRanges;
673*4d7e907cSAndroid Build Coastguard Worker // FPS ranges
674*4d7e907cSAndroid Build Coastguard Worker for (const auto& framerate : framerates) {
675*4d7e907cSAndroid Build Coastguard Worker // Empirical: webcams often have close to 2x fps error and cannot support fixed fps range
676*4d7e907cSAndroid Build Coastguard Worker fpsRanges.push_back(framerate / 2);
677*4d7e907cSAndroid Build Coastguard Worker fpsRanges.push_back(framerate);
678*4d7e907cSAndroid Build Coastguard Worker }
679*4d7e907cSAndroid Build Coastguard Worker minFps /= 2;
680*4d7e907cSAndroid Build Coastguard Worker int64_t maxFrameDuration = 1000000000LL / minFps;
681*4d7e907cSAndroid Build Coastguard Worker
682*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, fpsRanges.data(),
683*4d7e907cSAndroid Build Coastguard Worker fpsRanges.size());
684*4d7e907cSAndroid Build Coastguard Worker
685*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_SENSOR_INFO_MAX_FRAME_DURATION, &maxFrameDuration, 1);
686*4d7e907cSAndroid Build Coastguard Worker
687*4d7e907cSAndroid Build Coastguard Worker return true;
688*4d7e907cSAndroid Build Coastguard Worker }
689*4d7e907cSAndroid Build Coastguard Worker
initOutputCharsKeys(int fd,::android::hardware::camera::common::V1_0::helper::CameraMetadata * metadata)690*4d7e907cSAndroid Build Coastguard Worker status_t ExternalCameraDevice::initOutputCharsKeys(
691*4d7e907cSAndroid Build Coastguard Worker int fd, ::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) {
692*4d7e907cSAndroid Build Coastguard Worker initSupportedFormatsLocked(fd);
693*4d7e907cSAndroid Build Coastguard Worker if (mSupportedFormats.empty()) {
694*4d7e907cSAndroid Build Coastguard Worker ALOGE("%s: Init supported format list failed", __FUNCTION__);
695*4d7e907cSAndroid Build Coastguard Worker return UNKNOWN_ERROR;
696*4d7e907cSAndroid Build Coastguard Worker }
697*4d7e907cSAndroid Build Coastguard Worker
698*4d7e907cSAndroid Build Coastguard Worker bool hasDepth = false;
699*4d7e907cSAndroid Build Coastguard Worker bool hasColor = false;
700*4d7e907cSAndroid Build Coastguard Worker
701*4d7e907cSAndroid Build Coastguard Worker // For V4L2_PIX_FMT_Z16
702*4d7e907cSAndroid Build Coastguard Worker std::array<int, /*size*/ 1> halDepthFormats{{HAL_PIXEL_FORMAT_Y16}};
703*4d7e907cSAndroid Build Coastguard Worker // For V4L2_PIX_FMT_MJPEG
704*4d7e907cSAndroid Build Coastguard Worker std::array<int, /*size*/ 3> halFormats{{HAL_PIXEL_FORMAT_BLOB, HAL_PIXEL_FORMAT_YCbCr_420_888,
705*4d7e907cSAndroid Build Coastguard Worker HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED}};
706*4d7e907cSAndroid Build Coastguard Worker
707*4d7e907cSAndroid Build Coastguard Worker for (const auto& supportedFormat : mSupportedFormats) {
708*4d7e907cSAndroid Build Coastguard Worker switch (supportedFormat.fourcc) {
709*4d7e907cSAndroid Build Coastguard Worker case V4L2_PIX_FMT_Z16:
710*4d7e907cSAndroid Build Coastguard Worker hasDepth = true;
711*4d7e907cSAndroid Build Coastguard Worker break;
712*4d7e907cSAndroid Build Coastguard Worker case V4L2_PIX_FMT_MJPEG:
713*4d7e907cSAndroid Build Coastguard Worker hasColor = true;
714*4d7e907cSAndroid Build Coastguard Worker break;
715*4d7e907cSAndroid Build Coastguard Worker default:
716*4d7e907cSAndroid Build Coastguard Worker ALOGW("%s: format %c%c%c%c is not supported!", __FUNCTION__,
717*4d7e907cSAndroid Build Coastguard Worker supportedFormat.fourcc & 0xFF, (supportedFormat.fourcc >> 8) & 0xFF,
718*4d7e907cSAndroid Build Coastguard Worker (supportedFormat.fourcc >> 16) & 0xFF, (supportedFormat.fourcc >> 24) & 0xFF);
719*4d7e907cSAndroid Build Coastguard Worker }
720*4d7e907cSAndroid Build Coastguard Worker }
721*4d7e907cSAndroid Build Coastguard Worker
722*4d7e907cSAndroid Build Coastguard Worker if (hasDepth) {
723*4d7e907cSAndroid Build Coastguard Worker initOutputCharskeysByFormat(metadata, V4L2_PIX_FMT_Z16, halDepthFormats,
724*4d7e907cSAndroid Build Coastguard Worker ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS_OUTPUT,
725*4d7e907cSAndroid Build Coastguard Worker ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS,
726*4d7e907cSAndroid Build Coastguard Worker ANDROID_DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS,
727*4d7e907cSAndroid Build Coastguard Worker ANDROID_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS);
728*4d7e907cSAndroid Build Coastguard Worker }
729*4d7e907cSAndroid Build Coastguard Worker if (hasColor) {
730*4d7e907cSAndroid Build Coastguard Worker initOutputCharskeysByFormat(metadata, V4L2_PIX_FMT_MJPEG, halFormats,
731*4d7e907cSAndroid Build Coastguard Worker ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
732*4d7e907cSAndroid Build Coastguard Worker ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
733*4d7e907cSAndroid Build Coastguard Worker ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,
734*4d7e907cSAndroid Build Coastguard Worker ANDROID_SCALER_AVAILABLE_STALL_DURATIONS);
735*4d7e907cSAndroid Build Coastguard Worker }
736*4d7e907cSAndroid Build Coastguard Worker
737*4d7e907cSAndroid Build Coastguard Worker calculateMinFps(metadata);
738*4d7e907cSAndroid Build Coastguard Worker
739*4d7e907cSAndroid Build Coastguard Worker SupportedV4L2Format maximumFormat {.width = 0, .height = 0};
740*4d7e907cSAndroid Build Coastguard Worker for (const auto& supportedFormat : mSupportedFormats) {
741*4d7e907cSAndroid Build Coastguard Worker if (supportedFormat.width >= maximumFormat.width &&
742*4d7e907cSAndroid Build Coastguard Worker supportedFormat.height >= maximumFormat.height) {
743*4d7e907cSAndroid Build Coastguard Worker maximumFormat = supportedFormat;
744*4d7e907cSAndroid Build Coastguard Worker }
745*4d7e907cSAndroid Build Coastguard Worker }
746*4d7e907cSAndroid Build Coastguard Worker int32_t activeArraySize[] = {0, 0,
747*4d7e907cSAndroid Build Coastguard Worker static_cast<int32_t>(maximumFormat.width),
748*4d7e907cSAndroid Build Coastguard Worker static_cast<int32_t>(maximumFormat.height)};
749*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE,
750*4d7e907cSAndroid Build Coastguard Worker activeArraySize, ARRAY_SIZE(activeArraySize));
751*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE, activeArraySize,
752*4d7e907cSAndroid Build Coastguard Worker ARRAY_SIZE(activeArraySize));
753*4d7e907cSAndroid Build Coastguard Worker
754*4d7e907cSAndroid Build Coastguard Worker int32_t pixelArraySize[] = {static_cast<int32_t>(maximumFormat.width),
755*4d7e907cSAndroid Build Coastguard Worker static_cast<int32_t>(maximumFormat.height)};
756*4d7e907cSAndroid Build Coastguard Worker UPDATE(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE, pixelArraySize,
757*4d7e907cSAndroid Build Coastguard Worker ARRAY_SIZE(pixelArraySize));
758*4d7e907cSAndroid Build Coastguard Worker return OK;
759*4d7e907cSAndroid Build Coastguard Worker }
760*4d7e907cSAndroid Build Coastguard Worker
761*4d7e907cSAndroid Build Coastguard Worker #undef ARRAY_SIZE
762*4d7e907cSAndroid Build Coastguard Worker #undef UPDATE
763*4d7e907cSAndroid Build Coastguard Worker
getFrameRateList(int fd,double fpsUpperBound,SupportedV4L2Format * format)764*4d7e907cSAndroid Build Coastguard Worker void ExternalCameraDevice::getFrameRateList(
765*4d7e907cSAndroid Build Coastguard Worker int fd, double fpsUpperBound, SupportedV4L2Format* format) {
766*4d7e907cSAndroid Build Coastguard Worker format->frameRates.clear();
767*4d7e907cSAndroid Build Coastguard Worker
768*4d7e907cSAndroid Build Coastguard Worker v4l2_frmivalenum frameInterval{
769*4d7e907cSAndroid Build Coastguard Worker .index = 0,
770*4d7e907cSAndroid Build Coastguard Worker .pixel_format = format->fourcc,
771*4d7e907cSAndroid Build Coastguard Worker .width = format->width,
772*4d7e907cSAndroid Build Coastguard Worker .height = format->height,
773*4d7e907cSAndroid Build Coastguard Worker };
774*4d7e907cSAndroid Build Coastguard Worker
775*4d7e907cSAndroid Build Coastguard Worker for (frameInterval.index = 0;
776*4d7e907cSAndroid Build Coastguard Worker TEMP_FAILURE_RETRY(ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frameInterval)) == 0;
777*4d7e907cSAndroid Build Coastguard Worker ++frameInterval.index) {
778*4d7e907cSAndroid Build Coastguard Worker if (frameInterval.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
779*4d7e907cSAndroid Build Coastguard Worker if (frameInterval.discrete.numerator != 0) {
780*4d7e907cSAndroid Build Coastguard Worker SupportedV4L2Format::FrameRate fr = {
781*4d7e907cSAndroid Build Coastguard Worker frameInterval.discrete.numerator,
782*4d7e907cSAndroid Build Coastguard Worker frameInterval.discrete.denominator};
783*4d7e907cSAndroid Build Coastguard Worker double framerate = fr.getDouble();
784*4d7e907cSAndroid Build Coastguard Worker if (framerate > fpsUpperBound) {
785*4d7e907cSAndroid Build Coastguard Worker continue;
786*4d7e907cSAndroid Build Coastguard Worker }
787*4d7e907cSAndroid Build Coastguard Worker ALOGV("index:%d, format:%c%c%c%c, w %d, h %d, framerate %f",
788*4d7e907cSAndroid Build Coastguard Worker frameInterval.index,
789*4d7e907cSAndroid Build Coastguard Worker frameInterval.pixel_format & 0xFF,
790*4d7e907cSAndroid Build Coastguard Worker (frameInterval.pixel_format >> 8) & 0xFF,
791*4d7e907cSAndroid Build Coastguard Worker (frameInterval.pixel_format >> 16) & 0xFF,
792*4d7e907cSAndroid Build Coastguard Worker (frameInterval.pixel_format >> 24) & 0xFF,
793*4d7e907cSAndroid Build Coastguard Worker frameInterval.width, frameInterval.height, framerate);
794*4d7e907cSAndroid Build Coastguard Worker format->frameRates.push_back(fr);
795*4d7e907cSAndroid Build Coastguard Worker }
796*4d7e907cSAndroid Build Coastguard Worker }
797*4d7e907cSAndroid Build Coastguard Worker }
798*4d7e907cSAndroid Build Coastguard Worker
799*4d7e907cSAndroid Build Coastguard Worker if (format->frameRates.empty()) {
800*4d7e907cSAndroid Build Coastguard Worker ALOGE("%s: failed to get supported frame rates for format:%c%c%c%c w %d h %d",
801*4d7e907cSAndroid Build Coastguard Worker __FUNCTION__,
802*4d7e907cSAndroid Build Coastguard Worker frameInterval.pixel_format & 0xFF,
803*4d7e907cSAndroid Build Coastguard Worker (frameInterval.pixel_format >> 8) & 0xFF,
804*4d7e907cSAndroid Build Coastguard Worker (frameInterval.pixel_format >> 16) & 0xFF,
805*4d7e907cSAndroid Build Coastguard Worker (frameInterval.pixel_format >> 24) & 0xFF,
806*4d7e907cSAndroid Build Coastguard Worker frameInterval.width, frameInterval.height);
807*4d7e907cSAndroid Build Coastguard Worker }
808*4d7e907cSAndroid Build Coastguard Worker }
809*4d7e907cSAndroid Build Coastguard Worker
trimSupportedFormats(CroppingType cropType,std::vector<SupportedV4L2Format> * pFmts)810*4d7e907cSAndroid Build Coastguard Worker void ExternalCameraDevice::trimSupportedFormats(
811*4d7e907cSAndroid Build Coastguard Worker CroppingType cropType,
812*4d7e907cSAndroid Build Coastguard Worker /*inout*/std::vector<SupportedV4L2Format>* pFmts) {
813*4d7e907cSAndroid Build Coastguard Worker std::vector<SupportedV4L2Format>& sortedFmts = *pFmts;
814*4d7e907cSAndroid Build Coastguard Worker if (cropType == VERTICAL) {
815*4d7e907cSAndroid Build Coastguard Worker std::sort(sortedFmts.begin(), sortedFmts.end(),
816*4d7e907cSAndroid Build Coastguard Worker [](const SupportedV4L2Format& a, const SupportedV4L2Format& b) -> bool {
817*4d7e907cSAndroid Build Coastguard Worker if (a.width == b.width) {
818*4d7e907cSAndroid Build Coastguard Worker return a.height < b.height;
819*4d7e907cSAndroid Build Coastguard Worker }
820*4d7e907cSAndroid Build Coastguard Worker return a.width < b.width;
821*4d7e907cSAndroid Build Coastguard Worker });
822*4d7e907cSAndroid Build Coastguard Worker } else {
823*4d7e907cSAndroid Build Coastguard Worker std::sort(sortedFmts.begin(), sortedFmts.end(),
824*4d7e907cSAndroid Build Coastguard Worker [](const SupportedV4L2Format& a, const SupportedV4L2Format& b) -> bool {
825*4d7e907cSAndroid Build Coastguard Worker if (a.height == b.height) {
826*4d7e907cSAndroid Build Coastguard Worker return a.width < b.width;
827*4d7e907cSAndroid Build Coastguard Worker }
828*4d7e907cSAndroid Build Coastguard Worker return a.height < b.height;
829*4d7e907cSAndroid Build Coastguard Worker });
830*4d7e907cSAndroid Build Coastguard Worker }
831*4d7e907cSAndroid Build Coastguard Worker
832*4d7e907cSAndroid Build Coastguard Worker if (sortedFmts.size() == 0) {
833*4d7e907cSAndroid Build Coastguard Worker ALOGE("%s: input format list is empty!", __FUNCTION__);
834*4d7e907cSAndroid Build Coastguard Worker return;
835*4d7e907cSAndroid Build Coastguard Worker }
836*4d7e907cSAndroid Build Coastguard Worker
837*4d7e907cSAndroid Build Coastguard Worker const auto& maxSize = sortedFmts[sortedFmts.size() - 1];
838*4d7e907cSAndroid Build Coastguard Worker float maxSizeAr = ASPECT_RATIO(maxSize);
839*4d7e907cSAndroid Build Coastguard Worker
840*4d7e907cSAndroid Build Coastguard Worker // Remove formats that has aspect ratio not croppable from largest size
841*4d7e907cSAndroid Build Coastguard Worker std::vector<SupportedV4L2Format> out;
842*4d7e907cSAndroid Build Coastguard Worker for (const auto& fmt : sortedFmts) {
843*4d7e907cSAndroid Build Coastguard Worker float ar = ASPECT_RATIO(fmt);
844*4d7e907cSAndroid Build Coastguard Worker if (isAspectRatioClose(ar, maxSizeAr)) {
845*4d7e907cSAndroid Build Coastguard Worker out.push_back(fmt);
846*4d7e907cSAndroid Build Coastguard Worker } else if (cropType == HORIZONTAL && ar < maxSizeAr) {
847*4d7e907cSAndroid Build Coastguard Worker out.push_back(fmt);
848*4d7e907cSAndroid Build Coastguard Worker } else if (cropType == VERTICAL && ar > maxSizeAr) {
849*4d7e907cSAndroid Build Coastguard Worker out.push_back(fmt);
850*4d7e907cSAndroid Build Coastguard Worker } else {
851*4d7e907cSAndroid Build Coastguard Worker ALOGV("%s: size (%d,%d) is removed due to unable to crop %s from (%d,%d)",
852*4d7e907cSAndroid Build Coastguard Worker __FUNCTION__, fmt.width, fmt.height,
853*4d7e907cSAndroid Build Coastguard Worker cropType == VERTICAL ? "vertically" : "horizontally",
854*4d7e907cSAndroid Build Coastguard Worker maxSize.width, maxSize.height);
855*4d7e907cSAndroid Build Coastguard Worker }
856*4d7e907cSAndroid Build Coastguard Worker }
857*4d7e907cSAndroid Build Coastguard Worker sortedFmts = out;
858*4d7e907cSAndroid Build Coastguard Worker }
859*4d7e907cSAndroid Build Coastguard Worker
getCandidateSupportedFormatsLocked(int fd,CroppingType cropType,const std::vector<ExternalCameraConfig::FpsLimitation> & fpsLimits,const std::vector<ExternalCameraConfig::FpsLimitation> & depthFpsLimits,const Size & minStreamSize,bool depthEnabled)860*4d7e907cSAndroid Build Coastguard Worker std::vector<SupportedV4L2Format> ExternalCameraDevice::getCandidateSupportedFormatsLocked(
861*4d7e907cSAndroid Build Coastguard Worker int fd, CroppingType cropType,
862*4d7e907cSAndroid Build Coastguard Worker const std::vector<ExternalCameraConfig::FpsLimitation>& fpsLimits,
863*4d7e907cSAndroid Build Coastguard Worker const std::vector<ExternalCameraConfig::FpsLimitation>& depthFpsLimits,
864*4d7e907cSAndroid Build Coastguard Worker const Size& minStreamSize,
865*4d7e907cSAndroid Build Coastguard Worker bool depthEnabled) {
866*4d7e907cSAndroid Build Coastguard Worker std::vector<SupportedV4L2Format> outFmts;
867*4d7e907cSAndroid Build Coastguard Worker struct v4l2_fmtdesc fmtdesc {
868*4d7e907cSAndroid Build Coastguard Worker .index = 0,
869*4d7e907cSAndroid Build Coastguard Worker .type = V4L2_BUF_TYPE_VIDEO_CAPTURE};
870*4d7e907cSAndroid Build Coastguard Worker int ret = 0;
871*4d7e907cSAndroid Build Coastguard Worker while (ret == 0) {
872*4d7e907cSAndroid Build Coastguard Worker ret = TEMP_FAILURE_RETRY(ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc));
873*4d7e907cSAndroid Build Coastguard Worker ALOGV("index:%d,ret:%d, format:%c%c%c%c", fmtdesc.index, ret,
874*4d7e907cSAndroid Build Coastguard Worker fmtdesc.pixelformat & 0xFF,
875*4d7e907cSAndroid Build Coastguard Worker (fmtdesc.pixelformat >> 8) & 0xFF,
876*4d7e907cSAndroid Build Coastguard Worker (fmtdesc.pixelformat >> 16) & 0xFF,
877*4d7e907cSAndroid Build Coastguard Worker (fmtdesc.pixelformat >> 24) & 0xFF);
878*4d7e907cSAndroid Build Coastguard Worker if (ret == 0 && !(fmtdesc.flags & V4L2_FMT_FLAG_EMULATED)) {
879*4d7e907cSAndroid Build Coastguard Worker auto it = std::find (
880*4d7e907cSAndroid Build Coastguard Worker kSupportedFourCCs.begin(), kSupportedFourCCs.end(), fmtdesc.pixelformat);
881*4d7e907cSAndroid Build Coastguard Worker if (it != kSupportedFourCCs.end()) {
882*4d7e907cSAndroid Build Coastguard Worker // Found supported format
883*4d7e907cSAndroid Build Coastguard Worker v4l2_frmsizeenum frameSize {
884*4d7e907cSAndroid Build Coastguard Worker .index = 0,
885*4d7e907cSAndroid Build Coastguard Worker .pixel_format = fmtdesc.pixelformat};
886*4d7e907cSAndroid Build Coastguard Worker for (; TEMP_FAILURE_RETRY(ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frameSize)) == 0;
887*4d7e907cSAndroid Build Coastguard Worker ++frameSize.index) {
888*4d7e907cSAndroid Build Coastguard Worker if (frameSize.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
889*4d7e907cSAndroid Build Coastguard Worker ALOGV("index:%d, format:%c%c%c%c, w %d, h %d", frameSize.index,
890*4d7e907cSAndroid Build Coastguard Worker fmtdesc.pixelformat & 0xFF,
891*4d7e907cSAndroid Build Coastguard Worker (fmtdesc.pixelformat >> 8) & 0xFF,
892*4d7e907cSAndroid Build Coastguard Worker (fmtdesc.pixelformat >> 16) & 0xFF,
893*4d7e907cSAndroid Build Coastguard Worker (fmtdesc.pixelformat >> 24) & 0xFF,
894*4d7e907cSAndroid Build Coastguard Worker frameSize.discrete.width, frameSize.discrete.height);
895*4d7e907cSAndroid Build Coastguard Worker // Disregard h > w formats so all aspect ratio (h/w) <= 1.0
896*4d7e907cSAndroid Build Coastguard Worker // This will simplify the crop/scaling logic down the road
897*4d7e907cSAndroid Build Coastguard Worker if (frameSize.discrete.height > frameSize.discrete.width) {
898*4d7e907cSAndroid Build Coastguard Worker continue;
899*4d7e907cSAndroid Build Coastguard Worker }
900*4d7e907cSAndroid Build Coastguard Worker // Discard all formats which is smaller than minStreamSize
901*4d7e907cSAndroid Build Coastguard Worker if (frameSize.discrete.width < minStreamSize.width
902*4d7e907cSAndroid Build Coastguard Worker || frameSize.discrete.height < minStreamSize.height) {
903*4d7e907cSAndroid Build Coastguard Worker continue;
904*4d7e907cSAndroid Build Coastguard Worker }
905*4d7e907cSAndroid Build Coastguard Worker SupportedV4L2Format format {
906*4d7e907cSAndroid Build Coastguard Worker .width = frameSize.discrete.width,
907*4d7e907cSAndroid Build Coastguard Worker .height = frameSize.discrete.height,
908*4d7e907cSAndroid Build Coastguard Worker .fourcc = fmtdesc.pixelformat
909*4d7e907cSAndroid Build Coastguard Worker };
910*4d7e907cSAndroid Build Coastguard Worker
911*4d7e907cSAndroid Build Coastguard Worker if (format.fourcc == V4L2_PIX_FMT_Z16 && depthEnabled) {
912*4d7e907cSAndroid Build Coastguard Worker updateFpsBounds(fd, cropType, depthFpsLimits, format, outFmts);
913*4d7e907cSAndroid Build Coastguard Worker } else {
914*4d7e907cSAndroid Build Coastguard Worker updateFpsBounds(fd, cropType, fpsLimits, format, outFmts);
915*4d7e907cSAndroid Build Coastguard Worker }
916*4d7e907cSAndroid Build Coastguard Worker }
917*4d7e907cSAndroid Build Coastguard Worker }
918*4d7e907cSAndroid Build Coastguard Worker }
919*4d7e907cSAndroid Build Coastguard Worker }
920*4d7e907cSAndroid Build Coastguard Worker fmtdesc.index++;
921*4d7e907cSAndroid Build Coastguard Worker }
922*4d7e907cSAndroid Build Coastguard Worker trimSupportedFormats(cropType, &outFmts);
923*4d7e907cSAndroid Build Coastguard Worker return outFmts;
924*4d7e907cSAndroid Build Coastguard Worker }
925*4d7e907cSAndroid Build Coastguard Worker
updateFpsBounds(int fd,CroppingType cropType,const std::vector<ExternalCameraConfig::FpsLimitation> & fpsLimits,SupportedV4L2Format format,std::vector<SupportedV4L2Format> & outFmts)926*4d7e907cSAndroid Build Coastguard Worker void ExternalCameraDevice::updateFpsBounds(
927*4d7e907cSAndroid Build Coastguard Worker int fd, CroppingType cropType,
928*4d7e907cSAndroid Build Coastguard Worker const std::vector<ExternalCameraConfig::FpsLimitation>& fpsLimits, SupportedV4L2Format format,
929*4d7e907cSAndroid Build Coastguard Worker std::vector<SupportedV4L2Format>& outFmts) {
930*4d7e907cSAndroid Build Coastguard Worker double fpsUpperBound = -1.0;
931*4d7e907cSAndroid Build Coastguard Worker for (const auto& limit : fpsLimits) {
932*4d7e907cSAndroid Build Coastguard Worker if (cropType == VERTICAL) {
933*4d7e907cSAndroid Build Coastguard Worker if (format.width <= limit.size.width) {
934*4d7e907cSAndroid Build Coastguard Worker fpsUpperBound = limit.fpsUpperBound;
935*4d7e907cSAndroid Build Coastguard Worker break;
936*4d7e907cSAndroid Build Coastguard Worker }
937*4d7e907cSAndroid Build Coastguard Worker } else { // HORIZONTAL
938*4d7e907cSAndroid Build Coastguard Worker if (format.height <= limit.size.height) {
939*4d7e907cSAndroid Build Coastguard Worker fpsUpperBound = limit.fpsUpperBound;
940*4d7e907cSAndroid Build Coastguard Worker break;
941*4d7e907cSAndroid Build Coastguard Worker }
942*4d7e907cSAndroid Build Coastguard Worker }
943*4d7e907cSAndroid Build Coastguard Worker }
944*4d7e907cSAndroid Build Coastguard Worker if (fpsUpperBound < 0.f) {
945*4d7e907cSAndroid Build Coastguard Worker return;
946*4d7e907cSAndroid Build Coastguard Worker }
947*4d7e907cSAndroid Build Coastguard Worker
948*4d7e907cSAndroid Build Coastguard Worker getFrameRateList(fd, fpsUpperBound, &format);
949*4d7e907cSAndroid Build Coastguard Worker if (!format.frameRates.empty()) {
950*4d7e907cSAndroid Build Coastguard Worker outFmts.push_back(format);
951*4d7e907cSAndroid Build Coastguard Worker }
952*4d7e907cSAndroid Build Coastguard Worker }
953*4d7e907cSAndroid Build Coastguard Worker
initSupportedFormatsLocked(int fd)954*4d7e907cSAndroid Build Coastguard Worker void ExternalCameraDevice::initSupportedFormatsLocked(int fd) {
955*4d7e907cSAndroid Build Coastguard Worker std::vector<SupportedV4L2Format> horizontalFmts = getCandidateSupportedFormatsLocked(
956*4d7e907cSAndroid Build Coastguard Worker fd, HORIZONTAL, mCfg.fpsLimits, mCfg.depthFpsLimits, mCfg.minStreamSize, mCfg.depthEnabled);
957*4d7e907cSAndroid Build Coastguard Worker std::vector<SupportedV4L2Format> verticalFmts = getCandidateSupportedFormatsLocked(
958*4d7e907cSAndroid Build Coastguard Worker fd, VERTICAL, mCfg.fpsLimits, mCfg.depthFpsLimits, mCfg.minStreamSize, mCfg.depthEnabled);
959*4d7e907cSAndroid Build Coastguard Worker
960*4d7e907cSAndroid Build Coastguard Worker size_t horiSize = horizontalFmts.size();
961*4d7e907cSAndroid Build Coastguard Worker size_t vertSize = verticalFmts.size();
962*4d7e907cSAndroid Build Coastguard Worker
963*4d7e907cSAndroid Build Coastguard Worker if (horiSize == 0 && vertSize == 0) {
964*4d7e907cSAndroid Build Coastguard Worker ALOGE("%s: cannot find suitable cropping type!", __FUNCTION__);
965*4d7e907cSAndroid Build Coastguard Worker return;
966*4d7e907cSAndroid Build Coastguard Worker }
967*4d7e907cSAndroid Build Coastguard Worker
968*4d7e907cSAndroid Build Coastguard Worker if (horiSize == 0) {
969*4d7e907cSAndroid Build Coastguard Worker mSupportedFormats = verticalFmts;
970*4d7e907cSAndroid Build Coastguard Worker mCroppingType = VERTICAL;
971*4d7e907cSAndroid Build Coastguard Worker return;
972*4d7e907cSAndroid Build Coastguard Worker } else if (vertSize == 0) {
973*4d7e907cSAndroid Build Coastguard Worker mSupportedFormats = horizontalFmts;
974*4d7e907cSAndroid Build Coastguard Worker mCroppingType = HORIZONTAL;
975*4d7e907cSAndroid Build Coastguard Worker return;
976*4d7e907cSAndroid Build Coastguard Worker }
977*4d7e907cSAndroid Build Coastguard Worker
978*4d7e907cSAndroid Build Coastguard Worker const auto& maxHoriSize = horizontalFmts[horizontalFmts.size() - 1];
979*4d7e907cSAndroid Build Coastguard Worker const auto& maxVertSize = verticalFmts[verticalFmts.size() - 1];
980*4d7e907cSAndroid Build Coastguard Worker
981*4d7e907cSAndroid Build Coastguard Worker // Try to keep largest possible output size
982*4d7e907cSAndroid Build Coastguard Worker // When they are the same or ambiguous, pick the one support more sizes
983*4d7e907cSAndroid Build Coastguard Worker if (maxHoriSize.width == maxVertSize.width &&
984*4d7e907cSAndroid Build Coastguard Worker maxHoriSize.height == maxVertSize.height) {
985*4d7e907cSAndroid Build Coastguard Worker if (horiSize > vertSize) {
986*4d7e907cSAndroid Build Coastguard Worker mSupportedFormats = horizontalFmts;
987*4d7e907cSAndroid Build Coastguard Worker mCroppingType = HORIZONTAL;
988*4d7e907cSAndroid Build Coastguard Worker } else {
989*4d7e907cSAndroid Build Coastguard Worker mSupportedFormats = verticalFmts;
990*4d7e907cSAndroid Build Coastguard Worker mCroppingType = VERTICAL;
991*4d7e907cSAndroid Build Coastguard Worker }
992*4d7e907cSAndroid Build Coastguard Worker } else if (maxHoriSize.width >= maxVertSize.width &&
993*4d7e907cSAndroid Build Coastguard Worker maxHoriSize.height >= maxVertSize.height) {
994*4d7e907cSAndroid Build Coastguard Worker mSupportedFormats = horizontalFmts;
995*4d7e907cSAndroid Build Coastguard Worker mCroppingType = HORIZONTAL;
996*4d7e907cSAndroid Build Coastguard Worker } else if (maxHoriSize.width <= maxVertSize.width &&
997*4d7e907cSAndroid Build Coastguard Worker maxHoriSize.height <= maxVertSize.height) {
998*4d7e907cSAndroid Build Coastguard Worker mSupportedFormats = verticalFmts;
999*4d7e907cSAndroid Build Coastguard Worker mCroppingType = VERTICAL;
1000*4d7e907cSAndroid Build Coastguard Worker } else {
1001*4d7e907cSAndroid Build Coastguard Worker if (horiSize > vertSize) {
1002*4d7e907cSAndroid Build Coastguard Worker mSupportedFormats = horizontalFmts;
1003*4d7e907cSAndroid Build Coastguard Worker mCroppingType = HORIZONTAL;
1004*4d7e907cSAndroid Build Coastguard Worker } else {
1005*4d7e907cSAndroid Build Coastguard Worker mSupportedFormats = verticalFmts;
1006*4d7e907cSAndroid Build Coastguard Worker mCroppingType = VERTICAL;
1007*4d7e907cSAndroid Build Coastguard Worker }
1008*4d7e907cSAndroid Build Coastguard Worker }
1009*4d7e907cSAndroid Build Coastguard Worker }
1010*4d7e907cSAndroid Build Coastguard Worker
createSession(const sp<ICameraDeviceCallback> & cb,const ExternalCameraConfig & cfg,const std::vector<SupportedV4L2Format> & sortedFormats,const CroppingType & croppingType,const common::V1_0::helper::CameraMetadata & chars,const std::string & cameraId,unique_fd v4l2Fd)1011*4d7e907cSAndroid Build Coastguard Worker sp<ExternalCameraDeviceSession> ExternalCameraDevice::createSession(
1012*4d7e907cSAndroid Build Coastguard Worker const sp<ICameraDeviceCallback>& cb,
1013*4d7e907cSAndroid Build Coastguard Worker const ExternalCameraConfig& cfg,
1014*4d7e907cSAndroid Build Coastguard Worker const std::vector<SupportedV4L2Format>& sortedFormats,
1015*4d7e907cSAndroid Build Coastguard Worker const CroppingType& croppingType,
1016*4d7e907cSAndroid Build Coastguard Worker const common::V1_0::helper::CameraMetadata& chars,
1017*4d7e907cSAndroid Build Coastguard Worker const std::string& cameraId,
1018*4d7e907cSAndroid Build Coastguard Worker unique_fd v4l2Fd) {
1019*4d7e907cSAndroid Build Coastguard Worker return new ExternalCameraDeviceSession(
1020*4d7e907cSAndroid Build Coastguard Worker cb, cfg, sortedFormats, croppingType, chars, cameraId, std::move(v4l2Fd));
1021*4d7e907cSAndroid Build Coastguard Worker }
1022*4d7e907cSAndroid Build Coastguard Worker
1023*4d7e907cSAndroid Build Coastguard Worker } // namespace implementation
1024*4d7e907cSAndroid Build Coastguard Worker } // namespace V3_4
1025*4d7e907cSAndroid Build Coastguard Worker } // namespace device
1026*4d7e907cSAndroid Build Coastguard Worker } // namespace camera
1027*4d7e907cSAndroid Build Coastguard Worker } // namespace hardware
1028*4d7e907cSAndroid Build Coastguard Worker } // namespace android
1029*4d7e907cSAndroid Build Coastguard Worker
1030