11#include <private/qvideoframe_p.h>
14#include <qstringlist.h>
16#include <QtCore/qthread.h>
17#include <QtCore/qreadwritelock.h>
18#include <QtCore/qmutex.h>
19#include <QtMultimedia/private/qmemoryvideobuffer_p.h>
20#include <QtCore/qcoreapplication.h>
31Q_GLOBAL_STATIC(CameraMap, cameras)
32Q_GLOBAL_STATIC(QReadWriteLock, rwLock)
34static QRect areaToRect(jobject areaObj)
36 QJniObject area(areaObj);
37 QJniObject rect = area.getObjectField(
"rect",
"Landroid/graphics/Rect;");
39 return QRect(rect.getField<jint>(
"left"),
40 rect.getField<jint>(
"top"),
41 rect.callMethod<jint>(
"width"),
42 rect.callMethod<jint>(
"height"));
45static QJniObject rectToArea(
const QRect &rect)
47 QJniObject jrect(
"android/graphics/Rect",
49 rect.left(), rect.top(), rect.right(), rect.bottom());
51 QJniObject area(
"android/hardware/Camera$Area",
52 "(Landroid/graphics/Rect;I)V",
59static void notifyAutoFocusComplete(JNIEnv* , jobject,
int id, jboolean success)
61 QReadLocker locker(rwLock);
62 const auto it = cameras->constFind(id);
63 if (Q_UNLIKELY(it == cameras->cend()))
66 Q_EMIT (*it)->autoFocusComplete(success);
69static void notifyPictureExposed(JNIEnv* , jobject,
int id)
71 QReadLocker locker(rwLock);
72 const auto it = cameras->constFind(id);
73 if (Q_UNLIKELY(it == cameras->cend()))
76 Q_EMIT (*it)->pictureExposed();
79static void notifyPictureCaptured(JNIEnv *env, jobject,
int id, jbyteArray data)
81 QReadLocker locker(rwLock);
82 const auto it = cameras->constFind(id);
83 if (Q_UNLIKELY(it == cameras->cend())) {
84 qCWarning(lcAndroidCamera) <<
"Could not obtain camera!";
88 AndroidCamera *camera = (*it);
90 const int arrayLength = env->GetArrayLength(data);
91 QByteArray bytes(arrayLength, Qt::Uninitialized);
92 env->GetByteArrayRegion(data, 0, arrayLength,
reinterpret_cast<jbyte *>(bytes.data()));
94 auto parameters = camera->getParametersObject();
97 parameters.callObjectMethod(
"getPictureSize",
"()Landroid/hardware/Camera$Size;");
99 if (!size.isValid()) {
100 qCWarning(lcAndroidCamera) <<
"Picture Size is not valid!";
104 QSize pictureSize(size.getField<jint>(
"width"), size.getField<jint>(
"height"));
106 auto format = AndroidCamera::ImageFormat(parameters.callMethod<jint>(
"getPictureFormat"));
108 if (format == AndroidCamera::ImageFormat::UnknownImageFormat) {
109 qCWarning(lcAndroidCamera) <<
"Android Camera Image Format is UnknownImageFormat!";
113 int bytesPerLine = 0;
116 case AndroidCamera::ImageFormat::YV12:
117 bytesPerLine = (pictureSize.width() + 15) & ~15;
119 case AndroidCamera::ImageFormat::NV21:
120 bytesPerLine = pictureSize.width();
122 case AndroidCamera::ImageFormat::RGB565:
123 case AndroidCamera::ImageFormat::YUY2:
124 bytesPerLine = pictureSize.width() * 2;
130 auto pictureFormat = qt_pixelFormatFromAndroidImageFormat(format);
132 emit camera->pictureCaptured(bytes, pictureFormat, pictureSize, bytesPerLine);
135static void notifyNewPreviewFrame(JNIEnv *env, jobject,
int id, jbyteArray data,
136 int width,
int height,
int format,
int bpl)
138 QReadLocker locker(rwLock);
139 const auto it = cameras->constFind(id);
140 if (Q_UNLIKELY(it == cameras->cend()))
143 const int arrayLength = env->GetArrayLength(data);
144 if (arrayLength == 0)
147 QByteArray bytes(arrayLength, Qt::Uninitialized);
148 env->GetByteArrayRegion(data, 0, arrayLength, (jbyte*)bytes.data());
150 QVideoFrameFormat frameFormat(
151 QSize(width, height),
152 qt_pixelFormatFromAndroidImageFormat(AndroidCamera::ImageFormat(format)));
154 QVideoFrame frame = QVideoFramePrivate::createFrame(
155 std::make_unique<QMemoryVideoBuffer>(std::move(bytes), bpl), std::move(frameFormat));
157 Q_EMIT (*it)->newPreviewFrame(frame);
160static void notifyFrameAvailable(JNIEnv *, jobject,
int id)
162 QReadLocker locker(rwLock);
163 const auto it = cameras->constFind(id);
164 if (Q_UNLIKELY(it == cameras->cend()))
167 (*it)->fetchLastPreviewFrame();
170class AndroidCameraPrivate :
public QObject
174 AndroidCameraPrivate();
175 ~AndroidCameraPrivate();
177 Q_INVOKABLE
bool init(
int cameraId);
179 Q_INVOKABLE
void release();
180 Q_INVOKABLE
bool lock();
181 Q_INVOKABLE
bool unlock();
182 Q_INVOKABLE
bool reconnect();
184 Q_INVOKABLE AndroidCamera::CameraFacing getFacing();
185 Q_INVOKABLE
int getNativeOrientation();
187 Q_INVOKABLE QSize getPreferredPreviewSizeForVideo();
188 Q_INVOKABLE QList<QSize> getSupportedPreviewSizes();
189 static QList<QSize> getSupportedPreviewSizes(QJniObject ¶meters);
191 Q_INVOKABLE QList<AndroidCamera::FpsRange> getSupportedPreviewFpsRange();
193 Q_INVOKABLE AndroidCamera::FpsRange getPreviewFpsRange();
194 static AndroidCamera::FpsRange getPreviewFpsRange(QJniObject ¶meters);
195 Q_INVOKABLE
void setPreviewFpsRange(
int min,
int max);
197 Q_INVOKABLE AndroidCamera::ImageFormat getPreviewFormat();
198 Q_INVOKABLE
void setPreviewFormat(AndroidCamera::ImageFormat fmt);
199 Q_INVOKABLE QList<AndroidCamera::ImageFormat> getSupportedPreviewFormats();
200 static QList<AndroidCamera::ImageFormat> getSupportedPreviewFormats(QJniObject ¶meters);
202 Q_INVOKABLE QSize previewSize()
const {
return m_previewSize; }
203 Q_INVOKABLE QSize getPreviewSize();
204 Q_INVOKABLE
void updatePreviewSize();
205 Q_INVOKABLE
bool setPreviewTexture(
void *surfaceTexture);
206 Q_INVOKABLE
bool setPreviewDisplay(
void *surfaceHolder);
207 Q_INVOKABLE
void setDisplayOrientation(
int degrees);
209 Q_INVOKABLE
bool isZoomSupported();
210 Q_INVOKABLE
int getMaxZoom();
211 Q_INVOKABLE QList<
int> getZoomRatios();
212 Q_INVOKABLE
int getZoom();
213 Q_INVOKABLE
void setZoom(
int value);
215 Q_INVOKABLE QString getFlashMode();
216 Q_INVOKABLE
void setFlashMode(
const QString &value);
218 Q_INVOKABLE QString getFocusMode();
219 Q_INVOKABLE
void setFocusMode(
const QString &value);
221 Q_INVOKABLE
int getMaxNumFocusAreas();
222 Q_INVOKABLE QList<QRect> getFocusAreas();
223 Q_INVOKABLE
void setFocusAreas(
const QList<QRect> &areas);
225 Q_INVOKABLE
void autoFocus();
226 Q_INVOKABLE
void cancelAutoFocus();
228 Q_INVOKABLE
bool isAutoExposureLockSupported();
229 Q_INVOKABLE
bool getAutoExposureLock();
230 Q_INVOKABLE
void setAutoExposureLock(
bool toggle);
232 Q_INVOKABLE
bool isAutoWhiteBalanceLockSupported();
233 Q_INVOKABLE
bool getAutoWhiteBalanceLock();
234 Q_INVOKABLE
void setAutoWhiteBalanceLock(
bool toggle);
236 Q_INVOKABLE
int getExposureCompensation();
237 Q_INVOKABLE
void setExposureCompensation(
int value);
238 Q_INVOKABLE
float getExposureCompensationStep();
239 Q_INVOKABLE
int getMinExposureCompensation();
240 Q_INVOKABLE
int getMaxExposureCompensation();
242 Q_INVOKABLE QString getSceneMode();
243 Q_INVOKABLE
void setSceneMode(
const QString &value);
245 Q_INVOKABLE QString getWhiteBalance();
246 Q_INVOKABLE
void setWhiteBalance(
const QString &value);
248 Q_INVOKABLE
void updateRotation();
250 Q_INVOKABLE QList<QSize> getSupportedPictureSizes();
251 Q_INVOKABLE QList<QSize> getSupportedVideoSizes();
252 Q_INVOKABLE
void setPictureSize(
const QSize &size);
253 Q_INVOKABLE
void setJpegQuality(
int quality);
255 Q_INVOKABLE
void startPreview();
256 Q_INVOKABLE
void stopPreview();
258 Q_INVOKABLE
void takePicture();
260 Q_INVOKABLE
void setupPreviewFrameCallback();
261 Q_INVOKABLE
void notifyNewFrames(
bool notify);
262 Q_INVOKABLE
void fetchLastPreviewFrame();
264 Q_INVOKABLE
void applyParameters();
266 Q_INVOKABLE QStringList callParametersStringListMethod(
const QByteArray &methodName);
269 QRecursiveMutex m_parametersMutex;
273 QJniObject m_parameters;
275 QJniObject m_cameraListener;
278 void previewSizeChanged();
279 void previewStarted();
280 void previewFailedToStart();
281 void previewStopped();
283 void autoFocusStarted();
285 void whiteBalanceChanged();
287 void takePictureFailed();
289 void lastPreviewFrameFetched(
const QVideoFrame &frame);
292AndroidCamera::AndroidCamera(AndroidCameraPrivate *d, QThread *worker)
298 connect(d, &AndroidCameraPrivate::previewSizeChanged,
this, &AndroidCamera::previewSizeChanged);
299 connect(d, &AndroidCameraPrivate::previewStarted,
this, &AndroidCamera::previewStarted);
300 connect(d, &AndroidCameraPrivate::previewFailedToStart,
this, &AndroidCamera::previewFailedToStart);
301 connect(d, &AndroidCameraPrivate::previewStopped,
this, &AndroidCamera::previewStopped);
302 connect(d, &AndroidCameraPrivate::autoFocusStarted,
this, &AndroidCamera::autoFocusStarted);
303 connect(d, &AndroidCameraPrivate::whiteBalanceChanged,
this, &AndroidCamera::whiteBalanceChanged);
304 connect(d, &AndroidCameraPrivate::takePictureFailed,
this, &AndroidCamera::takePictureFailed);
305 connect(d, &AndroidCameraPrivate::lastPreviewFrameFetched,
this, &AndroidCamera::lastPreviewFrameFetched);
311 if (d->m_camera.isValid()) {
313 QWriteLocker locker(rwLock);
314 cameras->remove(cameraId());
318 m_worker->wait(5000);
326 AndroidCameraPrivate *d =
new AndroidCameraPrivate();
327 QThread *worker =
new QThread;
329 d->moveToThread(worker);
330 connect(worker, &QThread::finished, d, &AndroidCameraPrivate::deleteLater);
332 QMetaObject::invokeMethod(d,
"init", Qt::BlockingQueuedConnection, Q_RETURN_ARG(
bool, ok), Q_ARG(
int, cameraId));
341 QWriteLocker locker(rwLock);
342 cameras->insert(cameraId, q);
349 Q_D(
const AndroidCamera);
350 return d->m_cameraId;
357 QMetaObject::invokeMethod(d,
"lock", Qt::BlockingQueuedConnection, Q_RETURN_ARG(
bool, ok));
365 QMetaObject::invokeMethod(d,
"unlock", Qt::BlockingQueuedConnection, Q_RETURN_ARG(
bool, ok));
373 QMetaObject::invokeMethod(d,
"reconnect", Qt::BlockingQueuedConnection, Q_RETURN_ARG(
bool, ok));
380 QMetaObject::invokeMethod(d,
"release", Qt::BlockingQueuedConnection);
386 return d->getFacing();
392 return d->getNativeOrientation();
398 return d->getPreferredPreviewSizeForVideo();
404 return d->getSupportedPreviewSizes();
410 return d->getSupportedPreviewFpsRange();
416 return d->getPreviewFpsRange();
422 QMetaObject::invokeMethod(d,
"setPreviewFpsRange", Q_ARG(
int, range.min), Q_ARG(
int, range.max));
428 return d->getPreviewFormat();
434 QMetaObject::invokeMethod(d,
"setPreviewFormat", Q_ARG(AndroidCamera::ImageFormat, fmt));
440 return d->getSupportedPreviewFormats();
445 Q_D(
const AndroidCamera);
446 return d->m_previewSize;
452 return d->getPreviewSize();
458 d->m_parametersMutex.lock();
459 bool areParametersValid = d->m_parameters.isValid();
460 d->m_parametersMutex.unlock();
461 if (!areParametersValid)
464 d->m_previewSize = size;
465 QMetaObject::invokeMethod(d,
"updatePreviewSize");
472 QMetaObject::invokeMethod(d,
474 Qt::BlockingQueuedConnection,
475 Q_RETURN_ARG(
bool, ok),
476 Q_ARG(
void *, surfaceTexture ? surfaceTexture->surfaceTexture() : 0));
484 QMetaObject::invokeMethod(d,
486 Qt::BlockingQueuedConnection,
487 Q_RETURN_ARG(
bool, ok),
488 Q_ARG(
void *, surfaceHolder ? surfaceHolder->surfaceHolder() : 0));
495 QMetaObject::invokeMethod(d,
"setDisplayOrientation", Qt::QueuedConnection, Q_ARG(
int, degrees));
501 return d->isZoomSupported();
507 return d->getMaxZoom();
513 return d->getZoomRatios();
525 QMetaObject::invokeMethod(d,
"setZoom", Q_ARG(
int, value));
531 return d->callParametersStringListMethod(
"getSupportedFlashModes");
537 return d->getFlashMode();
543 QMetaObject::invokeMethod(d,
"setFlashMode", Q_ARG(QString, value));
549 return d->callParametersStringListMethod(
"getSupportedFocusModes");
555 return d->getFocusMode();
561 QMetaObject::invokeMethod(d,
"setFocusMode", Q_ARG(QString, value));
567 return d->getMaxNumFocusAreas();
573 return d->getFocusAreas();
579 QMetaObject::invokeMethod(d,
"setFocusAreas", Q_ARG(QList<QRect>, areas));
585 QMetaObject::invokeMethod(d,
"autoFocus");
591 QMetaObject::invokeMethod(d,
"cancelAutoFocus", Qt::QueuedConnection);
597 return d->isAutoExposureLockSupported();
603 return d->getAutoExposureLock();
609 QMetaObject::invokeMethod(d,
"setAutoExposureLock", Q_ARG(
bool, toggle));
615 return d->isAutoWhiteBalanceLockSupported();
621 return d->getAutoWhiteBalanceLock();
627 QMetaObject::invokeMethod(d,
"setAutoWhiteBalanceLock", Q_ARG(
bool, toggle));
633 return d->getExposureCompensation();
639 QMetaObject::invokeMethod(d,
"setExposureCompensation", Q_ARG(
int, value));
645 return d->getExposureCompensationStep();
651 return d->getMinExposureCompensation();
657 return d->getMaxExposureCompensation();
663 return d->callParametersStringListMethod(
"getSupportedSceneModes");
669 return d->getSceneMode();
675 QMetaObject::invokeMethod(d,
"setSceneMode", Q_ARG(QString, value));
681 return d->callParametersStringListMethod(
"getSupportedWhiteBalance");
687 return d->getWhiteBalance();
693 QMetaObject::invokeMethod(d,
"setWhiteBalance", Q_ARG(QString, value));
700 d->m_parametersMutex.lock();
701 bool areParametersValid = d->m_parameters.isValid();
702 d->m_parametersMutex.unlock();
703 if (!areParametersValid)
706 d->m_rotation = rotation;
707 QMetaObject::invokeMethod(d,
"updateRotation");
712 Q_D(
const AndroidCamera);
713 return d->m_rotation;
719 return d->getSupportedPictureSizes();
725 return d->getSupportedVideoSizes();
731 QMetaObject::invokeMethod(d,
"setPictureSize", Q_ARG(QSize, size));
737 QMetaObject::invokeMethod(d,
"setJpegQuality", Q_ARG(
int, quality));
743 QMetaObject::invokeMethod(d,
"takePicture", Qt::BlockingQueuedConnection);
749 QMetaObject::invokeMethod(d,
"setupPreviewFrameCallback");
755 QMetaObject::invokeMethod(d,
"notifyNewFrames", Q_ARG(
bool, notify));
761 QMetaObject::invokeMethod(d,
"fetchLastPreviewFrame");
775 return QJniObject::callStaticMethod<jint>(
"android/hardware/Camera",
776 "getNumberOfCameras");
783 QJniObject cameraInfo(
"android/hardware/Camera$CameraInfo");
784 QJniObject::callStaticMethod<
void>(
"android/hardware/Camera",
786 "(ILandroid/hardware/Camera$CameraInfo;)V",
787 id, cameraInfo.object());
789 AndroidCamera::CameraFacing facing = AndroidCamera::CameraFacing(cameraInfo.getField<jint>(
"facing"));
791 info->orientation = (360 - cameraInfo.getField<jint>(
"orientation")) % 360;
794 case AndroidCamera::CameraFacingBack:
795 info->id = QByteArray(
"back");
796 info->description = QStringLiteral(
"Rear-facing camera");
797 info->position = QCameraDevice::BackFace;
798 info->isDefault =
true;
800 case AndroidCamera::CameraFacingFront:
801 info->id = QByteArray(
"front");
802 info->description = QStringLiteral(
"Front-facing camera");
803 info->position = QCameraDevice::FrontFace;
811 info->id.append(QByteArray::number(id));
812 info->description.append(QStringLiteral(
" %1").arg(id));
816QVideoFrameFormat::PixelFormat
AndroidCamera::QtPixelFormatFromAndroidImageFormat(AndroidCamera::ImageFormat format)
819 case AndroidCamera::NV21:
820 return QVideoFrameFormat::Format_NV21;
821 case AndroidCamera::YUY2:
822 return QVideoFrameFormat::Format_YUYV;
823 case AndroidCamera::JPEG:
824 return QVideoFrameFormat::Format_Jpeg;
825 case AndroidCamera::YV12:
826 return QVideoFrameFormat::Format_YV12;
828 return QVideoFrameFormat::Format_Invalid;
832AndroidCamera::ImageFormat
AndroidCamera::AndroidImageFormatFromQtPixelFormat(QVideoFrameFormat::PixelFormat format)
835 case QVideoFrameFormat::Format_NV21:
836 return AndroidCamera::NV21;
837 case QVideoFrameFormat::Format_YUYV:
838 return AndroidCamera::YUY2;
839 case QVideoFrameFormat::Format_Jpeg:
840 return AndroidCamera::JPEG;
841 case QVideoFrameFormat::Format_YV12:
842 return AndroidCamera::YV12;
844 return AndroidCamera::UnknownImageFormat;
850 QList<QCameraFormat> formats;
851 AndroidCamera::FpsRange range = getPreviewFpsRange();
852 for (
const auto &previewSize : getSupportedVideoSizes()) {
853 for (
const auto &previewFormat : getSupportedPreviewFormats()) {
854 QCameraFormatPrivate * format =
new QCameraFormatPrivate();
855 format->pixelFormat = QtPixelFormatFromAndroidImageFormat(previewFormat);
856 format->resolution = previewSize;
857 format->minFrameRate = range.min;
858 format->maxFrameRate = range.max;
859 formats.append(format->create());
869 QMetaObject::invokeMethod(d,
"startPreview");
875 QMetaObject::invokeMethod(d,
"stopPreview");
881 QMetaObject::invokeMethod(d,
"stopPreview", Qt::BlockingQueuedConnection);
887 return d->m_parameters;
890AndroidCameraPrivate::AndroidCameraPrivate()
895AndroidCameraPrivate::~AndroidCameraPrivate()
901bool AndroidCameraPrivate::init(
int cameraId)
903 m_cameraId = cameraId;
906 const bool opened = s_activeCameras & (1 << cameraId);
910 m_camera = QJniObject::callStaticObjectMethod(
"android/hardware/Camera",
912 "(I)Landroid/hardware/Camera;",
914 if (!m_camera.isValid())
917 m_cameraListener = QJniObject(QtCameraListenerClassName,
"(I)V", m_cameraId);
918 m_info = QJniObject(
"android/hardware/Camera$CameraInfo");
919 m_camera.callStaticMethod<
void>(
"android/hardware/Camera",
921 "(ILandroid/hardware/Camera$CameraInfo;)V",
925 QJniObject params = m_camera.callObjectMethod(
"getParameters",
926 "()Landroid/hardware/Camera$Parameters;");
927 m_parameters = QJniObject(params);
928 s_activeCameras |= 1 << cameraId;
933void AndroidCameraPrivate::release()
935 m_previewSize = QSize();
936 m_parametersMutex.lock();
937 m_parameters = QJniObject();
938 m_parametersMutex.unlock();
939 if (m_camera.isValid()) {
940 m_camera.callMethod<
void>(
"release");
941 s_activeCameras &= ~(1 << m_cameraId);
945bool AndroidCameraPrivate::lock()
948 auto methodId = env->GetMethodID(m_camera.objectClass(),
"lock",
"()V");
949 env->CallVoidMethod(m_camera.object(), methodId);
951 if (env.checkAndClearExceptions())
956bool AndroidCameraPrivate::unlock()
959 auto methodId = env->GetMethodID(m_camera.objectClass(),
"unlock",
"()V");
960 env->CallVoidMethod(m_camera.object(), methodId);
962 if (env.checkAndClearExceptions())
967bool AndroidCameraPrivate::reconnect()
970 auto methodId = env->GetMethodID(m_camera.objectClass(),
"reconnect",
"()V");
971 env->CallVoidMethod(m_camera.object(), methodId);
973 if (env.checkAndClearExceptions())
978AndroidCamera::CameraFacing AndroidCameraPrivate::getFacing()
980 return AndroidCamera::CameraFacing(m_info.getField<jint>(
"facing"));
983int AndroidCameraPrivate::getNativeOrientation()
985 return m_info.getField<jint>(
"orientation");
988QSize AndroidCameraPrivate::getPreferredPreviewSizeForVideo()
990 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
992 if (!m_parameters.isValid())
995 QJniObject size = m_parameters.callObjectMethod(
"getPreferredPreviewSizeForVideo",
996 "()Landroid/hardware/Camera$Size;");
1001 return QSize(size.getField<jint>(
"width"), size.getField<jint>(
"height"));
1004QList<QSize> AndroidCameraPrivate::getSupportedPreviewSizes()
1006 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1007 return getSupportedPreviewSizes(m_parameters);
1010QList<QSize> AndroidCameraPrivate::getSupportedPreviewSizes(QJniObject ¶meters)
1014 if (parameters.isValid()) {
1015 QJniObject sizeList = parameters.callObjectMethod(
"getSupportedPreviewSizes",
1016 "()Ljava/util/List;");
1017 int count = sizeList.callMethod<jint>(
"size");
1018 for (
int i = 0; i < count; ++i) {
1019 QJniObject size = sizeList.callObjectMethod(
"get",
1020 "(I)Ljava/lang/Object;",
1022 list.append(QSize(size.getField<jint>(
"width"), size.getField<jint>(
"height")));
1025 std::sort(list.begin(), list.end(), qt_sizeLessThan);
1031QList<AndroidCamera::FpsRange> AndroidCameraPrivate::getSupportedPreviewFpsRange()
1033 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1035 QJniEnvironment env;
1037 QList<AndroidCamera::FpsRange> rangeList;
1039 if (m_parameters.isValid()) {
1040 QJniObject rangeListNative = m_parameters.callObjectMethod(
"getSupportedPreviewFpsRange",
1041 "()Ljava/util/List;");
1042 int count = rangeListNative.callMethod<jint>(
"size");
1044 rangeList.reserve(count);
1046 for (
int i = 0; i < count; ++i) {
1047 QJniObject range = rangeListNative.callObjectMethod(
"get",
1048 "(I)Ljava/lang/Object;",
1051 jintArray jRange =
static_cast<jintArray>(range.object());
1052 jint* rangeArray = env->GetIntArrayElements(jRange, 0);
1054 AndroidCamera::FpsRange fpsRange;
1056 fpsRange.min = rangeArray[0];
1057 fpsRange.max = rangeArray[1];
1059 env->ReleaseIntArrayElements(jRange, rangeArray, 0);
1061 rangeList << fpsRange;
1068AndroidCamera::FpsRange AndroidCameraPrivate::getPreviewFpsRange()
1070 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1071 return getPreviewFpsRange(m_parameters);
1074AndroidCamera::FpsRange AndroidCameraPrivate::getPreviewFpsRange(QJniObject ¶meters)
1076 QJniEnvironment env;
1078 AndroidCamera::FpsRange range;
1080 if (!parameters.isValid())
1083 jintArray jRangeArray = env->NewIntArray(2);
1084 parameters.callMethod<
void>(
"getPreviewFpsRange",
"([I)V", jRangeArray);
1086 jint* jRangeElements = env->GetIntArrayElements(jRangeArray, 0);
1090 range.min = jRangeElements[0] / 1000;
1091 range.max = jRangeElements[1] / 1000;
1093 env->ReleaseIntArrayElements(jRangeArray, jRangeElements, 0);
1094 env->DeleteLocalRef(jRangeArray);
1099void AndroidCameraPrivate::setPreviewFpsRange(
int min,
int max)
1101 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1103 if (!m_parameters.isValid())
1108 m_parameters.callMethod<
void>(
"setPreviewFpsRange",
"(II)V", min * 1000, max * 1000);
1111AndroidCamera::ImageFormat AndroidCameraPrivate::getPreviewFormat()
1113 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1115 if (!m_parameters.isValid())
1116 return AndroidCamera::UnknownImageFormat;
1118 return AndroidCamera::ImageFormat(m_parameters.callMethod<jint>(
"getPreviewFormat"));
1121void AndroidCameraPrivate::setPreviewFormat(AndroidCamera::ImageFormat fmt)
1123 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1125 if (!m_parameters.isValid())
1128 m_parameters.callMethod<
void>(
"setPreviewFormat",
"(I)V", jint(fmt));
1132QList<AndroidCamera::ImageFormat> AndroidCameraPrivate::getSupportedPreviewFormats()
1134 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1135 return getSupportedPreviewFormats(m_parameters);
1138QList<AndroidCamera::ImageFormat> AndroidCameraPrivate::getSupportedPreviewFormats(QJniObject ¶meters)
1140 QList<AndroidCamera::ImageFormat> list;
1142 if (parameters.isValid()) {
1143 QJniObject formatList = parameters.callObjectMethod(
"getSupportedPreviewFormats",
1144 "()Ljava/util/List;");
1145 int count = formatList.callMethod<jint>(
"size");
1146 for (
int i = 0; i < count; ++i) {
1147 QJniObject format = formatList.callObjectMethod(
"get",
1148 "(I)Ljava/lang/Object;",
1150 list.append(AndroidCamera::ImageFormat(format.callMethod<jint>(
"intValue")));
1157QSize AndroidCameraPrivate::getPreviewSize()
1159 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1161 if (!m_parameters.isValid())
1164 QJniObject size = m_parameters.callObjectMethod(
"getPreviewSize",
1165 "()Landroid/hardware/Camera$Size;");
1167 if (!size.isValid())
1170 return QSize(size.getField<jint>(
"width"), size.getField<jint>(
"height"));
1173void AndroidCameraPrivate::updatePreviewSize()
1175 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1177 if (m_previewSize.isValid()) {
1178 m_parameters.callMethod<
void>(
"setPreviewSize",
"(II)V", m_previewSize.width(), m_previewSize.height());
1182 emit previewSizeChanged();
1185bool AndroidCameraPrivate::setPreviewTexture(
void *surfaceTexture)
1187 QJniEnvironment env;
1188 auto methodId = env->GetMethodID(m_camera.objectClass(),
"setPreviewTexture",
1189 "(Landroid/graphics/SurfaceTexture;)V");
1190 env->CallVoidMethod(m_camera.object(), methodId,
static_cast<jobject>(surfaceTexture));
1192 if (env.checkAndClearExceptions())
1197bool AndroidCameraPrivate::setPreviewDisplay(
void *surfaceHolder)
1199 QJniEnvironment env;
1200 auto methodId = env->GetMethodID(m_camera.objectClass(),
"setPreviewDisplay",
1201 "(Landroid/view/SurfaceHolder;)V");
1202 env->CallVoidMethod(m_camera.object(), methodId,
static_cast<jobject>(surfaceHolder));
1204 if (env.checkAndClearExceptions())
1209void AndroidCameraPrivate::setDisplayOrientation(
int degrees)
1211 m_camera.callMethod<
void>(
"setDisplayOrientation",
"(I)V", degrees);
1212 m_cameraListener.callMethod<
void>(
"setPhotoRotation",
"(I)V", degrees);
1215bool AndroidCameraPrivate::isZoomSupported()
1217 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1219 if (!m_parameters.isValid())
1222 return m_parameters.callMethod<jboolean>(
"isZoomSupported");
1225int AndroidCameraPrivate::getMaxZoom()
1227 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1229 if (!m_parameters.isValid())
1232 return m_parameters.callMethod<jint>(
"getMaxZoom");
1235QList<
int> AndroidCameraPrivate::getZoomRatios()
1237 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1241 if (m_parameters.isValid()) {
1242 QJniObject ratioList = m_parameters.callObjectMethod(
"getZoomRatios",
1243 "()Ljava/util/List;");
1244 int count = ratioList.callMethod<jint>(
"size");
1245 for (
int i = 0; i < count; ++i) {
1246 QJniObject zoomRatio = ratioList.callObjectMethod(
"get",
1247 "(I)Ljava/lang/Object;",
1250 ratios.append(zoomRatio.callMethod<jint>(
"intValue"));
1257int AndroidCameraPrivate::getZoom()
1259 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1261 if (!m_parameters.isValid())
1264 return m_parameters.callMethod<jint>(
"getZoom");
1267void AndroidCameraPrivate::setZoom(
int value)
1269 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1271 if (!m_parameters.isValid())
1274 m_parameters.callMethod<
void>(
"setZoom",
"(I)V", value);
1278QString AndroidCameraPrivate::getFlashMode()
1280 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1284 if (m_parameters.isValid()) {
1285 QJniObject flashMode = m_parameters.callObjectMethod(
"getFlashMode",
1286 "()Ljava/lang/String;");
1287 if (flashMode.isValid())
1288 value = flashMode.toString();
1294void AndroidCameraPrivate::setFlashMode(
const QString &value)
1296 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1298 if (!m_parameters.isValid())
1301 m_parameters.callMethod<
void>(
"setFlashMode",
1302 "(Ljava/lang/String;)V",
1303 QJniObject::fromString(value).object());
1307QString AndroidCameraPrivate::getFocusMode()
1309 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1313 if (m_parameters.isValid()) {
1314 QJniObject focusMode = m_parameters.callObjectMethod(
"getFocusMode",
1315 "()Ljava/lang/String;");
1316 if (focusMode.isValid())
1317 value = focusMode.toString();
1323void AndroidCameraPrivate::setFocusMode(
const QString &value)
1325 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1327 if (!m_parameters.isValid())
1330 m_parameters.callMethod<
void>(
"setFocusMode",
1331 "(Ljava/lang/String;)V",
1332 QJniObject::fromString(value).object());
1336int AndroidCameraPrivate::getMaxNumFocusAreas()
1338 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1340 if (!m_parameters.isValid())
1343 return m_parameters.callMethod<jint>(
"getMaxNumFocusAreas");
1346QList<QRect> AndroidCameraPrivate::getFocusAreas()
1349 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1351 if (m_parameters.isValid()) {
1352 QJniObject list = m_parameters.callObjectMethod(
"getFocusAreas",
1353 "()Ljava/util/List;");
1355 if (list.isValid()) {
1356 int count = list.callMethod<jint>(
"size");
1357 for (
int i = 0; i < count; ++i) {
1358 QJniObject area = list.callObjectMethod(
"get",
1359 "(I)Ljava/lang/Object;",
1362 areas.append(areaToRect(area.object()));
1370void AndroidCameraPrivate::setFocusAreas(
const QList<QRect> &areas)
1372 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1374 if (!m_parameters.isValid() || areas.isEmpty())
1379 if (!areas.isEmpty()) {
1380 QJniEnvironment env;
1381 QJniObject arrayList(
"java/util/ArrayList",
"(I)V", areas.size());
1382 for (
int i = 0; i < areas.size(); ++i) {
1383 arrayList.callMethod<jboolean>(
"add",
1384 "(Ljava/lang/Object;)Z",
1385 rectToArea(areas.at(i)).object());
1390 m_parameters.callMethod<
void>(
"setFocusAreas",
"(Ljava/util/List;)V", list.object());
1395void AndroidCameraPrivate::autoFocus()
1397 QJniEnvironment env;
1398 auto methodId = env->GetMethodID(m_camera.objectClass(),
"autoFocus",
1399 "(Landroid/hardware/Camera$AutoFocusCallback;)V");
1400 env->CallVoidMethod(m_camera.object(), methodId, m_cameraListener.object());
1402 if (!env.checkAndClearExceptions())
1403 emit autoFocusStarted();
1406void AndroidCameraPrivate::cancelAutoFocus()
1408 QJniEnvironment env;
1409 m_camera.callMethod<
void>(
"cancelAutoFocus");
1412bool AndroidCameraPrivate::isAutoExposureLockSupported()
1414 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1416 if (!m_parameters.isValid())
1419 return m_parameters.callMethod<jboolean>(
"isAutoExposureLockSupported");
1422bool AndroidCameraPrivate::getAutoExposureLock()
1424 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1426 if (!m_parameters.isValid())
1429 return m_parameters.callMethod<jboolean>(
"getAutoExposureLock");
1432void AndroidCameraPrivate::setAutoExposureLock(
bool toggle)
1434 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1436 if (!m_parameters.isValid())
1439 m_parameters.callMethod<
void>(
"setAutoExposureLock",
"(Z)V", toggle);
1443bool AndroidCameraPrivate::isAutoWhiteBalanceLockSupported()
1445 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1447 if (!m_parameters.isValid())
1450 return m_parameters.callMethod<jboolean>(
"isAutoWhiteBalanceLockSupported");
1453bool AndroidCameraPrivate::getAutoWhiteBalanceLock()
1455 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1457 if (!m_parameters.isValid())
1460 return m_parameters.callMethod<jboolean>(
"getAutoWhiteBalanceLock");
1463void AndroidCameraPrivate::setAutoWhiteBalanceLock(
bool toggle)
1465 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1467 if (!m_parameters.isValid())
1470 m_parameters.callMethod<
void>(
"setAutoWhiteBalanceLock",
"(Z)V", toggle);
1474int AndroidCameraPrivate::getExposureCompensation()
1476 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1478 if (!m_parameters.isValid())
1481 return m_parameters.callMethod<jint>(
"getExposureCompensation");
1484void AndroidCameraPrivate::setExposureCompensation(
int value)
1486 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1488 if (!m_parameters.isValid())
1491 m_parameters.callMethod<
void>(
"setExposureCompensation",
"(I)V", value);
1495float AndroidCameraPrivate::getExposureCompensationStep()
1497 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1499 if (!m_parameters.isValid())
1502 return m_parameters.callMethod<jfloat>(
"getExposureCompensationStep");
1505int AndroidCameraPrivate::getMinExposureCompensation()
1507 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1509 if (!m_parameters.isValid())
1512 return m_parameters.callMethod<jint>(
"getMinExposureCompensation");
1515int AndroidCameraPrivate::getMaxExposureCompensation()
1517 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1519 if (!m_parameters.isValid())
1522 return m_parameters.callMethod<jint>(
"getMaxExposureCompensation");
1525QString AndroidCameraPrivate::getSceneMode()
1527 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1531 if (m_parameters.isValid()) {
1532 QJniObject sceneMode = m_parameters.callObjectMethod(
"getSceneMode",
1533 "()Ljava/lang/String;");
1534 if (sceneMode.isValid())
1535 value = sceneMode.toString();
1541void AndroidCameraPrivate::setSceneMode(
const QString &value)
1543 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1545 if (!m_parameters.isValid())
1548 m_parameters.callMethod<
void>(
"setSceneMode",
1549 "(Ljava/lang/String;)V",
1550 QJniObject::fromString(value).object());
1554QString AndroidCameraPrivate::getWhiteBalance()
1556 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1560 if (m_parameters.isValid()) {
1561 QJniObject wb = m_parameters.callObjectMethod(
"getWhiteBalance",
1562 "()Ljava/lang/String;");
1564 value = wb.toString();
1570void AndroidCameraPrivate::setWhiteBalance(
const QString &value)
1572 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1574 if (!m_parameters.isValid())
1577 m_parameters.callMethod<
void>(
"setWhiteBalance",
1578 "(Ljava/lang/String;)V",
1579 QJniObject::fromString(value).object());
1582 emit whiteBalanceChanged();
1585void AndroidCameraPrivate::updateRotation()
1587 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1589 m_parameters.callMethod<
void>(
"setRotation",
"(I)V", m_rotation);
1593QList<QSize> AndroidCameraPrivate::getSupportedPictureSizes()
1595 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1599 if (m_parameters.isValid()) {
1600 QJniObject sizeList = m_parameters.callObjectMethod(
"getSupportedPictureSizes",
1601 "()Ljava/util/List;");
1602 int count = sizeList.callMethod<jint>(
"size");
1603 for (
int i = 0; i < count; ++i) {
1604 QJniObject size = sizeList.callObjectMethod(
"get",
1605 "(I)Ljava/lang/Object;",
1607 list.append(QSize(size.getField<jint>(
"width"), size.getField<jint>(
"height")));
1610 std::sort(list.begin(), list.end(), qt_sizeLessThan);
1616QList<QSize> AndroidCameraPrivate::getSupportedVideoSizes()
1618 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1621 if (m_parameters.isValid()) {
1622 QJniObject sizeList = m_parameters.callObjectMethod(
"getSupportedVideoSizes",
1623 "()Ljava/util/List;");
1624 if (!sizeList.isValid())
1627 int count = sizeList.callMethod<jint>(
"size");
1628 for (
int i = 0; i < count; ++i) {
1629 const QJniObject size = sizeList.callObjectMethod(
"get",
"(I)Ljava/lang/Object;", i);
1631 list.append(QSize(size.getField<jint>(
"width"), size.getField<jint>(
"height")));
1633 std::sort(list.begin(), list.end(), qt_sizeLessThan);
1639void AndroidCameraPrivate::setPictureSize(
const QSize &size)
1641 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1643 if (!m_parameters.isValid())
1646 m_parameters.callMethod<
void>(
"setPictureSize",
"(II)V", size.width(), size.height());
1650void AndroidCameraPrivate::setJpegQuality(
int quality)
1652 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1654 if (!m_parameters.isValid())
1657 m_parameters.callMethod<
void>(
"setJpegQuality",
"(I)V", quality);
1661void AndroidCameraPrivate::startPreview()
1663 setupPreviewFrameCallback();
1665 QJniEnvironment env;
1666 auto methodId = env->GetMethodID(m_camera.objectClass(),
"startPreview",
"()V");
1667 env->CallVoidMethod(m_camera.object(), methodId);
1669 if (env.checkAndClearExceptions())
1670 emit previewFailedToStart();
1672 emit previewStarted();
1675void AndroidCameraPrivate::stopPreview()
1678 m_cameraListener.callMethod<
void>(
"notifyWhenFrameAvailable",
"(Z)V",
false);
1679 m_camera.callMethod<
void>(
"stopPreview");
1680 emit previewStopped();
1683void AndroidCameraPrivate::takePicture()
1688 m_cameraListener.callMethod<
void>(
"clearPreviewCallback",
"(Landroid/hardware/Camera;)V", m_camera.object());
1690 QJniEnvironment env;
1691 auto methodId = env->GetMethodID(m_camera.objectClass(),
"takePicture",
1692 "(Landroid/hardware/Camera$ShutterCallback;"
1693 "Landroid/hardware/Camera$PictureCallback;"
1694 "Landroid/hardware/Camera$PictureCallback;)V");
1695 env->CallVoidMethod(m_camera.object(), methodId, m_cameraListener.object(),
1696 jobject(0), m_cameraListener.object());
1698 if (env.checkAndClearExceptions())
1699 emit takePictureFailed();
1702void AndroidCameraPrivate::setupPreviewFrameCallback()
1704 m_cameraListener.callMethod<
void>(
"setupPreviewCallback",
"(Landroid/hardware/Camera;)V", m_camera.object());
1707void AndroidCameraPrivate::notifyNewFrames(
bool notify)
1709 m_cameraListener.callMethod<
void>(
"notifyNewFrames",
"(Z)V", notify);
1712void AndroidCameraPrivate::fetchLastPreviewFrame()
1714 QJniEnvironment env;
1715 QJniObject data = m_cameraListener.callObjectMethod(
"lastPreviewBuffer",
"()[B");
1717 if (!data.isValid()) {
1719 m_cameraListener.callMethod<
void>(
"notifyWhenFrameAvailable",
"(Z)V",
true);
1723 const int arrayLength = env->GetArrayLength(
static_cast<jbyteArray>(data.object()));
1724 if (arrayLength == 0)
1727 QByteArray bytes(arrayLength, Qt::Uninitialized);
1728 env->GetByteArrayRegion(
static_cast<jbyteArray>(data.object()),
1731 reinterpret_cast<jbyte *>(bytes.data()));
1733 const int width = m_cameraListener.callMethod<jint>(
"previewWidth");
1734 const int height = m_cameraListener.callMethod<jint>(
"previewHeight");
1735 const int format = m_cameraListener.callMethod<jint>(
"previewFormat");
1736 const int bpl = m_cameraListener.callMethod<jint>(
"previewBytesPerLine");
1738 QVideoFrameFormat frameFormat(
1739 QSize(width, height),
1740 qt_pixelFormatFromAndroidImageFormat(AndroidCamera::ImageFormat(format)));
1742 QVideoFrame frame = QVideoFramePrivate::createFrame(
1743 std::make_unique<QMemoryVideoBuffer>(std::move(bytes), bpl), std::move(frameFormat));
1745 emit lastPreviewFrameFetched(frame);
1748void AndroidCameraPrivate::applyParameters()
1750 QJniEnvironment env;
1751 m_camera.callMethod<
void>(
"setParameters",
1752 "(Landroid/hardware/Camera$Parameters;)V",
1753 m_parameters.object());
1756QStringList AndroidCameraPrivate::callParametersStringListMethod(
const QByteArray &methodName)
1758 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1760 QStringList stringList;
1762 if (m_parameters.isValid()) {
1763 QJniObject list = m_parameters.callObjectMethod(methodName.constData(),
1764 "()Ljava/util/List;");
1766 if (list.isValid()) {
1767 int count = list.callMethod<jint>(
"size");
1768 for (
int i = 0; i < count; ++i) {
1769 QJniObject string = list.callObjectMethod(
"get",
1770 "(I)Ljava/lang/Object;",
1772 stringList.append(string.toString());
1782 static const JNINativeMethod methods[] = {
1783 {
"notifyAutoFocusComplete",
"(IZ)V", (
void *)notifyAutoFocusComplete},
1784 {
"notifyPictureExposed",
"(I)V", (
void *)notifyPictureExposed},
1785 {
"notifyPictureCaptured",
"(I[B)V", (
void *)notifyPictureCaptured},
1786 {
"notifyNewPreviewFrame",
"(I[BIIII)V", (
void *)notifyNewPreviewFrame},
1787 {
"notifyFrameAvailable",
"(I)V", (
void *)notifyFrameAvailable}
1790 const int size =
std::size(methods);
1796#include "androidcamera.moc"
1797#include "moc_androidcamera_p.cpp"
QHash< int, AndroidCamera * > CameraMap
static qint32 s_activeCameras
static const char QtCameraListenerClassName[]
void setupPreviewFrameCallback()
QJniObject getCameraObject()
ImageFormat getPreviewFormat()
QSize getPreferredPreviewSizeForVideo()
void setPictureSize(const QSize &size)
void setFlashMode(const QString &value)
QSize actualPreviewSize()
int getExposureCompensation()
QString getWhiteBalance()
void setExposureCompensation(int value)
bool getAutoExposureLock()
float getExposureCompensationStep()
QList< QCameraFormat > getSupportedFormats()
void setFocusAreas(const QList< QRect > &areas)
bool getAutoWhiteBalanceLock()
QList< QRect > getFocusAreas()
void stopPreviewSynchronous()
QStringList getSupportedFocusModes()
bool setPreviewDisplay(AndroidSurfaceHolder *surfaceHolder)
void setRotation(int rotation)
QList< FpsRange > getSupportedPreviewFpsRange()
bool isAutoWhiteBalanceLockSupported()
static int getNumberOfCameras()
QJniObject getParametersObject()
void setWhiteBalance(const QString &value)
bool setPreviewTexture(AndroidSurfaceTexture *surfaceTexture)
void setAutoExposureLock(bool toggle)
FpsRange getPreviewFpsRange()
void fetchLastPreviewFrame()
void setPreviewFpsRange(FpsRange)
void setJpegQuality(int quality)
QStringList getSupportedSceneModes()
QList< QSize > getSupportedPictureSizes()
QList< QSize > getSupportedPreviewSizes()
static AndroidCamera * open(int cameraId)
void setSceneMode(const QString &value)
QList< QSize > getSupportedVideoSizes()
static bool registerNativeMethods()
void setFocusMode(const QString &value)
QList< ImageFormat > getSupportedPreviewFormats()
void setDisplayOrientation(int degrees)
QSize previewSize() const
int getMaxNumFocusAreas()
QStringList getSupportedWhiteBalance()
int getMinExposureCompensation()
int getNativeOrientation()
void notifyNewFrames(bool notify)
void setPreviewSize(const QSize &size)
int getMaxExposureCompensation()
void setPreviewFormat(ImageFormat fmt)
QStringList getSupportedFlashModes()
QList< int > getZoomRatios()
void setAutoWhiteBalanceLock(bool toggle)
bool isAutoExposureLockSupported()
Q_STATIC_LOGGING_CATEGORY(lcAccessibilityCore, "qt.accessibility.core")