[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