Commit graph

1342 commits

Author SHA1 Message Date
Havard Graff
87457a862d rtpjitterbuffer: make sure not to drop packets based on skew
One of the jitterbuffers functions is to try and make sense of weird
network behavior.

It is quite unhelpful for the jitterbuffer to start dropping packets
itself when what you are trying to achieve is better network resilience.

In the case of a skew, this could often mean the sender has restarted
in some fashion, and then dropping the very first buffer of this "new"
stream could often mean missing valuable information, like in the case
of video and I-frames.

This patch simply reverts back to the old behavior, prior to 8d955fc32b
and includes the simplest test I could write to demonstrate the behavior,
where a single packet arrives "perfectly", then a 50ms gap happens,
and then two more packets arrive in perfect order after that.

# Conflicts:
#	tests/check/elements/rtpjitterbuffer.c
2019-11-02 23:05:32 +00:00
Edward Hervey
8e1c224fbc good: Avoid usage of deprecated API
GTimeval and related functions are now deprecated in glib.
Replacement APIs have been present since 2.26
2019-10-16 07:46:58 +00:00
Tim-Philipp Müller
c9a47c0c8d Remove autotools build system 2019-10-14 11:04:18 +01:00
Aaron Boxer
46989dca96 documentation: fix a number of typos 2019-10-05 22:38:11 +00:00
Simon Arnling Bååth
8173596ed2 gstrtpjitterbuffer: Custom messages when dropping packets
This commit adds custom element messages for when gstrtpjitterbuffer
drops an incoming rtp packets due to for example arriving too late.
Applications can listen to these messages on the bus which enables
actions to be taken when packets are dropped due to for example high
network jitter.

Two properties has been added, one to enable posting drop messages and
one to set a minimum time between each message to enable throttling the
posting of messages as high drop rates.
2019-10-04 20:31:56 +00:00
Olivier Crête
a24596423a rtpjitterbuffer: Cancel timers instead of just unlocking loop thread
When the queue is full (and adding more packets would risk a seqnum
roll-over), the best approach is to just start pushing out packets
from the other side.  Just pushing out the packets results in the
timers being left hanging with old seqnums, so it's safer to just
execute them immediately in this case. It does limit the timer space
to the time it takes to receiver about 32k packets, but without
extended sequence number, this is the best RTP can do.

This also results in the test no longer needed to have timeouts or
timers as pushing packets in drives everything.

Fixes #619
2019-09-28 07:47:54 -04:00
Nicolas Dufresne
4a9f42430a rtpjitterbuffer: Optimize offset update
As we are applying the same offset over all timers, there timer
ordering won't change, so we can safely skip time-reordering.
2019-09-27 17:34:04 -04:00
Nicolas Dufresne
af1c586c7b rtptimerqueue: Optimize reschedule optations
This basically add ability to choose between inserting from head, tail
or in-place in order to try and minimize the distance to walk through in
the timer queue. This removes an overhead we had seen on high drop rate.
2019-09-27 17:34:04 -04:00
Nicolas Dufresne
1897c1fbe6 rtpjitterbuffer: Fix a typo in comment 2019-09-27 17:34:04 -04:00
Nicolas Dufresne
9ebcadb349 rtpjitterbuffer: Don't use stats timer on the timers queue
The timer passed to update_timers may be from the stats timer. At the
moment, we could endup rescheduling (reusing) that timer onto the normal
timer queue, unschedul it as if it was from the normal timer queue or
duplicate it into the stats timer queue again. This was protected before
as the with the fact the stats timer didn't have a valid idx.
2019-09-27 17:34:04 -04:00
Nicolas Dufresne
81bffb5e5c rtpjitterbuffer: Update timers on ts-offset changes
As the offset is already applied now, we need to update and reschedule
all timers each time the offset is changed. I'm not sure who expect this
to be retro-actively applied, but there was a unit test for it.
2019-09-27 17:34:04 -04:00
Nicolas Dufresne
d4c6c335c5 rtpjitterbuffer: No need to wake the timer thread on head changes
If the jitterbuffer head change, there is no need to systematically
wakeup the timer thread. The timer thread will be waken up on if
an earlier timeout has been pushed. This prevent some more spurious
wakeup when the system is loaded. As a side effect, cranking the clock
may set the clock at an earlier position.
2019-09-27 17:34:04 -04:00
Nicolas Dufresne
36771b75e9 rtpjittterbuffer: Port timers array to RtpTimerQueue
In this patch we now make use of the new RtpTimerQueue instead of the
old GArray. This required a lot of changes all over the place, some of
the important changes are that `timer->timeout` is no longer a PTS but
the actual timeout. This was required to get the RtpTimerQueue sorting
right. The applied offset is saved as `timer->offset`, this allow
retreiving back the PTS when needed.

The clockid updates only happens once per incoming packet. If the
currently schedule timer is before the earliest timer in the queue, we
no longer wakeup the thread. This way, if other timers get setup in the
meantime, this will reduce the number of wakup.

The timer loop code has been mostly rewritten, though the behaviour of
running the lost timers first has been kept (even though there is no
test to show what would be the side effect of doing this differently).

Fixes #608
2019-09-27 17:34:04 -04:00
Nicolas Dufresne
d4b2231de2 rtpjittterbuffer: Port from TimerQueue to RtpTimerQueue 2019-09-27 17:34:04 -04:00
Nicolas Dufresne
f5e3280dbe rtpjitterbuffer: Port use the new RtpTimer structure
First iteration toward porting to the new timer queue.
2019-09-27 17:34:04 -04:00
Nicolas Dufresne
37742cd36d rtptimerqueue: Consolidate a data structure for timers
Implement a single timer queue for all timers. The goal is to always use
ordered queues for storing timers. This way, extracting timers for
execution becomes O(1). This also allow separating the clock wait
scheduling from the timer itself and ensure that we only wake up the
timer thread when strictly needed.

The knew data structure is still O(n) on insertions and reschedule,
but we now use proximity optimization so that normal cases should be
really fast. The GList structure is also embeded intot he RtpTimer
structure to reduce the number of allocations.
2019-09-27 17:34:04 -04:00
Nicolas Dufresne
c917f11ae8 rtpjitterbuffer: Move item structure outside of the element
This moves the RtpJitterBufferStructure type, alloc, free into
rtpjitterbuffer.c/h implementation. jitterbuffer.c strictly rely on
the fact this structure is compatible with GList, and so it make more
sense to keep encapsulate it. Also, anything that could possibly
reduce the amount of code in the element is a win.

In order to support that move, a function pointer to free the data
was added. This also allow making the free function option when
flushing the jitterbuffer.
2019-09-27 13:02:16 -04:00
Nicolas Dufresne
9b706b6220 rtpjitterbuffer: Constify timer pointers where possible
This helps understanding which function modify the Timerdata
and which one does not. This is not always obvious from thelper
name considering recalculate_timer() does not.
2019-09-27 13:02:16 -04:00
Mathieu Duponchelle
b5e414cdc2 rtpbin: add request-jitterbuffer signal
This can be used to pass the threadsharing jitterbuffer from
gst-plugins-rs for example.
2019-09-24 15:33:21 +00:00
Antonio Ospite
8dd03042cc rtpsession: add support for buffer lists on the recv path
The send path in rtpsession processes the buffer list along the way,
sharing info and stats between packets in the same list, because it
assumes that all packets in a buffer list are from the same frame.

However, in the receiving path packets can arrive in all sorts of
arrangements:

  - different sources,
  - different frames (different timestamps),
  - different types (multiplexed RTP and RTCP, invalid RTP packets).

so a more general approach should be used to correctly support buffer
lists in the receive path.

It turns out that it's simpler and more robust to process buffers
individually inside the rtpsession element even if they come in a buffer
list, and then reassemble a new buffer list when pushing the buffers
downstream.

This avoids complicating the existing code to make all functions
buffer-list-aware with the risk of introducing regressions,

To support buffer lists in the receive path and reduce the "push
overhead" in the pipeline, a new private field named processed_list is
added to GstRtpSessionPrivate, it is set in the chain_list handler and
used in the process_rtp callback; this is to achieve the following:

  - iterate over the incoming buffer list;
  - process the packets one by one;
  - add the valid ones to a new buffer list;
  - push the new buffer list downstream.

The processed_list field is reset before pushing a buffer list to be on
the safe side in case a single buffer was to be pushed by upstream
at some later point.

NOTE:

The proposed modifications do not change the behavior of the send path.

The process_rtp callback is called in rtpsource.c by the push_rtp
callback (via source_push_rtp) only when the source is not internal.

So even though push_rtp is also called in the send path, it won't end up
using process_rtp in this case because the source would be internal in
the send path.

The reasoning from above may suggest a future refactoring: push_rtp
might be split to better differentiate the send and receive path.
2019-08-07 15:32:30 -04:00
Mathieu Duponchelle
e18d5d6ec6 rtpfunnel: forward correct segment when switching pad
Forwarding a single segment event from the pad that first gets
chained is incorrect: when that first event was sent by an element
such as x264enc, with its offset start, we end pushing out of segment
buffers for the other pad(s).

Instead, everytime the active pad changes, forward the appropriate
segment event.

Fixes https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/issues/1028
2019-08-06 14:02:50 +00:00
Antonio Ospite
ae48646d8e rtpsource: fix receiver source stats to consider previously queued packets
When it is not clear yet if a packet relative to a source should be
pushed, the packet is put into a queue, this happens in two cases:

  - the source is still in probation;
  - there is a large jump in seqnum, and it is not clear what
    the cause is, future packets will help making a guess.

In either case stats about received packets are not updated at all; and
even if they were, when init_seq() is called it resets all receiver
stats, effectively loosing any possible stat about previously received
packets.

Fix this by taking into account the queued packets and update the stats
when calling init_seq().
2019-08-02 17:22:51 +02:00
Antonio Ospite
cf0ffd8693 rtpsource: clarify meaning of the octets-sent and octets-received stats
The octets-send and octets-received stats count the payload bytes
excluding RTP and lower level headers, clarify that in the
documentation.
2019-08-02 17:22:51 +02:00
Antonio Ospite
821994240e rtpsource: expose field bytes_received in RTPSourceStats
Since commit c971d1a9a (rtpsource: refactor bitrate estimation,
2010-03-02) bytes_received filed in RTPSourceStats is set but then never
used again, expose it so that it can be used  by user code to verify how
many bytes have been received.
2019-08-02 17:22:51 +02:00
Antonio Ospite
9d800cad43 rtpmanager: consider UDP and IP headers in bandwidth calculation
According to RFC3550 lower-level headers should be considered for
bandwidth calculation.

See https://tools.ietf.org/html/rfc3550#section-6.2 paragraph 4:

  Bandwidth calculations for control and data traffic include
  lower-layer transport and network protocols (e.g., UDP and IP) since
  that is what the resource reservation system would need to know.

Fix the source data to accommodate that.

Assume UDPv4 over IP for now, this is a simplification but it's good
enough for now.

While at it define a constant and use that instead of a magic number.

NOTE: this change basically reverts the logic of commit 529f443a6
(rtpsource: use payload size to estimate bitrate, 2010-03-02)
2019-08-02 17:22:51 +02:00
Olivier Crête
9d9d543d5c rtpsession: Also send conflict event when sending packet
If the conflict is detected when sending a packet, then also send an
upstream event to tell the source to reconfigure itself.

Also ignore the collision if we see more than one collision from the same
remote source to avoid problems on loops.
2019-07-06 14:23:20 +00:00
Olivier Crête
37d22186ff rtpjitterbuffer: Unlock output if the queue is full 2019-07-03 18:03:42 +00:00
Thomas Bluemel
080eba64de rtpjitterbuffer: Ignore unsolicited rtx packets.
If an rtx packet arrives that hasn't been requested (it might
have been requested from prior to a reset), ignore it so that
it doesn't inadvertently trigger a clock skew.
2019-07-03 06:23:07 -06:00
Thomas Bluemel
8d955fc32b rtpjitterbuffer: Only calculate skew or reset if no gap.
In the case of reordered packets, calculating skew would cause
pts values to be off. Only calculate skew when packets come
in as expected. Also, late RTX packets should not trigger
clock skew adjustments.

Fixes #612
2019-07-03 06:23:07 -06:00
Olivier Crête
af618cb081 rtpjitterbuffer: max-dropout-time gets cast to int32
So any value over MAXINT32 gets considered as negative and is silently ignored.
2019-07-02 19:59:49 +00:00
Jan Schmidt
53b3f2ddbb rtpjitterbuffer: Clear clock master before unreffing
Make sure to clear any master clock on the media_clock
before unreffing it to release the timer callback that's
updating the clock and keeping it reffed.
2019-06-16 20:36:55 +10:00
Mathieu Duponchelle
ebe2756434 jitterbuffer: unset DTS on output buffers 2019-06-14 16:02:59 +02:00
Mikhail Fludkov
ec5fa49631 rtpjitterbuffer: late packets shouldn't affect PTS of the following packet
If, say, a rtx-packet arrives really late, this can have a dramatic
effect on the jitterbuffer clock-skew logic, having it being reset
and losing track of the current dts-to-pts calculations, directly affecting
the packets that arrive later.

This is demonstrated in the test, where a RTX packet is pushed in really
late, and without this patch the last packet will have its PTS affected
by this, where as a late RTX packet should be redundant information, and
not affect anything.
2019-06-13 11:55:10 +02:00
Mikhail Fludkov
b9c3e354ee rtpjitterbuffer: fix rtx delay calulation when large packet spacing 2019-06-12 11:39:32 +02:00
Stian Selnes
6269ed49ab rtpjitterbuffer: Fix delay for EXPECTED timers added by gaps
This patch corrects the delay set on EXPECTED timers that are added when
processing gaps. Previously the delay could be too small so that
'timout + delay' was much less than 'now', causing the following retries
to be scheduled too early. (They were sent earlier than
rtx-retry-timeout after the previous timeout.)
2019-06-12 11:39:32 +02:00
Havard Graff
8ed7ab178b rtpjitterbuffer: don't try and calculate packet-rate if seqnum are jumping
Turns out that the "big-gap"-logic of the jitterbuffer has been horribly
broken.

For people using lost-events, an RTP-stream with a gap in sequencenumbers,
would produce exactly that many lost-events immediately.
So if your sequence-numbers jumped 20000, you would get 20000 lost-events
in your pipeline...

The test that looks after this logic "test_push_big_gap", basically
incremented the DTS of the buffer equal to the gap that was introduced,
so that in fact this would be more of a "large pause" test, than an
actual gap/discontinuity in the sequencenumbers.

Once the test was modified to not increment DTS (buffer arrival time) with
a similar gap, all sorts of crazy started happening, including adding
thousands of timers, and the logic that should have kicked in, the
"handle_big_gap_buffer"-logic, was not called at all, why?

Because the number max_dropout is calculated using the packet-rate, and
the packet-rate logic would, in this particular test, report that
the new packet rate was over 400000 packets per second!!!

I believe the right fix is to don't try and update the packet-rate if
there is any jumps in the sequence-numbers, and only do these calculations
for nice, sequential streams.
2019-06-12 11:39:31 +02:00
Nicolas Dufresne
f7c712d0b8 rtpssrcdemux: Avoid taking streamlock out-of-band
In this change we now protect the internal srcpads list using the
stream lock and limit usage of the internal stream lock to
preventing data flowing on the other src pad type while creating
and signalling the new pad.

This fixes a deadlock with RTPBin shutdown lock. These two locks would
end up being taken in two different order, which caused a deadlock. More
generally, we should not rely on a streamlock when handling out-of-band
data, so as a side effect, we should not take a stream lock when
iterating internal links.
2019-06-04 09:26:06 -04:00
Vivia Nikolaidou
987230a759 rtpjitterbuffer: Print GstClockTimeDiff as GST_STIME_FORMAT 2019-05-26 17:46:06 +03:00
Mathieu Duponchelle
d704790519 doc: fix element section documentations
Element sections were not rendered anymore after the hotdoc
port, fixing this revealed a few incorrect links.
2019-05-25 16:57:31 +02:00
Nicolas Dufresne
4e0bdca3f0 rtpbin: Improve RTPStorage action signal documentation
This is a tiny clarification as the storage was loosely named "storage".
This change clarify that the storage is specificaly used for received RTP
packets. This is unlike the storage found in rtprtxsend that stores a
backlog of sent RTP packets.
2019-05-25 13:44:00 +02:00
Nicolas Dufresne
947a37f3c8 rtpsession: Always keep at least one NACK on early RTCP
We recently added code to remove outdate NACK to avoid using bandwidth
for packet that have no chance of arriving on time. Though, this had a
side effect, which is that it was to get an early RTCP packet with no
feedback into it. This was pretty useless but also had a side effect,
which is that the RTX RTT value would never be updated. So we we stared
having late RTX request due to high RTT, we'd never manage to recover.

This fixes the regression by making sure we keep at least one NACK in
this situation. This is really light on the bandwidth and allow for
quick recover after the RTT have spiked higher then the jitterbuffer
capacity.
2019-05-17 19:13:22 +00:00
Thibault Saunier
38c5ba90b3 doc: Fix some docstrings 2019-05-13 17:00:00 -04:00
Thibault Saunier
af01988534 doc: Port documentation to hotdoc 2019-05-13 11:34:56 -04:00
Thibault Saunier
232e3682ea Mark some properties as DOC_SHOW_DEFAULT 2019-05-13 10:24:40 -04:00
Thibault Saunier
0a6a62aa76 docs: Port all docstring to gtk-doc markdown 2019-05-13 10:24:40 -04:00
Nicolas Dufresne
a6e7f258ac rtpsource: Add more information to probation warning 2019-05-02 14:44:58 -04:00
Nicolas Dufresne
84c102b6fe rtpsession: Call on-new-ssrc earlier
Right now, we may call on-new-ssrc after we have processed the first
RTP packet. This prevents properly configuring the source as some
property like "probation" are copied internally for use as a
decreasing counter. For this specific property, it prevents the
application from disabling probation on auxiliary sparse stream.

Probation is harmful on sparse streams since the probation algorithm
assume frequent and contiguous RTP packets.
2019-05-02 14:44:58 -04:00
Danny Smith
037d70c01b rtpbin: Free storage when freeing session 2019-04-29 10:57:38 +02:00
Nicolas Dufresne
ec06268ed8 rtpsession: Allow overriding NACK packet creation
This introduce a new signal on RTSession, on-sending-nacks is emited
right before the list of seqnums to be nacked are processed and
transformed into FB Nack. This allow implementing custom nacks
handling through another mechanism with APP feedback.
2019-04-05 18:36:36 -04:00
Mathieu Duponchelle
280d86a841 rtpsession: Add disable-sr-timestamp property
The Onvif Streaming Spec, in section 6.11, mandates that when
Rate-Control is disabled potential RTCP packets shall have
their timestamps set to 0.

<https://www.onvif.org/specs/stream/ONVIF-Streaming-Spec.pdf>
2019-04-05 20:23:08 +02:00