summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@theqtcompany.com>2015-06-03 10:58:51 +0200
committerLiang Qi <liang.qi@theqtcompany.com>2015-06-03 10:58:51 +0200
commit2cf8ac3398ce97273103bbef0f5538e57b57f66c (patch)
tree66143b4501d1ddb37b4cbecdec682491d6339d4a
parenta08bcb3279670f1920c774e9861c34d8f7653625 (diff)
parent7fd0fec5e5e2906ee7c9fdfce9181ef81c09d9f1 (diff)
downloadqtmultimedia-2cf8ac3398ce97273103bbef0f5538e57b57f66c.tar.gz
qtmultimedia-2cf8ac3398ce97273103bbef0f5538e57b57f66c.tar.bz2
qtmultimedia-2cf8ac3398ce97273103bbef0f5538e57b57f66c.zip
Merge remote-tracking branch 'origin/5.5' into dev
Change-Id: I7ac7db69c37cc9e5c5241a25b9a874986a23a886
-rw-r--r--examples/multimedia/declarative-radio/doc/images/declarative-radio-example.pngbin16734 -> 12113 bytes
-rw-r--r--examples/multimedia/declarative-radio/doc/src/declarative-radio.qdoc4
-rw-r--r--src/gsttools/qgstreamervideowidget.cpp5
-rw-r--r--src/gsttools/qgstreamervideowindow.cpp7
-rw-r--r--src/gsttools/qgstvideorenderersink.cpp47
-rw-r--r--src/gsttools/qvideosurfacegstsink.cpp62
-rw-r--r--src/imports/multimedia/qdeclarativecameraflash.cpp5
-rw-r--r--src/multimedia/controls/qcameraviewfindersettingscontrol.cpp2
-rw-r--r--src/multimedia/doc/src/qtmultimedia-index.qdoc5
-rw-r--r--src/multimedia/gsttools_headers/qgstvideorenderersink_p.h4
-rw-r--r--src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h5
-rw-r--r--src/plugins/android/src/mediacapture/qandroidcamerasession.cpp34
-rw-r--r--src/plugins/android/src/mediacapture/qandroidcapturesession.cpp10
-rw-r--r--src/plugins/android/src/mediacapture/qandroidcapturesession.h1
-rw-r--r--src/plugins/android/src/wrappers/jni/androidcamera.cpp3
-rw-r--r--src/plugins/avfoundation/camera/avfcamerarenderercontrol.h6
-rw-r--r--src/plugins/avfoundation/camera/avfcamerarenderercontrol.mm52
-rw-r--r--src/plugins/avfoundation/camera/avfcameraservice.h9
-rw-r--r--src/plugins/avfoundation/camera/avfcameraservice.mm31
-rw-r--r--src/plugins/avfoundation/camera/avfcamerasession.h2
-rw-r--r--src/plugins/avfoundation/camera/avfcamerasession.mm7
-rw-r--r--src/plugins/avfoundation/camera/avfcamerautility.h68
-rw-r--r--src/plugins/avfoundation/camera/avfcamerautility.mm17
-rw-r--r--src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.mm121
-rw-r--r--src/plugins/avfoundation/camera/avfcamerazoomcontrol.mm10
-rw-r--r--src/plugins/avfoundation/camera/avfmediaassetwriter.h119
-rw-r--r--src/plugins/avfoundation/camera/avfmediaassetwriter.mm474
-rw-r--r--src/plugins/avfoundation/camera/avfmediarecordercontrol_ios.h108
-rw-r--r--src/plugins/avfoundation/camera/avfmediarecordercontrol_ios.mm349
-rw-r--r--src/plugins/avfoundation/camera/camera.pro17
-rw-r--r--src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm4
-rw-r--r--src/plugins/videonode/imx6/qsgvivantevideomaterial.cpp39
-rw-r--r--src/plugins/videonode/imx6/qsgvivantevideomaterial.h4
-rw-r--r--src/plugins/videonode/imx6/qsgvivantevideomaterialshader.cpp22
-rw-r--r--src/plugins/videonode/imx6/qsgvivantevideomaterialshader.h9
-rw-r--r--src/plugins/videonode/imx6/qsgvivantevideonode.cpp19
-rw-r--r--src/plugins/videonode/imx6/qsgvivantevideonode.h1
-rw-r--r--src/plugins/winrt/qwinrtabstractvideorenderercontrol.cpp23
-rw-r--r--src/plugins/winrt/qwinrtabstractvideorenderercontrol.h23
-rw-r--r--src/plugins/winrt/qwinrtcameracontrol.cpp23
-rw-r--r--src/plugins/winrt/qwinrtcameracontrol.h23
-rw-r--r--src/plugins/winrt/qwinrtcameraimagecapturecontrol.cpp23
-rw-r--r--src/plugins/winrt/qwinrtcameraimagecapturecontrol.h23
-rw-r--r--src/plugins/winrt/qwinrtcamerainfocontrol.cpp23
-rw-r--r--src/plugins/winrt/qwinrtcamerainfocontrol.h23
-rw-r--r--src/plugins/winrt/qwinrtcameraservice.cpp23
-rw-r--r--src/plugins/winrt/qwinrtcameraservice.h23
-rw-r--r--src/plugins/winrt/qwinrtcameravideorenderercontrol.cpp23
-rw-r--r--src/plugins/winrt/qwinrtcameravideorenderercontrol.h23
-rw-r--r--src/plugins/winrt/qwinrtmediaplayercontrol.cpp23
-rw-r--r--src/plugins/winrt/qwinrtmediaplayercontrol.h23
-rw-r--r--src/plugins/winrt/qwinrtmediaplayerservice.cpp23
-rw-r--r--src/plugins/winrt/qwinrtmediaplayerservice.h23
-rw-r--r--src/plugins/winrt/qwinrtplayerrenderercontrol.cpp23
-rw-r--r--src/plugins/winrt/qwinrtplayerrenderercontrol.h23
-rw-r--r--src/plugins/winrt/qwinrtserviceplugin.cpp23
-rw-r--r--src/plugins/winrt/qwinrtserviceplugin.h23
-rw-r--r--src/plugins/winrt/qwinrtvideodeviceselectorcontrol.cpp23
-rw-r--r--src/plugins/winrt/qwinrtvideodeviceselectorcontrol.h23
-rw-r--r--src/plugins/wmf/decoder/mfaudiodecodercontrol.cpp3
-rw-r--r--src/qtmultimediaquicktools/qdeclarativevideooutput.cpp5
-rw-r--r--src/qtmultimediaquicktools/qsgvideonode_yuv.cpp3
-rw-r--r--tests/auto/unit/qaudiobuffer/qaudiobuffer.pro2
63 files changed, 1843 insertions, 358 deletions
diff --git a/examples/multimedia/declarative-radio/doc/images/declarative-radio-example.png b/examples/multimedia/declarative-radio/doc/images/declarative-radio-example.png
index 6c039349..5b29174c 100644
--- a/examples/multimedia/declarative-radio/doc/images/declarative-radio-example.png
+++ b/examples/multimedia/declarative-radio/doc/images/declarative-radio-example.png
Binary files differ
diff --git a/examples/multimedia/declarative-radio/doc/src/declarative-radio.qdoc b/examples/multimedia/declarative-radio/doc/src/declarative-radio.qdoc
index 42cebe2f..62687f03 100644
--- a/examples/multimedia/declarative-radio/doc/src/declarative-radio.qdoc
+++ b/examples/multimedia/declarative-radio/doc/src/declarative-radio.qdoc
@@ -28,11 +28,13 @@
/*!
\example declarative-radio
\title Declarative Radio Example
- \brief Demonstrates the radio functionality
+ \brief Demonstrates using the Radio QML type from Qt Multimedia.
\ingroup multimedia_examples
This examples uses the \l{Qt Multimedia} \l Radio QML type to list the
available channels on the FM frequency.
+ \image declarative-radio-example.png
+
\include examples-run.qdocinc
*/
diff --git a/src/gsttools/qgstreamervideowidget.cpp b/src/gsttools/qgstreamervideowidget.cpp
index 9a29d327..6e65b306 100644
--- a/src/gsttools/qgstreamervideowidget.cpp
+++ b/src/gsttools/qgstreamervideowidget.cpp
@@ -98,7 +98,10 @@ QGstreamerVideoWidgetControl::QGstreamerVideoWidgetControl(QObject *parent)
, m_widget(0)
, m_fullScreen(false)
{
- m_videoSink = gst_element_factory_make ("xvimagesink", NULL);
+ // The QWidget needs to have a native X window handle to be able to use xvimagesink.
+ // Bail out if Qt is not using xcb (the control will then be ignored by the plugin)
+ if (QGuiApplication::platformName().compare(QLatin1String("xcb"), Qt::CaseInsensitive) == 0)
+ m_videoSink = gst_element_factory_make ("xvimagesink", NULL);
if (m_videoSink) {
// Check if the xv sink is usable
diff --git a/src/gsttools/qgstreamervideowindow.cpp b/src/gsttools/qgstreamervideowindow.cpp
index 7dd6ab25..ee25acc4 100644
--- a/src/gsttools/qgstreamervideowindow.cpp
+++ b/src/gsttools/qgstreamervideowindow.cpp
@@ -35,6 +35,7 @@
#include <private/qgstutils_p.h>
#include <QtCore/qdebug.h>
+#include <QtGui/qguiapplication.h>
#include <gst/gst.h>
@@ -57,7 +58,9 @@ QGstreamerVideoWindow::QGstreamerVideoWindow(QObject *parent, const char *elemen
{
if (elementName) {
m_videoSink = gst_element_factory_make(elementName, NULL);
- } else {
+ } else if (QGuiApplication::platformName().compare(QLatin1String("xcb"), Qt::CaseInsensitive) == 0) {
+ // We need a native X window handle to be able to use xvimagesink.
+ // Bail out if Qt is not using xcb (the control will then be ignored by the plugin)
m_videoSink = gst_element_factory_make("xvimagesink", NULL);
}
@@ -68,8 +71,6 @@ QGstreamerVideoWindow::QGstreamerVideoWindow(QObject *parent, const char *elemen
addProbeToPad(pad);
gst_object_unref(GST_OBJECT(pad));
}
- else
- qDebug() << "No m_videoSink available!";
}
QGstreamerVideoWindow::~QGstreamerVideoWindow()
diff --git a/src/gsttools/qgstvideorenderersink.cpp b/src/gsttools/qgstvideorenderersink.cpp
index 615348c1..31ac94e8 100644
--- a/src/gsttools/qgstvideorenderersink.cpp
+++ b/src/gsttools/qgstvideorenderersink.cpp
@@ -222,6 +222,17 @@ bool QVideoSurfaceGstDelegate::proposeAllocation(GstQuery *query)
}
}
+void QVideoSurfaceGstDelegate::flush()
+{
+ QMutexLocker locker(&m_mutex);
+
+ m_flush = true;
+ m_renderBuffer = 0;
+ m_renderCondition.wakeAll();
+
+ notify();
+}
+
GstFlowReturn QVideoSurfaceGstDelegate::render(GstBuffer *buffer)
{
QMutexLocker locker(&m_mutex);
@@ -388,6 +399,8 @@ QGstVideoRendererSink *QGstVideoRendererSink::createSink(QAbstractVideoSurface *
sink->delegate = new QVideoSurfaceGstDelegate(surface);
+ g_signal_connect(G_OBJECT(sink), "notify::show-preroll-frame", G_CALLBACK(handleShowPrerollChange), sink);
+
return sink;
}
@@ -472,13 +485,41 @@ void QGstVideoRendererSink::finalize(GObject *object)
G_OBJECT_CLASS(sink_parent_class)->finalize(object);
}
+void QGstVideoRendererSink::handleShowPrerollChange(GObject *o, GParamSpec *p, gpointer d)
+{
+ Q_UNUSED(o);
+ Q_UNUSED(p);
+ QGstVideoRendererSink *sink = reinterpret_cast<QGstVideoRendererSink *>(d);
+
+ gboolean showPrerollFrame = true; // "show-preroll-frame" property is true by default
+ g_object_get(G_OBJECT(sink), "show-preroll-frame", &showPrerollFrame, NULL);
+
+ if (!showPrerollFrame) {
+ GstState state = GST_STATE_VOID_PENDING;
+ gst_element_get_state(GST_ELEMENT(sink), &state, NULL, GST_CLOCK_TIME_NONE);
+ // show-preroll-frame being set to 'false' while in GST_STATE_PAUSED means
+ // the QMediaPlayer was stopped from the paused state.
+ // We need to flush the current frame.
+ if (state == GST_STATE_PAUSED)
+ sink->delegate->flush();
+ }
+}
+
GstStateChangeReturn QGstVideoRendererSink::change_state(
GstElement *element, GstStateChange transition)
{
- Q_UNUSED(element);
+ QGstVideoRendererSink *sink = reinterpret_cast<QGstVideoRendererSink *>(element);
+
+ gboolean showPrerollFrame = true; // "show-preroll-frame" property is true by default
+ g_object_get(G_OBJECT(element), "show-preroll-frame", &showPrerollFrame, NULL);
+
+ // If show-preroll-frame is 'false' when transitioning from GST_STATE_PLAYING to
+ // GST_STATE_PAUSED, it means the QMediaPlayer was stopped.
+ // We need to flush the current frame.
+ if (transition == GST_STATE_CHANGE_PLAYING_TO_PAUSED && !showPrerollFrame)
+ sink->delegate->flush();
- return GST_ELEMENT_CLASS(sink_parent_class)->change_state(
- element, transition);
+ return GST_ELEMENT_CLASS(sink_parent_class)->change_state(element, transition);
}
GstCaps *QGstVideoRendererSink::get_caps(GstBaseSink *base, GstCaps *filter)
diff --git a/src/gsttools/qvideosurfacegstsink.cpp b/src/gsttools/qvideosurfacegstsink.cpp
index 4a786ea1..737bc648 100644
--- a/src/gsttools/qvideosurfacegstsink.cpp
+++ b/src/gsttools/qvideosurfacegstsink.cpp
@@ -184,6 +184,21 @@ void QVideoSurfaceGstDelegate::clearPoolBuffers()
m_pool->clear();
}
+void QVideoSurfaceGstDelegate::flush()
+{
+ QMutexLocker locker(&m_mutex);
+
+ m_frame = QVideoFrame();
+ m_renderCondition.wakeAll();
+
+ if (QThread::currentThread() == thread()) {
+ if (!m_surface.isNull())
+ m_surface->present(m_frame);
+ } else {
+ QMetaObject::invokeMethod(this, "queuedFlush", Qt::QueuedConnection);
+ }
+}
+
GstFlowReturn QVideoSurfaceGstDelegate::render(GstBuffer *buffer)
{
if (!m_surface) {
@@ -244,6 +259,14 @@ void QVideoSurfaceGstDelegate::queuedStop()
m_setupCondition.wakeAll();
}
+void QVideoSurfaceGstDelegate::queuedFlush()
+{
+ QMutexLocker locker(&m_mutex);
+
+ if (!m_surface.isNull())
+ m_surface->present(QVideoFrame());
+}
+
void QVideoSurfaceGstDelegate::queuedRender()
{
QMutexLocker locker(&m_mutex);
@@ -316,6 +339,8 @@ QVideoSurfaceGstSink *QVideoSurfaceGstSink::createSink(QAbstractVideoSurface *su
sink->delegate = new QVideoSurfaceGstDelegate(surface);
+ g_signal_connect(G_OBJECT(sink), "notify::show-preroll-frame", G_CALLBACK(handleShowPrerollChange), sink);
+
return sink;
}
@@ -420,13 +445,40 @@ void QVideoSurfaceGstSink::finalize(GObject *object)
G_OBJECT_CLASS(sink_parent_class)->finalize(object);
}
-GstStateChangeReturn QVideoSurfaceGstSink::change_state(
- GstElement *element, GstStateChange transition)
+void QVideoSurfaceGstSink::handleShowPrerollChange(GObject *o, GParamSpec *p, gpointer d)
{
- Q_UNUSED(element);
+ Q_UNUSED(o);
+ Q_UNUSED(p);
+ QVideoSurfaceGstSink *sink = reinterpret_cast<QVideoSurfaceGstSink *>(d);
+
+ gboolean showPrerollFrame = true; // "show-preroll-frame" property is true by default
+ g_object_get(G_OBJECT(sink), "show-preroll-frame", &showPrerollFrame, NULL);
+
+ if (!showPrerollFrame) {
+ GstState state = GST_STATE_VOID_PENDING;
+ gst_element_get_state(GST_ELEMENT(sink), &state, NULL, GST_CLOCK_TIME_NONE);
+ // show-preroll-frame being set to 'false' while in GST_STATE_PAUSED means
+ // the QMediaPlayer was stopped from the paused state.
+ // We need to flush the current frame.
+ if (state == GST_STATE_PAUSED)
+ sink->delegate->flush();
+ }
+}
+
+GstStateChangeReturn QVideoSurfaceGstSink::change_state(GstElement *element, GstStateChange transition)
+{
+ QVideoSurfaceGstSink *sink = reinterpret_cast<QVideoSurfaceGstSink *>(element);
+
+ gboolean showPrerollFrame = true; // "show-preroll-frame" property is true by default
+ g_object_get(G_OBJECT(element), "show-preroll-frame", &showPrerollFrame, NULL);
+
+ // If show-preroll-frame is 'false' when transitioning from GST_STATE_PLAYING to
+ // GST_STATE_PAUSED, it means the QMediaPlayer was stopped.
+ // We need to flush the current frame.
+ if (transition == GST_STATE_CHANGE_PLAYING_TO_PAUSED && !showPrerollFrame)
+ sink->delegate->flush();
- return GST_ELEMENT_CLASS(sink_parent_class)->change_state(
- element, transition);
+ return GST_ELEMENT_CLASS(sink_parent_class)->change_state(element, transition);
}
GstCaps *QVideoSurfaceGstSink::get_caps(GstBaseSink *base)
diff --git a/src/imports/multimedia/qdeclarativecameraflash.cpp b/src/imports/multimedia/qdeclarativecameraflash.cpp
index 0bde737e..ae4fd939 100644
--- a/src/imports/multimedia/qdeclarativecameraflash.cpp
+++ b/src/imports/multimedia/qdeclarativecameraflash.cpp
@@ -113,7 +113,10 @@ bool QDeclarativeCameraFlash::isFlashReady() const
\row \li Camera.FlashAuto \li Automatic flash.
\row \li Camera.FlashRedEyeReduction \li Red eye reduction flash.
\row \li Camera.FlashFill \li Use flash to fillin shadows.
- \row \li Camera.FlashTorch \li Constant light source, useful for focusing and video capture.
+ \row \li Camera.FlashTorch \li Constant light source. If supported, torch can be
+ enabled without loading the camera.
+ \row \li Camera.FlashVideoLight \li Constant light source, useful for video capture.
+ The light is turned on only while the camera is active.
\row \li Camera.FlashSlowSyncFrontCurtain
\li Use the flash in conjunction with a slow shutter speed.
This mode allows better exposure of distant objects and/or motion blur effect.
diff --git a/src/multimedia/controls/qcameraviewfindersettingscontrol.cpp b/src/multimedia/controls/qcameraviewfindersettingscontrol.cpp
index 49bc81ab..95b48696 100644
--- a/src/multimedia/controls/qcameraviewfindersettingscontrol.cpp
+++ b/src/multimedia/controls/qcameraviewfindersettingscontrol.cpp
@@ -96,7 +96,7 @@ QCameraViewfinderSettingsControl::~QCameraViewfinderSettingsControl()
Viewfinder pixel format, QVideoFrame::PixelFormat
\value UserParameter
The base value for platform specific extended parameters.
- For such parameters the sequential values starting from UserParameter shuld be used.
+ For such parameters the sequential values starting from UserParameter should be used.
*/
/*!
diff --git a/src/multimedia/doc/src/qtmultimedia-index.qdoc b/src/multimedia/doc/src/qtmultimedia-index.qdoc
index 39e7cbc4..6dc89429 100644
--- a/src/multimedia/doc/src/qtmultimedia-index.qdoc
+++ b/src/multimedia/doc/src/qtmultimedia-index.qdoc
@@ -130,6 +130,11 @@
\endlist
\section2 Platform Notes
+
+ The \l{Qt Multimedia Backends} wiki provides a summary of features
+ supported by each platform plugin made available by this module. The
+ following topics provide more platform-specific information.
+
\list
\li \l{Qt Multimedia on BlackBerry}{BlackBerry}
\li \l{Qt Multimedia on Windows}{Windows}
diff --git a/src/multimedia/gsttools_headers/qgstvideorenderersink_p.h b/src/multimedia/gsttools_headers/qgstvideorenderersink_p.h
index 18670887..78bdf8cb 100644
--- a/src/multimedia/gsttools_headers/qgstvideorenderersink_p.h
+++ b/src/multimedia/gsttools_headers/qgstvideorenderersink_p.h
@@ -99,6 +99,8 @@ public:
void unlock();
bool proposeAllocation(GstQuery *query);
+ void flush();
+
GstFlowReturn render(GstBuffer *buffer);
bool event(QEvent *event);
@@ -145,6 +147,8 @@ private:
static void finalize(GObject *object);
+ static void handleShowPrerollChange(GObject *o, GParamSpec *p, gpointer d);
+
static GstStateChangeReturn change_state(GstElement *element, GstStateChange transition);
static GstCaps *get_caps(GstBaseSink *sink, GstCaps *filter);
diff --git a/src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h b/src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h
index e8f61afe..a1ef5616 100644
--- a/src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h
+++ b/src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h
@@ -96,11 +96,14 @@ public:
QMutex *poolMutex() { return &m_poolMutex; }
void clearPoolBuffers();
+ void flush();
+
GstFlowReturn render(GstBuffer *buffer);
private slots:
void queuedStart();
void queuedStop();
+ void queuedFlush();
void queuedRender();
void updateSupportedFormats();
@@ -139,6 +142,8 @@ private:
static void finalize(GObject *object);
+ static void handleShowPrerollChange(GObject *o, GParamSpec *p, gpointer d);
+
static GstStateChangeReturn change_state(GstElement *element, GstStateChange transition);
static GstCaps *get_caps(GstBaseSink *sink);
diff --git a/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp b/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp
index 2ff17592..4a64e1b1 100644
--- a/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp
+++ b/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp
@@ -277,26 +277,28 @@ void QAndroidCameraSession::adjustViewfinderSize(const QSize &captureSize, bool
return;
QSize currentViewfinderResolution = m_camera->previewSize();
- const qreal aspectRatio = qreal(captureSize.width()) / qreal(captureSize.height());
- if (currentViewfinderResolution.isValid() &&
- qAbs(aspectRatio - (qreal(currentViewfinderResolution.width()) / currentViewfinderResolution.height())) < 0.01) {
- return;
- }
-
QSize adjustedViewfinderResolution;
- QList<QSize> previewSizes = m_camera->getSupportedPreviewSizes();
- for (int i = previewSizes.count() - 1; i >= 0; --i) {
- const QSize &size = previewSizes.at(i);
+
+ if (m_captureMode.testFlag(QCamera::CaptureVideo) && m_camera->getPreferredPreviewSizeForVideo().isEmpty()) {
+ // According to the Android doc, if getPreferredPreviewSizeForVideo() returns null, it means
+ // the preview size cannot be different from the capture size
+ adjustedViewfinderResolution = captureSize;
+ } else {
// search for viewfinder resolution with the same aspect ratio
- if (qAbs(aspectRatio - (qreal(size.width()) / size.height())) < 0.01) {
- adjustedViewfinderResolution = size;
- break;
+ const qreal aspectRatio = qreal(captureSize.width()) / qreal(captureSize.height());
+ QList<QSize> previewSizes = m_camera->getSupportedPreviewSizes();
+ for (int i = previewSizes.count() - 1; i >= 0; --i) {
+ const QSize &size = previewSizes.at(i);
+ if (qAbs(aspectRatio - (qreal(size.width()) / size.height())) < 0.01) {
+ adjustedViewfinderResolution = size;
+ break;
+ }
}
- }
- if (!adjustedViewfinderResolution.isValid()) {
- qWarning("Cannot find a viewfinder resolution matching the capture aspect ratio.");
- return;
+ if (!adjustedViewfinderResolution.isValid()) {
+ qWarning("Cannot find a viewfinder resolution matching the capture aspect ratio.");
+ return;
+ }
}
if (currentViewfinderResolution != adjustedViewfinderResolution) {
diff --git a/src/plugins/android/src/mediacapture/qandroidcapturesession.cpp b/src/plugins/android/src/mediacapture/qandroidcapturesession.cpp
index af803302..aaad8fd8 100644
--- a/src/plugins/android/src/mediacapture/qandroidcapturesession.cpp
+++ b/src/plugins/android/src/mediacapture/qandroidcapturesession.cpp
@@ -48,7 +48,6 @@ QAndroidCaptureSession::QAndroidCaptureSession(QAndroidCameraSession *cameraSess
, m_duration(0)
, m_state(QMediaRecorder::StoppedState)
, m_status(QMediaRecorder::UnloadedStatus)
- , m_resolutionDirty(false)
, m_containerFormatDirty(true)
, m_videoSettingsDirty(true)
, m_audioSettingsDirty(true)
@@ -321,9 +320,6 @@ void QAndroidCaptureSession::setVideoSettings(const QVideoEncoderSettings &setti
if (!m_cameraSession || m_videoSettings == settings)
return;
- if (m_videoSettings.resolution() != settings.resolution())
- m_resolutionDirty = true;
-
m_videoSettings = settings;
m_videoSettingsDirty = true;
}
@@ -376,7 +372,6 @@ void QAndroidCaptureSession::applySettings()
if (m_cameraSession && m_cameraSession->camera() && m_videoSettingsDirty) {
if (m_videoSettings.resolution().isEmpty()) {
m_videoSettings.setResolution(m_defaultSettings.videoResolution);
- m_resolutionDirty = true;
} else if (!m_supportedResolutions.contains(m_videoSettings.resolution())) {
// if the requested resolution is not supported, find the closest one
QSize reqSize = m_videoSettings.resolution();
@@ -388,7 +383,6 @@ void QAndroidCaptureSession::applySettings()
}
int closestIndex = qt_findClosestValue(supportedPixelCounts, reqPixelCount);
m_videoSettings.setResolution(m_supportedResolutions.at(closestIndex));
- m_resolutionDirty = true;
}
if (m_videoSettings.frameRate() <= 0)
@@ -413,12 +407,8 @@ void QAndroidCaptureSession::applySettings()
void QAndroidCaptureSession::updateViewfinder()
{
- if (!m_resolutionDirty)
- return;
-
m_cameraSession->camera()->stopPreview();
m_cameraSession->adjustViewfinderSize(m_videoSettings.resolution(), false);
- m_resolutionDirty = false;
}
void QAndroidCaptureSession::restartViewfinder()
diff --git a/src/plugins/android/src/mediacapture/qandroidcapturesession.h b/src/plugins/android/src/mediacapture/qandroidcapturesession.h
index 90af39fd..a0e7a894 100644
--- a/src/plugins/android/src/mediacapture/qandroidcapturesession.h
+++ b/src/plugins/android/src/mediacapture/qandroidcapturesession.h
@@ -161,7 +161,6 @@ private:
QString m_containerFormat;
QAudioEncoderSettings m_audioSettings;
QVideoEncoderSettings m_videoSettings;
- bool m_resolutionDirty;
bool m_containerFormatDirty;
bool m_videoSettingsDirty;
bool m_audioSettingsDirty;
diff --git a/src/plugins/android/src/wrappers/jni/androidcamera.cpp b/src/plugins/android/src/wrappers/jni/androidcamera.cpp
index d9c8befa..7496e9cd 100644
--- a/src/plugins/android/src/wrappers/jni/androidcamera.cpp
+++ b/src/plugins/android/src/wrappers/jni/androidcamera.cpp
@@ -786,6 +786,9 @@ QSize AndroidCameraPrivate::getPreferredPreviewSizeForVideo()
QJNIObjectPrivate size = m_parameters.callObjectMethod("getPreferredPreviewSizeForVideo",
"()Landroid/hardware/Camera$Size;");
+ if (!size.isValid())
+ return QSize();
+
return QSize(size.getField<jint>("width"), size.getField<jint>("height"));
}
diff --git a/src/plugins/avfoundation/camera/avfcamerarenderercontrol.h b/src/plugins/avfoundation/camera/avfcamerarenderercontrol.h
index 92ab75bd..b8f92d9c 100644
--- a/src/plugins/avfoundation/camera/avfcamerarenderercontrol.h
+++ b/src/plugins/avfoundation/camera/avfcamerarenderercontrol.h
@@ -63,6 +63,11 @@ public:
AVCaptureVideoDataOutput *videoDataOutput() const;
+#ifdef Q_OS_IOS
+ AVFCaptureFramesDelegate *captureDelegate() const;
+ void resetCaptureDelegate() const;
+#endif
+
Q_SIGNALS:
void surfaceChanged(QAbstractVideoSurface *surface);
@@ -80,6 +85,7 @@ private:
QVideoFrame m_lastViewfinderFrame;
QMutex m_vfMutex;
+ dispatch_queue_t m_delegateQueue;
};
QT_END_NAMESPACE
diff --git a/src/plugins/avfoundation/camera/avfcamerarenderercontrol.mm b/src/plugins/avfoundation/camera/avfcamerarenderercontrol.mm
index cf13635f..52954128 100644
--- a/src/plugins/avfoundation/camera/avfcamerarenderercontrol.mm
+++ b/src/plugins/avfoundation/camera/avfcamerarenderercontrol.mm
@@ -143,6 +143,7 @@ private:
- (void) captureOutput:(AVCaptureOutput *)captureOutput
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
fromConnection:(AVCaptureConnection *)connection;
+
@end
@implementation AVFCaptureFramesDelegate
@@ -163,25 +164,23 @@ private:
Q_UNUSED(connection);
Q_UNUSED(captureOutput);
+ // NB: on iOS captureOutput/connection can be nil (when recording a video -
+ // avfmediaassetwriter).
+
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
int width = CVPixelBufferGetWidth(imageBuffer);
int height = CVPixelBufferGetHeight(imageBuffer);
+ QVideoFrame::PixelFormat format =
+ AVFCameraViewfinderSettingsControl2::QtPixelFormatFromCVFormat(CVPixelBufferGetPixelFormatType(imageBuffer));
- QAbstractVideoBuffer *buffer = new CVPixelBufferVideoBuffer(imageBuffer);
-
- QVideoFrame::PixelFormat format = QVideoFrame::Format_RGB32;
- if ([captureOutput isKindOfClass:[AVCaptureVideoDataOutput class]]) {
- NSDictionary *settings = ((AVCaptureVideoDataOutput *)captureOutput).videoSettings;
- if (settings && [settings objectForKey:(id)kCVPixelBufferPixelFormatTypeKey]) {
- NSNumber *avf = [settings objectForKey:(id)kCVPixelBufferPixelFormatTypeKey];
- format = AVFCameraViewfinderSettingsControl2::QtPixelFormatFromCVFormat([avf unsignedIntValue]);
- }
- }
+ if (format == QVideoFrame::Format_Invalid)
+ return;
- QVideoFrame frame(buffer, QSize(width, height), format);
+ QVideoFrame frame(new CVPixelBufferVideoBuffer(imageBuffer), QSize(width, height), format);
m_renderer->syncHandleViewfinderFrame(frame);
}
+
@end
@@ -197,6 +196,8 @@ AVFCameraRendererControl::~AVFCameraRendererControl()
{
[m_cameraSession->captureSession() removeOutput:m_videoDataOutput];
[m_viewfinderFramesDelegate release];
+ if (m_delegateQueue)
+ dispatch_release(m_delegateQueue);
}
QAbstractVideoSurface *AVFCameraRendererControl::surface() const
@@ -223,17 +224,10 @@ void AVFCameraRendererControl::configureAVCaptureSession(AVFCameraSession *camer
m_videoDataOutput = [[[AVCaptureVideoDataOutput alloc] init] autorelease];
// Configure video output
- dispatch_queue_t queue = dispatch_queue_create("vf_queue", NULL);
+ m_delegateQueue = dispatch_queue_create("vf_queue", NULL);
[m_videoDataOutput
setSampleBufferDelegate:m_viewfinderFramesDelegate
- queue:queue];
- dispatch_release(queue);
-
- // Specify the pixel format
- m_videoDataOutput.videoSettings =
- [NSDictionary dictionaryWithObject:
- [NSNumber numberWithInt:kCVPixelFormatType_32BGRA]
- forKey:(id)kCVPixelBufferPixelFormatTypeKey];
+ queue:m_delegateQueue];
[m_cameraSession->captureSession() addOutput:m_videoDataOutput];
}
@@ -291,6 +285,20 @@ AVCaptureVideoDataOutput *AVFCameraRendererControl::videoDataOutput() const
return m_videoDataOutput;
}
+#ifdef Q_OS_IOS
+
+AVFCaptureFramesDelegate *AVFCameraRendererControl::captureDelegate() const
+{
+ return m_viewfinderFramesDelegate;
+}
+
+void AVFCameraRendererControl::resetCaptureDelegate() const
+{
+ [m_videoDataOutput setSampleBufferDelegate:m_viewfinderFramesDelegate queue:m_delegateQueue];
+}
+
+#endif
+
void AVFCameraRendererControl::handleViewfinderFrame()
{
QVideoFrame frame;
@@ -301,8 +309,10 @@ void AVFCameraRendererControl::handleViewfinderFrame()
}
if (m_surface && frame.isValid()) {
- if (m_surface->isActive() && m_surface->surfaceFormat().pixelFormat() != frame.pixelFormat())
+ if (m_surface->isActive() && (m_surface->surfaceFormat().pixelFormat() != frame.pixelFormat()
+ || m_surface->surfaceFormat().frameSize() != frame.size())) {
m_surface->stop();
+ }
if (!m_surface->isActive()) {
QVideoSurfaceFormat format(frame.size(), frame.pixelFormat());
diff --git a/src/plugins/avfoundation/camera/avfcameraservice.h b/src/plugins/avfoundation/camera/avfcameraservice.h
index d557872a..08b0ad26 100644
--- a/src/plugins/avfoundation/camera/avfcameraservice.h
+++ b/src/plugins/avfoundation/camera/avfcameraservice.h
@@ -41,13 +41,13 @@
QT_BEGIN_NAMESPACE
class QCameraControl;
+class QMediaRecorderControl;
class AVFCameraControl;
class AVFCameraInfoControl;
class AVFCameraMetaDataControl;
class AVFVideoWindowControl;
class AVFVideoWidgetControl;
class AVFCameraRendererControl;
-class AVFMediaRecorderControl;
class AVFImageCaptureControl;
class AVFCameraSession;
class AVFCameraDeviceControl;
@@ -59,6 +59,8 @@ class AVFCameraViewfinderSettingsControl2;
class AVFCameraViewfinderSettingsControl;
class AVFImageEncoderControl;
class AVFCameraFlashControl;
+class AVFMediaRecorderControl;
+class AVFMediaRecorderControlIOS;
class AVFCameraService : public QMediaService
{
@@ -75,7 +77,8 @@ public:
AVFCameraDeviceControl *videoDeviceControl() const { return m_videoDeviceControl; }
AVFAudioInputSelectorControl *audioInputSelectorControl() const { return m_audioInputSelectorControl; }
AVFCameraMetaDataControl *metaDataControl() const { return m_metaDataControl; }
- AVFMediaRecorderControl *recorderControl() const { return m_recorderControl; }
+ AVFMediaRecorderControl *recorderControl() const;
+ AVFMediaRecorderControlIOS *recorderControlIOS() const;
AVFImageCaptureControl *imageCaptureControl() const { return m_imageCaptureControl; }
AVFCameraFocusControl *cameraFocusControl() const { return m_cameraFocusControl; }
AVFCameraExposureControl *cameraExposureControl() const {return m_cameraExposureControl; }
@@ -94,7 +97,7 @@ private:
AVFAudioInputSelectorControl *m_audioInputSelectorControl;
AVFCameraRendererControl *m_videoOutput;
AVFCameraMetaDataControl *m_metaDataControl;
- AVFMediaRecorderControl *m_recorderControl;
+ QMediaRecorderControl *m_recorderControl;
AVFImageCaptureControl *m_imageCaptureControl;
AVFCameraFocusControl *m_cameraFocusControl;
AVFCameraExposureControl *m_cameraExposureControl;
diff --git a/src/plugins/avfoundation/camera/avfcameraservice.mm b/src/plugins/avfoundation/camera/avfcameraservice.mm
index f163e129..fd473b37 100644
--- a/src/plugins/avfoundation/camera/avfcameraservice.mm
+++ b/src/plugins/avfoundation/camera/avfcameraservice.mm
@@ -56,6 +56,7 @@
#ifdef Q_OS_IOS
#include "avfcamerazoomcontrol.h"
+#include "avfmediarecordercontrol_ios.h"
#endif
#include <private/qmediaplaylistnavigator_p.h>
@@ -74,7 +75,14 @@ AVFCameraService::AVFCameraService(QObject *parent):
m_audioInputSelectorControl = new AVFAudioInputSelectorControl(this);
m_metaDataControl = new AVFCameraMetaDataControl(this);
+#ifndef Q_OS_IOS
+ // This will connect a slot to 'captureModeChanged'
+ // and will break viewfinder by attaching AVCaptureMovieFileOutput
+ // in this slot.
m_recorderControl = new AVFMediaRecorderControl(this);
+#else
+ m_recorderControl = new AVFMediaRecorderControlIOS(this);
+#endif
m_imageCaptureControl = new AVFImageCaptureControl(this);
m_cameraFocusControl = new AVFCameraFocusControl(this);
m_cameraExposureControl = 0;
@@ -97,6 +105,10 @@ AVFCameraService::~AVFCameraService()
{
m_cameraControl->setState(QCamera::UnloadedState);
+#ifdef Q_OS_IOS
+ delete m_recorderControl;
+#endif
+
if (m_videoOutput) {
m_session->setVideoOutput(0);
delete m_videoOutput;
@@ -205,4 +217,23 @@ void AVFCameraService::releaseControl(QMediaControl *control)
}
+AVFMediaRecorderControl *AVFCameraService::recorderControl() const
+{
+#ifdef Q_OS_IOS
+ return 0;
+#else
+ return static_cast<AVFMediaRecorderControl *>(m_recorderControl);
+#endif
+}
+
+AVFMediaRecorderControlIOS *AVFCameraService::recorderControlIOS() const
+{
+#ifdef Q_OS_OSX
+ return 0;
+#else
+ return static_cast<AVFMediaRecorderControlIOS *>(m_recorderControl);
+#endif
+}
+
+
#include "moc_avfcameraservice.cpp"
diff --git a/src/plugins/avfoundation/camera/avfcamerasession.h b/src/plugins/avfoundation/camera/avfcamerasession.h
index 7b25a99c..2b322cfa 100644
--- a/src/plugins/avfoundation/camera/avfcamerasession.h
+++ b/src/plugins/avfoundation/camera/avfcamerasession.h
@@ -83,6 +83,8 @@ public:
void removeProbe(AVFMediaVideoProbeControl *probe);
FourCharCode defaultCodec();
+ AVCaptureDeviceInput *videoInput() const {return m_videoInput;}
+
public Q_SLOTS:
void setState(QCamera::State state);
diff --git a/src/plugins/avfoundation/camera/avfcamerasession.mm b/src/plugins/avfoundation/camera/avfcamerasession.mm
index 6e4803f3..2cb3824d 100644
--- a/src/plugins/avfoundation/camera/avfcamerasession.mm
+++ b/src/plugins/avfoundation/camera/avfcamerasession.mm
@@ -283,12 +283,12 @@ void AVFCameraSession::setState(QCamera::State newState)
if (m_state == QCamera::ActiveState) {
Q_EMIT readyToConfigureConnections();
- [m_captureSession commitConfiguration];
- [m_captureSession startRunning];
m_defaultCodec = 0;
defaultCodec();
applyImageEncoderSettings();
applyViewfinderSettings();
+ [m_captureSession commitConfiguration];
+ [m_captureSession startRunning];
}
if (oldState == QCamera::ActiveState) {
@@ -374,8 +374,7 @@ void AVFCameraSession::applyViewfinderSettings()
}
}
- if (!vfSettings.isNull())
- vfControl->applySettings();
+ vfControl->applySettings();
}
}
diff --git a/src/plugins/avfoundation/camera/avfcamerautility.h b/src/plugins/avfoundation/camera/avfcamerautility.h
index 03a61460..42005a50 100644
--- a/src/plugins/avfoundation/camera/avfcamerautility.h
+++ b/src/plugins/avfoundation/camera/avfcamerautility.h
@@ -78,6 +78,74 @@ private:
bool m_locked;
};
+struct AVFObjectDeleter {
+ static void cleanup(NSObject *obj)
+ {
+ if (obj)
+ [obj release];
+ }
+};
+
+template<class T>
+class AVFScopedPointer : public QScopedPointer<NSObject, AVFObjectDeleter>
+{
+public:
+ AVFScopedPointer() {}
+ explicit AVFScopedPointer(T *ptr) : QScopedPointer(ptr) {}
+ operator T*() const
+ {
+ // Quite handy operator to enable Obj-C messages: [ptr someMethod];
+ return data();
+ }
+
+ T *data() const
+ {
+ return static_cast<T *>(QScopedPointer::data());
+ }
+
+ T *take()
+ {
+ return static_cast<T *>(QScopedPointer::take());
+ }
+};
+
+template<>
+class AVFScopedPointer<dispatch_queue_t>
+{
+public:
+ AVFScopedPointer() : m_queue(0) {}
+ explicit AVFScopedPointer(dispatch_queue_t q) : m_queue(q) {}
+
+ ~AVFScopedPointer()
+ {
+ if (m_queue)
+ dispatch_release(m_queue);
+ }
+
+ operator dispatch_queue_t() const
+ {
+ // Quite handy operator to enable Obj-C messages: [ptr someMethod];
+ return m_queue;
+ }
+
+ dispatch_queue_t data() const
+ {
+ return m_queue;
+ }
+
+ void reset(dispatch_queue_t q = 0)
+ {
+ if (m_queue)
+ dispatch_release(m_queue);
+ m_queue = q;
+ }
+
+private:
+ dispatch_queue_t m_queue;
+
+ Q_DISABLE_COPY(AVFScopedPointer);
+};
+
inline QSysInfo::MacVersion qt_OS_limit(QSysInfo::MacVersion osxVersion,
QSysInfo::MacVersion iosVersion)
{
diff --git a/src/plugins/avfoundation/camera/avfcamerautility.mm b/src/plugins/avfoundation/camera/avfcamerautility.mm
index f8d5647e..f45169d0 100644
--- a/src/plugins/avfoundation/camera/avfcamerautility.mm
+++ b/src/plugins/avfoundation/camera/avfcamerautility.mm
@@ -59,13 +59,20 @@ AVFPSRange qt_connection_framerates(AVCaptureConnection *videoConnection)
}
}
- if (videoConnection.supportsVideoMaxFrameDuration) {
- const CMTime cmMax = videoConnection.videoMaxFrameDuration;
- if (CMTimeCompare(cmMax, kCMTimeInvalid)) {
- if (const Float64 maxSeconds = CMTimeGetSeconds(cmMax))
- newRange.first = 1. / maxSeconds;
+#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_9, __IPHONE_5_0)
+#if QT_OSX_DEPLOYMENT_TARGET_BELOW(__MAC_10_9)
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_9)
+#endif
+ {
+ if (videoConnection.supportsVideoMaxFrameDuration) {
+ const CMTime cmMax = videoConnection.videoMaxFrameDuration;
+ if (CMTimeCompare(cmMax, kCMTimeInvalid)) {
+ if (const Float64 maxSeconds = CMTimeGetSeconds(cmMax))
+ newRange.first = 1. / maxSeconds;
+ }
}
}
+#endif
return newRange;
}
diff --git a/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.mm b/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.mm
index 60df1e2e..b32c0cd6 100644
--- a/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.mm
+++ b/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.mm
@@ -76,31 +76,40 @@ void qt_set_framerate_limits(AVCaptureConnection *videoConnection,
return;
}
- const qreal minFPS = settings.minimumFrameRate();
const qreal maxFPS = settings.maximumFrameRate();
-
CMTime minDuration = kCMTimeInvalid;
- CMTime maxDuration = kCMTimeInvalid;
- if (minFPS > 0. || maxFPS > 0.) {
- if (maxFPS) {
- if (!videoConnection.supportsVideoMinFrameDuration)
- qDebugCamera() << Q_FUNC_INFO << "maximum framerate is not supported";
- else
- minDuration = CMTimeMake(1, maxFPS);
- }
+ if (maxFPS > 0.) {
+ if (!videoConnection.supportsVideoMinFrameDuration)
+ qDebugCamera() << Q_FUNC_INFO << "maximum framerate is not supported";
+ else
+ minDuration = CMTimeMake(1, maxFPS);
+ }
+ if (videoConnection.supportsVideoMinFrameDuration)
+ videoConnection.videoMinFrameDuration = minDuration;
- if (minFPS) {
+ const qreal minFPS = settings.minimumFrameRate();
+#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_9, __IPHONE_5_0)
+#if QT_OSX_DEPLOYMENT_TARGET_BELOW(__MAC_10_9)
+ if (QSysInfo::MacintoshVersion < QSysInfo::MV_10_9) {
+ if (minFPS > 0.)
+ qDebugCamera() << Q_FUNC_INFO << "minimum framerate is not supported";
+ } else
+#endif
+ {
+ CMTime maxDuration = kCMTimeInvalid;
+ if (minFPS > 0.) {
if (!videoConnection.supportsVideoMaxFrameDuration)
qDebugCamera() << Q_FUNC_INFO << "minimum framerate is not supported";
else
maxDuration = CMTimeMake(1, minFPS);
}
+ if (videoConnection.supportsVideoMaxFrameDuration)
+ videoConnection.videoMaxFrameDuration = maxDuration;
}
-
- if (videoConnection.supportsVideoMinFrameDuration)
- videoConnection.videoMinFrameDuration = minDuration;
- if (videoConnection.supportsVideoMaxFrameDuration)
- videoConnection.videoMaxFrameDuration = maxDuration;
+#else
+ if (minFPS > 0.)
+ qDebugCamera() << Q_FUNC_INFO << "minimum framerate is not supported";
+#endif
}
#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0)
@@ -171,12 +180,21 @@ void qt_set_framerate_limits(AVCaptureDevice *captureDevice,
#ifdef Q_OS_IOS
[captureDevice setActiveVideoMinFrameDuration:minFrameDuration];
[captureDevice setActiveVideoMaxFrameDuration:maxFrameDuration];
-#else
+#else // Q_OS_OSX
+
if (CMTimeCompare(minFrameDuration, kCMTimeInvalid))
[captureDevice setActiveVideoMinFrameDuration:minFrameDuration];
- if (CMTimeCompare(maxFrameDuration, kCMTimeInvalid))
- [captureDevice setActiveVideoMaxFrameDuration:maxFrameDuration];
+
+#if QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_9)
+#if QT_OSX_DEPLOYMENT_TARGET_BELOW(__MAC_10_9)
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_9)
#endif
+ {
+ if (CMTimeCompare(maxFrameDuration, kCMTimeInvalid))
+ [captureDevice setActiveVideoMaxFrameDuration:maxFrameDuration];
+ }
+#endif // QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_9)
+#endif // Q_OS_OSX
}
#endif // Platform SDK >= 10.9, >= 7.0.
@@ -197,15 +215,23 @@ AVFPSRange qt_current_framerates(AVCaptureDevice *captureDevice, AVCaptureConnec
fps.second = 1. / minSeconds; // Max FPS = 1 / MinDuration.
}
- const CMTime maxDuration = captureDevice.activeVideoMaxFrameDuration;
- if (CMTimeCompare(maxDuration, kCMTimeInvalid)) {
- if (const Float64 maxSeconds = CMTimeGetSeconds(maxDuration))
- fps.first = 1. / maxSeconds; // Min FPS = 1 / MaxDuration.
+#if QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_9)
+#if QT_OSX_DEPLOYMENT_TARGET_BELOW(__MAC_10_9)
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_9)
+#endif
+ {
+ const CMTime maxDuration = captureDevice.activeVideoMaxFrameDuration;
+ if (CMTimeCompare(maxDuration, kCMTimeInvalid)) {
+ if (const Float64 maxSeconds = CMTimeGetSeconds(maxDuration))
+ fps.first = 1. / maxSeconds; // Min FPS = 1 / MaxDuration.
+ }
}
+#endif // QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_9)
+
} else {
-#else
+#else // OSX < 10.7 or iOS < 7.0
{
-#endif
+#endif // QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0)
fps = qt_connection_framerates(videoConnection);
}
@@ -459,13 +485,7 @@ QVector<QVideoFrame::PixelFormat> AVFCameraViewfinderSettingsControl2::viewfinde
Q_ASSERT(m_videoOutput);
QVector<QVideoFrame::PixelFormat> qtFormats;
- QList<QVideoFrame::PixelFormat> filter;
-
NSArray *pixelFormats = [m_videoOutput availableVideoCVPixelFormatTypes];
- const QAbstractVideoSurface *surface = m_service->videoOutput() ? m_service->videoOutput()->surface() : 0;
-
- if (surface)
- filter = surface->supportedPixelFormats();
for (NSObject *obj in pixelFormats) {
if (![obj isKindOfClass:[NSNumber class]])
@@ -474,8 +494,8 @@ QVector<QVideoFrame::PixelFormat> AVFCameraViewfinderSettingsControl2::viewfinde
NSNumber *formatAsNSNumber = static_cast<NSNumber *>(obj);
// It's actually FourCharCode (== UInt32):
const QVideoFrame::PixelFormat qtFormat(QtPixelFormatFromCVFormat([formatAsNSNumber unsignedIntValue]));
- if (qtFormat != QVideoFrame::Format_Invalid && (!surface || filter.contains(qtFormat))
- && !qtFormats.contains(qtFormat)) { // Can happen, for example, with 8BiPlanar existing in video/full range.
+ if (qtFormat != QVideoFrame::Format_Invalid
+ && !qtFormats.contains(qtFormat)) { // Can happen, for example, with 8BiPlanar existing in video/full range.
qtFormats << qtFormat;
}
}
@@ -550,22 +570,33 @@ void AVFCameraViewfinderSettingsControl2::applySettings()
#endif
unsigned avfPixelFormat = 0;
- if (m_settings.pixelFormat() != QVideoFrame::Format_Invalid &&
- convertPixelFormatIfSupported(m_settings.pixelFormat(), avfPixelFormat)) {
- [videoSettings setObject:[NSNumber numberWithUnsignedInt:avfPixelFormat]
- forKey:(id)kCVPixelBufferPixelFormatTypeKey];
- } else {
- // We have to set the pixel format, otherwise AVFoundation can change it to something we do not support.
- if (NSObject *oldFormat = [m_videoOutput.videoSettings objectForKey:(id)kCVPixelBufferPixelFormatTypeKey]) {
- [videoSettings setObject:oldFormat forKey:(id)kCVPixelBufferPixelFormatTypeKey];
- } else {
- [videoSettings setObject:[NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA]
- forKey:(id)kCVPixelBufferPixelFormatTypeKey];
+ 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();
+ QList<QVideoFrame::PixelFormat> surfaceFormats;
+ if (m_service->videoOutput() && m_service->videoOutput()->surface())
+ surfaceFormats = m_service->videoOutput()->surface()->supportedPixelFormats();
+
+ QVideoFrame::PixelFormat format = deviceFormats.first();
+
+ for (int i = 0; i < surfaceFormats.count(); ++i) {
+ const QVideoFrame::PixelFormat surfaceFormat = surfaceFormats.at(i);
+ if (deviceFormats.contains(surfaceFormat)) {
+ format = surfaceFormat;
+ break;
+ }
}
+
+ CVPixelFormatFromQtFormat(format, avfPixelFormat);
}
- if (videoSettings.count)
+ if (avfPixelFormat != 0) {
+ [videoSettings setObject:[NSNumber numberWithUnsignedInt:avfPixelFormat]
+ forKey:(id)kCVPixelBufferPixelFormatTypeKey];
+
m_videoOutput.videoSettings = videoSettings;
+ }
qt_set_framerate_limits(m_captureDevice, m_videoConnection, m_settings);
}
diff --git a/src/plugins/avfoundation/camera/avfcamerazoomcontrol.mm b/src/plugins/avfoundation/camera/avfcamerazoomcontrol.mm
index 8206112b..158073dc 100644
--- a/src/plugins/avfoundation/camera/avfcamerazoomcontrol.mm
+++ b/src/plugins/avfoundation/camera/avfcamerazoomcontrol.mm
@@ -128,11 +128,11 @@ void AVFCameraZoomControl::cameraStateChanged()
return;
}
- if (captureDevice.activeFormat.videoMaxZoomFactor > 1.
- && !qFuzzyCompare(m_maxZoomFactor, captureDevice.activeFormat.videoMaxZoomFactor)) {
- m_maxZoomFactor = captureDevice.activeFormat.videoMaxZoomFactor;
-
- Q_EMIT maximumDigitalZoomChanged(m_maxZoomFactor);
+ if (captureDevice.activeFormat.videoMaxZoomFactor > 1.) {
+ if (!qFuzzyCompare(m_maxZoomFactor, captureDevice.activeFormat.videoMaxZoomFactor)) {
+ m_maxZoomFactor = captureDevice.activeFormat.videoMaxZoomFactor;
+ Q_EMIT maximumDigitalZoomChanged(m_maxZoomFactor);
+ }
} else if (!qFuzzyCompare(m_maxZoomFactor, CGFloat(1.))) {
m_maxZoomFactor = 1.;
diff --git a/src/plugins/avfoundation/camera/avfmediaassetwriter.h b/src/plugins/avfoundation/camera/avfmediaassetwriter.h
new file mode 100644
index 00000000..eae70075
--- /dev/null
+++ b/src/plugins/avfoundation/camera/avfmediaassetwriter.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef AVFMEDIAASSETWRITER_H
+#define AVFMEDIAASSETWRITER_H
+
+#include "avfcamerautility.h"
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qatomic.h>
+#include <QtCore/qmutex.h>
+
+#include <AVFoundation/AVFoundation.h>
+
+QT_BEGIN_NAMESPACE
+
+class AVFCameraService;
+
+class AVFMediaAssetWriterDelegate
+{
+public:
+ virtual ~AVFMediaAssetWriterDelegate();
+
+ virtual void assetWriterStarted() = 0;
+ virtual void assetWriterFailedToStart() = 0;
+ virtual void assetWriterFailedToStop() = 0;
+ virtual void assetWriterFinished() = 0;
+};
+
+typedef QAtomicInteger<bool> AVFAtomicBool;
+typedef QAtomicInteger<qint64> AVFAtomicInt64;
+
+QT_END_NAMESPACE
+
+// TODO: any reasonable error handling requires smart pointers, otherwise it's getting crappy immediately.
+
+@interface QT_MANGLE_NAMESPACE(AVFMediaAssetWriter) : NSObject<AVCaptureVideoDataOutputSampleBufferDelegate,
+ AVCaptureAudioDataOutputSampleBufferDelegate>
+{
+@private
+ AVFCameraService *m_service;
+
+ QT_MANGLE_NAMESPACE(AVFScopedPointer)<AVAssetWriterInput> m_cameraWriterInput;
+ QT_MANGLE_NAMESPACE(AVFScopedPointer)<AVCaptureDeviceInput> m_audioInput;
+ QT_MANGLE_NAMESPACE(AVFScopedPointer)<AVCaptureAudioDataOutput> m_audioOutput;
+ QT_MANGLE_NAMESPACE(AVFScopedPointer)<AVAssetWriterInput> m_audioWriterInput;
+
+ // High priority serial queue for video output:
+ QT_MANGLE_NAMESPACE(AVFScopedPointer)<dispatch_queue_t> m_videoQueue;
+ // Serial queue for audio output:
+ QT_MANGLE_NAMESPACE(AVFScopedPointer)<dispatch_queue_t> m_audioQueue;
+ // Queue to write sample buffers:
+ __weak dispatch_queue_t m_writerQueue;
+
+ QT_MANGLE_NAMESPACE(AVFScopedPointer)<AVAssetWriter> m_assetWriter;
+ // Delegate's queue.
+ __weak dispatch_queue_t m_delegateQueue;
+ // TODO: QPointer??
+ QT_PREPEND_NAMESPACE(AVFMediaAssetWriterDelegate) *m_delegate;
+
+ bool m_setStartTime;
+ QT_MANGLE_NAMESPACE(AVFAtomicBool) m_stopped;
+ bool m_stoppedInternal;
+ bool m_aborted;
+
+ QT_MANGLE_NAMESPACE(QMutex) m_writerMutex;
+@public
+ QT_MANGLE_NAMESPACE(AVFAtomicInt64) m_durationInMs;
+@private
+ CMTime m_startTime;
+ CMTime m_lastTimeStamp;
+}
+
+- (id)initWithQueue:(dispatch_queue_t)writerQueue
+ delegate:(QT_PREPEND_NAMESPACE(AVFMediaAssetWriterDelegate) *)delegate
+ delegateQueue:(dispatch_queue_t)delegateQueue;
+
+- (bool)setupWithFileURL:(NSURL *)fileURL
+ cameraService:(QT_PREPEND_NAMESPACE(AVFCameraService) *)service;
+
+- (void)start;
+- (void)stop;
+// This to be called if control's dtor gets called,
+// on the control's thread.
+- (void)abort;
+
+@end
+
+#endif // AVFMEDIAASSETWRITER_H
diff --git a/src/plugins/avfoundation/camera/avfmediaassetwriter.mm b/src/plugins/avfoundation/camera/avfmediaassetwriter.mm
new file mode 100644
index 00000000..37004c1d
--- /dev/null
+++ b/src/plugins/avfoundation/camera/avfmediaassetwriter.mm
@@ -0,0 +1,474 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "avfaudioinputselectorcontrol.h"
+#include "avfcamerarenderercontrol.h"
+#include "avfmediaassetwriter.h"
+#include "avfcameraservice.h"
+#include "avfcamerasession.h"
+#include "avfcameradebug.h"
+
+//#include <QtCore/qmutexlocker.h>
+#include <QtCore/qsysinfo.h>
+
+QT_USE_NAMESPACE
+
+namespace {
+
+bool qt_camera_service_isValid(AVFCameraService *service)
+{
+ if (!service || !service->session())
+ return false;
+
+ AVFCameraSession *session = service->session();
+ if (!session->captureSession())
+ return false;
+
+ if (!session->videoInput())
+ return false;
+
+ if (!service->videoOutput()
+ || !service->videoOutput()->videoDataOutput()) {
+ return false;
+ }
+
+ return true;
+}
+
+}
+
+AVFMediaAssetWriterDelegate::~AVFMediaAssetWriterDelegate()
+{
+}
+
+@interface QT_MANGLE_NAMESPACE(AVFMediaAssetWriter) (PrivateAPI)
+- (bool)addAudioCapture;
+- (bool)addWriterInputs;
+- (void)setQueues;
+- (NSDictionary *)videoSettings;
+- (NSDictionary *)audioSettings;
+- (void)updateDuration:(CMTime)newTimeStamp;
+@end
+
+@implementation QT_MANGLE_NAMESPACE(AVFMediaAssetWriter)
+
+- (id)initWithQueue:(dispatch_queue_t)writerQueue
+ delegate:(AVFMediaAssetWriterDelegate *)delegate
+ delegateQueue:(dispatch_queue_t)delegateQueue
+{
+ Q_ASSERT(writerQueue);
+ Q_ASSERT(delegate);
+ Q_ASSERT(delegateQueue);
+
+ if (self = [super init]) {
+ m_writerQueue = writerQueue;
+ m_delegate = delegate;
+ m_delegateQueue = delegateQueue;
+ m_setStartTime = true;
+ m_stopped.store(true);
+ m_stoppedInternal = false;
+ m_aborted = false;
+ m_startTime = kCMTimeInvalid;
+ m_lastTimeStamp = kCMTimeInvalid;
+ m_durationInMs.store(0);
+ }
+
+ return self;
+}
+
+- (bool)setupWithFileURL:(NSURL *)fileURL
+ cameraService:(AVFCameraService *)service
+{
+ Q_ASSERT(fileURL);
+
+ if (!qt_camera_service_isValid(service)) {
+ qDebugCamera() << Q_FUNC_INFO << "invalid camera service";
+ return false;
+ }
+
+ m_service = service;
+
+ m_videoQueue.reset(dispatch_queue_create("video-output-queue", DISPATCH_QUEUE_SERIAL));
+ if (!m_videoQueue) {
+ qDebugCamera() << Q_FUNC_INFO << "failed to create video queue";
+ return false;
+ }
+ dispatch_set_target_queue(m_videoQueue, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0));
+ m_audioQueue.reset(dispatch_queue_create("audio-output-queue", DISPATCH_QUEUE_SERIAL));
+ if (!m_audioQueue) {
+ qDebugCamera() << Q_FUNC_INFO << "failed to create audio queue";
+ // But we still can write video!
+ }
+
+ m_assetWriter.reset([[AVAssetWriter alloc] initWithURL:fileURL fileType:AVFileTypeQuickTimeMovie error:nil]);
+ if (!m_assetWriter) {
+ qDebugCamera() << Q_FUNC_INFO << "failed to create asset writer";
+ return false;
+ }
+
+ bool audioCaptureOn = false;
+
+ if (m_audioQueue)
+ audioCaptureOn = [self addAudioCapture];
+
+ if (![self addWriterInputs]) {
+ if (audioCaptureOn) {
+ AVCaptureSession *session = m_service->session()->captureSession();
+ [session removeOutput:m_audioOutput];
+ [session removeInput:m_audioInput];
+ m_audioOutput.reset();
+ m_audioInput.reset();
+ }
+ m_assetWriter.reset();
+ return false;
+ }
+ // Ready to start ...
+ return true;
+}
+
+- (void)start
+{
+ // To be executed on a writer's queue.
+ const QMutexLocker lock(&m_writerMutex);
+ if (m_aborted)
+ return;
+
+ [self setQueues];
+
+ m_setStartTime = true;
+ m_stopped.store(false);
+ m_stoppedInternal = false;
+ [m_assetWriter startWriting];
+ AVCaptureSession *session = m_service->session()->captureSession();
+ if (!session.running)
+ [session startRunning];
+}
+
+- (void)stop
+{
+ // To be executed on a writer's queue.
+ const QMutexLocker lock(&m_writerMutex);
+ if (m_aborted)
+ return;
+
+ if (m_stopped.load()) {
+ // Should never happen, but ...
+ // if something went wrong in a recorder control
+ // and we set state stopped without starting first ...
+ // m_stoppedIntenal will be false, but m_stopped - true.
+ return;
+ }
+
+ m_stopped.store(true);
+ m_stoppedInternal = true;
+ [m_assetWriter finishWritingWithCompletionHandler:^{
+ // TODO: make sure the session exist and we can call stop/remove on it.
+ AVCaptureSession *session = m_service->session()->captureSession();
+ [session stopRunning];
+ [session removeOutput:m_audioOutput];
+ [session removeInput:m_audioInput];
+ dispatch_async(m_delegateQueue, ^{
+ m_delegate->assetWriterFinished();
+ });
+ }];
+}
+
+- (void)abort
+{
+ // To be executed on any thread, prevents writer from
+ // accessing any external object (probably deleted by this time)
+ const QMutexLocker lock(&m_writerMutex);
+ m_aborted = true;
+ if (m_stopped.load())
+ return;
+ [m_assetWriter finishWritingWithCompletionHandler:^{
+ }];
+}
+
+- (void)setStartTimeFrom:(CMSampleBufferRef)sampleBuffer
+{
+ // Writer's queue only.
+ Q_ASSERT(m_setStartTime);
+ Q_ASSERT(sampleBuffer);
+
+ dispatch_async(m_delegateQueue, ^{
+ m_delegate->assetWriterStarted();
+ });
+
+ m_durationInMs.store(0);
+ m_startTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);
+ m_lastTimeStamp = m_startTime;
+ [m_assetWriter startSessionAtSourceTime:m_startTime];
+ m_setStartTime = false;
+}
+
+- (void)writeVideoSampleBuffer:(CMSampleBufferRef)sampleBuffer
+{
+ Q_ASSERT(sampleBuffer);
+
+ // This code is executed only on a writer's queue, but
+ // it can access potentially deleted objects, so we
+ // need a lock and m_aborted flag test.
+ {
+ const QMutexLocker lock(&m_writerMutex);
+ if (!m_aborted && !m_stoppedInternal) {
+ if (m_setStartTime)
+ [self setStartTimeFrom:sampleBuffer];
+
+ if (m_cameraWriterInput.data().readyForMoreMediaData) {
+ [self updateDuration:CMSampleBufferGetPresentationTimeStamp(sampleBuffer)];
+ [m_cameraWriterInput appendSampleBuffer:sampleBuffer];
+ }
+ }
+ }
+
+ CFRelease(sampleBuffer);
+}
+
+- (void)writeAudioSampleBuffer:(CMSampleBufferRef)sampleBuffer
+{
+ // This code is executed only on a writer's queue.
+ // it does not touch any shared/external data.
+ Q_ASSERT(sampleBuffer);
+
+ {
+ const QMutexLocker lock(&m_writerMutex);
+ if (!m_aborted && !m_stoppedInternal) {
+ if (m_setStartTime)
+ [self setStartTimeFrom:sampleBuffer];
+
+ if (m_audioWriterInput.data().readyForMoreMediaData) {
+ [self updateDuration:CMSampleBufferGetPresentationTimeStamp(sampleBuffer)];
+ [m_audioWriterInput appendSampleBuffer:sampleBuffer];
+ }
+ }
+ }
+
+ CFRelease(sampleBuffer);
+}
+
+- (void)captureOutput:(AVCaptureOutput *)captureOutput
+ didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
+ fromConnection:(AVCaptureConnection *)connection
+{
+ Q_UNUSED(connection)
+
+ // This method can be called on either video or audio queue, never on a writer's
+ // queue - it does not access any shared data except this atomic flag below.
+ if (m_stopped.load())
+ return;
+
+ // Even if we are stopped now, we still do not access any data.
+
+ if (!CMSampleBufferDataIsReady(sampleBuffer)) {
+ qDebugCamera() << Q_FUNC_INFO << "sample buffer is not ready, skipping.";
+ return;
+ }
+
+ CFRetain(sampleBuffer);
+
+ if (captureOutput != m_audioOutput.data()) {
+ {
+ const QMutexLocker lock(&m_writerMutex);
+ if (m_aborted || m_stoppedInternal) {
+ CFRelease(sampleBuffer);
+ return;
+ }
+
+ // Find renderercontrol's delegate and invoke its method to
+ // show updated viewfinder's frame.
+ if (m_service && m_service->videoOutput()) {
+ NSObject<AVCaptureVideoDataOutputSampleBufferDelegate> *vfDelegate =
+ (NSObject<AVCaptureVideoDataOutputSampleBufferDelegate> *)m_service->videoOutput()->captureDelegate();
+ if (vfDelegate)
+ [vfDelegate captureOutput:nil didOutputSampleBuffer:sampleBuffer fromConnection:nil];
+ }
+ }
+
+ dispatch_async(m_writerQueue, ^{
+ [self writeVideoSampleBuffer:sampleBuffer];
+ });
+ } else {
+ dispatch_async(m_writerQueue, ^{
+ [self writeAudioSampleBuffer:sampleBuffer];
+ });
+ }
+}
+
+- (bool)addAudioCapture
+{
+ Q_ASSERT(m_service && m_service->session() && m_service->session()->captureSession());
+
+ if (!m_service->audioInputSelectorControl())
+ return false;
+
+ AVCaptureSession *captureSession = m_service->session()->captureSession();
+
+ AVCaptureDevice *audioDevice = m_service->audioInputSelectorControl()->createCaptureDevice();
+ if (!audioDevice) {
+ qWarning() << Q_FUNC_INFO << "no audio input device available";
+ return false;
+ } else {
+ NSError *error = nil;
+ m_audioInput.reset([[AVCaptureDeviceInput deviceInputWithDevice:audioDevice error:&error] retain]);
+
+ if (!m_audioInput || error) {
+ qWarning() << Q_FUNC_INFO << "failed to create audio device input";
+ m_audioInput.reset();
+ return false;
+ } else if (![captureSession canAddInput:m_audioInput]) {
+ qWarning() << Q_FUNC_INFO << "could not connect the audio input";
+ m_audioInput.reset();
+ return false;
+ } else {
+ [captureSession addInput:m_audioInput];
+ }
+ }
+
+
+ m_audioOutput.reset([[AVCaptureAudioDataOutput alloc] init]);
+ if (m_audioOutput && [captureSession canAddOutput:m_audioOutput]) {
+ [captureSession addOutput:m_audioOutput];
+ } else {
+ qDebugCamera() << Q_FUNC_INFO << "failed to add audio output";
+ [captureSession removeInput:m_audioInput];
+ m_audioInput.reset();
+ m_audioOutput.reset();
+ return false;
+ }
+
+ return true;
+}
+
+- (bool)addWriterInputs
+{
+ Q_ASSERT(m_service && m_service->videoOutput()
+ && m_service->videoOutput()->videoDataOutput());
+ Q_ASSERT(m_assetWriter);
+
+ m_cameraWriterInput.reset([[AVAssetWriterInput alloc] initWithMediaType:AVMediaTypeVideo outputSettings:[self videoSettings]]);
+ if (!m_cameraWriterInput) {
+ qDebugCamera() << Q_FUNC_INFO << "failed to create camera writer input";
+ return false;
+ }
+
+ if ([m_assetWriter canAddInput:m_cameraWriterInput]) {
+ [m_assetWriter addInput:m_cameraWriterInput];
+ } else {
+ qDebugCamera() << Q_FUNC_INFO << "failed to add camera writer input";
+ m_cameraWriterInput.reset();
+ return false;
+ }
+
+ m_cameraWriterInput.data().expectsMediaDataInRealTime = YES;
+
+ if (m_audioOutput) {
+ m_audioWriterInput.reset([[AVAssetWriterInput alloc] initWithMediaType:AVMediaTypeAudio outputSettings:[self audioSettings]]);
+ if (!m_audioWriterInput) {
+ qDebugCamera() << Q_FUNC_INFO << "failed to create audio writer input";
+ // But we still can record video.
+ } else if ([m_assetWriter canAddInput:m_audioWriterInput]) {
+ [m_assetWriter addInput:m_audioWriterInput];
+ m_audioWriterInput.data().expectsMediaDataInRealTime = YES;
+ } else {
+ qDebugCamera() << Q_FUNC_INFO << "failed to add audio writer input";
+ m_audioWriterInput.reset();
+ // We can (still) write video though ...
+ }
+ }
+
+ return true;
+}
+
+- (void)setQueues
+{
+ Q_ASSERT(m_service && m_service->videoOutput() && m_service->videoOutput()->videoDataOutput());
+ Q_ASSERT(m_videoQueue);
+
+ [m_service->videoOutput()->videoDataOutput() setSampleBufferDelegate:self queue:m_videoQueue];
+
+ if (m_audioOutput) {
+ Q_ASSERT(m_audioQueue);
+ [m_audioOutput setSampleBufferDelegate:self queue:m_audioQueue];
+ }
+}
+
+
+- (NSDictionary *)videoSettings
+{
+ // TODO: these settings should be taken from
+ // the video encoding settings control.
+ // For now we either take recommended (iOS >= 7.0)
+ // or some hardcoded values - they are still better than nothing (nil).
+#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_7_0)
+ AVCaptureVideoDataOutput *videoOutput = m_service->videoOutput()->videoDataOutput();
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_7_0 && videoOutput)
+ return [videoOutput recommendedVideoSettingsForAssetWriterWithOutputFileType:AVFileTypeQuickTimeMovie];
+#endif
+ NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:AVVideoCodecH264, AVVideoCodecKey,
+ [NSNumber numberWithInt:1280], AVVideoWidthKey,
+ [NSNumber numberWithInt:720], AVVideoHeightKey, nil];
+
+ return videoSettings;
+}
+
+- (NSDictionary *)audioSettings
+{
+ // TODO: these settings should be taken from
+ // the video/audio encoder settings control.
+ // For now we either take recommended (iOS >= 7.0)
+ // or nil - this seems to be good enough.
+#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_7_0)
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_7_0 && m_audioOutput)
+ return [m_audioOutput recommendedAudioSettingsForAssetWriterWithOutputFileType:AVFileTypeQuickTimeMovie];
+#endif
+
+ return nil;
+}
+
+- (void)updateDuration:(CMTime)newTimeStamp
+{
+ Q_ASSERT(CMTimeCompare(m_startTime, kCMTimeInvalid));
+ Q_ASSERT(CMTimeCompare(m_lastTimeStamp, kCMTimeInvalid));
+ if (CMTimeCompare(newTimeStamp, m_lastTimeStamp) > 0) {
+
+ const CMTime duration = CMTimeSubtract(newTimeStamp, m_startTime);
+ if (!CMTimeCompare(duration, kCMTimeInvalid))
+ return;
+
+ m_durationInMs.store(CMTimeGetSeconds(duration) * 1000);
+ m_lastTimeStamp = newTimeStamp;
+ }
+}
+
+@end
diff --git a/src/plugins/avfoundation/camera/avfmediarecordercontrol_ios.h b/src/plugins/avfoundation/camera/avfmediarecordercontrol_ios.h
new file mode 100644
index 00000000..78576948
--- /dev/null
+++ b/src/plugins/avfoundation/camera/avfmediarecordercontrol_ios.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef AVFMEDIARECORDERCONTROL_IOS_H
+#define AVFMEDIARECORDERCONTROL_IOS_H
+
+#include "avfmediaassetwriter.h"
+#include "avfstoragelocation.h"
+#include "avfcamerautility.h"
+
+#include <QtMultimedia/qmediarecordercontrol.h>
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qurl.h>
+
+#include <AVFoundation/AVFoundation.h>
+
+QT_BEGIN_NAMESPACE
+
+class AVFCameraService;
+class QString;
+class QUrl;
+
+class AVFMediaRecorderControlIOS : public QMediaRecorderControl, public AVFMediaAssetWriterDelegate
+{
+ Q_OBJECT
+public:
+ AVFMediaRecorderControlIOS(AVFCameraService *service, QObject *parent = 0);
+ ~AVFMediaRecorderControlIOS();
+
+ QUrl outputLocation() const Q_DECL_OVERRIDE;
+ bool setOutputLocation(const QUrl &location) Q_DECL_OVERRIDE;
+
+ QMediaRecorder::State state() const Q_DECL_OVERRIDE;
+ QMediaRecorder::Status status() const Q_DECL_OVERRIDE;
+
+ qint64 duration() const Q_DECL_OVERRIDE;
+
+ bool isMuted() const Q_DECL_OVERRIDE;
+ qreal volume() const Q_DECL_OVERRIDE;
+
+ void applySettings() Q_DECL_OVERRIDE;
+
+public Q_SLOTS:
+ void setState(QMediaRecorder::State state) Q_DECL_OVERRIDE;
+ void setMuted(bool muted) Q_DECL_OVERRIDE;
+ void setVolume(qreal volume) Q_DECL_OVERRIDE;
+
+ // Writer delegate:
+private:
+
+ void assetWriterStarted() Q_DECL_OVERRIDE;
+ void assetWriterFailedToStart() Q_DECL_OVERRIDE;
+ void assetWriterFailedToStop() Q_DECL_OVERRIDE;
+ void assetWriterFinished() Q_DECL_OVERRIDE;
+
+private Q_SLOTS:
+ void captureModeChanged(QCamera::CaptureModes);
+ void cameraStatusChanged(QCamera::Status newStatus);
+
+private:
+ void stopWriter();
+
+ AVFCameraService *m_service;
+
+ AVFScopedPointer<dispatch_queue_t> m_writerQueue;
+ AVFScopedPointer<QT_MANGLE_NAMESPACE(AVFMediaAssetWriter)> m_writer;
+
+ QUrl m_outputLocation;
+ AVFStorageLocation m_storageLocation;
+
+ QMediaRecorder::State m_state;
+ QMediaRecorder::Status m_lastStatus;
+};
+
+QT_END_NAMESPACE
+
+#endif // AVFMEDIARECORDERCONTROL_IOS_H
diff --git a/src/plugins/avfoundation/camera/avfmediarecordercontrol_ios.mm b/src/plugins/avfoundation/camera/avfmediarecordercontrol_ios.mm
new file mode 100644
index 00000000..b763dbcc
--- /dev/null
+++ b/src/plugins/avfoundation/camera/avfmediarecordercontrol_ios.mm
@@ -0,0 +1,349 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd and/or its subsidiary(-ies).
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "avfmediarecordercontrol_ios.h"
+#include "avfcamerarenderercontrol.h"
+#include "avfcamerasession.h"
+#include "avfcameracontrol.h"
+#include "avfcameraservice.h"
+#include "avfcameradebug.h"
+
+#include <QtCore/qdebug.h>
+
+QT_USE_NAMESPACE
+
+namespace {
+
+bool qt_is_writable_file_URL(NSURL *fileURL)
+{
+ Q_ASSERT(fileURL);
+
+ if (![fileURL isFileURL])
+ return false;
+
+ if (NSString *path = [[fileURL path] stringByExpandingTildeInPath]) {
+ return [[NSFileManager defaultManager]
+ isWritableFileAtPath:[path stringByDeletingLastPathComponent]];
+ }
+
+ return false;
+}
+
+bool qt_file_exists(NSURL *fileURL)
+{
+ Q_ASSERT(fileURL);
+
+ if (NSString *path = [[fileURL path] stringByExpandingTildeInPath])
+ return [[NSFileManager defaultManager] fileExistsAtPath:path];
+
+ return false;
+}
+
+}
+
+AVFMediaRecorderControlIOS::AVFMediaRecorderControlIOS(AVFCameraService *service, QObject *parent)
+ : QMediaRecorderControl(parent)
+ , m_service(service)
+ , m_state(QMediaRecorder::StoppedState)
+ , m_lastStatus(QMediaRecorder::UnloadedStatus)
+{
+ Q_ASSERT(service);
+
+ m_writerQueue.reset(dispatch_queue_create("asset-writer-queue", DISPATCH_QUEUE_SERIAL));
+ if (!m_writerQueue) {
+ qDebugCamera() << Q_FUNC_INFO << "failed to create an asset writer's queue";
+ return;
+ }
+
+ m_writer.reset([[QT_MANGLE_NAMESPACE(AVFMediaAssetWriter) alloc] initWithQueue:m_writerQueue
+ delegate:this delegateQueue:dispatch_get_main_queue()]);
+ if (!m_writer) {
+ qDebugCamera() << Q_FUNC_INFO << "failed to create an asset writer";
+ return;
+ }
+
+ AVFCameraControl *cameraControl = m_service->cameraControl();
+ if (!cameraControl) {
+ qDebugCamera() << Q_FUNC_INFO << "camera control is nil";
+ return;
+ }
+
+ connect(cameraControl, SIGNAL(captureModeChanged(QCamera::CaptureModes)),
+ SLOT(captureModeChanged(QCamera::CaptureModes)));
+ connect(cameraControl, SIGNAL(statusChanged(QCamera::Status)),
+ SLOT(cameraStatusChanged(QCamera::Status)));
+}
+
+AVFMediaRecorderControlIOS::~AVFMediaRecorderControlIOS()
+{
+ [m_writer abort];
+}
+
+QUrl AVFMediaRecorderControlIOS::outputLocation() const
+{
+ return m_outputLocation;
+}
+
+bool AVFMediaRecorderControlIOS::setOutputLocation(const QUrl &location)
+{
+ m_outputLocation = location;
+ return location.scheme() == QLatin1String("file") || location.scheme().isEmpty();
+}
+
+QMediaRecorder::State AVFMediaRecorderControlIOS::state() const
+{
+ return m_state;
+}
+
+QMediaRecorder::Status AVFMediaRecorderControlIOS::status() const
+{
+ return m_lastStatus;
+}
+
+qint64 AVFMediaRecorderControlIOS::duration() const
+{
+ return m_writer.data()->m_durationInMs.load();
+}
+
+bool AVFMediaRecorderControlIOS::isMuted() const
+{
+ return false;
+}
+
+qreal AVFMediaRecorderControlIOS::volume() const
+{
+ return 1.;
+}
+
+void AVFMediaRecorderControlIOS::applySettings()
+{
+}
+
+void AVFMediaRecorderControlIOS::setState(QMediaRecorder::State state)
+{
+ Q_ASSERT(m_service->session()
+ && m_service->session()->captureSession());
+
+ if (!m_writer) {
+ qDebugCamera() << Q_FUNC_INFO << "Invalid recorder";
+ return;
+ }
+
+ if (state == m_state)
+ return;
+
+ switch (state) {
+ case QMediaRecorder::RecordingState:
+ {
+ AVFCameraControl *cameraControl = m_service->cameraControl();
+ Q_ASSERT(cameraControl);
+
+ if (!(cameraControl->captureMode() & QCamera::CaptureVideo)) {
+ qDebugCamera() << Q_FUNC_INFO << "wrong capture mode, CaptureVideo expected";
+ Q_EMIT error(QMediaRecorder::ResourceError, tr("Failed to start recording"));
+ return;
+ }
+
+ if (cameraControl->status() != QCamera::ActiveStatus) {
+ qDebugCamera() << Q_FUNC_INFO << "can not start record while camera is not active";
+ Q_EMIT error(QMediaRecorder::ResourceError, tr("Failed to start recording"));
+ return;
+ }
+
+ const QString path(m_outputLocation.scheme() == QLatin1String("file") ?
+ m_outputLocation.path() : m_outputLocation.toString());
+ const QUrl fileURL(QUrl::fromLocalFile(m_storageLocation.generateFileName(path, QCamera::CaptureVideo,
+ QLatin1String("clip_"), QLatin1String("mp4"))));
+
+ NSURL *nsFileURL = fileURL.toNSURL();
+ if (!nsFileURL) {
+ qWarning() << Q_FUNC_INFO << "invalid output URL:" << fileURL;
+ Q_EMIT error(QMediaRecorder::ResourceError, tr("Invalid output file URL"));
+ return;
+ }
+ if (!qt_is_writable_file_URL(nsFileURL)) {
+ qWarning() << Q_FUNC_INFO << "invalid output URL:" << fileURL
+ << "(the location is not writable)";
+ Q_EMIT error(QMediaRecorder::ResourceError, tr("Non-writeable file location"));
+ return;
+ }
+ if (qt_file_exists(nsFileURL)) {
+ // We test for/handle this error here since AWAssetWriter will raise an
+ // Objective-C exception, which is not good at all.
+ qWarning() << Q_FUNC_INFO << "invalid output URL:" << fileURL
+ << "(file already exists)";
+ Q_EMIT error(QMediaRecorder::ResourceError, tr("File already exists"));
+ return;
+ }
+
+ AVCaptureSession *session = m_service->session()->captureSession();
+ // We stop session now so that no more frames for renderer's queue
+ // generated, will restart in assetWriterStarted.
+ [session stopRunning];
+
+ if ([m_writer setupWithFileURL:nsFileURL cameraService:m_service]) {
+ m_state = QMediaRecorder::RecordingState;
+ m_lastStatus = QMediaRecorder::StartingStatus;
+
+ Q_EMIT actualLocationChanged(fileURL);
+ Q_EMIT stateChanged(m_state);
+ Q_EMIT statusChanged(m_lastStatus);
+
+ dispatch_async(m_writerQueue, ^{
+ [m_writer start];
+ });
+ } else {
+ [session startRunning];
+ Q_EMIT error(QMediaRecorder::FormatError, tr("Failed to start recording"));
+ }
+ } break;
+ case QMediaRecorder::PausedState:
+ {
+ Q_EMIT error(QMediaRecorder::FormatError, tr("Recording pause not supported"));
+ return;
+ } break;
+ case QMediaRecorder::StoppedState:
+ {
+ // Do not check the camera status, we can stop if we started.
+ stopWriter();
+ }
+ }
+}
+
+void AVFMediaRecorderControlIOS::setMuted(bool muted)
+{
+ Q_UNUSED(muted)
+ qDebugCamera() << Q_FUNC_INFO << "not implemented";
+}
+
+void AVFMediaRecorderControlIOS::setVolume(qreal volume)
+{
+ Q_UNUSED(volume);
+ qDebugCamera() << Q_FUNC_INFO << "not implemented";
+}
+
+void AVFMediaRecorderControlIOS::assetWriterStarted()
+{
+ m_lastStatus = QMediaRecorder::RecordingStatus;
+ Q_EMIT statusChanged(QMediaRecorder::RecordingStatus);
+}
+
+void AVFMediaRecorderControlIOS::assetWriterFailedToStart()
+{
+}
+
+void AVFMediaRecorderControlIOS::assetWriterFailedToStop()
+{
+}
+
+void AVFMediaRecorderControlIOS::assetWriterFinished()
+{
+ AVFCameraControl *cameraControl = m_service->cameraControl();
+ Q_ASSERT(cameraControl);
+
+ const QMediaRecorder::Status lastStatus = m_lastStatus;
+
+ if (cameraControl->captureMode() & QCamera::CaptureVideo)
+ m_lastStatus = QMediaRecorder::LoadedStatus;
+ else
+ m_lastStatus = QMediaRecorder::UnloadedStatus;
+
+ m_service->videoOutput()->resetCaptureDelegate();
+ [m_service->session()->captureSession() startRunning];
+
+ if (m_lastStatus != lastStatus)
+ Q_EMIT statusChanged(m_lastStatus);
+}
+
+void AVFMediaRecorderControlIOS::captureModeChanged(QCamera::CaptureModes newMode)
+{
+ AVFCameraControl *cameraControl = m_service->cameraControl();
+ Q_ASSERT(cameraControl);
+
+ const QMediaRecorder::Status lastStatus = m_lastStatus;
+
+ if (newMode & QCamera::CaptureVideo) {
+ if (cameraControl->status() == QCamera::ActiveStatus)
+ m_lastStatus = QMediaRecorder::LoadedStatus;
+ } else {
+ if (m_lastStatus == QMediaRecorder::RecordingStatus)
+ return stopWriter();
+ else
+ m_lastStatus = QMediaRecorder::UnloadedStatus;
+ }
+
+ if (m_lastStatus != lastStatus)
+ Q_EMIT statusChanged(m_lastStatus);
+}
+
+void AVFMediaRecorderControlIOS::cameraStatusChanged(QCamera::Status newStatus)
+{
+ AVFCameraControl *cameraControl = m_service->cameraControl();
+ Q_ASSERT(cameraControl);
+
+ const QMediaRecorder::Status lastStatus = m_lastStatus;
+ const bool isCapture = cameraControl->captureMode() & QCamera::CaptureVideo;
+ if (newStatus == QCamera::StartingStatus) {
+ if (isCapture && m_lastStatus == QMediaRecorder::UnloadedStatus)
+ m_lastStatus = QMediaRecorder::LoadingStatus;
+ } else if (newStatus == QCamera::ActiveStatus) {
+ if (isCapture && m_lastStatus == QMediaRecorder::LoadingStatus)
+ m_lastStatus = QMediaRecorder::LoadedStatus;
+ } else {
+ if (m_lastStatus == QMediaRecorder::RecordingStatus)
+ return stopWriter();
+ if (newStatus == QCamera::UnloadedStatus)
+ m_lastStatus = QMediaRecorder::UnloadedStatus;
+ }
+
+ if (lastStatus != m_lastStatus)
+ Q_EMIT statusChanged(m_lastStatus);
+}
+
+void AVFMediaRecorderControlIOS::stopWriter()
+{
+ if (m_lastStatus == QMediaRecorder::RecordingStatus) {
+ m_state = QMediaRecorder::StoppedState;
+ m_lastStatus = QMediaRecorder::FinalizingStatus;
+
+ Q_EMIT stateChanged(m_state);
+ Q_EMIT statusChanged(m_lastStatus);
+
+ dispatch_async(m_writerQueue, ^{
+ [m_writer stop];
+ });
+ }
+}
+
+#include "moc_avfmediarecordercontrol_ios.cpp"
diff --git a/src/plugins/avfoundation/camera/camera.pro b/src/plugins/avfoundation/camera/camera.pro
index ac389df7..62afdcd8 100644
--- a/src/plugins/avfoundation/camera/camera.pro
+++ b/src/plugins/avfoundation/camera/camera.pro
@@ -27,7 +27,6 @@ HEADERS += \
avfcameracontrol.h \
avfcamerametadatacontrol.h \
avfimagecapturecontrol.h \
- avfmediarecordercontrol.h \
avfcameraservice.h \
avfcamerasession.h \
avfstoragelocation.h \
@@ -49,7 +48,6 @@ OBJECTIVE_SOURCES += \
avfcameracontrol.mm \
avfcamerametadatacontrol.mm \
avfimagecapturecontrol.mm \
- avfmediarecordercontrol.mm \
avfcameraservice.mm \
avfcamerasession.mm \
avfstoragelocation.mm \
@@ -66,9 +64,20 @@ OBJECTIVE_SOURCES += \
avfimageencodercontrol.mm \
avfcameraflashcontrol.mm
+osx {
+
+HEADERS += avfmediarecordercontrol.h
+OBJECTIVE_SOURCES += avfmediarecordercontrol.mm
+
+}
+
ios {
-HEADERS += avfcamerazoomcontrol.h
-OBJECTIVE_SOURCES += avfcamerazoomcontrol.mm
+HEADERS += avfcamerazoomcontrol.h \
+ avfmediaassetwriter.h \
+ avfmediarecordercontrol_ios.h
+OBJECTIVE_SOURCES += avfcamerazoomcontrol.mm \
+ avfmediaassetwriter.mm \
+ avfmediarecordercontrol_ios.mm
}
diff --git a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm
index 005c00a1..5ef1f9ba 100644
--- a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm
+++ b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm
@@ -728,7 +728,7 @@ void AVFMediaPlayerSession::setVolume(int volume)
return;
}
- [player setVolume:m_volume / 100.0f];
+ [player setVolume:volume / 100.0f];
m_volume = volume;
Q_EMIT volumeChanged(m_volume);
@@ -752,7 +752,7 @@ void AVFMediaPlayerSession::setMuted(bool muted)
return;
}
- [player setMuted:m_muted];
+ [player setMuted:muted];
m_muted = muted;
Q_EMIT mutedChanged(muted);
diff --git a/src/plugins/videonode/imx6/qsgvivantevideomaterial.cpp b/src/plugins/videonode/imx6/qsgvivantevideomaterial.cpp
index ab6bcd52..2e2092be 100644
--- a/src/plugins/videonode/imx6/qsgvivantevideomaterial.cpp
+++ b/src/plugins/videonode/imx6/qsgvivantevideomaterial.cpp
@@ -60,6 +60,8 @@ QSGVivanteVideoMaterial::QSGVivanteVideoMaterial() :
#endif
setFlag(Blending, false);
+
+ mShader = new QSGVivanteVideoMaterialShader;
}
QSGVivanteVideoMaterial::~QSGVivanteVideoMaterial()
@@ -73,7 +75,7 @@ QSGMaterialType *QSGVivanteVideoMaterial::type() const {
}
QSGMaterialShader *QSGVivanteVideoMaterial::createShader() const {
- return new QSGVivanteVideoMaterialShader;
+ return mShader;
}
int QSGVivanteVideoMaterial::compare(const QSGMaterial *other) const {
@@ -175,18 +177,49 @@ GLuint QSGVivanteVideoMaterial::vivanteMapping(QVideoFrame vF)
glGenTextures(1, &tmpTexId);
mBitsToTextureMap.insert(vF.bits(), tmpTexId);
+ // Determine the full width & height. Full means: actual width/height plus extra padding pixels.
+ // The full width can be deduced from the bytesPerLine value. The full height is calculated
+ // by calculating the distance between the start of the first and second planes, and dividing
+ // it by the stride (= the bytesPerLine). If there is only one plane, we don't worry about
+ // extra padding rows, since there are no adjacent extra planes.
+ // XXX: This assumes the distance between bits(1) and bits(0) is exactly the size of the first
+ // plane (the Y plane in the case of YUV data). A better way would be to have a dedicated
+ // planeSize() or planeOffset() getter.
+ // Also, this assumes that planes are tightly packed, that is, there is no space between them.
+ // It is okay to assume this here though, because the Vivante direct textures also assume that.
+ // In other words, if the planes aren't tightly packed, then the direct textures won't be able
+ // to render the frame correctly anyway.
+ int fullWidth = vF.bytesPerLine() / QSGVivanteVideoNode::getBytesForPixelFormat(vF.pixelFormat());
+ int fullHeight = (vF.planeCount() > 1) ? ((vF.bits(1) - vF.bits(0)) / vF.bytesPerLine()) : vF.height();
+
+ // The uscale is the ratio of actual width to the full width (same for vscale and height).
+ // Since the vivante direct textures do not offer a way to explicitly specify the amount of padding
+ // columns and rows, we use a trick. We show the full frame - including the padding pixels - in the
+ // texture, but render only a subset of that texture. This subset goes from (0,0) to (uScale, vScale).
+ // In the shader, the texture coordinates (which go from (0.0, 0.0) to (1.0, 1.0)) are multiplied by
+ // the u/v scale values. Since 1.0 * x = x, this effectively limits the texture coordinates from
+ // (0.0, 0.0) - (1.0, 1.0) to (0.0, 0.0) - (uScale, vScale).
+ float uScale = float(vF.width()) / float(fullWidth);
+ float vScale = float(vF.height()) / float(fullHeight);
+ mShader->setUVScale(uScale, vScale);
+
const uchar *constBits = vF.bits();
void *bits = (void*)constBits;
#ifdef QT_VIVANTE_VIDEO_DEBUG
- qDebug() << Q_FUNC_INFO << "new texture, texId: " << tmpTexId << "; constBits: " << constBits;
+ qDebug() << Q_FUNC_INFO
+ << "new texture, texId: " << tmpTexId
+ << "; constBits: " << constBits
+ << "; actual/full width: " << vF.width() << "/" << fullWidth
+ << "; actual/full height: " << vF.height() << "/" << fullHeight
+ << "; UV scale: U " << uScale << " V " << vScale;
#endif
GLuint physical = ~0U;
glBindTexture(GL_TEXTURE_2D, tmpTexId);
glTexDirectVIVMap_LOCAL(GL_TEXTURE_2D,
- vF.width(), vF.height(),
+ fullWidth, fullHeight,
QSGVivanteVideoNode::getVideoFormat2GLFormatMap().value(vF.pixelFormat()),
&bits, &physical);
diff --git a/src/plugins/videonode/imx6/qsgvivantevideomaterial.h b/src/plugins/videonode/imx6/qsgvivantevideomaterial.h
index faefa1c9..faf4e8d2 100644
--- a/src/plugins/videonode/imx6/qsgvivantevideomaterial.h
+++ b/src/plugins/videonode/imx6/qsgvivantevideomaterial.h
@@ -43,6 +43,8 @@
#include <private/qsgvideonode_p.h>
+class QSGVivanteVideoMaterialShader;
+
class QSGVivanteVideoMaterial : public QSGMaterial
{
public:
@@ -78,6 +80,8 @@ private:
GLuint mTexDirectTexture;
GLvoid *mTexDirectPlanes[3];
+
+ QSGVivanteVideoMaterialShader *mShader;
};
#endif // QSGVIDEOMATERIAL_VIVMAP_H
diff --git a/src/plugins/videonode/imx6/qsgvivantevideomaterialshader.cpp b/src/plugins/videonode/imx6/qsgvivantevideomaterialshader.cpp
index b51acfe6..a0a41773 100644
--- a/src/plugins/videonode/imx6/qsgvivantevideomaterialshader.cpp
+++ b/src/plugins/videonode/imx6/qsgvivantevideomaterialshader.cpp
@@ -35,6 +35,13 @@
#include "qsgvivantevideonode.h"
#include "qsgvivantevideomaterial.h"
+QSGVivanteVideoMaterialShader::QSGVivanteVideoMaterialShader() :
+ mUScale(1),
+ mVScale(1),
+ mNewUVScale(true)
+{
+}
+
void QSGVivanteVideoMaterialShader::updateState(const RenderState &state,
QSGMaterial *newMaterial,
QSGMaterial *oldMaterial)
@@ -48,6 +55,10 @@ void QSGVivanteVideoMaterialShader::updateState(const RenderState &state,
mat->setOpacity(state.opacity());
program()->setUniformValue(mIdOpacity, state.opacity());
}
+ if (mNewUVScale) {
+ program()->setUniformValue(mIdUVScale, mUScale, mVScale);
+ mNewUVScale = false;
+ }
if (state.isMatrixDirty())
program()->setUniformValue(mIdMatrix, state.combinedMatrix());
}
@@ -61,6 +72,13 @@ const char * const *QSGVivanteVideoMaterialShader::attributeNames() const {
return names;
}
+void QSGVivanteVideoMaterialShader::setUVScale(float uScale, float vScale)
+{
+ mUScale = uScale;
+ mVScale = vScale;
+ mNewUVScale = true;
+}
+
const char *QSGVivanteVideoMaterialShader::vertexShader() const {
static const char *shader =
"uniform highp mat4 qt_Matrix; \n"
@@ -78,12 +96,13 @@ const char *QSGVivanteVideoMaterialShader::fragmentShader() const {
static const char *shader =
"uniform sampler2D texture;"
"uniform lowp float opacity;"
+ "uniform highp vec2 uvScale;"
""
"varying highp vec2 qt_TexCoord;"
""
"void main()"
"{"
- " gl_FragColor = vec4(texture2D( texture, qt_TexCoord ).rgb, 1.0) * opacity;\n"
+ " gl_FragColor = vec4(texture2D( texture, qt_TexCoord * uvScale ).rgb, 1.0) * opacity;\n"
"}";
return shader;
}
@@ -93,4 +112,5 @@ void QSGVivanteVideoMaterialShader::initialize() {
mIdMatrix = program()->uniformLocation("qt_Matrix");
mIdTexture = program()->uniformLocation("texture");
mIdOpacity = program()->uniformLocation("opacity");
+ mIdUVScale = program()->uniformLocation("uvScale");
}
diff --git a/src/plugins/videonode/imx6/qsgvivantevideomaterialshader.h b/src/plugins/videonode/imx6/qsgvivantevideomaterialshader.h
index f902f763..f6e707da 100644
--- a/src/plugins/videonode/imx6/qsgvivantevideomaterialshader.h
+++ b/src/plugins/videonode/imx6/qsgvivantevideomaterialshader.h
@@ -39,9 +39,13 @@
class QSGVivanteVideoMaterialShader : public QSGMaterialShader
{
public:
+ QSGVivanteVideoMaterialShader();
+
void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial);
virtual char const *const *attributeNames() const;
+ void setUVScale(float uScale, float vScale);
+
protected:
virtual const char *vertexShader() const;
virtual const char *fragmentShader() const;
@@ -51,6 +55,11 @@ private:
int mIdMatrix;
int mIdTexture;
int mIdOpacity;
+ int mIdUVScale;
+
+ float mUScale;
+ float mVScale;
+ bool mNewUVScale;
};
#endif // QSGVIDEOMATERIALSHADER_VIVANTE_H
diff --git a/src/plugins/videonode/imx6/qsgvivantevideonode.cpp b/src/plugins/videonode/imx6/qsgvivantevideonode.cpp
index 42058f1b..229a69bc 100644
--- a/src/plugins/videonode/imx6/qsgvivantevideonode.cpp
+++ b/src/plugins/videonode/imx6/qsgvivantevideonode.cpp
@@ -78,4 +78,23 @@ const QMap<QVideoFrame::PixelFormat, GLenum>& QSGVivanteVideoNode::getVideoForma
}
+int QSGVivanteVideoNode::getBytesForPixelFormat(QVideoFrame::PixelFormat pixelformat)
+{
+ switch (pixelformat) {
+ case QVideoFrame::Format_YUV420P: return 1;
+ case QVideoFrame::Format_YV12: return 1;
+ case QVideoFrame::Format_NV12: return 1;
+ case QVideoFrame::Format_NV21: return 1;
+ case QVideoFrame::Format_UYVY: return 2;
+ case QVideoFrame::Format_YUYV: return 2;
+ case QVideoFrame::Format_RGB32: return 4;
+ case QVideoFrame::Format_ARGB32: return 4;
+ case QVideoFrame::Format_BGR32: return 4;
+ case QVideoFrame::Format_BGRA32: return 4;
+ case QVideoFrame::Format_RGB565: return 2;
+ default: return 1;
+ }
+}
+
+
diff --git a/src/plugins/videonode/imx6/qsgvivantevideonode.h b/src/plugins/videonode/imx6/qsgvivantevideonode.h
index ca088e21..c65fc11e 100644
--- a/src/plugins/videonode/imx6/qsgvivantevideonode.h
+++ b/src/plugins/videonode/imx6/qsgvivantevideonode.h
@@ -49,6 +49,7 @@ public:
void setCurrentFrame(const QVideoFrame &frame, FrameFlags flags);
static const QMap<QVideoFrame::PixelFormat, GLenum>& getVideoFormat2GLFormatMap();
+ static int getBytesForPixelFormat(QVideoFrame::PixelFormat pixelformat);
private:
QVideoSurfaceFormat mFormat;
diff --git a/src/plugins/winrt/qwinrtabstractvideorenderercontrol.cpp b/src/plugins/winrt/qwinrtabstractvideorenderercontrol.cpp
index 0f46e585..2d0b5413 100644
--- a/src/plugins/winrt/qwinrtabstractvideorenderercontrol.cpp
+++ b/src/plugins/winrt/qwinrtabstractvideorenderercontrol.cpp
@@ -5,7 +5,7 @@
**
** This file is part of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
**
** $QT_END_LICENSE$
**
diff --git a/src/plugins/winrt/qwinrtabstractvideorenderercontrol.h b/src/plugins/winrt/qwinrtabstractvideorenderercontrol.h
index 278ec179..ed8b76a6 100644
--- a/src/plugins/winrt/qwinrtabstractvideorenderercontrol.h
+++ b/src/plugins/winrt/qwinrtabstractvideorenderercontrol.h
@@ -5,7 +5,7 @@
**
** This file is part of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
**
** $QT_END_LICENSE$
**
diff --git a/src/plugins/winrt/qwinrtcameracontrol.cpp b/src/plugins/winrt/qwinrtcameracontrol.cpp
index e8f433d4..e4a57764 100644
--- a/src/plugins/winrt/qwinrtcameracontrol.cpp
+++ b/src/plugins/winrt/qwinrtcameracontrol.cpp
@@ -5,7 +5,7 @@
**
** This file is part of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
**
** $QT_END_LICENSE$
**
diff --git a/src/plugins/winrt/qwinrtcameracontrol.h b/src/plugins/winrt/qwinrtcameracontrol.h
index a90d482e..95692cbc 100644
--- a/src/plugins/winrt/qwinrtcameracontrol.h
+++ b/src/plugins/winrt/qwinrtcameracontrol.h
@@ -5,7 +5,7 @@
**
** This file is part of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
**
** $QT_END_LICENSE$
**
diff --git a/src/plugins/winrt/qwinrtcameraimagecapturecontrol.cpp b/src/plugins/winrt/qwinrtcameraimagecapturecontrol.cpp
index 1e6050a3..104484a6 100644
--- a/src/plugins/winrt/qwinrtcameraimagecapturecontrol.cpp
+++ b/src/plugins/winrt/qwinrtcameraimagecapturecontrol.cpp
@@ -5,7 +5,7 @@
**
** This file is part of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
**
** $QT_END_LICENSE$
**
diff --git a/src/plugins/winrt/qwinrtcameraimagecapturecontrol.h b/src/plugins/winrt/qwinrtcameraimagecapturecontrol.h
index 38dbbf2c..dc880255 100644
--- a/src/plugins/winrt/qwinrtcameraimagecapturecontrol.h
+++ b/src/plugins/winrt/qwinrtcameraimagecapturecontrol.h
@@ -5,7 +5,7 @@
**
** This file is part of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
**
** $QT_END_LICENSE$
**
diff --git a/src/plugins/winrt/qwinrtcamerainfocontrol.cpp b/src/plugins/winrt/qwinrtcamerainfocontrol.cpp
index 0a741eaa..69fc0a9a 100644
--- a/src/plugins/winrt/qwinrtcamerainfocontrol.cpp
+++ b/src/plugins/winrt/qwinrtcamerainfocontrol.cpp
@@ -5,7 +5,7 @@
**
** This file is part of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
**
** $QT_END_LICENSE$
**
diff --git a/src/plugins/winrt/qwinrtcamerainfocontrol.h b/src/plugins/winrt/qwinrtcamerainfocontrol.h
index 7020b12d..5bad6cb0 100644
--- a/src/plugins/winrt/qwinrtcamerainfocontrol.h
+++ b/src/plugins/winrt/qwinrtcamerainfocontrol.h
@@ -5,7 +5,7 @@
**
** This file is part of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
**
** $QT_END_LICENSE$
**
diff --git a/src/plugins/winrt/qwinrtcameraservice.cpp b/src/plugins/winrt/qwinrtcameraservice.cpp
index 275fbccf..09b56575 100644
--- a/src/plugins/winrt/qwinrtcameraservice.cpp
+++ b/src/plugins/winrt/qwinrtcameraservice.cpp
@@ -5,7 +5,7 @@
**
** This file is part of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
**
** $QT_END_LICENSE$
**
diff --git a/src/plugins/winrt/qwinrtcameraservice.h b/src/plugins/winrt/qwinrtcameraservice.h
index 9565de62..eb3b0d01 100644
--- a/src/plugins/winrt/qwinrtcameraservice.h
+++ b/src/plugins/winrt/qwinrtcameraservice.h
@@ -5,7 +5,7 @@
**
** This file is part of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
**
** $QT_END_LICENSE$
**
diff --git a/src/plugins/winrt/qwinrtcameravideorenderercontrol.cpp b/src/plugins/winrt/qwinrtcameravideorenderercontrol.cpp
index bcae8a20..3b8a38bb 100644
--- a/src/plugins/winrt/qwinrtcameravideorenderercontrol.cpp
+++ b/src/plugins/winrt/qwinrtcameravideorenderercontrol.cpp
@@ -5,7 +5,7 @@
**
** This file is part of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
**
** $QT_END_LICENSE$
**
diff --git a/src/plugins/winrt/qwinrtcameravideorenderercontrol.h b/src/plugins/winrt/qwinrtcameravideorenderercontrol.h
index 55ea1266..68e9bd9f 100644
--- a/src/plugins/winrt/qwinrtcameravideorenderercontrol.h
+++ b/src/plugins/winrt/qwinrtcameravideorenderercontrol.h
@@ -5,7 +5,7 @@
**
** This file is part of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
**
** $QT_END_LICENSE$
**
diff --git a/src/plugins/winrt/qwinrtmediaplayercontrol.cpp b/src/plugins/winrt/qwinrtmediaplayercontrol.cpp
index 333a6d1e..0402553d 100644
--- a/src/plugins/winrt/qwinrtmediaplayercontrol.cpp
+++ b/src/plugins/winrt/qwinrtmediaplayercontrol.cpp
@@ -5,7 +5,7 @@
**
** This file is part of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
**
** $QT_END_LICENSE$
**
diff --git a/src/plugins/winrt/qwinrtmediaplayercontrol.h b/src/plugins/winrt/qwinrtmediaplayercontrol.h
index f2899531..34abcc12 100644
--- a/src/plugins/winrt/qwinrtmediaplayercontrol.h
+++ b/src/plugins/winrt/qwinrtmediaplayercontrol.h
@@ -5,7 +5,7 @@
**
** This file is part of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
**
** $QT_END_LICENSE$
**
diff --git a/src/plugins/winrt/qwinrtmediaplayerservice.cpp b/src/plugins/winrt/qwinrtmediaplayerservice.cpp
index c8c34d83..a6b3d1f3 100644
--- a/src/plugins/winrt/qwinrtmediaplayerservice.cpp
+++ b/src/plugins/winrt/qwinrtmediaplayerservice.cpp
@@ -5,7 +5,7 @@
**
** This file is part of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
**
** $QT_END_LICENSE$
**
diff --git a/src/plugins/winrt/qwinrtmediaplayerservice.h b/src/plugins/winrt/qwinrtmediaplayerservice.h
index 039ca309..7a2771fd 100644
--- a/src/plugins/winrt/qwinrtmediaplayerservice.h
+++ b/src/plugins/winrt/qwinrtmediaplayerservice.h
@@ -5,7 +5,7 @@
**
** This file is part of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
**
** $QT_END_LICENSE$
**
diff --git a/src/plugins/winrt/qwinrtplayerrenderercontrol.cpp b/src/plugins/winrt/qwinrtplayerrenderercontrol.cpp
index cf815fcd..5a8f4b87 100644
--- a/src/plugins/winrt/qwinrtplayerrenderercontrol.cpp
+++ b/src/plugins/winrt/qwinrtplayerrenderercontrol.cpp
@@ -5,7 +5,7 @@
**
** This file is part of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
**
** $QT_END_LICENSE$
**
diff --git a/src/plugins/winrt/qwinrtplayerrenderercontrol.h b/src/plugins/winrt/qwinrtplayerrenderercontrol.h
index 85fc00c5..c6d410b1 100644
--- a/src/plugins/winrt/qwinrtplayerrenderercontrol.h
+++ b/src/plugins/winrt/qwinrtplayerrenderercontrol.h
@@ -5,7 +5,7 @@
**
** This file is part of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
**
** $QT_END_LICENSE$
**
diff --git a/src/plugins/winrt/qwinrtserviceplugin.cpp b/src/plugins/winrt/qwinrtserviceplugin.cpp
index c0e51907..fc0103d1 100644
--- a/src/plugins/winrt/qwinrtserviceplugin.cpp
+++ b/src/plugins/winrt/qwinrtserviceplugin.cpp
@@ -5,7 +5,7 @@
**
** This file is part of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
**
** $QT_END_LICENSE$
**
diff --git a/src/plugins/winrt/qwinrtserviceplugin.h b/src/plugins/winrt/qwinrtserviceplugin.h
index 004ad89c..5f5cf559 100644
--- a/src/plugins/winrt/qwinrtserviceplugin.h
+++ b/src/plugins/winrt/qwinrtserviceplugin.h
@@ -5,7 +5,7 @@
**
** This file is part of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
**
** $QT_END_LICENSE$
**
diff --git a/src/plugins/winrt/qwinrtvideodeviceselectorcontrol.cpp b/src/plugins/winrt/qwinrtvideodeviceselectorcontrol.cpp
index 0352aaab..582a9fc6 100644
--- a/src/plugins/winrt/qwinrtvideodeviceselectorcontrol.cpp
+++ b/src/plugins/winrt/qwinrtvideodeviceselectorcontrol.cpp
@@ -5,7 +5,7 @@
**
** This file is part of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
**
** $QT_END_LICENSE$
**
diff --git a/src/plugins/winrt/qwinrtvideodeviceselectorcontrol.h b/src/plugins/winrt/qwinrtvideodeviceselectorcontrol.h
index df655f44..3b3e7c74 100644
--- a/src/plugins/winrt/qwinrtvideodeviceselectorcontrol.h
+++ b/src/plugins/winrt/qwinrtvideodeviceselectorcontrol.h
@@ -5,7 +5,7 @@
**
** This file is part of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
@@ -16,16 +16,19 @@
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
**
** $QT_END_LICENSE$
**
diff --git a/src/plugins/wmf/decoder/mfaudiodecodercontrol.cpp b/src/plugins/wmf/decoder/mfaudiodecodercontrol.cpp
index e3d1ebde..55fae714 100644
--- a/src/plugins/wmf/decoder/mfaudiodecodercontrol.cpp
+++ b/src/plugins/wmf/decoder/mfaudiodecodercontrol.cpp
@@ -389,7 +389,8 @@ void MFAudioDecoderControl::handleSampleAdded()
s->Release();
}
}
- m_cachedAudioBuffer = QAudioBuffer(abuf, m_audioFormat, qint64(sampleStartTime / 10000));
+ // WMF uses 100-nanosecond units, QAudioDecoder uses milliseconds, QAudioBuffer uses microseconds...
+ m_cachedAudioBuffer = QAudioBuffer(abuf, m_audioFormat, qint64(sampleStartTime / 10));
m_bufferReady = true;
emit positionChanged(m_position);
emit bufferAvailableChanged(m_bufferReady);
diff --git a/src/qtmultimediaquicktools/qdeclarativevideooutput.cpp b/src/qtmultimediaquicktools/qdeclarativevideooutput.cpp
index c638b306..7a9dfdaa 100644
--- a/src/qtmultimediaquicktools/qdeclarativevideooutput.cpp
+++ b/src/qtmultimediaquicktools/qdeclarativevideooutput.cpp
@@ -41,6 +41,10 @@
#include <private/qmediapluginloader_p.h>
#include <QtCore/qloggingcategory.h>
+static void initResource() {
+ Q_INIT_RESOURCE(qtmultimediaquicktools);
+}
+
QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(qLcVideo, "qt.multimedia.video")
@@ -130,6 +134,7 @@ QDeclarativeVideoOutput::QDeclarativeVideoOutput(QQuickItem *parent) :
m_autoOrientation(false),
m_screenOrientationHandler(0)
{
+ initResource();
setFlag(ItemHasContents, true);
}
diff --git a/src/qtmultimediaquicktools/qsgvideonode_yuv.cpp b/src/qtmultimediaquicktools/qsgvideonode_yuv.cpp
index 9da1023b..c920ba3b 100644
--- a/src/qtmultimediaquicktools/qsgvideonode_yuv.cpp
+++ b/src/qtmultimediaquicktools/qsgvideonode_yuv.cpp
@@ -318,7 +318,8 @@ void QSGVideoMaterial_YUV::bind()
m_frame = QVideoFrame();
} else {
- for (int i = 0; i < m_planeCount; ++i) {
+ // Go backwards to finish with GL_TEXTURE0
+ for (int i = m_planeCount - 1; i >= 0; --i) {
functions->glActiveTexture(GL_TEXTURE0 + i);
functions->glBindTexture(GL_TEXTURE_2D, m_textureIds[i]);
}
diff --git a/tests/auto/unit/qaudiobuffer/qaudiobuffer.pro b/tests/auto/unit/qaudiobuffer/qaudiobuffer.pro
index 0694bf82..cd3b42f5 100644
--- a/tests/auto/unit/qaudiobuffer/qaudiobuffer.pro
+++ b/tests/auto/unit/qaudiobuffer/qaudiobuffer.pro
@@ -8,7 +8,7 @@ QT += multimedia testlib
QT -= gui
TARGET = tst_qaudiobuffer
-CONFIG += console
+CONFIG += testcase
CONFIG -= app_bundle
TEMPLATE = app