mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
rtptwcc: move TWCC-logic over to the TWCC-manager
Prevent cluttering up the rtpsession, and keeping things localized. Also write TWCC-seqnums for *all* streams in the session if configured by caps. A while back WebRTC was not doing TWCC for audio, basically breaking the whole idea of a "transport-wide seqnuencenumber" applying for all bundled streams. However, they have since fixed this, and now it no longers makes sense to be able to single out certain payloadtypes for use with TWCC, rather just including them all. This also makes using RTX, RED, FEC etc much simpler, as it will apply to them all as they enter the rtpsession. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/merge_requests/927>
This commit is contained in:
parent
ee361bf958
commit
b66c6714fa
3 changed files with 140 additions and 91 deletions
|
@ -117,9 +117,6 @@ enum
|
|||
else \
|
||||
(avg) = ((val) + (15 * (avg))) >> 4;
|
||||
|
||||
|
||||
#define TWCC_EXTMAP_STR "http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01"
|
||||
|
||||
/* GObject vmethods */
|
||||
static void rtp_session_finalize (GObject * object);
|
||||
static void rtp_session_set_property (GObject * object, guint prop_id,
|
||||
|
@ -2196,22 +2193,6 @@ clean_packet_info (RTPPacketInfo * pinfo)
|
|||
g_bytes_unref (pinfo->header_ext);
|
||||
}
|
||||
|
||||
static gint32
|
||||
packet_info_get_twcc_seqnum (RTPPacketInfo * pinfo, guint8 ext_id)
|
||||
{
|
||||
gint32 val = -1;
|
||||
gpointer data;
|
||||
guint size;
|
||||
|
||||
if (pinfo->header_ext &&
|
||||
gst_rtp_buffer_get_extension_onebyte_header_from_bytes (pinfo->header_ext,
|
||||
pinfo->header_ext_bit_pattern, ext_id, 0, &data, &size)) {
|
||||
if (size == 2)
|
||||
val = GST_READ_UINT16_BE (data);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
source_update_active (RTPSession * sess, RTPSource * source,
|
||||
gboolean prevactive)
|
||||
|
@ -2237,16 +2218,7 @@ source_update_active (RTPSession * sess, RTPSource * source,
|
|||
static void
|
||||
process_twcc_packet (RTPSession * sess, RTPPacketInfo * pinfo)
|
||||
{
|
||||
gint32 twcc_seqnum;
|
||||
|
||||
if (sess->twcc_recv_ext_id == 0)
|
||||
return;
|
||||
|
||||
twcc_seqnum = packet_info_get_twcc_seqnum (pinfo, sess->twcc_recv_ext_id);
|
||||
if (twcc_seqnum == -1)
|
||||
return;
|
||||
|
||||
if (rtp_twcc_manager_recv_packet (sess->twcc, twcc_seqnum, pinfo)) {
|
||||
if (rtp_twcc_manager_recv_packet (sess->twcc, pinfo)) {
|
||||
RTP_SESSION_UNLOCK (sess);
|
||||
|
||||
/* TODO: find a better rational for this number, and possibly tune it based
|
||||
|
@ -3151,29 +3123,6 @@ invalid_packet:
|
|||
}
|
||||
}
|
||||
|
||||
static guint8
|
||||
_get_extmap_id_for_attribute (const GstStructure * s, const gchar * ext_name)
|
||||
{
|
||||
guint i;
|
||||
guint8 extmap_id = 0;
|
||||
guint n_fields = gst_structure_n_fields (s);
|
||||
|
||||
for (i = 0; i < n_fields; i++) {
|
||||
const gchar *field_name = gst_structure_nth_field_name (s, i);
|
||||
if (g_str_has_prefix (field_name, "extmap-")) {
|
||||
const gchar *str = gst_structure_get_string (s, field_name);
|
||||
if (str && g_strcmp0 (str, ext_name) == 0) {
|
||||
gint64 id = g_ascii_strtoll (field_name + 7, NULL, 10);
|
||||
if (id > 0 && id < 15) {
|
||||
extmap_id = id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return extmap_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* rtp_session_update_send_caps:
|
||||
* @sess: an #RTPSession
|
||||
|
@ -3229,29 +3178,9 @@ rtp_session_update_send_caps (RTPSession * sess, GstCaps * caps)
|
|||
sess->internal_ssrc_from_caps_or_property = FALSE;
|
||||
}
|
||||
|
||||
sess->twcc_send_ext_id = _get_extmap_id_for_attribute (s, TWCC_EXTMAP_STR);
|
||||
if (sess->twcc_send_ext_id > 0) {
|
||||
GST_INFO ("TWCC enabled for send using extension id: %u",
|
||||
sess->twcc_send_ext_id);
|
||||
}
|
||||
rtp_twcc_manager_parse_send_ext_id (sess->twcc, s);
|
||||
}
|
||||
|
||||
static void
|
||||
send_twcc_packet (RTPSession * sess, RTPPacketInfo * pinfo)
|
||||
{
|
||||
gint32 twcc_seqnum;
|
||||
|
||||
if (sess->twcc_send_ext_id == 0)
|
||||
return;
|
||||
|
||||
twcc_seqnum = packet_info_get_twcc_seqnum (pinfo, sess->twcc_send_ext_id);
|
||||
if (twcc_seqnum == -1)
|
||||
return;
|
||||
|
||||
rtp_twcc_manager_send_packet (sess->twcc, twcc_seqnum, pinfo);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* rtp_session_send_rtp:
|
||||
* @sess: an #RTPSession
|
||||
|
@ -3286,7 +3215,7 @@ rtp_session_send_rtp (RTPSession * sess, gpointer data, gboolean is_list,
|
|||
current_time, running_time, -1))
|
||||
goto invalid_packet;
|
||||
|
||||
send_twcc_packet (sess, &pinfo);
|
||||
rtp_twcc_manager_send_packet (sess->twcc, &pinfo);
|
||||
|
||||
source = obtain_internal_source (sess, pinfo.ssrc, &created, current_time);
|
||||
if (created)
|
||||
|
@ -4947,10 +4876,5 @@ void
|
|||
rtp_session_update_recv_caps_structure (RTPSession * sess,
|
||||
const GstStructure * s)
|
||||
{
|
||||
guint8 ext_id = _get_extmap_id_for_attribute (s, TWCC_EXTMAP_STR);
|
||||
if (ext_id > 0) {
|
||||
sess->twcc_recv_ext_id = ext_id;
|
||||
GST_INFO ("TWCC enabled for recv using extension id: %u",
|
||||
sess->twcc_recv_ext_id);
|
||||
}
|
||||
rtp_twcc_manager_parse_recv_ext_id (sess->twcc, s);
|
||||
}
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
GST_DEBUG_CATEGORY_EXTERN (rtp_session_debug);
|
||||
#define GST_CAT_DEFAULT rtp_session_debug
|
||||
|
||||
#define TWCC_EXTMAP_STR "http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01"
|
||||
|
||||
#define REF_TIME_UNIT (64 * GST_MSECOND)
|
||||
#define DELTA_UNIT (250 * GST_USECOND)
|
||||
#define MAX_TS_DELTA (0xff * DELTA_UNIT)
|
||||
|
@ -71,6 +73,10 @@ struct _RTPTWCCManager
|
|||
{
|
||||
GObject object;
|
||||
|
||||
guint8 send_ext_id;
|
||||
guint8 recv_ext_id;
|
||||
guint16 send_seqnum;
|
||||
|
||||
guint mtu;
|
||||
guint max_packets_per_rtcp;
|
||||
GArray *recv_packets;
|
||||
|
@ -155,6 +161,51 @@ recv_packet_init (RecvPacket * packet, guint16 seqnum, RTPPacketInfo * pinfo)
|
|||
packet->ts = pinfo->running_time;
|
||||
}
|
||||
|
||||
static guint8
|
||||
_get_extmap_id_for_attribute (const GstStructure * s, const gchar * ext_name)
|
||||
{
|
||||
guint i;
|
||||
guint8 extmap_id = 0;
|
||||
guint n_fields = gst_structure_n_fields (s);
|
||||
|
||||
for (i = 0; i < n_fields; i++) {
|
||||
const gchar *field_name = gst_structure_nth_field_name (s, i);
|
||||
if (g_str_has_prefix (field_name, "extmap-")) {
|
||||
const gchar *str = gst_structure_get_string (s, field_name);
|
||||
if (str && g_strcmp0 (str, ext_name) == 0) {
|
||||
gint64 id = g_ascii_strtoll (field_name + 7, NULL, 10);
|
||||
if (id > 0 && id < 15) {
|
||||
extmap_id = id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return extmap_id;
|
||||
}
|
||||
|
||||
void
|
||||
rtp_twcc_manager_parse_recv_ext_id (RTPTWCCManager * twcc,
|
||||
const GstStructure * s)
|
||||
{
|
||||
twcc->recv_ext_id = _get_extmap_id_for_attribute (s, TWCC_EXTMAP_STR);
|
||||
if (twcc->recv_ext_id > 0) {
|
||||
GST_INFO ("TWCC enabled for recv using extension id: %u",
|
||||
twcc->recv_ext_id);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
rtp_twcc_manager_parse_send_ext_id (RTPTWCCManager * twcc,
|
||||
const GstStructure * s)
|
||||
{
|
||||
twcc->send_ext_id = _get_extmap_id_for_attribute (s, TWCC_EXTMAP_STR);
|
||||
if (twcc->send_ext_id > 0) {
|
||||
GST_INFO ("TWCC enabled for send using extension id: %u",
|
||||
twcc->send_ext_id);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
rtp_twcc_manager_set_mtu (RTPTWCCManager * twcc, guint mtu)
|
||||
{
|
||||
|
@ -180,6 +231,63 @@ rtp_twcc_manager_get_feedback_interval (RTPTWCCManager * twcc)
|
|||
return twcc->feedback_interval;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_get_twcc_seqnum_data (RTPPacketInfo * pinfo, guint8 ext_id, gpointer * data)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
guint size;
|
||||
|
||||
if (pinfo->header_ext &&
|
||||
gst_rtp_buffer_get_extension_onebyte_header_from_bytes (pinfo->header_ext,
|
||||
pinfo->header_ext_bit_pattern, ext_id, 0, data, &size)) {
|
||||
if (size == 2)
|
||||
ret = TRUE;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
_set_twcc_seqnum_data (GstBuffer * buf, guint8 ext_id, guint16 seqnum)
|
||||
{
|
||||
GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
|
||||
gpointer data;
|
||||
|
||||
if (gst_rtp_buffer_map (buf, GST_MAP_READWRITE, &rtp)) {
|
||||
if (gst_rtp_buffer_get_extension_onebyte_header (&rtp,
|
||||
ext_id, 0, &data, NULL)) {
|
||||
GST_WRITE_UINT16_BE (data, seqnum);
|
||||
}
|
||||
gst_rtp_buffer_unmap (&rtp);
|
||||
}
|
||||
}
|
||||
|
||||
static guint16
|
||||
rtp_twcc_manager_set_send_twcc_seqnum (RTPTWCCManager * twcc,
|
||||
RTPPacketInfo * pinfo)
|
||||
{
|
||||
guint16 seqnum = twcc->send_seqnum++;
|
||||
pinfo->data = gst_buffer_make_writable (pinfo->data);
|
||||
_set_twcc_seqnum_data (pinfo->data, twcc->send_ext_id, seqnum);
|
||||
return seqnum;
|
||||
}
|
||||
|
||||
static gint32
|
||||
rtp_twcc_manager_get_recv_twcc_seqnum (RTPTWCCManager * twcc,
|
||||
RTPPacketInfo * pinfo)
|
||||
{
|
||||
gint32 val = -1;
|
||||
gpointer data;
|
||||
|
||||
if (twcc->recv_ext_id == 0)
|
||||
return val;
|
||||
|
||||
if (_get_twcc_seqnum_data (pinfo, twcc->recv_ext_id, &data)) {
|
||||
val = GST_READ_UINT16_BE (data);
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static gint
|
||||
_twcc_seqnum_sort (gconstpointer a, gconstpointer b)
|
||||
{
|
||||
|
@ -621,13 +729,17 @@ _many_packets_some_lost (RTPTWCCManager * twcc, guint16 seqnum)
|
|||
}
|
||||
|
||||
gboolean
|
||||
rtp_twcc_manager_recv_packet (RTPTWCCManager * twcc,
|
||||
guint16 seqnum, RTPPacketInfo * pinfo)
|
||||
rtp_twcc_manager_recv_packet (RTPTWCCManager * twcc, RTPPacketInfo * pinfo)
|
||||
{
|
||||
gboolean send_feedback = FALSE;
|
||||
RecvPacket packet;
|
||||
gint32 seqnum;
|
||||
gint diff;
|
||||
|
||||
seqnum = rtp_twcc_manager_get_recv_twcc_seqnum (twcc, pinfo);
|
||||
if (seqnum == -1)
|
||||
return FALSE;
|
||||
|
||||
/* if this packet would exceed the capacity of our MTU, we create a feedback
|
||||
with the current packets, and start over with this one */
|
||||
if (_exceeds_max_packets (twcc, seqnum)) {
|
||||
|
@ -666,8 +778,10 @@ rtp_twcc_manager_recv_packet (RTPTWCCManager * twcc,
|
|||
recv_packet_init (&packet, seqnum, pinfo);
|
||||
g_array_append_val (twcc->recv_packets, packet);
|
||||
twcc->last_seqnum = seqnum;
|
||||
GST_LOG ("Receive: twcc-seqnum: %u, marker: %d, ts: %" GST_TIME_FORMAT,
|
||||
seqnum, pinfo->marker, GST_TIME_ARGS (pinfo->running_time));
|
||||
|
||||
GST_LOG ("Receive: twcc-seqnum: %u, pt: %u, marker: %d, ts: %"
|
||||
GST_TIME_FORMAT, seqnum, pinfo->pt, pinfo->marker,
|
||||
GST_TIME_ARGS (pinfo->running_time));
|
||||
|
||||
if (!pinfo->marker)
|
||||
twcc->packet_count_no_marker++;
|
||||
|
@ -732,15 +846,22 @@ sent_packet_init (SentPacket * packet, guint16 seqnum, RTPPacketInfo * pinfo)
|
|||
}
|
||||
|
||||
void
|
||||
rtp_twcc_manager_send_packet (RTPTWCCManager * twcc,
|
||||
guint16 seqnum, RTPPacketInfo * pinfo)
|
||||
rtp_twcc_manager_send_packet (RTPTWCCManager * twcc, RTPPacketInfo * pinfo)
|
||||
{
|
||||
SentPacket packet;
|
||||
guint16 seqnum;
|
||||
|
||||
if (twcc->send_ext_id == 0)
|
||||
return;
|
||||
|
||||
seqnum = rtp_twcc_manager_set_send_twcc_seqnum (twcc, pinfo);
|
||||
|
||||
sent_packet_init (&packet, seqnum, pinfo);
|
||||
g_array_append_val (twcc->sent_packets, packet);
|
||||
|
||||
GST_LOG ("Send: twcc-seqnum: %u, marker: %d, ts: %" GST_TIME_FORMAT,
|
||||
seqnum, pinfo->marker, GST_TIME_ARGS (pinfo->running_time));
|
||||
|
||||
GST_LOG ("Send: twcc-seqnum: %u, pt: %u, marker: %d, ts: %" GST_TIME_FORMAT,
|
||||
seqnum, pinfo->pt, pinfo->marker, GST_TIME_ARGS (pinfo->running_time));
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -53,16 +53,20 @@ struct _RTPTWCCPacket
|
|||
|
||||
RTPTWCCManager * rtp_twcc_manager_new (guint mtu);
|
||||
|
||||
void rtp_twcc_manager_parse_recv_ext_id (RTPTWCCManager * twcc,
|
||||
const GstStructure * s);
|
||||
void rtp_twcc_manager_parse_send_ext_id (RTPTWCCManager * twcc,
|
||||
const GstStructure * s);
|
||||
|
||||
void rtp_twcc_manager_set_mtu (RTPTWCCManager * twcc, guint mtu);
|
||||
void rtp_twcc_manager_set_feedback_interval (RTPTWCCManager * twcc,
|
||||
GstClockTime feedback_interval);
|
||||
GstClockTime rtp_twcc_manager_get_feedback_interval (RTPTWCCManager * twcc);
|
||||
|
||||
gboolean rtp_twcc_manager_recv_packet (RTPTWCCManager * twcc,
|
||||
guint16 seqnum, RTPPacketInfo * pinfo);
|
||||
|
||||
RTPPacketInfo * pinfo);
|
||||
void rtp_twcc_manager_send_packet (RTPTWCCManager * twcc,
|
||||
guint16 seqnum, RTPPacketInfo * pinfo);
|
||||
RTPPacketInfo * pinfo);
|
||||
|
||||
GstBuffer * rtp_twcc_manager_get_feedback (RTPTWCCManager * twcc,
|
||||
guint32 sender_ssrc);
|
||||
|
|
Loading…
Reference in a new issue