RTSP Server with Tokio rather than GLib?

Wondering whether it is at all possible to use the Gstreamer RTSP server without GLib? I’m using tokio everywhere else so it’d be nice if I didn’t have to introduce something else just for this, is that possible? If so can anyone shed some light on an example of it?

Thanks for any help or advice!

gst-rtsp-server is built completely around the GLib main loop unfortunately, so making that work with tokio instead basically means redesigning the whole thing.

Some years ago I started wroting a new rtsp-server that actually uses async-std (moving that to tokio should be trivial) but it’s a different API and API design completely. Also it’s far from finished feature-wise, and I didn’t have a lot of time to spend on it recently.

Oh that’s very cool

I looked at the “simple” example you have there and it’s quite long though haha

Is it buggy or ready for some use? My project isn’t anything serious but I do want to use things that are relatively stable if I can

I tried my hand at getting glib to run in a separate thread but for some reason it still seems to block everything else

pub(crate) async fn initiate_stream() {
    let (stream, stream_fd) = open_portal().await.expect("failed to open portal");
    let pipewire_node_id = &stream.pipe_wire_node_id();
    let stream_raw_fd = &stream_fd.as_raw_fd();

    println!("node id {}, fd {}", pipewire_node_id, stream_raw_fd);

    let pipeline = format!(
        "pipewiresrc fd={stream_raw_fd} path={pipewire_node_id} min-buffers=8 max-buffers=8 ! queue ! vapostproc ! vah265enc target-usage=7 ref-frames=1 rate-control=4 b-frames=0 ! rtph265pay name=pay0"
    );
    println!("{}", &pipeline);

    std::thread::spawn(move || {
        // let context = MainContext::new();
        let main_loop = MainLoop::new(None, false);

        gst::init().expect("Unable to start gstreamer");
        let server = gst_rtsp_server::RTSPServer::new();
        server.set_address("192.168.1.10");

        let mounts = server.mount_points().unwrap();
        let factory = gst_rtsp_server::RTSPMediaFactory::new();
        factory.set_shared(true);
        factory.set_launch(&pipeline);
        factory.set_buffer_size(0);
        factory.set_latency(0u32);

        let id = server.attach(None).unwrap();
        mounts.add_factory("/", factory);

        println!(
            "Stream ready at rtsp://{}:{}",
            server.address().unwrap().to_string(),
            server.bound_port()
        );

        main_loop.run();
        id.remove();
    })
    .join()
    .unwrap();
}


tokio::spawn(initiate_stream())

Is there a proper intended way to do this?

EDIT: Looks like I can use tokio::task::spawn_blocking but it’s still pretty nasty imo

Don’t .join() the std::thread::spawn() will fix the blocking. A backtrace would also show you the blocking on the .join().

I didn’t initially have the join but it wasn’t working so I added it, I think just await on spawn_blocking seems to work fine though without either problem

Is there an intended way to close the RTSP server gracefully?
When I cntrl-c in the terminal my Android RTSP client doesn’t seem to get a shutdown signal