The timestamp offset can be negative, and it can be a bigger negative
number than the latency introduced by the rtpjitterbuffer so the overall
timeout offset can be negative.
Using the negative offset for calculating how many packets can still
arrive in time when encountering a lost packet in an equidistant stream
would then overflow and instead of considering fewer packets lost a lot
more packets are considered lost.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5318>
This is a fix for a data race leading to:
> GLib-CRITICAL: g_hash_table_foreach:
> assertion 'version == hash_table->version' failed
Identified sequence:
* `rtp_session_on_timeout` acquires the lock on `session` and proceeds with its
processing.
* `rtp_session_process_rtcp` is called (debug log : received RTCP packet) and
attempts to acquire the lock on `session`, which is still held by
`rtp_session_on_timeout`.
* as part of an hash table iterator, `rtp_session_on_timeout` transitively
invokes `source_caps` which releases the lock on `session` so as to call
`session->callbacks.caps`.
* Since `rtp_session_process_rtcp` was waiting for the lock to be released, it
succeeds in acquiring it and proceeds with `rtp_session_process_rr` which
transitively calls `g_hash_table_insert` via `add_source`.
* After `source_caps` re-acquires the lock and gives the control flow back to
`rtp_session_on_timeout`, the hash table iterator is changed, resulting in the
assertion failure.
This commits copies `sess->ssrcs[sess->mask_idx]` and iterates on the copy so
the iterator is not affected by a concurrent change due to the lock being
released in the `source_caps` callback.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4585>
While testing the [implementation for insertable streams] in `webrtcsink` &
`webrtcsrc`, I encountered critical warnings, which turned out to result from
two race conditions in `rtpsession`. Both race conditions produce:
> GLib-CRITICAL: g_hash_table_foreach:
> assertion 'version == hash_table->version' failed
This commit fixes one of the race conditions observed.
In its simplest form, the test consists in 2 pipelines and a Signalling server:
* pipelines_sink: audiotestsrc ! webrtcsink
* pipelines_src: webrtcsrc ! appsrc
1. Set `pipelines_sink` to `Playing`.
2. The Signalling server delivers the `producer_id`.
3. Initialize `pipelines_src` to establish a session with `producer_id`.
4. Set `pipelines_src` to `Playing`.
5. Wait for a buffer to be received by the `appsrc`.
6. Set `pipelines_src` to `Null`.
7. Set `pipelines_sink` to `Null`.
The race condition happens in the following sequence:
* `webrtcsink` runs a task to periodically retrieve statistics from `webrtcbin`.
This transitively ends up executing `rtp_session_create_stats`.
* `pipelines_sink` is set to `Null`.
* In `Paused` to `Ready`, `gst_rtp_session_change_state()` calls
`rtp_session_reset()`.
* The assertion failure occurs when `rtp_session_reset` is called while
`rtp_session_create_stats` is executing.
This is because `rtp_session_create_stats` acquires the lock on `session` prior
to calling `g_hash_table_foreach`, but `rtp_session_reset` doesn't acquire the
lock before calling `g_hash_table_remove_all`.
Acquiring the lock in `rtp_session_reset` fixes the issue.
[implementing insertable streams support]: https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/1176
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4532>
The previous code would only check if two packets in a row were duplicates. If
not (i.e. a packet is a duplicate of a packet received slightly before) the code
would generate completely bogus FCI because it assumes there were no duplicates
present in the array.
In order to be efficient, just store all received packets and remove the
duplicates just before the FCI is generated once the array of observations have
been sorted by seqnum.
Fixes TWCC usage with moderate to high packet duplication.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4378>
All the RTP src pads were sharing the same stream-id while each actually
carry a different stream.
This was causing problem for example when funneling the streams together
and then trying to split them using 'streamiddemux'.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3866>
Currently in rtp_session_send_rtp(), the existing ntp-64 RTP header
extension timestamp is updated with the actual NTP time before sending
the packet. However, there are some circumstances where we would like
to preserve the original timestamp obtained from reference timestamp
buffer metadata.
This commit provides the ability to configure whether or not to update
the ntp-64 header extension timestamp with the actual NTP time via the
update-ntp64-header-ext boolean property. The property is also exposed
via rtpbin. Default property value of TRUE will preserve existing
behavior (update ntp-64 header ext with actual NTP time).
Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/1580
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3451>
Previously we tried to route an incoming RTCP FB FIR to the correct ssrc
using the "media source" component of the RTCP FB message. However,
according to RFC5104 (section 4.3.1.2) the "media source" SHALL be set
to 0. Instead the ssrc(s) in use are propagated via the FCI data. Now
a specific GstForceKeyUnit event is sent for every ssrc.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3292>
RTP source statistics are tracked for local senders by
treating them as a receiver of their own outbound packets.
Accordingly, track the highest packet seqnum so that the
packets-lost calculation generates a sensible number instead
of always reporting -$number_of_packets_sent
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3454>
Timers for RTX packets are dealt with later in update_rtx_timers(), and
timers for non-RTX packets would potentially also be unscheduled a
second time from there so avoid that.
Also don't shadow the timer variable from the outer scope but instead
make use of it directly.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2973>
Otherwise we won't send the protection packets for the last few
packets when a stream ends.
Also send EOS on the FEC src row pad immediately, and on the FEC src
column pad after draining is complete. This makes it so that the FEC
src pads on rtpbin behave the same way as the RTCP src pads on rtpbin
when EOS is received on the send_rtp_sink pad.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2863>
https://bugzilla.gnome.org/show_bug.cgi?id=741398 changed
rtpptdemux in 2014 to not post a GST_ELEMENT_ERROR on the
bus when dropping an invalid (non-RTP) packet, but still
returned GST_FLOW_ERROR upstream - so the pipeline still
stops, but now without a useful bus error.
Return GST_FLOW_OK instead, so the pipeline keeps
running. Some old telephony equipment can send invalid
packets before the real RTP traffic starts.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2520>
Mixing C loops with switch statements is a bad idea as break has a
different meaning in both. Breaking inside the switch statements wrongly
caused further loop iterations.
Instead use goto to get out of the loop and continue to do another loop
iteration, and never ever use break except for the end of a case.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2336>
Previously, we only added it when actually performing synchronization
based on the NTP time.
The information can be useful downstream in other situations too, and
we can compute a NTP time as soon as we get a sender report with the
relevant information.
Co-authored-by: Mathieu Duponchelle <mathieu@centricular.com>
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2252>
The RTCP SR packet might be without SDES in case of a reduced-size RTCP
packet. For syncing purposes the CNAME is needed but it might be known
already from an earlier RTCP packet or out of band, via the SDP for
example.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2132>