Commit 7afc3bf9 authored by Val Doroshchuk's avatar Val Doroshchuk

Split GstreamerMediaPlayer to GstreamerPipeline and GstreamerPlaybin

parent f2d2bcbe
...@@ -2,10 +2,19 @@ TARGET = QtGstreamerExtras ...@@ -2,10 +2,19 @@ TARGET = QtGstreamerExtras
QT += multimediagsttools-private QT += multimediagsttools-private
include(playback/playback.pri)
CONFIG += simd optimize_full CONFIG += simd optimize_full
PUBLIC_HEADERS += \
qgstreamerpipeline.h \
qgstreamerplaybin.h
PRIVATE_HEADERS += \
qgstreamerpipeline_p.h
SOURCES += \
qgstreamerpipeline.cpp \
qgstreamerplaybin.cpp
HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS
load(qt_module) load(qt_module)
INCLUDEPATH += playback
PUBLIC_HEADERS += \
playback/qgstreamermediaplayer.h
SOURCES += \
playback/qgstreamermediaplayer.cpp
/****************************************************************************
**
** 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 "qgstreamermediaplayer.h"
#include <private/qgstreamerplayercontrol_p.h>
#include <private/qgstreamerplayersession_p.h>
#include <QPointer>
#include <QMediaService>
QT_BEGIN_NAMESPACE
class QGstreamerMediaPlayerPrivate : public QObject
{
Q_DECLARE_PUBLIC(QGstreamerMediaPlayer)
public:
QGstreamerMediaPlayerPrivate(QGstreamerMediaPlayer *parent)
: QObject(parent)
, q_ptr(parent)
{
}
void setMediaObject(QMediaObject *src);
public Q_SLOTS:
void updateMediaObject();
QPointer<QObject> source;
QPointer<QMediaObject> mediaObject;
QPointer<QGstreamerPlayerSession> session;
QString pipeline;
QString videoSink;
bool showText = false;
QUrl textUri;
QString textFont;
QGstreamerMediaPlayer *q_ptr = nullptr;
};
void QGstreamerMediaPlayerPrivate::updateMediaObject()
{
Q_Q(QGstreamerMediaPlayer);
QMediaObject *obj = qobject_cast<QMediaObject*>(source->property("mediaObject").value<QObject*>());
q->setMediaObject(obj);
}
QGstreamerMediaPlayer::QGstreamerMediaPlayer(QMediaObject *player, QObject *parent)
: QGstreamerMediaPlayer(parent)
{
setMediaObject(player);
}
QGstreamerMediaPlayer::QGstreamerMediaPlayer(QObject *parent)
: QObject(parent)
, d_ptr(new QGstreamerMediaPlayerPrivate(this))
{
}
QGstreamerMediaPlayer::~QGstreamerMediaPlayer()
{
Q_D(QGstreamerMediaPlayer);
d->session.clear();
}
QObject *QGstreamerMediaPlayer::source() const
{
return d_func()->source.data();
}
void QGstreamerMediaPlayer::setSource(QObject *src)
{
Q_D(QGstreamerMediaPlayer);
if (d->source == src)
return;
if (d->source)
disconnect(d->source.data(), 0, d, SLOT(updateMediaObject()));
d->source = src;
if (d->source) {
const QMetaObject *metaObject = d->source->metaObject();
int mediaObjectPropertyIndex = metaObject->indexOfProperty("mediaObject");
if (mediaObjectPropertyIndex != -1) {
const QMetaProperty mediaObjectProperty = metaObject->property(mediaObjectPropertyIndex);
if (mediaObjectProperty.hasNotifySignal()) {
QMetaMethod method = mediaObjectProperty.notifySignal();
QMetaObject::connect(d->source.data(), method.methodIndex(),
d, d->metaObject()->indexOfSlot("updateMediaObject()"),
Qt::DirectConnection, 0);
}
}
}
d->updateMediaObject();
emit sourceChanged();
}
QMediaObject *QGstreamerMediaPlayer::mediaObject() const
{
return d_func()->mediaObject.data();
}
void QGstreamerMediaPlayer::setMediaObject(QMediaObject *src)
{
Q_D(QGstreamerMediaPlayer);
if (d->mediaObject == src)
return;
d->mediaObject.clear();
auto service = src ? src->service() : nullptr;
if (!service)
return;
auto control = qobject_cast<QGstreamerPlayerControl *>(service->requestControl(QMediaPlayerControl_iid));
d->session = control ? control->session() : nullptr;
if (!d->session)
return;
connect(d->session, &QGstreamerPlayerSession::pipelineDescChanged,
this, &QGstreamerMediaPlayer::pipelineChanged);
connect(d->session, &QGstreamerPlayerSession::videoSinkDescChanged,
this, &QGstreamerMediaPlayer::videoSinkChanged);
connect(d->session, &QGstreamerPlayerSession::showTextChanged,
this, &QGstreamerMediaPlayer::showTextChanged);
connect(d->session, &QGstreamerPlayerSession::textUriChanged,
this, &QGstreamerMediaPlayer::textUriChanged);
connect(d->session, &QGstreamerPlayerSession::textFontChanged,
this, &QGstreamerMediaPlayer::textFontChanged);
connect(d->session, &QGstreamerPlayerSession::audioStreamsCountChanged,
this, &QGstreamerMediaPlayer::audioStreamsCountChanged);
connect(d->session, &QGstreamerPlayerSession::audioStreamChanged,
this, &QGstreamerMediaPlayer::audioStreamChanged);
connect(d->session, &QGstreamerPlayerSession::audioStreamPropertiesChanged,
this, &QGstreamerMediaPlayer::audioStreamPropertiesChanged);
connect(d->session, &QGstreamerPlayerSession::videoStreamsCountChanged,
this, &QGstreamerMediaPlayer::videoStreamsCountChanged);
connect(d->session, &QGstreamerPlayerSession::videoStreamChanged,
this, &QGstreamerMediaPlayer::videoStreamChanged);
connect(d->session, &QGstreamerPlayerSession::videoStreamPropertiesChanged,
this, &QGstreamerMediaPlayer::videoStreamPropertiesChanged);
connect(d->session, &QGstreamerPlayerSession::textStreamsCountChanged,
this, &QGstreamerMediaPlayer::textStreamsCountChanged);
connect(d->session, &QGstreamerPlayerSession::textStreamChanged,
this, &QGstreamerMediaPlayer::textStreamChanged);
connect(d->session, &QGstreamerPlayerSession::textStreamPropertiesChanged,
this, &QGstreamerMediaPlayer::textStreamPropertiesChanged);
connect(d->session, &QGstreamerPlayerSession::streamsChanged,
this, &QGstreamerMediaPlayer::streamsChanged);
// In case if these values've been applied
// before mediaObject is available.
setPipeline(d->pipeline);
setVideoSink(d->videoSink);
setShowText(d->showText);
setTextUri(d->textUri);
setTextFont(d->textFont);
d->mediaObject = src;
emit mediaObjectChanged();
}
QString QGstreamerMediaPlayer::pipeline() const
{
Q_D(const QGstreamerMediaPlayer);
return d->session ? d->session->pipelineDesc() : d->pipeline;
}
void QGstreamerMediaPlayer::setPipeline(const QString &desc)
{
Q_D(QGstreamerMediaPlayer);
d->pipeline = desc;
if (d->session)
d->session->setPipelineDesc(desc);
}
QString QGstreamerMediaPlayer::videoSink() const
{
Q_D(const QGstreamerMediaPlayer);
return d->session ? d->session->videoSinkDesc() : d->videoSink;
}
void QGstreamerMediaPlayer::setVideoSink(const QString &name)
{
Q_D(QGstreamerMediaPlayer);
d->videoSink = name;
if (d->session)
d->session->setVideoSinkDesc(name);
}
bool QGstreamerMediaPlayer::showText() const
{
Q_D(const QGstreamerMediaPlayer);
return d->session ? d->session->showText() : d->showText;
}
void QGstreamerMediaPlayer::setShowText(bool show)
{
Q_D(QGstreamerMediaPlayer);
d->showText = show;
if (d->session)
d->session->setShowText(show);
}
QUrl QGstreamerMediaPlayer::textUri() const
{
Q_D(const QGstreamerMediaPlayer);
return d->session ? d->session->textUri() : d->textUri;
}
void QGstreamerMediaPlayer::setTextUri(const QUrl &url)
{
Q_D(QGstreamerMediaPlayer);
d->textUri = url;
setShowText(!url.isEmpty());
if (d->session)
d->session->setTextUri(url);
}
QString QGstreamerMediaPlayer::textFont() const
{
Q_D(const QGstreamerMediaPlayer);
return d->session ? d->session->textFont() : d->textFont;
}
void QGstreamerMediaPlayer::setTextFont(const QString &str)
{
Q_D(QGstreamerMediaPlayer);
d->textFont = str;
if (d->session)
d->session->setTextFont(str);
}
int QGstreamerMediaPlayer::audioStreamsCount() const
{
Q_D(const QGstreamerMediaPlayer);
return d->session ? d->session->audioStreamsCount() : 0;
}
int QGstreamerMediaPlayer::videoStreamsCount() const
{
Q_D(const QGstreamerMediaPlayer);
return d->session ? d->session->videoStreamsCount() : 0;
}
int QGstreamerMediaPlayer::textStreamsCount() const
{
Q_D(const QGstreamerMediaPlayer);
return d->session ? d->session->textStreamsCount() : 0;
}
int QGstreamerMediaPlayer::audioStream() const
{
Q_D(const QGstreamerMediaPlayer);
return d->session ? d->session->audioStream() : -1;
}
void QGstreamerMediaPlayer::setAudioStream(int i)
{
Q_D(QGstreamerMediaPlayer);
if (d->session)
d->session->setAudioStream(i);
}
QVariantMap QGstreamerMediaPlayer::audioStreamProperties(int i)
{
Q_D(const QGstreamerMediaPlayer);
return d->session ? d->session->audioStreamProperties(i) : QVariantMap();
}
int QGstreamerMediaPlayer::videoStream() const
{
Q_D(const QGstreamerMediaPlayer);
return d->session ? d->session->videoStream() : -1;
}
void QGstreamerMediaPlayer::setVideoStream(int i)
{
Q_D(QGstreamerMediaPlayer);
if (d->session)
d->session->setVideoStream(i);
}
QVariantMap QGstreamerMediaPlayer::videoStreamProperties(int i)
{
Q_D(const QGstreamerMediaPlayer);
return d->session ? d->session->videoStreamProperties(i) : QVariantMap();
}
int QGstreamerMediaPlayer::textStream() const
{
Q_D(const QGstreamerMediaPlayer);
return d->session ? d->session->textStream() : -1;
}
void QGstreamerMediaPlayer::setTextStream(int i)
{
Q_D(QGstreamerMediaPlayer);
if (d->session)
d->session->setTextStream(i);
}
QVariantMap QGstreamerMediaPlayer::textStreamProperties(int i)
{
Q_D(const QGstreamerMediaPlayer);
return d->session ? d->session->textStreamProperties(i) : QVariantMap();
}
void QGstreamerMediaPlayer::set(const QString &elementName, const QVariantMap& map)
{
Q_D(QGstreamerMediaPlayer);
if (d->session)
d->session->setGstProperties(elementName, map);
}
#include "moc_qgstreamermediaplayer.cpp"
QT_END_NAMESPACE
/****************************************************************************
**
** 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 "qgstreamerpipeline_p.h"
#include <private/qgstvideorenderersink_p.h>
#include <QMediaObject>
#include <QtCore/qmetaobject.h>
#include <QDebug>
QT_BEGIN_NAMESPACE
QGstreamerPipelinePrivate::QGstreamerPipelinePrivate(QGstreamerPipeline *pipeline)
: q_ptr(pipeline)
{
}
QGstreamerPipelinePrivate::~QGstreamerPipelinePrivate()
{
if (pipeline)
gst_object_unref(GST_OBJECT(pipeline));
}
void QGstreamerPipelinePrivate::updateMediaObject()
{
Q_Q(QGstreamerPipeline);
QMediaObject *obj = qobject_cast<QMediaObject*>(source->property("mediaObject").value<QObject*>());
q->setMediaObject(obj);
}
static GstElement *parseDesc(const QString &name)
{
GError *error = NULL;
GstElement *element = gst_parse_launch(name.toLatin1().constData(), &error);
if (error) {
g_printerr("ERROR: %s: %s\n", name.toLatin1().constData(), GST_STR_NULL(error->message));
g_clear_error(&error);
}
return element;
}
void QGstreamerPipelinePrivate::updatePipeline()
{
Q_Q(QGstreamerPipeline);
if (!renderer || !renderer->isReady())
return;
if (!pendingPipelineDesc.isEmpty()) {
QGstVideoRendererSink::setSurface(renderer->surface());
pipeline = parseDesc(pendingPipelineDesc);
if (pipeline) {
pipelineDesc = pendingPipelineDesc;
pendingPipelineDesc.clear();
emit q->pipelineChanged();
}
} else if (!pendingVideoSinkDesc.isEmpty()) {
GstElement *videoSink = parseDesc(pendingVideoSinkDesc);
if (videoSink) {
videoSinkDesc = pendingVideoSinkDesc;
pendingVideoSinkDesc.clear();
renderer->setVideoSink(videoSink);
emit q->videoSinkChanged();
}
}
}
QGstreamerPipeline::QGstreamerPipeline(QGstreamerPipelinePrivate *d, QObject *parent)
: QObject(parent)
, d_ptr(d)
{
}
QGstreamerPipeline::~QGstreamerPipeline()
{
delete d_ptr;
}
QObject *QGstreamerPipeline::source() const
{
return d_func()->source.data();
}
void QGstreamerPipeline::setSource(QObject *src)
{
Q_D(QGstreamerPipeline);
if (d->source == src)
return;
if (d->source)
disconnect(d->source.data(), 0, d, SLOT(updateMediaObject()));
d->source = src;
if (d->source) {
const QMetaObject *metaObject = d->source->metaObject();
int mediaObjectPropertyIndex = metaObject->indexOfProperty("mediaObject");
if (mediaObjectPropertyIndex != -1) {
const QMetaProperty mediaObjectProperty = metaObject->property(mediaObjectPropertyIndex);
if (mediaObjectProperty.hasNotifySignal()) {
QMetaMethod method = mediaObjectProperty.notifySignal();
QMetaObject::connect(d->source.data(), method.methodIndex(),
d, d->metaObject()->indexOfSlot("updateMediaObject()"),
Qt::DirectConnection, 0);
}
}
}
d->updateMediaObject();
emit sourceChanged();
}
QMediaObject *QGstreamerPipeline::mediaObject() const
{
return d_func()->mediaObject.data();
}
void QGstreamerPipeline::setMediaObject(QMediaObject *src)
{
Q_D(QGstreamerPipeline);
if (d->mediaObject == src)
return;
d->mediaObject = src;
emit mediaObjectChanged();
}
QString QGstreamerPipeline::pipeline() const
{
return d_func()->pipelineDesc;
}
void QGstreamerPipeline::setPipeline(const QString &desc)
{
Q_D(QGstreamerPipeline);
d->pendingPipelineDesc = desc;
if (d->pipelineDesc == desc)
return;
d->updatePipeline();
}
QString QGstreamerPipeline::videoSink() const