summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dist/changes-5.13.268
-rw-r--r--src/gsttools/qgstreamerplayercontrol.cpp8
-rw-r--r--src/gsttools/qgstreamerplayersession.cpp3
-rw-r--r--src/multimedia/playback/qmediaplaylist.cpp48
-rw-r--r--src/multimedia/qmediaserviceprovider.cpp11
-rw-r--r--src/plugins/alsa/qalsaaudiooutput.cpp34
-rw-r--r--src/plugins/android/src/common/qandroidmultimediautils.cpp12
-rw-r--r--src/plugins/android/src/common/qandroidmultimediautils.h3
-rw-r--r--src/plugins/android/src/common/qandroidvideooutput.cpp33
-rw-r--r--src/plugins/android/src/common/qandroidvideooutput.h5
-rw-r--r--src/plugins/android/src/mediacapture/qandroidcamerasession.cpp13
-rw-r--r--src/plugins/android/src/mediacapture/qandroidcamerasession.h2
-rw-r--r--src/plugins/android/src/mediacapture/qandroidcapturesession.cpp6
-rw-r--r--src/plugins/android/src/wrappers/jni/androidcamera.cpp15
-rw-r--r--src/plugins/android/src/wrappers/jni/androidmediarecorder.cpp5
-rw-r--r--src/plugins/android/src/wrappers/jni/androidmediarecorder.h1
-rw-r--r--src/plugins/avfoundation/camera/avfmediaassetwriter.h9
-rw-r--r--src/plugins/avfoundation/camera/avfmediaassetwriter.mm41
-rw-r--r--src/plugins/avfoundation/camera/avfmediarecordercontrol_ios.mm2
-rw-r--r--src/plugins/opensles/qopenslesaudioinput.cpp2
-rw-r--r--src/plugins/opensles/qopenslesaudioinput.h1
-rw-r--r--src/plugins/opensles/qopenslesengine.cpp3
-rw-r--r--src/qtmultimediaquicktools/qdeclarativevideooutput.cpp7
-rw-r--r--src/qtmultimediaquicktools/qtmultimediaquicktools.pro23
-rw-r--r--src/src.pro2
25 files changed, 249 insertions, 108 deletions
diff --git a/dist/changes-5.13.2 b/dist/changes-5.13.2
new file mode 100644
index 000000000..62dffcb02
--- /dev/null
+++ b/dist/changes-5.13.2
@@ -0,0 +1,68 @@
+Qt 5.13.2 is a bug-fix release. It maintains both forward and backward
+source compatibility with Qt 5.13.0 through 5.13.1.
+In Qt 5.13.0, binary compatibility was broken due to the usage of the enum
+QVideoFrame::PixelFormat, the break has been reverted,
+thus introducing a binary compatibility break with earlier Qt 5.13.0 and 5.13.1.
+
+For more details, refer to the online documentation included in this
+distribution. The documentation is also available online:
+
+https://doc.qt.io/qt-5/index.html
+
+The Qt version 5.13 series is binary compatible with the 5.12.x series.
+Applications compiled for 5.12 will continue to run with 5.13.
+
+Some of the changes listed in this file include issue tracking numbers
+corresponding to tasks in the Qt Bug Tracker:
+
+https://bugreports.qt.io/
+
+Each of these identifiers can be entered in the bug tracker to obtain more
+information about a particular change.
+
+****************************************************************************
+* Qt 5.13.2 Changes *
+****************************************************************************
+
+ - In Qt 5.13.0 binary compatibility was broken
+ for usage of the enum QVideoFrame::PixelFormat by introducing
+ QVideoFrame::Format_ABGR32.
+ To minimize the impact of this, the break has been reverted,
+ thus introducing a binary compatibility break with earlier Qt 5.13.x
+ versions, but restoring compatibility with all earlier versions of Qt 5.
+ - Fixed crash when VideoOutput.sourceRect is requested but playback is stopped.
+ - [QTBUG-51588] Fixed leaking of QVideoFilterRunnable when window is closed.
+ - [QTBUG-45064] Introduced QGraphicsVideoItem::type().
+ - Fixed camera.viewfinder to respect camera's media status
+ if the viewfinder is requested after the camera is loaded.
+
+****************************************************************************
+* Platform Specific Changes *
+****************************************************************************
+
+ - GStreamer:
+ * CameraBin plugin now fetches supported viewfinder settings at status
+ higher or equal to LoadedStatus if it has not been fetched.
+ * Fixed duplicated entries in supported Camera's resolution/framerate if the
+ underlying element uses caps' features.
+ * Introduced audio/x-raw codec in QAudioRecorder.
+ * [QTBUG-65399] Fixed media player to show pre-rolled frame on new media
+ (means to seek to the beginning) only when pause() is called.
+ * [QTBUG-76135] Show image processing warnings only when the camera is loaded.
+ * [QTBUG-78079] Fixed media player to recreate playbin features after custom pipeline.
+ * [QTBUG-73084] Fixed mapping of VPU texture using real physical address of data
+ which prevents leaks in the kernel for iMX boards.
+
+ - AVFoundation:
+ * [QTBUG-77270] Fixed black frames being shown if current OpenGL context has been changed.
+ * [QTBUG-49806] Fixed media player to send StalledMedia status when no enough data to play
+ and resume playback afterwards.
+
+ - DirectShow:
+ * [QTBUG-77829] Fixed crash when there is no surface on flush().
+ * [QTBUG-77849] Introduced startTime and endTime to QVideoFrame.
+ * [QTBUG-77163] Introduced support to use QMediaPlayer in secondary thread.
+ * [QTBUG-46368] Implemented QMediaVideoProbeControl->flush().
+ * [QTBUG-46368] Fixed media player to send media status before errors.
+ * [QTBUG-68778] Fixed media player to postpone seeking if the playback is stopped.
+ * Fixed crash when qrc media resource is set twice to media player.
diff --git a/src/gsttools/qgstreamerplayercontrol.cpp b/src/gsttools/qgstreamerplayercontrol.cpp
index bd4c90ac5..165978288 100644
--- a/src/gsttools/qgstreamerplayercontrol.cpp
+++ b/src/gsttools/qgstreamerplayercontrol.cpp
@@ -450,6 +450,10 @@ void QGstreamerPlayerControl::updateSessionState(QMediaPlayer::State state)
void QGstreamerPlayerControl::updateMediaStatus()
{
+ //EndOfMedia status should be kept, until reset by pause, play or setMedia
+ if (m_mediaStatus == QMediaPlayer::EndOfMedia)
+ return;
+
pushState();
QMediaPlayer::MediaStatus oldStatus = m_mediaStatus;
@@ -477,10 +481,6 @@ void QGstreamerPlayerControl::updateMediaStatus()
if (m_currentState == QMediaPlayer::PlayingState && !m_resources->isGranted())
m_mediaStatus = QMediaPlayer::StalledMedia;
- //EndOfMedia status should be kept, until reset by pause, play or setMedia
- if (oldStatus == QMediaPlayer::EndOfMedia)
- m_mediaStatus = QMediaPlayer::EndOfMedia;
-
popAndNotifyState();
}
diff --git a/src/gsttools/qgstreamerplayersession.cpp b/src/gsttools/qgstreamerplayersession.cpp
index b9e1c084f..ed3f16c5f 100644
--- a/src/gsttools/qgstreamerplayersession.cpp
+++ b/src/gsttools/qgstreamerplayersession.cpp
@@ -265,8 +265,11 @@ void QGstreamerPlayerSession::resetElements()
resetGstObject(m_nullVideoSink);
resetGstObject(m_videoOutputBin);
+ m_audioSink = nullptr;
m_volumeElement = nullptr;
m_videoIdentity = nullptr;
+ m_pendingVideoSink = nullptr;
+ m_videoSink = nullptr;
}
GstElement *QGstreamerPlayerSession::playbin() const
diff --git a/src/multimedia/playback/qmediaplaylist.cpp b/src/multimedia/playback/qmediaplaylist.cpp
index 7c21a599b..9539a1809 100644
--- a/src/multimedia/playback/qmediaplaylist.cpp
+++ b/src/multimedia/playback/qmediaplaylist.cpp
@@ -184,20 +184,20 @@ bool QMediaPlaylist::setMediaObject(QMediaObject *mediaObject)
disconnect(playlist, SIGNAL(loadFailed(QMediaPlaylist::Error,QString)),
this, SLOT(_q_loadFailed(QMediaPlaylist::Error,QString)));
- disconnect(playlist, SIGNAL(mediaChanged(int,int)), this, SIGNAL(mediaChanged(int,int)));
- disconnect(playlist, SIGNAL(mediaAboutToBeInserted(int,int)), this, SIGNAL(mediaAboutToBeInserted(int,int)));
- disconnect(playlist, SIGNAL(mediaInserted(int,int)), this, SIGNAL(mediaInserted(int,int)));
- disconnect(playlist, SIGNAL(mediaAboutToBeRemoved(int,int)), this, SIGNAL(mediaAboutToBeRemoved(int,int)));
- disconnect(playlist, SIGNAL(mediaRemoved(int,int)), this, SIGNAL(mediaRemoved(int,int)));
+ disconnect(playlist, &QMediaPlaylistProvider::mediaChanged, this, &QMediaPlaylist::mediaChanged);
+ disconnect(playlist, &QMediaPlaylistProvider::mediaAboutToBeInserted, this, &QMediaPlaylist::mediaAboutToBeInserted);
+ disconnect(playlist, &QMediaPlaylistProvider::mediaInserted, this, &QMediaPlaylist::mediaInserted);
+ disconnect(playlist, &QMediaPlaylistProvider::mediaAboutToBeRemoved, this, &QMediaPlaylist::mediaAboutToBeRemoved);
+ disconnect(playlist, &QMediaPlaylistProvider::mediaRemoved, this, &QMediaPlaylist::mediaRemoved);
- disconnect(playlist, SIGNAL(loaded()), this, SIGNAL(loaded()));
+ disconnect(playlist, &QMediaPlaylistProvider::loaded, this, &QMediaPlaylist::loaded);
- disconnect(d->control, SIGNAL(playbackModeChanged(QMediaPlaylist::PlaybackMode)),
- this, SIGNAL(playbackModeChanged(QMediaPlaylist::PlaybackMode)));
- disconnect(d->control, SIGNAL(currentIndexChanged(int)),
- this, SIGNAL(currentIndexChanged(int)));
- disconnect(d->control, SIGNAL(currentMediaChanged(QMediaContent)),
- this, SIGNAL(currentMediaChanged(QMediaContent)));
+ disconnect(d->control, &QMediaPlaylistControl::playbackModeChanged,
+ this, &QMediaPlaylist::playbackModeChanged);
+ disconnect(d->control, &QMediaPlaylistControl::currentIndexChanged,
+ this, &QMediaPlaylist::currentIndexChanged);
+ disconnect(d->control, &QMediaPlaylistControl::currentMediaChanged,
+ this, &QMediaPlaylist::currentMediaChanged);
// Copy playlist items, sync playback mode and sync current index between
// old control and new control
@@ -214,20 +214,20 @@ bool QMediaPlaylist::setMediaObject(QMediaObject *mediaObject)
connect(playlist, SIGNAL(loadFailed(QMediaPlaylist::Error,QString)),
this, SLOT(_q_loadFailed(QMediaPlaylist::Error,QString)));
- connect(playlist, SIGNAL(mediaChanged(int,int)), this, SIGNAL(mediaChanged(int,int)));
- connect(playlist, SIGNAL(mediaAboutToBeInserted(int,int)), this, SIGNAL(mediaAboutToBeInserted(int,int)));
- connect(playlist, SIGNAL(mediaInserted(int,int)), this, SIGNAL(mediaInserted(int,int)));
- connect(playlist, SIGNAL(mediaAboutToBeRemoved(int,int)), this, SIGNAL(mediaAboutToBeRemoved(int,int)));
- connect(playlist, SIGNAL(mediaRemoved(int,int)), this, SIGNAL(mediaRemoved(int,int)));
+ connect(playlist, &QMediaPlaylistProvider::mediaChanged, this, &QMediaPlaylist::mediaChanged);
+ connect(playlist, &QMediaPlaylistProvider::mediaAboutToBeInserted, this, &QMediaPlaylist::mediaAboutToBeInserted);
+ connect(playlist, &QMediaPlaylistProvider::mediaInserted, this, &QMediaPlaylist::mediaInserted);
+ connect(playlist, &QMediaPlaylistProvider::mediaAboutToBeRemoved, this, &QMediaPlaylist::mediaAboutToBeRemoved);
+ connect(playlist, &QMediaPlaylistProvider::mediaRemoved, this, &QMediaPlaylist::mediaRemoved);
- connect(playlist, SIGNAL(loaded()), this, SIGNAL(loaded()));
+ connect(playlist, &QMediaPlaylistProvider::loaded, this, &QMediaPlaylist::loaded);
- connect(d->control, SIGNAL(playbackModeChanged(QMediaPlaylist::PlaybackMode)),
- this, SIGNAL(playbackModeChanged(QMediaPlaylist::PlaybackMode)));
- connect(d->control, SIGNAL(currentIndexChanged(int)),
- this, SIGNAL(currentIndexChanged(int)));
- connect(d->control, SIGNAL(currentMediaChanged(QMediaContent)),
- this, SIGNAL(currentMediaChanged(QMediaContent)));
+ connect(d->control, &QMediaPlaylistControl::playbackModeChanged,
+ this, &QMediaPlaylist::playbackModeChanged);
+ connect(d->control, &QMediaPlaylistControl::currentIndexChanged,
+ this, &QMediaPlaylist::currentIndexChanged);
+ connect(d->control, &QMediaPlaylistControl::currentMediaChanged,
+ this, &QMediaPlaylist::currentMediaChanged);
if (removedStart != -1 && removedEnd != -1) {
emit mediaAboutToBeRemoved(removedStart, removedEnd);
diff --git a/src/multimedia/qmediaserviceprovider.cpp b/src/multimedia/qmediaserviceprovider.cpp
index 5731cf5be..d8ffe42ae 100644
--- a/src/multimedia/qmediaserviceprovider.cpp
+++ b/src/multimedia/qmediaserviceprovider.cpp
@@ -682,6 +682,7 @@ Q_GLOBAL_STATIC(QPluginServiceProvider, pluginProvider);
*/
/*!
+ \internal
\fn QMediaServiceProvider::requestService(const QByteArray &type, const QMediaServiceProviderHint &hint)
Requests an instance of a \a type service which best matches the given \a
@@ -695,12 +696,14 @@ Q_GLOBAL_STATIC(QPluginServiceProvider, pluginProvider);
*/
/*!
+ \internal
\fn QMediaServiceProvider::releaseService(QMediaService *service)
Releases a media \a service requested with requestService().
*/
/*!
+ \internal
\fn QMediaServiceProvider::supportedFeatures(const QMediaService *service) const
Returns the features supported by a given \a service.
@@ -713,6 +716,7 @@ QMediaServiceProviderHint::Features QMediaServiceProvider::supportedFeatures(con
}
/*!
+ \internal
Returns how confident a media service provider is that is can provide a \a
serviceType service that is able to play media of a specific \a mimeType
that is encoded using the listed \a codecs while adhering to constraints
@@ -732,6 +736,7 @@ QMultimedia::SupportEstimate QMediaServiceProvider::hasSupport(const QByteArray
}
/*!
+ \internal
\fn QStringList QMediaServiceProvider::supportedMimeTypes(const QByteArray &serviceType, int flags) const
Returns a list of MIME types supported by the service provider for the
@@ -749,6 +754,7 @@ QStringList QMediaServiceProvider::supportedMimeTypes(const QByteArray &serviceT
}
/*!
+ \internal
\since 5.3
Returns the default device for a \a service type.
@@ -760,6 +766,7 @@ QByteArray QMediaServiceProvider::defaultDevice(const QByteArray &serviceType) c
}
/*!
+ \internal
Returns the list of devices related to \a service type.
*/
QList<QByteArray> QMediaServiceProvider::devices(const QByteArray &service) const
@@ -769,6 +776,7 @@ QList<QByteArray> QMediaServiceProvider::devices(const QByteArray &service) cons
}
/*!
+ \internal
Returns the description of \a device related to \a serviceType, suitable for use by
an application for display.
*/
@@ -780,6 +788,7 @@ QString QMediaServiceProvider::deviceDescription(const QByteArray &serviceType,
}
/*!
+ \internal
\since 5.3
Returns the physical position of a camera \a device on the system hardware.
@@ -791,6 +800,7 @@ QCamera::Position QMediaServiceProvider::cameraPosition(const QByteArray &device
}
/*!
+ \internal
\since 5.3
Returns the physical orientation of the camera \a device. The value is the angle by which the
@@ -818,6 +828,7 @@ void QMediaServiceProvider::setDefaultServiceProvider(QMediaServiceProvider *pro
/*!
+ \internal
Returns a default provider of media services.
*/
QMediaServiceProvider *QMediaServiceProvider::defaultServiceProvider()
diff --git a/src/plugins/alsa/qalsaaudiooutput.cpp b/src/plugins/alsa/qalsaaudiooutput.cpp
index ddbe04de9..5c8ae171c 100644
--- a/src/plugins/alsa/qalsaaudiooutput.cpp
+++ b/src/plugins/alsa/qalsaaudiooutput.cpp
@@ -53,9 +53,11 @@
#include <QtMultimedia/private/qaudiohelpers_p.h>
#include "qalsaaudiooutput.h"
#include "qalsaaudiodeviceinfo.h"
+#include <QLoggingCategory>
QT_BEGIN_NAMESPACE
+Q_LOGGING_CATEGORY(lcAlsaOutput, "qt.multimedia.alsa.output")
//#define DEBUG_AUDIO 1
QAlsaAudioOutput::QAlsaAudioOutput(const QByteArray &device)
@@ -403,28 +405,22 @@ bool QAlsaAudioOutput::open()
fatal = true;
errMessage = QString::fromLatin1("QAudioOutput: buffer/period min and max: err = %1").arg(err);
} else {
- if (maxBufferTime < buffer_time || buffer_time < minBufferTime || maxPeriodTime < period_time || minPeriodTime > period_time) {
-#ifdef DEBUG_AUDIO
- qDebug()<<"defaults out of range";
- qDebug()<<"pmin="<<minPeriodTime<<", pmax="<<maxPeriodTime<<", bmin="<<minBufferTime<<", bmax="<<maxBufferTime;
-#endif
- period_time = minPeriodTime;
- if (period_time*4 <= maxBufferTime) {
- // Use 4 periods if possible
- buffer_time = period_time*4;
- chunks = 4;
- } else if (period_time*2 <= maxBufferTime) {
- // Use 2 periods if possible
- buffer_time = period_time*2;
- chunks = 2;
+ static unsigned user_buffer_time = qEnvironmentVariableIntValue("QT_ALSA_OUTPUT_BUFFER_TIME");
+ static unsigned user_period_time = qEnvironmentVariableIntValue("QT_ALSA_OUTPUT_PERIOD_TIME");
+ const bool outOfRange = maxBufferTime < buffer_time || buffer_time < minBufferTime || maxPeriodTime < period_time || minPeriodTime > period_time;
+ if (outOfRange || user_period_time || user_buffer_time) {
+ period_time = user_period_time ? user_period_time : minPeriodTime;
+ if (!user_buffer_time) {
+ chunks = maxBufferTime / period_time;
+ buffer_time = period_time * chunks;
} else {
- qWarning()<<"QAudioOutput: alsa only supports single period!";
- fatal = true;
+ buffer_time = user_buffer_time;
+ chunks = buffer_time / period_time;
}
-#ifdef DEBUG_AUDIO
- qDebug()<<"used: buffer_time="<<buffer_time<<", period_time="<<period_time;
-#endif
}
+ qCDebug(lcAlsaOutput) << "buffer time: [" << minBufferTime << "-" << maxBufferTime << "] =" << buffer_time;
+ qCDebug(lcAlsaOutput) << "period time: [" << minPeriodTime << "-" << maxPeriodTime << "] =" << period_time;
+ qCDebug(lcAlsaOutput) << "chunks =" << chunks;
}
}
if ( !fatal ) {
diff --git a/src/plugins/android/src/common/qandroidmultimediautils.cpp b/src/plugins/android/src/common/qandroidmultimediautils.cpp
index a4a7f773d..1f03d5d29 100644
--- a/src/plugins/android/src/common/qandroidmultimediautils.cpp
+++ b/src/plugins/android/src/common/qandroidmultimediautils.cpp
@@ -113,7 +113,7 @@ AndroidCamera::ImageFormat qt_androidImageFormatFromPixelFormat(QVideoFrame::Pix
}
}
-bool qt_androidRequestPermission(const QString &key)
+static bool androidRequestPermission(const QString &key)
{
using namespace QtAndroidPrivate;
@@ -139,4 +139,14 @@ bool qt_androidRequestPermission(const QString &key)
return true;
}
+bool qt_androidRequestCameraPermission()
+{
+ return androidRequestPermission(QLatin1String("android.permission.CAMERA"));
+}
+
+bool qt_androidRequestRecordingPermission()
+{
+ return androidRequestPermission(QLatin1String("android.permission.RECORD_AUDIO"));
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/android/src/common/qandroidmultimediautils.h b/src/plugins/android/src/common/qandroidmultimediautils.h
index 0a837ae3c..381671cb8 100644
--- a/src/plugins/android/src/common/qandroidmultimediautils.h
+++ b/src/plugins/android/src/common/qandroidmultimediautils.h
@@ -55,7 +55,8 @@ bool qt_sizeLessThan(const QSize &s1, const QSize &s2);
QVideoFrame::PixelFormat qt_pixelFormatFromAndroidImageFormat(AndroidCamera::ImageFormat f);
AndroidCamera::ImageFormat qt_androidImageFormatFromPixelFormat(QVideoFrame::PixelFormat f);
-bool qt_androidRequestPermission(const QString &key);
+bool qt_androidRequestCameraPermission();
+bool qt_androidRequestRecordingPermission();
QT_END_NAMESPACE
diff --git a/src/plugins/android/src/common/qandroidvideooutput.cpp b/src/plugins/android/src/common/qandroidvideooutput.cpp
index 25e67e865..fd6eb0e8b 100644
--- a/src/plugins/android/src/common/qandroidvideooutput.cpp
+++ b/src/plugins/android/src/common/qandroidvideooutput.cpp
@@ -49,6 +49,8 @@
#include <qopenglshaderprogram.h>
#include <qopenglframebufferobject.h>
#include <QtCore/private/qjnihelpers_p.h>
+#include <QtGui/QWindow>
+#include <QtGui/QOffscreenSurface>
QT_BEGIN_NAMESPACE
@@ -182,6 +184,8 @@ QAndroidTextureVideoOutput::QAndroidTextureVideoOutput(QObject *parent)
QAndroidTextureVideoOutput::~QAndroidTextureVideoOutput()
{
+ delete m_offscreenSurface;
+ delete m_glContext;
clearSurfaceTexture();
if (m_glDeleter) { // Make sure all of these are deleted on the render thread.
@@ -345,6 +349,35 @@ bool QAndroidTextureVideoOutput::renderFrameToFbo()
if (!m_nativeSize.isValid() || !m_surfaceTexture)
return false;
+ // Make sure we have an OpenGL context to make current.
+ if (!QOpenGLContext::currentContext() && !m_glContext) {
+ // Create Hidden QWindow surface to create context in this thread.
+ m_offscreenSurface = new QWindow();
+ m_offscreenSurface->setSurfaceType(QWindow::OpenGLSurface);
+ // Needs geometry to be a valid surface, but size is not important.
+ m_offscreenSurface->setGeometry(0, 0, 1, 1);
+ m_offscreenSurface->create();
+
+ // Create OpenGL context and set share context from surface.
+ m_glContext = new QOpenGLContext();
+ m_glContext->setFormat(m_offscreenSurface->requestedFormat());
+
+ auto surface = qobject_cast<QAbstractVideoSurface *>(m_surface->property("videoSurface").value<QObject *>());
+ if (!surface)
+ surface = m_surface;
+ auto shareContext = qobject_cast<QOpenGLContext *>(surface->property("GLContext").value<QObject *>());
+ if (shareContext)
+ m_glContext->setShareContext(shareContext);
+
+ if (!m_glContext->create()) {
+ qWarning("Failed to create QOpenGLContext");
+ return false;
+ }
+ }
+
+ if (m_glContext)
+ m_glContext->makeCurrent(m_offscreenSurface);
+
createGLResources();
m_surfaceTexture->updateTexImage();
diff --git a/src/plugins/android/src/common/qandroidvideooutput.h b/src/plugins/android/src/common/qandroidvideooutput.h
index 2a35247e9..456fe8e22 100644
--- a/src/plugins/android/src/common/qandroidvideooutput.h
+++ b/src/plugins/android/src/common/qandroidvideooutput.h
@@ -51,6 +51,8 @@ class AndroidSurfaceHolder;
class QOpenGLFramebufferObject;
class QOpenGLShaderProgram;
class QAbstractVideoSurface;
+class QWindow;
+class QOpenGLContext;
class QAndroidVideoOutput : public QObject
{
@@ -132,6 +134,9 @@ private:
bool m_surfaceTextureCanAttachToContext;
+ QWindow *m_offscreenSurface = nullptr;
+ QOpenGLContext *m_glContext = nullptr;
+
friend class AndroidTextureVideoBuffer;
};
diff --git a/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp b/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp
index 5df8241e0..a0f809376 100644
--- a/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp
+++ b/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp
@@ -77,6 +77,7 @@ QAndroidCameraSession::QAndroidCameraSession(QObject *parent)
, m_captureCanceled(false)
, m_currentImageCaptureId(-1)
, m_previewCallback(0)
+ , m_keepActive(false)
{
m_mediaStorageLocation.addStorageLocation(
QMediaStorageLocation::Pictures,
@@ -182,7 +183,7 @@ bool QAndroidCameraSession::open()
m_status = QCamera::LoadingStatus;
emit statusChanged(m_status);
- m_camera = AndroidCamera::requestCameraPermission() ? AndroidCamera::open(m_selectedCamera) : nullptr;
+ m_camera = AndroidCamera::open(m_selectedCamera);
if (m_camera) {
connect(m_camera, SIGNAL(pictureExposed()), this, SLOT(onCameraPictureExposed()));
@@ -912,7 +913,7 @@ void QAndroidCameraSession::onApplicationStateChanged(Qt::ApplicationState state
{
switch (state) {
case Qt::ApplicationInactive:
- if (m_state != QCamera::UnloadedState) {
+ if (!m_keepActive && m_state != QCamera::UnloadedState) {
m_savedState = m_state;
close();
m_state = QCamera::UnloadedState;
@@ -930,4 +931,12 @@ void QAndroidCameraSession::onApplicationStateChanged(Qt::ApplicationState state
}
}
+bool QAndroidCameraSession::requestRecordingPermission()
+{
+ m_keepActive = true;
+ const bool result = qt_androidRequestRecordingPermission();
+ m_keepActive = false;
+ return result;
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/android/src/mediacapture/qandroidcamerasession.h b/src/plugins/android/src/mediacapture/qandroidcamerasession.h
index b51dcc628..728dc484e 100644
--- a/src/plugins/android/src/mediacapture/qandroidcamerasession.h
+++ b/src/plugins/android/src/mediacapture/qandroidcamerasession.h
@@ -112,6 +112,7 @@ public:
virtual void onFrameAvailable(const QVideoFrame &frame) = 0;
};
void setPreviewCallback(PreviewCallback *callback);
+ bool requestRecordingPermission();
Q_SIGNALS:
void statusChanged(QCamera::Status status);
@@ -196,6 +197,7 @@ private:
QSet<QAndroidMediaVideoProbeControl *> m_videoProbes;
QMutex m_videoProbesMutex;
PreviewCallback *m_previewCallback;
+ bool m_keepActive;
};
QT_END_NAMESPACE
diff --git a/src/plugins/android/src/mediacapture/qandroidcapturesession.cpp b/src/plugins/android/src/mediacapture/qandroidcapturesession.cpp
index bc9bc983e..7cc3ad619 100644
--- a/src/plugins/android/src/mediacapture/qandroidcapturesession.cpp
+++ b/src/plugins/android/src/mediacapture/qandroidcapturesession.cpp
@@ -206,8 +206,10 @@ void QAndroidCaptureSession::start()
delete m_mediaRecorder;
}
-
- if (!AndroidMediaRecorder::requestRecordingPermission()) {
+ const bool granted = m_cameraSession
+ ? m_cameraSession->requestRecordingPermission()
+ : qt_androidRequestRecordingPermission();
+ if (!granted) {
setStatus(QMediaRecorder::UnavailableStatus);
Q_EMIT error(QMediaRecorder::ResourceError, QLatin1String("Permission denied."));
return;
diff --git a/src/plugins/android/src/wrappers/jni/androidcamera.cpp b/src/plugins/android/src/wrappers/jni/androidcamera.cpp
index 2f32fb742..3ea7bc773 100644
--- a/src/plugins/android/src/wrappers/jni/androidcamera.cpp
+++ b/src/plugins/android/src/wrappers/jni/androidcamera.cpp
@@ -58,11 +58,6 @@ QT_BEGIN_NAMESPACE
static const char QtCameraListenerClassName[] = "org/qtproject/qt5/android/multimedia/QtCameraListener";
-static QString cameraPermissionKey()
-{
- return QStringLiteral("android.permission.CAMERA");
-}
-
typedef QHash<int, AndroidCamera *> CameraMap;
Q_GLOBAL_STATIC(CameraMap, cameras)
Q_GLOBAL_STATIC(QReadWriteLock, rwLock)
@@ -324,6 +319,9 @@ AndroidCamera::~AndroidCamera()
AndroidCamera *AndroidCamera::open(int cameraId)
{
+ if (!qt_androidRequestCameraPermission())
+ return nullptr;
+
AndroidCameraPrivate *d = new AndroidCameraPrivate();
QThread *worker = new QThread;
worker->start();
@@ -764,7 +762,7 @@ QJNIObjectPrivate AndroidCamera::getCameraObject()
int AndroidCamera::getNumberOfCameras()
{
- if (!requestCameraPermission())
+ if (!qt_androidRequestCameraPermission())
return 0;
return QJNIObjectPrivate::callStaticMethod<jint>("android/hardware/Camera",
@@ -801,11 +799,6 @@ void AndroidCamera::getCameraInfo(int id, AndroidCameraInfo *info)
}
}
-bool AndroidCamera::requestCameraPermission()
-{
- return qt_androidRequestPermission(cameraPermissionKey());
-}
-
void AndroidCamera::startPreview()
{
Q_D(AndroidCamera);
diff --git a/src/plugins/android/src/wrappers/jni/androidmediarecorder.cpp b/src/plugins/android/src/wrappers/jni/androidmediarecorder.cpp
index d0101411b..d607ab806 100644
--- a/src/plugins/android/src/wrappers/jni/androidmediarecorder.cpp
+++ b/src/plugins/android/src/wrappers/jni/androidmediarecorder.cpp
@@ -383,11 +383,6 @@ void AndroidMediaRecorder::setSurfaceHolder(AndroidSurfaceHolder *holder)
}
}
-bool AndroidMediaRecorder::requestRecordingPermission()
-{
- return qt_androidRequestPermission(QLatin1String("android.permission.RECORD_AUDIO"));
-}
-
bool AndroidMediaRecorder::initJNI(JNIEnv *env)
{
jclass clazz = QJNIEnvironmentPrivate::findClass(QtMediaRecorderListenerClassName,
diff --git a/src/plugins/android/src/wrappers/jni/androidmediarecorder.h b/src/plugins/android/src/wrappers/jni/androidmediarecorder.h
index cd2d164d8..e4b3a80ea 100644
--- a/src/plugins/android/src/wrappers/jni/androidmediarecorder.h
+++ b/src/plugins/android/src/wrappers/jni/androidmediarecorder.h
@@ -160,7 +160,6 @@ public:
void setSurfaceTexture(AndroidSurfaceTexture *texture);
void setSurfaceHolder(AndroidSurfaceHolder *holder);
- static bool requestRecordingPermission();
static bool initJNI(JNIEnv *env);
Q_SIGNALS:
diff --git a/src/plugins/avfoundation/camera/avfmediaassetwriter.h b/src/plugins/avfoundation/camera/avfmediaassetwriter.h
index 9d61d5089..f063dab4b 100644
--- a/src/plugins/avfoundation/camera/avfmediaassetwriter.h
+++ b/src/plugins/avfoundation/camera/avfmediaassetwriter.h
@@ -43,7 +43,6 @@
#include "avfcamerautility.h"
#include <QtCore/qglobal.h>
-#include <QtCore/qatomic.h>
#include <AVFoundation/AVFoundation.h>
@@ -52,17 +51,10 @@ QT_BEGIN_NAMESPACE
class AVFMediaRecorderControlIOS;
class AVFCameraService;
-typedef QAtomicInteger<qint64> AVFAtomicInt64;
-
QT_END_NAMESPACE
@interface QT_MANGLE_NAMESPACE(AVFMediaAssetWriter) : NSObject<AVCaptureVideoDataOutputSampleBufferDelegate,
AVCaptureAudioDataOutputSampleBufferDelegate>
-{
-@public
- QT_PREPEND_NAMESPACE(AVFAtomicInt64) m_durationInMs;
-}
-
- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(AVFMediaRecorderControlIOS) *)delegate;
- (bool)setupWithFileURL:(NSURL *)fileURL
@@ -76,6 +68,7 @@ QT_END_NAMESPACE
- (void)stop;
// This to be called from the recorder control's dtor:
- (void)abort;
+- (qint64)durationInMs;
@end
diff --git a/src/plugins/avfoundation/camera/avfmediaassetwriter.mm b/src/plugins/avfoundation/camera/avfmediaassetwriter.mm
index 318d66117..2d40b9087 100644
--- a/src/plugins/avfoundation/camera/avfmediaassetwriter.mm
+++ b/src/plugins/avfoundation/camera/avfmediaassetwriter.mm
@@ -47,6 +47,7 @@
#include "avfmediacontainercontrol.h"
#include <QtCore/qmetaobject.h>
+#include <QtCore/qatomic.h>
QT_USE_NAMESPACE
@@ -79,6 +80,8 @@ enum WriterState
WriterStateAborted
};
+using AVFAtomicInt64 = QAtomicInteger<qint64>;
+
} // unnamed namespace
@interface QT_MANGLE_NAMESPACE(AVFMediaAssetWriter) (PrivateAPI)
@@ -93,32 +96,35 @@ enum WriterState
@private
AVFCameraService *m_service;
- QT_PREPEND_NAMESPACE(AVFScopedPointer)<AVAssetWriterInput> m_cameraWriterInput;
- QT_PREPEND_NAMESPACE(AVFScopedPointer)<AVCaptureDeviceInput> m_audioInput;
- QT_PREPEND_NAMESPACE(AVFScopedPointer)<AVCaptureAudioDataOutput> m_audioOutput;
- QT_PREPEND_NAMESPACE(AVFScopedPointer)<AVAssetWriterInput> m_audioWriterInput;
+ AVFScopedPointer<AVAssetWriterInput> m_cameraWriterInput;
+ AVFScopedPointer<AVCaptureDeviceInput> m_audioInput;
+ AVFScopedPointer<AVCaptureAudioDataOutput> m_audioOutput;
+ AVFScopedPointer<AVAssetWriterInput> m_audioWriterInput;
+
AVCaptureDevice *m_audioCaptureDevice;
// Queue to write sample buffers:
- QT_PREPEND_NAMESPACE(AVFScopedPointer)<dispatch_queue_t> m_writerQueue;
+ AVFScopedPointer<dispatch_queue_t> m_writerQueue;
// High priority serial queue for video output:
- QT_PREPEND_NAMESPACE(AVFScopedPointer)<dispatch_queue_t> m_videoQueue;
+ AVFScopedPointer<dispatch_queue_t> m_videoQueue;
// Serial queue for audio output:
- QT_PREPEND_NAMESPACE(AVFScopedPointer)<dispatch_queue_t> m_audioQueue;
+ AVFScopedPointer<dispatch_queue_t> m_audioQueue;
- QT_PREPEND_NAMESPACE(AVFScopedPointer)<AVAssetWriter> m_assetWriter;
+ AVFScopedPointer<AVAssetWriter> m_assetWriter;
- QT_PREPEND_NAMESPACE(AVFMediaRecorderControlIOS) *m_delegate;
+ AVFMediaRecorderControlIOS *m_delegate;
bool m_setStartTime;
- QT_PREPEND_NAMESPACE(QAtomicInt) m_state;
-@private
+ QAtomicInt m_state;
+
CMTime m_startTime;
CMTime m_lastTimeStamp;
NSDictionary *m_audioSettings;
NSDictionary *m_videoSettings;
+
+ AVFAtomicInt64 m_durationInMs;
}
- (id)initWithDelegate:(AVFMediaRecorderControlIOS *)delegate
@@ -413,7 +419,7 @@ enum WriterState
m_audioOutput.reset([[AVCaptureAudioDataOutput alloc] init]);
- if (m_audioOutput && [captureSession canAddOutput:m_audioOutput]) {
+ if (m_audioOutput.data() && [captureSession canAddOutput:m_audioOutput]) {
[captureSession addOutput:m_audioOutput];
} else {
qDebugCamera() << Q_FUNC_INFO << "failed to add audio output";
@@ -431,7 +437,7 @@ enum WriterState
{
Q_ASSERT(m_service && m_service->videoOutput()
&& m_service->videoOutput()->videoDataOutput());
- Q_ASSERT(m_assetWriter);
+ Q_ASSERT(m_assetWriter.data());
m_cameraWriterInput.reset([[AVAssetWriterInput alloc] initWithMediaType:AVMediaTypeVideo
outputSettings:m_videoSettings
@@ -451,7 +457,7 @@ enum WriterState
m_cameraWriterInput.data().expectsMediaDataInRealTime = YES;
- if (m_audioOutput) {
+ if (m_audioOutput.data()) {
CMFormatDescriptionRef sourceFormat = m_audioCaptureDevice ? m_audioCaptureDevice.activeFormat.formatDescription : 0;
m_audioWriterInput.reset([[AVAssetWriterInput alloc] initWithMediaType:AVMediaTypeAudio
outputSettings:m_audioSettings
@@ -479,7 +485,7 @@ enum WriterState
[m_service->videoOutput()->videoDataOutput() setSampleBufferDelegate:self queue:m_videoQueue];
- if (m_audioOutput) {
+ if (m_audioOutput.data()) {
Q_ASSERT(m_audioQueue);
[m_audioOutput setSampleBufferDelegate:self queue:m_audioQueue];
}
@@ -500,4 +506,9 @@ enum WriterState
}
}
+- (qint64)durationInMs
+{
+ return m_durationInMs.loadAcquire();
+}
+
@end
diff --git a/src/plugins/avfoundation/camera/avfmediarecordercontrol_ios.mm b/src/plugins/avfoundation/camera/avfmediarecordercontrol_ios.mm
index 0b31bd0bc..62197e900 100644
--- a/src/plugins/avfoundation/camera/avfmediarecordercontrol_ios.mm
+++ b/src/plugins/avfoundation/camera/avfmediarecordercontrol_ios.mm
@@ -144,7 +144,7 @@ QMediaRecorder::Status AVFMediaRecorderControlIOS::status() const
qint64 AVFMediaRecorderControlIOS::duration() const
{
- return m_writer.data()->m_durationInMs.load();
+ return m_writer.data().durationInMs;
}
bool AVFMediaRecorderControlIOS::isMuted() const
diff --git a/src/plugins/opensles/qopenslesaudioinput.cpp b/src/plugins/opensles/qopenslesaudioinput.cpp
index ad87cb057..54ed18ac1 100644
--- a/src/plugins/opensles/qopenslesaudioinput.cpp
+++ b/src/plugins/opensles/qopenslesaudioinput.cpp
@@ -117,6 +117,8 @@ QOpenSLESAudioInput::QOpenSLESAudioInput(const QByteArray &device)
m_recorderPreset = SL_ANDROID_RECORDING_PRESET_CAMCORDER;
else if (qstrcmp(device, QT_ANDROID_PRESET_VOICE_RECOGNITION) == 0)
m_recorderPreset = SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION;
+ else if (qstrcmp(device, QT_ANDROID_PRESET_VOICE_COMMUNICATION) == 0)
+ m_recorderPreset = SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION;
else
m_recorderPreset = SL_ANDROID_RECORDING_PRESET_GENERIC;
#endif
diff --git a/src/plugins/opensles/qopenslesaudioinput.h b/src/plugins/opensles/qopenslesaudioinput.h
index ad84db0cd..35cc37959 100644
--- a/src/plugins/opensles/qopenslesaudioinput.h
+++ b/src/plugins/opensles/qopenslesaudioinput.h
@@ -50,6 +50,7 @@
#define QT_ANDROID_PRESET_MIC "mic"
#define QT_ANDROID_PRESET_CAMCORDER "camcorder"
#define QT_ANDROID_PRESET_VOICE_RECOGNITION "voicerecognition"
+#define QT_ANDROID_PRESET_VOICE_COMMUNICATION "voicecommunication"
#endif
diff --git a/src/plugins/opensles/qopenslesengine.cpp b/src/plugins/opensles/qopenslesengine.cpp
index 43cdcb276..36025dcfd 100644
--- a/src/plugins/opensles/qopenslesengine.cpp
+++ b/src/plugins/opensles/qopenslesengine.cpp
@@ -114,7 +114,8 @@ QList<QByteArray> QOpenSLESEngine::availableDevices(QAudio::Mode mode) const
#ifdef ANDROID
devices << QT_ANDROID_PRESET_MIC
<< QT_ANDROID_PRESET_CAMCORDER
- << QT_ANDROID_PRESET_VOICE_RECOGNITION;
+ << QT_ANDROID_PRESET_VOICE_RECOGNITION
+ << QT_ANDROID_PRESET_VOICE_COMMUNICATION;
#else
devices << "default";
#endif
diff --git a/src/qtmultimediaquicktools/qdeclarativevideooutput.cpp b/src/qtmultimediaquicktools/qdeclarativevideooutput.cpp
index 18cf0e927..32166502d 100644
--- a/src/qtmultimediaquicktools/qdeclarativevideooutput.cpp
+++ b/src/qtmultimediaquicktools/qdeclarativevideooutput.cpp
@@ -57,7 +57,7 @@ Q_LOGGING_CATEGORY(qLcVideo, "qt.multimedia.video")
/*!
\qmltype VideoOutput
- \instantiates QDeclarativeVideoOutput
+ //! \instantiates QDeclarativeVideoOutput
\brief Render video or camera viewfinder.
\ingroup multimedia_qml
@@ -206,6 +206,7 @@ void QDeclarativeVideoOutput::setSource(QObject *source)
}
m_sourceType = MediaObjectSource;
+#if QT_CONFIG(opengl)
} else if (metaObject->indexOfProperty("videoSurface") != -1) {
// Make sure our backend is a QDeclarativeVideoRendererBackend
m_backend.reset();
@@ -219,6 +220,7 @@ void QDeclarativeVideoOutput::setSource(QObject *source)
m_source.data()->setProperty("videoSurface",
QVariant::fromValue<QAbstractVideoSurface*>(surface));
m_sourceType = VideoSurfaceSource;
+#endif
} else {
m_sourceType = NoSource;
}
@@ -247,12 +249,13 @@ bool QDeclarativeVideoOutput::createBackend(QMediaService *service)
}
}
}
-
+#if QT_CONFIG(opengl)
if (!backendAvailable) {
m_backend.reset(new QDeclarativeVideoRendererBackend(this));
if (m_backend->init(service))
backendAvailable = true;
}
+#endif
// QDeclarativeVideoWindowBackend only works when there is a service with a QVideoWindowControl.
// Without service, the QDeclarativeVideoRendererBackend should always work.
diff --git a/src/qtmultimediaquicktools/qtmultimediaquicktools.pro b/src/qtmultimediaquicktools/qtmultimediaquicktools.pro
index 7c8d07647..cb1f8106b 100644
--- a/src/qtmultimediaquicktools/qtmultimediaquicktools.pro
+++ b/src/qtmultimediaquicktools/qtmultimediaquicktools.pro
@@ -11,20 +11,23 @@ PRIVATE_HEADERS += \
HEADERS += \
$$PRIVATE_HEADERS \
- qdeclarativevideooutput_render_p.h \
- qdeclarativevideooutput_window_p.h \
- qsgvideonode_yuv_p.h \
- qsgvideonode_rgb_p.h \
- qsgvideonode_texture_p.h
+ qdeclarativevideooutput_window_p.h
SOURCES += \
qsgvideonode_p.cpp \
qdeclarativevideooutput.cpp \
- qdeclarativevideooutput_render.cpp \
- qdeclarativevideooutput_window.cpp \
- qsgvideonode_yuv.cpp \
- qsgvideonode_rgb.cpp \
- qsgvideonode_texture.cpp
+ qdeclarativevideooutput_window.cpp
+
+qtConfig(opengl) {
+ SOURCES += qdeclarativevideooutput_render.cpp \
+ qsgvideonode_rgb.cpp \
+ qsgvideonode_yuv.cpp \
+ qsgvideonode_texture.cpp
+ HEADERS += qdeclarativevideooutput_render_p.h \
+ qsgvideonode_rgb_p.h \
+ qsgvideonode_yuv_p.h \
+ qsgvideonode_texture_p.h
+}
RESOURCES += \
qtmultimediaquicktools.qrc
diff --git a/src/src.pro b/src/src.pro
index 97a053379..1dc1015c6 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -16,7 +16,7 @@ src_plugins.subdir = plugins
src_plugins.depends = multimedia
-qtHaveModule(quick):qtConfig(opengl) {
+qtHaveModule(quick) {
src_qtmultimediaquicktools.subdir = qtmultimediaquicktools
src_qtmultimediaquicktools.depends = multimedia