What is a possible way to loop video playback in an RTSPServer implementation? (I’m using rust, but happy to translate examples in c or python).
I’ve tried sending a SEGMENT seek to the pipeline at the beginning (which works) though the pipeline still receives EOS before SEGMENT_DONE is sent, and I have no opportunity to drop the EOS event.
My factory launch string is:
filesrc name=input location=/tmp/clip.mp4 \
! qtdemux name=demux ! queue ! rtph265pay name=pay0 pt=96
I’ve connected the RTSPMedia object’s ‘handle-message’ signal and can receive the EOS and SEGMENT_DONE events there, but cannot cause the EOS to be dropped from this handler. Maybe it’s possible but I haven’t yet figured out how.
I’ve also attached a pad probe to the filesrc in attempts to intercept an EOS message there, to no avail.
As of the current state, my clip (which is 3s long) plays successfully for it’s normal duration (verified in gst-play-1.0 rtsp://…) and terminates.
Any pointers on how I can loop this clip?
For context, my overall goal is to set up an ONVIF test camera where a pre-encoded video on a loop stands in for dynamically generated content that would otherwise consume cpu time with encoding…
I have done the same thing myself.
The filesrc operate in pull-mode and you won’t be recieve the EOS event there, instead put the probe on the demuxer and you will find it.
You can intercept these events, I would recommend reading this.
So say you listen to Events downstream from the demuxer and you don’t want EOS to propagate you can ex. return Handled. There’s also other PadProbeReturn types that you might find useful.
As for the looping I took same approach as you mentioned with segment seeking. So in the beginning do a seek to zero; we will then receive SEGMENT_DONE instead of EOS [*]. When you receive it, segment-seek back to zero again. On the demuxer.
Good luck, let me know if anything comes up!
Thanks much for the pointers! Can’t believe I hadn’t stumbled across the probes design doc–very useful.
So changing the return from Drop
to Handled
on the EOS and SEGMENT_DONE messages helped. I was getting segfaults when returning Drop
from these probes before, so had abandoned that route.
I’m performing an initial SEGMENT + FLUSH seek when the pipe transitions to Playing, and intercepting any SEGMENT_DONE or EOS messages and sending another SEGMENT seek direct to the demux element.
Still playback stops after 3s on the client; I think I’ve stumbled on another piece of this puzzle…in the logs, it seems to indicate that a ‘Pause’ request is being sent from the client, and the client (gst-play-1.0 in my case) never sees any other duration than the 3s of the original clip.
rtspclient rtsp-client.c:4015:handle_request: client 0x7c4ba8006740: received a request PAUSE rtsp://127.0.0.1:44873/cam/ 1.0
Do I need to intercept/modify duration queries somewhere to indicate that the stream is live? and/or not pauseable?
On that note, I did try adding an identity single-segment=true
after the demux, and this causes the client to show unlimited duration, but still it stops at 3s.
Ok, got it working.
After paying more attention to the seeking docs, I updated my code to send SEGMENT + FLUSHING on the first seek (I actually did this upon catching/handling the EOS, but you could also do it anywhere early in the pipeline, I think), and then just sent a SEGMENT seek on intercepting any subsequent SEGMENT_DONE events.
I kicked off these seeks from a probe on video (source) pad of the demux element, and sent them directly to the demux element (rather than the pipeline).
The final piece (based on referencing the replay example) was to add a query probe on the payloader sink pad which responds to the SEEKING and SEGMENT queries as in the example; this seems to take care of the client sending a PAUSE and TEARDOWN at the end of the 3s duration.
Adding an identity single-segment
in the pipeline was not required, but without it, the client may display the stream as having a fixed duration as opposed to undefined duration.
@AxelTob thanks again for the pointers and advice!
Sorry for late follow-up.
Exactly!
Send an initial segment | flush initially in the pipeline and seek back to zero on SEGMENT_DONE event.
It’s a good idea to use [quote=“matt-deboer, post:4, topic:3528”]
identity single-segment
[/quote]
for continues timestamps. Probably needed on the client so it doesn’t disgard them / appear as live