For some reason we have had trouble finding working solutions to this problem online.
Right now our source is a filesrc element. Our current non-solution is to change the pipeline's state to READY, change the location property, and set the pipeline's state to PLAYING (see the change_song method below).
This gives the following error:
CHANGING SONG TO music2.mp3
('ERROR:', 'filesource', ':', 'Internal data stream error.')
('debugging info:', 'gstbasesrc.c(2950): gst_base_src_loop (): /GstPipeline:pipeline0/GstFileSrc:filesource:\nstreaming stopped, reason not-linked (-1)')
We hear the first song playing, but the pipeline crashes when attempting to re-enter the PLAYING state. This is our code:
import gi
import time
import threading
gi.require_version('Gst', '1.0')
from gi.repository import Gst, GObject, GLib
class Server:
def __init__(self):
self.pipeline = None
bus = None
message = None
# initialize GStreamer
Gst.init(None)
# build the pipeline
self.pipeline = Gst.parse_launch('filesrc name=filesource ! queue name=queueelement ! decodebin ! audioconvert ! audioresample ! opusenc ! rtpopuspay ! udpsink port=40401 host=224.1.1.1')
self.filesrc = self.pipeline.get_by_name("filesource")
self.filesrc.set_property("location", "music.mp3")
self.queue = self.pipeline.get_by_name("queueelement")
def hang(self):
# wait until EOS or error
bus = self.pipeline.get_bus()
msg = bus.timed_pop_filtered(Gst.CLOCK_TIME_NONE, Gst.MessageType.ERROR | Gst.MessageType.EOS)
if msg:
t = msg.type
if t == Gst.MessageType.ERROR:
err, dbg = msg.parse_error()
print("ERROR:", msg.src.get_name(), ":", err.message)
if dbg:
print("debugging info:", dbg)
elif t == Gst.MessageType.EOS:
print("End-Of-Stream reached")
else:
# this should not happen. we only asked for ERROR and EOS
print("ERROR: Unexpected message received.")
# free resources
self.pipeline.set_state(Gst.State.NULL)
def start(self):
# start playing
self.pipeline.set_state(Gst.State.PLAYING)
t = threading.Thread(target=self.hang)
t.start()
def change_song(self, song_name):
print("CHANGING SONG TO " + song_name)
self.pipeline.set_state(Gst.State.READY)
self.filesrc.set_property("location", song_name)
self.pipeline.set_state(Gst.State.PLAYING)
s = Server()
s.start()
time.sleep(5)
s.change_song("music2.mp3")
We have also tried the following:
def change_song(self, song_name):
print("CHANGING SONG TO " + song_name)
self.pipeline.set_state(Gst.State.READY)
self.filesrc.unlink(queue)
self.filesrc.set_property("location", song_name)
self.filesrc.link(queue)
self.pipeline.set_state(Gst.State.PLAYING)
but this gives the same error.