Correct way to change source (filesrc location) in python
whoman at gmail.com
whoman at gmail.com
Wed Sep 2 04:19:41 UTC 2020
Hello,
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?
Currently, the way I'm changing the source is :
1. Set pipeline state to READY:
2. change location property of filesrc:
3. Set pipeline state to PLAYING
(example code below)
Is this the correct way, or am I missing some steps?
My python example is below.
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.
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).
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).
Jeffy's response:
https://github.com/rockchip-linux/gstreamer-rockchip/issues/70#issuecomment-684649694
"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...
1/ you need to add a bus watch to handle messages(especially the state
changed messages in your case)
2/ you need to run the glib main loop"
My example is below
please note: this small leak does not occur when using avdec_h264 in place
of mppvideodec.
Can anyone confirm which steps I may be missing when
stopping/changingSrc/starting the pipeline?
Thanks
import tty
import sys
import termios
import gi
import subprocess
import os, signal
import time
from time import sleep
gi.require_version('Gst', '1.0')
gi.require_version('GLib', '2.0')
gi.require_version('GObject', '2.0')
from gi.repository import Gst, GObject, GLib
GObject.threads_init()
Gst.init(sys.argv)
#GST PIPELINE
#GST - create the elements
source = Gst.ElementFactory.make("filesrc", "source")
demux = Gst.ElementFactory.make("qtdemux", "demux")
parse = Gst.ElementFactory.make("h264parse", "parse")
decoder = Gst.ElementFactory.make("mppvideodec", "decoder")
video_convert = Gst.ElementFactory.make("videoconvert", "videoconvert")
sink = Gst.ElementFactory.make("kmssink", "sink")
#GST - create the empty pipeline
p1 = Gst.Pipeline.new("test-pipeline")
if not p1 or not source or not sink:
print("ERROR: Not all elements could be created")
sys.exit(1)
#GST - add and link elements in pipeline
p1.add(source)
p1.add(demux)
p1.add(parse)
p1.add(decoder)
p1.add(video_convert)
p1.add(sink)
if not source.link(demux):
print("ERROR: Could not link source to demux")
sys.exit(1)
#if not demux.link(parse):
# print("ERROR: Could not link demux to parse")
# sys.exit(1)
if not parse.link(decoder):
print("ERROR: Could not link parse to decoder")
sys.exit(1)
if not decoder.link(video_convert):
print("ERROR: Could not link decoder to video_convert")
# sys.exit(1)
#if not decoder.link(sink):
if not video_convert.link(sink):
print("ERROR: Could not link scaler to sink")
sys.exit(1)
# set the source element's location property
source.set_property("location", "/video/g62.mp4")
ret = p1.get_state(1)
print ret.state
#GST - handler for the pad-added signal
def demux_on_pad_added(src, new_pad):
if new_pad.get_name() == "video_0":
print(
"Received new pad '{0:s}' from '{1:s}'".format(
new_pad.get_name(),
src.get_name()))
# attempt the link
sink_pad = parse.get_static_pad("sink")
new_pad_caps = new_pad.get_current_caps()
new_pad_struct = new_pad_caps.get_structure(0)
new_pad_type = new_pad_struct.get_name()
print(new_pad_type)
ret = new_pad.link(sink_pad)
if not ret == Gst.PadLinkReturn.OK:
print("Type is '{0:s}' but link failed".format(new_pad_type))
else:
print("Link succeeded (type '{0:s}')".format(new_pad_type))
return
return
# connect to the pad-added signal
demux.connect("pad-added", demux_on_pad_added)
def dispose_src_cb(src):
src.set_state(Gst.State.NULL)
p1.set_state(Gst.State.PLAYING)
#GST - Puase playback, set "location", and begin playback
def PlayVideo1():
# GST stop pipeline
ret = p1.get_state(1)
print "current state:"
print ret.state
print "setting STATE to READY"
p1.set_state(Gst.State.READY)
# GLib.idle_add(dispose_src_cb, decoder)
ret = p1.get_state(1)
print "current state:"
print ret.state
# GST set filesrc 'location'
print "changing filesrc location"
source.set_property('location', '/video/test1.mp4')
print "filesrc location has been changed. Setting STATE back to PLAYING"
# GST start pipeline
# decoder.sync_state_with_parent()
p1.set_state(Gst.State.PLAYING)
ret = p1.get_state(1)
print "current state:"
print ret.state
def PlayVideo2():
# GST stop pipeline
p1.set_state(Gst.State.READY)
# GLib.idle_add(dispose_src_cb, decoder)
# GST set filesrc 'location'
source.set_property('location', '/video/test2.mp4')
# GST start pipeline
# decoder.sync_state_with_parent()
p1.set_state(Gst.State.PLAYING)
#KEYBOARD - detect key press, and launch GST PlayVideo functions
orig_settings = termios.tcgetattr(sys.stdin)
tty.setcbreak(sys.stdin)
x = 0
while x != chr(27): # ESC
x=sys.stdin.read(1)[0]
print("You pressed", x)
if x == "1":
PlayVideo1()
if x == "2":
PlayVideo2()
if x == "x":
exit()
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, orig_settings)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/gstreamer-devel/attachments/20200901/27cfaa6d/attachment-0001.htm>
More information about the gstreamer-devel
mailing list