[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: [phonon-gstreamer/1.0-porting-for-merge] gstreamer: Fix more memory leaks and optimize memory manage
From: Dan_Vrátil <dvratil () redhat ! com>
Date: 2014-08-12 14:39:08
Message-ID: E1XHDEC-00073J-FM () scm ! kde ! org
[Download RAW message or body]
Git commit 0bf6eb925dbbb4719a2789e53fd3a60eb8adfc26 by Dan Vrátil.
Committed on 12/08/2014 at 13:46.
Pushed by dvratil into branch '1.0-porting-for-merge'.
Fix more memory leaks and optimize memory management
Calling gst_object_ref_sink() and gst_object_ref() means that we were holding two \
references to the object, so obviously we were leaking the references later on, when \
we did only one unref.
Some structures have to be freed using special methods from Gst 1.0, so we use them \
to prevent more reference or memory leaks.
Finally, this change refactors AbstractRenderer, Effect and MediaNode a little so \
that subclasses must pass and access the Gst pointers (sinks, bins, ...) via setters \
and getters so that we can propertly manage ownership of these objects and don't leak \
references or accidentally try to free the object twice.
M +15 -2 gstreamer/abstractrenderer.cpp
M +12 -3 gstreamer/abstractrenderer.h
M +0 -1 gstreamer/audiodataoutput.cpp
M +3 -1 gstreamer/audiodataoutput.h
M +5 -4 gstreamer/audioeffect.cpp
M +6 -1 gstreamer/audioeffect.h
M +7 -1 gstreamer/audiooutput.cpp
M +1 -1 gstreamer/audiooutput.h
M +6 -4 gstreamer/backend.cpp
M +11 -8 gstreamer/devicemanager.cpp
M +6 -1 gstreamer/devicemanager.h
M +18 -4 gstreamer/effect.cpp
M +13 -1 gstreamer/effect.h
M +1 -1 gstreamer/effectmanager.cpp
M +5 -10 gstreamer/glrenderer.cpp
M +1 -0 gstreamer/glrenderer.h
M +0 -2 gstreamer/medianode.cpp
M +4 -4 gstreamer/medianode.h
M +3 -2 gstreamer/mediaobject.cpp
M +8 -8 gstreamer/mediaobject.h
M +10 -3 gstreamer/pipeline.cpp
M +1 -1 gstreamer/plugininstaller.cpp
M +5 -2 gstreamer/videodataoutput.cpp
M +3 -1 gstreamer/videodataoutput.h
M +8 -1 gstreamer/videographicsobject.cpp
M +5 -6 gstreamer/videowidget.cpp
M +4 -6 gstreamer/videowidget.h
M +13 -11 gstreamer/volumefadereffect.cpp
M +3 -1 gstreamer/volumefadereffect.h
M +21 -16 gstreamer/widgetrenderer.cpp
M +2 -0 gstreamer/widgetrenderer.h
M +27 -23 gstreamer/x11renderer.cpp
M +8 -3 gstreamer/x11renderer.h
http://commits.kde.org/phonon-gstreamer/0bf6eb925dbbb4719a2789e53fd3a60eb8adfc26
diff --git a/gstreamer/abstractrenderer.cpp b/gstreamer/abstractrenderer.cpp
index df7e204..9247f05 100644
--- a/gstreamer/abstractrenderer.cpp
+++ b/gstreamer/abstractrenderer.cpp
@@ -30,11 +30,10 @@ AbstractRenderer::AbstractRenderer(VideoWidget* video)
{
}
-
AbstractRenderer::~AbstractRenderer()
{
if (m_videoSink) {
- gst_object_unref (GST_OBJECT (m_videoSink)); //Take ownership
+ gst_object_unref(m_videoSink);
m_videoSink = 0;
}
}
@@ -54,6 +53,20 @@ void AbstractRenderer::movieSizeChanged(const QSize &size)
Q_UNUSED(size);
}
+void AbstractRenderer::setVideoSink(GstElement* sink)
+{
+ gst_object_ref_sink(sink);
+ if (m_videoSink) {
+ gst_object_unref(m_videoSink);
+ }
+ m_videoSink = sink;
+}
+
+VideoWidget* AbstractRenderer::videoWidget() const
+{
+ return m_videoWidget;
+}
+
}
} //namespace Phonon::Gstreamer
#endif //QT_NO_PHONON_VIDEO
diff --git a/gstreamer/abstractrenderer.h b/gstreamer/abstractrenderer.h
index da5c55e..eecee07 100644
--- a/gstreamer/abstractrenderer.h
+++ b/gstreamer/abstractrenderer.h
@@ -36,9 +36,6 @@ class AbstractRenderer
public:
AbstractRenderer(VideoWidget *video);
virtual ~AbstractRenderer();
- virtual GstElement *videoSink() {
- return m_videoSink;
- }
virtual void aspectRatioChanged(Phonon::VideoWidget::AspectRatio aspectRatio);
virtual void scaleModeChanged(Phonon::VideoWidget::ScaleMode scaleMode);
@@ -50,7 +47,19 @@ public:
return true;
}
+ GstElement *videoSink() const {
+ return m_videoSink;
+ }
+
protected:
+ /**
+ * Takes ownership of @p sink
+ */
+ void setVideoSink(GstElement *sink);
+
+ VideoWidget *videoWidget() const;
+
+private:
VideoWidget *m_videoWidget;
GstElement *m_videoSink;
};
diff --git a/gstreamer/audiodataoutput.cpp b/gstreamer/audiodataoutput.cpp
index e7e9c14..f302657 100644
--- a/gstreamer/audiodataoutput.cpp
+++ b/gstreamer/audiodataoutput.cpp
@@ -48,7 +48,6 @@ AudioDataOutput::AudioDataOutput(Backend *backend, QObject *parent)
m_name = "AudioDataOutput" + QString::number(count++);
m_queue = gst_bin_new(NULL);
- gst_object_ref(GST_OBJECT(m_queue));
gst_object_ref_sink(GST_OBJECT(m_queue));
GstElement* sink = gst_element_factory_make("fakesink", NULL);
GstElement* queue = gst_element_factory_make("queue", NULL);
diff --git a/gstreamer/audiodataoutput.h b/gstreamer/audiodataoutput.h
index ce97346..eb26e07 100644
--- a/gstreamer/audiodataoutput.h
+++ b/gstreamer/audiodataoutput.h
@@ -59,7 +59,9 @@ public:
Phonon::AudioDataOutput* frontendObject() const { return m_frontend; }
void setFrontendObject(Phonon::AudioDataOutput *frontend) { m_frontend = \
frontend; }
- GstElement *audioElement() { return m_queue; }
+ GstElement *audioElement() const {
+ return m_queue;
+ }
signals:
void dataReady(const QMap<Phonon::AudioDataOutput::Channel, QVector<qint16> > \
&data);
diff --git a/gstreamer/audioeffect.cpp b/gstreamer/audioeffect.cpp
index 6959d79..1537998 100644
--- a/gstreamer/audioeffect.cpp
+++ b/gstreamer/audioeffect.cpp
@@ -57,16 +57,17 @@ GstElement* AudioEffect::createEffectBin()
GstElement *mconv= gst_element_factory_make("audioconvert", NULL);
gst_bin_add(GST_BIN(audioBin), mconv);
- m_effectElement = gst_element_factory_make(qPrintable(m_effectName), NULL);
- gst_bin_add(GST_BIN(audioBin), m_effectElement);
+ GstElement *effectElement = gst_element_factory_make(qPrintable(m_effectName), \
NULL); + setEffectElement(effectElement);
+ gst_bin_add(GST_BIN(audioBin), effectElement);
//Link src pad
- GstPad *srcPad= gst_element_get_static_pad(m_effectElement, "src");
+ GstPad *srcPad = gst_element_get_static_pad(effectElement, "src");
gst_element_add_pad(audioBin, gst_ghost_pad_new("src", srcPad));
gst_object_unref(srcPad);
//Link sink pad
- gst_element_link_many(queue, mconv, m_effectElement, NULL);
+ gst_element_link_many(queue, mconv, effectElement, NULL);
GstPad *sinkpad = gst_element_get_static_pad(queue, "sink");
gst_element_add_pad(audioBin, gst_ghost_pad_new("sink", sinkpad));
gst_object_unref(sinkpad);
diff --git a/gstreamer/audioeffect.h b/gstreamer/audioeffect.h
index ec98c04..49953eb 100644
--- a/gstreamer/audioeffect.h
+++ b/gstreamer/audioeffect.h
@@ -39,9 +39,14 @@ class AudioEffect : public Effect
Q_OBJECT
public:
AudioEffect (Backend *backend, int effectId, QObject *parent);
+
protected:
GstElement* createEffectBin();
- GstElement* audioElement() { return m_effectBin; }
+
+ GstElement* audioElement() const {
+ return effectBin();
+ }
+
QString m_effectName;
};
diff --git a/gstreamer/audiooutput.cpp b/gstreamer/audiooutput.cpp
index ebe9251..6446d0e 100644
--- a/gstreamer/audiooutput.cpp
+++ b/gstreamer/audiooutput.cpp
@@ -51,7 +51,6 @@ AudioOutput::AudioOutput(Backend *backend, QObject *parent)
m_name = "AudioOutput" + QString::number(count++);
m_audioBin = gst_bin_new(NULL);
- gst_object_ref(GST_OBJECT (m_audioBin));
gst_object_ref_sink(GST_OBJECT (m_audioBin));
m_conv = gst_element_factory_make("audioconvert", NULL);
@@ -62,6 +61,7 @@ AudioOutput::AudioOutput(Backend *backend, QObject *parent)
category = audioOutput->category();
m_audioSink = m_backend->deviceManager()->createAudioSink(category);
+ gst_object_ref_sink(m_audioSink);
m_volumeElement = gst_element_factory_make("volume", NULL);
GstElement *queue = gst_element_factory_make("queue", NULL);
GstElement *audioresample = gst_element_factory_make("audioresample", NULL);
@@ -86,6 +86,12 @@ AudioOutput::~AudioOutput()
if (m_audioBin) {
gst_element_set_state(m_audioBin, GST_STATE_NULL);
gst_object_unref(m_audioBin);
+ m_audioBin = 0;
+ }
+ if (m_audioSink) {
+ gst_element_set_state(m_audioSink, GST_STATE_NULL);
+ gst_object_unref(m_audioSink);
+ m_audioSink = 0;
}
}
diff --git a/gstreamer/audiooutput.h b/gstreamer/audiooutput.h
index cbc4962..2753625 100644
--- a/gstreamer/audiooutput.h
+++ b/gstreamer/audiooutput.h
@@ -49,7 +49,7 @@ public:
#endif
public:
- GstElement *audioElement()
+ GstElement *audioElement() const
{
Q_ASSERT(m_audioBin);
return m_audioBin;
diff --git a/gstreamer/backend.cpp b/gstreamer/backend.cpp
index 7888af1..8ac074a 100644
--- a/gstreamer/backend.cpp
+++ b/gstreamer/backend.cpp
@@ -91,7 +91,7 @@ Backend::Backend(QObject *parent, const QVariantList &)
bool wasInit = gst_init_check(&argc, &argv, &err); //init gstreamer: must be \
called before any gst-related functions
if (err) {
- error() << err->message;
+ qWarning("Phonon::GStreamer::Backend: Failed to initialize GStreamer: %s", \
err->message); g_error_free(err);
}
@@ -243,8 +243,9 @@ QStringList Backend::availableMimeTypes() const
{
QStringList availableMimeTypes;
- if (!isValid())
+ if (!isValid()) {
return availableMimeTypes;
+ }
GstElementFactory *mpegFactory;
// Add mp3 as a separate mime type as people are likely to look for it.
@@ -253,7 +254,7 @@ QStringList Backend::availableMimeTypes() const
(mpegFactory = gst_element_factory_find("flump3dec"))) {
availableMimeTypes << QLatin1String("audio/x-mp3");
availableMimeTypes << QLatin1String("audio/x-ape");// ape is available \
from ffmpeg
- gst_object_unref(GST_OBJECT(mpegFactory));
+ gst_object_unref(mpegFactory);
}
// Iterate over all audio and video decoders and extract mime types from sink \
caps @@ -296,7 +297,8 @@ QStringList Backend::availableMimeTypes() const
}
}
}
- g_list_free(factoryList);
+ gst_plugin_feature_list_free(factoryList);
+
if (availableMimeTypes.contains("audio/x-vorbis") && \
availableMimeTypes.contains("application/x-ogm-audio")) { if \
(!availableMimeTypes.contains("audio/x-vorbis+ogg")) { \
availableMimeTypes.append("audio/x-vorbis+ogg");
diff --git a/gstreamer/devicemanager.cpp b/gstreamer/devicemanager.cpp
index fb7c04d..6ea509d 100644
--- a/gstreamer/devicemanager.cpp
+++ b/gstreamer/devicemanager.cpp
@@ -63,7 +63,11 @@ DeviceInfo::DeviceInfo(DeviceManager *manager, const QByteArray \
&deviceId, m_description = "Default video capture device";
} else {
GstElement *dev = gst_element_factory_make("v4l2src", NULL);
- useGstElement(dev, deviceId);
+ if (dev) {
+ useGstElement(dev, deviceId);
+ gst_element_set_state(dev, GST_STATE_NULL);
+ gst_object_unref(dev);
+ }
}
}
@@ -77,7 +81,11 @@ DeviceInfo::DeviceInfo(DeviceManager *manager, const QByteArray \
&deviceId, m_description = "Default audio device";
} else {
GstElement *aSink = manager->createAudioSink();
- useGstElement(aSink, deviceId);
+ if (aSink) {
+ useGstElement(aSink, deviceId);
+ gst_element_set_state(aSink, GST_STATE_NULL);
+ gst_object_unref(aSink);
+ }
}
}
@@ -89,10 +97,6 @@ DeviceInfo::DeviceInfo(DeviceManager *manager, const QByteArray \
&deviceId,
void DeviceInfo::useGstElement(GstElement *element, const QByteArray &deviceId)
{
- if (!element) {
- return;
- }
-
gchar *deviceName = NULL;
if (g_object_class_find_property(G_OBJECT_GET_CLASS(element), "device")){
g_object_set(G_OBJECT(element), "device", deviceId.constData(), NULL);
@@ -107,8 +111,6 @@ void DeviceInfo::useGstElement(GstElement *element, const \
QByteArray &deviceId) }
g_free(deviceName);
- gst_element_set_state(element, GST_STATE_NULL);
- gst_object_unref(element);
}
}
@@ -359,6 +361,7 @@ AbstractRenderer *DeviceManager::createVideoRenderer(VideoWidget \
*parent) } else {
GstElementFactory *srcfactory = gst_element_factory_find("ximagesink");
if (srcfactory) {
+ gst_object_unref(srcfactory);
return new X11Renderer(parent);
}
}
diff --git a/gstreamer/devicemanager.h b/gstreamer/devicemanager.h
index e3e8f71..87b6cd8 100644
--- a/gstreamer/devicemanager.h
+++ b/gstreamer/devicemanager.h
@@ -89,8 +89,12 @@ class DeviceManager : public QObject {
public:
DeviceManager(Backend *parent);
virtual ~DeviceManager();
- GstElement *createGNOMEAudioSink(Category category);
+
+ /**
+ * @returns a GstElement with a floating reference
+ */
GstElement *createAudioSink(Category category = NoCategory);
+
AbstractRenderer *createVideoRenderer(VideoWidget *parent);
QList<int> deviceIds(ObjectDescriptionType type);
QHash<QByteArray, QVariant> deviceProperties(int id);
@@ -105,6 +109,7 @@ public slots:
private:
static bool listContainsDevice(const QList<DeviceInfo> &list, int id);
+ GstElement *createGNOMEAudioSink(Category category);
bool canOpenDevice(GstElement *element) const;
private:
diff --git a/gstreamer/effect.cpp b/gstreamer/effect.cpp
index 14df5d0..b699962 100644
--- a/gstreamer/effect.cpp
+++ b/gstreamer/effect.cpp
@@ -41,9 +41,8 @@ void Effect::init()
{
m_effectBin = createEffectBin();
if (m_effectBin) {
+ gst_object_ref_sink(m_effectBin); // Take ownership of the bin
setupEffectParams();
- gst_object_ref(GST_OBJECT(m_effectBin)); // Take ownership
- gst_object_ref_sink(GST_OBJECT(m_effectBin));
m_isValid = true;
}
}
@@ -51,9 +50,24 @@ void Effect::init()
Effect::~Effect()
{
if (m_effectBin) {
- gst_element_set_state (m_effectBin, GST_STATE_NULL);
- gst_object_unref (m_effectBin);
+ gst_element_set_state(m_effectBin, GST_STATE_NULL);
+ gst_object_unref(m_effectBin);
+ m_effectBin = 0;
}
+ if (m_effectElement) {
+ gst_element_set_state(m_effectElement, GST_STATE_NULL);
+ gst_object_unref(m_effectElement);
+ m_effectElement = 0;
+ }
+}
+
+void Effect::setEffectElement(GstElement* effectElement)
+{
+ gst_object_ref_sink(effectElement);
+ if (m_effectElement) {
+ gst_object_unref(m_effectElement);
+ }
+ m_effectElement = effectElement;
}
void Effect::setupEffectParams()
diff --git a/gstreamer/effect.h b/gstreamer/effect.h
index f60f0e4..739e1b8 100644
--- a/gstreamer/effect.h
+++ b/gstreamer/effect.h
@@ -46,11 +46,23 @@ namespace Gstreamer
virtual QVariant parameterValue(const EffectParameter &) const;
virtual void setParameterValue(const EffectParameter &, const QVariant \
&);
- virtual GstElement* createEffectBin() = 0;
virtual void init();
virtual void setupEffectParams();
protected:
+ virtual GstElement* createEffectBin() = 0;
+
+ void setEffectElement(GstElement *effectElement);
+
+ GstElement *effectElement() const {
+ return m_effectElement;
+ }
+
+ GstElement *effectBin() const {
+ return m_effectBin;
+ }
+
+ private:
GstElement *m_effectBin;
GstElement *m_effectElement;
QList<Phonon::EffectParameter> m_parameterList;
diff --git a/gstreamer/effectmanager.cpp b/gstreamer/effectmanager.cpp
index fa59e8c..e110899 100644
--- a/gstreamer/effectmanager.cpp
+++ b/gstreamer/effectmanager.cpp
@@ -102,7 +102,7 @@ EffectManager::EffectManager(Backend *backend)
}
}
}
- g_list_free(factoryList);
+ gst_plugin_feature_list_free(factoryList);
}
EffectManager::~EffectManager()
diff --git a/gstreamer/glrenderer.cpp b/gstreamer/glrenderer.cpp
index 52f1234..ca24132 100644
--- a/gstreamer/glrenderer.cpp
+++ b/gstreamer/glrenderer.cpp
@@ -80,11 +80,10 @@ GLRenderer::GLRenderer(VideoWidget* videoWidget) :
format.setSwapInterval(1); // Enable vertical sync on draw to avoid tearing
m_glWindow = new GLRenderWidgetImplementation(videoWidget, format);
- if ((m_videoSink = m_glWindow->createVideoSink())) { //if ((m_videoSink = \
m_glWindow->createVideoSink())) {
- gst_object_ref(GST_OBJECT(m_videoSink)); //Take ownership
- gst_object_ref_sink(GST_OBJECT(m_videoSink));
-
- QWidgetVideoSinkBase* sink = \
reinterpret_cast<QWidgetVideoSinkBase*>(m_videoSink); + GstElement *videoSink = \
m_glWindow->createVideoSink(); + if (videoSink) {
+ setVideoSink(videoSink);
+ QWidgetVideoSinkBase* sink = \
reinterpret_cast<QWidgetVideoSinkBase*>(videoSink); // Let the videosink know which \
widget to direct frame updates to sink->renderWidget = videoWidget;
}
@@ -92,10 +91,6 @@ GLRenderer::GLRenderer(VideoWidget* videoWidget) :
GLRenderer::~GLRenderer()
{
- if (m_videoSink) {
- gst_object_unref(GST_OBJECT(m_videoSink));
- m_videoSink = 0;
- }
}
@@ -106,7 +101,7 @@ bool GLRenderer::eventFilter(QEvent * event)
m_glWindow->setNextFrame(frameEvent->frame, frameEvent->width, \
frameEvent->height); return true;
} else if (event->type() == QEvent::Resize) {
- m_glWindow->setGeometry(m_videoWidget->geometry());
+ m_glWindow->setGeometry(videoWidget()->geometry());
return true;
}
return false;
diff --git a/gstreamer/glrenderer.h b/gstreamer/glrenderer.h
index 8ee7ab5..fe6aebd 100644
--- a/gstreamer/glrenderer.h
+++ b/gstreamer/glrenderer.h
@@ -42,6 +42,7 @@ public:
~GLRenderer();
bool eventFilter(QEvent * event);
bool paintsOnWidget() { return false; }
+
private:
GLRenderWidgetImplementation *m_glWindow;
};
diff --git a/gstreamer/medianode.cpp b/gstreamer/medianode.cpp
index ddf82eb..deb634f 100644
--- a/gstreamer/medianode.cpp
+++ b/gstreamer/medianode.cpp
@@ -46,14 +46,12 @@ MediaNode::MediaNode(Backend *backend, NodeDescription \
description) : if (description & AudioSource) {
m_audioTee = gst_element_factory_make("tee", NULL);
Q_ASSERT(m_audioTee); // Must not ever be null.
- gst_object_ref(GST_OBJECT(m_audioTee));
gst_object_ref_sink(GST_OBJECT(m_audioTee));
}
if (description & VideoSource) {
m_videoTee = gst_element_factory_make("tee", NULL);
Q_ASSERT(m_videoTee); // Must not ever be null.
- gst_object_ref(GST_OBJECT(m_videoTee));
gst_object_ref_sink(GST_OBJECT(m_videoTee));
}
}
diff --git a/gstreamer/medianode.h b/gstreamer/medianode.h
index 70bf2f2..fbf7825 100644
--- a/gstreamer/medianode.h
+++ b/gstreamer/medianode.h
@@ -70,19 +70,19 @@ public:
m_root = mediaObject;
}
- Backend *backend() {
+ Backend *backend() const {
return m_backend;
}
- const QString &name() {
+ const QString &name() const {
return m_name;
}
- virtual GstElement *audioElement() {
+ virtual GstElement *audioElement() const {
return m_audioTee;
}
- virtual GstElement *videoElement() {
+ virtual GstElement *videoElement() const {
return m_videoTee;
}
diff --git a/gstreamer/mediaobject.cpp b/gstreamer/mediaobject.cpp
index fad729d..8c46ec2 100644
--- a/gstreamer/mediaobject.cpp
+++ b/gstreamer/mediaobject.cpp
@@ -226,10 +226,11 @@ qint32 MediaObject::tickInterval() const
void MediaObject::setTickInterval(qint32 newTickInterval)
{
m_tickInterval = newTickInterval;
- if (m_tickInterval <= 0)
+ if (m_tickInterval <= 0) {
m_tickTimer->setInterval(50);
- else
+ } else {
m_tickTimer->setInterval(newTickInterval);
+ }
}
/**
diff --git a/gstreamer/mediaobject.h b/gstreamer/mediaobject.h
index 6cdfc3f..12ab5f6 100644
--- a/gstreamer/mediaobject.h
+++ b/gstreamer/mediaobject.h
@@ -108,32 +108,32 @@ public:
bool hasInterface(Interface) const;
QVariant interfaceCall(Interface, int, const QList<QVariant> &);
#endif
- bool isLoading()
+ bool isLoading() const
{
return m_loading;
}
- bool audioAvailable()
+ bool audioAvailable() const
{
return m_pipeline->audioIsAvailable();
}
- bool videoAvailable()
+ bool videoAvailable() const
{
return m_pipeline->videoIsAvailable();
}
- GstElement *audioGraph()
+ GstElement *audioGraph() const
{
return m_pipeline->audioGraph();
}
- GstElement *videoGraph()
+ GstElement *videoGraph() const
{
return m_pipeline->videoGraph();
}
- Pipeline *pipeline()
+ Pipeline *pipeline() const
{
return m_pipeline;
}
@@ -179,12 +179,12 @@ protected:
void loadingComplete();
Q_INVOKABLE void setError(const QString &errorString, Phonon::ErrorType error = \
NormalError);
- GstElement *audioElement()
+ GstElement *audioElement() const
{
return m_pipeline->audioPipe();
}
- GstElement *videoElement()
+ GstElement *videoElement() const
{
return m_pipeline->videoPipe();
}
diff --git a/gstreamer/pipeline.cpp b/gstreamer/pipeline.cpp
index a770dd3..87f5458 100644
--- a/gstreamer/pipeline.cpp
+++ b/gstreamer/pipeline.cpp
@@ -52,7 +52,6 @@ Pipeline::Pipeline(QObject *parent)
{
qRegisterMetaType<GstState>("GstState");
m_pipeline = GST_PIPELINE(gst_element_factory_make("playbin", NULL));
- gst_object_ref(m_pipeline);
gst_object_ref_sink (m_pipeline);
g_signal_connect(m_pipeline, "video-changed", G_CALLBACK(cb_videoChanged), \
this);
g_signal_connect(m_pipeline, "text-tags-changed", \
G_CALLBACK(cb_textTagsChanged), this); @@ -75,7 +74,6 @@ Pipeline::Pipeline(QObject \
*parent)
// Set up audio graph
m_audioGraph = gst_bin_new("audioGraph");
- gst_object_ref(GST_OBJECT(m_audioGraph));
gst_object_ref_sink(GST_OBJECT(m_audioGraph));
// Note that these queues are only required for streaming content
@@ -101,7 +99,6 @@ Pipeline::Pipeline(QObject *parent)
// Set up video graph
m_videoGraph = gst_bin_new("videoGraph");
- gst_object_ref(GST_OBJECT(m_videoGraph));
gst_object_ref_sink(GST_OBJECT(m_videoGraph));
m_videoPipe = gst_element_factory_make("queue", "videoPipe");
@@ -224,6 +221,16 @@ Pipeline::~Pipeline()
gst_element_set_state(GST_ELEMENT(m_pipeline), GST_STATE_NULL);
gst_object_unref(m_pipeline);
m_pipeline = 0;
+
+ if (m_audioGraph) {
+ gst_object_unref(m_audioGraph);
+ m_audioGraph = 0;
+ }
+
+ if (m_videoGraph) {
+ gst_object_unref(m_videoGraph);
+ m_videoGraph = 0;
+ }
}
GstElement *Pipeline::element() const
diff --git a/gstreamer/plugininstaller.cpp b/gstreamer/plugininstaller.cpp
index 69f39f6..add70c4 100644
--- a/gstreamer/plugininstaller.cpp
+++ b/gstreamer/plugininstaller.cpp
@@ -251,7 +251,7 @@ PluginInstaller::InstallStatus \
PluginInstaller::checkInstalledPlugins() return m_state;
bool allFound = true;
foreach (const QString &plugin, m_pluginList.keys()) {
- if (!gst_registry_check_feature_version(gst_registry_get(), \
plugin.toLocal8Bit().data(), 1, 0, 0)) { + if \
(!gst_registry_check_feature_version(gst_registry_get(), qPrintable(plugin), 1, 0, \
0)) { allFound = false;
break;
}
diff --git a/gstreamer/videodataoutput.cpp b/gstreamer/videodataoutput.cpp
index eebb546..edb5f32 100644
--- a/gstreamer/videodataoutput.cpp
+++ b/gstreamer/videodataoutput.cpp
@@ -44,7 +44,6 @@ VideoDataOutput::VideoDataOutput(Backend *backend, QObject *parent)
m_name = "VideoDataOutput" + QString::number(count++);
m_queue = gst_bin_new(NULL);
- gst_object_ref(GST_OBJECT(m_queue));
gst_object_ref_sink(GST_OBJECT(m_queue));
GstElement* sink = gst_element_factory_make("fakesink", NULL);
@@ -78,13 +77,17 @@ VideoDataOutput::~VideoDataOutput()
{
gst_element_set_state(m_queue, GST_STATE_NULL);
gst_object_unref(m_queue);
+ m_queue = 0;
}
void VideoDataOutput::processBuffer(GstElement*, GstBuffer* buffer, GstPad* pad, \
gpointer gThat) {
VideoDataOutput *that = reinterpret_cast<VideoDataOutput*>(gThat);
- GstStructure* structure = gst_caps_get_structure(gst_pad_get_current_caps(pad), \
0); + GstCaps *caps = gst_pad_get_current_caps(pad);
+ GstStructure* structure = gst_caps_get_structure(caps, 0);
+ gst_caps_unref(caps);
+
int width;
int height;
double aspect;
diff --git a/gstreamer/videodataoutput.h b/gstreamer/videodataoutput.h
index eebd889..66040b8 100644
--- a/gstreamer/videodataoutput.h
+++ b/gstreamer/videodataoutput.h
@@ -53,7 +53,9 @@ class Backend;
Phonon::Experimental::AbstractVideoDataOutput *frontendObject() const { \
return m_frontend; }
void setFrontendObject(Phonon::Experimental::AbstractVideoDataOutput \
*object) { m_frontend = object; }
- GstElement *videoElement() { return m_queue; }
+ GstElement *videoElement() const {
+ return m_queue;
+ }
private:
GstElement *m_queue;
diff --git a/gstreamer/videographicsobject.cpp b/gstreamer/videographicsobject.cpp
index cee9356..976d956 100644
--- a/gstreamer/videographicsobject.cpp
+++ b/gstreamer/videographicsobject.cpp
@@ -39,7 +39,6 @@ VideoGraphicsObject::VideoGraphicsObject(Backend *backend, QObject \
*parent) : m_name = "VideoGraphicsObject" + QString::number(count++);
m_bin = gst_bin_new(0);
- gst_object_ref(GST_OBJECT(m_bin));
gst_object_ref_sink(GST_OBJECT(m_bin));
m_sink = P_GST_VIDEO_SINK(g_object_new(P_GST_TYPE_VIDEO_SINK, 0));
@@ -68,6 +67,14 @@ VideoGraphicsObject::VideoGraphicsObject(Backend *backend, QObject \
*parent) :
VideoGraphicsObject::~VideoGraphicsObject()
{
+ gst_element_set_state(m_bin, GST_STATE_NULL);
+ gst_object_unref(m_bin);
+ m_bin = 0;
+
+ if (m_buffer) {
+ gst_object_unref(m_buffer);
+ m_buffer = 0;
+ }
}
void VideoGraphicsObject::renderCallback(GstBuffer *buffer, void *userData)
diff --git a/gstreamer/videowidget.cpp b/gstreamer/videowidget.cpp
index 6e3a807..5dd35cb 100644
--- a/gstreamer/videowidget.cpp
+++ b/gstreamer/videowidget.cpp
@@ -71,11 +71,11 @@ VideoWidget::~VideoWidget()
if (m_videoBin) {
gst_element_set_state(m_videoBin, GST_STATE_NULL);
gst_object_unref(m_videoBin);
+ m_videoBin = 0;
}
- if (m_renderer) {
- delete m_renderer;
- }
+ delete m_renderer;
+ m_renderer = 0;
}
void VideoWidget::updateWindowID()
@@ -120,8 +120,7 @@ void VideoWidget::setupVideoBin()
m_videoBin = gst_bin_new (NULL);
Q_ASSERT(m_videoBin);
- gst_object_ref(GST_OBJECT (m_videoBin)); //Take ownership
- gst_object_ref_sink(GST_OBJECT (m_videoBin));
+ gst_object_ref_sink(GST_OBJECT (m_videoBin)); //Take ownership
QByteArray tegraEnv = qgetenv("TEGRA_GST_OPENMAX");
if (tegraEnv.isEmpty()) {
//The videoplug element is the final element before the pluggable videosink
@@ -603,7 +602,7 @@ void VideoWidget::cb_capsChanged(GstPad *pad, GParamSpec *spec, \
gpointer data) return;
}
GstState videoState;
- gst_element_get_state(that->videoElement(), &videoState, NULL, 1000);
+ gst_element_get_state(that->m_videoBin, &videoState, NULL, 1000);
gint width;
gint height;
diff --git a/gstreamer/videowidget.h b/gstreamer/videowidget.h
index f36f327..0d9b319 100644
--- a/gstreamer/videowidget.h
+++ b/gstreamer/videowidget.h
@@ -63,16 +63,14 @@ public:
QRect calculateDrawFrameRect() const;
QImage snapshot() const;
- GstElement *videoElement()
- {
- Q_ASSERT(m_videoBin);
- return m_videoBin;
- }
-
QSize movieSize() const {
return m_movieSize;
}
+ GstElement* videoElement() const {
+ return m_videoBin;
+ }
+
bool event(QEvent *);
QWidget *widget() {
diff --git a/gstreamer/volumefadereffect.cpp b/gstreamer/volumefadereffect.cpp
index 40f68c2..d081f5d 100644
--- a/gstreamer/volumefadereffect.cpp
+++ b/gstreamer/volumefadereffect.cpp
@@ -36,10 +36,12 @@ VolumeFaderEffect::VolumeFaderEffect(Backend *backend, QObject \
*parent) , m_fadeFromVolume(0)
, m_fadeToVolume(0)
{
- m_effectElement = gst_element_factory_make("volume", NULL);
- if (m_effectElement) {
+ GstElement *effectElement = gst_element_factory_make("volume", NULL);
+ if (effectElement) {
+ setEffectElement(effectElement);
init();
}
+
m_fadeTimeline = new QTimeLine(1000, this);
connect(m_fadeTimeline, SIGNAL(valueChanged(qreal)), this, \
SLOT(slotSetVolume(qreal))); }
@@ -53,20 +55,20 @@ GstElement* VolumeFaderEffect::createEffectBin()
GstElement *audioBin = gst_bin_new(NULL);
// We need a queue to handle tee-connections from parent node
- GstElement *queue= gst_element_factory_make("queue", NULL);
+ GstElement *queue = gst_element_factory_make("queue", NULL);
gst_bin_add(GST_BIN(audioBin), queue);
- GstElement *mconv= gst_element_factory_make("audioconvert", NULL);
+ GstElement *mconv = gst_element_factory_make("audioconvert", NULL);
gst_bin_add(GST_BIN(audioBin), mconv);
- gst_bin_add(GST_BIN(audioBin), m_effectElement);
+ gst_bin_add(GST_BIN(audioBin), effectElement());
// Link src pad
- GstPad *srcPad= gst_element_get_static_pad(m_effectElement, "src");
+ GstPad *srcPad = gst_element_get_static_pad(effectElement(), "src");
gst_element_add_pad(audioBin, gst_ghost_pad_new("src", srcPad));
gst_object_unref(srcPad);
// Link sink pad
- gst_element_link_many(queue, mconv, m_effectElement, NULL);
+ gst_element_link_many(queue, mconv, effectElement(), NULL);
GstPad *sinkpad = gst_element_get_static_pad(queue, "sink");
gst_element_add_pad(audioBin, gst_ghost_pad_new("sink", sinkpad));
gst_object_unref(sinkpad);
@@ -76,8 +78,8 @@ GstElement* VolumeFaderEffect::createEffectBin()
float VolumeFaderEffect::volume() const
{
gdouble val = 1.0;
- if (m_effectElement) {
- g_object_get(G_OBJECT(m_effectElement), "volume", &val, NULL);
+ if (effectElement()) {
+ g_object_get(G_OBJECT(effectElement()), "volume", &val, NULL);
}
return (float)val;
}
@@ -118,7 +120,7 @@ void VolumeFaderEffect::fadeTo(float targetVolume, int fadeTime)
{
abortFade();
m_fadeToVolume = targetVolume;
- g_object_get(G_OBJECT(m_effectElement), "volume", &m_fadeFromVolume, NULL);
+ g_object_get(G_OBJECT(effectElement()), "volume", &m_fadeFromVolume, NULL);
// Don't call QTimeLine::setDuration() with zero.
// It is not supported and breaks fading.
@@ -144,7 +146,7 @@ void VolumeFaderEffect::abortFade()
void VolumeFaderEffect::setVolumeInternal(float v)
{
- g_object_set(G_OBJECT(m_effectElement), "volume", (gdouble)v, NULL);
+ g_object_set(G_OBJECT(effectElement()), "volume", (gdouble)v, NULL);
debug() << "Fading to" << v;
}
diff --git a/gstreamer/volumefadereffect.h b/gstreamer/volumefadereffect.h
index 21cc9d1..59f6ef0 100644
--- a/gstreamer/volumefadereffect.h
+++ b/gstreamer/volumefadereffect.h
@@ -39,7 +39,9 @@ public:
~VolumeFaderEffect();
GstElement* createEffectBin();
- GstElement *audioElement() { return m_effectBin; }
+ GstElement *audioElement() const {
+ return effectBin();
+ }
// VolumeFaderInterface:
float volume() const;
diff --git a/gstreamer/widgetrenderer.cpp b/gstreamer/widgetrenderer.cpp
index 0641a41..751da12 100644
--- a/gstreamer/widgetrenderer.cpp
+++ b/gstreamer/widgetrenderer.cpp
@@ -63,33 +63,38 @@ namespace Phonon
namespace Gstreamer
{
-WidgetRenderer::WidgetRenderer(VideoWidget *videoWidget)
- : AbstractRenderer(videoWidget)
+WidgetRenderer::WidgetRenderer(VideoWidget *videoWidget_)
+ : AbstractRenderer(videoWidget_)
, m_width(0)
, m_height(0)
{
debug() << "Creating QWidget renderer";
- if ((m_videoSink = GST_ELEMENT(g_object_new(get_type_RGB(), NULL)))) {
- gst_object_ref (GST_OBJECT (m_videoSink)); //Take ownership
- gst_object_ref_sink (GST_OBJECT (m_videoSink));
+ GstElement *videoSink = GST_ELEMENT(g_object_new(get_type_RGB(), NULL));
+ if (videoSink) {
+ setVideoSink(videoSink);
- QWidgetVideoSinkBase* sink = \
reinterpret_cast<QWidgetVideoSinkBase*>(m_videoSink); + QWidgetVideoSinkBase* \
sink = reinterpret_cast<QWidgetVideoSinkBase*>(videoSink); // Let the videosink know \
which widget to direct frame updates to
- sink->renderWidget = videoWidget;
+ sink->renderWidget = videoWidget();
}
// Clear the background with black by default
QPalette palette;
palette.setColor(QPalette::Background, Qt::black);
- m_videoWidget->setPalette(palette);
- m_videoWidget->setAutoFillBackground(true);
- m_videoWidget->setAttribute(Qt::WA_NoSystemBackground, false);
- m_videoWidget->setAttribute(Qt::WA_PaintOnScreen, false);
+ videoWidget()->setPalette(palette);
+ videoWidget()->setAutoFillBackground(true);
+ videoWidget()->setAttribute(Qt::WA_NoSystemBackground, false);
+ videoWidget()->setAttribute(Qt::WA_PaintOnScreen, false);
}
+WidgetRenderer::~WidgetRenderer()
+{
+}
+
+
void WidgetRenderer::setNextFrame(const QByteArray &array, int w, int h)
{
- if (m_videoWidget->root()->state() == Phonon::LoadingState) {
+ if (videoWidget()->root()->state() == Phonon::LoadingState) {
return;
}
@@ -98,14 +103,14 @@ void WidgetRenderer::setNextFrame(const QByteArray &array, int \
w, int h) m_width = w;
m_height = h;
- m_videoWidget->update();
+ videoWidget()->update();
}
void WidgetRenderer::clearFrame()
{
m_frame = QImage();
m_array = QByteArray();
- m_videoWidget->update();
+ videoWidget()->update();
}
const QImage &WidgetRenderer::currentFrame() const
@@ -116,8 +121,8 @@ const QImage &WidgetRenderer::currentFrame() const
void WidgetRenderer::handlePaint(QPaintEvent *event)
{
Q_UNUSED(event);
- QPainter painter(m_videoWidget);
- m_drawFrameRect = m_videoWidget->calculateDrawFrameRect();
+ QPainter painter(videoWidget());
+ m_drawFrameRect = videoWidget()->calculateDrawFrameRect();
painter.drawImage(drawFrameRect(), currentFrame());
frameRendered();
}
diff --git a/gstreamer/widgetrenderer.h b/gstreamer/widgetrenderer.h
index ed065e6..b5fdb1b 100644
--- a/gstreamer/widgetrenderer.h
+++ b/gstreamer/widgetrenderer.h
@@ -34,6 +34,8 @@ class WidgetRenderer : public AbstractRenderer
{
public:
WidgetRenderer(VideoWidget *videoWidget);
+ virtual ~WidgetRenderer();
+
bool eventFilter(QEvent * event);
void handlePaint(QPaintEvent *paintEvent);
const QImage& currentFrame() const;
diff --git a/gstreamer/x11renderer.cpp b/gstreamer/x11renderer.cpp
index 9c98ceb..1e3472c 100644
--- a/gstreamer/x11renderer.cpp
+++ b/gstreamer/x11renderer.cpp
@@ -39,10 +39,13 @@ namespace Gstreamer
class OverlayWidget : public QWidget
{
public:
- OverlayWidget(VideoWidget *videoWidget, X11Renderer *renderer) :
- QWidget(videoWidget),
- m_videoWidget(videoWidget),
- m_renderer(renderer) { }
+ OverlayWidget(VideoWidget *videoWidget, X11Renderer *renderer)
+ : QWidget(videoWidget)
+ , m_videoWidget(videoWidget)
+ , m_renderer(renderer)
+ {
+ }
+
void paintEvent(QPaintEvent *) {
Phonon::State state = m_videoWidget->root() ? m_videoWidget->root()->state() \
: Phonon::LoadingState;
if (state == Phonon::PlayingState || state == Phonon::PausedState) {
@@ -52,6 +55,7 @@ public:
painter.fillRect(m_videoWidget->rect(), \
m_videoWidget->palette().background()); }
}
+
private:
VideoWidget *m_videoWidget;
X11Renderer *m_renderer;
@@ -64,10 +68,13 @@ X11Renderer::X11Renderer(VideoWidget *videoWidget)
debug() << "Creating X11 overlay renderer";
QPalette palette;
palette.setColor(QPalette::Background, Qt::black);
- m_videoWidget->setPalette(palette);
- m_videoWidget->setAutoFillBackground(true);
+ videoWidget->setPalette(palette);
+ videoWidget->setAutoFillBackground(true);
m_renderWidget->setMouseTracking(true);
- m_videoSink = createVideoSink();
+ GstElement *videoSink = createVideoSink();
+ if (videoSink) {
+ setVideoSink(videoSink);
+ }
aspectRatioChanged(videoWidget->aspectRatio());
setOverlay();
}
@@ -99,29 +106,26 @@ GstElement* X11Renderer::createVideoSink()
}
QByteArray tegraEnv = qgetenv("TEGRA_GST_OPENMAX");
if (!tegraEnv.isEmpty()) {
- videoSink = gst_element_factory_make ("nv_gl_videosink", NULL);
+ videoSink = gst_element_factory_make("nv_gl_videosink", NULL);
}
if (!videoSink) {
- videoSink = gst_element_factory_make ("ximagesink", NULL);
+ videoSink = gst_element_factory_make("ximagesink", NULL);
}
- gst_object_ref(GST_OBJECT (videoSink)); //Take ownership
- gst_object_ref_sink(GST_OBJECT (videoSink));
-
return videoSink;
}
void X11Renderer::aspectRatioChanged(Phonon::VideoWidget::AspectRatio)
{
if (m_renderWidget) {
- m_renderWidget->setGeometry(m_videoWidget->calculateDrawFrameRect());
+ m_renderWidget->setGeometry(videoWidget()->calculateDrawFrameRect());
}
}
void X11Renderer::scaleModeChanged(Phonon::VideoWidget::ScaleMode)
{
if (m_renderWidget) {
- m_renderWidget->setGeometry(m_videoWidget->calculateDrawFrameRect());
+ m_renderWidget->setGeometry(videoWidget()->calculateDrawFrameRect());
}
}
@@ -130,7 +134,7 @@ void X11Renderer::movieSizeChanged(const QSize &movieSize)
Q_UNUSED(movieSize);
if (m_renderWidget) {
- m_renderWidget->setGeometry(m_videoWidget->calculateDrawFrameRect());
+ m_renderWidget->setGeometry(videoWidget()->calculateDrawFrameRect());
}
}
@@ -145,7 +149,7 @@ bool X11Renderer::eventFilter(QEvent *e)
} else if (e->type() == QEvent::Resize) {
// This is a workaround for missing background repaints
// when reducing window size
- m_renderWidget->setGeometry(m_videoWidget->calculateDrawFrameRect());
+ m_renderWidget->setGeometry(videoWidget()->calculateDrawFrameRect());
windowExposed();
}
return false;
@@ -153,15 +157,15 @@ bool X11Renderer::eventFilter(QEvent *e)
void X11Renderer::handlePaint(QPaintEvent *)
{
- QPainter painter(m_videoWidget);
- painter.fillRect(m_videoWidget->rect(), m_videoWidget->palette().background());
+ QPainter painter(videoWidget());
+ painter.fillRect(videoWidget()->rect(), videoWidget()->palette().background());
}
void X11Renderer::setOverlay()
{
- if (m_videoSink && GST_IS_VIDEO_OVERLAY(m_videoSink)) {
+ if (videoSink() && GST_IS_VIDEO_OVERLAY(videoSink())) {
WId windowId = m_renderWidget->winId();
- gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(m_videoSink), \
windowId); + gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(videoSink()), \
windowId); }
windowExposed();
m_overlaySet = true;
@@ -171,11 +175,11 @@ void X11Renderer::windowExposed()
{
// This can be invoked within a callchain in an arbitrary thread, so make
// sure we call syncX() from the main thread
- QMetaObject::invokeMethod(m_videoWidget, "syncX",
+ QMetaObject::invokeMethod(videoWidget(), "syncX",
Qt::QueuedConnection);
- if (m_videoSink && GST_IS_VIDEO_OVERLAY(m_videoSink)) {
- gst_video_overlay_expose(GST_VIDEO_OVERLAY(m_videoSink));
+ if (videoSink() && GST_IS_VIDEO_OVERLAY(videoSink())) {
+ gst_video_overlay_expose(GST_VIDEO_OVERLAY(videoSink()));
}
}
diff --git a/gstreamer/x11renderer.h b/gstreamer/x11renderer.h
index d6e69c9..ab01b8c 100644
--- a/gstreamer/x11renderer.h
+++ b/gstreamer/x11renderer.h
@@ -42,12 +42,17 @@ public:
void scaleModeChanged(Phonon::VideoWidget::ScaleMode scaleMode);
void movieSizeChanged(const QSize &movieSize);
bool eventFilter(QEvent *);
- bool paintsOnWidget() { return false; }
- bool overlaySet() const { return m_overlaySet; }
+ bool paintsOnWidget() {
+ return false;
+ }
+ bool overlaySet() const {
+ return m_overlaySet;
+ }
void setOverlay();
void windowExposed();
- GstElement *createVideoSink();
private:
+ GstElement *createVideoSink();
+
OverlayWidget *m_renderWidget;
bool m_overlaySet;
};
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic