Commit 9fffe22d authored by Val Doroshchuk's avatar Val Doroshchuk

Rename to Playbin

parent 32d64263
...@@ -2,7 +2,16 @@ TARGET = QtGstreamerExtras ...@@ -2,7 +2,16 @@ TARGET = QtGstreamerExtras
QT = multimediagsttools_private QT = multimediagsttools_private
include(playback/playback.pri) PUBLIC_HEADERS += \
qgstreamerpipeline.h \
qgstreamerplaybin.h
PRIVATE_HEADERS += \
qgstreamerpipeline_p.h
SOURCES += \
qgstreamerplaybin.cpp \
qgstreamerpipeline.cpp
CONFIG += simd optimize_full CONFIG += simd optimize_full
......
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 "qgstreamerpipeline.h"
#include "qgstreamerpipeline_p.h"
#include <private/qgstreamervideorenderer_p.h>
#include <private/qgstreamerplayersession_p.h>
#include <QMediaService>
QT_BEGIN_NAMESPACE
void QGstreamerPipelinePrivate::updateMediaObject()
{
Q_Q(QGstreamerPipeline);
QMediaObject *obj = qobject_cast<QMediaObject*>(source->property("mediaObject").value<QObject*>());
q->setMediaObject(obj);
}
QGstreamerPipeline::QGstreamerPipeline(QGstreamerPipelinePrivate *d, QMediaObject *media, QObject *parent)
: QObject(parent)
, d_ptr(d)
{
setMediaObject(media);
}
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);
auto service = src ? src->service() : nullptr;
if (!service)
return;
auto control = qobject_cast<QGstreamerPlayerControl *>(service->requestControl(QMediaPlayerControl_iid));
d->session = control ? control->session() : nullptr;
d->mediaObject = src;
emit mediaObjectChanged();
}
template <class T>
static void setGstProperty(GstElement *element, const QString &name, T v)
{
g_object_set(G_OBJECT(element), name.toLatin1().constData(), v, NULL);
}
bool QGstreamerPipeline::set(const QString &elementName, const QVariantMap& map)
{
Q_D(QGstreamerPipeline);
GstElement *element = nullptr;
if (elementName == QLatin1String("videoSink"))
element = (d->session && d->session->renderer()) ? d->session->renderer()->videoSink() : nullptr;
else if (d->session->pipeline())
element = gst_bin_get_by_name(GST_BIN(d->session->pipeline()), elementName.toLatin1().constData());
if (!element) {
qWarning() << "Could not find element by name:" << elementName;
if (d->session->pipeline()) {
qWarning() << "Available elements:";
qWarning() << " " << "videoSink";
GstIterator *children = gst_bin_iterate_recurse(GST_BIN(d->session->pipeline()));
gst_iterator_foreach(children, [](const GValue *item, gpointer) {
GstElement *element = GST_ELEMENT(g_value_get_object(item));
qWarning() << " " << GST_ELEMENT_NAME(element);
}, nullptr);
gst_iterator_free(children);
} else {
qWarning() << "No pipeline available";
}
return false;
}
for (auto it = map.begin(); it != map.end(); ++it) {
QString name = it.key();
QVariant value = it.value();
switch (value.type()) {
case QMetaType::Int:
setGstProperty(element, name, value.toInt());
break;
case QMetaType::Bool:
setGstProperty(element, name, value.toBool());
break;
case QMetaType::Double:
setGstProperty(element, name, value.toDouble());
break;
case QMetaType::QString:
setGstProperty(element, name, value.toString().toUtf8().constData());
break;
default:
break;
}
}
return true;
}
#include "moc_qgstreamerpipeline.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$
**
****************************************************************************/
#ifndef QGSTREAMERPIPELINE_H
#define QGSTREAMERPIPELINE_H
#include <QtMultimedia/qtmultimediaglobal.h>
#include <QVariantMap>
#include <QUrl>
QT_BEGIN_NAMESPACE
class QMediaObject;
class QGstreamerPipelinePrivate;
class Q_MULTIMEDIA_EXPORT QGstreamerPipeline : public QObject
{
Q_OBJECT
Q_PROPERTY(QObject* source READ source WRITE setSource NOTIFY sourceChanged)
Q_PROPERTY(QMediaObject* mediaObject READ mediaObject NOTIFY mediaObjectChanged SCRIPTABLE false DESIGNABLE false)
public:
~QGstreamerPipeline();
QObject *source() const;
void setSource(QObject *source);
QMediaObject *mediaObject() const;
void setMediaObject(QMediaObject *source);
Q_INVOKABLE bool set(const QString &elementName, const QVariantMap& map);
Q_SIGNALS:
void sourceChanged();
void mediaObjectChanged();
protected:
QGstreamerPipeline(QGstreamerPipelinePrivate *d,
QMediaObject *player = nullptr, QObject *parent = nullptr);
QGstreamerPipelinePrivate *d_ptr = nullptr;
private:
Q_DISABLE_COPY(QGstreamerPipeline)
Q_DECLARE_PRIVATE(QGstreamerPipeline)
};
QT_END_NAMESPACE
#endif // QGSTREAMERPIPELINE_H
/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QGSTREAMERPIPELINE_P_H
#define QGSTREAMERPIPELINE_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <QPointer>
QT_BEGIN_NAMESPACE
class QMediaObject;
class QGstreamerPlayerSession;
class QGstreamerPipeline;
class QGstreamerPipelinePrivate : public QObject
{
Q_OBJECT
Q_DECLARE_PUBLIC(QGstreamerPipeline)
public:
QGstreamerPipelinePrivate(QGstreamerPipeline *q) : q_ptr(q) { }
~QGstreamerPipelinePrivate() { }
public Q_SLOTS:
void updateMediaObject();
protected:
QPointer<QObject> source;
QPointer<QMediaObject> mediaObject;
QGstreamerPlayerSession *session = nullptr;
QGstreamerPipeline *q_ptr = nullptr;
};
QT_END_NAMESPACE
#endif // QGSTREAMERPIPELINE_P_H
...@@ -37,24 +37,20 @@ ...@@ -37,24 +37,20 @@
** **
****************************************************************************/ ****************************************************************************/
#ifndef QGSTREAMERMEDIAPLAYER_H #ifndef QGSTREAMERPLAYBIN_H
#define QGSTREAMERMEDIAPLAYER_H #define QGSTREAMERPLAYBIN_H
#include <QObject> #include "qgstreamerpipeline.h"
#include <QVariantMap> #include <QVariantMap>
#include <QtMultimedia/qtmultimediaglobal.h>
#include <QUrl> #include <QUrl>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QMediaObject; class QMediaObject;
class QGstreamerMediaPlayerPrivate; class QGstreamerPlaybinPrivate;
class Q_MULTIMEDIA_EXPORT QGstreamerMediaPlayer : public QObject class Q_MULTIMEDIA_EXPORT QGstreamerPlaybin : public QGstreamerPipeline
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QObject* source READ source WRITE setSource NOTIFY sourceChanged)
Q_PROPERTY(QMediaObject* mediaObject READ mediaObject NOTIFY mediaObjectChanged SCRIPTABLE false DESIGNABLE false)
Q_PROPERTY(QString pipeline READ pipeline WRITE setPipeline NOTIFY pipelineChanged)
Q_PROPERTY(QString videoSink READ videoSink WRITE setVideoSink NOTIFY videoSinkChanged) Q_PROPERTY(QString videoSink READ videoSink WRITE setVideoSink NOTIFY videoSinkChanged)
Q_PROPERTY(bool showText READ showText WRITE setShowText NOTIFY showTextChanged) Q_PROPERTY(bool showText READ showText WRITE setShowText NOTIFY showTextChanged)
Q_PROPERTY(QUrl textUri READ textUri WRITE setTextUri NOTIFY textUriChanged) Q_PROPERTY(QUrl textUri READ textUri WRITE setTextUri NOTIFY textUriChanged)
...@@ -67,18 +63,9 @@ class Q_MULTIMEDIA_EXPORT QGstreamerMediaPlayer : public QObject ...@@ -67,18 +63,9 @@ class Q_MULTIMEDIA_EXPORT QGstreamerMediaPlayer : public QObject
Q_PROPERTY(int textStream READ textStream WRITE setTextStream NOTIFY textStreamChanged) Q_PROPERTY(int textStream READ textStream WRITE setTextStream NOTIFY textStreamChanged)
public: public:
QGstreamerMediaPlayer(QMediaObject *player, QObject *parent = nullptr); QGstreamerPlaybin(QMediaObject *player, QObject *parent = nullptr);
QGstreamerMediaPlayer(QObject *parent = nullptr); QGstreamerPlaybin(QObject *parent = nullptr);
~QGstreamerMediaPlayer(); ~QGstreamerPlaybin();
QObject *source() const;
void setSource(QObject *source);
QMediaObject *mediaObject() const;
void setMediaObject(QMediaObject *source);
QString pipeline() const;
void setPipeline(const QString &name);
QString videoSink() const; QString videoSink() const;
void setVideoSink(const QString &name); void setVideoSink(const QString &name);
...@@ -107,12 +94,7 @@ public: ...@@ -107,12 +94,7 @@ public:
void setTextStream(int i); void setTextStream(int i);
Q_INVOKABLE QVariantMap textStreamProperties(int i); Q_INVOKABLE QVariantMap textStreamProperties(int i);
Q_INVOKABLE bool set(const QString &elementName, const QVariantMap& map);
Q_SIGNALS: Q_SIGNALS:
void sourceChanged();
void mediaObjectChanged();
void pipelineChanged();
void videoSinkChanged(); void videoSinkChanged();
void showTextChanged(); void showTextChanged();
void textUriChanged(); void textUriChanged();
...@@ -131,12 +113,10 @@ Q_SIGNALS: ...@@ -131,12 +113,10 @@ Q_SIGNALS:
void textStreamPropertiesChanged(); void textStreamPropertiesChanged();
private: private:
Q_DISABLE_COPY(QGstreamerMediaPlayer) Q_DISABLE_COPY(QGstreamerPlaybin)
Q_DECLARE_PRIVATE(QGstreamerMediaPlayer) Q_DECLARE_PRIVATE(QGstreamerPlaybin)
QGstreamerMediaPlayerPrivate *d_ptr = nullptr;
}; };
QT_END_NAMESPACE QT_END_NAMESPACE
#endif // QGSTREAMERMEDIAPLAYER_H #endif // QGSTREAMERPLAYBIN_H
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
#include <QtQml/qqmlengine.h> #include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h> #include <QtQml/qqmlcomponent.h>
#include "qgstreamermediaplayer.h" #include "qgstreamerplaybin.h"
#include "qtransparentrectangle_p.h" #include "qtransparentrectangle_p.h"
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
...@@ -58,7 +58,7 @@ public: ...@@ -58,7 +58,7 @@ public:
{ {
Q_ASSERT(QLatin1String(uri) == QLatin1String("QtGstreamerExtras")); Q_ASSERT(QLatin1String(uri) == QLatin1String("QtGstreamerExtras"));
qmlRegisterType<QGstreamerMediaPlayer>(uri, 5, 12, "GstreamerMediaPlayer"); qmlRegisterType<QGstreamerPlaybin>(uri, 5, 12, "Playbin");
qmlRegisterType<QTransparentRectangle>(uri, 5, 12, "TransparentRectangle"); qmlRegisterType<QTransparentRectangle>(uri, 5, 12, "TransparentRectangle");
} }
}; };
......
TEMPLATE = subdirs TEMPLATE = subdirs
SUBDIRS += \ SUBDIRS += \
qml \ qml \
qgstreamermediaplayer qgstreamerplaybin
CONFIG += testcase CONFIG += testcase
TARGET = tst_qgstreamermediaplayer TARGET = tst_qgstreamerplaybin
QT += network gstreamerextras-private multimedia-private testlib QT += network gstreamerextras-private multimedia-private testlib
SOURCES += tst_qgstreamermediaplayer.cpp SOURCES += tst_qgstreamerplaybin.cpp
RESOURCES += testdata.qrc RESOURCES += testdata.qrc
\ No newline at end of file
...@@ -29,12 +29,12 @@ ...@@ -29,12 +29,12 @@
#include <QtTest/QtTest> #include <QtTest/QtTest>
#include <QMediaPlayer> #include <QMediaPlayer>
#include <QGstreamerMediaPlayer> #include <QGstreamerPlaybin>
#include <QAbstractVideoSurface> #include <QAbstractVideoSurface>
QT_USE_NAMESPACE QT_USE_NAMESPACE
class tst_QGstreamerMediaPlayer: public QObject class tst_QGstreamerPlaybin: public QObject
{ {
Q_OBJECT Q_OBJECT
...@@ -43,7 +43,6 @@ public slots: ...@@ -43,7 +43,6 @@ public slots:
void cleanup(); void cleanup();
private slots: private slots:
void testPipeline();
void testVideoSink(); void testVideoSink();
void testShowText(); void testShowText();
void testTextUri(); void testTextUri();
...@@ -58,7 +57,7 @@ private slots: ...@@ -58,7 +57,7 @@ private slots:
private: private:
QMediaPlayer *mediaPlayer = nullptr; QMediaPlayer *mediaPlayer = nullptr;
QGstreamerMediaPlayer *control = nullptr; QGstreamerPlaybin *control = nullptr;
}; };
struct Surface : QAbstractVideoSurface struct Surface : QAbstractVideoSurface
...@@ -80,23 +79,23 @@ struct Surface : QAbstractVideoSurface ...@@ -80,23 +79,23 @@ struct Surface : QAbstractVideoSurface
bool present(const QVideoFrame &) override { return true; } bool present(const QVideoFrame &) override { return true; }
}; };
void tst_QGstreamerMediaPlayer::init() void tst_QGstreamerPlaybin::init()
{ {
mediaPlayer = new QMediaPlayer; mediaPlayer = new QMediaPlayer;
mediaPlayer->setMedia(QUrl("qrc:/testdata/colors.mp4")); mediaPlayer->setMedia(QUrl("qrc:/testdata/colors.mp4"));
control = new QGstreamerMediaPlayer(mediaPlayer); control = new QGstreamerPlaybin(mediaPlayer);
Surface *s = new Surface(mediaPlayer); Surface *s = new Surface(mediaPlayer);
mediaPlayer->setVideoOutput(s); mediaPlayer->setVideoOutput(s);
} }
void tst_QGstreamerMediaPlayer::cleanup() void tst_QGstreamerPlaybin::cleanup()
{ {
delete mediaPlayer; delete mediaPlayer;
} }
void tst_QGstreamerMediaPlayer::testVideoSink() void tst_QGstreamerPlaybin::testVideoSink()
{ {
QSignalSpy spy(control, &QGstreamerMediaPlayer::videoSinkChanged); QSignalSpy spy(control, &QGstreamerPlaybin::videoSinkChanged);
QVERIFY(control->videoSink().isEmpty()); QVERIFY(control->videoSink().isEmpty());
QString sink = "xvimagesink hue=100"; QString sink = "xvimagesink hue=100";
...@@ -105,20 +104,9 @@ void tst_QGstreamerMediaPlayer::testVideoSink() ...@@ -105,20 +104,9 @@ void tst_QGstreamerMediaPlayer::testVideoSink()
QCOMPARE(sink, control->videoSink()); QCOMPARE(sink, control->videoSink());
} }
void tst_QGstreamerMediaPlayer::testPipeline() void tst_QGstreamerPlaybin::testShowText()
{ {
QSignalSpy spy(control, &QGstreamerMediaPlayer::pipelineChanged); QSignalSpy spy(control, &QGstreamerPlaybin::showTextChanged);
QVERIFY(control->pipeline().isEmpty());
QString p = "videotestsrc ! autovideosink";
control->setPipeline(p);
QTRY_COMPARE(spy.count(), 1);
QCOMPARE(p, control->pipeline());
}
void tst_QGstreamerMediaPlayer::testShowText()
{
QSignalSpy spy(control, &QGstreamerMediaPlayer::showTextChanged);
QVERIFY(!control->showText()); QVERIFY(!control->showText());
control->setShowText(true); control->setShowText(true);
...@@ -132,9 +120,9 @@ void tst_QGstreamerMediaPlayer::testShowText() ...@@ -132,9 +120,9 @@ void tst_QGstreamerMediaPlayer::testShowText()
QCOMPARE(spy.count(), 2); QCOMPARE(spy.count(), 2);
} }
void tst_QGstreamerMediaPlayer::testTextUri() void tst_QGstreamerPlaybin::testTextUri()
{ {
QSignalSpy spy(control, &QGstreamerMediaPlayer::textUriChanged); QSignalSpy spy(control, &QGstreamerPlaybin::textUriChanged);
QCOMPARE(control->textUri(), QUrl()); QCOMPARE(control->textUri(), QUrl());
QUrl text("text.srt"); QUrl text("text.srt");
...@@ -144,9 +132,9 @@ void tst_QGstreamerMediaPlayer::testTextUri() ...@@ -144,9 +132,9 @@ void tst_QGstreamerMediaPlayer::testTextUri()
QCOMPARE(spy.count(), 1); QCOMPARE(spy.count(), 1);
} }
void tst_QGstreamerMediaPlayer::testTextFont() void tst_QGstreamerPlaybin::testTextFont()
{ {
QSignalSpy spy(control, &QGstreamerMediaPlayer::textFontChanged); QSignalSpy spy(control, &QGstreamerPlaybin::textFontChanged);
QCOMPARE(control->textFont(), QString()); QCOMPARE(control->textFont(), QString());
QString font = "Sans, 18"; QString font = "Sans, 18";
...@@ -155,36 +143,36 @@ void tst_QGstreamerMediaPlayer::testTextFont() ...@@ -155,36 +143,36 @@ void tst_QGstreamerMediaPlayer::testTextFont()
QCOMPARE(spy.count(), 1); QCOMPARE(spy.count(), 1);
} }
void tst_QGstreamerMediaPlayer::testAudioStreams() void tst_QGstreamerPlaybin::testAudioStreams()
{ {
QSignalSpy spy(control, &QGstreamerMediaPlayer::audioStreamsCountChanged); QSignalSpy spy(control, &QGstreamerPlaybin::audioStreamsCountChanged);
QCOMPARE(control->audioStreamsCount(), 0); QCOMPARE(control->audioStreamsCount(), 0);
QTRY_VERIFY(spy.count() > 0); QTRY_VERIFY(spy.count() > 0);
QCOMPARE(control->audioStreamsCount(), 1); QCOMPARE(control->audioStreamsCount(), 1);