<div dir="ltr"><div>Hello,<br>Can anyone help me confirm that I'm doing the correct process/workflow in order to change the source (filesrc) of a pipeline dynamically in python?<br><br>Currently, the way I'm changing the source is :<br><br>1.  Set pipeline state to READY:<br>2.  change location property of filesrc:<br>3.  Set pipeline state to PLAYING<br><br>(example code below)<br><br>Is this the correct way, or am I missing some steps?<br>My python example is below.<br><br>The reason I ask is that I am using rockchip's mppvideodec (h264 hardware GST decoder element for rockchip).  I'm experiencing a tiny continuous memory leak while playing h264 videos with rockchip's hardware decoder.  This leak is very small, so in order to show the memory leak, I made a simple python script that changes source once per second.  <br><br>The maintainer of gstreamer-rockchip has suggested that the way I'm changing the source might not be correct, and that I should be handling state change messages from the bus (somehow).<br><br>Now, this maintainer (Jeffy) is a really great person and a great maintainer, and over the last month or two he has helped me VERY MUCH to debug many problems I was experiencing with 'changing the source' (filesrc location) with gstreamer-rockchip elements.  Because of this, I want to follow his advice and determine if there are steps I'm missing when changing source (stopping/starting pipeline).<br><br><br>Jeffy's response:  <a href="https://github.com/rockchip-linux/gstreamer-rockchip/issues/70#issuecomment-684649694">https://github.com/rockchip-linux/gstreamer-rockchip/issues/70#issuecomment-684649694</a><br><br>"guessing you just cannot do it this way, since the state changing would create and post an async message to the pipeline bus, which needs to be handled...<br>1/ you need to add a bus watch to handle messages(especially the state changed messages in your case)<br>2/ you need to run the glib main loop"<br><br><br><br>My example is below<br>please note:  this small leak does not occur when using avdec_h264 in place of mppvideodec.<br><br>Can anyone confirm which steps I may be missing when stopping/changingSrc/starting the pipeline?<br><br>Thanks</div><div><br></div><div><br></div><div><br></div><div><br></div><div>import tty<br>import sys<br>import termios<br>import gi<br>import subprocess<br>import os, signal<br>import time<br>from time import sleep<br>gi.require_version('Gst', '1.0')<br>gi.require_version('GLib', '2.0')<br>gi.require_version('GObject', '2.0')<br>from gi.repository import Gst, GObject, GLib<br>GObject.threads_init()<br>Gst.init(sys.argv)<br><br><br><br>#GST PIPELINE<br>#GST - create the elements<br>source = Gst.ElementFactory.make("filesrc", "source")<br>demux = Gst.ElementFactory.make("qtdemux", "demux")<br>parse = Gst.ElementFactory.make("h264parse", "parse")<br>decoder = Gst.ElementFactory.make("mppvideodec", "decoder")<br>video_convert = Gst.ElementFactory.make("videoconvert", "videoconvert")<br>sink = Gst.ElementFactory.make("kmssink", "sink")<br><br>#GST - create the empty pipeline<br>p1 = Gst.Pipeline.new("test-pipeline")<br><br>if not p1 or not source or not sink:<br>  print("ERROR: Not all elements could be created")<br>   sys.exit(1)<br><br>#GST - add and link elements in pipeline<br>p1.add(source)<br>p1.add(demux)<br>p1.add(parse)<br>p1.add(decoder)<br>p1.add(video_convert)<br>p1.add(sink)<br><br>if not source.link(demux):<br>     print("ERROR: Could not link source to demux")<br>      sys.exit(1)<br>#if not demux.link(parse):<br>#      print("ERROR: Could not link demux to parse")<br>#              sys.exit(1)<br>if not parse.link(decoder):<br>      print("ERROR: Could not link parse to decoder")<br>     sys.exit(1)<br>if not decoder.link(video_convert):<br>      print("ERROR: Could not link decoder to video_convert")<br>#            sys.exit(1)<br>#if not decoder.link(sink):<br>if not video_convert.link(sink):<br>    print("ERROR: Could not link scaler to sink")<br>       sys.exit(1)<br><br># set the source element's location property<br>source.set_property("location", "/video/g62.mp4")<br><br>ret = p1.get_state(1)<br>print ret.state<br><br><br><br>#GST - handler for the pad-added signal<br>def demux_on_pad_added(src, new_pad):<br>        if new_pad.get_name() == "video_0":<br>         print(<br>                        "Received new pad '{0:s}' from '{1:s}'".format(<br>                             new_pad.get_name(),<br>                           src.get_name()))<br><br>            # attempt the link<br>            sink_pad = parse.get_static_pad("sink")<br>             new_pad_caps = new_pad.get_current_caps()<br>             new_pad_struct = new_pad_caps.get_structure(0)<br>                new_pad_type = new_pad_struct.get_name()<br>              print(new_pad_type)<br>           ret = new_pad.link(sink_pad)<br>          if not ret == Gst.PadLinkReturn.OK:<br>                   print("Type is '{0:s}' but link failed".format(new_pad_type))<br>               else:<br>                 print("Link succeeded (type '{0:s}')".format(new_pad_type))<br>         return<br>        return<br><br># connect to the pad-added signal<br>demux.connect("pad-added", demux_on_pad_added)<br><br><br><br>def dispose_src_cb(src):<br>    src.set_state(Gst.State.NULL)<br><br><br>p1.set_state(Gst.State.PLAYING)<br><br><br>#GST - Puase playback, set "location", and begin playback<br>def PlayVideo1():<br>#  GST stop pipeline<br>        ret = p1.get_state(1)<br>        print "current state:"<br>        print ret.state<br>        print "setting STATE to READY"<br>        p1.set_state(Gst.State.READY)<br>#        GLib.idle_add(dispose_src_cb, decoder)<br>        ret = p1.get_state(1)<br>        print "current state:"<br>        print ret.state<br><br><br><br>#    GST set filesrc 'location'<br>        print "changing filesrc location"<br>        source.set_property('location', '/video/test1.mp4')<br>  print "filesrc location has been changed.  Setting STATE back to PLAYING"<br><br>#       GST start pipeline<br>#        decoder.sync_state_with_parent()<br>        p1.set_state(Gst.State.PLAYING)<br>        ret = p1.get_state(1)<br>        print "current state:"<br>        print ret.state<br><br>        <br>def PlayVideo2():<br>#  GST stop pipeline<br>        p1.set_state(Gst.State.READY)<br>#       GLib.idle_add(dispose_src_cb, decoder)<br><br>#    GST set filesrc 'location'<br>        source.set_property('location', '/video/test2.mp4')<br>   <br>#     GST start pipeline<br>#   decoder.sync_state_with_parent()<br>        p1.set_state(Gst.State.PLAYING)<br><br>#KEYBOARD - detect key press, and launch GST PlayVideo functions<br>orig_settings = termios.tcgetattr(sys.stdin)<br><br>tty.setcbreak(sys.stdin)<br>x = 0<br>while x != chr(27): # ESC<br>    x=sys.stdin.read(1)[0]<br>    print("You pressed", x)<br>    if x == "1":<br>        PlayVideo1()<br>    if x == "2":<br>        PlayVideo2()<br>    if x == "x":<br>        exit()<br>                <br>termios.tcsetattr(sys.stdin, termios.TCSADRAIN, orig_settings)  <br></div></div>