python http streaming via multisocketsink with gstreamer
Alexander Heinz
mailsanmich at gmx.li
Mon Jun 25 17:54:08 UTC 2018
Hello,
I would like to stream a single source to multiple clients via http.
Clients should be able to connect and disconnect while streaming is
already ongoing.
I am aware of http launch but I would prefer to do this in python
because I would like to add additional functionality later that easier
for me to write in python.
I use the gstreamer packages that come with raspbian Jessie (GStreamer
1.4.4) on a Raspberry Pi 2
My questions:
- I cannot stream to more than one client with the code below and I
would like to know what I need to change to make it work
- If I stop my single client and try to reconnect afterwards, the stream
does not start again. What needs to be done to fix this?
- the code does not even work for a single client if I use raspbian
stretch (which comes with gstreamer 1.10.4). Any idea what needs to be
changed?
Thank you for your help!
Best regards,
Alex
P.S.:
here is the code:
#!/usr/bin/env python
import os,signal,sys,time
import gi,BaseHTTPServer,SocketServer
gi.require_version('Gst', '1.0')
from gi.repository import GObject, Gio, Gst
# Initialize the gstreamer toolchain
Gst.init(None)
GObject.threads_init()
# reopen stdout in non-buffered mode
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
class gst_broadcaster:
def __init__(self, gpipeline):
self.pipeline = Gst.parse_launch(gpipeline)
self.source = self.pipeline.get_by_name('source')
self.sink = self.pipeline.get_by_name('sink')
self.bus = self.pipeline.get_bus()
self.bus.add_signal_watch()
self.bus.connect('message',self.message_handler)
self.sink.connect('client-added',self.add_client)
self.sink.connect('client-socket-removed',self.remove_client)
self.sink.set_property('timeout',30000000000)
self.clients = []
self.pipeline.set_state(Gst.State.READY)
def kill(self):
self.pipeline.set_state(Gst.State.NULL)
def add_client(self,sink,gsock):
self.pipeline.set_state(Gst.State.PLAYING)
self.clients.append(gsock)
def remove_client(self,sink,gsock):
self.sink.emit('remove-flush',gsock)
if gsock in self.clients:
self.clients.remove(gsock)
def handle(self, wfile):
gsock = Gio.Socket().new_from_fd(wfile.fileno())
self.sink.emit("add", gsock)
while gsock in self.clients:
time.sleep(1)
def message_handler(self,bus,message):
msgType = message.type
if msgType == Gst.MessageType.ERROR:
self.kill()
print "\n Unable to play Video. Error: ", \
message.parse_error()
elif msgType == Gst.MessageType.EOS:
self.kill()
def get_pipeline():
r= "videotestsrc name=source is-live=true ! x264enc "
r+= ' ! h264parse ! matroskamux name=mux streamable=true !
multisocketsink name=sink'
return r
def get_player():
pipeline = get_pipeline()
player = gst_broadcaster(pipeline)
return player
class MyHTTPHandler(BaseHTTPServer.BaseHTTPRequestHandler):
def do_HEAD(self):
self.send_response(200)
self.send_header("Content-type", "video/x-matroska")
self.end_headers()
def do_GET(self):
self.do_HEAD()
player.handle(self.wfile)
class ThreadedHTTPServer(SocketServer.ThreadingMixIn,
BaseHTTPServer.HTTPServer):
"""Handle requests in a separate thread."""
port = 8001
httpd = ThreadedHTTPServer(("0.0.0.0", port), MyHTTPHandler)
def httpd_start():
print time.asctime(), "server start (port %i)" % port
httpd.serve_forever()
def httpd_shutdown():
httpd.server_close()
print time.asctime(), "server stop"
def signal_handler(signal, frame):
try:
httpd_shutdown()
finally:
sys.exit(0)
if __name__ == '__main__':
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
player = get_player()
try:
httpd_start()
except KeyboardInterrupt:
pass
httpd_shutdown()
More information about the gstreamer-devel
mailing list