summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--qtmultimedia.pro1
-rw-r--r--src/gsttools/qgstreamervideorenderer.cpp2
-rw-r--r--src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h1
-rw-r--r--src/multimediawidgets/qpaintervideosurface.cpp9
-rw-r--r--src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer.java5
-rw-r--r--src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp47
-rw-r--r--src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h2
-rw-r--r--src/plugins/android/src/wrappers/jni/androidmediaplayer.cpp61
-rw-r--r--src/plugins/android/src/wrappers/jni/androidmediaplayer.h2
-rw-r--r--src/plugins/directshow/camera/camera.pri6
-rw-r--r--src/plugins/directshow/camera/directshowcameraimageencodercontrol.cpp95
-rw-r--r--src/plugins/directshow/camera/directshowcameraimageencodercontrol.h70
-rw-r--r--src/plugins/directshow/camera/dscameraservice.cpp6
-rw-r--r--src/plugins/directshow/camera/dscameraservice.h2
-rw-r--r--src/plugins/directshow/camera/dscamerasession.cpp33
-rw-r--r--src/plugins/directshow/camera/dscamerasession.h8
-rw-r--r--src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp2
-rw-r--r--src/plugins/gstreamer/mediacapture/qgstreamerrecordercontrol.cpp4
-rw-r--r--src/plugins/qnx/mediaplayer/mmrenderervideowindowcontrol.cpp18
-rw-r--r--src/plugins/videonode/imx6/qsgvivantevideomaterial.cpp74
-rw-r--r--src/plugins/videonode/imx6/qsgvivantevideomaterial.h1
21 files changed, 384 insertions, 65 deletions
diff --git a/qtmultimedia.pro b/qtmultimedia.pro
index 00c82cd0f..29e5102f7 100644
--- a/qtmultimedia.pro
+++ b/qtmultimedia.pro
@@ -1,3 +1,4 @@
requires(qtHaveModule(gui))
+requires(qtHaveModule(network))
load(qt_parts)
diff --git a/src/gsttools/qgstreamervideorenderer.cpp b/src/gsttools/qgstreamervideorenderer.cpp
index 1b5cc8caf..25fc33cb3 100644
--- a/src/gsttools/qgstreamervideorenderer.cpp
+++ b/src/gsttools/qgstreamervideorenderer.cpp
@@ -113,7 +113,7 @@ void QGstreamerVideoRenderer::setSurface(QAbstractVideoSurface *surface)
if (m_surface) {
connect(m_surface.data(), SIGNAL(supportedFormatsChanged()),
this, SLOT(handleFormatChange()));
- QGstVideoRendererSink::setSurface(m_surface);
+ QVideoSurfaceGstSink::setSurface(m_surface);
}
if (wasReady != isReady())
diff --git a/src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h b/src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h
index 034af39fc..961cf91d2 100644
--- a/src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h
+++ b/src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h
@@ -139,6 +139,7 @@ public:
GstVideoSink parent;
static QVideoSurfaceGstSink *createSink(QAbstractVideoSurface *surface);
+ static void setSurface(QAbstractVideoSurface *surface) { Q_UNUSED(surface); }
private:
static GType get_type();
diff --git a/src/multimediawidgets/qpaintervideosurface.cpp b/src/multimediawidgets/qpaintervideosurface.cpp
index 0396f9fc0..e4762a7e1 100644
--- a/src/multimediawidgets/qpaintervideosurface.cpp
+++ b/src/multimediawidgets/qpaintervideosurface.cpp
@@ -143,6 +143,11 @@ QAbstractVideoSurface::Error QVideoSurfaceGenericPainter::start(const QVideoSurf
{
m_frame = QVideoFrame();
m_imageFormat = QVideoFrame::imageFormatFromPixelFormat(format.pixelFormat());
+ // Do not render into ARGB32 images using QPainter.
+ // Using QImage::Format_ARGB32_Premultiplied is significantly faster.
+ if (m_imageFormat == QImage::Format_ARGB32)
+ m_imageFormat = QImage::Format_ARGB32_Premultiplied;
+
m_imageSize = format.frameSize();
m_scanLineDirection = format.scanLineDirection();
m_mirrored = format.property("mirrored").toBool();
@@ -191,10 +196,6 @@ QAbstractVideoSurface::Error QVideoSurfaceGenericPainter::paint(
m_imageSize.height(),
m_frame.bytesPerLine(),
m_imageFormat);
- // Do not render into ARGB32 images using QPainter.
- // Using QImage::Format_ARGB32_Premultiplied is significantly faster.
- if (m_imageFormat == QImage::Format_ARGB32)
- image = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
const QTransform oldTransform = painter->transform();
QTransform transform = oldTransform;
diff --git a/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer.java b/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer.java
index 7fb4a8690..b1da2f1fa 100644
--- a/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer.java
+++ b/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer.java
@@ -212,6 +212,11 @@ public class QtAndroidMediaPlayer
mContext = context;
}
+ public MediaPlayer getMediaPlayerHandle()
+ {
+ return mMediaPlayer;
+ }
+
private void setState(int state)
{
if (mState == state)
diff --git a/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp
index 9631a6ba7..df1463a87 100644
--- a/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp
+++ b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp
@@ -93,7 +93,9 @@ QAndroidMediaPlayerControl::QAndroidMediaPlayerControl(QObject *parent)
mPendingVolume(-1),
mPendingMute(-1),
mReloadingMedia(false),
- mActiveStateChangeNotifiers(0)
+ mActiveStateChangeNotifiers(0),
+ mPendingPlaybackRate(1.0),
+ mHasPendingPlaybackRate(false)
{
connect(mMediaPlayer,SIGNAL(bufferingChanged(qint32)),
this,SLOT(onBufferingChanged(qint32)));
@@ -290,12 +292,45 @@ void QAndroidMediaPlayerControl::updateAvailablePlaybackRanges()
qreal QAndroidMediaPlayerControl::playbackRate() const
{
- return 1.0f;
+ if (mHasPendingPlaybackRate ||
+ (mState & (AndroidMediaPlayer::Initialized
+ | AndroidMediaPlayer::Prepared
+ | AndroidMediaPlayer::Started
+ | AndroidMediaPlayer::Paused
+ | AndroidMediaPlayer::PlaybackCompleted
+ | AndroidMediaPlayer::Error)) == 0) {
+ return mPendingPlaybackRate;
+ }
+
+ return mMediaPlayer->playbackRate();
}
void QAndroidMediaPlayerControl::setPlaybackRate(qreal rate)
{
- Q_UNUSED(rate);
+ if ((mState & (AndroidMediaPlayer::Initialized
+ | AndroidMediaPlayer::Prepared
+ | AndroidMediaPlayer::Started
+ | AndroidMediaPlayer::Paused
+ | AndroidMediaPlayer::PlaybackCompleted
+ | AndroidMediaPlayer::Error)) == 0) {
+ if (mPendingPlaybackRate != rate) {
+ mPendingPlaybackRate = rate;
+ mHasPendingPlaybackRate = true;
+ Q_EMIT playbackRateChanged(rate);
+ }
+ return;
+ }
+
+ bool succeeded = mMediaPlayer->setPlaybackRate(rate);
+
+ if (mHasPendingPlaybackRate) {
+ mHasPendingPlaybackRate = false;
+ mPendingPlaybackRate = qreal(1.0);
+ if (!succeeded)
+ Q_EMIT playbackRateChanged(playbackRate());
+ } else if (succeeded) {
+ Q_EMIT playbackRateChanged(rate);
+ }
}
QMediaContent QAndroidMediaPlayerControl::media() const
@@ -379,6 +414,9 @@ void QAndroidMediaPlayerControl::play()
setMedia(mMediaContent, mMediaStream);
}
+ if (!mMediaContent.isNull())
+ setState(QMediaPlayer::PlayingState);
+
if ((mState & (AndroidMediaPlayer::Prepared
| AndroidMediaPlayer::Started
| AndroidMediaPlayer::Paused
@@ -387,7 +425,6 @@ void QAndroidMediaPlayerControl::play()
return;
}
- setState(QMediaPlayer::PlayingState);
mMediaPlayer->play();
}
@@ -718,6 +755,8 @@ void QAndroidMediaPlayerControl::flushPendingStates()
setVolume(mPendingVolume);
if (mPendingMute != -1)
setMuted((mPendingMute == 1));
+ if (mHasPendingPlaybackRate)
+ setPlaybackRate(mPendingPlaybackRate);
switch (newState) {
case QMediaPlayer::PlayingState:
diff --git a/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h
index 04f728a59..119add7f8 100644
--- a/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h
+++ b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h
@@ -117,6 +117,8 @@ private:
int mPendingMute;
bool mReloadingMedia;
int mActiveStateChangeNotifiers;
+ qreal mPendingPlaybackRate;
+ bool mHasPendingPlaybackRate; // we need this because the rate can theoretically be negative
void setState(QMediaPlayer::State state);
void setMediaStatus(QMediaPlayer::MediaStatus status);
diff --git a/src/plugins/android/src/wrappers/jni/androidmediaplayer.cpp b/src/plugins/android/src/wrappers/jni/androidmediaplayer.cpp
index 582d8aa9d..b81f98cbd 100644
--- a/src/plugins/android/src/wrappers/jni/androidmediaplayer.cpp
+++ b/src/plugins/android/src/wrappers/jni/androidmediaplayer.cpp
@@ -109,6 +109,33 @@ bool AndroidMediaPlayer::isMuted()
return mMediaPlayer.callMethod<jboolean>("isMuted");
}
+qreal AndroidMediaPlayer::playbackRate()
+{
+ qreal rate(1.0);
+
+ if (QtAndroidPrivate::androidSdkVersion() < 23)
+ return rate;
+
+ QJNIObjectPrivate player = mMediaPlayer.callObjectMethod("getMediaPlayerHandle", "()Landroid/media/MediaPlayer;");
+ if (player.isValid()) {
+ QJNIObjectPrivate playbackParams = player.callObjectMethod("getPlaybackParams", "()Landroid/media/PlaybackParams;");
+ if (playbackParams.isValid()) {
+ const qreal speed = playbackParams.callMethod<jfloat>("getSpeed", "()F");
+ QJNIEnvironmentPrivate env;
+ if (env->ExceptionCheck()) {
+#ifdef QT_DEBUG
+ env->ExceptionDescribe();
+#endif // QT_DEBUG
+ env->ExceptionClear();
+ } else {
+ rate = speed;
+ }
+ }
+ }
+
+ return rate;
+}
+
jobject AndroidMediaPlayer::display()
{
return mMediaPlayer.callObjectMethod("display", "()Landroid/view/SurfaceHolder;").object();
@@ -155,6 +182,40 @@ void AndroidMediaPlayer::setVolume(int volume)
mMediaPlayer.callMethod<void>("setVolume", "(I)V", jint(volume));
}
+bool AndroidMediaPlayer::setPlaybackRate(qreal rate)
+{
+ if (QtAndroidPrivate::androidSdkVersion() < 23) {
+ qWarning("Setting the playback rate on a media player requires Android 6.0 (API level 23) or later");
+ return false;
+ }
+
+ QJNIEnvironmentPrivate env;
+
+ QJNIObjectPrivate player = mMediaPlayer.callObjectMethod("getMediaPlayerHandle", "()Landroid/media/MediaPlayer;");
+ if (player.isValid()) {
+ QJNIObjectPrivate playbackParams = player.callObjectMethod("getPlaybackParams", "()Landroid/media/PlaybackParams;");
+ if (playbackParams.isValid()) {
+ playbackParams.callObjectMethod("setSpeed", "(F)Landroid/media/PlaybackParams;", jfloat(rate));
+ // pitch can only be > 0
+ if (!qFuzzyIsNull(rate))
+ playbackParams.callObjectMethod("setPitch", "(F)Landroid/media/PlaybackParams;", jfloat(qAbs(rate)));
+ player.callMethod<void>("setPlaybackParams", "(Landroid/media/PlaybackParams;)V", playbackParams.object());
+ if (Q_UNLIKELY(env->ExceptionCheck())) {
+#ifdef QT_DEBUG
+ env->ExceptionDescribe();
+#endif // QT_DEBUG
+ env->ExceptionClear();
+ qWarning() << "Invalid playback rate" << rate;
+ return false;
+ } else {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
void AndroidMediaPlayer::setDisplay(AndroidSurfaceTexture *surfaceTexture)
{
mMediaPlayer.callMethod<void>("setDisplay",
diff --git a/src/plugins/android/src/wrappers/jni/androidmediaplayer.h b/src/plugins/android/src/wrappers/jni/androidmediaplayer.h
index 28bfa3662..a7284bb0c 100644
--- a/src/plugins/android/src/wrappers/jni/androidmediaplayer.h
+++ b/src/plugins/android/src/wrappers/jni/androidmediaplayer.h
@@ -103,6 +103,7 @@ public:
bool isPlaying();
int volume();
bool isMuted();
+ qreal playbackRate();
jobject display();
void play();
@@ -113,6 +114,7 @@ public:
void setDataSource(const QString &path);
void prepareAsync();
void setVolume(int volume);
+ bool setPlaybackRate(qreal rate);
void setDisplay(AndroidSurfaceTexture *surfaceTexture);
static bool initJNI(JNIEnv *env);
diff --git a/src/plugins/directshow/camera/camera.pri b/src/plugins/directshow/camera/camera.pri
index 0e1c1e895..3be1acc49 100644
--- a/src/plugins/directshow/camera/camera.pri
+++ b/src/plugins/directshow/camera/camera.pri
@@ -15,7 +15,8 @@ HEADERS += \
$$PWD/directshowcameraexposurecontrol.h \
$$PWD/directshowcameracapturedestinationcontrol.h \
$$PWD/directshowcameracapturebufferformatcontrol.h \
- $$PWD/directshowcamerazoomcontrol.h
+ $$PWD/directshowcamerazoomcontrol.h \
+ $$PWD/directshowcameraimageencodercontrol.h
SOURCES += \
$$PWD/dscameraservice.cpp \
@@ -29,7 +30,8 @@ SOURCES += \
$$PWD/directshowcameraexposurecontrol.cpp \
$$PWD/directshowcameracapturedestinationcontrol.cpp \
$$PWD/directshowcameracapturebufferformatcontrol.cpp \
- $$PWD/directshowcamerazoomcontrol.cpp
+ $$PWD/directshowcamerazoomcontrol.cpp \
+ $$PWD/directshowcameraimageencodercontrol.cpp
*-msvc*:INCLUDEPATH += $$(DXSDK_DIR)/include
QMAKE_USE += directshow
diff --git a/src/plugins/directshow/camera/directshowcameraimageencodercontrol.cpp b/src/plugins/directshow/camera/directshowcameraimageencodercontrol.cpp
new file mode 100644
index 000000000..912f67a2d
--- /dev/null
+++ b/src/plugins/directshow/camera/directshowcameraimageencodercontrol.cpp
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 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-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "directshowcameraimageencodercontrol.h"
+#include "dscamerasession.h"
+#include <QImageWriter>
+
+QT_BEGIN_NAMESPACE
+
+DirectShowCameraImageEncoderControl::DirectShowCameraImageEncoderControl(DSCameraSession *session)
+ : QImageEncoderControl(session)
+ , m_session(session)
+{
+}
+
+QList<QSize> DirectShowCameraImageEncoderControl::supportedResolutions(const QImageEncoderSettings &settings, bool *continuous) const
+{
+ QList<QSize> res;
+ if (!settings.codec().isEmpty() && !supportedImageCodecs().contains(settings.codec(), Qt::CaseInsensitive))
+ return res;
+
+ QList<QSize> resolutions = m_session->supportedResolutions(continuous);
+ QSize r = settings.resolution();
+ if (!r.isValid())
+ return resolutions;
+
+ if (resolutions.contains(r))
+ res << settings.resolution();
+
+ return res;
+}
+
+QStringList DirectShowCameraImageEncoderControl::supportedImageCodecs() const
+{
+ QStringList supportedCodecs;
+ for (const QByteArray &type: QImageWriter::supportedImageFormats()) {
+ supportedCodecs << type;
+ }
+
+ return supportedCodecs;
+}
+
+QString DirectShowCameraImageEncoderControl::imageCodecDescription(const QString &codecName) const
+{
+ Q_UNUSED(codecName);
+ return QString();
+}
+
+QImageEncoderSettings DirectShowCameraImageEncoderControl::imageSettings() const
+{
+ return m_session->imageEncoderSettings();
+}
+
+void DirectShowCameraImageEncoderControl::setImageSettings(const QImageEncoderSettings &settings)
+{
+ m_session->setImageEncoderSettings(settings);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/directshow/camera/directshowcameraimageencodercontrol.h b/src/plugins/directshow/camera/directshowcameraimageencodercontrol.h
new file mode 100644
index 000000000..6891bea77
--- /dev/null
+++ b/src/plugins/directshow/camera/directshowcameraimageencodercontrol.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 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-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DIRECTSHOWCAMERAIMAGEENCODERCONTROL_H
+#define DIRECTSHOWCAMERAIMAGEENCODERCONTROL_H
+
+#include <qimageencodercontrol.h>
+
+QT_BEGIN_NAMESPACE
+
+class DSCameraSession;
+class DirectShowCameraImageEncoderControl : public QImageEncoderControl
+{
+ Q_OBJECT
+public:
+ DirectShowCameraImageEncoderControl(DSCameraSession *session);
+
+ QList<QSize> supportedResolutions(
+ const QImageEncoderSettings &settings = QImageEncoderSettings(),
+ bool *continuous = nullptr) const override;
+
+ QStringList supportedImageCodecs() const override;
+ QString imageCodecDescription(const QString &formatName) const override;
+
+ QImageEncoderSettings imageSettings() const override;
+ void setImageSettings(const QImageEncoderSettings &settings) override;
+
+private:
+ DSCameraSession *m_session;
+};
+
+QT_END_NAMESPACE
+
+#endif // DIRECTSHOWCAMERAIMAGEENCODERCONTROL_H
diff --git a/src/plugins/directshow/camera/dscameraservice.cpp b/src/plugins/directshow/camera/dscameraservice.cpp
index a806cabe3..8115ef385 100644
--- a/src/plugins/directshow/camera/dscameraservice.cpp
+++ b/src/plugins/directshow/camera/dscameraservice.cpp
@@ -53,6 +53,7 @@
#include "directshowcameracapturebufferformatcontrol.h"
#include "directshowvideoprobecontrol.h"
#include "directshowcamerazoomcontrol.h"
+#include "directshowcameraimageencodercontrol.h"
QT_BEGIN_NAMESPACE
@@ -70,6 +71,7 @@ DSCameraService::DSCameraService(QObject *parent):
, m_captureBufferFormatControl(new DirectShowCameraCaptureBufferFormatControl)
, m_videoProbeControl(nullptr)
, m_zoomControl(new DirectShowCameraZoomControl(m_session))
+ , m_imageEncoderControl(new DirectShowCameraImageEncoderControl(m_session))
{
}
@@ -81,6 +83,7 @@ DSCameraService::~DSCameraService()
delete m_videoDevice;
delete m_videoRenderer;
delete m_imageCapture;
+ delete m_imageEncoderControl;
delete m_session;
delete m_exposureControl;
delete m_captureDestinationControl;
@@ -134,6 +137,9 @@ QMediaControl* DSCameraService::requestControl(const char *name)
if (qstrcmp(name, QCameraZoomControl_iid) == 0)
return m_zoomControl;
+ if (qstrcmp(name, QImageEncoderControl_iid) == 0)
+ return m_imageEncoderControl;
+
return 0;
}
diff --git a/src/plugins/directshow/camera/dscameraservice.h b/src/plugins/directshow/camera/dscameraservice.h
index 2e45edcce..9a8f745f6 100644
--- a/src/plugins/directshow/camera/dscameraservice.h
+++ b/src/plugins/directshow/camera/dscameraservice.h
@@ -57,6 +57,7 @@ class DirectShowCameraCaptureDestinationControl;
class DirectShowCameraCaptureBufferFormatControl;
class DirectShowVideoProbeControl;
class DirectShowCameraZoomControl;
+class DirectShowCameraImageEncoderControl;
class DSCameraService : public QMediaService
{
@@ -82,6 +83,7 @@ private:
DirectShowCameraCaptureBufferFormatControl *m_captureBufferFormatControl;
DirectShowVideoProbeControl *m_videoProbeControl;
DirectShowCameraZoomControl *m_zoomControl;
+ DirectShowCameraImageEncoderControl *m_imageEncoderControl;
};
QT_END_NAMESPACE
diff --git a/src/plugins/directshow/camera/dscamerasession.cpp b/src/plugins/directshow/camera/dscamerasession.cpp
index bf81262d6..8d0c72057 100644
--- a/src/plugins/directshow/camera/dscamerasession.cpp
+++ b/src/plugins/directshow/camera/dscamerasession.cpp
@@ -584,10 +584,13 @@ int DSCameraSession::captureImage(const QString &fileName)
return m_imageIdCounter;
}
+ const QString ext = !m_imageEncoderSettings.codec().isEmpty()
+ ? m_imageEncoderSettings.codec().toLower()
+ : QLatin1String("jpg");
m_imageCaptureFileName = m_fileNameGenerator.generateFileName(fileName,
QMediaStorageLocation::Pictures,
QLatin1String("IMG_"),
- QLatin1String("jpg"));
+ ext);
updateReadyForCapture();
@@ -687,8 +690,9 @@ void DSCameraSession::processCapturedImage(int id,
const QImage &image,
const QString &path)
{
+ const QString format = m_imageEncoderSettings.codec();
if (captureDestinations & QCameraImageCapture::CaptureToFile) {
- if (image.save(path, "JPG")) {
+ if (image.save(path, !format.isEmpty() ? format.toUtf8().constData() : "JPG")) {
Q_EMIT imageSaved(id, path);
} else {
Q_EMIT captureError(id, QCameraImageCapture::ResourceError,
@@ -713,7 +717,7 @@ bool DSCameraSession::createFilterGraph()
// Create the filter graph
hr = CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC,
- IID_IGraphBuilder, reinterpret_cast<void**>(*&m_filterGraph));
+ IID_IGraphBuilder, reinterpret_cast<void**>(&m_filterGraph));
if (FAILED(hr)) {
errorString = tr("Failed to create filter graph");
goto failed;
@@ -844,9 +848,11 @@ bool DSCameraSession::configurePreviewFormat()
{
// Resolve viewfinder settings
int settingsIndex = 0;
+ const QSize captureResolution = m_imageEncoderSettings.resolution();
+ const QSize resolution = captureResolution.isValid() ? captureResolution : m_viewfinderSettings.resolution();
QCameraViewfinderSettings resolvedViewfinderSettings;
for (const QCameraViewfinderSettings &s : qAsConst(m_supportedViewfinderSettings)) {
- if ((m_viewfinderSettings.resolution().isEmpty() || m_viewfinderSettings.resolution() == s.resolution())
+ if ((resolution.isEmpty() || resolution == s.resolution())
&& (qFuzzyIsNull(m_viewfinderSettings.minimumFrameRate()) || qFuzzyCompare((float)m_viewfinderSettings.minimumFrameRate(), (float)s.minimumFrameRate()))
&& (qFuzzyIsNull(m_viewfinderSettings.maximumFrameRate()) || qFuzzyCompare((float)m_viewfinderSettings.maximumFrameRate(), (float)s.maximumFrameRate()))
&& (m_viewfinderSettings.pixelFormat() == QVideoFrame::Format_Invalid || m_viewfinderSettings.pixelFormat() == s.pixelFormat())
@@ -1171,4 +1177,23 @@ void DSCameraSession::updateSourceCapabilities()
updateImageProcessingParametersInfos();
}
+QList<QSize> DSCameraSession::supportedResolutions(bool *continuous) const
+{
+ if (continuous)
+ *continuous = false;
+
+ QList<QSize> res;
+ for (auto &settings : m_supportedViewfinderSettings) {
+ auto size = settings.resolution();
+ if (!res.contains(size))
+ res << size;
+ }
+
+ std::sort(res.begin(), res.end(), [](const QSize &r1, const QSize &r2) {
+ return qlonglong(r1.width()) * r1.height() < qlonglong(r2.width()) * r2.height();
+ });
+
+ return res;
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/directshow/camera/dscamerasession.h b/src/plugins/directshow/camera/dscamerasession.h
index ac861ae58..361a0220e 100644
--- a/src/plugins/directshow/camera/dscamerasession.h
+++ b/src/plugins/directshow/camera/dscamerasession.h
@@ -51,6 +51,7 @@
#include <QtMultimedia/qvideosurfaceformat.h>
#include <QtMultimedia/qcameraimageprocessingcontrol.h>
#include <QtMultimedia/qcameraimagecapture.h>
+#include <QtMultimedia/qmediaencodersettings.h>
#include <private/qmediastoragelocation_p.h>
#include <tchar.h>
@@ -129,6 +130,11 @@ public:
void addVideoProbe(DirectShowVideoProbeControl *probe);
void removeVideoProbe(DirectShowVideoProbeControl *probe);
+ QList<QSize> supportedResolutions(bool *continuous) const;
+ QImageEncoderSettings imageEncoderSettings() const { return m_imageEncoderSettings; }
+ void setImageEncoderSettings(const QImageEncoderSettings &settings)
+ { m_imageEncoderSettings = settings; }
+
Q_SIGNALS:
void statusChanged(QCamera::Status);
void imageExposed(int id);
@@ -217,6 +223,8 @@ private:
QMutex m_probeMutex;
DirectShowVideoProbeControl *m_videoProbeControl;
+ QImageEncoderSettings m_imageEncoderSettings;
+
// Internal state
QCamera::Status m_status;
QTimer m_deviceLostEventTimer;
diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp b/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp
index b268592c6..c83e467a6 100644
--- a/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp
+++ b/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp
@@ -107,8 +107,6 @@ QGstreamerCaptureSession::QGstreamerCaptureSession(QGstreamerCaptureSession::Cap
qWarning() << QMediaRecorder::Error(e) << ":" << str.toLatin1().constData();
});
m_mediaContainerControl = new QGstreamerMediaContainerControl(this);
-
- setState(StoppedState);
}
QGstreamerCaptureSession::~QGstreamerCaptureSession()
diff --git a/src/plugins/gstreamer/mediacapture/qgstreamerrecordercontrol.cpp b/src/plugins/gstreamer/mediacapture/qgstreamerrecordercontrol.cpp
index 958204803..ba26d8df8 100644
--- a/src/plugins/gstreamer/mediacapture/qgstreamerrecordercontrol.cpp
+++ b/src/plugins/gstreamer/mediacapture/qgstreamerrecordercontrol.cpp
@@ -115,6 +115,9 @@ void QGstreamerRecorderControl::updateStatus()
if (m_status != newStatus) {
m_status = newStatus;
emit statusChanged(m_status);
+ // If stop has been called and session state became stopped.
+ if (m_status == QMediaRecorder::LoadedStatus)
+ emit stateChanged(m_state);
}
}
@@ -204,7 +207,6 @@ void QGstreamerRecorderControl::stop()
m_session->setState(QGstreamerCaptureSession::PreviewState);
}
- emit stateChanged(m_state);
updateStatus();
}
diff --git a/src/plugins/qnx/mediaplayer/mmrenderervideowindowcontrol.cpp b/src/plugins/qnx/mediaplayer/mmrenderervideowindowcontrol.cpp
index 9930dd2e1..fbd698eea 100644
--- a/src/plugins/qnx/mediaplayer/mmrenderervideowindowcontrol.cpp
+++ b/src/plugins/qnx/mediaplayer/mmrenderervideowindowcontrol.cpp
@@ -205,18 +205,11 @@ void MmRendererVideoWindowControl::attachDisplay(mmr_context_t *context)
return;
}
- QWindow *windowForGroup = window;
-
- //According to mmr_output_attach() documentation, the window group name of the
- //application's top-level window is expected.
- while (windowForGroup->parent())
- windowForGroup = windowForGroup->parent();
-
const char * const groupNameData = static_cast<const char *>(
- nativeInterface->nativeResourceForWindow("windowGroup", windowForGroup));
+ nativeInterface->nativeResourceForWindow("windowGroup", window));
if (!groupNameData) {
qDebug() << "MmRendererVideoWindowControl: Unable to find window group for window"
- << windowForGroup;
+ << window;
return;
}
@@ -250,9 +243,7 @@ void MmRendererVideoWindowControl::updateVideoPosition()
{
QWindow * const window = findWindow(m_winId);
if (m_context && m_videoId != -1 && window) {
- QPoint topLeft = m_fullscreen ?
- QPoint(0,0) :
- window->mapToGlobal(m_displayRect.topLeft());
+ QPoint topLeft = m_displayRect.topLeft();
QScreen * const screen = window->screen();
int width = m_fullscreen ?
@@ -262,7 +253,8 @@ void MmRendererVideoWindowControl::updateVideoPosition()
screen->size().height() :
m_displayRect.height();
- if (m_metaData.hasVideo()) { // We need the source size to do aspect ratio scaling
+ if (m_metaData.hasVideo() && m_metaData.width() > 0 && m_metaData.height() > 0) {
+ // We need the source size to do aspect ratio scaling
const qreal sourceRatio = m_metaData.width() / static_cast<float>(m_metaData.height());
const qreal targetRatio = width / static_cast<float>(height);
diff --git a/src/plugins/videonode/imx6/qsgvivantevideomaterial.cpp b/src/plugins/videonode/imx6/qsgvivantevideomaterial.cpp
index 465ccfa7d..4b68f47a4 100644
--- a/src/plugins/videonode/imx6/qsgvivantevideomaterial.cpp
+++ b/src/plugins/videonode/imx6/qsgvivantevideomaterial.cpp
@@ -103,7 +103,7 @@ void QSGVivanteVideoMaterial::setCurrentFrame(const QVideoFrame &frame, QSGVideo
{
QMutexLocker lock(&mFrameMutex);
mNextFrame = frame;
- mMappable = !flags.testFlag(QSGVideoNode::FrameFiltered);
+ mMappable = mMapError == GL_NO_ERROR && !flags.testFlag(QSGVideoNode::FrameFiltered);
#ifdef QT_VIVANTE_VIDEO_DEBUG
qDebug() << Q_FUNC_INFO << " new frame: " << frame;
@@ -172,6 +172,7 @@ GLuint QSGVivanteVideoMaterial::vivanteMapping(QVideoFrame vF)
mWidth = vF.width();
mHeight = vF.height();
mFormat = vF.pixelFormat();
+ mMapError = GL_NO_ERROR;
clearTextures();
}
@@ -236,7 +237,12 @@ GLuint QSGVivanteVideoMaterial::vivanteMapping(QVideoFrame vF)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexDirectInvalidateVIV_LOCAL(GL_TEXTURE_2D);
- return tmpTexId;
+ mMapError = glGetError();
+ if (mMapError == GL_NO_ERROR)
+ return tmpTexId;
+
+ // Error occurred.
+ // Fallback to copying data.
} else {
// Fastest path: already seen this logical address. Just
// indicate that the data belonging to the texture has changed.
@@ -244,40 +250,40 @@ GLuint QSGVivanteVideoMaterial::vivanteMapping(QVideoFrame vF)
glTexDirectInvalidateVIV_LOCAL(GL_TEXTURE_2D);
return mBitsToTextureMap.value(vF.bits());
}
+ }
+
+ // Cannot map. So copy.
+ if (!mTexDirectTexture) {
+ glGenTextures(1, &mTexDirectTexture);
+ glBindTexture(GL_TEXTURE_2D, mTexDirectTexture);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexDirectVIV_LOCAL(GL_TEXTURE_2D, mCurrentFrame.width(), mCurrentFrame.height(),
+ QSGVivanteVideoNode::getVideoFormat2GLFormatMap().value(mCurrentFrame.pixelFormat()),
+ (GLvoid **) &mTexDirectPlanes);
} else {
- // Cannot map. So copy.
- if (!mTexDirectTexture) {
- glGenTextures(1, &mTexDirectTexture);
- glBindTexture(GL_TEXTURE_2D, mTexDirectTexture);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexDirectVIV_LOCAL(GL_TEXTURE_2D, mCurrentFrame.width(), mCurrentFrame.height(),
- QSGVivanteVideoNode::getVideoFormat2GLFormatMap().value(mCurrentFrame.pixelFormat()),
- (GLvoid **) &mTexDirectPlanes);
- } else {
- glBindTexture(GL_TEXTURE_2D, mTexDirectTexture);
- }
- switch (mCurrentFrame.pixelFormat()) {
- case QVideoFrame::Format_YUV420P:
- case QVideoFrame::Format_YV12:
- memcpy(mTexDirectPlanes[0], mCurrentFrame.bits(0), mCurrentFrame.height() * mCurrentFrame.bytesPerLine(0));
- memcpy(mTexDirectPlanes[1], mCurrentFrame.bits(1), mCurrentFrame.height() * mCurrentFrame.bytesPerLine(1));
- memcpy(mTexDirectPlanes[2], mCurrentFrame.bits(2), mCurrentFrame.height() * mCurrentFrame.bytesPerLine(2));
- break;
- case QVideoFrame::Format_NV12:
- case QVideoFrame::Format_NV21:
- memcpy(mTexDirectPlanes[0], mCurrentFrame.bits(0), mCurrentFrame.height() * mCurrentFrame.bytesPerLine(0));
- memcpy(mTexDirectPlanes[1], mCurrentFrame.bits(1), mCurrentFrame.height() / 2 * mCurrentFrame.bytesPerLine(1));
- break;
- default:
- memcpy(mTexDirectPlanes[0], mCurrentFrame.bits(), mCurrentFrame.height() * mCurrentFrame.bytesPerLine());
- break;
- }
- glTexDirectInvalidateVIV_LOCAL(GL_TEXTURE_2D);
- return mTexDirectTexture;
+ glBindTexture(GL_TEXTURE_2D, mTexDirectTexture);
+ }
+ switch (mCurrentFrame.pixelFormat()) {
+ case QVideoFrame::Format_YUV420P:
+ case QVideoFrame::Format_YV12:
+ memcpy(mTexDirectPlanes[0], mCurrentFrame.bits(0), mCurrentFrame.height() * mCurrentFrame.bytesPerLine(0));
+ memcpy(mTexDirectPlanes[1], mCurrentFrame.bits(1), mCurrentFrame.height() / 2 * mCurrentFrame.bytesPerLine(1));
+ memcpy(mTexDirectPlanes[2], mCurrentFrame.bits(2), mCurrentFrame.height() / 2 * mCurrentFrame.bytesPerLine(2));
+ break;
+ case QVideoFrame::Format_NV12:
+ case QVideoFrame::Format_NV21:
+ memcpy(mTexDirectPlanes[0], mCurrentFrame.bits(0), mCurrentFrame.height() * mCurrentFrame.bytesPerLine(0));
+ memcpy(mTexDirectPlanes[1], mCurrentFrame.bits(1), mCurrentFrame.height() / 2 * mCurrentFrame.bytesPerLine(1));
+ break;
+ default:
+ memcpy(mTexDirectPlanes[0], mCurrentFrame.bits(), mCurrentFrame.height() * mCurrentFrame.bytesPerLine());
+ break;
}
+ glTexDirectInvalidateVIV_LOCAL(GL_TEXTURE_2D);
+ return mTexDirectTexture;
}
else {
#ifdef QT_VIVANTE_VIDEO_DEBUG
diff --git a/src/plugins/videonode/imx6/qsgvivantevideomaterial.h b/src/plugins/videonode/imx6/qsgvivantevideomaterial.h
index 862747f27..adbd960a4 100644
--- a/src/plugins/videonode/imx6/qsgvivantevideomaterial.h
+++ b/src/plugins/videonode/imx6/qsgvivantevideomaterial.h
@@ -81,6 +81,7 @@ private:
QVideoFrame mCurrentFrame, mNextFrame;
GLuint mCurrentTexture;
bool mMappable;
+ GLenum mMapError = GL_NO_ERROR;
QMutex mFrameMutex;