[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: kdereview/phonon/gstreamer
From: Jens Bache-Wiig <jbache () trolltech ! com>
Date: 2008-01-17 11:19:17
Message-ID: 1200568757.850593.6788.nullmailer () svn ! kde ! org
[Download RAW message or body]
SVN commit 762604 by jbache:
Reduced latency on gstreamer messages
We now spin a glib eventloop in the backend to
signal Qt directly about state changes rather
than polling the bus. This should result in
somewhat improved latency and battery consumption.
M +45 -23 backend.cpp
M +6 -5 backend.h
M +4 -0 medianode.h
M +2 -1 mediaobject.cpp
M +20 -4 message.cpp
M +5 -1 message.h
--- trunk/kdereview/phonon/gstreamer/backend.cpp #762603:762604
@@ -44,14 +44,15 @@
class MediaNode;
Backend::Backend(QObject *parent, const QVariantList &)
- : QObject(parent)
- , m_busIntervalTimer(0)
+ : QThread(parent)
, m_deviceManager(0)
, m_effectManager(0)
, m_debugLevel(Warning)
, m_isValid(false)
+ , loop(0)
{
gst_init (0, 0); //init gstreamer: must be called before any gst-related \
functions + qRegisterMetaType<Message>("Message");
setProperty("identifier", QLatin1String("phonon_gstreamer"));
setProperty("backendName", QLatin1String("Gstreamer"));
@@ -71,14 +72,45 @@
m_deviceManager = new DeviceManager(this);
m_effectManager = new EffectManager(this);
- m_busIntervalTimer = new QTimer(this);
- m_busIntervalTimer->setInterval(100);
- connect(m_busIntervalTimer, SIGNAL(timeout()), this, SLOT(handleBusMessages()));
+ start();
}
-Backend::~Backend() {}
+Backend::~Backend()
+{
+ g_main_loop_quit (loop);
+ // Wait for thread to finish
+ QTime timeOut;
+ timeOut.start();
+ while (isRunning() && timeOut.elapsed() < 2000)
+ wait(1);
+ g_main_loop_unref (loop);
+ loop = 0;
+}
+gboolean Backend::busCall(GstBus *bus, GstMessage *msg, gpointer data)
+{
+ Q_UNUSED(bus);
+ Q_ASSERT(msg);
+ MediaObject *mediaObject = static_cast<MediaObject*>(data);
+ Q_ASSERT(mediaObject);
+
+ Message message(msg, mediaObject);
+ QMetaObject::invokeMethod(mediaObject->backend(), "handleBusMessage", \
Qt::QueuedConnection, Q_ARG(Message, message)); +
+ return true;
+}
+
+void Backend::run()
+{
+ // Default context is used by Qt so we create a new one
+ GMainContext *context = g_main_context_new();
+ loop = g_main_loop_new (context, FALSE);
+ g_main_loop_run (loop);
+ g_main_context_unref(context);
+ context = 0;
+}
+
/***
* !reimp
*/
@@ -331,9 +363,8 @@
*/
void Backend::addBusWatcher(MediaObject* node)
{
- m_busWatchers.append(node);
- if (m_busWatchers.size() == 1)
- m_busIntervalTimer->start();
+ Q_ASSERT(node);
+ gst_bus_add_watch (gst_pipeline_get_bus ((GstPipeline*)node->pipeline()), \
busCall, node); }
/***
@@ -341,27 +372,18 @@
*/
void Backend::removeBusWatcher(MediaObject* node)
{
- m_busWatchers.removeAll(node);
- if (m_busWatchers.size() == 0)
- m_busIntervalTimer->stop();
+ Q_ASSERT(node);
+ g_source_remove_by_user_data(node);
}
/***
* Polls each mediaobject's pipeline and delivers
* pending any pending messages
*/
-void Backend::handleBusMessages()
+void Backend::handleBusMessage(Message message)
{
- // iterate over all the listening media nodes and deliver the message to each \
one
- GstMessage* message;
- QListIterator<MediaObject*> i(m_busWatchers);
- while (i.hasNext()) {
- MediaObject *mediaObject = i.next();
- GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (mediaObject->pipeline()));
- while ((message = gst_bus_poll(bus, GST_MESSAGE_ANY, 0)) != 0) {
- mediaObject->handleBusMessage(Message(message));
- }
- }
+ MediaObject *mediaObject = message.source();
+ mediaObject->handleBusMessage(message);
}
DeviceManager* Backend::deviceManager() const
--- trunk/kdereview/phonon/gstreamer/backend.h #762603:762604
@@ -40,7 +40,8 @@
class MediaNode;
class MediaObject;
class EffectManager;
-class Backend : public QObject, public BackendInterface
+
+class Backend : public QThread, public BackendInterface
{
Q_OBJECT
Q_INTERFACES(Phonon::BackendInterface)
@@ -48,7 +49,6 @@
public:
enum DebugLevel {NoDebug, Warning, Info, Debug};
-
Backend(QObject *parent = 0, const QVariantList & = QVariantList());
virtual ~Backend();
@@ -57,6 +57,7 @@
QObject *createObject(BackendInterface::Class, QObject *parent, const \
QList<QVariant> &args);
+ void run();
bool isValid() const;
bool supportsVideo() const;
QStringList availableMimeTypes() const;
@@ -80,17 +81,17 @@
void objectDescriptionChanged(ObjectDescriptionType);
private Q_SLOTS:
- void handleBusMessages();
+ void handleBusMessage(Message);
private:
+ static gboolean busCall(GstBus *bus, GstMessage *msg, gpointer data);
QList<QPointer<AudioOutput> > m_audioOutputs;
- QTimer* m_busIntervalTimer;
- QList<MediaObject*> m_busWatchers;
DeviceManager *m_deviceManager;
EffectManager *m_effectManager;
DebugLevel m_debugLevel;
bool m_isValid;
+ GMainLoop *loop;
};
}
} // namespace Phonon::Gstreamer
--- trunk/kdereview/phonon/gstreamer/medianode.h #762603:762604
@@ -75,6 +75,10 @@
void notify(const MediaNodeEvent *event);
+ Backend *backend() {
+ return m_backend;
+ }
+
const QString &name() {
return m_name;
}
--- trunk/kdereview/phonon/gstreamer/mediaobject.cpp #762603:762604
@@ -79,8 +79,8 @@
"\nhave libgstreamer-plugins-base installed."), \
Phonon::FatalError); } else {
m_root = this;
+ createPipeline();
m_backend->addBusWatcher(this);
- createPipeline();
connect(m_tickTimer, SIGNAL(timeout()), SLOT(emitTick()));
}
connect(this, SIGNAL(stateChanged(Phonon::State, Phonon::State)),
@@ -936,6 +936,7 @@
QTimer::singleShot (qMax(0, transitionTime()), this, \
SLOT(beginPlay())); } else {
stop(); // Current track completed
+ changeState(Phonon::StoppedState); //playback has already stopped so \
we can indicate this immediately emit finished();
}
break;
--- trunk/kdereview/phonon/gstreamer/message.cpp #762603:762604
@@ -37,13 +37,24 @@
m_message(0)
{}
-Message::Message(GstMessage* message):
- m_message(message)
-{}
+Message::Message(GstMessage* message, MediaObject *source):
+ m_message(message),
+ m_source(source)
+{
+ Q_ASSERT(m_message);
+ gst_message_ref(m_message);
+}
+Message::Message(const Message &other)
+{
+ m_message = other.m_message;
+ gst_message_ref(m_message);
+ m_source = other.m_source;
+}
+
Message::~Message()
{
-// gst_message_unref(m_message); // should count?
+ gst_message_unref(m_message);
}
GstMessage* Message::rawMessage() const
@@ -51,6 +62,11 @@
return m_message;
}
+MediaObject *Message::source() const
+{
+ return m_source;
+}
+
} // ns gstreamer
} // ns phonon
--- trunk/kdereview/phonon/gstreamer/message.h #762603:762604
@@ -28,17 +28,21 @@
namespace Gstreamer
{
+class MediaObject;
class Message
{
public:
Message();
- Message(GstMessage* message);
+ Message(GstMessage* message, MediaObject *source);
~Message();
GstMessage* rawMessage() const;
+ MediaObject *source() const;
+ Message(const Message &other);
private:
GstMessage* m_message;
+ MediaObject *m_source;
};
} // ns gstreamer
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic