summaryrefslogtreecommitdiffstats
path: root/src/plugins/avfoundation
diff options
context:
space:
mode:
authorYoann Lopes <yoann.lopes@theqtcompany.com>2016-03-09 16:26:33 +0100
committerTimur Pocheptsov <timur.pocheptsov@theqtcompany.com>2016-06-14 09:55:13 +0000
commit32b8310e34890b83929f8b143dc9947f370994e3 (patch)
tree3188d31a1f1ade02c4c6e272e73c891749df6814 /src/plugins/avfoundation
parentaf5e0d04852e5efc1ebd9d099f3906bc66a62338 (diff)
AVFoundation: improve changing the capture device format.
Make sure the device format is always set in the same way. We don't actually set the format anymore when it's the same as the current one. We also make sure the frame rate is preserved. Change-Id: I1c68239bc99d9c3cef920effcf47fc253220c26f Reviewed-by: Timur Pocheptsov <timur.pocheptsov@theqtcompany.com>
Diffstat (limited to 'src/plugins/avfoundation')
-rw-r--r--src/plugins/avfoundation/camera/avfcamerautility.h3
-rw-r--r--src/plugins/avfoundation/camera/avfcamerautility.mm50
-rw-r--r--src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.mm10
-rw-r--r--src/plugins/avfoundation/camera/avfimageencodercontrol.mm10
-rw-r--r--src/plugins/avfoundation/camera/avfvideoencodersettingscontrol.mm44
5 files changed, 74 insertions, 43 deletions
diff --git a/src/plugins/avfoundation/camera/avfcamerautility.h b/src/plugins/avfoundation/camera/avfcamerautility.h
index 7a0de4a66..79e9359ec 100644
--- a/src/plugins/avfoundation/camera/avfcamerautility.h
+++ b/src/plugins/avfoundation/camera/avfcamerautility.h
@@ -176,6 +176,9 @@ AVCaptureDeviceFormat *qt_find_best_framerate_match(AVCaptureDevice *captureDevi
Float64 fps);
AVFrameRateRange *qt_find_supported_framerate_range(AVCaptureDeviceFormat *format, Float64 fps);
+bool qt_formats_are_equal(AVCaptureDeviceFormat *f1, AVCaptureDeviceFormat *f2);
+bool qt_set_active_format(AVCaptureDevice *captureDevice, AVCaptureDeviceFormat *format, bool preserveFps);
+
#endif
AVFPSRange qt_current_framerates(AVCaptureDevice *captureDevice, AVCaptureConnection *videoConnection);
diff --git a/src/plugins/avfoundation/camera/avfcamerautility.mm b/src/plugins/avfoundation/camera/avfcamerautility.mm
index 712868d22..4bec1dbe9 100644
--- a/src/plugins/avfoundation/camera/avfcamerautility.mm
+++ b/src/plugins/avfoundation/camera/avfcamerautility.mm
@@ -380,6 +380,56 @@ AVFrameRateRange *qt_find_supported_framerate_range(AVCaptureDeviceFormat *forma
return match;
}
+bool qt_formats_are_equal(AVCaptureDeviceFormat *f1, AVCaptureDeviceFormat *f2)
+{
+ if (f1 == f2)
+ return true;
+
+ if (![f1.mediaType isEqualToString:f2.mediaType])
+ return false;
+
+ return CMFormatDescriptionEqual(f1.formatDescription, f2.formatDescription);
+}
+
+bool qt_set_active_format(AVCaptureDevice *captureDevice, AVCaptureDeviceFormat *format, bool preserveFps)
+{
+ static bool firstSet = true;
+
+ if (!captureDevice || !format)
+ return false;
+
+ if (qt_formats_are_equal(captureDevice.activeFormat, format)) {
+ if (firstSet) {
+ // The capture device format is persistent. The first time we set a format, report that
+ // it changed even if the formats are the same.
+ // This prevents the session from resetting the format to the default value.
+ firstSet = false;
+ return true;
+ }
+ return false;
+ }
+
+ firstSet = false;
+
+ const AVFConfigurationLock lock(captureDevice);
+ if (!lock) {
+ qWarning("Failed to set active format (lock failed)");
+ return false;
+ }
+
+ // Changing the activeFormat resets the frame rate.
+ AVFPSRange fps;
+ if (preserveFps)
+ fps = qt_current_framerates(captureDevice, nil);
+
+ captureDevice.activeFormat = format;
+
+ if (preserveFps)
+ qt_set_framerate_limits(captureDevice, nil, fps.first, fps.second);
+
+ return true;
+}
+
#endif // SDK
void qt_set_framerate_limits(AVCaptureConnection *videoConnection, qreal minFPS, qreal maxFPS)
diff --git a/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.mm b/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.mm
index 1d2539893..14f146d25 100644
--- a/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.mm
+++ b/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.mm
@@ -382,15 +382,7 @@ bool AVFCameraViewfinderSettingsControl2::applySettings(const QCameraViewfinderS
#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0)
AVCaptureDeviceFormat *match = findBestFormatMatch(settings);
if (match) {
- if (match != captureDevice.activeFormat) {
- const AVFConfigurationLock lock(captureDevice);
- if (lock) {
- captureDevice.activeFormat = match;
- activeFormatChanged = true;
- } else {
- qDebugCamera() << Q_FUNC_INFO << "failed to lock for configuration";
- }
- }
+ activeFormatChanged = qt_set_active_format(captureDevice, match, false);
} else {
qDebugCamera() << Q_FUNC_INFO << "matching device format not found";
// We still can update the pixel format at least.
diff --git a/src/plugins/avfoundation/camera/avfimageencodercontrol.mm b/src/plugins/avfoundation/camera/avfimageencodercontrol.mm
index b35008030..20de4b5e8 100644
--- a/src/plugins/avfoundation/camera/avfimageencodercontrol.mm
+++ b/src/plugins/avfoundation/camera/avfimageencodercontrol.mm
@@ -227,15 +227,7 @@ bool AVFImageEncoderControl::applySettings()
return false;
}
- if (match != captureDevice.activeFormat) {
- const AVFConfigurationLock lock(captureDevice);
- if (!lock) {
- qDebugCamera() << Q_FUNC_INFO << "failed to lock for configuration";
- return false;
- }
- captureDevice.activeFormat = match;
- activeFormatChanged = true;
- }
+ activeFormatChanged = qt_set_active_format(captureDevice, match, true);
#if defined(Q_OS_IOS) && QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_8_0)
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_8_0) {
diff --git a/src/plugins/avfoundation/camera/avfvideoencodersettingscontrol.mm b/src/plugins/avfoundation/camera/avfvideoencodersettingscontrol.mm
index 87bc91129..248997d57 100644
--- a/src/plugins/avfoundation/camera/avfvideoencodersettingscontrol.mm
+++ b/src/plugins/avfoundation/camera/avfvideoencodersettingscontrol.mm
@@ -215,6 +215,10 @@ NSDictionary *AVFVideoEncoderSettingsControl::applySettings(AVCaptureConnection
if (!device)
return nil;
+ AVFPSRange currentFps = qt_current_framerates(device, connection);
+ const bool needFpsChange = m_requestedSettings.frameRate() > 0
+ && m_requestedSettings.frameRate() != currentFps.second;
+
NSMutableDictionary *videoSettings = [NSMutableDictionary dictionary];
// -- Codec
@@ -234,8 +238,8 @@ NSDictionary *AVFVideoEncoderSettingsControl::applySettings(AVCaptureConnection
int h = m_requestedSettings.resolution().height();
#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0)
- if (device.activeFormat) {
- CMFormatDescriptionRef formatDesc = device.activeFormat.formatDescription;
+ if (AVCaptureDeviceFormat *currentFormat = device.activeFormat) {
+ CMFormatDescriptionRef formatDesc = currentFormat.formatDescription;
CMVideoDimensions dim = CMVideoFormatDescriptionGetDimensions(formatDesc);
// We have to change the device's activeFormat in 3 cases:
@@ -245,7 +249,7 @@ NSDictionary *AVFVideoEncoderSettingsControl::applySettings(AVCaptureConnection
AVCaptureDeviceFormat *newFormat = nil;
if ((w <= 0 || h <= 0)
&& m_requestedSettings.frameRate() > 0
- && !format_supports_framerate(device.activeFormat, m_requestedSettings.frameRate())) {
+ && !format_supports_framerate(currentFormat, m_requestedSettings.frameRate())) {
newFormat = qt_find_best_framerate_match(device,
m_service->session()->defaultCodec(),
@@ -267,17 +271,10 @@ NSDictionary *AVFVideoEncoderSettingsControl::applySettings(AVCaptureConnection
}
}
- if (newFormat && newFormat != device.activeFormat) {
- const AVFConfigurationLock lock(device);
- if (lock) {
- m_restoreFormat = [device.activeFormat retain];
- m_restoreFps = qt_current_framerates(device, connection);
-
- device.activeFormat = newFormat;
-
- formatDesc = newFormat.formatDescription;
- dim = CMVideoFormatDescriptionGetDimensions(formatDesc);
- }
+ if (qt_set_active_format(device, newFormat, !needFpsChange)) {
+ m_restoreFormat = [currentFormat retain];
+ formatDesc = newFormat.formatDescription;
+ dim = CMVideoFormatDescriptionGetDimensions(formatDesc);
}
if (w > 0 && h > 0) {
@@ -313,14 +310,12 @@ NSDictionary *AVFVideoEncoderSettingsControl::applySettings(AVCaptureConnection
// -- FPS
- const qreal fps = m_requestedSettings.frameRate();
- if (fps > qreal(0)) {
- if (!m_restoreFps.first && !m_restoreFps.second)
- m_restoreFps = qt_current_framerates(device, connection);
+ if (needFpsChange) {
+ m_restoreFps = currentFps;
+ const qreal fps = m_requestedSettings.frameRate();
qt_set_framerate_limits(device, connection, fps, fps);
}
- AVFPSRange currentFps = qt_current_framerates(device, connection);
- m_actualSettings.setFrameRate(currentFps.second);
+ m_actualSettings.setFrameRate(qt_current_framerates(device, connection).second);
// -- Codec Settings
@@ -379,18 +374,17 @@ void AVFVideoEncoderSettingsControl::unapplySettings(AVCaptureConnection *connec
if (!device)
return;
+ const bool needFpsChanged = m_restoreFps.first || m_restoreFps.second;
+
#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0)
if (m_restoreFormat) {
- const AVFConfigurationLock lock(device);
- if (lock)
- device.activeFormat = m_restoreFormat;
-
+ qt_set_active_format(device, m_restoreFormat, !needFpsChanged);
[m_restoreFormat release];
m_restoreFormat = nil;
}
#endif
- if (m_restoreFps.first || m_restoreFps.second) {
+ if (needFpsChanged) {
qt_set_framerate_limits(device, connection, m_restoreFps.first, m_restoreFps.second);
m_restoreFps = AVFPSRange();
}