summaryrefslogtreecommitdiffstats
path: root/src/plugins/gstreamer
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/gstreamer')
-rw-r--r--src/plugins/gstreamer/mediaplayer/mediaplayer.pro4
-rw-r--r--src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp2
-rw-r--r--src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp631
-rw-r--r--src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.h143
-rw-r--r--src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.cpp4
-rw-r--r--src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp1876
-rw-r--r--src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.h262
-rw-r--r--src/plugins/gstreamer/mediaplayer/qgstreamerstreamscontrol.cpp2
8 files changed, 4 insertions, 2920 deletions
diff --git a/src/plugins/gstreamer/mediaplayer/mediaplayer.pro b/src/plugins/gstreamer/mediaplayer/mediaplayer.pro
index 5ccf89bfd..8150d8f5b 100644
--- a/src/plugins/gstreamer/mediaplayer/mediaplayer.pro
+++ b/src/plugins/gstreamer/mediaplayer/mediaplayer.pro
@@ -5,18 +5,14 @@ include(../common.pri)
INCLUDEPATH += $$PWD
HEADERS += \
- $$PWD/qgstreamerplayercontrol.h \
$$PWD/qgstreamerplayerservice.h \
- $$PWD/qgstreamerplayersession.h \
$$PWD/qgstreamerstreamscontrol.h \
$$PWD/qgstreamermetadataprovider.h \
$$PWD/qgstreameravailabilitycontrol.h \
$$PWD/qgstreamerplayerserviceplugin.h
SOURCES += \
- $$PWD/qgstreamerplayercontrol.cpp \
$$PWD/qgstreamerplayerservice.cpp \
- $$PWD/qgstreamerplayersession.cpp \
$$PWD/qgstreamerstreamscontrol.cpp \
$$PWD/qgstreamermetadataprovider.cpp \
$$PWD/qgstreameravailabilitycontrol.cpp \
diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp
index b9e29245f..50ab0256b 100644
--- a/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp
+++ b/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp
@@ -38,7 +38,7 @@
****************************************************************************/
#include "qgstreamermetadataprovider.h"
-#include "qgstreamerplayersession.h"
+#include <private/qgstreamerplayersession_p.h>
#include <QDebug>
#include <QtMultimedia/qmediametadata.h>
diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp
deleted file mode 100644
index ff17e37eb..000000000
--- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp
+++ /dev/null
@@ -1,631 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 "qgstreamerplayercontrol.h"
-#include "qgstreamerplayersession.h"
-
-#include <private/qmediaplaylistnavigator_p.h>
-#include <private/qmediaresourcepolicy_p.h>
-#include <private/qmediaresourceset_p.h>
-
-#include <QtCore/qdir.h>
-#include <QtCore/qsocketnotifier.h>
-#include <QtCore/qurl.h>
-#include <QtCore/qdebug.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-//#define DEBUG_PLAYBIN
-
-QT_BEGIN_NAMESPACE
-
-QGstreamerPlayerControl::QGstreamerPlayerControl(QGstreamerPlayerSession *session, QObject *parent)
- : QMediaPlayerControl(parent)
- , m_session(session)
- , m_userRequestedState(QMediaPlayer::StoppedState)
- , m_currentState(QMediaPlayer::StoppedState)
- , m_mediaStatus(QMediaPlayer::NoMedia)
- , m_bufferProgress(-1)
- , m_pendingSeekPosition(-1)
- , m_setMediaPending(false)
- , m_stream(0)
-{
- m_resources = QMediaResourcePolicy::createResourceSet<QMediaPlayerResourceSetInterface>();
- Q_ASSERT(m_resources);
-
- connect(m_session, SIGNAL(positionChanged(qint64)),
- this, SIGNAL(positionChanged(qint64)));
- connect(m_session, SIGNAL(durationChanged(qint64)),
- this, SIGNAL(durationChanged(qint64)));
- connect(m_session, SIGNAL(mutedStateChanged(bool)),
- this, SIGNAL(mutedChanged(bool)));
- connect(m_session, SIGNAL(volumeChanged(int)),
- this, SIGNAL(volumeChanged(int)));
- connect(m_session, SIGNAL(stateChanged(QMediaPlayer::State)),
- this, SLOT(updateSessionState(QMediaPlayer::State)));
- connect(m_session,SIGNAL(bufferingProgressChanged(int)),
- this, SLOT(setBufferProgress(int)));
- connect(m_session, SIGNAL(playbackFinished()),
- this, SLOT(processEOS()));
- connect(m_session, SIGNAL(audioAvailableChanged(bool)),
- this, SIGNAL(audioAvailableChanged(bool)));
- connect(m_session, SIGNAL(videoAvailableChanged(bool)),
- this, SIGNAL(videoAvailableChanged(bool)));
- connect(m_session, SIGNAL(seekableChanged(bool)),
- this, SIGNAL(seekableChanged(bool)));
- connect(m_session, SIGNAL(error(int,QString)),
- this, SIGNAL(error(int,QString)));
- connect(m_session, SIGNAL(invalidMedia()),
- this, SLOT(handleInvalidMedia()));
- connect(m_session, SIGNAL(playbackRateChanged(qreal)),
- this, SIGNAL(playbackRateChanged(qreal)));
-
- connect(m_resources, SIGNAL(resourcesGranted()), SLOT(handleResourcesGranted()));
- //denied signal should be queued to have correct state update process,
- //since in playOrPause, when acquire is call on resource set, it may trigger a resourcesDenied signal immediately,
- //so handleResourcesDenied should be processed later, otherwise it will be overwritten by state update later in playOrPause.
- connect(m_resources, SIGNAL(resourcesDenied()), this, SLOT(handleResourcesDenied()), Qt::QueuedConnection);
- connect(m_resources, SIGNAL(resourcesLost()), SLOT(handleResourcesLost()));
-}
-
-QGstreamerPlayerControl::~QGstreamerPlayerControl()
-{
- QMediaResourcePolicy::destroyResourceSet(m_resources);
-}
-
-QMediaPlayerResourceSetInterface* QGstreamerPlayerControl::resources() const
-{
- return m_resources;
-}
-
-qint64 QGstreamerPlayerControl::position() const
-{
- if (m_mediaStatus == QMediaPlayer::EndOfMedia)
- return m_session->duration();
-
- return m_pendingSeekPosition != -1 ? m_pendingSeekPosition : m_session->position();
-}
-
-qint64 QGstreamerPlayerControl::duration() const
-{
- return m_session->duration();
-}
-
-QMediaPlayer::State QGstreamerPlayerControl::state() const
-{
- return m_currentState;
-}
-
-QMediaPlayer::MediaStatus QGstreamerPlayerControl::mediaStatus() const
-{
- return m_mediaStatus;
-}
-
-int QGstreamerPlayerControl::bufferStatus() const
-{
- if (m_bufferProgress == -1) {
- return m_session->state() == QMediaPlayer::StoppedState ? 0 : 100;
- } else
- return m_bufferProgress;
-}
-
-int QGstreamerPlayerControl::volume() const
-{
- return m_session->volume();
-}
-
-bool QGstreamerPlayerControl::isMuted() const
-{
- return m_session->isMuted();
-}
-
-bool QGstreamerPlayerControl::isSeekable() const
-{
- return m_session->isSeekable();
-}
-
-QMediaTimeRange QGstreamerPlayerControl::availablePlaybackRanges() const
-{
- return m_session->availablePlaybackRanges();
-}
-
-qreal QGstreamerPlayerControl::playbackRate() const
-{
- return m_session->playbackRate();
-}
-
-void QGstreamerPlayerControl::setPlaybackRate(qreal rate)
-{
- m_session->setPlaybackRate(rate);
-}
-
-void QGstreamerPlayerControl::setPosition(qint64 pos)
-{
-#ifdef DEBUG_PLAYBIN
- qDebug() << Q_FUNC_INFO << pos/1000.0;
-#endif
-
- pushState();
-
- if (m_mediaStatus == QMediaPlayer::EndOfMedia) {
- m_mediaStatus = QMediaPlayer::LoadedMedia;
- }
-
- if (m_currentState == QMediaPlayer::StoppedState) {
- m_pendingSeekPosition = pos;
- emit positionChanged(m_pendingSeekPosition);
- } else if (m_session->isSeekable()) {
- m_session->showPrerollFrames(true);
- m_session->seek(pos);
- m_pendingSeekPosition = -1;
- } else if (m_session->state() == QMediaPlayer::StoppedState) {
- m_pendingSeekPosition = pos;
- emit positionChanged(m_pendingSeekPosition);
- } else if (m_pendingSeekPosition != -1) {
- m_pendingSeekPosition = -1;
- emit positionChanged(m_pendingSeekPosition);
- }
-
- popAndNotifyState();
-}
-
-void QGstreamerPlayerControl::play()
-{
-#ifdef DEBUG_PLAYBIN
- qDebug() << Q_FUNC_INFO;
-#endif
- //m_userRequestedState is needed to know that we need to resume playback when resource-policy
- //regranted the resources after lost, since m_currentState will become paused when resources are
- //lost.
- m_userRequestedState = QMediaPlayer::PlayingState;
- playOrPause(QMediaPlayer::PlayingState);
-}
-
-void QGstreamerPlayerControl::pause()
-{
-#ifdef DEBUG_PLAYBIN
- qDebug() << Q_FUNC_INFO;
-#endif
- m_userRequestedState = QMediaPlayer::PausedState;
-
- playOrPause(QMediaPlayer::PausedState);
-}
-
-void QGstreamerPlayerControl::playOrPause(QMediaPlayer::State newState)
-{
- if (m_mediaStatus == QMediaPlayer::NoMedia)
- return;
-
- pushState();
-
- if (m_setMediaPending) {
- m_mediaStatus = QMediaPlayer::LoadingMedia;
- setMedia(m_currentResource, m_stream);
- }
-
- if (m_mediaStatus == QMediaPlayer::EndOfMedia && m_pendingSeekPosition == -1) {
- m_pendingSeekPosition = 0;
- }
-
- if (!m_resources->isGranted())
- m_resources->acquire();
-
- if (m_resources->isGranted()) {
- // show prerolled frame if switching from stopped state
- if (m_pendingSeekPosition == -1) {
- m_session->showPrerollFrames(true);
- } else if (m_session->state() == QMediaPlayer::StoppedState) {
- // Don't evaluate the next two conditions.
- } else if (m_session->isSeekable()) {
- m_session->pause();
- m_session->showPrerollFrames(true);
- m_session->seek(m_pendingSeekPosition);
- m_pendingSeekPosition = -1;
- } else {
- m_pendingSeekPosition = -1;
- }
-
- bool ok = false;
-
- //To prevent displaying the first video frame when playback is resumed
- //the pipeline is paused instead of playing, seeked to requested position,
- //and after seeking is finished (position updated) playback is restarted
- //with show-preroll-frame enabled.
- if (newState == QMediaPlayer::PlayingState && m_pendingSeekPosition == -1)
- ok = m_session->play();
- else
- ok = m_session->pause();
-
- if (!ok)
- newState = QMediaPlayer::StoppedState;
- }
-
- if (m_mediaStatus == QMediaPlayer::InvalidMedia)
- m_mediaStatus = QMediaPlayer::LoadingMedia;
-
- m_currentState = newState;
-
- if (m_mediaStatus == QMediaPlayer::EndOfMedia || m_mediaStatus == QMediaPlayer::LoadedMedia) {
- if (m_bufferProgress == -1 || m_bufferProgress == 100)
- m_mediaStatus = QMediaPlayer::BufferedMedia;
- else
- m_mediaStatus = QMediaPlayer::BufferingMedia;
- }
-
- popAndNotifyState();
-
- emit positionChanged(position());
-}
-
-void QGstreamerPlayerControl::stop()
-{
-#ifdef DEBUG_PLAYBIN
- qDebug() << Q_FUNC_INFO;
-#endif
- m_userRequestedState = QMediaPlayer::StoppedState;
-
- pushState();
-
- if (m_currentState != QMediaPlayer::StoppedState) {
- m_currentState = QMediaPlayer::StoppedState;
- m_session->showPrerollFrames(false); // stop showing prerolled frames in stop state
- // Since gst is not going to send GST_STATE_PAUSED
- // when pipeline is already paused,
- // needs to update media status directly.
- if (m_session->state() == QMediaPlayer::PausedState)
- updateMediaStatus();
- else if (m_resources->isGranted())
- m_session->pause();
-
- if (m_mediaStatus != QMediaPlayer::EndOfMedia) {
- m_pendingSeekPosition = 0;
- emit positionChanged(position());
- }
- }
-
- popAndNotifyState();
-}
-
-void QGstreamerPlayerControl::setVolume(int volume)
-{
- m_session->setVolume(volume);
-}
-
-void QGstreamerPlayerControl::setMuted(bool muted)
-{
- m_session->setMuted(muted);
-}
-
-QMediaContent QGstreamerPlayerControl::media() const
-{
- return m_currentResource;
-}
-
-const QIODevice *QGstreamerPlayerControl::mediaStream() const
-{
- return m_stream;
-}
-
-void QGstreamerPlayerControl::setMedia(const QMediaContent &content, QIODevice *stream)
-{
-#ifdef DEBUG_PLAYBIN
- qDebug() << Q_FUNC_INFO;
-#endif
-
- pushState();
-
- m_currentState = QMediaPlayer::StoppedState;
- QMediaContent oldMedia = m_currentResource;
- m_pendingSeekPosition = 0;
- m_session->showPrerollFrames(false); // do not show prerolled frames until pause() or play() explicitly called
- m_setMediaPending = false;
-
- if (!content.isNull() || stream) {
- if (!m_resources->isGranted())
- m_resources->acquire();
- } else {
- m_resources->release();
- }
-
- m_session->stop();
-
- bool userStreamValid = false;
-
- if (m_bufferProgress != -1) {
- m_bufferProgress = -1;
- emit bufferStatusChanged(0);
- }
-
- m_currentResource = content;
- m_stream = stream;
-
- QNetworkRequest request;
-
- if (m_stream) {
- userStreamValid = stream->isOpen() && m_stream->isReadable();
- request = content.canonicalRequest();
- } else if (!content.isNull()) {
- request = content.canonicalRequest();
- }
-
-#if !QT_CONFIG(gstreamer_app)
- m_session->loadFromUri(request);
-#else
- if (m_stream) {
- if (userStreamValid){
- m_session->loadFromStream(request, m_stream);
- } else {
- m_mediaStatus = QMediaPlayer::InvalidMedia;
- emit error(QMediaPlayer::FormatError, tr("Attempting to play invalid user stream"));
- if (m_currentState != QMediaPlayer::PlayingState)
- m_resources->release();
- popAndNotifyState();
- return;
- }
- } else
- m_session->loadFromUri(request);
-#endif
-
-#if QT_CONFIG(gstreamer_app)
- if (!request.url().isEmpty() || userStreamValid) {
-#else
- if (!request.url().isEmpty()) {
-#endif
- m_mediaStatus = QMediaPlayer::LoadingMedia;
- m_session->pause();
- } else {
- m_mediaStatus = QMediaPlayer::NoMedia;
- setBufferProgress(0);
- }
-
- if (m_currentResource != oldMedia)
- emit mediaChanged(m_currentResource);
-
- emit positionChanged(position());
-
- if (content.isNull() && !stream)
- m_resources->release();
-
- popAndNotifyState();
-}
-
-void QGstreamerPlayerControl::setVideoOutput(QObject *output)
-{
- m_session->setVideoRenderer(output);
-}
-
-bool QGstreamerPlayerControl::isAudioAvailable() const
-{
- return m_session->isAudioAvailable();
-}
-
-bool QGstreamerPlayerControl::isVideoAvailable() const
-{
- return m_session->isVideoAvailable();
-}
-
-void QGstreamerPlayerControl::updateSessionState(QMediaPlayer::State state)
-{
- pushState();
-
- if (state == QMediaPlayer::StoppedState) {
- m_session->showPrerollFrames(false);
- m_currentState = QMediaPlayer::StoppedState;
- }
-
- if (state == QMediaPlayer::PausedState && m_currentState != QMediaPlayer::StoppedState) {
- if (m_pendingSeekPosition != -1 && m_session->isSeekable()) {
- m_session->showPrerollFrames(true);
- m_session->seek(m_pendingSeekPosition);
- }
- m_pendingSeekPosition = -1;
-
- if (m_currentState == QMediaPlayer::PlayingState)
- m_session->play();
- }
-
- updateMediaStatus();
-
- popAndNotifyState();
-}
-
-void QGstreamerPlayerControl::updateMediaStatus()
-{
- pushState();
- QMediaPlayer::MediaStatus oldStatus = m_mediaStatus;
-
- switch (m_session->state()) {
- case QMediaPlayer::StoppedState:
- if (m_currentResource.isNull())
- m_mediaStatus = QMediaPlayer::NoMedia;
- else if (oldStatus != QMediaPlayer::InvalidMedia)
- m_mediaStatus = QMediaPlayer::LoadingMedia;
- break;
-
- case QMediaPlayer::PlayingState:
- case QMediaPlayer::PausedState:
- if (m_currentState == QMediaPlayer::StoppedState) {
- m_mediaStatus = QMediaPlayer::LoadedMedia;
- } else {
- if (m_bufferProgress == -1 || m_bufferProgress == 100)
- m_mediaStatus = QMediaPlayer::BufferedMedia;
- else
- m_mediaStatus = QMediaPlayer::StalledMedia;
- }
- break;
- }
-
- 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();
-}
-
-void QGstreamerPlayerControl::processEOS()
-{
- pushState();
- m_mediaStatus = QMediaPlayer::EndOfMedia;
- emit positionChanged(position());
- m_session->endOfMediaReset();
-
- if (m_currentState != QMediaPlayer::StoppedState) {
- m_currentState = QMediaPlayer::StoppedState;
- m_session->showPrerollFrames(false); // stop showing prerolled frames in stop state
- }
-
- popAndNotifyState();
-}
-
-void QGstreamerPlayerControl::setBufferProgress(int progress)
-{
- if (m_bufferProgress == progress || m_mediaStatus == QMediaPlayer::NoMedia)
- return;
-
-#ifdef DEBUG_PLAYBIN
- qDebug() << Q_FUNC_INFO << progress;
-#endif
- m_bufferProgress = progress;
-
- if (m_resources->isGranted()) {
- if (m_currentState == QMediaPlayer::PlayingState &&
- m_bufferProgress == 100 &&
- m_session->state() != QMediaPlayer::PlayingState)
- m_session->play();
-
- if (!m_session->isLiveSource() && m_bufferProgress < 100 &&
- (m_session->state() == QMediaPlayer::PlayingState ||
- m_session->pendingState() == QMediaPlayer::PlayingState))
- m_session->pause();
- }
-
- updateMediaStatus();
-
- emit bufferStatusChanged(m_bufferProgress);
-}
-
-void QGstreamerPlayerControl::handleInvalidMedia()
-{
- pushState();
- m_mediaStatus = QMediaPlayer::InvalidMedia;
- m_currentState = QMediaPlayer::StoppedState;
- m_setMediaPending = true;
- popAndNotifyState();
-}
-
-void QGstreamerPlayerControl::handleResourcesGranted()
-{
- pushState();
-
- //This may be triggered when there is an auto resume
- //from resource-policy, we need to take action according to m_userRequestedState
- //rather than m_currentState
- m_currentState = m_userRequestedState;
- if (m_currentState != QMediaPlayer::StoppedState)
- playOrPause(m_currentState);
- else
- updateMediaStatus();
-
- popAndNotifyState();
-}
-
-void QGstreamerPlayerControl::handleResourcesLost()
-{
- //on resource lost the pipeline should be paused
- //player status is changed to paused
- pushState();
- QMediaPlayer::State oldState = m_currentState;
-
- m_session->pause();
-
- if (oldState != QMediaPlayer::StoppedState )
- m_currentState = QMediaPlayer::PausedState;
-
- popAndNotifyState();
-}
-
-void QGstreamerPlayerControl::handleResourcesDenied()
-{
- //on resource denied the pipeline should stay paused
- //player status is changed to paused
- pushState();
-
- if (m_currentState != QMediaPlayer::StoppedState )
- m_currentState = QMediaPlayer::PausedState;
-
- popAndNotifyState();
-}
-
-void QGstreamerPlayerControl::pushState()
-{
- m_stateStack.push(m_currentState);
- m_mediaStatusStack.push(m_mediaStatus);
-}
-
-void QGstreamerPlayerControl::popAndNotifyState()
-{
- Q_ASSERT(!m_stateStack.isEmpty());
-
- QMediaPlayer::State oldState = m_stateStack.pop();
- QMediaPlayer::MediaStatus oldMediaStatus = m_mediaStatusStack.pop();
-
- if (m_stateStack.isEmpty()) {
- if (m_mediaStatus != oldMediaStatus) {
-#ifdef DEBUG_PLAYBIN
- qDebug() << "Media status changed:" << m_mediaStatus;
-#endif
- emit mediaStatusChanged(m_mediaStatus);
- }
-
- if (m_currentState != oldState) {
-#ifdef DEBUG_PLAYBIN
- qDebug() << "State changed:" << m_currentState;
-#endif
- emit stateChanged(m_currentState);
- }
- }
-}
-
-QT_END_NAMESPACE
diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.h b/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.h
deleted file mode 100644
index 6067a68fc..000000000
--- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.h
+++ /dev/null
@@ -1,143 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 QGSTREAMERPLAYERCONTROL_H
-#define QGSTREAMERPLAYERCONTROL_H
-
-#include <QtCore/qobject.h>
-#include <QtCore/qstack.h>
-
-#include <qmediaplayercontrol.h>
-#include <qmediaplayer.h>
-
-#include <limits.h>
-
-QT_BEGIN_NAMESPACE
-
-class QMediaPlayerResourceSetInterface;
-
-class QMediaPlaylist;
-class QMediaPlaylistNavigator;
-class QSocketNotifier;
-
-class QGstreamerPlayerSession;
-class QGstreamerPlayerService;
-
-class QGstreamerPlayerControl : public QMediaPlayerControl
-{
- Q_OBJECT
-
-public:
- QGstreamerPlayerControl(QGstreamerPlayerSession *session, QObject *parent = 0);
- ~QGstreamerPlayerControl();
-
- QMediaPlayer::State state() const override;
- QMediaPlayer::MediaStatus mediaStatus() const override;
-
- qint64 position() const override;
- qint64 duration() const override;
-
- int bufferStatus() const override;
-
- int volume() const override;
- bool isMuted() const override;
-
- bool isAudioAvailable() const override;
- bool isVideoAvailable() const override;
- void setVideoOutput(QObject *output);
-
- bool isSeekable() const override;
- QMediaTimeRange availablePlaybackRanges() const override;
-
- qreal playbackRate() const override;
- void setPlaybackRate(qreal rate) override;
-
- QMediaContent media() const override;
- const QIODevice *mediaStream() const override;
- void setMedia(const QMediaContent&, QIODevice *) override;
-
- QMediaPlayerResourceSetInterface* resources() const;
-
-public Q_SLOTS:
- void setPosition(qint64 pos) override;
-
- void play() override;
- void pause() override;
- void stop() override;
-
- void setVolume(int volume) override;
- void setMuted(bool muted) override;
-
-private Q_SLOTS:
- void updateSessionState(QMediaPlayer::State state);
- void updateMediaStatus();
- void processEOS();
- void setBufferProgress(int progress);
-
- void handleInvalidMedia();
-
- void handleResourcesGranted();
- void handleResourcesLost();
- void handleResourcesDenied();
-
-private:
- void playOrPause(QMediaPlayer::State state);
-
- void pushState();
- void popAndNotifyState();
-
- QGstreamerPlayerSession *m_session;
- QMediaPlayer::State m_userRequestedState;
- QMediaPlayer::State m_currentState;
- QMediaPlayer::MediaStatus m_mediaStatus;
- QStack<QMediaPlayer::State> m_stateStack;
- QStack<QMediaPlayer::MediaStatus> m_mediaStatusStack;
-
- int m_bufferProgress;
- qint64 m_pendingSeekPosition;
- bool m_setMediaPending;
- QMediaContent m_currentResource;
- QIODevice *m_stream;
-
- QMediaPlayerResourceSetInterface *m_resources;
-};
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.cpp
index 2c2de1bbc..0712f6e6c 100644
--- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.cpp
+++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.cpp
@@ -46,8 +46,6 @@
#endif
#include "qgstreamerplayerservice.h"
-#include "qgstreamerplayercontrol.h"
-#include "qgstreamerplayersession.h"
#include "qgstreamermetadataprovider.h"
#include "qgstreameravailabilitycontrol.h"
@@ -64,6 +62,8 @@
#include "qgstreamerstreamscontrol.h"
#include <private/qgstreameraudioprobecontrol_p.h>
#include <private/qgstreamervideoprobecontrol_p.h>
+#include <private/qgstreamerplayersession_p.h>
+#include <private/qgstreamerplayercontrol_p.h>
#include <private/qmediaplaylistnavigator_p.h>
#include <qmediaplaylist.h>
diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp
deleted file mode 100644
index d7cc5ed12..000000000
--- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp
+++ /dev/null
@@ -1,1876 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 "qgstreamerplayersession.h"
-#include <private/qgstreamerbushelper_p.h>
-
-#include <private/qgstreameraudioprobecontrol_p.h>
-#include <private/qgstreamervideoprobecontrol_p.h>
-#include <private/qgstreamervideorendererinterface_p.h>
-#if !GST_CHECK_VERSION(1,0,0)
-#include <private/gstvideoconnector_p.h>
-#endif
-#include <private/qgstutils_p.h>
-#include <private/qgstutils_p.h>
-
-#include <gst/gstvalue.h>
-#include <gst/base/gstbasesrc.h>
-
-#include <QtMultimedia/qmediametadata.h>
-#include <QtCore/qdatetime.h>
-#include <QtCore/qdebug.h>
-#include <QtCore/qsize.h>
-#include <QtCore/qtimer.h>
-#include <QtCore/qdebug.h>
-#include <QtCore/qdir.h>
-#include <QtCore/qstandardpaths.h>
-
-//#define DEBUG_PLAYBIN
-//#define DEBUG_VO_BIN_DUMP
-
-QT_BEGIN_NAMESPACE
-
-static bool usePlaybinVolume()
-{
- static enum { Yes, No, Unknown } status = Unknown;
- if (status == Unknown) {
- QByteArray v = qgetenv("QT_GSTREAMER_USE_PLAYBIN_VOLUME");
- bool value = !v.isEmpty() && v != "0" && v != "false";
- if (value)
- status = Yes;
- else
- status = No;
- }
- return status == Yes;
-}
-
-typedef enum {
- GST_PLAY_FLAG_VIDEO = 0x00000001,
- GST_PLAY_FLAG_AUDIO = 0x00000002,
- GST_PLAY_FLAG_TEXT = 0x00000004,
- GST_PLAY_FLAG_VIS = 0x00000008,
- GST_PLAY_FLAG_SOFT_VOLUME = 0x00000010,
- GST_PLAY_FLAG_NATIVE_AUDIO = 0x00000020,
- GST_PLAY_FLAG_NATIVE_VIDEO = 0x00000040,
- GST_PLAY_FLAG_DOWNLOAD = 0x00000080,
- GST_PLAY_FLAG_BUFFERING = 0x000000100
-} GstPlayFlags;
-
-#if !GST_CHECK_VERSION(1,0,0)
-#define DEFAULT_RAW_CAPS \
- "video/x-raw-yuv; " \
- "video/x-raw-rgb; " \
- "video/x-raw-gray; " \
- "video/x-surface; " \
- "video/x-android-buffer; " \
- "audio/x-raw-int; " \
- "audio/x-raw-float; " \
- "text/plain; " \
- "text/x-pango-markup; " \
- "video/x-dvd-subpicture; " \
- "subpicture/x-pgs"
-
-static GstStaticCaps static_RawCaps = GST_STATIC_CAPS(DEFAULT_RAW_CAPS);
-#endif
-
-QGstreamerPlayerSession::QGstreamerPlayerSession(QObject *parent)
- :QObject(parent),
- m_state(QMediaPlayer::StoppedState),
- m_pendingState(QMediaPlayer::StoppedState),
- m_busHelper(0),
- m_playbin(0),
- m_videoSink(0),
-#if !GST_CHECK_VERSION(1,0,0)
- m_usingColorspaceElement(false),
-#endif
- m_pendingVideoSink(0),
- m_nullVideoSink(0),
- m_audioSink(0),
- m_volumeElement(0),
- m_bus(0),
- m_videoOutput(0),
- m_renderer(0),
-#if QT_CONFIG(gstreamer_app)
- m_appSrc(0),
-#endif
- m_videoProbe(0),
- m_audioProbe(0),
- m_volume(100),
- m_playbackRate(1.0),
- m_muted(false),
- m_audioAvailable(false),
- m_videoAvailable(false),
- m_seekable(false),
- m_lastPosition(0),
- m_duration(0),
- m_durationQueries(0),
- m_displayPrerolledFrame(true),
- m_sourceType(UnknownSrc),
- m_everPlayed(false),
- m_isLiveSource(false)
-{
- m_playbin = gst_element_factory_make(QT_GSTREAMER_PLAYBIN_ELEMENT_NAME, NULL);
- if (m_playbin) {
- //GST_PLAY_FLAG_NATIVE_VIDEO omits configuration of ffmpegcolorspace and videoscale,
- //since those elements are included in the video output bin when necessary.
- int flags = GST_PLAY_FLAG_VIDEO | GST_PLAY_FLAG_AUDIO;
- QByteArray envFlags = qgetenv("QT_GSTREAMER_PLAYBIN_FLAGS");
- if (!envFlags.isEmpty()) {
- flags |= envFlags.toInt();
-#if !GST_CHECK_VERSION(1,0,0)
- } else {
- flags |= GST_PLAY_FLAG_NATIVE_VIDEO;
-#endif
- }
- g_object_set(G_OBJECT(m_playbin), "flags", flags, NULL);
-
- const QByteArray envAudioSink = qgetenv("QT_GSTREAMER_PLAYBIN_AUDIOSINK");
- GstElement *audioSink = gst_element_factory_make(envAudioSink.isEmpty() ? "autoaudiosink" : envAudioSink, "audiosink");
- if (audioSink) {
- if (usePlaybinVolume()) {
- m_audioSink = audioSink;
- m_volumeElement = m_playbin;
- } else {
- m_volumeElement = gst_element_factory_make("volume", "volumeelement");
- if (m_volumeElement) {
- m_audioSink = gst_bin_new("audio-output-bin");
-
- gst_bin_add_many(GST_BIN(m_audioSink), m_volumeElement, audioSink, NULL);
- gst_element_link(m_volumeElement, audioSink);
-
- GstPad *pad = gst_element_get_static_pad(m_volumeElement, "sink");
- gst_element_add_pad(GST_ELEMENT(m_audioSink), gst_ghost_pad_new("sink", pad));
- gst_object_unref(GST_OBJECT(pad));
- } else {
- m_audioSink = audioSink;
- m_volumeElement = m_playbin;
- }
- }
-
- g_object_set(G_OBJECT(m_playbin), "audio-sink", m_audioSink, NULL);
- addAudioBufferProbe();
- }
- }
-
-#if GST_CHECK_VERSION(1,0,0)
- m_videoIdentity = gst_element_factory_make("identity", NULL); // floating ref
-#else
- m_videoIdentity = GST_ELEMENT(g_object_new(gst_video_connector_get_type(), 0)); // floating ref
- g_signal_connect(G_OBJECT(m_videoIdentity), "connection-failed", G_CALLBACK(insertColorSpaceElement), (gpointer)this);
- m_colorSpace = gst_element_factory_make(QT_GSTREAMER_COLORCONVERSION_ELEMENT_NAME, "ffmpegcolorspace-vo");
-
- // might not get a parent, take ownership to avoid leak
- qt_gst_object_ref_sink(GST_OBJECT(m_colorSpace));
-#endif
-
- m_nullVideoSink = gst_element_factory_make("fakesink", NULL);
- g_object_set(G_OBJECT(m_nullVideoSink), "sync", true, NULL);
- gst_object_ref(GST_OBJECT(m_nullVideoSink));
-
- m_videoOutputBin = gst_bin_new("video-output-bin");
- // might not get a parent, take ownership to avoid leak
- qt_gst_object_ref_sink(GST_OBJECT(m_videoOutputBin));
- gst_bin_add_many(GST_BIN(m_videoOutputBin), m_videoIdentity, m_nullVideoSink, NULL);
- gst_element_link(m_videoIdentity, m_nullVideoSink);
-
- m_videoSink = m_nullVideoSink;
-
- // add ghostpads
- GstPad *pad = gst_element_get_static_pad(m_videoIdentity,"sink");
- gst_element_add_pad(GST_ELEMENT(m_videoOutputBin), gst_ghost_pad_new("sink", pad));
- gst_object_unref(GST_OBJECT(pad));
-
- if (m_playbin != 0) {
- // Sort out messages
- m_bus = gst_element_get_bus(m_playbin);
- m_busHelper = new QGstreamerBusHelper(m_bus, this);
- m_busHelper->installMessageFilter(this);
-
- g_object_set(G_OBJECT(m_playbin), "video-sink", m_videoOutputBin, NULL);
-
- g_signal_connect(G_OBJECT(m_playbin), "notify::source", G_CALLBACK(playbinNotifySource), this);
- g_signal_connect(G_OBJECT(m_playbin), "element-added", G_CALLBACK(handleElementAdded), this);
-
- if (usePlaybinVolume()) {
- updateVolume();
- updateMuted();
- g_signal_connect(G_OBJECT(m_playbin), "notify::volume", G_CALLBACK(handleVolumeChange), this);
- g_signal_connect(G_OBJECT(m_playbin), "notify::mute", G_CALLBACK(handleMutedChange), this);
- }
-
- g_signal_connect(G_OBJECT(m_playbin), "video-changed", G_CALLBACK(handleStreamsChange), this);
- g_signal_connect(G_OBJECT(m_playbin), "audio-changed", G_CALLBACK(handleStreamsChange), this);
- g_signal_connect(G_OBJECT(m_playbin), "text-changed", G_CALLBACK(handleStreamsChange), this);
-
-#if QT_CONFIG(gstreamer_app)
- g_signal_connect(G_OBJECT(m_playbin), "deep-notify::source", G_CALLBACK(configureAppSrcElement), this);
-#endif
- }
-}
-
-QGstreamerPlayerSession::~QGstreamerPlayerSession()
-{
- if (m_playbin) {
- stop();
-
- removeVideoBufferProbe();
- removeAudioBufferProbe();
-
- delete m_busHelper;
- gst_object_unref(GST_OBJECT(m_bus));
- gst_object_unref(GST_OBJECT(m_playbin));
-#if !GST_CHECK_VERSION(1,0,0)
- gst_object_unref(GST_OBJECT(m_colorSpace));
-#endif
- gst_object_unref(GST_OBJECT(m_nullVideoSink));
- gst_object_unref(GST_OBJECT(m_videoOutputBin));
- }
-}
-
-GstElement *QGstreamerPlayerSession::playbin() const
-{
- return m_playbin;
-}
-
-#if QT_CONFIG(gstreamer_app)
-void QGstreamerPlayerSession::configureAppSrcElement(GObject* object, GObject *orig, GParamSpec *pspec, QGstreamerPlayerSession* self)
-{
- Q_UNUSED(object);
- Q_UNUSED(pspec);
-
- if (!self->appsrc())
- return;
-
- GstElement *appsrc;
- g_object_get(orig, "source", &appsrc, NULL);
-
- if (!self->appsrc()->setup(appsrc))
- qWarning()<<"Could not setup appsrc element";
-
- g_object_unref(G_OBJECT(appsrc));
-}
-#endif
-
-void QGstreamerPlayerSession::loadFromStream(const QNetworkRequest &request, QIODevice *appSrcStream)
-{
-#if QT_CONFIG(gstreamer_app)
-#ifdef DEBUG_PLAYBIN
- qDebug() << Q_FUNC_INFO;
-#endif
- m_request = request;
- m_duration = 0;
- m_lastPosition = 0;
-
- if (!m_appSrc)
- m_appSrc = new QGstAppSrc(this);
- m_appSrc->setStream(appSrcStream);
-
- if (m_playbin) {
- m_tags.clear();
- emit tagsChanged();
-
- g_object_set(G_OBJECT(m_playbin), "uri", "appsrc://", NULL);
-
- if (!m_streamTypes.isEmpty()) {
- m_streamProperties.clear();
- m_streamTypes.clear();
-
- emit streamsChanged();
- }
- }
-#endif
-}
-
-void QGstreamerPlayerSession::loadFromUri(const QNetworkRequest &request)
-{
-#ifdef DEBUG_PLAYBIN
- qDebug() << Q_FUNC_INFO << request.url();
-#endif
- m_request = request;
- m_duration = 0;
- m_lastPosition = 0;
-
-#if QT_CONFIG(gstreamer_app)
- if (m_appSrc) {
- m_appSrc->deleteLater();
- m_appSrc = 0;
- }
-#endif
-
- if (m_playbin) {
- m_tags.clear();
- emit tagsChanged();
-
- g_object_set(G_OBJECT(m_playbin), "uri", m_request.url().toEncoded().constData(), NULL);
-
- if (!m_streamTypes.isEmpty()) {
- m_streamProperties.clear();
- m_streamTypes.clear();
-
- emit streamsChanged();
- }
- }
-}
-
-qint64 QGstreamerPlayerSession::duration() const
-{
- return m_duration;
-}
-
-qint64 QGstreamerPlayerSession::position() const
-{
- gint64 position = 0;
-
- if (m_playbin && qt_gst_element_query_position(m_playbin, GST_FORMAT_TIME, &position))
- m_lastPosition = position / 1000000;
- return m_lastPosition;
-}
-
-qreal QGstreamerPlayerSession::playbackRate() const
-{
- return m_playbackRate;
-}
-
-void QGstreamerPlayerSession::setPlaybackRate(qreal rate)
-{
-#ifdef DEBUG_PLAYBIN
- qDebug() << Q_FUNC_INFO << rate;
-#endif
- if (!qFuzzyCompare(m_playbackRate, rate)) {
- m_playbackRate = rate;
- if (m_playbin && m_seekable) {
- gst_element_seek(m_playbin, rate, GST_FORMAT_TIME,
- GstSeekFlags(GST_SEEK_FLAG_FLUSH),
- GST_SEEK_TYPE_NONE,0,
- GST_SEEK_TYPE_NONE,0 );
- }
- emit playbackRateChanged(m_playbackRate);
- }
-}
-
-QMediaTimeRange QGstreamerPlayerSession::availablePlaybackRanges() const
-{
- QMediaTimeRange ranges;
-
- if (duration() <= 0)
- return ranges;
-
-#if GST_CHECK_VERSION(0, 10, 31)
- //GST_FORMAT_TIME would be more appropriate, but unfortunately it's not supported.
- //with GST_FORMAT_PERCENT media is treated as encoded with constant bitrate.
- GstQuery* query = gst_query_new_buffering(GST_FORMAT_PERCENT);
-
- if (!gst_element_query(m_playbin, query)) {
- gst_query_unref(query);
- return ranges;
- }
-
- gint64 rangeStart = 0;
- gint64 rangeStop = 0;
- for (guint index = 0; index < gst_query_get_n_buffering_ranges(query); index++) {
- if (gst_query_parse_nth_buffering_range(query, index, &rangeStart, &rangeStop))
- ranges.addInterval(rangeStart * duration() / 100,
- rangeStop * duration() / 100);
- }
-
- gst_query_unref(query);
-#endif
-
- if (ranges.isEmpty() && !isLiveSource() && isSeekable())
- ranges.addInterval(0, duration());
-
-#ifdef DEBUG_PLAYBIN
- qDebug() << ranges;
-#endif
-
- return ranges;
-}
-
-int QGstreamerPlayerSession::activeStream(QMediaStreamsControl::StreamType streamType) const
-{
- int streamNumber = -1;
- if (m_playbin) {
- switch (streamType) {
- case QMediaStreamsControl::AudioStream:
- g_object_get(G_OBJECT(m_playbin), "current-audio", &streamNumber, NULL);
- break;
- case QMediaStreamsControl::VideoStream:
- g_object_get(G_OBJECT(m_playbin), "current-video", &streamNumber, NULL);
- break;
- case QMediaStreamsControl::SubPictureStream:
- g_object_get(G_OBJECT(m_playbin), "current-text", &streamNumber, NULL);
- break;
- default:
- break;
- }
- }
-
- if (streamNumber >= 0)
- streamNumber += m_playbin2StreamOffset.value(streamType,0);
-
- return streamNumber;
-}
-
-void QGstreamerPlayerSession::setActiveStream(QMediaStreamsControl::StreamType streamType, int streamNumber)
-{
-#ifdef DEBUG_PLAYBIN
- qDebug() << Q_FUNC_INFO << streamType << streamNumber;
-#endif
-
- if (streamNumber >= 0)
- streamNumber -= m_playbin2StreamOffset.value(streamType,0);
-
- if (m_playbin) {
- switch (streamType) {
- case QMediaStreamsControl::AudioStream:
- g_object_set(G_OBJECT(m_playbin), "current-audio", streamNumber, NULL);
- break;
- case QMediaStreamsControl::VideoStream:
- g_object_set(G_OBJECT(m_playbin), "current-video", streamNumber, NULL);
- break;
- case QMediaStreamsControl::SubPictureStream:
- g_object_set(G_OBJECT(m_playbin), "current-text", streamNumber, NULL);
- break;
- default:
- break;
- }
- }
-}
-
-int QGstreamerPlayerSession::volume() const
-{
- return m_volume;
-}
-
-bool QGstreamerPlayerSession::isMuted() const
-{
- return m_muted;
-}
-
-bool QGstreamerPlayerSession::isAudioAvailable() const
-{
- return m_audioAvailable;
-}
-
-#if GST_CHECK_VERSION(1,0,0)
-static GstPadProbeReturn block_pad_cb(GstPad *pad, GstPadProbeInfo *info, gpointer user_data)
-#else
-static void block_pad_cb(GstPad *pad, gboolean blocked, gpointer user_data)
-#endif
-{
- Q_UNUSED(pad);
-#if GST_CHECK_VERSION(1,0,0)
- Q_UNUSED(info);
- Q_UNUSED(user_data);
- return GST_PAD_PROBE_OK;
-#else
-#ifdef DEBUG_PLAYBIN
- qDebug() << "block_pad_cb, blocked:" << blocked;
-#endif
- if (blocked && user_data) {
- QGstreamerPlayerSession *session = reinterpret_cast<QGstreamerPlayerSession*>(user_data);
- QMetaObject::invokeMethod(session, "finishVideoOutputChange", Qt::QueuedConnection);
- }
-#endif
-}
-
-void QGstreamerPlayerSession::updateVideoRenderer()
-{
-#ifdef DEBUG_PLAYBIN
- qDebug() << "Video sink has chaged, reload video output";
-#endif
-
- if (m_videoOutput)
- setVideoRenderer(m_videoOutput);
-}
-
-void QGstreamerPlayerSession::setVideoRenderer(QObject *videoOutput)
-{
-#ifdef DEBUG_PLAYBIN
- qDebug() << Q_FUNC_INFO;
-#endif
- if (m_videoOutput != videoOutput) {
- if (m_videoOutput) {
- disconnect(m_videoOutput, SIGNAL(sinkChanged()),
- this, SLOT(updateVideoRenderer()));
- disconnect(m_videoOutput, SIGNAL(readyChanged(bool)),
- this, SLOT(updateVideoRenderer()));
-
- m_busHelper->removeMessageFilter(m_videoOutput);
- }
-
- m_videoOutput = videoOutput;
-
- if (m_videoOutput) {
- connect(m_videoOutput, SIGNAL(sinkChanged()),
- this, SLOT(updateVideoRenderer()));
- connect(m_videoOutput, SIGNAL(readyChanged(bool)),
- this, SLOT(updateVideoRenderer()));
-
- m_busHelper->installMessageFilter(m_videoOutput);
- }
- }
-
- QGstreamerVideoRendererInterface* renderer = qobject_cast<QGstreamerVideoRendererInterface*>(videoOutput);
-
- m_renderer = renderer;
-
-#ifdef DEBUG_VO_BIN_DUMP
- gst_debug_bin_to_dot_file_with_ts(GST_BIN(m_playbin),
- GstDebugGraphDetails(GST_DEBUG_GRAPH_SHOW_ALL /* GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE | GST_DEBUG_GRAPH_SHOW_NON_DEFAULT_PARAMS | GST_DEBUG_GRAPH_SHOW_STATES*/),
- "playbin_set");
-#endif
-
- GstElement *videoSink = 0;
- if (m_renderer && m_renderer->isReady())
- videoSink = m_renderer->videoSink();
-
- if (!videoSink)
- videoSink = m_nullVideoSink;
-
-#ifdef DEBUG_PLAYBIN
- qDebug() << "Set video output:" << videoOutput;
- qDebug() << "Current sink:" << (m_videoSink ? GST_ELEMENT_NAME(m_videoSink) : "") << m_videoSink
- << "pending:" << (m_pendingVideoSink ? GST_ELEMENT_NAME(m_pendingVideoSink) : "") << m_pendingVideoSink
- << "new sink:" << (videoSink ? GST_ELEMENT_NAME(videoSink) : "") << videoSink;
-#endif
-
- if (m_pendingVideoSink == videoSink ||
- (m_pendingVideoSink == 0 && m_videoSink == videoSink)) {
-#ifdef DEBUG_PLAYBIN
- qDebug() << "Video sink has not changed, skip video output reconfiguration";
-#endif
- return;
- }
-
-#ifdef DEBUG_PLAYBIN
- qDebug() << "Reconfigure video output";
-#endif
-
- if (m_state == QMediaPlayer::StoppedState) {
-#ifdef DEBUG_PLAYBIN
- qDebug() << "The pipeline has not started yet, pending state:" << m_pendingState;
-#endif
- //the pipeline has not started yet
- flushVideoProbes();
- m_pendingVideoSink = 0;
- gst_element_set_state(m_videoSink, GST_STATE_NULL);
- gst_element_set_state(m_playbin, GST_STATE_NULL);
-
-#if !GST_CHECK_VERSION(1,0,0)
- if (m_usingColorspaceElement) {
- gst_element_unlink(m_colorSpace, m_videoSink);
- gst_bin_remove(GST_BIN(m_videoOutputBin), m_colorSpace);
- } else {
- gst_element_unlink(m_videoIdentity, m_videoSink);
- }
-#endif
-
- removeVideoBufferProbe();
-
- gst_bin_remove(GST_BIN(m_videoOutputBin), m_videoSink);
-
- m_videoSink = videoSink;
-
- gst_bin_add(GST_BIN(m_videoOutputBin), m_videoSink);
-
- bool linked = gst_element_link(m_videoIdentity, m_videoSink);
-#if !GST_CHECK_VERSION(1,0,0)
- m_usingColorspaceElement = false;
- if (!linked) {
- m_usingColorspaceElement = true;
-#ifdef DEBUG_PLAYBIN
- qDebug() << "Failed to connect video output, inserting the colorspace element.";
-#endif
- gst_bin_add(GST_BIN(m_videoOutputBin), m_colorSpace);
- linked = gst_element_link_many(m_videoIdentity, m_colorSpace, m_videoSink, NULL);
- }
-#endif
-
- if (!linked)
- qWarning() << "Linking video output element failed";
-
- if (g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "show-preroll-frame") != 0) {
- gboolean value = m_displayPrerolledFrame;
- g_object_set(G_OBJECT(m_videoSink), "show-preroll-frame", value, NULL);
- }
-
- addVideoBufferProbe();
-
- switch (m_pendingState) {
- case QMediaPlayer::PausedState:
- gst_element_set_state(m_playbin, GST_STATE_PAUSED);
- break;
- case QMediaPlayer::PlayingState:
- gst_element_set_state(m_playbin, GST_STATE_PLAYING);
- break;
- default:
- break;
- }
-
- resumeVideoProbes();
-
- } else {
- if (m_pendingVideoSink) {
-#ifdef DEBUG_PLAYBIN
- qDebug() << "already waiting for pad to be blocked, just change the pending sink";
-#endif
- m_pendingVideoSink = videoSink;
- return;
- }
-
- m_pendingVideoSink = videoSink;
-
-#ifdef DEBUG_PLAYBIN
- qDebug() << "Blocking the video output pad...";
-#endif
-
- //block pads, async to avoid locking in paused state
- GstPad *srcPad = gst_element_get_static_pad(m_videoIdentity, "src");
-#if GST_CHECK_VERSION(1,0,0)
- this->pad_probe_id = gst_pad_add_probe(srcPad, (GstPadProbeType)(GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_BLOCKING), block_pad_cb, this, NULL);
-#else
- gst_pad_set_blocked_async(srcPad, true, &block_pad_cb, this);
-#endif
- gst_object_unref(GST_OBJECT(srcPad));
-
- //Unpause the sink to avoid waiting until the buffer is processed
- //while the sink is paused. The pad will be blocked as soon as the current
- //buffer is processed.
- if (m_state == QMediaPlayer::PausedState) {
-#ifdef DEBUG_PLAYBIN
- qDebug() << "Starting video output to avoid blocking in paused state...";
-#endif
- gst_element_set_state(m_videoSink, GST_STATE_PLAYING);
- }
- }
-}
-
-void QGstreamerPlayerSession::finishVideoOutputChange()
-{
- if (!m_pendingVideoSink)
- return;
-
-#ifdef DEBUG_PLAYBIN
- qDebug() << "finishVideoOutputChange" << m_pendingVideoSink;
-#endif
-
- GstPad *srcPad = gst_element_get_static_pad(m_videoIdentity, "src");
-
- if (!gst_pad_is_blocked(srcPad)) {
- //pad is not blocked, it's possible to swap outputs only in the null state
- qWarning() << "Pad is not blocked yet, could not switch video sink";
- GstState identityElementState = GST_STATE_NULL;
- gst_element_get_state(m_videoIdentity, &identityElementState, NULL, GST_CLOCK_TIME_NONE);
- if (identityElementState != GST_STATE_NULL) {
- gst_object_unref(GST_OBJECT(srcPad));
- return; //can't change vo yet, received async call from the previous change
- }
- }
-
- if (m_pendingVideoSink == m_videoSink) {
- qDebug() << "Abort, no change";
- //video output was change back to the current one,
- //no need to torment the pipeline, just unblock the pad
- if (gst_pad_is_blocked(srcPad))
-#if GST_CHECK_VERSION(1,0,0)
- gst_pad_remove_probe(srcPad, this->pad_probe_id);
-#else
- gst_pad_set_blocked_async(srcPad, false, &block_pad_cb, 0);
-#endif
-
- m_pendingVideoSink = 0;
- gst_object_unref(GST_OBJECT(srcPad));
- return;
- }
-
-#if !GST_CHECK_VERSION(1,0,0)
- if (m_usingColorspaceElement) {
- gst_element_set_state(m_colorSpace, GST_STATE_NULL);
- gst_element_set_state(m_videoSink, GST_STATE_NULL);
-
- gst_element_unlink(m_colorSpace, m_videoSink);
- gst_bin_remove(GST_BIN(m_videoOutputBin), m_colorSpace);
- } else {
-#else
- {
-#endif
- gst_element_set_state(m_videoSink, GST_STATE_NULL);
- gst_element_unlink(m_videoIdentity, m_videoSink);
- }
-
- removeVideoBufferProbe();
-
- gst_bin_remove(GST_BIN(m_videoOutputBin), m_videoSink);
-
- m_videoSink = m_pendingVideoSink;
- m_pendingVideoSink = 0;
-
- gst_bin_add(GST_BIN(m_videoOutputBin), m_videoSink);
-
- addVideoBufferProbe();
-
- bool linked = gst_element_link(m_videoIdentity, m_videoSink);
-#if !GST_CHECK_VERSION(1,0,0)
- m_usingColorspaceElement = false;
- if (!linked) {
- m_usingColorspaceElement = true;
-#ifdef DEBUG_PLAYBIN
- qDebug() << "Failed to connect video output, inserting the colorspace element.";
-#endif
- gst_bin_add(GST_BIN(m_videoOutputBin), m_colorSpace);
- linked = gst_element_link_many(m_videoIdentity, m_colorSpace, m_videoSink, NULL);
- }
-#endif
-
- if (!linked)
- qWarning() << "Linking video output element failed";
-
-#ifdef DEBUG_PLAYBIN
- qDebug() << "notify the video connector it has to emit a new segment message...";
-#endif
-
-#if !GST_CHECK_VERSION(1,0,0)
- //it's necessary to send a new segment event just before
- //the first buffer pushed to the new sink
- g_signal_emit_by_name(m_videoIdentity,
- "resend-new-segment",
- true //emit connection-failed signal
- //to have a chance to insert colorspace element
- );
-#endif
-
- GstState state = GST_STATE_VOID_PENDING;
-
- switch (m_pendingState) {
- case QMediaPlayer::StoppedState:
- state = GST_STATE_NULL;
- break;
- case QMediaPlayer::PausedState:
- state = GST_STATE_PAUSED;
- break;
- case QMediaPlayer::PlayingState:
- state = GST_STATE_PLAYING;
- break;
- }
-
-#if !GST_CHECK_VERSION(1,0,0)
- if (m_usingColorspaceElement)
- gst_element_set_state(m_colorSpace, state);
-#endif
-
- gst_element_set_state(m_videoSink, state);
-
- if (state == GST_STATE_NULL)
- flushVideoProbes();
-
- // Set state change that was deferred due the video output
- // change being pending
- gst_element_set_state(m_playbin, state);
-
- if (state != GST_STATE_NULL)
- resumeVideoProbes();
-
- //don't have to wait here, it will unblock eventually
- if (gst_pad_is_blocked(srcPad))
-#if GST_CHECK_VERSION(1,0,0)
- gst_pad_remove_probe(srcPad, this->pad_probe_id);
-#else
- gst_pad_set_blocked_async(srcPad, false, &block_pad_cb, 0);
-#endif
-
- gst_object_unref(GST_OBJECT(srcPad));
-
-#ifdef DEBUG_VO_BIN_DUMP
- gst_debug_bin_to_dot_file_with_ts(GST_BIN(m_playbin),
- GstDebugGraphDetails(GST_DEBUG_GRAPH_SHOW_ALL /* | GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE | GST_DEBUG_GRAPH_SHOW_NON_DEFAULT_PARAMS | GST_DEBUG_GRAPH_SHOW_STATES */),
- "playbin_finish");
-#endif
-}
-
-#if !GST_CHECK_VERSION(1,0,0)
-
-void QGstreamerPlayerSession::insertColorSpaceElement(GstElement *element, gpointer data)
-{
-#ifdef DEBUG_PLAYBIN
- qDebug() << Q_FUNC_INFO;
-#endif
- Q_UNUSED(element);
- QGstreamerPlayerSession* session = reinterpret_cast<QGstreamerPlayerSession*>(data);
-
- if (session->m_usingColorspaceElement)
- return;
- session->m_usingColorspaceElement = true;
-
-#ifdef DEBUG_PLAYBIN
- qDebug() << "Failed to connect video output, inserting the colorspace elemnt.";
- qDebug() << "notify the video connector it has to emit a new segment message...";
-#endif
- //it's necessary to send a new segment event just before
- //the first buffer pushed to the new sink
- g_signal_emit_by_name(session->m_videoIdentity,
- "resend-new-segment",
- false // don't emit connection-failed signal
- );
-
- gst_element_unlink(session->m_videoIdentity, session->m_videoSink);
- gst_bin_add(GST_BIN(session->m_videoOutputBin), session->m_colorSpace);
- gst_element_link_many(session->m_videoIdentity, session->m_colorSpace, session->m_videoSink, NULL);
-
- GstState state = GST_STATE_VOID_PENDING;
-
- switch (session->m_pendingState) {
- case QMediaPlayer::StoppedState:
- state = GST_STATE_NULL;
- break;
- case QMediaPlayer::PausedState:
- state = GST_STATE_PAUSED;
- break;
- case QMediaPlayer::PlayingState:
- state = GST_STATE_PLAYING;
- break;
- }
-
- gst_element_set_state(session->m_colorSpace, state);
-}
-
-#endif
-
-bool QGstreamerPlayerSession::isVideoAvailable() const
-{
- return m_videoAvailable;
-}
-
-bool QGstreamerPlayerSession::isSeekable() const
-{
- return m_seekable;
-}
-
-bool QGstreamerPlayerSession::play()
-{
-#ifdef DEBUG_PLAYBIN
- qDebug() << Q_FUNC_INFO;
-#endif
-
- m_everPlayed = false;
- if (m_playbin) {
- m_pendingState = QMediaPlayer::PlayingState;
- if (gst_element_set_state(m_playbin, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
- qWarning() << "GStreamer; Unable to play -" << m_request.url().toString();
- m_pendingState = m_state = QMediaPlayer::StoppedState;
- emit stateChanged(m_state);
- } else {
- resumeVideoProbes();
- return true;
- }
- }
-
- return false;
-}
-
-bool QGstreamerPlayerSession::pause()
-{
-#ifdef DEBUG_PLAYBIN
- qDebug() << Q_FUNC_INFO;
-#endif
- if (m_playbin) {
- m_pendingState = QMediaPlayer::PausedState;
- if (m_pendingVideoSink != 0)
- return true;
-
- if (gst_element_set_state(m_playbin, GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE) {
- qWarning() << "GStreamer; Unable to pause -" << m_request.url().toString();
- m_pendingState = m_state = QMediaPlayer::StoppedState;
- emit stateChanged(m_state);
- } else {
- resumeVideoProbes();
- return true;
- }
- }
-
- return false;
-}
-
-void QGstreamerPlayerSession::stop()
-{
-#ifdef DEBUG_PLAYBIN
- qDebug() << Q_FUNC_INFO;
-#endif
- m_everPlayed = false;
- if (m_playbin) {
-
- if (m_renderer)
- m_renderer->stopRenderer();
-
- flushVideoProbes();
- gst_element_set_state(m_playbin, GST_STATE_NULL);
-
- m_lastPosition = 0;
- QMediaPlayer::State oldState = m_state;
- m_pendingState = m_state = QMediaPlayer::StoppedState;
-
- finishVideoOutputChange();
-
- //we have to do it here, since gstreamer will not emit bus messages any more
- setSeekable(false);
- if (oldState != m_state)
- emit stateChanged(m_state);
- }
-}
-
-bool QGstreamerPlayerSession::seek(qint64 ms)
-{
-#ifdef DEBUG_PLAYBIN
- qDebug() << Q_FUNC_INFO << ms;
-#endif
- //seek locks when the video output sink is changing and pad is blocked
- if (m_playbin && !m_pendingVideoSink && m_state != QMediaPlayer::StoppedState && m_seekable) {
- ms = qMax(ms,qint64(0));
- gint64 position = ms * 1000000;
- bool isSeeking = gst_element_seek(m_playbin,
- m_playbackRate,
- GST_FORMAT_TIME,
- GstSeekFlags(GST_SEEK_FLAG_FLUSH),
- GST_SEEK_TYPE_SET,
- position,
- GST_SEEK_TYPE_NONE,
- 0);
- if (isSeeking)
- m_lastPosition = ms;
-
- return isSeeking;
- }
-
- return false;
-}
-
-void QGstreamerPlayerSession::setVolume(int volume)
-{
-#ifdef DEBUG_PLAYBIN
- qDebug() << Q_FUNC_INFO << volume;
-#endif
-
- if (m_volume != volume) {
- m_volume = volume;
-
- if (m_volumeElement)
- g_object_set(G_OBJECT(m_volumeElement), "volume", m_volume / 100.0, NULL);
-
- emit volumeChanged(m_volume);
- }
-}
-
-void QGstreamerPlayerSession::setMuted(bool muted)
-{
-#ifdef DEBUG_PLAYBIN
- qDebug() << Q_FUNC_INFO << muted;
-#endif
- if (m_muted != muted) {
- m_muted = muted;
-
- if (m_volumeElement)
- g_object_set(G_OBJECT(m_volumeElement), "mute", m_muted ? TRUE : FALSE, NULL);
-
- emit mutedStateChanged(m_muted);
- }
-}
-
-
-void QGstreamerPlayerSession::setSeekable(bool seekable)
-{
-#ifdef DEBUG_PLAYBIN
- qDebug() << Q_FUNC_INFO << seekable;
-#endif
- if (seekable != m_seekable) {
- m_seekable = seekable;
- emit seekableChanged(m_seekable);
- }
-}
-
-bool QGstreamerPlayerSession::processBusMessage(const QGstreamerMessage &message)
-{
- GstMessage* gm = message.rawMessage();
- if (gm) {
- //tag message comes from elements inside playbin, not from playbin itself
- if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_TAG) {
- GstTagList *tag_list;
- gst_message_parse_tag(gm, &tag_list);
-
- QMap<QByteArray, QVariant> newTags = QGstUtils::gstTagListToMap(tag_list);
- QMap<QByteArray, QVariant>::const_iterator it = newTags.constBegin();
- for ( ; it != newTags.constEnd(); ++it)
- m_tags.insert(it.key(), it.value()); // overwrite existing tags
-
- gst_tag_list_free(tag_list);
-
- emit tagsChanged();
- } else if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_DURATION) {
- updateDuration();
- }
-
-#ifdef DEBUG_PLAYBIN
- if (m_sourceType == MMSSrc && qstrcmp(GST_OBJECT_NAME(GST_MESSAGE_SRC(gm)), "source") == 0) {
- qDebug() << "Message from MMSSrc: " << GST_MESSAGE_TYPE(gm);
- } else if (m_sourceType == RTSPSrc && qstrcmp(GST_OBJECT_NAME(GST_MESSAGE_SRC(gm)), "source") == 0) {
- qDebug() << "Message from RTSPSrc: " << GST_MESSAGE_TYPE(gm);
- } else {
- qDebug() << "Message from " << GST_OBJECT_NAME(GST_MESSAGE_SRC(gm)) << ":" << GST_MESSAGE_TYPE(gm);
- }
-#endif
-
- if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_BUFFERING) {
- int progress = 0;
- gst_message_parse_buffering(gm, &progress);
- emit bufferingProgressChanged(progress);
- }
-
- bool handlePlaybin2 = false;
- if (GST_MESSAGE_SRC(gm) == GST_OBJECT_CAST(m_playbin)) {
- switch (GST_MESSAGE_TYPE(gm)) {
- case GST_MESSAGE_STATE_CHANGED:
- {
- GstState oldState;
- GstState newState;
- GstState pending;
-
- gst_message_parse_state_changed(gm, &oldState, &newState, &pending);
-
-#ifdef DEBUG_PLAYBIN
- QStringList states;
- states << "GST_STATE_VOID_PENDING" << "GST_STATE_NULL" << "GST_STATE_READY" << "GST_STATE_PAUSED" << "GST_STATE_PLAYING";
-
- qDebug() << QString("state changed: old: %1 new: %2 pending: %3") \
- .arg(states[oldState]) \
- .arg(states[newState]) \
- .arg(states[pending]);
-#endif
-
- switch (newState) {
- case GST_STATE_VOID_PENDING:
- case GST_STATE_NULL:
- setSeekable(false);
- finishVideoOutputChange();
- if (m_state != QMediaPlayer::StoppedState)
- emit stateChanged(m_state = QMediaPlayer::StoppedState);
- break;
- case GST_STATE_READY:
- setSeekable(false);
- if (m_state != QMediaPlayer::StoppedState)
- emit stateChanged(m_state = QMediaPlayer::StoppedState);
- break;
- case GST_STATE_PAUSED:
- {
- QMediaPlayer::State prevState = m_state;
- m_state = QMediaPlayer::PausedState;
-
- //check for seekable
- if (oldState == GST_STATE_READY) {
- if (m_sourceType == SoupHTTPSrc || m_sourceType == MMSSrc) {
- //since udpsrc is a live source, it is not applicable here
- m_everPlayed = true;
- }
-
- getStreamsInfo();
- updateVideoResolutionTag();
-
- //gstreamer doesn't give a reliable indication the duration
- //information is ready, GST_MESSAGE_DURATION is not sent by most elements
- //the duration is queried up to 5 times with increasing delay
- m_durationQueries = 5;
- // This should also update the seekable flag.
- updateDuration();
-
- if (!qFuzzyCompare(m_playbackRate, qreal(1.0))) {
- qreal rate = m_playbackRate;
- m_playbackRate = 1.0;
- setPlaybackRate(rate);
- }
- }
-
- if (m_state != prevState)
- emit stateChanged(m_state);
-
- break;
- }
- case GST_STATE_PLAYING:
- m_everPlayed = true;
- if (m_state != QMediaPlayer::PlayingState) {
- emit stateChanged(m_state = QMediaPlayer::PlayingState);
-
- // For rtsp streams duration information might not be available
- // until playback starts.
- if (m_duration <= 0) {
- m_durationQueries = 5;
- updateDuration();
- }
- }
-
- break;
- }
- }
- break;
-
- case GST_MESSAGE_EOS:
- emit playbackFinished();
- break;
-
- case GST_MESSAGE_TAG:
- case GST_MESSAGE_STREAM_STATUS:
- case GST_MESSAGE_UNKNOWN:
- break;
- case GST_MESSAGE_ERROR: {
- GError *err;
- gchar *debug;
- gst_message_parse_error(gm, &err, &debug);
- if (err->domain == GST_STREAM_ERROR && err->code == GST_STREAM_ERROR_CODEC_NOT_FOUND)
- processInvalidMedia(QMediaPlayer::FormatError, tr("Cannot play stream of type: <unknown>"));
- else
- processInvalidMedia(QMediaPlayer::ResourceError, QString::fromUtf8(err->message));
- qWarning() << "Error:" << QString::fromUtf8(err->message);
- g_error_free(err);
- g_free(debug);
- }
- break;
- case GST_MESSAGE_WARNING:
- {
- GError *err;
- gchar *debug;
- gst_message_parse_warning (gm, &err, &debug);
- qWarning() << "Warning:" << QString::fromUtf8(err->message);
- g_error_free (err);
- g_free (debug);
- }
- break;
- case GST_MESSAGE_INFO:
-#ifdef DEBUG_PLAYBIN
- {
- GError *err;
- gchar *debug;
- gst_message_parse_info (gm, &err, &debug);
- qDebug() << "Info:" << QString::fromUtf8(err->message);
- g_error_free (err);
- g_free (debug);
- }
-#endif
- break;
- case GST_MESSAGE_BUFFERING:
- case GST_MESSAGE_STATE_DIRTY:
- case GST_MESSAGE_STEP_DONE:
- case GST_MESSAGE_CLOCK_PROVIDE:
- case GST_MESSAGE_CLOCK_LOST:
- case GST_MESSAGE_NEW_CLOCK:
- case GST_MESSAGE_STRUCTURE_CHANGE:
- case GST_MESSAGE_APPLICATION:
- case GST_MESSAGE_ELEMENT:
- break;
- case GST_MESSAGE_SEGMENT_START:
- {
- const GstStructure *structure = gst_message_get_structure(gm);
- qint64 position = g_value_get_int64(gst_structure_get_value(structure, "position"));
- position /= 1000000;
- m_lastPosition = position;
- emit positionChanged(position);
- }
- break;
- case GST_MESSAGE_SEGMENT_DONE:
- break;
- case GST_MESSAGE_LATENCY:
-#if GST_CHECK_VERSION(0,10,13)
- case GST_MESSAGE_ASYNC_START:
- break;
- case GST_MESSAGE_ASYNC_DONE:
- {
- gint64 position = 0;
- if (qt_gst_element_query_position(m_playbin, GST_FORMAT_TIME, &position)) {
- position /= 1000000;
- m_lastPosition = position;
- emit positionChanged(position);
- }
- break;
- }
-#if GST_CHECK_VERSION(0,10,23)
- case GST_MESSAGE_REQUEST_STATE:
-#endif
-#endif
- case GST_MESSAGE_ANY:
- break;
- default:
- break;
- }
- } else if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_ERROR) {
- GError *err;
- gchar *debug;
- gst_message_parse_error(gm, &err, &debug);
- // If the source has given up, so do we.
- if (qstrcmp(GST_OBJECT_NAME(GST_MESSAGE_SRC(gm)), "source") == 0) {
- bool everPlayed = m_everPlayed;
- // Try and differentiate network related resource errors from the others
- if (!m_request.url().isRelative() && m_request.url().scheme().compare(QLatin1String("file"), Qt::CaseInsensitive) != 0 ) {
- if (everPlayed ||
- (err->domain == GST_RESOURCE_ERROR && (
- err->code == GST_RESOURCE_ERROR_BUSY ||
- err->code == GST_RESOURCE_ERROR_OPEN_READ ||
- err->code == GST_RESOURCE_ERROR_READ ||
- err->code == GST_RESOURCE_ERROR_SEEK ||
- err->code == GST_RESOURCE_ERROR_SYNC))) {
- processInvalidMedia(QMediaPlayer::NetworkError, QString::fromUtf8(err->message));
- } else {
- processInvalidMedia(QMediaPlayer::ResourceError, QString::fromUtf8(err->message));
- }
- }
- else
- processInvalidMedia(QMediaPlayer::ResourceError, QString::fromUtf8(err->message));
- } else if (err->domain == GST_STREAM_ERROR
- && (err->code == GST_STREAM_ERROR_DECRYPT || err->code == GST_STREAM_ERROR_DECRYPT_NOKEY)) {
- processInvalidMedia(QMediaPlayer::AccessDeniedError, QString::fromUtf8(err->message));
- } else {
- handlePlaybin2 = true;
- }
- if (!handlePlaybin2)
- qWarning() << "Error:" << QString::fromUtf8(err->message);
- g_error_free(err);
- g_free(debug);
- } else if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_ELEMENT
- && qstrcmp(GST_OBJECT_NAME(GST_MESSAGE_SRC(gm)), "source") == 0
- && m_sourceType == UDPSrc
- && gst_structure_has_name(gst_message_get_structure(gm), "GstUDPSrcTimeout")) {
- //since udpsrc will not generate an error for the timeout event,
- //we need to process its element message here and treat it as an error.
- processInvalidMedia(m_everPlayed ? QMediaPlayer::NetworkError : QMediaPlayer::ResourceError,
- tr("UDP source timeout"));
- } else {
- handlePlaybin2 = true;
- }
-
- if (handlePlaybin2) {
- if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_WARNING) {
- GError *err;
- gchar *debug;
- gst_message_parse_warning(gm, &err, &debug);
- if (err->domain == GST_STREAM_ERROR && err->code == GST_STREAM_ERROR_CODEC_NOT_FOUND)
- emit error(int(QMediaPlayer::FormatError), tr("Cannot play stream of type: <unknown>"));
- // GStreamer shows warning for HTTP playlists
- if (err && err->message)
- qWarning() << "Warning:" << QString::fromUtf8(err->message);
- g_error_free(err);
- g_free(debug);
- } else if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_ERROR) {
- GError *err;
- gchar *debug;
- gst_message_parse_error(gm, &err, &debug);
-
- // Nearly all errors map to ResourceError
- QMediaPlayer::Error qerror = QMediaPlayer::ResourceError;
- if (err->domain == GST_STREAM_ERROR
- && (err->code == GST_STREAM_ERROR_DECRYPT
- || err->code == GST_STREAM_ERROR_DECRYPT_NOKEY)) {
- qerror = QMediaPlayer::AccessDeniedError;
- }
- processInvalidMedia(qerror, QString::fromUtf8(err->message));
- if (err && err->message)
- qWarning() << "Error:" << QString::fromUtf8(err->message);
-
- g_error_free(err);
- g_free(debug);
- }
- }
- }
-
- return false;
-}
-
-void QGstreamerPlayerSession::getStreamsInfo()
-{
- QList< QMap<QString,QVariant> > oldProperties = m_streamProperties;
- QList<QMediaStreamsControl::StreamType> oldTypes = m_streamTypes;
- QMap<QMediaStreamsControl::StreamType, int> oldOffset = m_playbin2StreamOffset;
-
- //check if video is available:
- bool haveAudio = false;
- bool haveVideo = false;
- m_streamProperties.clear();
- m_streamTypes.clear();
- m_playbin2StreamOffset.clear();
-
- gint audioStreamsCount = 0;
- gint videoStreamsCount = 0;
- gint textStreamsCount = 0;
-
- g_object_get(G_OBJECT(m_playbin), "n-audio", &audioStreamsCount, NULL);
- g_object_get(G_OBJECT(m_playbin), "n-video", &videoStreamsCount, NULL);
- g_object_get(G_OBJECT(m_playbin), "n-text", &textStreamsCount, NULL);
-
- haveAudio = audioStreamsCount > 0;
- haveVideo = videoStreamsCount > 0;
-
- m_playbin2StreamOffset[QMediaStreamsControl::AudioStream] = 0;
- m_playbin2StreamOffset[QMediaStreamsControl::VideoStream] = audioStreamsCount;
- m_playbin2StreamOffset[QMediaStreamsControl::SubPictureStream] = audioStreamsCount+videoStreamsCount;
-
- for (int i=0; i<audioStreamsCount; i++)
- m_streamTypes.append(QMediaStreamsControl::AudioStream);
-
- for (int i=0; i<videoStreamsCount; i++)
- m_streamTypes.append(QMediaStreamsControl::VideoStream);
-
- for (int i=0; i<textStreamsCount; i++)
- m_streamTypes.append(QMediaStreamsControl::SubPictureStream);
-
- for (int i=0; i<m_streamTypes.count(); i++) {
- QMediaStreamsControl::StreamType streamType = m_streamTypes[i];
- QMap<QString, QVariant> streamProperties;
-
- int streamIndex = i - m_playbin2StreamOffset[streamType];
-
- GstTagList *tags = 0;
- switch (streamType) {
- case QMediaStreamsControl::AudioStream:
- g_signal_emit_by_name(G_OBJECT(m_playbin), "get-audio-tags", streamIndex, &tags);
- break;
- case QMediaStreamsControl::VideoStream:
- g_signal_emit_by_name(G_OBJECT(m_playbin), "get-video-tags", streamIndex, &tags);
- break;
- case QMediaStreamsControl::SubPictureStream:
- g_signal_emit_by_name(G_OBJECT(m_playbin), "get-text-tags", streamIndex, &tags);
- break;
- default:
- break;
- }
-#if GST_CHECK_VERSION(1,0,0)
- if (tags && GST_IS_TAG_LIST(tags)) {
-#else
- if (tags && gst_is_tag_list(tags)) {
-#endif
- gchar *languageCode = 0;
- if (gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &languageCode))
- streamProperties[QMediaMetaData::Language] = QString::fromUtf8(languageCode);
-
- //qDebug() << "language for setream" << i << QString::fromUtf8(languageCode);
- g_free (languageCode);
- gst_tag_list_free(tags);
- }
-
- m_streamProperties.append(streamProperties);
- }
-
- bool emitAudioChanged = (haveAudio != m_audioAvailable);
- bool emitVideoChanged = (haveVideo != m_videoAvailable);
-
- m_audioAvailable = haveAudio;
- m_videoAvailable = haveVideo;
-
- if (emitAudioChanged) {
- emit audioAvailableChanged(m_audioAvailable);
- }
- if (emitVideoChanged) {
- emit videoAvailableChanged(m_videoAvailable);
- }
-
- if (oldProperties != m_streamProperties || oldTypes != m_streamTypes || oldOffset != m_playbin2StreamOffset)
- emit streamsChanged();
-}
-
-void QGstreamerPlayerSession::updateVideoResolutionTag()
-{
-#ifdef DEBUG_PLAYBIN
- qDebug() << Q_FUNC_INFO;
-#endif
- QSize size;
- QSize aspectRatio;
- GstPad *pad = gst_element_get_static_pad(m_videoIdentity, "src");
- GstCaps *caps = qt_gst_pad_get_current_caps(pad);
-
- if (caps) {
- const GstStructure *structure = gst_caps_get_structure(caps, 0);
- gst_structure_get_int(structure, "width", &size.rwidth());
- gst_structure_get_int(structure, "height", &size.rheight());
-
- gint aspectNum = 0;
- gint aspectDenum = 0;
- if (!size.isEmpty() && gst_structure_get_fraction(
- structure, "pixel-aspect-ratio", &aspectNum, &aspectDenum)) {
- if (aspectDenum > 0)
- aspectRatio = QSize(aspectNum, aspectDenum);
- }
- gst_caps_unref(caps);
- }
-
- gst_object_unref(GST_OBJECT(pad));
-
- QSize currentSize = m_tags.value("resolution").toSize();
- QSize currentAspectRatio = m_tags.value("pixel-aspect-ratio").toSize();
-
- if (currentSize != size || currentAspectRatio != aspectRatio) {
- if (aspectRatio.isEmpty())
- m_tags.remove("pixel-aspect-ratio");
-
- if (size.isEmpty()) {
- m_tags.remove("resolution");
- } else {
- m_tags.insert("resolution", QVariant(size));
- if (!aspectRatio.isEmpty())
- m_tags.insert("pixel-aspect-ratio", QVariant(aspectRatio));
- }
-
- emit tagsChanged();
- }
-}
-
-void QGstreamerPlayerSession::updateDuration()
-{
- gint64 gstDuration = 0;
- int duration = 0;
-
- if (m_playbin && qt_gst_element_query_duration(m_playbin, GST_FORMAT_TIME, &gstDuration))
- duration = gstDuration / 1000000;
-
- if (m_duration != duration) {
- m_duration = duration;
- emit durationChanged(m_duration);
- }
-
- gboolean seekable = false;
- if (m_duration > 0) {
- m_durationQueries = 0;
- GstQuery *query = gst_query_new_seeking(GST_FORMAT_TIME);
- if (gst_element_query(m_playbin, query))
- gst_query_parse_seeking(query, 0, &seekable, 0, 0);
- gst_query_unref(query);
- }
- setSeekable(seekable);
-
- if (m_durationQueries > 0) {
- //increase delay between duration requests
- int delay = 25 << (5 - m_durationQueries);
- QTimer::singleShot(delay, this, SLOT(updateDuration()));
- m_durationQueries--;
- }
-#ifdef DEBUG_PLAYBIN
- qDebug() << Q_FUNC_INFO << m_duration;
-#endif
-}
-
-void QGstreamerPlayerSession::playbinNotifySource(GObject *o, GParamSpec *p, gpointer d)
-{
- Q_UNUSED(p);
-
- GstElement *source = 0;
- g_object_get(o, "source", &source, NULL);
- if (source == 0)
- return;
-
-#ifdef DEBUG_PLAYBIN
- qDebug() << "Playbin source added:" << G_OBJECT_CLASS_NAME(G_OBJECT_GET_CLASS(source));
-#endif
-
- // Set Headers
- const QByteArray userAgentString("User-Agent");
-
- QGstreamerPlayerSession *self = reinterpret_cast<QGstreamerPlayerSession *>(d);
-
- // User-Agent - special case, souphhtpsrc will always set something, even if
- // defined in extra-headers
- if (g_object_class_find_property(G_OBJECT_GET_CLASS(source), "user-agent") != 0) {
- g_object_set(G_OBJECT(source), "user-agent",
- self->m_request.rawHeader(userAgentString).constData(), NULL);
- }
-
- // The rest
- if (g_object_class_find_property(G_OBJECT_GET_CLASS(source), "extra-headers") != 0) {
- GstStructure *extras = qt_gst_structure_new_empty("extras");
-
- const auto rawHeaderList = self->m_request.rawHeaderList();
- for (const QByteArray &rawHeader : rawHeaderList) {
- if (rawHeader == userAgentString) // Filter User-Agent
- continue;
- else {
- GValue headerValue;
-
- memset(&headerValue, 0, sizeof(GValue));
- g_value_init(&headerValue, G_TYPE_STRING);
-
- g_value_set_string(&headerValue,
- self->m_request.rawHeader(rawHeader).constData());
-
- gst_structure_set_value(extras, rawHeader.constData(), &headerValue);
- }
- }
-
- if (gst_structure_n_fields(extras) > 0)
- g_object_set(G_OBJECT(source), "extra-headers", extras, NULL);
-
- gst_structure_free(extras);
- }
-
- //set timeout property to 30 seconds
- const int timeout = 30;
- if (qstrcmp(G_OBJECT_CLASS_NAME(G_OBJECT_GET_CLASS(source)), "GstUDPSrc") == 0) {
- quint64 convertedTimeout = timeout;
-#if GST_CHECK_VERSION(1,0,0)
- // Gst 1.x -> nanosecond
- convertedTimeout *= 1000000000;
-#else
- // Gst 0.10 -> microsecond
- convertedTimeout *= 1000000;
-#endif
- g_object_set(G_OBJECT(source), "timeout", convertedTimeout, NULL);
- self->m_sourceType = UDPSrc;
- //The udpsrc is always a live source.
- self->m_isLiveSource = true;
- } else if (qstrcmp(G_OBJECT_CLASS_NAME(G_OBJECT_GET_CLASS(source)), "GstSoupHTTPSrc") == 0) {
- //souphttpsrc timeout unit = second
- g_object_set(G_OBJECT(source), "timeout", guint(timeout), NULL);
- self->m_sourceType = SoupHTTPSrc;
- //since gst_base_src_is_live is not reliable, so we check the source property directly
- gboolean isLive = false;
- g_object_get(G_OBJECT(source), "is-live", &isLive, NULL);
- self->m_isLiveSource = isLive;
- } else if (qstrcmp(G_OBJECT_CLASS_NAME(G_OBJECT_GET_CLASS(source)), "GstMMSSrc") == 0) {
- self->m_sourceType = MMSSrc;
- self->m_isLiveSource = gst_base_src_is_live(GST_BASE_SRC(source));
- g_object_set(G_OBJECT(source), "tcp-timeout", G_GUINT64_CONSTANT(timeout*1000000), NULL);
- } else if (qstrcmp(G_OBJECT_CLASS_NAME(G_OBJECT_GET_CLASS(source)), "GstRTSPSrc") == 0) {
- //rtspsrc acts like a live source and will therefore only generate data in the PLAYING state.
- self->m_sourceType = RTSPSrc;
- self->m_isLiveSource = true;
- g_object_set(G_OBJECT(source), "buffer-mode", 1, NULL);
- } else {
- self->m_sourceType = UnknownSrc;
- self->m_isLiveSource = gst_base_src_is_live(GST_BASE_SRC(source));
- }
-
-#ifdef DEBUG_PLAYBIN
- if (self->m_isLiveSource)
- qDebug() << "Current source is a live source";
- else
- qDebug() << "Current source is a non-live source";
-#endif
-
- if (self->m_videoSink)
- g_object_set(G_OBJECT(self->m_videoSink), "sync", !self->m_isLiveSource, NULL);
-
- gst_object_unref(source);
-}
-
-bool QGstreamerPlayerSession::isLiveSource() const
-{
- return m_isLiveSource;
-}
-
-void QGstreamerPlayerSession::handleVolumeChange(GObject *o, GParamSpec *p, gpointer d)
-{
- Q_UNUSED(o);
- Q_UNUSED(p);
- QGstreamerPlayerSession *session = reinterpret_cast<QGstreamerPlayerSession *>(d);
- QMetaObject::invokeMethod(session, "updateVolume", Qt::QueuedConnection);
-}
-
-void QGstreamerPlayerSession::updateVolume()
-{
- double volume = 1.0;
- g_object_get(m_playbin, "volume", &volume, NULL);
-
- if (m_volume != int(volume*100 + 0.5)) {
- m_volume = int(volume*100 + 0.5);
-#ifdef DEBUG_PLAYBIN
- qDebug() << Q_FUNC_INFO << m_volume;
-#endif
- emit volumeChanged(m_volume);
- }
-}
-
-void QGstreamerPlayerSession::handleMutedChange(GObject *o, GParamSpec *p, gpointer d)
-{
- Q_UNUSED(o);
- Q_UNUSED(p);
- QGstreamerPlayerSession *session = reinterpret_cast<QGstreamerPlayerSession *>(d);
- QMetaObject::invokeMethod(session, "updateMuted", Qt::QueuedConnection);
-}
-
-void QGstreamerPlayerSession::updateMuted()
-{
- gboolean muted = FALSE;
- g_object_get(G_OBJECT(m_playbin), "mute", &muted, NULL);
- if (m_muted != muted) {
- m_muted = muted;
-#ifdef DEBUG_PLAYBIN
- qDebug() << Q_FUNC_INFO << m_muted;
-#endif
- emit mutedStateChanged(muted);
- }
-}
-
-#if !GST_CHECK_VERSION(0, 10, 33)
-static gboolean factory_can_src_any_caps (GstElementFactory *factory, const GstCaps *caps)
-{
- GList *templates;
-
- g_return_val_if_fail(factory != NULL, FALSE);
- g_return_val_if_fail(caps != NULL, FALSE);
-
- templates = factory->staticpadtemplates;
-
- while (templates) {
- GstStaticPadTemplate *templ = (GstStaticPadTemplate *)templates->data;
-
- if (templ->direction == GST_PAD_SRC) {
- GstCaps *templcaps = gst_static_caps_get(&templ->static_caps);
-
- if (qt_gst_caps_can_intersect(caps, templcaps)) {
- gst_caps_unref(templcaps);
- return TRUE;
- }
- gst_caps_unref(templcaps);
- }
- templates = g_list_next(templates);
- }
-
- return FALSE;
-}
-#endif
-
-GstAutoplugSelectResult QGstreamerPlayerSession::handleAutoplugSelect(GstBin *bin, GstPad *pad, GstCaps *caps, GstElementFactory *factory, QGstreamerPlayerSession *session)
-{
- Q_UNUSED(bin);
- Q_UNUSED(pad);
- Q_UNUSED(caps);
-
- GstAutoplugSelectResult res = GST_AUTOPLUG_SELECT_TRY;
-
- // if VAAPI is available and can be used to decode but the current video sink cannot handle
- // the decoded format, don't use it
- const gchar *factoryName = gst_plugin_feature_get_name(GST_PLUGIN_FEATURE(factory));
- if (g_str_has_prefix(factoryName, "vaapi")) {
- GstPad *sinkPad = gst_element_get_static_pad(session->m_videoSink, "sink");
-#if GST_CHECK_VERSION(1,0,0)
- GstCaps *sinkCaps = gst_pad_query_caps(sinkPad, NULL);
-#else
- GstCaps *sinkCaps = gst_pad_get_caps(sinkPad);
-#endif
-
-#if !GST_CHECK_VERSION(0, 10, 33)
- if (!factory_can_src_any_caps(factory, sinkCaps))
-#else
- if (!gst_element_factory_can_src_any_caps(factory, sinkCaps))
-#endif
- res = GST_AUTOPLUG_SELECT_SKIP;
-
- gst_object_unref(sinkPad);
- gst_caps_unref(sinkCaps);
- }
-
- return res;
-}
-
-void QGstreamerPlayerSession::handleElementAdded(GstBin *bin, GstElement *element, QGstreamerPlayerSession *session)
-{
- Q_UNUSED(bin);
- //we have to configure queue2 element to enable media downloading
- //and reporting available ranges,
- //but it's added dynamically to playbin2
-
- gchar *elementName = gst_element_get_name(element);
-
- if (g_str_has_prefix(elementName, "queue2")) {
- // Disable on-disk buffering.
- g_object_set(G_OBJECT(element), "temp-template", NULL, NULL);
- } else if (g_str_has_prefix(elementName, "uridecodebin") ||
-#if GST_CHECK_VERSION(1,0,0)
- g_str_has_prefix(elementName, "decodebin")) {
-#else
- g_str_has_prefix(elementName, "decodebin2")) {
- if (g_str_has_prefix(elementName, "uridecodebin")) {
- // Add video/x-surface (VAAPI) to default raw formats
- g_object_set(G_OBJECT(element), "caps", gst_static_caps_get(&static_RawCaps), NULL);
- // listen for uridecodebin autoplug-select to skip VAAPI usage when the current
- // video sink doesn't support it
- g_signal_connect(element, "autoplug-select", G_CALLBACK(handleAutoplugSelect), session);
- }
-#endif
- //listen for queue2 element added to uridecodebin/decodebin2 as well.
- //Don't touch other bins since they may have unrelated queues
- g_signal_connect(element, "element-added",
- G_CALLBACK(handleElementAdded), session);
- }
-
- g_free(elementName);
-}
-
-void QGstreamerPlayerSession::handleStreamsChange(GstBin *bin, gpointer user_data)
-{
- Q_UNUSED(bin);
-
- QGstreamerPlayerSession* session = reinterpret_cast<QGstreamerPlayerSession*>(user_data);
- QMetaObject::invokeMethod(session, "getStreamsInfo", Qt::QueuedConnection);
-}
-
-//doing proper operations when detecting an invalidMedia: change media status before signal the erorr
-void QGstreamerPlayerSession::processInvalidMedia(QMediaPlayer::Error errorCode, const QString& errorString)
-{
-#ifdef DEBUG_PLAYBIN
- qDebug() << Q_FUNC_INFO;
-#endif
- emit invalidMedia();
- stop();
- emit error(int(errorCode), errorString);
-}
-
-void QGstreamerPlayerSession::showPrerollFrames(bool enabled)
-{
-#ifdef DEBUG_PLAYBIN
- qDebug() << Q_FUNC_INFO << enabled;
-#endif
- if (enabled != m_displayPrerolledFrame && m_videoSink &&
- g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "show-preroll-frame") != 0) {
-
- gboolean value = enabled;
- g_object_set(G_OBJECT(m_videoSink), "show-preroll-frame", value, NULL);
- m_displayPrerolledFrame = enabled;
- }
-}
-
-void QGstreamerPlayerSession::addProbe(QGstreamerVideoProbeControl* probe)
-{
- Q_ASSERT(!m_videoProbe);
- m_videoProbe = probe;
- addVideoBufferProbe();
-}
-
-void QGstreamerPlayerSession::removeProbe(QGstreamerVideoProbeControl* probe)
-{
- Q_ASSERT(m_videoProbe == probe);
- removeVideoBufferProbe();
- m_videoProbe = 0;
-}
-
-void QGstreamerPlayerSession::addProbe(QGstreamerAudioProbeControl* probe)
-{
- Q_ASSERT(!m_audioProbe);
- m_audioProbe = probe;
- addAudioBufferProbe();
-}
-
-void QGstreamerPlayerSession::removeProbe(QGstreamerAudioProbeControl* probe)
-{
- Q_ASSERT(m_audioProbe == probe);
- removeAudioBufferProbe();
- m_audioProbe = 0;
-}
-
-// This function is similar to stop(),
-// but does not set m_everPlayed, m_lastPosition,
-// and setSeekable() values.
-void QGstreamerPlayerSession::endOfMediaReset()
-{
- if (m_renderer)
- m_renderer->stopRenderer();
-
- flushVideoProbes();
- gst_element_set_state(m_playbin, GST_STATE_NULL);
-
- QMediaPlayer::State oldState = m_state;
- m_pendingState = m_state = QMediaPlayer::StoppedState;
-
- finishVideoOutputChange();
-
- if (oldState != m_state)
- emit stateChanged(m_state);
-}
-
-void QGstreamerPlayerSession::removeVideoBufferProbe()
-{
- if (!m_videoProbe)
- return;
-
- GstPad *pad = gst_element_get_static_pad(m_videoSink, "sink");
- if (pad) {
- m_videoProbe->removeProbeFromPad(pad);
- gst_object_unref(GST_OBJECT(pad));
- }
-}
-
-void QGstreamerPlayerSession::addVideoBufferProbe()
-{
- if (!m_videoProbe)
- return;
-
- GstPad *pad = gst_element_get_static_pad(m_videoSink, "sink");
- if (pad) {
- m_videoProbe->addProbeToPad(pad);
- gst_object_unref(GST_OBJECT(pad));
- }
-}
-
-void QGstreamerPlayerSession::removeAudioBufferProbe()
-{
- if (!m_audioProbe)
- return;
-
- GstPad *pad = gst_element_get_static_pad(m_audioSink, "sink");
- if (pad) {
- m_audioProbe->removeProbeFromPad(pad);
- gst_object_unref(GST_OBJECT(pad));
- }
-}
-
-void QGstreamerPlayerSession::addAudioBufferProbe()
-{
- if (!m_audioProbe)
- return;
-
- GstPad *pad = gst_element_get_static_pad(m_audioSink, "sink");
- if (pad) {
- m_audioProbe->addProbeToPad(pad);
- gst_object_unref(GST_OBJECT(pad));
- }
-}
-
-void QGstreamerPlayerSession::flushVideoProbes()
-{
- if (m_videoProbe)
- m_videoProbe->startFlushing();
-}
-
-void QGstreamerPlayerSession::resumeVideoProbes()
-{
- if (m_videoProbe)
- m_videoProbe->stopFlushing();
-}
-
-QT_END_NAMESPACE
diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.h b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.h
deleted file mode 100644
index 7f46e8f41..000000000
--- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.h
+++ /dev/null
@@ -1,262 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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 QGSTREAMERPLAYERSESSION_H
-#define QGSTREAMERPLAYERSESSION_H
-
-#include <QtMultimedia/private/qtmultimediaglobal_p.h>
-#include <QObject>
-#include <QtCore/qmutex.h>
-#include <QtNetwork/qnetworkrequest.h>
-#include "qgstreamerplayercontrol.h"
-#include <private/qgstreamerbushelper_p.h>
-#include <qmediaplayer.h>
-#include <qmediastreamscontrol.h>
-#include <qaudioformat.h>
-
-#if QT_CONFIG(gstreamer_app)
-#include <private/qgstappsrc_p.h>
-#endif
-
-#include <gst/gst.h>
-
-QT_BEGIN_NAMESPACE
-
-class QGstreamerBusHelper;
-class QGstreamerMessage;
-
-class QGstreamerVideoRendererInterface;
-class QGstreamerVideoProbeControl;
-class QGstreamerAudioProbeControl;
-
-typedef enum {
- GST_AUTOPLUG_SELECT_TRY,
- GST_AUTOPLUG_SELECT_EXPOSE,
- GST_AUTOPLUG_SELECT_SKIP
-} GstAutoplugSelectResult;
-
-class QGstreamerPlayerSession : public QObject,
- public QGstreamerBusMessageFilter
-{
-Q_OBJECT
-Q_INTERFACES(QGstreamerBusMessageFilter)
-
-public:
- QGstreamerPlayerSession(QObject *parent);
- virtual ~QGstreamerPlayerSession();
-
- GstElement *playbin() const;
- QGstreamerBusHelper *bus() const { return m_busHelper; }
-
- QNetworkRequest request() const;
-
- QMediaPlayer::State state() const { return m_state; }
- QMediaPlayer::State pendingState() const { return m_pendingState; }
-
- qint64 duration() const;
- qint64 position() const;
-
- int volume() const;
- bool isMuted() const;
-
- bool isAudioAvailable() const;
-
- void setVideoRenderer(QObject *renderer);
- bool isVideoAvailable() const;
-
- bool isSeekable() const;
-
- qreal playbackRate() const;
- void setPlaybackRate(qreal rate);
-
- QMediaTimeRange availablePlaybackRanges() const;
-
- QMap<QByteArray ,QVariant> tags() const { return m_tags; }
- QMap<QString,QVariant> streamProperties(int streamNumber) const { return m_streamProperties[streamNumber]; }
- int streamCount() const { return m_streamProperties.count(); }
- QMediaStreamsControl::StreamType streamType(int streamNumber) { return m_streamTypes.value(streamNumber, QMediaStreamsControl::UnknownStream); }
-
- int activeStream(QMediaStreamsControl::StreamType streamType) const;
- void setActiveStream(QMediaStreamsControl::StreamType streamType, int streamNumber);
-
- bool processBusMessage(const QGstreamerMessage &message) override;
-
-#if QT_CONFIG(gstreamer_app)
- QGstAppSrc *appsrc() const { return m_appSrc; }
- static void configureAppSrcElement(GObject*, GObject*, GParamSpec*,QGstreamerPlayerSession* _this);
-#endif
-
- bool isLiveSource() const;
-
- void addProbe(QGstreamerVideoProbeControl* probe);
- void removeProbe(QGstreamerVideoProbeControl* probe);
-
- void addProbe(QGstreamerAudioProbeControl* probe);
- void removeProbe(QGstreamerAudioProbeControl* probe);
-
- void endOfMediaReset();
-
-public slots:
- void loadFromUri(const QNetworkRequest &url);
- void loadFromStream(const QNetworkRequest &url, QIODevice *stream);
- bool play();
- bool pause();
- void stop();
-
- bool seek(qint64 pos);
-
- void setVolume(int volume);
- void setMuted(bool muted);
-
- void showPrerollFrames(bool enabled);
-
-signals:
- void durationChanged(qint64 duration);
- void positionChanged(qint64 position);
- void stateChanged(QMediaPlayer::State state);
- void volumeChanged(int volume);
- void mutedStateChanged(bool muted);
- void audioAvailableChanged(bool audioAvailable);
- void videoAvailableChanged(bool videoAvailable);
- void bufferingProgressChanged(int percentFilled);
- void playbackFinished();
- void tagsChanged();
- void streamsChanged();
- void seekableChanged(bool);
- void error(int error, const QString &errorString);
- void invalidMedia();
- void playbackRateChanged(qreal);
-
-private slots:
- void getStreamsInfo();
- void setSeekable(bool);
- void finishVideoOutputChange();
- void updateVideoRenderer();
- void updateVideoResolutionTag();
- void updateVolume();
- void updateMuted();
- void updateDuration();
-
-private:
- static void playbinNotifySource(GObject *o, GParamSpec *p, gpointer d);
- static void handleVolumeChange(GObject *o, GParamSpec *p, gpointer d);
- static void handleMutedChange(GObject *o, GParamSpec *p, gpointer d);
-#if !GST_CHECK_VERSION(1,0,0)
- static void insertColorSpaceElement(GstElement *element, gpointer data);
-#endif
- static void handleElementAdded(GstBin *bin, GstElement *element, QGstreamerPlayerSession *session);
- static void handleStreamsChange(GstBin *bin, gpointer user_data);
- static GstAutoplugSelectResult handleAutoplugSelect(GstBin *bin, GstPad *pad, GstCaps *caps, GstElementFactory *factory, QGstreamerPlayerSession *session);
-
- void processInvalidMedia(QMediaPlayer::Error errorCode, const QString& errorString);
-
- void removeVideoBufferProbe();
- void addVideoBufferProbe();
- void removeAudioBufferProbe();
- void addAudioBufferProbe();
- void flushVideoProbes();
- void resumeVideoProbes();
-
- QNetworkRequest m_request;
- QMediaPlayer::State m_state;
- QMediaPlayer::State m_pendingState;
- QGstreamerBusHelper* m_busHelper;
- GstElement* m_playbin;
-
- GstElement* m_videoSink;
-
- GstElement* m_videoOutputBin;
- GstElement* m_videoIdentity;
-#if !GST_CHECK_VERSION(1,0,0)
- GstElement* m_colorSpace;
- bool m_usingColorspaceElement;
-#endif
- GstElement* m_pendingVideoSink;
- GstElement* m_nullVideoSink;
-
- GstElement* m_audioSink;
- GstElement* m_volumeElement;
-
- GstBus* m_bus;
- QObject *m_videoOutput;
- QGstreamerVideoRendererInterface *m_renderer;
-
-#if QT_CONFIG(gstreamer_app)
- QGstAppSrc *m_appSrc;
-#endif
-
- QMap<QByteArray, QVariant> m_tags;
- QList< QMap<QString,QVariant> > m_streamProperties;
- QList<QMediaStreamsControl::StreamType> m_streamTypes;
- QMap<QMediaStreamsControl::StreamType, int> m_playbin2StreamOffset;
-
- QGstreamerVideoProbeControl *m_videoProbe;
- QGstreamerAudioProbeControl *m_audioProbe;
-
- int m_volume;
- qreal m_playbackRate;
- bool m_muted;
- bool m_audioAvailable;
- bool m_videoAvailable;
- bool m_seekable;
-
- mutable qint64 m_lastPosition;
- qint64 m_duration;
- int m_durationQueries;
-
- bool m_displayPrerolledFrame;
-
- enum SourceType
- {
- UnknownSrc,
- SoupHTTPSrc,
- UDPSrc,
- MMSSrc,
- RTSPSrc,
- };
- SourceType m_sourceType;
- bool m_everPlayed;
- bool m_isLiveSource;
-
- gulong pad_probe_id;
-};
-
-QT_END_NAMESPACE
-
-#endif // QGSTREAMERPLAYERSESSION_H
diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerstreamscontrol.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerstreamscontrol.cpp
index 99caa2ae0..4f5c3f0b2 100644
--- a/src/plugins/gstreamer/mediaplayer/qgstreamerstreamscontrol.cpp
+++ b/src/plugins/gstreamer/mediaplayer/qgstreamerstreamscontrol.cpp
@@ -38,7 +38,7 @@
****************************************************************************/
#include "qgstreamerstreamscontrol.h"
-#include "qgstreamerplayersession.h"
+#include <private/qgstreamerplayersession_p.h>
QGstreamerStreamsControl::QGstreamerStreamsControl(QGstreamerPlayerSession *session, QObject *parent)
:QMediaStreamsControl(parent), m_session(session)