After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 770133 - Out of segment data sent to clients when not wanted
Out of segment data sent to clients when not wanted
Status: RESOLVED OBSOLETE
Product: GStreamer
Classification: Platform
Component: gst-rtsp-server
git master
Other Linux
: Normal normal
: git master
Assigned To: GStreamer Maintainers
GStreamer Maintainers
Depends on:
Blocks:
 
 
Reported: 2016-08-19 08:54 UTC by Linus Svensson
Modified: 2018-11-03 15:40 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Drop buffers outside segment (3.62 KB, patch)
2016-08-26 13:31 UTC, Joakim Johansson
none Details | Review

Description Linus Svensson 2016-08-19 08:54:54 UTC
gst-rtsp-server sometimes sends buffers that are outside the current segment (before the segment in this case), when it performs a seek.

The problem appears if a client issues an RTSP PLAY (without specifying a new start position) when the server is PAUSED at a delta unit in the stream, and the RTSP PLAY method requires the server to perform a seek. A seek will be required; if the stop position is updated (Range: npt=135.42), scale or speed is changed (currently not supported though), or something else that's updated with a seek. The server always performs a FLUSHING seek, but that is unfortunate since we want to keep the current position in case the start position isn't changed. GstRTSPMedia will actually seek to the current position (obtained with a gst_query_position on the pipeline) and set GST_SEEK_FLAG_ACCURATE in such case. The result (in a use case with a H.264 stream contained a matroska file) from such seek is that the segment will have a start time matching the seek'ed start position and the first buffer will be the previous non-delta unit in the stream (That's of course good :)), which results in an RTP stream starting at position X, and the Range in the RTSP PLAY response is position X + the delta between the seek'ed position and the non-delta unit. In this case the connected client already have received all frames until the delta frame at the seek'ed position.


Would it make sense to drop all buffers outside of the segment in GstRtpBasePayload, or make it configurable to do so?
Comment 1 Joakim Johansson 2016-08-26 13:31:10 UTC
Created attachment 334224 [details] [review]
Drop buffers outside segment

This patch drops all buffers that are outside the segment.

This solves the problem with the call to gst_segment_to_stream_time that returns GST_CLOCK_TIME_NONE for a buffer that is outside the segment.

This can happen if an empty PLAY request is received (after PAUSE).

The result in that scenario is a empty RTP-Info is being sent which is solved with this patch.
Comment 2 Joakim Johansson 2016-11-02 15:10:27 UTC
Hi,

I heard from Linus which talked with Slomo during the Gstreamer conference that there where some discussions of removing Accurate Seek functionality and instead use KeyUnit Seek.

I have done a quick test of using KeyUnit for this use case that we have problem with:

1) Play with a Range

2) Pause

3) Empty Play requested

Since it is a onvif stream do we want to update the extension headers of buffers that are still in queue and therefore forces a seek from the application with no range set which today triggers the accurate seek (but in this test changed to keyunit seek).

Comparing Accurate and KeyUnit:

Accurate seek does not work onfly because there will be segment data before the start position which will result in the error print “Failed to get stream time” in gstrtponviftimestamp which means that the buffers are sent without valid time information.

This is solved with a patch provided with this bugzilla case which drops all buffers before the accurate position (in my test was 18 buffers dropped) but this is data that the client have already received before the Pause command and this should be correct.

KeyUnit seek does not need any dropping functionality but in the tests that I have done will the empty play request cause a jump back between 0.6s – 1.2s (this can be a much larger jump depending on how frequent the I-frames is coming).

I see a couple of problems with KeyUnit approach:
1) The application might not like to receive an old chunk of data again, worst case is the same data played twice (if not dropped by application)
2) Does KeyUnit approach follow the specification?

Important parts of the specification: rfc2326

A PLAY request without a Range header is legal. It starts playing a stream from the beginning unless the stream has been paused. If a stream has been paused via PAUSE, stream delivery resumes at the pause point. If a stream is playing, such a PLAY request causes no further action and can be used by the client to test server liveness.

Any server resources are kept, though servers MAY close the session and free resources after being paused for the duration specified with the timeout parameter of the Session header in the SETUP message.

If the Range header is missing, stream delivery is interrupted immediately on receipt of the message and the pause point is set to the current normal play time.

A PAUSE request discards all queued PLAY requests. However, the pause point in the media stream MUST be maintained. A subsequent PLAY request without Range header resumes from the pause point.

My opinion is that KeyUnit Seek will not follow the specification because the pause point will not be maintained and used when resuming after the empty play request.


While testing have I also seen one more thing that looks strange:

1) Play with a Range

2) Play with a new Range (seek)

In step 2 are the rtptimestamp (received from gstrtpbasepayload) reset and the same rtptimestamp are re-used again (but the correct data is handled)

This is because gstrtpbasepayload set a ts_base when the element is going from ready to paused and then is there a running clock that is added to the base to get the rtptimestamp for each buffer.

But the running time is reset at the seek operation so the same timestamps are “re-used”.

Is this according to the specifications?

This is taken from Appendix B: Interaction with RTP (rfc2326)

 As an example, assume a clock frequency of 8000 Hz, a packetization
   interval of 100 ms and an initial sequence number and timestamp of
   zero. First we play NPT 10 through 15, then skip ahead and play NPT
   18 through 20. The first segment is presented as RTP packets with
   sequence numbers 0 through 49 and timestamp 0 through 39,200. The
   second segment consists of RTP packets with sequence number 50
   through 69, with timestamps 40,000 through 55,200.

Should the ts_base be set to last rtptimestamp when performing the seek and then reset the running clock?
Comment 3 Joakim Johansson 2016-12-19 11:11:21 UTC
Please review or comment
Comment 4 GStreamer system administrator 2018-11-03 15:40:13 UTC
-- GitLab Migration Automatic Message --

This bug has been migrated to freedesktop.org's GitLab instance and has been closed from further activity.

You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.freedesktop.org/gstreamer/gst-rtsp-server/issues/25.