rtprtxreceive

rtprtxreceive listens to the retransmission events from the downstream rtpjitterbuffer and remembers the SSRC (ssrc1) of the stream and the sequence number that was requested. When it receives a packet with a sequence number equal to one of the ones stored and with a different SSRC, it identifies the new SSRC (ssrc2) as the retransmission stream of ssrc1. From this point on, it replaces ssrc2 with ssrc1 in all packets of the ssrc2 stream and flags them as retransmissions, so that rtpjitterbuffer can reconstruct the original stream.

This algorithm is implemented as specified in RFC 4588.

This element is meant to be used with rtprtxsend on the sender side. See rtprtxsend

Below you can see some examples that illustrate how rtprtxreceive and rtprtxsend fit among the other rtp elements and how they work internally. Normally, hoewever, you should avoid using such pipelines and use rtpbin instead, with its request-aux-sender and request-aux-receiver signals. See rtpbin.

Example pipelines

 gst-launch-1.0 rtpsession name=rtpsession rtp-profile=avpf \
     audiotestsrc is-live=true ! opusenc ! rtpopuspay pt=96 ! \
         rtprtxsend payload-type-map="application/x-rtp-pt-map,96=(uint)97" ! \
         rtpsession.send_rtp_sink \
     rtpsession.send_rtp_src ! identity drop-probability=0.01 ! \
         udpsink host="127.0.0.1" port=5000 \
     udpsrc port=5001 ! rtpsession.recv_rtcp_sink \
     rtpsession.send_rtcp_src ! udpsink host="127.0.0.1" port=5002 \
         sync=false async=false

Send audio stream through port 5000 (5001 and 5002 are just the rtcp link with the receiver)

 gst-launch-1.0 rtpsession name=rtpsession rtp-profile=avpf \
     udpsrc port=5000 caps="application/x-rtp,media=(string)audio,clock-rate=(int)48000,encoding-name=(string)OPUS,payload=(int)96" ! \
         rtpsession.recv_rtp_sink \
     rtpsession.recv_rtp_src ! \
         rtprtxreceive payload-type-map="application/x-rtp-pt-map,96=(uint)97" ! \
         rtpssrcdemux ! rtpjitterbuffer do-retransmission=true ! \
         rtpopusdepay ! opusdec ! audioconvert ! audioresample ! autoaudiosink \
     rtpsession.send_rtcp_src ! \
         udpsink host="127.0.0.1" port=5001 sync=false async=false \
     udpsrc port=5002 ! rtpsession.recv_rtcp_sink

Receive audio stream from port 5000 (5001 and 5002 are just the rtcp link with the sender)

In this example we can see a simple streaming of an OPUS stream with some of the packets being artificially dropped by the identity element. Thanks to retransmission, you should still hear a clear sound when setting drop-probability to something greater than 0.

Internally, the rtpjitterbuffer will generate a custom upstream event, GstRTPRetransmissionRequest, when it detects that one packet is missing. Then this request is translated to a FB NACK in the rtcp link by rtpsession. Finally the rtpsession of the sender side will re-convert it in a GstRTPRetransmissionRequest that will be handled by rtprtxsend. rtprtxsend will then re-send the missing packet with a new srrc and a different payload type (here, 97), but with the same original sequence number. On the receiver side, rtprtxreceive will associate this new stream with the original and forward the retransmission packets to rtpjitterbuffer with the original ssrc and payload type.

 gst-launch-1.0 rtpsession name=rtpsession rtp-profile=avpf \
     audiotestsrc is-live=true ! opusenc ! rtpopuspay pt=97 seqnum-offset=1 ! \
         rtprtxsend payload-type-map="application/x-rtp-pt-map,97=(uint)99" ! \
         funnel name=f ! rtpsession.send_rtp_sink \
     audiotestsrc freq=660.0 is-live=true ! opusenc ! \
         rtpopuspay pt=97 seqnum-offset=100 ! \
         rtprtxsend payload-type-map="application/x-rtp-pt-map,97=(uint)99" ! \
         f. \
     rtpsession.send_rtp_src ! identity drop-probability=0.01 ! \
         udpsink host="127.0.0.1" port=5000 \
     udpsrc port=5001 ! rtpsession.recv_rtcp_sink \
     rtpsession.send_rtcp_src ! udpsink host="127.0.0.1" port=5002 \
         sync=false async=false

Send two audio streams to port 5000.

 gst-launch-1.0 rtpsession name=rtpsession rtp-profile=avpf \
     udpsrc port=5000 caps="application/x-rtp,media=(string)audio,clock-rate=(int)48000,encoding-name=(string)OPUS,payload=(int)97" ! \
         rtpsession.recv_rtp_sink \
     rtpsession.recv_rtp_src ! \
         rtprtxreceive payload-type-map="application/x-rtp-pt-map,97=(uint)99" ! \
         rtpssrcdemux name=demux \
     demux. ! queue ! rtpjitterbuffer do-retransmission=true ! rtpopusdepay ! \
         opusdec ! audioconvert ! autoaudiosink \
     demux. ! queue ! rtpjitterbuffer do-retransmission=true ! rtpopusdepay ! \
         opusdec ! audioconvert ! autoaudiosink \
     udpsrc port=5002 ! rtpsession.recv_rtcp_sink \
     rtpsession.send_rtcp_src ! udpsink host="127.0.0.1" port=5001 \
         sync=false async=false

Receive two audio streams from port 5000.

In this example we are streaming two streams of the same type through the same port. They, however, are using a different SSRC (ssrc is randomly generated on each payloader - rtpopuspay in this example), so they can be identified and demultiplexed by rtpssrcdemux on the receiver side. This is an example of SSRC-multiplexing.

It is important here to use a different starting sequence number (seqnum-offset), since this is the only means of identification that rtprtxreceive uses the very first time to identify retransmission streams. It is an error, according to RFC4588 to have two retransmission requests for packets belonging to two different streams but with the same sequence number. Note that the default seqnum-offset value (-1, which means random) would work just fine, but it is overridden here for illustration purposes.

Hierarchy

GObject
    ╰──GInitiallyUnowned
        ╰──GstObject
            ╰──GstElement
                ╰──rtprtxreceive

Factory details

Authors: – Julien Isorce

Classification:Codec

Rank – none

Plugin – rtpmanager

Package – GStreamer Good Plug-ins

Pad Templates

sink

application/x-rtp:

Presencealways

Directionsink

Object typeGstPad


src

application/x-rtp:

Presencealways

Directionsrc

Object typeGstPad


Action Signals

add-extension

g_signal_emit_by_name (param_0, "add-extension", arg0);
ret = param_0.emit ("add-extension", arg0)
let ret = param_0.emit ("add-extension", arg0);

Add ext as an extension for writing part of an RTP header extension onto outgoing RTP packets. Currently only supports using the following extension URIs. All other RTP header extensions are copied as-is.

  • "urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id": will be removed
  • "urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id": will be written instead of the "rtp-stream-id" header extension.

Parameters:

param_0 (GstElement *)
No description available
arg0 (GstRTPHeaderExtension *)
No description available

Flags: Run Last / Action

Since : 1.22


clear-extensions

g_signal_emit_by_name (object, "clear-extensions");
ret = object.emit ("clear-extensions")
let ret = object.emit ("clear-extensions");

Clear all RTP header extensions used by rtprtxreceive.

Parameters:

object (GstElement *)

the GstRTPBasePayload

Flags: Run Last / Action

Since : 1.22


Properties

num-rtx-assoc-packets

“num-rtx-assoc-packets” guint

Number of retransmission packets correctly associated with retransmission requests

Flags : Read

Default value : 0


num-rtx-packets

“num-rtx-packets” guint

Number of retransmission packets received

Flags : Read

Default value : 0


num-rtx-requests

“num-rtx-requests” guint

Number of retransmission events received

Flags : Read

Default value : 0


payload-type-map

“payload-type-map” GstStructure *

Map of original payload types to their retransmission payload types

Flags : Read / Write


ssrc-map

“ssrc-map” GstStructure *

Map of SSRCs to their retransmission SSRCs for SSRC-multiplexed mode.

If an application know this information already (WebRTC signals this in their SDP), it can allow the rtxreceive element to know a packet is a "valid" RTX packet even if it has not been requested.

Flags : Read / Write

Since : 1.22


The results of the search are