| 1 | // Copyright (C) 2016 The Qt Company Ltd. | 
| 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only | 
| 3 |  | 
| 4 | #include "qplatformcamera_p.h" | 
| 5 | #include "private/qcameradevice_p.h" | 
| 6 |  | 
| 7 | QT_BEGIN_NAMESPACE | 
| 8 |  | 
| 9 | QPlatformCamera::QPlatformCamera(QCamera *parent) : QPlatformVideoSource(parent), m_camera(parent) | 
| 10 | { | 
| 11 |     qRegisterMetaType<QVideoFrame>(); | 
| 12 | } | 
| 13 |  | 
| 14 | QCameraFormat QPlatformCamera::findBestCameraFormat(const QCameraDevice &camera) const | 
| 15 | { | 
| 16 |     // check if fmt is better. We try to find the highest resolution that offers | 
| 17 |     // at least 30 FPS | 
| 18 |     // we use 29 FPS to compare against as some cameras report 29.97 FPS... | 
| 19 |  | 
| 20 |     auto makeCriteria = [this](const QCameraFormat &fmt) { | 
| 21 |         constexpr float MinSufficientFrameRate = 29.f; | 
| 22 |  | 
| 23 |         const auto isValid = fmt.pixelFormat() != QVideoFrameFormat::Format_Invalid; | 
| 24 |         const auto resolution = fmt.resolution(); | 
| 25 |         const auto sufficientFrameRate = std::min(a: fmt.maxFrameRate(), b: MinSufficientFrameRate); | 
| 26 |         const auto pixelFormatScore = | 
| 27 |                 cameraPixelFormatScore(fmt.pixelFormat(), QCameraFormatPrivate::getColorRange(format: fmt)); | 
| 28 |  | 
| 29 |         return std::make_tuple( | 
| 30 |                 args: isValid, // 1st: ensure valid formats | 
| 31 |                 args: sufficientFrameRate, // 2nd: ensure the highest frame rate in the range [0; 29]*/ | 
| 32 |                 args: resolution.width() * resolution.height(), // 3rd: ensure the highest resolution | 
| 33 |                 args: pixelFormatScore, // 4th: eshure the best pixel format | 
| 34 |                 args: fmt.maxFrameRate()); // 5th: ensure the highest framerate in the whole range | 
| 35 |     }; | 
| 36 |  | 
| 37 |     const auto formats = camera.videoFormats(); | 
| 38 |     const auto found = | 
| 39 |             std::max_element(first: formats.begin(), last: formats.end(), | 
| 40 |                              comp: [makeCriteria](const QCameraFormat &fmtA, const QCameraFormat &fmtB) { | 
| 41 |                                  return makeCriteria(fmtA) < makeCriteria(fmtB); | 
| 42 |                              }); | 
| 43 |  | 
| 44 |     return found == formats.end() ? QCameraFormat{} : *found; | 
| 45 | } | 
| 46 |  | 
| 47 | QVideoFrameFormat QPlatformCamera::frameFormat() const | 
| 48 | { | 
| 49 |     QVideoFrameFormat result(m_cameraFormat.resolution(), | 
| 50 |                              m_framePixelFormat == QVideoFrameFormat::Format_Invalid | 
| 51 |                                      ? m_cameraFormat.pixelFormat() | 
| 52 |                                      : m_framePixelFormat); | 
| 53 |     result.setStreamFrameRate(m_cameraFormat.maxFrameRate()); | 
| 54 |     return result; | 
| 55 | } | 
| 56 |  | 
| 57 | void QPlatformCamera::supportedFeaturesChanged(QCamera::Features f) | 
| 58 | { | 
| 59 |     if (m_supportedFeatures == f) | 
| 60 |         return; | 
| 61 |     m_supportedFeatures = f; | 
| 62 |     emit m_camera->supportedFeaturesChanged(); | 
| 63 | } | 
| 64 |  | 
| 65 | void QPlatformCamera::minimumZoomFactorChanged(float factor) | 
| 66 | { | 
| 67 |     if (m_minZoom == factor) | 
| 68 |         return; | 
| 69 |     m_minZoom = factor; | 
| 70 |     emit m_camera->minimumZoomFactorChanged(factor); | 
| 71 | } | 
| 72 |  | 
| 73 | void QPlatformCamera::maximumZoomFactorChanged(float factor) | 
| 74 | { | 
| 75 |     if (m_maxZoom == factor) | 
| 76 |         return; | 
| 77 |     m_maxZoom = factor; | 
| 78 |     emit m_camera->maximumZoomFactorChanged(factor); | 
| 79 | } | 
| 80 |  | 
| 81 | void QPlatformCamera::focusModeChanged(QCamera::FocusMode mode) | 
| 82 | { | 
| 83 |     if (m_focusMode == mode) | 
| 84 |         return; | 
| 85 |     m_focusMode = mode; | 
| 86 |     emit m_camera->focusModeChanged(); | 
| 87 | } | 
| 88 |  | 
| 89 | void QPlatformCamera::customFocusPointChanged(const QPointF &point) | 
| 90 | { | 
| 91 |     if (m_customFocusPoint == point) | 
| 92 |         return; | 
| 93 |     m_customFocusPoint = point; | 
| 94 |     emit m_camera->customFocusPointChanged(); | 
| 95 | } | 
| 96 |  | 
| 97 |  | 
| 98 | void QPlatformCamera::zoomFactorChanged(float zoom) | 
| 99 | { | 
| 100 |     if (m_zoomFactor == zoom) | 
| 101 |         return; | 
| 102 |     m_zoomFactor = zoom; | 
| 103 |     emit m_camera->zoomFactorChanged(zoom); | 
| 104 | } | 
| 105 |  | 
| 106 |  | 
| 107 | void QPlatformCamera::focusDistanceChanged(float d) | 
| 108 | { | 
| 109 |     if (m_focusDistance == d) | 
| 110 |         return; | 
| 111 |     m_focusDistance = d; | 
| 112 |     emit m_camera->focusDistanceChanged(m_focusDistance); | 
| 113 | } | 
| 114 |  | 
| 115 |  | 
| 116 | void QPlatformCamera::flashReadyChanged(bool ready) | 
| 117 | { | 
| 118 |     if (m_flashReady == ready) | 
| 119 |         return; | 
| 120 |     m_flashReady = ready; | 
| 121 |     emit m_camera->flashReady(m_flashReady); | 
| 122 | } | 
| 123 |  | 
| 124 | void QPlatformCamera::flashModeChanged(QCamera::FlashMode mode) | 
| 125 | { | 
| 126 |     if (m_flashMode == mode) | 
| 127 |         return; | 
| 128 |     m_flashMode = mode; | 
| 129 |     emit m_camera->flashModeChanged(); | 
| 130 | } | 
| 131 |  | 
| 132 | void QPlatformCamera::torchModeChanged(QCamera::TorchMode mode) | 
| 133 | { | 
| 134 |     if (m_torchMode == mode) | 
| 135 |         return; | 
| 136 |     m_torchMode = mode; | 
| 137 |     emit m_camera->torchModeChanged(); | 
| 138 | } | 
| 139 |  | 
| 140 | void QPlatformCamera::exposureModeChanged(QCamera::ExposureMode mode) | 
| 141 | { | 
| 142 |     if (m_exposureMode == mode) | 
| 143 |         return; | 
| 144 |     m_exposureMode = mode; | 
| 145 |     emit m_camera->exposureModeChanged(); | 
| 146 | } | 
| 147 |  | 
| 148 | void QPlatformCamera::exposureCompensationChanged(float compensation) | 
| 149 | { | 
| 150 |     if (m_exposureCompensation == compensation) | 
| 151 |         return; | 
| 152 |     m_exposureCompensation = compensation; | 
| 153 |     emit m_camera->exposureCompensationChanged(compensation); | 
| 154 | } | 
| 155 |  | 
| 156 | void QPlatformCamera::exposureCompensationRangeChanged(float min, float max) | 
| 157 | { | 
| 158 |     if (m_minExposureCompensation == min && m_maxExposureCompensation == max) | 
| 159 |         return; | 
| 160 |     m_minExposureCompensation = min; | 
| 161 |     m_maxExposureCompensation = max; | 
| 162 |     // tell frontend | 
| 163 | } | 
| 164 |  | 
| 165 | void QPlatformCamera::isoSensitivityChanged(int iso) | 
| 166 | { | 
| 167 |     if (m_iso == iso) | 
| 168 |         return; | 
| 169 |     m_iso = iso; | 
| 170 |     emit m_camera->isoSensitivityChanged(iso); | 
| 171 | } | 
| 172 |  | 
| 173 | void QPlatformCamera::exposureTimeChanged(float speed) | 
| 174 | { | 
| 175 |     if (m_exposureTime == speed) | 
| 176 |         return; | 
| 177 |     m_exposureTime = speed; | 
| 178 |     emit m_camera->exposureTimeChanged(speed); | 
| 179 | } | 
| 180 |  | 
| 181 | void QPlatformCamera::whiteBalanceModeChanged(QCamera::WhiteBalanceMode mode) | 
| 182 | { | 
| 183 |     if (m_whiteBalance == mode) | 
| 184 |         return; | 
| 185 |     m_whiteBalance = mode; | 
| 186 |     emit m_camera->whiteBalanceModeChanged(); | 
| 187 | } | 
| 188 |  | 
| 189 | void QPlatformCamera::colorTemperatureChanged(int temperature) | 
| 190 | { | 
| 191 |     Q_ASSERT(temperature >= 0); | 
| 192 |     Q_ASSERT((temperature > 0 && whiteBalanceMode() == QCamera::WhiteBalanceManual) || | 
| 193 |              (temperature == 0 && whiteBalanceMode() == QCamera::WhiteBalanceAuto)); | 
| 194 |     if (m_colorTemperature == temperature) | 
| 195 |         return; | 
| 196 |     m_colorTemperature = temperature; | 
| 197 |     emit m_camera->colorTemperatureChanged(); | 
| 198 | } | 
| 199 |  | 
| 200 | int QPlatformCamera::colorTemperatureForWhiteBalance(QCamera::WhiteBalanceMode mode) | 
| 201 | { | 
| 202 |     switch (mode) { | 
| 203 |     case QCamera::WhiteBalanceAuto: | 
| 204 |         break; | 
| 205 |     case QCamera::WhiteBalanceManual: | 
| 206 |     case QCamera::WhiteBalanceSunlight: | 
| 207 |         return 5600; | 
| 208 |     case QCamera::WhiteBalanceCloudy: | 
| 209 |         return 6000; | 
| 210 |     case QCamera::WhiteBalanceShade: | 
| 211 |         return 7000; | 
| 212 |     case QCamera::WhiteBalanceTungsten: | 
| 213 |         return 3200; | 
| 214 |     case QCamera::WhiteBalanceFluorescent: | 
| 215 |         return 4000; | 
| 216 |     case QCamera::WhiteBalanceFlash: | 
| 217 |         return 5500; | 
| 218 |     case QCamera::WhiteBalanceSunset: | 
| 219 |         return 3000; | 
| 220 |     } | 
| 221 |     return 0; | 
| 222 | } | 
| 223 |  | 
| 224 | void QPlatformCamera::updateError(QCamera::Error error, const QString &errorString) | 
| 225 | { | 
| 226 |     QMetaObject::invokeMethod(object: this, function: [this, error, errorString]() { | 
| 227 |         m_error.setAndNotify(code: error, description: errorString, notifier&: *this); | 
| 228 |     }); | 
| 229 | } | 
| 230 |  | 
| 231 | QT_END_NAMESPACE | 
| 232 |  | 
| 233 | #include "moc_qplatformcamera_p.cpp" | 
| 234 |  |