mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 11:41:09 +00:00
rtpulpfecdec: add property for passthrough
Support for enabling and disabling decoding of FEC data decoding on packet loss events and unconditional seqnum rewriting of packets. See https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/issues/581 for background. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3212>
This commit is contained in:
parent
d0e2b31470
commit
093e9c8c9d
3 changed files with 81 additions and 1 deletions
|
@ -16373,6 +16373,18 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"passthrough": {
|
||||||
|
"blurb": "Whether to passthrough all data as-is without modification and never attempt to recover packets",
|
||||||
|
"conditionally-available": false,
|
||||||
|
"construct": false,
|
||||||
|
"construct-only": false,
|
||||||
|
"controllable": false,
|
||||||
|
"default": "false",
|
||||||
|
"mutable": "null",
|
||||||
|
"readable": true,
|
||||||
|
"type": "gboolean",
|
||||||
|
"writable": true
|
||||||
|
},
|
||||||
"pt": {
|
"pt": {
|
||||||
"blurb": "FEC packets payload type",
|
"blurb": "FEC packets payload type",
|
||||||
"conditionally-available": false,
|
"conditionally-available": false,
|
||||||
|
|
|
@ -85,10 +85,12 @@ enum
|
||||||
PROP_STORAGE,
|
PROP_STORAGE,
|
||||||
PROP_RECOVERED,
|
PROP_RECOVERED,
|
||||||
PROP_UNRECOVERED,
|
PROP_UNRECOVERED,
|
||||||
|
PROP_PASSTHROUGH,
|
||||||
N_PROPERTIES
|
N_PROPERTIES
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DEFAULT_FEC_PT 0
|
#define DEFAULT_FEC_PT 0
|
||||||
|
#define DEFAULT_PASSTHROUGH FALSE
|
||||||
|
|
||||||
static GParamSpec *klass_properties[N_PROPERTIES] = { NULL, };
|
static GParamSpec *klass_properties[N_PROPERTIES] = { NULL, };
|
||||||
|
|
||||||
|
@ -378,6 +380,7 @@ gst_rtp_ulpfec_dec_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
|
||||||
|
|
||||||
if (G_LIKELY (GST_FLOW_OK == self->chain_return_val)) {
|
if (G_LIKELY (GST_FLOW_OK == self->chain_return_val)) {
|
||||||
GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
|
GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
|
||||||
|
gboolean passthrough;
|
||||||
buf = gst_buffer_make_writable (buf);
|
buf = gst_buffer_make_writable (buf);
|
||||||
|
|
||||||
if (G_UNLIKELY (self->unset_discont_flag)) {
|
if (G_UNLIKELY (self->unset_discont_flag)) {
|
||||||
|
@ -385,8 +388,20 @@ gst_rtp_ulpfec_dec_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
|
||||||
GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
|
GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GST_OBJECT_LOCK (self);
|
||||||
|
if (G_UNLIKELY (self->needs_discont)) {
|
||||||
|
self->needs_discont = FALSE;
|
||||||
|
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
|
||||||
|
}
|
||||||
|
passthrough = self->passthrough;
|
||||||
|
GST_OBJECT_UNLOCK (self);
|
||||||
|
|
||||||
gst_rtp_buffer_map (buf, GST_MAP_WRITE, &rtp);
|
gst_rtp_buffer_map (buf, GST_MAP_WRITE, &rtp);
|
||||||
gst_rtp_buffer_set_seq (&rtp, self->next_seqnum++);
|
if (passthrough) {
|
||||||
|
self->next_seqnum = gst_rtp_buffer_get_seq (&rtp) + 1;
|
||||||
|
} else {
|
||||||
|
gst_rtp_buffer_set_seq (&rtp, self->next_seqnum++);
|
||||||
|
}
|
||||||
gst_rtp_buffer_unmap (&rtp);
|
gst_rtp_buffer_unmap (&rtp);
|
||||||
|
|
||||||
return gst_pad_push (self->srcpad, buf);
|
return gst_pad_push (self->srcpad, buf);
|
||||||
|
@ -442,6 +457,13 @@ gst_rtp_ulpfec_dec_handle_packet_loss (GstRtpUlpFecDec * self, guint16 seqnum,
|
||||||
gst_rtp_buffer_set_seq (&rtp, self->next_seqnum++);
|
gst_rtp_buffer_set_seq (&rtp, self->next_seqnum++);
|
||||||
gst_rtp_buffer_unmap (&rtp);
|
gst_rtp_buffer_unmap (&rtp);
|
||||||
|
|
||||||
|
GST_OBJECT_LOCK (self);
|
||||||
|
if (G_UNLIKELY (self->needs_discont)) {
|
||||||
|
self->needs_discont = FALSE;
|
||||||
|
GST_BUFFER_FLAG_SET (sent_buffer, GST_BUFFER_FLAG_DISCONT);
|
||||||
|
}
|
||||||
|
GST_OBJECT_UNLOCK (self);
|
||||||
|
|
||||||
ret = FALSE;
|
ret = FALSE;
|
||||||
self->unset_discont_flag = TRUE;
|
self->unset_discont_flag = TRUE;
|
||||||
self->chain_return_val = gst_pad_push (self->srcpad, sent_buffer);
|
self->chain_return_val = gst_pad_push (self->srcpad, sent_buffer);
|
||||||
|
@ -481,6 +503,18 @@ gst_rtp_ulpfec_dec_handle_sink_event (GstPad * pad, GstObject * parent,
|
||||||
guint seqnum;
|
guint seqnum;
|
||||||
GstClockTime timestamp, duration;
|
GstClockTime timestamp, duration;
|
||||||
GstStructure *s;
|
GstStructure *s;
|
||||||
|
gboolean passthrough;
|
||||||
|
|
||||||
|
GST_OBJECT_LOCK (self);
|
||||||
|
passthrough = self->passthrough;
|
||||||
|
GST_OBJECT_UNLOCK (self);
|
||||||
|
|
||||||
|
if (passthrough) {
|
||||||
|
GST_TRACE_OBJECT (self,
|
||||||
|
"in passthrough mode, ignoring packet loss event");
|
||||||
|
forward = TRUE;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
event = gst_event_make_writable (event);
|
event = gst_event_make_writable (event);
|
||||||
s = gst_event_writable_structure (event);
|
s = gst_event_writable_structure (event);
|
||||||
|
@ -555,6 +589,7 @@ gst_rtp_ulpfec_dec_handle_sink_event (GstPad * pad, GstObject * parent,
|
||||||
self->caps_pt = caps_pt;
|
self->caps_pt = caps_pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
if (forward)
|
if (forward)
|
||||||
return gst_pad_push_event (self->srcpad, event);
|
return gst_pad_push_event (self->srcpad, event);
|
||||||
gst_event_unref (event);
|
gst_event_unref (event);
|
||||||
|
@ -577,6 +612,7 @@ gst_rtp_ulpfec_dec_init (GstRtpUlpFecDec * self)
|
||||||
gst_element_add_pad (GST_ELEMENT (self), self->sinkpad);
|
gst_element_add_pad (GST_ELEMENT (self), self->sinkpad);
|
||||||
|
|
||||||
self->fec_pt = DEFAULT_FEC_PT;
|
self->fec_pt = DEFAULT_FEC_PT;
|
||||||
|
self->passthrough = DEFAULT_PASSTHROUGH;
|
||||||
|
|
||||||
self->next_seqnum = g_random_int_range (0, G_MAXINT16);
|
self->next_seqnum = g_random_int_range (0, G_MAXINT16);
|
||||||
|
|
||||||
|
@ -642,6 +678,20 @@ gst_rtp_ulpfec_dec_set_property (GObject * object, guint prop_id,
|
||||||
if (self->storage)
|
if (self->storage)
|
||||||
g_object_ref (self->storage);
|
g_object_ref (self->storage);
|
||||||
break;
|
break;
|
||||||
|
case PROP_PASSTHROUGH:{
|
||||||
|
gboolean newval = g_value_get_boolean (value);
|
||||||
|
GST_OBJECT_LOCK (self);
|
||||||
|
/* if we changing into non-passthrough mode, then the sequence numbers may
|
||||||
|
* be completely different and we need to advertise that with a discont */
|
||||||
|
GST_INFO_OBJECT (self, "passthrough changing from %u to %u",
|
||||||
|
self->passthrough, newval);
|
||||||
|
if (self->passthrough && !newval) {
|
||||||
|
self->needs_discont = TRUE;
|
||||||
|
}
|
||||||
|
self->passthrough = newval;
|
||||||
|
GST_OBJECT_UNLOCK (self);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -667,6 +717,9 @@ gst_rtp_ulpfec_dec_get_property (GObject * object, guint prop_id,
|
||||||
case PROP_UNRECOVERED:
|
case PROP_UNRECOVERED:
|
||||||
g_value_set_uint (value, (guint) self->packets_unrecovered);
|
g_value_set_uint (value, (guint) self->packets_unrecovered);
|
||||||
break;
|
break;
|
||||||
|
case PROP_PASSTHROUGH:
|
||||||
|
g_value_set_boolean (value, self->passthrough);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -712,6 +765,19 @@ gst_rtp_ulpfec_dec_class_init (GstRtpUlpFecDecClass * klass)
|
||||||
g_param_spec_uint ("unrecovered", "unrecovered",
|
g_param_spec_uint ("unrecovered", "unrecovered",
|
||||||
"The number of unrecovered packets", 0, G_MAXUINT, 0,
|
"The number of unrecovered packets", 0, G_MAXUINT, 0,
|
||||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||||
|
/**
|
||||||
|
* GstRtpUlpFecDec:passthrough:
|
||||||
|
*
|
||||||
|
* Whether to push data through without any modification. If passthrough is
|
||||||
|
* enabled, then no packets will ever be recovered.
|
||||||
|
*
|
||||||
|
* Since: 1.22
|
||||||
|
*/
|
||||||
|
klass_properties[PROP_PASSTHROUGH] =
|
||||||
|
g_param_spec_boolean ("passthrough", "Passthrough",
|
||||||
|
"Whether to passthrough all data as-is without modification and "
|
||||||
|
"never attempt to recover packets", DEFAULT_PASSTHROUGH,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
||||||
|
|
||||||
g_object_class_install_properties (gobject_class, N_PROPERTIES,
|
g_object_class_install_properties (gobject_class, N_PROPERTIES,
|
||||||
klass_properties);
|
klass_properties);
|
||||||
|
|
|
@ -55,10 +55,12 @@ struct _GstRtpUlpFecDec {
|
||||||
RtpStorage *storage;
|
RtpStorage *storage;
|
||||||
gsize packets_recovered;
|
gsize packets_recovered;
|
||||||
gsize packets_unrecovered;
|
gsize packets_unrecovered;
|
||||||
|
gboolean passthrough;
|
||||||
|
|
||||||
/* internal stuff */
|
/* internal stuff */
|
||||||
GstFlowReturn chain_return_val;
|
GstFlowReturn chain_return_val;
|
||||||
gboolean unset_discont_flag;
|
gboolean unset_discont_flag;
|
||||||
|
gboolean needs_discont;
|
||||||
gboolean have_caps_ssrc;
|
gboolean have_caps_ssrc;
|
||||||
gboolean have_caps_pt;
|
gboolean have_caps_pt;
|
||||||
guint32 caps_ssrc;
|
guint32 caps_ssrc;
|
||||||
|
|
Loading…
Reference in a new issue