summaryrefslogtreecommitdiffstats
path: root/src/plugins/avfoundation/camera
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@theqtcompany.com>2016-01-07 11:13:47 +0100
committerLiang Qi <liang.qi@theqtcompany.com>2016-01-07 11:13:47 +0100
commit6166f102f5e52007f8e4e018adb73d26513557b3 (patch)
treeab6dcd29f68e07cf8c6643d69af679ed9b194019 /src/plugins/avfoundation/camera
parent0a7b553eeab0b81502189f6244ffc65c33cdaaa0 (diff)
parent604a5753fa2d9b8e1ef65ccd8c5fb72465462479 (diff)
Merge remote-tracking branch 'origin/5.5' into 5.6
Conflicts: src/plugins/android/src/wrappers/jni/androidcamera.cpp Change-Id: Ibb34f710b1dfb9a23b378462f31432581c6c26f4
Diffstat (limited to 'src/plugins/avfoundation/camera')
-rw-r--r--src/plugins/avfoundation/camera/avfcamerasession.h4
-rw-r--r--src/plugins/avfoundation/camera/avfcamerasession.mm34
-rw-r--r--src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.h10
-rw-r--r--src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.mm228
-rw-r--r--src/plugins/avfoundation/camera/avfimageencodercontrol.h4
-rw-r--r--src/plugins/avfoundation/camera/avfimageencodercontrol.mm30
-rw-r--r--src/plugins/avfoundation/camera/avfmediarecordercontrol.mm9
7 files changed, 172 insertions, 147 deletions
diff --git a/src/plugins/avfoundation/camera/avfcamerasession.h b/src/plugins/avfoundation/camera/avfcamerasession.h
index 838234522..13a8a35c5 100644
--- a/src/plugins/avfoundation/camera/avfcamerasession.h
+++ b/src/plugins/avfoundation/camera/avfcamerasession.h
@@ -105,8 +105,8 @@ Q_SIGNALS:
private:
static void updateCameraDevices();
void attachVideoInputDevice();
- void applyImageEncoderSettings();
- void applyViewfinderSettings();
+ bool applyImageEncoderSettings();
+ bool applyViewfinderSettings();
static int m_defaultCameraIndex;
static QList<AVFCameraInfo> m_cameraDevices;
diff --git a/src/plugins/avfoundation/camera/avfcamerasession.mm b/src/plugins/avfoundation/camera/avfcamerasession.mm
index 66dc43d81..993e28319 100644
--- a/src/plugins/avfoundation/camera/avfcamerasession.mm
+++ b/src/plugins/avfoundation/camera/avfcamerasession.mm
@@ -285,10 +285,23 @@ void AVFCameraSession::setState(QCamera::State newState)
Q_EMIT readyToConfigureConnections();
m_defaultCodec = 0;
defaultCodec();
- applyImageEncoderSettings();
- applyViewfinderSettings();
+
+ bool activeFormatSet = applyImageEncoderSettings();
+ activeFormatSet |= applyViewfinderSettings();
+
[m_captureSession commitConfiguration];
+
+ if (activeFormatSet) {
+ // According to the doc, the capture device must be locked before
+ // startRunning to prevent the format we set to be overriden by the
+ // session preset.
+ [videoCaptureDevice() lockForConfiguration:nil];
+ }
+
[m_captureSession startRunning];
+
+ if (activeFormatSet)
+ [videoCaptureDevice() unlockForConfiguration];
}
if (oldState == QCamera::ActiveState) {
@@ -357,27 +370,32 @@ void AVFCameraSession::attachVideoInputDevice()
}
}
-void AVFCameraSession::applyImageEncoderSettings()
+bool AVFCameraSession::applyImageEncoderSettings()
{
if (AVFImageEncoderControl *control = m_service->imageEncoderControl())
- control->applySettings();
+ return control->applySettings();
+
+ return false;
}
-void AVFCameraSession::applyViewfinderSettings()
+bool AVFCameraSession::applyViewfinderSettings()
{
if (AVFCameraViewfinderSettingsControl2 *vfControl = m_service->viewfinderSettingsControl2()) {
QCameraViewfinderSettings vfSettings(vfControl->requestedSettings());
+ // Viewfinder and image capture solutions must be the same, if an image capture
+ // resolution is set, it takes precedence over the viewfinder resolution.
if (AVFImageEncoderControl *imControl = m_service->imageEncoderControl()) {
- const QSize imageResolution(imControl->imageSettings().resolution());
+ const QSize imageResolution(imControl->requestedSettings().resolution());
if (!imageResolution.isNull() && imageResolution.isValid()) {
vfSettings.setResolution(imageResolution);
vfControl->setViewfinderSettings(vfSettings);
- return;
}
}
- vfControl->applySettings();
+ return vfControl->applySettings();
}
+
+ return false;
}
void AVFCameraSession::addProbe(AVFMediaVideoProbeControl *probe)
diff --git a/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.h b/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.h
index cf2f512a7..9a5bbd5de 100644
--- a/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.h
+++ b/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.h
@@ -76,17 +76,13 @@ private:
AVCaptureDeviceFormat *findBestFormatMatch(const QCameraViewfinderSettings &settings) const;
QVector<QVideoFrame::PixelFormat> viewfinderPixelFormats() const;
bool convertPixelFormatIfSupported(QVideoFrame::PixelFormat format, unsigned &avfFormat) const;
- void applySettings();
+ bool applySettings();
QCameraViewfinderSettings requestedSettings() const;
- // Aux. function to extract things like captureDevice, videoOutput, etc.
- bool updateAVFoundationObjects() const;
+
+ AVCaptureConnection *videoConnection() const;
AVFCameraService *m_service;
- mutable AVFCameraSession *m_session;
QCameraViewfinderSettings m_settings;
- mutable AVCaptureDevice *m_captureDevice;
- mutable AVCaptureVideoDataOutput *m_videoOutput;
- mutable AVCaptureConnection *m_videoConnection;
};
class AVFCameraViewfinderSettingsControl : public QCameraViewfinderSettingsControl
diff --git a/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.mm b/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.mm
index c5da1c343..3c20801e5 100644
--- a/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.mm
+++ b/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.mm
@@ -206,7 +206,6 @@ void qt_set_framerate_limits(AVCaptureDevice *captureDevice,
AVFPSRange qt_current_framerates(AVCaptureDevice *captureDevice, AVCaptureConnection *videoConnection)
{
Q_ASSERT(captureDevice);
- Q_ASSERT(videoConnection);
AVFPSRange fps;
#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0)
@@ -234,7 +233,8 @@ AVFPSRange qt_current_framerates(AVCaptureDevice *captureDevice, AVCaptureConnec
#else // OSX < 10.7 or iOS < 7.0
{
#endif // QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0)
- fps = qt_connection_framerates(videoConnection);
+ if (videoConnection)
+ fps = qt_connection_framerates(videoConnection);
}
return fps;
@@ -244,24 +244,20 @@ void qt_set_framerate_limits(AVCaptureDevice *captureDevice, AVCaptureConnection
const QCameraViewfinderSettings &settings)
{
Q_ASSERT(captureDevice);
- Q_ASSERT(videoConnection);
#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0)
if (QSysInfo::MacintoshVersion >= qt_OS_limit(QSysInfo::MV_10_9, QSysInfo::MV_IOS_7_0))
qt_set_framerate_limits(captureDevice, settings);
else
- qt_set_framerate_limits(videoConnection, settings);
-#else
- qt_set_framerate_limits(videoConnection, settings);
#endif
+ if (videoConnection)
+ qt_set_framerate_limits(videoConnection, settings);
+
}
} // Unnamed namespace.
AVFCameraViewfinderSettingsControl2::AVFCameraViewfinderSettingsControl2(AVFCameraService *service)
- : m_service(service),
- m_captureDevice(0),
- m_videoOutput(0),
- m_videoConnection(0)
+ : m_service(service)
{
Q_ASSERT(service);
}
@@ -270,8 +266,9 @@ QList<QCameraViewfinderSettings> AVFCameraViewfinderSettingsControl2::supportedV
{
QList<QCameraViewfinderSettings> supportedSettings;
- if (!updateAVFoundationObjects()) {
- qDebugCamera() << Q_FUNC_INFO << "no capture device or video output found";
+ AVCaptureDevice *captureDevice = m_service->session()->videoCaptureDevice();
+ if (!captureDevice) {
+ qDebugCamera() << Q_FUNC_INFO << "no capture device found";
return supportedSettings;
}
@@ -281,15 +278,16 @@ QList<QCameraViewfinderSettings> AVFCameraViewfinderSettingsControl2::supportedV
if (!pixelFormats.size())
pixelFormats << QVideoFrame::Format_Invalid; // The default value.
+
#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0)
if (QSysInfo::MacintoshVersion >= qt_OS_limit(QSysInfo::MV_10_7, QSysInfo::MV_IOS_7_0)) {
- if (!m_captureDevice.formats || !m_captureDevice.formats.count) {
+ if (!captureDevice.formats || !captureDevice.formats.count) {
qDebugCamera() << Q_FUNC_INFO << "no capture device formats found";
return supportedSettings;
}
- const QVector<AVCaptureDeviceFormat *> formats(qt_unique_device_formats(m_captureDevice,
- m_session->defaultCodec()));
+ const QVector<AVCaptureDeviceFormat *> formats(qt_unique_device_formats(captureDevice,
+ m_service->session()->defaultCodec()));
for (int i = 0; i < formats.size(); ++i) {
AVCaptureDeviceFormat *format = formats[i];
@@ -320,15 +318,18 @@ QList<QCameraViewfinderSettings> AVFCameraViewfinderSettingsControl2::supportedV
#else
{
#endif
- // TODO: resolution and PAR.
- framerates << qt_connection_framerates(m_videoConnection);
- for (int i = 0; i < pixelFormats.size(); ++i) {
- for (int j = 0; j < framerates.size(); ++j) {
- QCameraViewfinderSettings newSet;
- newSet.setPixelFormat(pixelFormats[i]);
- newSet.setMinimumFrameRate(framerates[j].first);
- newSet.setMaximumFrameRate(framerates[j].second);
- supportedSettings << newSet;
+ AVCaptureConnection *connection = videoConnection();
+ if (connection) {
+ // TODO: resolution and PAR.
+ framerates << qt_connection_framerates(connection);
+ for (int i = 0; i < pixelFormats.size(); ++i) {
+ for (int j = 0; j < framerates.size(); ++j) {
+ QCameraViewfinderSettings newSet;
+ newSet.setPixelFormat(pixelFormats[i]);
+ newSet.setMinimumFrameRate(framerates[j].first);
+ newSet.setMaximumFrameRate(framerates[j].second);
+ supportedSettings << newSet;
+ }
}
}
}
@@ -340,20 +341,21 @@ QCameraViewfinderSettings AVFCameraViewfinderSettingsControl2::viewfinderSetting
{
QCameraViewfinderSettings settings;
- if (!updateAVFoundationObjects()) {
- qDebugCamera() << Q_FUNC_INFO << "no capture device or video output found";
+ AVCaptureDevice *captureDevice = m_service->session()->videoCaptureDevice();
+ if (!captureDevice) {
+ qDebugCamera() << Q_FUNC_INFO << "no capture device found";
return settings;
}
#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0)
if (QSysInfo::MacintoshVersion >= qt_OS_limit(QSysInfo::MV_10_7, QSysInfo::MV_IOS_7_0)) {
- if (!m_captureDevice.activeFormat) {
+ if (!captureDevice.activeFormat) {
qDebugCamera() << Q_FUNC_INFO << "no active capture device format";
return settings;
}
- const QSize res(qt_device_format_resolution(m_captureDevice.activeFormat));
- const QSize par(qt_device_format_pixel_aspect_ratio(m_captureDevice.activeFormat));
+ const QSize res(qt_device_format_resolution(captureDevice.activeFormat));
+ const QSize par(qt_device_format_pixel_aspect_ratio(captureDevice.activeFormat));
if (res.isNull() || !res.isValid() || par.isNull() || !par.isValid()) {
qDebugCamera() << Q_FUNC_INFO << "failed to obtain resolution/pixel aspect ratio";
return settings;
@@ -364,12 +366,14 @@ QCameraViewfinderSettings AVFCameraViewfinderSettingsControl2::viewfinderSetting
}
#endif
// TODO: resolution and PAR before 7.0.
- const AVFPSRange fps = qt_current_framerates(m_captureDevice, m_videoConnection);
+ const AVFPSRange fps = qt_current_framerates(captureDevice, videoConnection());
settings.setMinimumFrameRate(fps.first);
settings.setMaximumFrameRate(fps.second);
- if (NSObject *obj = [m_videoOutput.videoSettings objectForKey:(id)kCVPixelBufferPixelFormatTypeKey]) {
- if ([obj isKindOfClass:[NSNumber class]]) {
+ AVCaptureVideoDataOutput *videoOutput = m_service->videoOutput() ? m_service->videoOutput()->videoDataOutput() : 0;
+ if (videoOutput) {
+ NSObject *obj = [videoOutput.videoSettings objectForKey:(id)kCVPixelBufferPixelFormatTypeKey];
+ if (obj && [obj isKindOfClass:[NSNumber class]]) {
NSNumber *nsNum = static_cast<NSNumber *>(obj);
settings.setPixelFormat(QtPixelFormatFromCVFormat([nsNum unsignedIntValue]));
}
@@ -380,11 +384,6 @@ QCameraViewfinderSettings AVFCameraViewfinderSettingsControl2::viewfinderSetting
void AVFCameraViewfinderSettingsControl2::setViewfinderSettings(const QCameraViewfinderSettings &settings)
{
- if (settings.isNull()) {
- qDebugCamera() << Q_FUNC_INFO << "empty viewfinder settings";
- return;
- }
-
if (m_settings == settings)
return;
@@ -449,17 +448,19 @@ bool AVFCameraViewfinderSettingsControl2::CVPixelFormatFromQtFormat(QVideoFrame:
AVCaptureDeviceFormat *AVFCameraViewfinderSettingsControl2::findBestFormatMatch(const QCameraViewfinderSettings &settings) const
{
+ AVCaptureDevice *captureDevice = m_service->session()->videoCaptureDevice();
+ if (!captureDevice || settings.isNull())
+ return nil;
+
#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0)
if (QSysInfo::MacintoshVersion >= qt_OS_limit(QSysInfo::MV_10_7, QSysInfo::MV_IOS_7_0)) {
- Q_ASSERT(m_captureDevice);
- Q_ASSERT(m_session);
const QSize &resolution = settings.resolution();
if (!resolution.isNull() && resolution.isValid()) {
// Either the exact match (including high resolution for images on iOS)
// or a format with a resolution close to the requested one.
- return qt_find_best_resolution_match(m_captureDevice, resolution,
- m_session->defaultCodec());
+ return qt_find_best_resolution_match(captureDevice, resolution,
+ m_service->session()->defaultCodec());
}
// No resolution requested, what about framerates?
@@ -472,22 +473,28 @@ AVCaptureDeviceFormat *AVFCameraViewfinderSettingsControl2::findBestFormatMatch(
const qreal minFPS(settings.minimumFrameRate());
const qreal maxFPS(settings.maximumFrameRate());
if (minFPS || maxFPS)
- return qt_find_best_framerate_match(m_captureDevice, maxFPS ? maxFPS : minFPS,
- m_session->defaultCodec());
+ return qt_find_best_framerate_match(captureDevice, maxFPS ? maxFPS : minFPS,
+ m_service->session()->defaultCodec());
// Ignore PAR for the moment (PAR without resolution can
// pick a format with really bad resolution).
// No need to test pixel format, just return settings.
}
#endif
+
return nil;
}
QVector<QVideoFrame::PixelFormat> AVFCameraViewfinderSettingsControl2::viewfinderPixelFormats() const
{
- Q_ASSERT(m_videoOutput);
-
QVector<QVideoFrame::PixelFormat> qtFormats;
- NSArray *pixelFormats = [m_videoOutput availableVideoCVPixelFormatTypes];
+
+ AVCaptureVideoDataOutput *videoOutput = m_service->videoOutput() ? m_service->videoOutput()->videoDataOutput() : 0;
+ if (!videoOutput) {
+ qDebugCamera() << Q_FUNC_INFO << "no video output found";
+ return qtFormats;
+ }
+
+ NSArray *pixelFormats = [videoOutput availableVideoCVPixelFormatTypes];
for (NSObject *obj in pixelFormats) {
if (![obj isKindOfClass:[NSNumber class]])
@@ -508,17 +515,19 @@ QVector<QVideoFrame::PixelFormat> AVFCameraViewfinderSettingsControl2::viewfinde
bool AVFCameraViewfinderSettingsControl2::convertPixelFormatIfSupported(QVideoFrame::PixelFormat qtFormat,
unsigned &avfFormat)const
{
- Q_ASSERT(m_videoOutput);
+ AVCaptureVideoDataOutput *videoOutput = m_service->videoOutput() ? m_service->videoOutput()->videoDataOutput() : 0;
+ if (!videoOutput)
+ return false;
unsigned conv = 0;
if (!CVPixelFormatFromQtFormat(qtFormat, conv))
return false;
- NSArray *formats = [m_videoOutput availableVideoCVPixelFormatTypes];
+ NSArray *formats = [videoOutput availableVideoCVPixelFormatTypes];
if (!formats || !formats.count)
return false;
- if (m_service->videoOutput() && m_service->videoOutput()->surface()) {
+ if (m_service->videoOutput()->surface()) {
const QAbstractVideoSurface *surface = m_service->videoOutput()->surface();
if (!surface->supportedPixelFormats().contains(qtFormat))
return false;
@@ -539,31 +548,30 @@ bool AVFCameraViewfinderSettingsControl2::convertPixelFormatIfSupported(QVideoFr
return found;
}
-void AVFCameraViewfinderSettingsControl2::applySettings()
+bool AVFCameraViewfinderSettingsControl2::applySettings()
{
- if (m_settings.isNull())
- return;
+ if (m_service->session()->state() != QCamera::LoadedState &&
+ m_service->session()->state() != QCamera::ActiveState) {
+ return false;
+ }
- if (!updateAVFoundationObjects())
- return;
+ AVCaptureDevice *captureDevice = m_service->session()->videoCaptureDevice();
+ if (!captureDevice)
+ return false;
- if (m_session->state() != QCamera::LoadedState &&
- m_session->state() != QCamera::ActiveState) {
- return;
- }
+ bool activeFormatChanged = false;
- NSMutableDictionary *videoSettings = [NSMutableDictionary dictionaryWithCapacity:1];
#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0)
AVCaptureDeviceFormat *match = findBestFormatMatch(m_settings);
if (match) {
- if (match != m_captureDevice.activeFormat) {
- const AVFConfigurationLock lock(m_captureDevice);
- if (!lock) {
+ 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";
- return;
}
-
- m_captureDevice.activeFormat = match;
}
} else {
qDebugCamera() << Q_FUNC_INFO << "matching device format not found";
@@ -571,43 +579,48 @@ void AVFCameraViewfinderSettingsControl2::applySettings()
}
#endif
- unsigned avfPixelFormat = 0;
- if (!convertPixelFormatIfSupported(m_settings.pixelFormat(), avfPixelFormat)) {
- // If the the pixel format is not specified or invalid, pick the preferred video surface
- // format, or if no surface is set, the preferred capture device format
-
- const QVector<QVideoFrame::PixelFormat> deviceFormats = viewfinderPixelFormats();
- QVideoFrame::PixelFormat pickedFormat = deviceFormats.first();
-
- QAbstractVideoSurface *surface = m_service->videoOutput() ? m_service->videoOutput()->surface()
- : 0;
- if (surface) {
- if (m_service->videoOutput()->supportsTextures()) {
- pickedFormat = QVideoFrame::Format_ARGB32;
- } else {
- QList<QVideoFrame::PixelFormat> surfaceFormats = m_service->videoOutput()->surface()->supportedPixelFormats();
-
- for (int i = 0; i < surfaceFormats.count(); ++i) {
- const QVideoFrame::PixelFormat surfaceFormat = surfaceFormats.at(i);
- if (deviceFormats.contains(surfaceFormat)) {
- pickedFormat = surfaceFormat;
- break;
+ AVCaptureVideoDataOutput *videoOutput = m_service->videoOutput() ? m_service->videoOutput()->videoDataOutput() : 0;
+ if (videoOutput) {
+ unsigned avfPixelFormat = 0;
+ if (!convertPixelFormatIfSupported(m_settings.pixelFormat(), avfPixelFormat)) {
+ // If the the pixel format is not specified or invalid, pick the preferred video surface
+ // format, or if no surface is set, the preferred capture device format
+
+ const QVector<QVideoFrame::PixelFormat> deviceFormats = viewfinderPixelFormats();
+ QVideoFrame::PixelFormat pickedFormat = deviceFormats.first();
+
+ QAbstractVideoSurface *surface = m_service->videoOutput()->surface();
+ if (surface) {
+ if (m_service->videoOutput()->supportsTextures()) {
+ pickedFormat = QVideoFrame::Format_ARGB32;
+ } else {
+ QList<QVideoFrame::PixelFormat> surfaceFormats = surface->supportedPixelFormats();
+
+ for (int i = 0; i < surfaceFormats.count(); ++i) {
+ const QVideoFrame::PixelFormat surfaceFormat = surfaceFormats.at(i);
+ if (deviceFormats.contains(surfaceFormat)) {
+ pickedFormat = surfaceFormat;
+ break;
+ }
}
}
}
- }
- CVPixelFormatFromQtFormat(pickedFormat, avfPixelFormat);
- }
+ CVPixelFormatFromQtFormat(pickedFormat, avfPixelFormat);
+ }
- if (avfPixelFormat != 0) {
- [videoSettings setObject:[NSNumber numberWithUnsignedInt:avfPixelFormat]
- forKey:(id)kCVPixelBufferPixelFormatTypeKey];
+ if (avfPixelFormat != 0) {
+ NSMutableDictionary *videoSettings = [NSMutableDictionary dictionaryWithCapacity:1];
+ [videoSettings setObject:[NSNumber numberWithUnsignedInt:avfPixelFormat]
+ forKey:(id)kCVPixelBufferPixelFormatTypeKey];
- m_videoOutput.videoSettings = videoSettings;
+ videoOutput.videoSettings = videoSettings;
+ }
}
- qt_set_framerate_limits(m_captureDevice, m_videoConnection, m_settings);
+ qt_set_framerate_limits(captureDevice, videoConnection(), m_settings);
+
+ return activeFormatChanged;
}
QCameraViewfinderSettings AVFCameraViewfinderSettingsControl2::requestedSettings() const
@@ -615,33 +628,12 @@ QCameraViewfinderSettings AVFCameraViewfinderSettingsControl2::requestedSettings
return m_settings;
}
-bool AVFCameraViewfinderSettingsControl2::updateAVFoundationObjects() const
+AVCaptureConnection *AVFCameraViewfinderSettingsControl2::videoConnection() const
{
- m_session = 0;
- m_captureDevice = 0;
- m_videoOutput = 0;
- m_videoConnection = 0;
-
- if (!m_service->session())
- return false;
-
- if (!m_service->session()->videoCaptureDevice())
- return false;
-
if (!m_service->videoOutput() || !m_service->videoOutput()->videoDataOutput())
- return false;
-
- AVCaptureVideoDataOutput *output = m_service->videoOutput()->videoDataOutput();
- AVCaptureConnection *connection = [output connectionWithMediaType:AVMediaTypeVideo];
- if (!connection)
- return false;
-
- m_session = m_service->session();
- m_captureDevice = m_session->videoCaptureDevice();
- m_videoOutput = output;
- m_videoConnection = connection;
+ return nil;
- return true;
+ return [m_service->videoOutput()->videoDataOutput() connectionWithMediaType:AVMediaTypeVideo];
}
AVFCameraViewfinderSettingsControl::AVFCameraViewfinderSettingsControl(AVFCameraService *service)
diff --git a/src/plugins/avfoundation/camera/avfimageencodercontrol.h b/src/plugins/avfoundation/camera/avfimageencodercontrol.h
index fcb665a03..d3af77ffd 100644
--- a/src/plugins/avfoundation/camera/avfimageencodercontrol.h
+++ b/src/plugins/avfoundation/camera/avfimageencodercontrol.h
@@ -62,11 +62,13 @@ public:
QImageEncoderSettings imageSettings() const Q_DECL_OVERRIDE;
void setImageSettings(const QImageEncoderSettings &settings) Q_DECL_OVERRIDE;
+ QImageEncoderSettings requestedSettings() const;
+
private:
AVFCameraService *m_service;
QImageEncoderSettings m_settings;
- void applySettings();
+ bool applySettings();
bool videoCaptureDeviceIsValid() const;
};
diff --git a/src/plugins/avfoundation/camera/avfimageencodercontrol.mm b/src/plugins/avfoundation/camera/avfimageencodercontrol.mm
index 36050c3a2..e2eb0bd01 100644
--- a/src/plugins/avfoundation/camera/avfimageencodercontrol.mm
+++ b/src/plugins/avfoundation/camera/avfimageencodercontrol.mm
@@ -115,6 +115,11 @@ QList<QSize> AVFImageEncoderControl::supportedResolutions(const QImageEncoderSet
return resolutions;
}
+QImageEncoderSettings AVFImageEncoderControl::requestedSettings() const
+{
+ return m_settings;
+}
+
QImageEncoderSettings AVFImageEncoderControl::imageSettings() const
{
QImageEncoderSettings settings;
@@ -163,40 +168,40 @@ QImageEncoderSettings AVFImageEncoderControl::imageSettings() const
void AVFImageEncoderControl::setImageSettings(const QImageEncoderSettings &settings)
{
- if (m_settings == settings || settings.isNull())
+ if (m_settings == settings)
return;
m_settings = settings;
applySettings();
}
-void AVFImageEncoderControl::applySettings()
+bool AVFImageEncoderControl::applySettings()
{
if (!videoCaptureDeviceIsValid())
- return;
+ return false;
AVFCameraSession *session = m_service->session();
if (!session || (session->state() != QCamera::ActiveState
&& session->state() != QCamera::LoadedState)) {
- return;
+ return false;
}
if (!m_service->imageCaptureControl()
|| !m_service->imageCaptureControl()->stillImageOutput()) {
qDebugCamera() << Q_FUNC_INFO << "no still image output";
- return;
+ return false;
}
if (m_settings.codec().size()
&& m_settings.codec() != QLatin1String("jpeg")) {
qDebugCamera() << Q_FUNC_INFO << "unsupported codec:" << m_settings.codec();
- return;
+ return false;
}
QSize res(m_settings.resolution());
if (res.isNull()) {
qDebugCamera() << Q_FUNC_INFO << "invalid resolution:" << res;
- return;
+ return false;
}
if (!res.isValid()) {
@@ -204,9 +209,11 @@ void AVFImageEncoderControl::applySettings()
// Here we could choose the best format available, but
// activeFormat is already equal to 'preset high' by default,
// which is good enough, otherwise we can end in some format with low framerates.
- return;
+ return false;
}
+ bool activeFormatChanged = false;
+
#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0)
if (QSysInfo::MacintoshVersion >= qt_OS_limit(QSysInfo::MV_10_7, QSysInfo::MV_IOS_7_0)) {
AVCaptureDevice *captureDevice = m_service->session()->videoCaptureDevice();
@@ -215,16 +222,17 @@ void AVFImageEncoderControl::applySettings()
if (!match) {
qDebugCamera() << Q_FUNC_INFO << "unsupported resolution:" << res;
- return;
+ return false;
}
if (match != captureDevice.activeFormat) {
const AVFConfigurationLock lock(captureDevice);
if (!lock) {
qDebugCamera() << Q_FUNC_INFO << "failed to lock for configuration";
- return;
+ return false;
}
captureDevice.activeFormat = match;
+ activeFormatChanged = true;
}
#if defined(Q_OS_IOS) && QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_8_0)
@@ -242,6 +250,8 @@ void AVFImageEncoderControl::applySettings()
#endif
// TODO: resolution without capture device format ...
}
+
+ return activeFormatChanged;
}
bool AVFImageEncoderControl::videoCaptureDeviceIsValid() const
diff --git a/src/plugins/avfoundation/camera/avfmediarecordercontrol.mm b/src/plugins/avfoundation/camera/avfmediarecordercontrol.mm
index 412dab76c..1b6e23ee5 100644
--- a/src/plugins/avfoundation/camera/avfmediarecordercontrol.mm
+++ b/src/plugins/avfoundation/camera/avfmediarecordercontrol.mm
@@ -37,6 +37,7 @@
#include "avfcameraservice.h"
#include "avfcameracontrol.h"
#include "avfaudioinputselectorcontrol.h"
+#include "avfcamerautility.h"
#include <QtCore/qurl.h>
#include <QtCore/qfileinfo.h>
@@ -330,6 +331,9 @@ void AVFMediaRecorderControl::setupSessionForCapture()
&& m_cameraControl->captureMode().testFlag(QCamera::CaptureVideo)
&& m_session->state() != QCamera::UnloadedState) {
+ // Lock the video capture device to make sure the active format is not reset
+ const AVFConfigurationLock lock(m_session->videoCaptureDevice());
+
// Add audio input
// Allow recording even if something wrong happens with the audio input initialization
AVCaptureDevice *audioDevice = m_audioInputControl->createCaptureDevice();
@@ -359,7 +363,10 @@ void AVFMediaRecorderControl::setupSessionForCapture()
}
} else if (m_connected
&& (!m_cameraControl->captureMode().testFlag(QCamera::CaptureVideo)
- || m_session->state() != QCamera::ActiveState)) {
+ || m_session->state() == QCamera::UnloadedState)) {
+
+ // Lock the video capture device to make sure the active format is not reset
+ const AVFConfigurationLock lock(m_session->videoCaptureDevice());
[captureSession removeOutput:m_movieOutput];