diff options
Diffstat (limited to 'src/plugins/avfoundation')
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(); } |