goodrobots / visiond

Python/Gstreamer based project to stream video from embedded system cameras in various ways
MIT License
10 stars 3 forks source link

RTSP server fails after first connection #9

Closed fnoop closed 4 years ago

fnoop commented 4 years ago

Once a successful connection and stream is made, any subsequent connections fail:

Feb 09 17:04:13 maverick-raspberrylite python3[15446]: 2020-02-09 17:04:13,428 - Visiond - INFO - Creating RTSP factory element: <GstRtsp.RTSPUrl object at 0xb5520ab0 (GstRTSPUrl at 0x2105ad0)>
Feb 09 17:04:13 maverick-raspberrylite python3[15446]: gst_ghost_pad_new: assertion '!gst_pad_is_linked (target)' failed
Feb 09 17:04:13 maverick-raspberrylite python3[15446]: gst_pad_set_active: assertion 'GST_IS_PAD (pad)' failed
Feb 09 17:04:13 maverick-raspberrylite python3[15446]: gst_element_add_pad: assertion 'GST_IS_PAD (pad)' failed
Feb 09 17:04:13 maverick-raspberrylite python3[15446]: gst_rtsp_stream_new: assertion 'GST_IS_PAD (pad)' failed
Feb 09 17:04:13 maverick-raspberrylite python3[15446]: gst_rtsp_stream_set_multicast_iface: assertion 'GST_IS_RTSP_STREAM (stream)' failed
Feb 09 17:04:13 maverick-raspberrylite python3[15446]: gst_rtsp_stream_set_profiles: assertion 'GST_IS_RTSP_STREAM (stream)' failed
Feb 09 17:04:13 maverick-raspberrylite python3[15446]: gst_rtsp_stream_set_protocols: assertion 'GST_IS_RTSP_STREAM (stream)' failed
Feb 09 17:04:13 maverick-raspberrylite systemd[1]: maverick-visiond.service: Main process exited, code=killed, status=11/SEGV
Feb 09 17:04:13 maverick-raspberrylite systemd[1]: maverick-visiond.service: Failed with result 'signal'.
fnoop commented 4 years ago

Need to work out how to access the RTSPMedia created by RTSPMediaFactory and set reusable to true.

fnoop commented 4 years ago

If the RTSPMediaFactory is set to shared, and the RTSPMedia is set to reusable, then the subclassed factory no longer tears down the pipeline and can be shared by multiple clients. However, after the last client has disconnected the media seems to be destroyed, or no longer useable. There needs to be a way to block this from happening, or else recreating the factory once the media is unuseable. Either we can try to look at factory client callbacks, or a more brute force approach might be to create a client connection from within the server so no matter what external clients do there will always be a connected client to prevent the media from being pulled down.

https://github.com/GStreamer/gst-rtsp-server/tree/master/docs https://lazka.github.io/pgi-docs/GstRtspServer-1.0/classes/RTSPMediaFactory.html https://lazka.github.io/pgi-docs/GstRtspServer-1.0/classes/RTSPMedia.html https://lazka.github.io/pgi-docs/GstRtspServer-1.0/classes/RTSPServer.html https://github.com/gkralik/python-gst-tutorial

fnoop commented 4 years ago

Listen to clients being removed, and then if this is the last client destroy the server, release the resources and recreate:

        self.rtspsessions = self.rtspserver.get_session_pool()
        self.rtspsessions.connect("session_removed", self.on_rtspsession_removed)

http://gstreamer-devel.966125.n4.nabble.com/Destroy-Gstreamer-RTSP-Server-Object-without-exiting-main-application-td4686001.html

All seems very unnecessary - why can't it just keep the pipeline alive and wait for the next client?

fnoop commented 4 years ago
* TEARDOWN

 A TEARDOWN request will first locate the GstRTSPSessionMedia of the URL. It
 will then remove all transports from the streams, making sure that streaming
 stops to the clients. It will then remove the GstRTSPSessionMedia and
 GstRTSPStreamTransport objects. Finally the GstRTSPSession is released back
 into the pool.

 When there are no more references to the GstRTSPMedia, the media pipeline is
 shut down (with _unprepare) and destroyed. This will then also destroy the
 GstRTSPStream objects.

This implies that if we can create a reference to GstRTSPMedia and hold it, then the media pipeline will stay intact.

fnoop commented 4 years ago

OK creating a fake client works - it holds open the constructed media object forever, at the expense of some CPU usage. Will do for now.