New to Gstreamer, trying to create an RTSP server that consumes a source once per output stream. Code follows. In the factory do_create_element(), if I use the source_pipeline as a return value, I am able to connect to the server and consume the stream. However, as expected, if I connect multiple clients, the server crashes with an error saying the src pad is already connected. My idea was to use the tee element, add a queue after it, and wrap the queue in a pipeline (since I need a GstBin element to give back from the factory). However, this does not work. When I connect a first client to server, nothing happens server-side (as-in, no crashes. The function is called and exits successfully). However, client side, no stream is read, with a 'SDP contains no stream error' (see the console output after the code).
I tried connecting the tee manually to the queue (line left in comment) instead of using the pipeline to do it, but nothing changes. I suspect the queue needs something to consume it, but I'm not sure how/what to use (or if that's the actual issue).
Here is a minimal example:
import gi
gi.require_version("Gst", "1.0")
gi.require_version("GstRtspServer", "1.0")
# noinspection PyUnresolvedReferences
from gi.repository import Gst, GstRtspServer, GObject
def create_source():
s_src = "videotestsrc ! video/x-raw,rate=30,width=320,height=240,format=I420"
s_h264 = "x264enc tune=zerolatency"
pipeline_str = "( {s_src} ! queue max-size-buffers=1000 name=q_enc ! {s_h264} ! rtph264pay name=pay0 pt=96 )".format(
**locals()
)
return Gst.parse_launch(pipeline_str)
def _main():
GObject.threads_init()
Gst.init(None)
source = create_source()
tee = Gst.ElementFactory.make("tee", "tee")
source_pipeline = Gst.Pipeline()
source_pipeline.add(source)
source_pipeline.add(tee)
source_pipeline.set_state(Gst.State.PLAYING)
class Factory(GstRtspServer.RTSPMediaFactoryURI):
def __init__(self):
super(Factory, self).__init__()
self._n = 0
def do_create_element(self, url): # -> GstBin (Pipeline)
print("in [Factory] do_create_element")
source_pipeline.set_state(Gst.State.PAUSED)
stream_pipeline = Gst.Pipeline()
# Create a new queue to buffer the tee's output
q = Gst.ElementFactory.make("queue")
stream_pipeline.add(q)
source_pipeline.add(tee)
source_pipeline.add(stream_pipeline)
# tee.link(q)
stream_pipeline.set_state(Gst.State.PLAYING)
source_pipeline.set_state(Gst.State.PLAYING)
return stream_pipeline
factory = Factory()
factory.set_shared(True)
server = GstRtspServer.RTSPServer()
server.get_mount_points().add_factory("/endpoint", factory)
server.attach(None)
loop = GObject.MainLoop()
loop.run()
if __name__ == "__main__":
_main()
Here is the shell output when connecting:
> gst-launch-1.0 rtspsrc location=rtsp://127.0.0.1:8554/endpoint ! rtph264depay ! h264parse ! mp4mux ! filesink location=file.mp4
Setting pipeline to PAUSED ...
Pipeline is live and does not need PREROLL ...
Progress: (open) Opening Stream
Pipeline is PREROLLED ...
Prerolled, waiting for progress to finish...
Progress: (connect) Connecting to rtsp://127.0.0.1:8554/endpoint
Progress: (open) Retrieving server options
Progress: (open) Retrieving media info
ERROR: from element /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0: Could not get/set settings from/on resource.
Additional debug info:
../gst/rtsp/gstrtspsrc.c(7637): gst_rtspsrc_setup_streams_start (): /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0:
SDP contains no streams
ERROR: pipeline doesn't want to preroll.
Setting pipeline to NULL ...
Freeing pipeline ...
Thanks ahead!