Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
androidcamera.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// Copyright (C) 2016 Ruslan Baratov
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#include "androidcamera_p.h"
9#include "qandroidglobal_p.h"
10
11#include <qhash.h>
12#include <qstringlist.h>
13#include <qdebug.h>
14#include <QtCore/qthread.h>
15#include <QtCore/qreadwritelock.h>
16#include <QtCore/qmutex.h>
17#include <QtMultimedia/private/qmemoryvideobuffer_p.h>
18#include <QtCore/qcoreapplication.h>
19
20#include <mutex>
21
23
24static Q_LOGGING_CATEGORY(lcAndroidCamera, "qt.multimedia.android.camera")
25
26static const char QtCameraListenerClassName[] = "org/qtproject/qt/android/multimedia/QtCameraListener";
27
31
32static QRect areaToRect(jobject areaObj)
33{
34 QJniObject area(areaObj);
35 QJniObject rect = area.getObjectField("rect", "Landroid/graphics/Rect;");
36
37 return QRect(rect.getField<jint>("left"),
38 rect.getField<jint>("top"),
39 rect.callMethod<jint>("width"),
40 rect.callMethod<jint>("height"));
41}
42
44{
45 QJniObject jrect("android/graphics/Rect",
46 "(IIII)V",
47 rect.left(), rect.top(), rect.right(), rect.bottom());
48
49 QJniObject area("android/hardware/Camera$Area",
50 "(Landroid/graphics/Rect;I)V",
51 jrect.object(), 500);
52
53 return area;
54}
55
56// native method for QtCameraLisener.java
57static void notifyAutoFocusComplete(JNIEnv* , jobject, int id, jboolean success)
58{
59 QReadLocker locker(rwLock);
60 const auto it = cameras->constFind(id);
61 if (Q_UNLIKELY(it == cameras->cend()))
62 return;
63
64 Q_EMIT (*it)->autoFocusComplete(success);
65}
66
67static void notifyPictureExposed(JNIEnv* , jobject, int id)
68{
69 QReadLocker locker(rwLock);
70 const auto it = cameras->constFind(id);
71 if (Q_UNLIKELY(it == cameras->cend()))
72 return;
73
74 Q_EMIT (*it)->pictureExposed();
75}
76
77static void notifyPictureCaptured(JNIEnv *env, jobject, int id, jbyteArray data)
78{
79 QReadLocker locker(rwLock);
80 const auto it = cameras->constFind(id);
81 if (Q_UNLIKELY(it == cameras->cend())) {
82 qCWarning(lcAndroidCamera) << "Could not obtain camera!";
83 return;
84 }
85
86 AndroidCamera *camera = (*it);
87
88 const int arrayLength = env->GetArrayLength(data);
90 env->GetByteArrayRegion(data, 0, arrayLength, reinterpret_cast<jbyte *>(bytes.data()));
91
92 auto parameters = camera->getParametersObject();
93
95 parameters.callObjectMethod("getPictureSize", "()Landroid/hardware/Camera$Size;");
96
97 if (!size.isValid()) {
98 qCWarning(lcAndroidCamera) << "Picture Size is not valid!";
99 return;
100 }
101
102 QSize pictureSize(size.getField<jint>("width"), size.getField<jint>("height"));
103
104 auto format = AndroidCamera::ImageFormat(parameters.callMethod<jint>("getPictureFormat"));
105
107 qCWarning(lcAndroidCamera) << "Android Camera Image Format is UnknownImageFormat!";
108 return;
109 }
110
111 int bytesPerLine = 0;
112
113 switch (format) {
115 bytesPerLine = (pictureSize.width() + 15) & ~15;
116 break;
118 bytesPerLine = pictureSize.width();
119 break;
122 bytesPerLine = pictureSize.width() * 2;
123 break;
124 default:
125 bytesPerLine = -1;
126 }
127
128 QVideoFrame frame(new QMemoryVideoBuffer(bytes, bytesPerLine),
130
131 emit camera->pictureCaptured(frame);
132}
133
134static void notifyNewPreviewFrame(JNIEnv *env, jobject, int id, jbyteArray data,
135 int width, int height, int format, int bpl)
136{
137 QReadLocker locker(rwLock);
138 const auto it = cameras->constFind(id);
139 if (Q_UNLIKELY(it == cameras->cend()))
140 return;
141
142 const int arrayLength = env->GetArrayLength(data);
143 if (arrayLength == 0)
144 return;
145
147 env->GetByteArrayRegion(data, 0, arrayLength, (jbyte*)bytes.data());
148
149 QVideoFrame frame(new QMemoryVideoBuffer(bytes, bpl),
152
153 Q_EMIT (*it)->newPreviewFrame(frame);
154}
155
156static void notifyFrameAvailable(JNIEnv *, jobject, int id)
157{
158 QReadLocker locker(rwLock);
159 const auto it = cameras->constFind(id);
160 if (Q_UNLIKELY(it == cameras->cend()))
161 return;
162
163 (*it)->fetchLastPreviewFrame();
164}
165
167{
169public:
172
173 Q_INVOKABLE bool init(int cameraId);
174
175 Q_INVOKABLE void release();
176 Q_INVOKABLE bool lock();
177 Q_INVOKABLE bool unlock();
178 Q_INVOKABLE bool reconnect();
179
182
186
188
191 Q_INVOKABLE void setPreviewFpsRange(int min, int max);
192
197
201 Q_INVOKABLE bool setPreviewTexture(void *surfaceTexture);
202 Q_INVOKABLE bool setPreviewDisplay(void *surfaceHolder);
203 Q_INVOKABLE void setDisplayOrientation(int degrees);
204
208 Q_INVOKABLE int getZoom();
209 Q_INVOKABLE void setZoom(int value);
210
213
216
219 Q_INVOKABLE void setFocusAreas(const QList<QRect> &areas);
220
221 Q_INVOKABLE void autoFocus();
223
226 Q_INVOKABLE void setAutoExposureLock(bool toggle);
227
230 Q_INVOKABLE void setAutoWhiteBalanceLock(bool toggle);
231
237
240
243
245
249 Q_INVOKABLE void setJpegQuality(int quality);
250
253
255
257 Q_INVOKABLE void notifyNewFrames(bool notify);
259
261
263
272
278
280
282
284
286};
287
288AndroidCamera::AndroidCamera(AndroidCameraPrivate *d, QThread *worker)
289 : QObject(),
290 d_ptr(d),
291 m_worker(worker)
292
293{
302}
303
305{
306 Q_D(AndroidCamera);
307 if (d->m_camera.isValid()) {
308 release();
309 QWriteLocker locker(rwLock);
310 cameras->remove(cameraId());
311 }
312
313 m_worker->exit();
314 m_worker->wait(5000);
315}
316
318{
320 return nullptr;
321
323 QThread *worker = new QThread;
324 worker->start();
325 d->moveToThread(worker);
327 bool ok = true;
329 if (!ok) {
330 worker->quit();
331 worker->wait(5000);
332 delete worker;
333 return 0;
334 }
335
336 AndroidCamera *q = new AndroidCamera(d, worker);
337 QWriteLocker locker(rwLock);
338 cameras->insert(cameraId, q);
339
340 return q;
341}
342
344{
345 Q_D(const AndroidCamera);
346 return d->m_cameraId;
347}
348
350{
351 Q_D(AndroidCamera);
352 bool ok = true;
354 return ok;
355}
356
358{
359 Q_D(AndroidCamera);
360 bool ok = true;
362 return ok;
363}
364
366{
367 Q_D(AndroidCamera);
368 bool ok = true;
370 return ok;
371}
372
374{
375 Q_D(AndroidCamera);
377}
378
380{
381 Q_D(AndroidCamera);
382 return d->getFacing();
383}
384
386{
387 Q_D(AndroidCamera);
388 return d->getNativeOrientation();
389}
390
392{
393 Q_D(AndroidCamera);
394 return d->getPreferredPreviewSizeForVideo();
395}
396
398{
399 Q_D(AndroidCamera);
400 return d->getSupportedPreviewSizes();
401}
402
404{
405 Q_D(AndroidCamera);
406 return d->getSupportedPreviewFpsRange();
407}
408
410{
411 Q_D(AndroidCamera);
412 return d->getPreviewFpsRange();
413}
414
416{
417 Q_D(AndroidCamera);
418 QMetaObject::invokeMethod(d, "setPreviewFpsRange", Q_ARG(int, range.min), Q_ARG(int, range.max));
419}
420
422{
423 Q_D(AndroidCamera);
424 return d->getPreviewFormat();
425}
426
428{
429 Q_D(AndroidCamera);
431}
432
434{
435 Q_D(AndroidCamera);
436 return d->getSupportedPreviewFormats();
437}
438
440{
441 Q_D(const AndroidCamera);
442 return d->m_previewSize;
443}
444
446{
447 Q_D(AndroidCamera);
448 return d->getPreviewSize();
449}
450
452{
453 Q_D(AndroidCamera);
454 d->m_parametersMutex.lock();
455 bool areParametersValid = d->m_parameters.isValid();
456 d->m_parametersMutex.unlock();
457 if (!areParametersValid)
458 return;
459
460 d->m_previewSize = size;
461 QMetaObject::invokeMethod(d, "updatePreviewSize");
462}
463
465{
466 Q_D(AndroidCamera);
467 bool ok = true;
469 "setPreviewTexture",
471 Q_RETURN_ARG(bool, ok),
472 Q_ARG(void *, surfaceTexture ? surfaceTexture->surfaceTexture() : 0));
473 return ok;
474}
475
477{
478 Q_D(AndroidCamera);
479 bool ok = true;
481 "setPreviewDisplay",
483 Q_RETURN_ARG(bool, ok),
484 Q_ARG(void *, surfaceHolder ? surfaceHolder->surfaceHolder() : 0));
485 return ok;
486}
487
489{
490 Q_D(AndroidCamera);
491 QMetaObject::invokeMethod(d, "setDisplayOrientation", Qt::QueuedConnection, Q_ARG(int, degrees));
492}
493
495{
496 Q_D(AndroidCamera);
497 return d->isZoomSupported();
498}
499
501{
502 Q_D(AndroidCamera);
503 return d->getMaxZoom();
504}
505
507{
508 Q_D(AndroidCamera);
509 return d->getZoomRatios();
510}
511
513{
514 Q_D(AndroidCamera);
515 return d->getZoom();
516}
517
519{
520 Q_D(AndroidCamera);
521 QMetaObject::invokeMethod(d, "setZoom", Q_ARG(int, value));
522}
523
525{
526 Q_D(AndroidCamera);
527 return d->callParametersStringListMethod("getSupportedFlashModes");
528}
529
531{
532 Q_D(AndroidCamera);
533 return d->getFlashMode();
534}
535
537{
538 Q_D(AndroidCamera);
539 QMetaObject::invokeMethod(d, "setFlashMode", Q_ARG(QString, value));
540}
541
543{
544 Q_D(AndroidCamera);
545 return d->callParametersStringListMethod("getSupportedFocusModes");
546}
547
549{
550 Q_D(AndroidCamera);
551 return d->getFocusMode();
552}
553
555{
556 Q_D(AndroidCamera);
557 QMetaObject::invokeMethod(d, "setFocusMode", Q_ARG(QString, value));
558}
559
561{
562 Q_D(AndroidCamera);
563 return d->getMaxNumFocusAreas();
564}
565
567{
568 Q_D(AndroidCamera);
569 return d->getFocusAreas();
570}
571
573{
574 Q_D(AndroidCamera);
575 QMetaObject::invokeMethod(d, "setFocusAreas", Q_ARG(QList<QRect>, areas));
576}
577
579{
580 Q_D(AndroidCamera);
581 QMetaObject::invokeMethod(d, "autoFocus");
582}
583
585{
586 Q_D(AndroidCamera);
588}
589
591{
592 Q_D(AndroidCamera);
593 return d->isAutoExposureLockSupported();
594}
595
597{
598 Q_D(AndroidCamera);
599 return d->getAutoExposureLock();
600}
601
603{
604 Q_D(AndroidCamera);
605 QMetaObject::invokeMethod(d, "setAutoExposureLock", Q_ARG(bool, toggle));
606}
607
609{
610 Q_D(AndroidCamera);
611 return d->isAutoWhiteBalanceLockSupported();
612}
613
615{
616 Q_D(AndroidCamera);
617 return d->getAutoWhiteBalanceLock();
618}
619
621{
622 Q_D(AndroidCamera);
623 QMetaObject::invokeMethod(d, "setAutoWhiteBalanceLock", Q_ARG(bool, toggle));
624}
625
627{
628 Q_D(AndroidCamera);
629 return d->getExposureCompensation();
630}
631
633{
634 Q_D(AndroidCamera);
635 QMetaObject::invokeMethod(d, "setExposureCompensation", Q_ARG(int, value));
636}
637
639{
640 Q_D(AndroidCamera);
641 return d->getExposureCompensationStep();
642}
643
645{
646 Q_D(AndroidCamera);
647 return d->getMinExposureCompensation();
648}
649
651{
652 Q_D(AndroidCamera);
653 return d->getMaxExposureCompensation();
654}
655
657{
658 Q_D(AndroidCamera);
659 return d->callParametersStringListMethod("getSupportedSceneModes");
660}
661
663{
664 Q_D(AndroidCamera);
665 return d->getSceneMode();
666}
667
669{
670 Q_D(AndroidCamera);
671 QMetaObject::invokeMethod(d, "setSceneMode", Q_ARG(QString, value));
672}
673
675{
676 Q_D(AndroidCamera);
677 return d->callParametersStringListMethod("getSupportedWhiteBalance");
678}
679
681{
682 Q_D(AndroidCamera);
683 return d->getWhiteBalance();
684}
685
687{
688 Q_D(AndroidCamera);
689 QMetaObject::invokeMethod(d, "setWhiteBalance", Q_ARG(QString, value));
690}
691
693{
694 Q_D(AndroidCamera);
695 //We need to do it here and not in worker class because we cache rotation
696 d->m_parametersMutex.lock();
697 bool areParametersValid = d->m_parameters.isValid();
698 d->m_parametersMutex.unlock();
699 if (!areParametersValid)
700 return;
701
702 d->m_rotation = rotation;
703 QMetaObject::invokeMethod(d, "updateRotation");
704}
705
707{
708 Q_D(const AndroidCamera);
709 return d->m_rotation;
710}
711
713{
714 Q_D(AndroidCamera);
715 return d->getSupportedPictureSizes();
716}
717
719{
720 Q_D(AndroidCamera);
721 return d->getSupportedVideoSizes();
722}
723
725{
726 Q_D(AndroidCamera);
727 QMetaObject::invokeMethod(d, "setPictureSize", Q_ARG(QSize, size));
728}
729
731{
732 Q_D(AndroidCamera);
733 QMetaObject::invokeMethod(d, "setJpegQuality", Q_ARG(int, quality));
734}
735
737{
738 Q_D(AndroidCamera);
740}
741
743{
744 Q_D(AndroidCamera);
745 QMetaObject::invokeMethod(d, "setupPreviewFrameCallback");
746}
747
749{
750 Q_D(AndroidCamera);
751 QMetaObject::invokeMethod(d, "notifyNewFrames", Q_ARG(bool, notify));
752}
753
755{
756 Q_D(AndroidCamera);
757 QMetaObject::invokeMethod(d, "fetchLastPreviewFrame");
758}
759
761{
762 Q_D(AndroidCamera);
763 return d->m_camera;
764}
765
767{
769 return 0;
770
771 return QJniObject::callStaticMethod<jint>("android/hardware/Camera",
772 "getNumberOfCameras");
773}
774
776{
777 Q_ASSERT(info);
778
779 QJniObject cameraInfo("android/hardware/Camera$CameraInfo");
780 QJniObject::callStaticMethod<void>("android/hardware/Camera",
781 "getCameraInfo",
782 "(ILandroid/hardware/Camera$CameraInfo;)V",
783 id, cameraInfo.object());
784
785 AndroidCamera::CameraFacing facing = AndroidCamera::CameraFacing(cameraInfo.getField<jint>("facing"));
786 // The orientation provided by Android is counter-clockwise, we need it clockwise
787 info->orientation = (360 - cameraInfo.getField<jint>("orientation")) % 360;
788
789 switch (facing) {
791 info->id = QByteArray("back");
792 info->description = QStringLiteral("Rear-facing camera");
793 info->position = QCameraDevice::BackFace;
794 info->isDefault = true;
795 break;
797 info->id = QByteArray("front");
798 info->description = QStringLiteral("Front-facing camera");
799 info->position = QCameraDevice::FrontFace;
800 break;
801 default:
802 break;
803 }
804 // Add a number to allow correct access to cameras on systems with two
805 // (and more) front/back cameras
806 if (id > 1) {
807 info->id.append(QByteArray::number(id));
808 info->description.append(QString(" %1").arg(id));
809 }
810}
811
813{
814 switch (format) {
823 default:
825 }
826}
827
829{
830 switch (format) {
832 return AndroidCamera::NV21;
834 return AndroidCamera::YUY2;
836 return AndroidCamera::JPEG;
838 return AndroidCamera::YV12;
839 default:
841 }
842}
843
845{
848 for (const auto &previewSize : getSupportedVideoSizes()) {
849 for (const auto &previewFormat : getSupportedPreviewFormats()) {
851 format->pixelFormat = QtPixelFormatFromAndroidImageFormat(previewFormat);
852 format->resolution = previewSize;
853 format->minFrameRate = range.min;
854 format->maxFrameRate = range.max;
855 formats.append(format->create());
856 }
857 }
858
859 return formats;
860}
861
863{
864 Q_D(AndroidCamera);
865 QMetaObject::invokeMethod(d, "startPreview");
866}
867
869{
870 Q_D(AndroidCamera);
871 QMetaObject::invokeMethod(d, "stopPreview");
872}
873
875{
876 Q_D(AndroidCamera);
878}
879
881{
882 Q_D(AndroidCamera);
883 return d->m_parameters;
884}
885
887 : QObject()
888{
889}
890
892{
893}
894
896
898{
899 m_cameraId = cameraId;
900 QJniEnvironment env;
901
902 const bool opened = s_activeCameras & (1 << cameraId);
903 if (opened)
904 return false;
905
906 m_camera = QJniObject::callStaticObjectMethod("android/hardware/Camera",
907 "open",
908 "(I)Landroid/hardware/Camera;",
909 cameraId);
910 if (!m_camera.isValid())
911 return false;
912
913 m_cameraListener = QJniObject(QtCameraListenerClassName, "(I)V", m_cameraId);
914 m_info = QJniObject("android/hardware/Camera$CameraInfo");
915 m_camera.callStaticMethod<void>("android/hardware/Camera",
916 "getCameraInfo",
917 "(ILandroid/hardware/Camera$CameraInfo;)V",
918 cameraId,
919 m_info.object());
920
921 QJniObject params = m_camera.callObjectMethod("getParameters",
922 "()Landroid/hardware/Camera$Parameters;");
924 s_activeCameras |= 1 << cameraId;
925
926 return true;
927}
928
930{
935 if (m_camera.isValid()) {
936 m_camera.callMethod<void>("release");
937 s_activeCameras &= ~(1 << m_cameraId);
938 }
939}
940
942{
943 QJniEnvironment env;
944 auto methodId = env->GetMethodID(m_camera.objectClass(), "lock", "()V");
945 env->CallVoidMethod(m_camera.object(), methodId);
946
947 if (env.checkAndClearExceptions())
948 return false;
949 return true;
950}
951
953{
954 QJniEnvironment env;
955 auto methodId = env->GetMethodID(m_camera.objectClass(), "unlock", "()V");
956 env->CallVoidMethod(m_camera.object(), methodId);
957
958 if (env.checkAndClearExceptions())
959 return false;
960 return true;
961}
962
964{
965 QJniEnvironment env;
966 auto methodId = env->GetMethodID(m_camera.objectClass(), "reconnect", "()V");
967 env->CallVoidMethod(m_camera.object(), methodId);
968
969 if (env.checkAndClearExceptions())
970 return false;
971 return true;
972}
973
975{
976 return AndroidCamera::CameraFacing(m_info.getField<jint>("facing"));
977}
978
980{
981 return m_info.getField<jint>("orientation");
982}
983
985{
986 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
987
988 if (!m_parameters.isValid())
989 return QSize();
990
991 QJniObject size = m_parameters.callObjectMethod("getPreferredPreviewSizeForVideo",
992 "()Landroid/hardware/Camera$Size;");
993
994 if (!size.isValid())
995 return QSize();
996
997 return QSize(size.getField<jint>("width"), size.getField<jint>("height"));
998}
999
1001{
1002 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1004}
1005
1007{
1009
1010 if (parameters.isValid()) {
1011 QJniObject sizeList = parameters.callObjectMethod("getSupportedPreviewSizes",
1012 "()Ljava/util/List;");
1013 int count = sizeList.callMethod<jint>("size");
1014 for (int i = 0; i < count; ++i) {
1015 QJniObject size = sizeList.callObjectMethod("get",
1016 "(I)Ljava/lang/Object;",
1017 i);
1018 list.append(QSize(size.getField<jint>("width"), size.getField<jint>("height")));
1019 }
1020
1021 std::sort(list.begin(), list.end(), qt_sizeLessThan);
1022 }
1023
1024 return list;
1025}
1026
1028{
1029 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1030
1031 QJniEnvironment env;
1032
1034
1035 if (m_parameters.isValid()) {
1036 QJniObject rangeListNative = m_parameters.callObjectMethod("getSupportedPreviewFpsRange",
1037 "()Ljava/util/List;");
1038 int count = rangeListNative.callMethod<jint>("size");
1039
1040 rangeList.reserve(count);
1041
1042 for (int i = 0; i < count; ++i) {
1043 QJniObject range = rangeListNative.callObjectMethod("get",
1044 "(I)Ljava/lang/Object;",
1045 i);
1046
1047 jintArray jRange = static_cast<jintArray>(range.object());
1048 jint* rangeArray = env->GetIntArrayElements(jRange, 0);
1049
1050 AndroidCamera::FpsRange fpsRange;
1051
1052 fpsRange.min = rangeArray[0];
1053 fpsRange.max = rangeArray[1];
1054
1055 env->ReleaseIntArrayElements(jRange, rangeArray, 0);
1056
1057 rangeList << fpsRange;
1058 }
1059 }
1060
1061 return rangeList;
1062}
1063
1065{
1066 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1068}
1069
1071{
1072 QJniEnvironment env;
1073
1075
1076 if (!parameters.isValid())
1077 return range;
1078
1079 jintArray jRangeArray = env->NewIntArray(2);
1080 parameters.callMethod<void>("getPreviewFpsRange", "([I)V", jRangeArray);
1081
1082 jint* jRangeElements = env->GetIntArrayElements(jRangeArray, 0);
1083
1084 // Android Camera API returns values scaled by 1000, so divide here to report
1085 // normal values for Qt
1086 range.min = jRangeElements[0] / 1000;
1087 range.max = jRangeElements[1] / 1000;
1088
1089 env->ReleaseIntArrayElements(jRangeArray, jRangeElements, 0);
1090 env->DeleteLocalRef(jRangeArray);
1091
1092 return range;
1093}
1094
1096{
1097 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1098
1099 if (!m_parameters.isValid())
1100 return;
1101
1102 // Android Camera API returns values scaled by 1000, so multiply here to
1103 // give Android API the scale is expects
1104 m_parameters.callMethod<void>("setPreviewFpsRange", "(II)V", min * 1000, max * 1000);
1105}
1106
1108{
1109 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1110
1111 if (!m_parameters.isValid())
1113
1114 return AndroidCamera::ImageFormat(m_parameters.callMethod<jint>("getPreviewFormat"));
1115}
1116
1118{
1119 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1120
1121 if (!m_parameters.isValid())
1122 return;
1123
1124 m_parameters.callMethod<void>("setPreviewFormat", "(I)V", jint(fmt));
1126}
1127
1129{
1130 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1132}
1133
1135{
1137
1138 if (parameters.isValid()) {
1139 QJniObject formatList = parameters.callObjectMethod("getSupportedPreviewFormats",
1140 "()Ljava/util/List;");
1141 int count = formatList.callMethod<jint>("size");
1142 for (int i = 0; i < count; ++i) {
1143 QJniObject format = formatList.callObjectMethod("get",
1144 "(I)Ljava/lang/Object;",
1145 i);
1146 list.append(AndroidCamera::ImageFormat(format.callMethod<jint>("intValue")));
1147 }
1148 }
1149
1150 return list;
1151}
1152
1154{
1155 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1156
1157 if (!m_parameters.isValid())
1158 return QSize();
1159
1160 QJniObject size = m_parameters.callObjectMethod("getPreviewSize",
1161 "()Landroid/hardware/Camera$Size;");
1162
1163 if (!size.isValid())
1164 return QSize();
1165
1166 return QSize(size.getField<jint>("width"), size.getField<jint>("height"));
1167}
1168
1170{
1171 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1172
1173 if (m_previewSize.isValid()) {
1174 m_parameters.callMethod<void>("setPreviewSize", "(II)V", m_previewSize.width(), m_previewSize.height());
1176 }
1177
1179}
1180
1182{
1183 QJniEnvironment env;
1184 auto methodId = env->GetMethodID(m_camera.objectClass(), "setPreviewTexture",
1185 "(Landroid/graphics/SurfaceTexture;)V");
1186 env->CallVoidMethod(m_camera.object(), methodId, static_cast<jobject>(surfaceTexture));
1187
1188 if (env.checkAndClearExceptions())
1189 return false;
1190 return true;
1191}
1192
1194{
1195 QJniEnvironment env;
1196 auto methodId = env->GetMethodID(m_camera.objectClass(), "setPreviewDisplay",
1197 "(Landroid/view/SurfaceHolder;)V");
1198 env->CallVoidMethod(m_camera.object(), methodId, static_cast<jobject>(surfaceHolder));
1199
1200 if (env.checkAndClearExceptions())
1201 return false;
1202 return true;
1203}
1204
1206{
1207 m_camera.callMethod<void>("setDisplayOrientation", "(I)V", degrees);
1208}
1209
1211{
1212 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1213
1214 if (!m_parameters.isValid())
1215 return false;
1216
1217 return m_parameters.callMethod<jboolean>("isZoomSupported");
1218}
1219
1221{
1222 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1223
1224 if (!m_parameters.isValid())
1225 return 0;
1226
1227 return m_parameters.callMethod<jint>("getMaxZoom");
1228}
1229
1231{
1232 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1233
1234 QList<int> ratios;
1235
1236 if (m_parameters.isValid()) {
1237 QJniObject ratioList = m_parameters.callObjectMethod("getZoomRatios",
1238 "()Ljava/util/List;");
1239 int count = ratioList.callMethod<jint>("size");
1240 for (int i = 0; i < count; ++i) {
1241 QJniObject zoomRatio = ratioList.callObjectMethod("get",
1242 "(I)Ljava/lang/Object;",
1243 i);
1244
1245 ratios.append(zoomRatio.callMethod<jint>("intValue"));
1246 }
1247 }
1248
1249 return ratios;
1250}
1251
1253{
1254 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1255
1256 if (!m_parameters.isValid())
1257 return 0;
1258
1259 return m_parameters.callMethod<jint>("getZoom");
1260}
1261
1263{
1264 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1265
1266 if (!m_parameters.isValid())
1267 return;
1268
1269 m_parameters.callMethod<void>("setZoom", "(I)V", value);
1271}
1272
1274{
1275 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1276
1277 QString value;
1278
1279 if (m_parameters.isValid()) {
1280 QJniObject flashMode = m_parameters.callObjectMethod("getFlashMode",
1281 "()Ljava/lang/String;");
1282 if (flashMode.isValid())
1283 value = flashMode.toString();
1284 }
1285
1286 return value;
1287}
1288
1290{
1291 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1292
1293 if (!m_parameters.isValid())
1294 return;
1295
1296 m_parameters.callMethod<void>("setFlashMode",
1297 "(Ljava/lang/String;)V",
1298 QJniObject::fromString(value).object());
1300}
1301
1303{
1304 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1305
1306 QString value;
1307
1308 if (m_parameters.isValid()) {
1309 QJniObject focusMode = m_parameters.callObjectMethod("getFocusMode",
1310 "()Ljava/lang/String;");
1311 if (focusMode.isValid())
1312 value = focusMode.toString();
1313 }
1314
1315 return value;
1316}
1317
1319{
1320 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1321
1322 if (!m_parameters.isValid())
1323 return;
1324
1325 m_parameters.callMethod<void>("setFocusMode",
1326 "(Ljava/lang/String;)V",
1327 QJniObject::fromString(value).object());
1329}
1330
1332{
1333 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1334
1335 if (!m_parameters.isValid())
1336 return 0;
1337
1338 return m_parameters.callMethod<jint>("getMaxNumFocusAreas");
1339}
1340
1342{
1343 QList<QRect> areas;
1344 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1345
1346 if (m_parameters.isValid()) {
1347 QJniObject list = m_parameters.callObjectMethod("getFocusAreas",
1348 "()Ljava/util/List;");
1349
1350 if (list.isValid()) {
1351 int count = list.callMethod<jint>("size");
1352 for (int i = 0; i < count; ++i) {
1353 QJniObject area = list.callObjectMethod("get",
1354 "(I)Ljava/lang/Object;",
1355 i);
1356
1357 areas.append(areaToRect(area.object()));
1358 }
1359 }
1360 }
1361
1362 return areas;
1363}
1364
1366{
1367 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1368
1369 if (!m_parameters.isValid() || areas.isEmpty())
1370 return;
1371
1373
1374 if (!areas.isEmpty()) {
1375 QJniEnvironment env;
1376 QJniObject arrayList("java/util/ArrayList", "(I)V", areas.size());
1377 for (int i = 0; i < areas.size(); ++i) {
1378 arrayList.callMethod<jboolean>("add",
1379 "(Ljava/lang/Object;)Z",
1380 rectToArea(areas.at(i)).object());
1381 }
1382 list = arrayList;
1383 }
1384
1385 m_parameters.callMethod<void>("setFocusAreas", "(Ljava/util/List;)V", list.object());
1386
1388}
1389
1391{
1392 QJniEnvironment env;
1393 auto methodId = env->GetMethodID(m_camera.objectClass(), "autoFocus",
1394 "(Landroid/hardware/Camera$AutoFocusCallback;)V");
1395 env->CallVoidMethod(m_camera.object(), methodId, m_cameraListener.object());
1396
1397 if (!env.checkAndClearExceptions())
1399}
1400
1402{
1403 QJniEnvironment env;
1404 m_camera.callMethod<void>("cancelAutoFocus");
1405}
1406
1408{
1409 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1410
1411 if (!m_parameters.isValid())
1412 return false;
1413
1414 return m_parameters.callMethod<jboolean>("isAutoExposureLockSupported");
1415}
1416
1418{
1419 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1420
1421 if (!m_parameters.isValid())
1422 return false;
1423
1424 return m_parameters.callMethod<jboolean>("getAutoExposureLock");
1425}
1426
1428{
1429 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1430
1431 if (!m_parameters.isValid())
1432 return;
1433
1434 m_parameters.callMethod<void>("setAutoExposureLock", "(Z)V", toggle);
1436}
1437
1439{
1440 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1441
1442 if (!m_parameters.isValid())
1443 return false;
1444
1445 return m_parameters.callMethod<jboolean>("isAutoWhiteBalanceLockSupported");
1446}
1447
1449{
1450 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1451
1452 if (!m_parameters.isValid())
1453 return false;
1454
1455 return m_parameters.callMethod<jboolean>("getAutoWhiteBalanceLock");
1456}
1457
1459{
1460 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1461
1462 if (!m_parameters.isValid())
1463 return;
1464
1465 m_parameters.callMethod<void>("setAutoWhiteBalanceLock", "(Z)V", toggle);
1467}
1468
1470{
1471 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1472
1473 if (!m_parameters.isValid())
1474 return 0;
1475
1476 return m_parameters.callMethod<jint>("getExposureCompensation");
1477}
1478
1480{
1481 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1482
1483 if (!m_parameters.isValid())
1484 return;
1485
1486 m_parameters.callMethod<void>("setExposureCompensation", "(I)V", value);
1488}
1489
1491{
1492 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1493
1494 if (!m_parameters.isValid())
1495 return 0;
1496
1497 return m_parameters.callMethod<jfloat>("getExposureCompensationStep");
1498}
1499
1501{
1502 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1503
1504 if (!m_parameters.isValid())
1505 return 0;
1506
1507 return m_parameters.callMethod<jint>("getMinExposureCompensation");
1508}
1509
1511{
1512 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1513
1514 if (!m_parameters.isValid())
1515 return 0;
1516
1517 return m_parameters.callMethod<jint>("getMaxExposureCompensation");
1518}
1519
1521{
1522 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1523
1524 QString value;
1525
1526 if (m_parameters.isValid()) {
1527 QJniObject sceneMode = m_parameters.callObjectMethod("getSceneMode",
1528 "()Ljava/lang/String;");
1529 if (sceneMode.isValid())
1530 value = sceneMode.toString();
1531 }
1532
1533 return value;
1534}
1535
1537{
1538 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1539
1540 if (!m_parameters.isValid())
1541 return;
1542
1543 m_parameters.callMethod<void>("setSceneMode",
1544 "(Ljava/lang/String;)V",
1545 QJniObject::fromString(value).object());
1547}
1548
1550{
1551 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1552
1553 QString value;
1554
1555 if (m_parameters.isValid()) {
1556 QJniObject wb = m_parameters.callObjectMethod("getWhiteBalance",
1557 "()Ljava/lang/String;");
1558 if (wb.isValid())
1559 value = wb.toString();
1560 }
1561
1562 return value;
1563}
1564
1566{
1567 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1568
1569 if (!m_parameters.isValid())
1570 return;
1571
1572 m_parameters.callMethod<void>("setWhiteBalance",
1573 "(Ljava/lang/String;)V",
1574 QJniObject::fromString(value).object());
1576
1578}
1579
1581{
1582 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1583
1584 m_parameters.callMethod<void>("setRotation", "(I)V", m_rotation);
1586}
1587
1589{
1590 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1591
1593
1594 if (m_parameters.isValid()) {
1595 QJniObject sizeList = m_parameters.callObjectMethod("getSupportedPictureSizes",
1596 "()Ljava/util/List;");
1597 int count = sizeList.callMethod<jint>("size");
1598 for (int i = 0; i < count; ++i) {
1599 QJniObject size = sizeList.callObjectMethod("get",
1600 "(I)Ljava/lang/Object;",
1601 i);
1602 list.append(QSize(size.getField<jint>("width"), size.getField<jint>("height")));
1603 }
1604
1605 std::sort(list.begin(), list.end(), qt_sizeLessThan);
1606 }
1607
1608 return list;
1609}
1610
1612{
1613 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1615
1616 if (m_parameters.isValid()) {
1617 QJniObject sizeList = m_parameters.callObjectMethod("getSupportedVideoSizes",
1618 "()Ljava/util/List;");
1619 if (!sizeList.isValid())
1620 return list;
1621
1622 int count = sizeList.callMethod<jint>("size");
1623 for (int i = 0; i < count; ++i) {
1624 const QJniObject size = sizeList.callObjectMethod("get", "(I)Ljava/lang/Object;", i);
1625 if (size.isValid())
1626 list.append(QSize(size.getField<jint>("width"), size.getField<jint>("height")));
1627 }
1628 std::sort(list.begin(), list.end(), qt_sizeLessThan);
1629 }
1630
1631 return list;
1632}
1633
1635{
1636 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1637
1638 if (!m_parameters.isValid())
1639 return;
1640
1641 m_parameters.callMethod<void>("setPictureSize", "(II)V", size.width(), size.height());
1643}
1644
1646{
1647 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1648
1649 if (!m_parameters.isValid())
1650 return;
1651
1652 m_parameters.callMethod<void>("setJpegQuality", "(I)V", quality);
1654}
1655
1657{
1659
1660 QJniEnvironment env;
1661 auto methodId = env->GetMethodID(m_camera.objectClass(), "startPreview", "()V");
1662 env->CallVoidMethod(m_camera.object(), methodId);
1663
1664 if (env.checkAndClearExceptions())
1666 else
1668}
1669
1671{
1672 // cancel any pending new frame notification
1673 m_cameraListener.callMethod<void>("notifyWhenFrameAvailable", "(Z)V", false);
1674 m_camera.callMethod<void>("stopPreview");
1676}
1677
1679{
1680 // We must clear the preview callback before calling takePicture(), otherwise the call will
1681 // block and the camera server will be frozen until the next device restart...
1682 // That problem only happens on some devices and on the emulator
1683 m_cameraListener.callMethod<void>("clearPreviewCallback", "(Landroid/hardware/Camera;)V", m_camera.object());
1684
1685 QJniEnvironment env;
1686 auto methodId = env->GetMethodID(m_camera.objectClass(), "takePicture",
1687 "(Landroid/hardware/Camera$ShutterCallback;"
1688 "Landroid/hardware/Camera$PictureCallback;"
1689 "Landroid/hardware/Camera$PictureCallback;)V");
1690 env->CallVoidMethod(m_camera.object(), methodId, m_cameraListener.object(),
1691 jobject(0), m_cameraListener.object());
1692
1693 if (env.checkAndClearExceptions())
1695}
1696
1698{
1699 m_cameraListener.callMethod<void>("setupPreviewCallback", "(Landroid/hardware/Camera;)V", m_camera.object());
1700}
1701
1703{
1704 m_cameraListener.callMethod<void>("notifyNewFrames", "(Z)V", notify);
1705}
1706
1708{
1709 QJniEnvironment env;
1710 QJniObject data = m_cameraListener.callObjectMethod("lastPreviewBuffer", "()[B");
1711
1712 if (!data.isValid()) {
1713 // If there's no buffer received yet, retry when the next one arrives
1714 m_cameraListener.callMethod<void>("notifyWhenFrameAvailable", "(Z)V", true);
1715 return;
1716 }
1717
1718 const int arrayLength = env->GetArrayLength(static_cast<jbyteArray>(data.object()));
1719 if (arrayLength == 0)
1720 return;
1721
1723 env->GetByteArrayRegion(static_cast<jbyteArray>(data.object()),
1724 0,
1726 reinterpret_cast<jbyte *>(bytes.data()));
1727
1728 const int width = m_cameraListener.callMethod<jint>("previewWidth");
1729 const int height = m_cameraListener.callMethod<jint>("previewHeight");
1730 const int format = m_cameraListener.callMethod<jint>("previewFormat");
1731 const int bpl = m_cameraListener.callMethod<jint>("previewBytesPerLine");
1732
1733 QVideoFrame frame(new QMemoryVideoBuffer(bytes, bpl),
1736
1738}
1739
1741{
1742 QJniEnvironment env;
1743 m_camera.callMethod<void>("setParameters",
1744 "(Landroid/hardware/Camera$Parameters;)V",
1745 m_parameters.object());
1746}
1747
1749{
1750 const std::lock_guard<QRecursiveMutex> locker(m_parametersMutex);
1751
1753
1754 if (m_parameters.isValid()) {
1755 QJniObject list = m_parameters.callObjectMethod(methodName.constData(),
1756 "()Ljava/util/List;");
1757
1758 if (list.isValid()) {
1759 int count = list.callMethod<jint>("size");
1760 for (int i = 0; i < count; ++i) {
1761 QJniObject string = list.callObjectMethod("get",
1762 "(I)Ljava/lang/Object;",
1763 i);
1764 stringList.append(string.toString());
1765 }
1766 }
1767 }
1768
1769 return stringList;
1770}
1771
1773{
1774 static const JNINativeMethod methods[] = {
1775 {"notifyAutoFocusComplete", "(IZ)V", (void *)notifyAutoFocusComplete},
1776 {"notifyPictureExposed", "(I)V", (void *)notifyPictureExposed},
1777 {"notifyPictureCaptured", "(I[B)V", (void *)notifyPictureCaptured},
1778 {"notifyNewPreviewFrame", "(I[BIIII)V", (void *)notifyNewPreviewFrame},
1779 {"notifyFrameAvailable", "(I)V", (void *)notifyFrameAvailable}
1780 };
1781
1782 const int size = std::size(methods);
1783 return QJniEnvironment().registerNativeMethods(QtCameraListenerClassName, methods, size);
1784}
1785
1787
1788#include "androidcamera.moc"
1789#include "moc_androidcamera_p.cpp"
static void notifyPictureExposed(JNIEnv *, jobject, int id)
static void notifyFrameAvailable(JNIEnv *, jobject, int id)
static QJniObject rectToArea(const QRect &rect)
static void notifyAutoFocusComplete(JNIEnv *, jobject, int id, jboolean success)
static qint32 s_activeCameras
static void notifyPictureCaptured(JNIEnv *env, jobject, int id, jbyteArray data)
static QRect areaToRect(jobject areaObj)
static void notifyNewPreviewFrame(JNIEnv *env, jobject, int id, jbyteArray data, int width, int height, int format, int bpl)
static JNINativeMethod methods[]
Q_INVOKABLE int getMaxZoom()
Q_INVOKABLE bool reconnect()
Q_INVOKABLE bool setPreviewDisplay(void *surfaceHolder)
Q_INVOKABLE void fetchLastPreviewFrame()
Q_INVOKABLE void updateRotation()
Q_INVOKABLE int getNativeOrientation()
Q_INVOKABLE void startPreview()
Q_INVOKABLE QSize previewSize() const
Q_INVOKABLE bool setPreviewTexture(void *surfaceTexture)
Q_INVOKABLE QList< AndroidCamera::FpsRange > getSupportedPreviewFpsRange()
Q_INVOKABLE void setFlashMode(const QString &value)
Q_INVOKABLE void updatePreviewSize()
Q_INVOKABLE void setExposureCompensation(int value)
Q_INVOKABLE void setPreviewFpsRange(int min, int max)
Q_INVOKABLE void takePicture()
QRecursiveMutex m_parametersMutex
Q_INVOKABLE void setFocusAreas(const QList< QRect > &areas)
Q_INVOKABLE void setupPreviewFrameCallback()
Q_INVOKABLE QSize getPreferredPreviewSizeForVideo()
Q_INVOKABLE void setWhiteBalance(const QString &value)
Q_INVOKABLE void applyParameters()
Q_INVOKABLE QList< QSize > getSupportedVideoSizes()
Q_INVOKABLE void setAutoExposureLock(bool toggle)
Q_INVOKABLE int getMaxNumFocusAreas()
Q_INVOKABLE QString getFlashMode()
Q_INVOKABLE QList< AndroidCamera::ImageFormat > getSupportedPreviewFormats()
Q_INVOKABLE int getZoom()
Q_INVOKABLE QStringList callParametersStringListMethod(const QByteArray &methodName)
Q_INVOKABLE QString getFocusMode()
Q_INVOKABLE bool getAutoExposureLock()
Q_INVOKABLE bool isZoomSupported()
Q_INVOKABLE bool lock()
Q_INVOKABLE int getMaxExposureCompensation()
Q_INVOKABLE QList< int > getZoomRatios()
Q_INVOKABLE float getExposureCompensationStep()
Q_INVOKABLE bool init(int cameraId)
Q_INVOKABLE AndroidCamera::CameraFacing getFacing()
Q_INVOKABLE void setAutoWhiteBalanceLock(bool toggle)
Q_INVOKABLE bool unlock()
Q_INVOKABLE void setZoom(int value)
Q_INVOKABLE QList< QSize > getSupportedPreviewSizes()
void lastPreviewFrameFetched(const QVideoFrame &frame)
Q_INVOKABLE void setPreviewFormat(AndroidCamera::ImageFormat fmt)
Q_INVOKABLE bool isAutoExposureLockSupported()
Q_INVOKABLE bool getAutoWhiteBalanceLock()
Q_INVOKABLE AndroidCamera::FpsRange getPreviewFpsRange()
Q_INVOKABLE void setDisplayOrientation(int degrees)
Q_INVOKABLE int getExposureCompensation()
Q_INVOKABLE void stopPreview()
Q_INVOKABLE AndroidCamera::ImageFormat getPreviewFormat()
Q_INVOKABLE bool isAutoWhiteBalanceLockSupported()
Q_INVOKABLE QList< QSize > getSupportedPictureSizes()
Q_INVOKABLE void autoFocus()
Q_INVOKABLE void setPictureSize(const QSize &size)
Q_INVOKABLE void release()
Q_INVOKABLE void setJpegQuality(int quality)
Q_INVOKABLE QList< QRect > getFocusAreas()
Q_INVOKABLE int getMinExposureCompensation()
Q_INVOKABLE void setFocusMode(const QString &value)
Q_INVOKABLE void notifyNewFrames(bool notify)
Q_INVOKABLE QSize getPreviewSize()
Q_INVOKABLE void cancelAutoFocus()
Q_INVOKABLE QString getWhiteBalance()
Q_INVOKABLE QString getSceneMode()
Q_INVOKABLE void setSceneMode(const QString &value)
void autoFocusStarted()
void setupPreviewFrameCallback()
QJniObject getCameraObject()
ImageFormat getPreviewFormat()
QSize getPreferredPreviewSizeForVideo()
void setPictureSize(const QSize &size)
void setFlashMode(const QString &value)
void previewStarted()
static AndroidCamera::ImageFormat AndroidImageFormatFromQtPixelFormat(QVideoFrameFormat::PixelFormat)
QSize actualPreviewSize()
void takePictureFailed()
int getExposureCompensation()
QString getWhiteBalance()
void setExposureCompensation(int value)
bool getAutoExposureLock()
float getExposureCompensationStep()
QList< QCameraFormat > getSupportedFormats()
void setFocusAreas(const QList< QRect > &areas)
void previewStopped()
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()
void previewSizeChanged()
QJniObject getParametersObject()
void previewFailedToStart()
static QVideoFrameFormat::PixelFormat QtPixelFormatFromAndroidImageFormat(AndroidCamera::ImageFormat)
void setWhiteBalance(const QString &value)
void lastPreviewFrameFetched(const QVideoFrame &frame)
bool setPreviewTexture(AndroidSurfaceTexture *surfaceTexture)
void setAutoExposureLock(bool toggle)
FpsRange getPreviewFpsRange()
void fetchLastPreviewFrame()
void setPreviewFpsRange(FpsRange)
QString getFocusMode()
void setJpegQuality(int quality)
QStringList getSupportedSceneModes()
QList< QSize > getSupportedPictureSizes()
static void getCameraInfo(int id, QCameraDevicePrivate *info)
QList< QSize > getSupportedPreviewSizes()
QString getSceneMode()
int getRotation() const
static AndroidCamera * open(int cameraId)
void setSceneMode(const QString &value)
QList< QSize > getSupportedVideoSizes()
static bool registerNativeMethods()
void setFocusMode(const QString &value)
QString getFlashMode()
QList< ImageFormat > getSupportedPreviewFormats()
void setDisplayOrientation(int degrees)
QSize previewSize() const
QStringList getSupportedWhiteBalance()
int getMinExposureCompensation()
CameraFacing getFacing()
void notifyNewFrames(bool notify)
void whiteBalanceChanged()
void setPreviewSize(const QSize &size)
int getMaxExposureCompensation()
void setPreviewFormat(ImageFormat fmt)
int cameraId() const
QStringList getSupportedFlashModes()
QList< int > getZoomRatios()
void setAutoWhiteBalanceLock(bool toggle)
void setZoom(int value)
bool isAutoExposureLockSupported()
jobject surfaceHolder() const
\inmodule QtCore
Definition qbytearray.h:57
char * data()
\macro QT_NO_CAST_FROM_BYTEARRAY
Definition qbytearray.h:534
static QByteArray number(int, int base=10)
Returns a byte-array representing the whole number n as text.
\inmodule QtCore
Definition qhash.h:818
\inmodule QtCore
\inmodule QtCore
Definition qlist.h:74
qsizetype size() const noexcept
Definition qlist.h:386
bool isEmpty() const noexcept
Definition qlist.h:390
iterator end()
Definition qlist.h:609
const_reference at(qsizetype i) const noexcept
Definition qlist.h:429
iterator begin()
Definition qlist.h:608
void reserve(qsizetype size)
Definition qlist.h:746
void append(parameter_type t)
Definition qlist.h:441
The QMemoryVideoBuffer class provides a system memory allocated video data buffer.
void unlock() noexcept
Unlocks the mutex.
Definition qmutex.h:293
void lock() noexcept
Locks the mutex.
Definition qmutex.h:290
\inmodule QtCore
Definition qobject.h:90
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2823
void deleteLater()
\threadsafe
Definition qobject.cpp:2352
\inmodule QtCore
\inmodule QtCore
\inmodule QtCore\reentrant
Definition qrect.h:30
\inmodule QtCore
Definition qmutex.h:313
const_iterator cend() const noexcept
Definition qset.h:142
const_iterator constFind(const T &value) const
Definition qset.h:161
\inmodule QtCore
Definition qsize.h:25
constexpr int height() const noexcept
Returns the height.
Definition qsize.h:132
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:129
constexpr bool isValid() const noexcept
Returns true if both the width and height is equal to or greater than 0; otherwise returns false.
Definition qsize.h:126
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
const QChar * constData() const
Returns a pointer to the data stored in the QString.
Definition qstring.h:1101
void start(Priority=InheritPriority)
Definition qthread.cpp:923
bool wait(QDeadlineTimer deadline=QDeadlineTimer(QDeadlineTimer::Forever))
Definition qthread.cpp:950
void finished(QPrivateSignal)
void quit()
Definition qthread.cpp:935
void exit(int retcode=0)
Definition qthread.cpp:940
The QVideoFrameFormat class specifies the stream format of a video presentation surface.
PixelFormat
Enumerates video data types.
The QVideoFrame class represents a frame of video data.
Definition qvideoframe.h:26
\inmodule QtCore
QCamera * camera
Definition camera.cpp:19
QSet< QString >::iterator it
rect
[4]
EGLint EGLint * formats
Combined button and popup list for selecting options.
@ BlockingQueuedConnection
@ QueuedConnection
constexpr Initialization Uninitialized
static int arrayLength(const QString &rawType)
Definition provider.cpp:52
QVideoFrameFormat::PixelFormat qt_pixelFormatFromAndroidImageFormat(AndroidCamera::ImageFormat f)
bool qt_androidCheckCameraPermission()
bool qt_sizeLessThan(const QSize &s1, const QSize &s2)
#define Q_UNLIKELY(x)
static QString methodName(const QDBusIntrospection::Method &method)
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
static int area(const QSize &s)
Definition qicon.cpp:152
#define Q_LOGGING_CATEGORY(name,...)
#define qCWarning(category,...)
#define Q_RETURN_ARG(Type, data)
Definition qobjectdefs.h:63
#define Q_ARG(Type, data)
Definition qobjectdefs.h:62
GLint GLsizei GLsizei height
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLenum GLsizei count
GLsizei range
GLint GLsizei width
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLint GLsizei GLsizei GLenum format
void ** params
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
SSL_CTX int(*) void arg)
#define QStringLiteral(str)
#define Q_OBJECT
#define Q_EMIT
#define Q_INVOKABLE
#define Q_SIGNALS
#define emit
int qint32
Definition qtypes.h:44
QVideoFrameFormat::PixelFormat fmt
QList< int > list
[14]
QFileInfo info(fileName)
[8]
QList< QString > stringList
QFrame frame
[0]
char * toString(const MyType &t)
[31]
static bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType, QGenericReturnArgument ret, QGenericArgument val0=QGenericArgument(nullptr), QGenericArgument val1=QGenericArgument(), QGenericArgument val2=QGenericArgument(), QGenericArgument val3=QGenericArgument(), QGenericArgument val4=QGenericArgument(), QGenericArgument val5=QGenericArgument(), QGenericArgument val6=QGenericArgument(), QGenericArgument val7=QGenericArgument(), QGenericArgument val8=QGenericArgument(), QGenericArgument val9=QGenericArgument())
\threadsafe This is an overloaded member function, provided for convenience. It differs from the abov...