After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 727003 - Memory Leak in QtGstreamer
Memory Leak in QtGstreamer
Status: RESOLVED OBSOLETE
Product: GStreamer
Classification: Platform
Component: qt-gstreamer
0.10.0
Other Linux
: Normal major
: NONE
Assigned To: GStreamer Maintainers
GStreamer Maintainers
Depends on:
Blocks:
 
 
Reported: 2014-03-25 05:10 UTC by monalisabarik29
Modified: 2014-06-21 14:15 UTC
See Also:
GNOME target: ---
GNOME version: ---



Description monalisabarik29 2014-03-25 05:10:13 UTC
I am using QTGstreamer in my application to play media files of .webm & .flv formats. The movies of length 5-10 secs play in a loop continuously.
I have observed huge memory leak while playing these small movies. Instead if I play a long (approx 1 hour) movie, the leak is almost negligible.
Please suggest some solution.
Below is the source code

[MAIN.CPP]

    #include "mediaapp.h"
    #include <QtGui/QApplication>
    #include <QGst/init.h>
     
    int main (int argc, char *argv [] )
    {
    QApplication app ( argc, argv );
    QGst :: init ( &argc, &argv );
     
    MediaApp media;
    media .show();
    media .openFile ("file://XYZ.webm");
    return app .exec();
    }


[MEDIAAPP.H]

    #ifndef MEDIAAPP_H_
    #define MEDIAAPP_H_
     
    #include <QtGui/QWidget>
    #include <QtGui/QStyle>
    #include <QtCore/QTimer>
     
    class Player;
    class QBoxLayout;
    class QTimer;
     
    class MediaApp : public QWidget
    {
    Q_OBJECT
    public:
    MediaApp(QWidget *parent = 0);
    ~MediaApp();
    void openFile(const QString & fileName);
     
     
     
    private Q_SLOTS:
    void onStateChanged();
     
    private:
    void createUI(QBoxLayout *appLayout);
    Player *m_player;
    };



[MEDIAAPP.CPP]

    #include "mediaapp.h"
    #include "player.h"
    #include <QtGui/QBoxLayout>
     
    MediaApp::MediaApp (QWidget *parent)
    : QWidget (parent)
    {
    //create the player
    m_player = new Player (this);
    connect (m_player, SIGNAL ( stateChanged() ), this, SLOT( onStateChanged() ) );
     
    //create the UI
    QVBoxLayout *appLayout = new QVBoxLayout;
    appLayout ->setContentsMargins (0, 0, 0, 0);
    appLayout ->addWidget (m_player);
     
    setLayout (appLayout);
    setWindowFlags (Qt::FramelessWindowHint);/* enable this for frameless window */
    }
     
    MediaApp::~MediaApp()
    {
    delete m_player;
    }
     
    void MediaApp::openFile(const QString & fileName)
    {
    m_player->stop();
    m_player->setUri(fileName);
    m_player->play();
    }



[PLAYER.H]

    #ifndef PLAYER_H_
    #define PLAYER_H_
     
    #include <QtCore/QTimer>
    #include <QtCore/QTime>
    #include <QGst/Pipeline>
    #include <QGst/Ui/VideoWidget>
     
    class Player : public QGst :: Ui :: VideoWidget
    {
    Q_OBJECT
    public:
    Player(QWidget *parent = 0);
    ~Player();
     
    void setUri(const QString & uri);
    QGst :: State state() const;
     
    public Q_SLOTS:
    void play();
     
    Q_SIGNALS:
    void positionChanged();
    void stateChanged();
     
    private:
    void onBusMessage(const QGst :: MessagePtr & message);
    void handlePipelineStateChange(const QGst :: StateChangedMessagePtr & scm);
     
    QGst :: PipelinePtr m_pipeline;
    QTimer m_positionTimer;
    };
     
    #endif /* PLAYER_H_ */



[PLAYER.CPP]

    #include "player.h"
    #include <QtCore/QDir>
    #include <QtCore/QUrl>
    #include <QGlib/Connect>
    #include <QGlib/Error>
    #include <QGst/Pipeline>
    #include <QGst/ElementFactory>
    #include <QGst/Bus>
    #include <QGst/Message>
    #include <QGst/Query>
    #include <QGst/ClockTime>
    #include <QGst/Event>
    #include <QGst/StreamVolume>
     
    Player::Player(QWidget *parent)
    : QGst :: Ui :: VideoWidget(parent)
    {
    //this timer is used to tell the ui to change its position slider & label
    //every 100 ms, but only when the pipeline is playing
    // connect ( &m_positionTimer, SIGNAL ( timeout () ), this, SIGNAL ( positionChanged () ) );
    }
     
    Player :: ~Player ()
    {
    if (m_pipeline) {
    m_pipeline ->setState (QGst :: StateNull );
    stopPipelineWatch ();
    }
    }
     
    void Player :: setUri (const QString & uri)
    {
    QString realUri = uri;
    //if uri is not a real uri, assume it is a file path
    if (realUri.indexOf("://") < 0) {
    realUri = QUrl :: fromLocalFile (realUri) .toEncoded();
    }
     
     
    if ( !m_pipeline )
    {
    m_pipeline = QGst :: ElementFactory :: make ("playbin2") .dynamicCast <QGst::Pipeline>();
    if (m_pipeline)
    {
    //let the video widget watch the pipeline for new video sinks
    watchPipeline (m_pipeline);
    //watch the bus for messages
    QGst :: BusPtr bus = m_pipeline ->bus();
    bus ->addSignalWatch();
    QGlib :: connect (bus, "message", this, &Player :: onBusMessage);
    }
    else
    {
    qCritical() << "Failed to create the pipeline";
    }
    }
     
    if (m_pipeline)
    {
    m_pipeline- >setProperty ("uri", realUri);
    }
    }
     
     
    QGst :: State Player :: state() const
    {
    return m_pipeline ? m_pipeline->currentState() : QGst :: StateNull;
    }
     
    void Player :: play()
    {
    if (m_pipeline)
    {
    m_pipeline ->setState(QGst :: StatePlaying);
    }
    }
     
    void Player::onBusMessage(const QGst::MessagePtr & message)
    {
    switch ( message->type()) {
    case QGst :: MessageEos : //End of stream. We reached the end of the file.
    {
    if (m_pipeline)
    {
    m_pipeline->setState(QGst::StateNull);
    m_pipeline->setState(QGst::StatePlaying);
    }
    }
    break;
    default:
    break;
    }
    }
Comment 1 André Klapper 2014-03-25 12:40:02 UTC
Please provide a *minimal*, self-contained testcase as attachment.
Comment 2 monalisabarik29 2014-03-27 07:02:15 UTC
(In reply to comment #1)
> Please provide a *minimal*, self-contained testcase as attachment.

if you can build the above code then paste any media file with name XYZ.webm in the same path where your is present.

Please let me know if I missed something in code which is creating memory leak.
Comment 3 George Kiagiadakis 2014-03-27 10:30:27 UTC
How much of memory being leaked are we talking about?
Also, how do you measure it? Have you used valgrind (with G_SLICE=always-malloc - https://developer.gnome.org/glib/unstable/glib-running.html)?
Finally, have you checked if gst-launch leaks as well?
Comment 4 monalisabarik29 2014-04-01 05:35:00 UTC
(In reply to comment #3)
> How much of memory being leaked are we talking about?
> Also, how do you measure it? Have you used valgrind (with G_SLICE=always-malloc
> - https://developer.gnome.org/glib/unstable/glib-running.html)?
> Finally, have you checked if gst-launch leaks as well?

-> valgrind result :
==11520== LEAK SUMMARY:
==11520==    definitely lost: 21,075 bytes in 11 blocks
==11520==    indirectly lost: 11,328 bytes in 352 blocks
==11520==      possibly lost: 3,960,827 bytes in 1,901 blocks
==11520==    still reachable: 4,431,810 bytes in 42,335 blocks
==11520==         suppressed: 0 bytes in 0 blocks
==11520== Reachable blocks (those to which a pointer was found) are not shown.
==11520== To see them, rerun with: --leak-check=full --show-reachable=yes
==11520== 
==11520== For counts of detected and suppressed errors, rerun with: -v
==11520== ERROR SUMMARY: 950 errors from 934 contexts (suppressed: 2 from 2)

-> I am checking memory uses using top command which becomes 85% for my application if it run continuously for 1 day.
Comment 5 monalisabarik29 2014-04-04 06:18:34 UTC
(In reply to comment #3)
> How much of memory being leaked are we talking about?
> Also, how do you measure it? Have you used valgrind (with G_SLICE=always-malloc
> - https://developer.gnome.org/glib/unstable/glib-running.html)?
> Finally, have you checked if gst-launch leaks as well?

Can you help me with an example where we play many media files one after one. In my application I need to play 4-5 media files in loops.
Comment 6 monalisabarik29 2014-04-04 07:25:39 UTC
(In reply to comment #5)
> (In reply to comment #3)
> > How much of memory being leaked are we talking about?
> > Also, how do you measure it? Have you used valgrind (with G_SLICE=always-malloc
> > - https://developer.gnome.org/glib/unstable/glib-running.html)?
> > Finally, have you checked if gst-launch leaks as well?
> 
> Can you help me with an example where we play many media files one after one.
> In my application I need to play 4-5 media files in loops.

after reaching end-of-stream, does setting state to StateNull releases all resources allocated.
Comment 7 Vincent Penquerc'h 2014-06-10 11:23:40 UTC
Could you add those options to valgrind, and post the output ?

--leak-check=full --num-callers=32 --suppressions=$path/gstreamer/common/gst.supp --suppressions=$path/gst-plugins-base/tests/check/gst-plugins-base.supp --suppressions=$path/gst-plugins-good/tests/check/gst-plugins-good.supp --suppressions=$path/gst-plugins-bad/tests/check/gst-plugins-bad.supp --suppressions=$path/gst-plugins-ugly/tests/check/gst-plugins-ugly.supp

With $path replaced with wherever you have installed the gstreamer trees.
Comment 8 Tim-Philipp Müller 2014-06-21 14:15:23 UTC
Closing this since no further details have been provided, and qt-gstreamer has been ported to GStreamer 1.x now.

Please feel free to re-open this bug or file a new bug if you get around to re-testing with a 1.x-based qt-gstreamer and can provide the requested information, thanks!