python gstreamer memory leak

1.9k views Asked by At

I am using the following code to show slide show via gstreamer (for simplicity, the following just re-shows the same image every second):

# python testcase.py large-image.jpg

import gi
gi.require_version("Gst", "1.0")

from gi.repository import GLib, GObject, Gst
import sys


class Player(object):
    def __init__(self):
        Gst.init(None)

        self.pipeline = Gst.Pipeline()

        self.source_bin = None

        self.sink = Gst.ElementFactory.make("xvimagesink")
        self.pipeline.add(self.sink)

    def play(self):
        self._load_next_file()

    def _load_next_file(self):
        self.pipeline.set_state(Gst.State.READY)

        if self.source_bin is not None:
            self.pipeline.remove(self.source_bin)
            self.source_bin.set_state(Gst.State.NULL)

        self.source_bin = self._create_image_source_bin()
        self.pipeline.add(self.source_bin)
        self.source_bin.link(self.sink)
        self.source_bin.sync_state_with_parent()
        self.pipeline.set_state(Gst.State.PLAYING)

    def _create_image_source_bin(self):
        src = Gst.ElementFactory.make("filesrc")
        src.set_property("location", sys.argv[1])

        decoder = Gst.ElementFactory.make("jpegdec")

        freezer = Gst.ElementFactory.make("imagefreeze")

        GObject.timeout_add(1000, self._on_image_timeout)

        bin = Gst.Bin()
        bin.add(src)
        bin.add(decoder)
        bin.add(freezer)
        bin.add_pad(Gst.GhostPad.new("src", freezer.get_static_pad("src")))
        src.link(decoder)
        decoder.link(freezer)
        return bin

    def _on_image_timeout(self):
        self._load_next_file()
        return False

p = Player()
p.play()

GObject.MainLoop().run()

Memory usage increases every second and never decreases; looks like, old source_bin is not being freed when new one is being created. Is it a bug in gstreamer/python-gstreamer or am I missing something?

1

There are 1 answers

0
Riccardo Cagnasso On

After unlinking and setting state to null of the source_bin, you should unref it to make sure is destroyed.

One note: IMHO the ref/unref system is nice to use in C where you can precisely count the references and it's not so handy in a garbage collected high level environment like python. What I would do in your case (and I have done in a similar problem) is to build a pool of decoding bins and reuse them.