I have written a simple python API to control a gstreamer RTSP server. I have a couple of configurable parameters for the stream that I want to change from the API.
The way I stop the stream does indeed prevent new connections from being made(so something right is happening), but I have two problems: It doesn't kill existing connections(I'm assuming it's therefore not a complete reset) and more importantly it doesn't load the new settings if changed unless I restart the whole fastapi server.
from threading import Thread
import json, os
import gi
gi.require_version('Gst', '1.0')
gi.require_version('GstRtspServer', '1.0')
from gi.repository import GLib, Gst, GstRtspServer
from fastapi import FastAPI
app = FastAPI()
loop = GLib.MainLoop()
CONFIG_DEFAULTS = {
'host': '127.0.0.1',
'port': '8554',
'mount': '/test',
'width': '1280',
'height': '800',
'bitrate': '50000',
'fps': '30'
}
CONFIGFILE = "config.cfg"
def load_config():
with open(CONFIGFILE) as f:
return json.load(f)
def save_config(config):
with open(CONFIGFILE, 'w') as f:
json.dump(config, f)
return True
@app.on_event("startup")
async def startup_event():
if not os.path.exists(CONFIGFILE):
with open(CONFIGFILE, 'w') as f:
json.dump(CONFIG_DEFAULTS, f)
@app.get("/get-fps")
def get_fps():
config = load_config()
return config['fps']
@app.get("/set-fps/{fps}")
def set_fps(fps: int):
config = load_config()
config['fps'] = fps
save_config(config)
return True
@app.get("/get-bitrate")
def get_bitrate():
config = load_config()
return config['bitrate']
@app.get("/set-bitrate/{bitrate}")
def set_bitrate(bitrate: int):
config = load_config()
config['bitrate'] = bitrate
save_config(config)
return True
@app.get("/get-resolution")
def get_resolution():
config = load_config()
return {
'width': config['width'],
'height': config['height'],
}
@app.get("/set-resolution/{width}&{height}")
def set_resolution(width: int, height: int):
config = load_config()
config['width'] = width
config['height'] = height
save_config(config)
return True
@app.get("/get-url")
def get_url():
config = load_config()
return config['host'] + ":" + config['port'] + config['mount']
@app.get("/start-stream")
def start_stream():
Gst.init(None)
config = load_config()
server = GstRtspServer.RTSPServer()
port = config['port']
mount = config['mount']
width = str(config['width'])
height = str(config['height'])
fps = str(config['fps'])
bitrate = str(config['bitrate'])
server.service = port
mounts = server.get_mount_points()
factory = GstRtspServer.RTSPMediaFactory()
pipeline = "v4l2src device=/dev/video0 io-mode=2 ! " + \
"image/jpeg,width="+width+",height="+height+",framerate="+fps+"/1 ! " + \
"nvjpegdec ! " + \
"video/x-raw ! " + \
"omxh264enc bitrate="+bitrate+" control-rate=constant ! " + \
"rtph264pay name=pay0 pt=96"
factory.set_launch(pipeline)
factory.set_shared(True)
mounts.add_factory(mount, factory)
server.attach()
loop_thread = Thread(target=run_loop)
loop_thread.start()
return 'stream ready at rtsp://127.0.0.1:%s%s' % (port, mount)
def run_loop():
global loop
loop.run()
@app.get("/stop-stream")
def stop_stream():
global loop
loop.quit()
return True
I have also tried with an unref call to context but perhaps I am missing something in how the server is setup.
loop.quit()
loop.get_context().unref()