Loop a video with gst-rtsp-server

Tyler Compton xaviosx at gmail.com
Mon Mar 30 21:46:07 UTC 2020


Thank you for the tip, Fabián! I was not aware of segment seeking, it
definitely seems like a better way to loop. However, it didn't entirely
solve my problem. The video stream loops, but the client (in this case,
gst-play-1.0) closes the connection because it expects the video stream to
only last as long as the video file's original run time.

I looked into the way gst-rtsp-server determines run time, and I found the
"gst_rtsp_stream_query_stop" method does this by reading the pipeline's
current segment stop time. Since the stop time will in my case always be
the end of the video, gst-rtsp-server assumes that to be the run time of
the stream. I was able to get around this by overriding
RTSPMedia.do_query_stop to always return -1, which causes gst-rtsp-server
to assume this is an unending source.

If anyone knows a more elegant solution I would be interested to hear it,
but for the time being this seems to work well.

My complete RTSPMedia subclass looks like this:

class RTSPMedia(GstRtspServer.RTSPMedia):
    def do_query_stop(self, _stop):
        return -1

    def do_handle_message(self, message: Gst.Message):
        if message.type == Gst.MessageType.STATE_CHANGED:
            # Set up segment seeking once the pipeline starts playing
            pipeline = self.get_property("element")
            _, new_state, _ = message.parse_state_changed()
            if message.src == pipeline and new_state == Gst.State.PLAYING:
                seek_result = pipeline.seek(
                    rate=1.0,
                    format=Gst.Format.TIME,
                    flags=Gst.SeekFlags.FLUSH | Gst.SeekFlags.SEGMENT,
                    start_type=Gst.SeekType.SET,
                    start=0,
                    stop_type=Gst.SeekType.NONE,
                    stop=-1)
                if not seek_result:
                    raise RuntimeError(f"Failed to send seek event")
        elif message.type == Gst.MessageType.SEGMENT_DONE:
            # Seek playback to the start when the segment is done
            seek_result = pipeline.seek(
                rate=1.0,
                format=Gst.Format.TIME,
                flags=Gst.SeekFlags.SEGMENT,
                start_type=Gst.SeekType.SET,
                start=0,
                stop_type=Gst.SeekType.NONE,
                stop=-1)
            if not seek_result:
                raise RuntimeError(f"Failed to send seek event")

        return GstRtspServer.RTSPMedia.do_handle_message(self, message)

On Sun, Mar 29, 2020 at 8:03 PM Fabián Orccón <cfoch.fabian at gmail.com>
wrote:

> Hello,
> Do a SEGMENT seek to 0.0 when you receive Gst.MessageType.SEGMENT_DONE.
>
>
> \o
>
> On Sun, Mar 29, 2020 at 9:45 PM Tyler Compton <xaviosx at gmail.com> wrote:
>
>> Hi list,
>>
>> I've been trying to create an RTSP stream from a video file source and
>> have the video loop back to the start when it ends. This has ended up being
>> quite tricky and I suspect I'm missing something obvious. My pipeline looks
>> something like this:
>>
>> filesrc location=video.mp4 ! parsebin ! rtph264pay name=pay0
>>
>> My current solution is to subclass RTSPMedia and override the
>> do_handle_message method. I capture EOS messages and seek the pipeline back
>> to the start. However, this doesn't seem to have any effect. The stream
>> just ends like normal.
>>
>> class MyRTSPMedia(GstRtspServer.RTSPMedia):
>>     def do_handle_message(self, message):
>>         print("Got message:", message.type)
>>         if message.type == Gst.MessageType.EOS:
>>             pipeline: Gst.Pipeline = self.get_property("element")
>>             seek_result = pipeline.seek(
>>                 rate=1.0,
>>                 format=Gst.Format.TIME,
>>                 flags=Gst.SeekFlags.FLUSH,
>>                 start_type=Gst.SeekType.SET,
>>                 start=0,
>>                 stop_type=Gst.SeekType.NONE,
>>                 stop=-1)
>>             if not seek_result:
>>                 logging.error(
>>                     f"Failed to seek stream back to start! Seek "
>>                     f"returned {seek_result}")
>>             return True
>>         return GstRtspServer.RTSPMedia.do_handle_message(self, message)
>>
>> I provide this class to my RTSPMediaFactory with the set_media_gtype
>> method.
>>
>> I noticed that gst-rtsp-server reports the video length to the client, so
>> the client expects the stream to only last for as long as the original
>> video. I would like the client to treat the source as a live, unending
>> stream. Is it possible that this inaccurate runtime is the source of my
>> problem?
>> _______________________________________________
>> gstreamer-devel mailing list
>> gstreamer-devel at lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
>>
> _______________________________________________
> gstreamer-devel mailing list
> gstreamer-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/gstreamer-devel/attachments/20200330/e778070c/attachment.htm>


More information about the gstreamer-devel mailing list