7#include <private/qcameradevice_p.h>
9#include <private/qplatformmediaintegration_p.h>
10#include <QtCore/qset.h>
22bool qt_check_exposure_duration(AVCaptureDevice *captureDevice, CMTime duration)
26 AVCaptureDeviceFormat *activeFormat = captureDevice.activeFormat;
32 return CMTimeCompare(duration, activeFormat.minExposureDuration) != -1
33 && CMTimeCompare(activeFormat.maxExposureDuration, duration) != -1;
36bool qt_check_ISO_value(AVCaptureDevice *captureDevice,
int newISO)
40 AVCaptureDeviceFormat *activeFormat = captureDevice.activeFormat;
46 return !(newISO < activeFormat.minISO || newISO > activeFormat.maxISO);
49bool qt_exposure_duration_equal(AVCaptureDevice *captureDevice,
qreal qDuration)
52 const CMTime avDuration = CMTimeMakeWithSeconds(qDuration, captureDevice.exposureDuration.timescale);
53 return !CMTimeCompare(avDuration, captureDevice.exposureDuration);
56bool qt_iso_equal(AVCaptureDevice *captureDevice,
int iso)
62bool qt_exposure_bias_equal(AVCaptureDevice *captureDevice,
qreal bias)
71 AVCaptureExposureMode &avMode)
77 if ([captureDevice isExposureModeSupported:AVCaptureExposureModeContinuousAutoExposure]) {
78 avMode = AVCaptureExposureModeContinuousAutoExposure;
84 if ([captureDevice isExposureModeSupported:AVCaptureExposureModeCustom]) {
85 avMode = AVCaptureExposureModeCustom;
101 NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
102 m_deviceConnectedObserver = [notificationCenter addObserverForName:AVCaptureDeviceWasConnectedNotification
104 queue:[NSOperationQueue mainQueue]
105 usingBlock:^(NSNotification *) {
106 this->updateCameraDevices();
109 m_deviceDisconnectedObserver = [notificationCenter addObserverForName:AVCaptureDeviceWasDisconnectedNotification
111 queue:[NSOperationQueue mainQueue]
112 usingBlock:^(NSNotification *) {
113 this->updateCameraDevices();
115 updateCameraDevices();
120 NSNotificationCenter* notificationCenter = [NSNotificationCenter defaultCenter];
121 [notificationCenter removeObserver:(
id)m_deviceConnectedObserver];
122 [notificationCenter removeObserver:(
id)m_deviceDisconnectedObserver];
127 return m_cameraDevices;
130void QAVFVideoDevices::updateCameraDevices()
134 if (!m_cameraDevices.
isEmpty())
140 AVCaptureDevice *defaultDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
141 NSArray *
videoDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
144 auto info = std::make_unique<QCameraDevicePrivate>();
145 if (defaultDevice && [defaultDevice.uniqueID isEqualToString:
device.uniqueID])
146 info->isDefault = true;
148 info->description = QString::fromNSString([
device localizedName]);
150 qCDebug(qLcCamera) <<
"Handling camera info" <<
info->description
151 << (
info->isDefault ?
"(default)" :
"");
157 if (![
format.mediaType isEqualToString:AVMediaTypeVideo])
160 auto dimensions = CMVideoFormatDescriptionGetDimensions(
format.formatDescription);
161 QSize resolution(dimensions.width, dimensions.height);
162 photoResolutions.
insert(resolution);
164 float maxFrameRate = 0;
165 float minFrameRate = 1.e6;
167 auto encoding = CMVideoFormatDescriptionGetCodecType(
format.formatDescription);
171 qCDebug(qLcCamera) <<
"ignore camera CV format" << encoding
172 <<
"as no matching video format found";
176 for (AVFrameRateRange *frameRateRange
in format.videoSupportedFrameRateRanges) {
177 if (frameRateRange.minFrameRate < minFrameRate)
178 minFrameRate = frameRateRange.minFrameRate;
179 if (frameRateRange.maxFrameRate > maxFrameRate)
180 maxFrameRate = frameRateRange.maxFrameRate;
190 if (!hrRes.isNull() && hrRes.isValid())
191 photoResolutions.
insert(hrRes);
194 qCDebug(qLcCamera) <<
"Add camera format. pixelFormat:" << pixelFormat
195 <<
"cvPixelFormat" << encoding <<
"resolution:" << resolution
196 <<
"frameRate: [" << minFrameRate << maxFrameRate <<
"]";
205 videoFormats <<
f->create();
210 <<
"Skip camera" <<
info->description <<
"without supported formats";
213 info->videoFormats = videoFormats;
214 info->photoResolutions = photoResolutions.
values();
219 if (cameras != m_cameraDevices) {
220 m_cameraDevices = cameras;
275 AVCaptureDevice *
device =
nullptr;
278 device = [AVCaptureDevice deviceWithUniqueID:
279 [NSString stringWithUTF8String:
301 switch (requestedMode) {
305 return AVCaptureFocusModeLocked;
307 return AVCaptureFocusModeContinuousAutoFocus;
321 AVCaptureDevice *captureDevice =
device();
322 if (!captureDevice) {
323 if (qt_focus_mode_supported(
mode)) {
327 <<
"focus mode not supported";
336 <<
"failed to lock for configuration";
340 captureDevice.focusMode = avf_focus_mode(
mode);
355 AVCaptureDevice *captureDevice =
device();
357 AVCaptureFocusMode avMode = avf_focus_mode(
mode);
367 return captureDevice.autoFocusRangeRestrictionSupported
386 AVCaptureDevice *captureDevice =
device();
390 if ([captureDevice isFocusPointOfInterestSupported]) {
397 const CGPoint focusPOI = CGPointMake(point.
x(), point.
y());
398 [captureDevice setFocusPointOfInterest:focusPOI];
400 [captureDevice
setFocusMode:AVCaptureFocusModeAutoFocus];
409 AVCaptureDevice *captureDevice =
device();
413 if (captureDevice.lockingFocusWithCustomLensPositionSupported) {
424 [captureDevice setFocusModeLockedWithLensPosition:
d completionHandler:nil];
434 AVCaptureDevice *captureDevice =
device();
435 if (!captureDevice) {
446 if ([captureDevice isFocusPointOfInterestSupported]) {
448 const CGPoint focusPOI = CGPointMake(point.x(), point.y());
449 [captureDevice setFocusPointOfInterest:focusPOI];
454 const AVCaptureFocusMode avMode = avf_focus_mode(
focusMode());
455 if (captureDevice.focusMode != avMode) {
464 if (!captureDevice.activeFormat) {
465 qCDebug(qLcCamera) <<
Q_FUNC_INFO <<
"camera state is active, but active format is nil";
474 CMTime newDuration = AVCaptureExposureDurationCurrent;
475 bool setCustomMode =
false;
479 && !qt_exposure_duration_equal(captureDevice,
exposureTime)) {
480 newDuration = CMTimeMakeWithSeconds(
exposureTime, captureDevice.exposureDuration.timescale);
481 if (!qt_check_exposure_duration(captureDevice, newDuration)) {
485 setCustomMode =
true;
488 float newISO = AVCaptureISOCurrent;
490 if (iso > 0 && !qt_iso_equal(captureDevice, iso)) {
492 if (!qt_check_ISO_value(captureDevice, newISO)) {
496 setCustomMode =
true;
500 if (
bias != 0 && !qt_exposure_bias_equal(captureDevice,
bias)) {
502 if (bias < captureDevice.minExposureTargetBias || bias > captureDevice.maxExposureTargetBias) {
507 [captureDevice setExposureTargetBias:
bias completionHandler:nil];
515 [captureDevice setExposureModeCustomWithDuration:newDuration
517 completionHandler:nil];
522 AVCaptureExposureMode avMode = AVCaptureExposureModeContinuousAutoExposure;
523 if (!qt_convert_exposure_mode(captureDevice, qtMode, avMode)) {
528 captureDevice.exposureMode = avMode;
531 isFlashSupported = isFlashAutoSupported =
false;
532 isTorchSupported = isTorchAutoSupported =
false;
534 if (captureDevice.hasFlash) {
536 isFlashSupported =
true;
538 isFlashAutoSupported =
true;
541 if (captureDevice.hasTorch) {
543 isTorchSupported =
true;
545 isTorchAutoSupported =
true;
554 QCamera::Features features;
555 AVCaptureDevice *captureDevice =
device();
561 if (captureDevice && [captureDevice isLockingFocusWithCustomLensPositionSupported])
565 if (captureDevice && [captureDevice isFocusPointOfInterestSupported])
580 AVCaptureDevice *captureDevice =
device();
581 if (!captureDevice || !captureDevice.activeFormat)
584 factor =
qBound(captureDevice.minAvailableVideoZoomFactor, factor,
585 captureDevice.activeFormat.videoMaxZoomFactor);
594 captureDevice.videoZoomFactor = factor;
596 [captureDevice rampToVideoZoomFactor:factor withRate:
rate];
623 return isFlashSupported;
625 return isFlashAutoSupported;
633 AVCaptureDevice *captureDevice =
device();
637 if (!captureDevice.hasFlash)
646 return [captureDevice isFlashAvailable];
672 return isTorchSupported;
674 return isTorchAutoSupported;
685 AVCaptureDevice *captureDevice =
device();
686 if (!captureDevice) {
691 AVCaptureExposureMode avMode = AVCaptureExposureModeContinuousAutoExposure;
692 if (!qt_convert_exposure_mode(captureDevice, qtMode, avMode)) {
700 <<
"for configuration";
718 if (@available(macOS 10.15, *)) {
719 AVCaptureDevice *captureDevice =
device();
730 AVCaptureDevice *captureDevice =
device();
731 if (!captureDevice) {
738 if (captureDevice.hasFlash) {
741 auto setAvFlashModeSafe = [&captureDevice](AVCaptureFlashMode avFlashMode) {
745 captureDevice.flashMode = avFlashMode;
747 qCDebug(qLcCamera) <<
"Attempt to setup unsupported flash mode " << avFlashMode;
751 setAvFlashModeSafe(AVCaptureFlashModeOff);
753 if ([captureDevice isFlashAvailable]) {
755 setAvFlashModeSafe(AVCaptureFlashModeOn);
757 setAvFlashModeSafe(AVCaptureFlashModeAuto);
764 if (captureDevice.hasTorch) {
767 auto setAvTorchModeSafe = [&captureDevice](AVCaptureTorchMode avTorchMode) {
769 captureDevice.torchMode = avTorchMode;
771 qCDebug(qLcCamera) <<
"Attempt to setup unsupported torch mode " << avTorchMode;
775 setAvTorchModeSafe(AVCaptureTorchModeOff);
777 if ([captureDevice isTorchAvailable]) {
779 setAvTorchModeSafe(AVCaptureTorchModeOn);
781 setAvTorchModeSafe(AVCaptureTorchModeAuto);
793 AVCaptureDevice *captureDevice =
device();
794 if (!captureDevice) {
799 bias =
qBound(captureDevice.minExposureTargetBias,
bias, captureDevice.maxExposureTargetBias);
807 [captureDevice setExposureTargetBias:
bias completionHandler:nil];
822 AVCaptureDevice *captureDevice =
device();
823 if (!captureDevice) {
828 const CMTime newDuration = CMTimeMakeWithSeconds(
value, captureDevice.exposureDuration.timescale);
829 if (!qt_check_exposure_duration(captureDevice, newDuration)) {
843 [captureDevice setExposureModeCustomWithDuration:newDuration
844 ISO:AVCaptureISOCurrent
845 completionHandler:nil];
857 AVCaptureDevice *captureDevice =
device();
860 auto duration = captureDevice.exposureDuration;
861 return CMTimeGetSeconds(duration);
871 AVCaptureWhiteBalanceMode &avMode)
874 avMode = AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance;
876 avMode = AVCaptureWhiteBalanceModeLocked;
879bool avf_set_white_balance_mode(AVCaptureDevice *captureDevice,
880 AVCaptureWhiteBalanceMode avMode)
884 const bool lock = [captureDevice lockForConfiguration:nil];
886 qDebug() <<
"Failed to lock a capture device for configuration\n";
890 captureDevice.whiteBalanceMode = avMode;
891 [captureDevice unlockForConfiguration];
895bool avf_convert_temp_and_tint_to_wb_gains(AVCaptureDevice *captureDevice,
896 float temp,
float tint, AVCaptureWhiteBalanceGains &wbGains)
900 AVCaptureWhiteBalanceTemperatureAndTintValues wbTTValues = {
904 wbGains = [captureDevice deviceWhiteBalanceGainsForTemperatureAndTintValues:wbTTValues];
906 if (wbGains.redGain >= 1.0 && wbGains.redGain <= captureDevice.maxWhiteBalanceGain
907 && wbGains.greenGain >= 1.0 && wbGains.greenGain <= captureDevice.maxWhiteBalanceGain
908 && wbGains.blueGain >= 1.0 && wbGains.blueGain <= captureDevice.maxWhiteBalanceGain)
914bool avf_set_white_balance_gains(AVCaptureDevice *captureDevice,
915 AVCaptureWhiteBalanceGains wbGains)
917 const bool lock = [captureDevice lockForConfiguration:nil];
919 qDebug() <<
"Failed to lock a capture device for configuration\n";
923 [captureDevice setWhiteBalanceModeLockedWithDeviceWhiteBalanceGains:wbGains
924 completionHandler:nil];
925 [captureDevice unlockForConfiguration];
935 AVCaptureDevice *captureDevice =
device();
946 AVCaptureDevice *captureDevice =
device();
952 <<
"for configuration";
956 AVCaptureWhiteBalanceMode avMode;
957 avf_convert_white_balance_mode(
mode, avMode);
958 avf_set_white_balance_mode(captureDevice, avMode);
966 AVCaptureWhiteBalanceGains wbGains;
967 if (avf_convert_temp_and_tint_to_wb_gains(captureDevice, colorTemp, 0., wbGains)
968 && avf_set_white_balance_gains(captureDevice, wbGains))
974 if (colorTemp == 0) {
979 AVCaptureDevice *captureDevice =
device();
986 <<
"for configuration";
990 AVCaptureWhiteBalanceGains wbGains;
991 if (avf_convert_temp_and_tint_to_wb_gains(captureDevice, colorTemp, 0., wbGains)
992 && avf_set_white_balance_gains(captureDevice, wbGains))
1005 AVCaptureDevice *captureDevice =
device();
1006 if (!captureDevice) {
1011 if (!qt_check_ISO_value(captureDevice,
value)) {
1019 <<
"for configuration";
1025 [captureDevice setExposureModeCustomWithDuration:AVCaptureExposureDurationCurrent
1027 completionHandler:nil];
1041#include "moc_qavfcamerabase_p.cpp"
QSize qt_device_format_high_resolution(AVCaptureDeviceFormat *format)
IOBluetoothDevice * device
virtual int isoSensitivity() const override
void setFocusDistance(float d) override
bool isTorchModeSupported(QCamera::TorchMode mode) const override
void setCamera(const QCameraDevice &camera) override
QCameraDevice m_cameraDevice
bool isFlashModeSupported(QCamera::FlashMode mode) const override
void setManualIsoSensitivity(int value) override
void setExposureMode(QCamera::ExposureMode) override
bool setCameraFormat(const QCameraFormat &format) override
void setActive(bool activce) override
void updateCameraConfiguration()
void setFocusMode(QCamera::FocusMode mode) override
void setCustomFocusPoint(const QPointF &point) override
void setFlashMode(QCamera::FlashMode mode) override
void setManualExposureTime(float value) override
bool isActive() const override
QAVFCameraBase(QCamera *camera)
virtual float exposureTime() const override
void setTorchMode(QCamera::TorchMode mode) override
bool isFlashReady() const override
void zoomTo(float factor, float rate) override
bool isExposureModeSupported(QCamera::ExposureMode mode) const override
AVCaptureDevice * device() const
void updateCameraProperties()
void applyFlashSettings()
void setExposureCompensation(float bias) override
bool isFocusModeSupported(QCamera::FocusMode mode) const override
QList< QCameraDevice > videoDevices() const override
QAVFVideoDevices(QPlatformMediaIntegration *integration)
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
The QCameraDevice class provides general information about camera devices.
bool isNull() const
Returns true if this QCameraDevice is null or invalid.
QList< QCameraFormat > videoFormats
\qmlproperty CameraFormat QtMultimedia::cameraDevice::videoFormats
QByteArray id
\qmlproperty string QtMultimedia::cameraDevice::id
The QCamera class provides interface for system camera devices.
WhiteBalanceMode
\value WhiteBalanceAuto Auto white balance mode.
TorchMode
\value TorchOff Torch is Off.
FocusMode
\value FocusModeAuto Continuous auto focus mode.
FlashMode
\value FlashOff Flash is Off.
ExposureMode
\value ExposureAuto Automatic mode.
bool isEmpty() const noexcept
void append(parameter_type t)
\inmodule QtCore\reentrant
constexpr qreal x() const noexcept
Returns the x coordinate of this point.
constexpr qreal y() const noexcept
Returns the y coordinate of this point.
\inmodule QtCore\reentrant
QList< T > values() const
iterator insert(const T &value)
QVideoFrameFormat::PixelFormat fromCVPixelFormat(unsigned avPixelFormat)
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
#define qCWarning(category,...)
#define qCDebug(category,...)
constexpr const T & qBound(const T &min, const T &val, const T &max)
static bool contains(const QJsonArray &haystack, unsigned needle)
GLint GLsizei GLsizei GLenum format
QFileInfo info(fileName)
[8]
bool contains(const AT &t) const noexcept