mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 19:51:11 +00:00
gstrtpmux: allow the ssrc-property to decide ssrc on outgoing buffers
By not doing this, the muxer is not effectively a rtpmuxer, rather a funnel, since it should be a single stream that exists the muxer. If not specified, take the first ssrc seen on a sinkpad, allowing upstream to decide ssrc in "passthrough" with only one sinkpad. Also, let downstream ssrc overrule internal configured one We hence has the following order for determining the ssrc used by rtpmux: 0. Suggestion from GstRTPCollision event 1. Downstream caps 2. ssrc-Property 3. (First) upstream caps containing ssrc 4. Randomly generated https://bugzilla.gnome.org/show_bug.cgi?id=752694
This commit is contained in:
parent
41a82b9706
commit
d5e26ab909
3 changed files with 333 additions and 39 deletions
|
@ -158,7 +158,8 @@ gst_rtp_mux_class_init (GstRTPMuxClass * klass)
|
|||
g_param_spec_uint ("ssrc", "SSRC",
|
||||
"The SSRC of the packets (-1 == random)",
|
||||
0, G_MAXUINT, DEFAULT_SSRC,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
GST_PARAM_MUTABLE_PLAYING | G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
gstelement_class->request_new_pad =
|
||||
GST_DEBUG_FUNCPTR (gst_rtp_mux_request_new_pad);
|
||||
|
@ -207,6 +208,51 @@ gst_rtp_mux_src_event_real (GstRTPMux * rtp_mux, GstEvent * event)
|
|||
gboolean result = FALSE;
|
||||
gboolean done = FALSE;
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_CUSTOM_UPSTREAM:
|
||||
{
|
||||
const GstStructure *s = gst_event_get_structure (event);
|
||||
|
||||
if (gst_structure_has_name (s, "GstRTPCollision")) {
|
||||
guint ssrc = 0;
|
||||
|
||||
if (!gst_structure_get_uint (s, "ssrc", &ssrc))
|
||||
ssrc = -1;
|
||||
|
||||
GST_DEBUG_OBJECT (rtp_mux, "collided ssrc: %" G_GUINT32_FORMAT, ssrc);
|
||||
|
||||
/* choose another ssrc for our stream */
|
||||
GST_OBJECT_LOCK (rtp_mux);
|
||||
if (ssrc == rtp_mux->current_ssrc) {
|
||||
GstCaps *caps;
|
||||
guint suggested_ssrc = 0;
|
||||
guint32 new_ssrc;
|
||||
|
||||
if (gst_structure_get_uint (s, "suggested-ssrc", &suggested_ssrc))
|
||||
rtp_mux->current_ssrc = suggested_ssrc;
|
||||
|
||||
while (ssrc == rtp_mux->current_ssrc)
|
||||
rtp_mux->current_ssrc = g_random_int ();
|
||||
|
||||
new_ssrc = rtp_mux->current_ssrc;
|
||||
GST_OBJECT_UNLOCK (rtp_mux);
|
||||
|
||||
caps = gst_pad_get_current_caps (rtp_mux->srcpad);
|
||||
caps = gst_caps_make_writable (caps);
|
||||
gst_caps_set_simple (caps, "ssrc", G_TYPE_UINT, new_ssrc, NULL);
|
||||
gst_pad_set_caps (rtp_mux->srcpad, caps);
|
||||
gst_caps_unref (caps);
|
||||
} else {
|
||||
GST_OBJECT_UNLOCK (rtp_mux);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
iter = gst_element_iterate_sink_pads (GST_ELEMENT (rtp_mux));
|
||||
|
||||
while (!done) {
|
||||
|
@ -249,6 +295,7 @@ gst_rtp_mux_init (GstRTPMux * rtp_mux)
|
|||
gst_element_add_pad (GST_ELEMENT (rtp_mux), rtp_mux->srcpad);
|
||||
|
||||
rtp_mux->ssrc = DEFAULT_SSRC;
|
||||
rtp_mux->current_ssrc = DEFAULT_SSRC;
|
||||
rtp_mux->ts_offset = DEFAULT_TIMESTAMP_OFFSET;
|
||||
rtp_mux->seqnum_offset = DEFAULT_SEQNUM_OFFSET;
|
||||
|
||||
|
@ -414,6 +461,17 @@ gst_rtp_mux_chain_list (GstPad * pad, GstObject * parent,
|
|||
|
||||
rtp_mux = GST_RTP_MUX (parent);
|
||||
|
||||
if (gst_pad_check_reconfigure (rtp_mux->srcpad)) {
|
||||
GstCaps *current_caps = gst_pad_get_current_caps (pad);
|
||||
|
||||
if (!gst_rtp_mux_setcaps (pad, rtp_mux, current_caps)) {
|
||||
ret = GST_FLOW_NOT_NEGOTIATED;
|
||||
gst_buffer_list_unref (bufferlist);
|
||||
goto out;
|
||||
}
|
||||
gst_caps_unref (current_caps);
|
||||
}
|
||||
|
||||
GST_OBJECT_LOCK (rtp_mux);
|
||||
|
||||
padpriv = gst_pad_get_element_private (pad);
|
||||
|
@ -472,7 +530,18 @@ gst_rtp_mux_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
|
|||
gboolean changed = FALSE;
|
||||
GstRTPBuffer rtpbuffer = GST_RTP_BUFFER_INIT;
|
||||
|
||||
rtp_mux = GST_RTP_MUX (GST_OBJECT_PARENT (pad));
|
||||
rtp_mux = GST_RTP_MUX (parent);
|
||||
|
||||
if (gst_pad_check_reconfigure (rtp_mux->srcpad)) {
|
||||
GstCaps *current_caps = gst_pad_get_current_caps (pad);
|
||||
|
||||
if (!gst_rtp_mux_setcaps (pad, rtp_mux, current_caps)) {
|
||||
ret = GST_FLOW_NOT_NEGOTIATED;
|
||||
gst_buffer_unref (buffer);
|
||||
goto out;
|
||||
}
|
||||
gst_caps_unref (current_caps);
|
||||
}
|
||||
|
||||
GST_OBJECT_LOCK (rtp_mux);
|
||||
padpriv = gst_pad_get_element_private (pad);
|
||||
|
@ -523,6 +592,7 @@ gst_rtp_mux_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
|
|||
ret = gst_pad_push (rtp_mux->srcpad, buffer);
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -532,6 +602,34 @@ gst_rtp_mux_setcaps (GstPad * pad, GstRTPMux * rtp_mux, GstCaps * caps)
|
|||
GstStructure *structure;
|
||||
gboolean ret = FALSE;
|
||||
GstRTPMuxPadPrivate *padpriv;
|
||||
GstCaps *peercaps;
|
||||
|
||||
if (!gst_caps_is_fixed (caps))
|
||||
return FALSE;
|
||||
|
||||
peercaps = gst_pad_peer_query_caps (rtp_mux->srcpad, NULL);
|
||||
if (peercaps) {
|
||||
GstCaps *tcaps, *othercaps;;
|
||||
tcaps = gst_pad_get_pad_template_caps (pad);
|
||||
othercaps = gst_caps_intersect_full (peercaps, tcaps,
|
||||
GST_CAPS_INTERSECT_FIRST);
|
||||
|
||||
if (gst_caps_get_size (othercaps) > 0) {
|
||||
structure = gst_caps_get_structure (othercaps, 0);
|
||||
GST_OBJECT_LOCK (rtp_mux);
|
||||
if (gst_structure_get_uint (structure, "ssrc", &rtp_mux->current_ssrc)) {
|
||||
GST_DEBUG_OBJECT (pad, "Use downstream ssrc: %x",
|
||||
rtp_mux->current_ssrc);
|
||||
rtp_mux->have_ssrc = TRUE;
|
||||
}
|
||||
GST_OBJECT_UNLOCK (rtp_mux);
|
||||
}
|
||||
|
||||
gst_caps_unref (othercaps);
|
||||
|
||||
gst_caps_unref (peercaps);
|
||||
gst_caps_unref (tcaps);
|
||||
}
|
||||
|
||||
structure = gst_caps_get_structure (caps, 0);
|
||||
|
||||
|
@ -545,13 +643,25 @@ gst_rtp_mux_setcaps (GstPad * pad, GstRTPMux * rtp_mux, GstCaps * caps)
|
|||
&padpriv->timestamp_offset)) {
|
||||
padpriv->have_timestamp_offset = TRUE;
|
||||
}
|
||||
GST_OBJECT_UNLOCK (rtp_mux);
|
||||
|
||||
caps = gst_caps_copy (caps);
|
||||
|
||||
/* if we don't have a specified ssrc, first try to take one from the caps,
|
||||
and if that fails, generate one */
|
||||
if (!rtp_mux->have_ssrc) {
|
||||
if (rtp_mux->ssrc == DEFAULT_SSRC) {
|
||||
if (!gst_structure_get_uint (structure, "ssrc", &rtp_mux->current_ssrc))
|
||||
rtp_mux->current_ssrc = g_random_int ();
|
||||
rtp_mux->have_ssrc = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
gst_caps_set_simple (caps,
|
||||
"timestamp-offset", G_TYPE_UINT, rtp_mux->ts_base,
|
||||
"seqnum-offset", G_TYPE_UINT, rtp_mux->seqnum_base, NULL);
|
||||
"seqnum-offset", G_TYPE_UINT, rtp_mux->seqnum_base,
|
||||
"ssrc", G_TYPE_UINT, rtp_mux->current_ssrc, NULL);
|
||||
|
||||
GST_OBJECT_UNLOCK (rtp_mux);
|
||||
|
||||
if (rtp_mux->send_stream_start) {
|
||||
gchar s_id[32];
|
||||
|
@ -567,7 +677,6 @@ gst_rtp_mux_setcaps (GstPad * pad, GstRTPMux * rtp_mux, GstCaps * caps)
|
|||
"setting caps %" GST_PTR_FORMAT " on src pad..", caps);
|
||||
ret = gst_pad_set_caps (rtp_mux->srcpad, caps);
|
||||
|
||||
gst_structure_get_uint (structure, "ssrc", &rtp_mux->current_ssrc);
|
||||
|
||||
gst_caps_unref (caps);
|
||||
|
||||
|
@ -630,9 +739,8 @@ gst_rtp_mux_getcaps (GstPad * pad, GstRTPMux * mux, GstCaps * filter)
|
|||
GstCaps *peercaps;
|
||||
GstCaps *othercaps;
|
||||
GstCaps *tcaps;
|
||||
GstCaps *other_filtered;
|
||||
|
||||
peercaps = gst_pad_peer_query_caps (mux->srcpad, filter);
|
||||
peercaps = gst_pad_peer_query_caps (mux->srcpad, NULL);
|
||||
|
||||
if (peercaps) {
|
||||
tcaps = gst_pad_get_pad_template_caps (pad);
|
||||
|
@ -649,21 +757,20 @@ gst_rtp_mux_getcaps (GstPad * pad, GstRTPMux * mux, GstCaps * filter)
|
|||
}
|
||||
gst_caps_unref (tcaps);
|
||||
|
||||
clear_caps (othercaps, FALSE);
|
||||
GST_LOG_OBJECT (pad, "Intersected srcpad-peercaps and template caps: %"
|
||||
GST_PTR_FORMAT, othercaps);
|
||||
|
||||
other_filtered = gst_caps_copy (othercaps);
|
||||
clear_caps (other_filtered, TRUE);
|
||||
clear_caps (othercaps, TRUE);
|
||||
|
||||
g_value_init (&v, GST_TYPE_CAPS);
|
||||
|
||||
iter = gst_element_iterate_sink_pads (GST_ELEMENT (mux));
|
||||
do {
|
||||
gst_value_set_caps (&v, other_filtered);
|
||||
gst_value_set_caps (&v, othercaps);
|
||||
res = gst_iterator_fold (iter, same_clock_rate_fold, &v, pad);
|
||||
gst_iterator_resync (iter);
|
||||
} while (res == GST_ITERATOR_RESYNC);
|
||||
gst_iterator_free (iter);
|
||||
gst_caps_unref (other_filtered);
|
||||
|
||||
caps = gst_caps_intersect ((GstCaps *) gst_value_get_caps (&v), othercaps);
|
||||
|
||||
|
@ -691,8 +798,12 @@ gst_rtp_mux_sink_query (GstPad * pad, GstObject * parent, GstQuery * query)
|
|||
GstCaps *filter, *caps;
|
||||
|
||||
gst_query_parse_caps (query, &filter);
|
||||
GST_LOG_OBJECT (pad, "Received caps-query with filter-caps: %"
|
||||
GST_PTR_FORMAT, filter);
|
||||
caps = gst_rtp_mux_getcaps (pad, mux, filter);
|
||||
gst_query_set_caps_result (query, caps);
|
||||
GST_LOG_OBJECT (mux, "Answering caps-query with caps: %"
|
||||
GST_PTR_FORMAT, caps);
|
||||
gst_caps_unref (caps);
|
||||
res = TRUE;
|
||||
break;
|
||||
|
@ -703,11 +814,8 @@ gst_rtp_mux_sink_query (GstPad * pad, GstObject * parent, GstQuery * query)
|
|||
}
|
||||
|
||||
return res;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gst_rtp_mux_get_property (GObject * object,
|
||||
guint prop_id, GValue * value, GParamSpec * pspec)
|
||||
|
@ -716,6 +824,7 @@ gst_rtp_mux_get_property (GObject * object,
|
|||
|
||||
rtp_mux = GST_RTP_MUX (object);
|
||||
|
||||
GST_OBJECT_LOCK (rtp_mux);
|
||||
switch (prop_id) {
|
||||
case PROP_TIMESTAMP_OFFSET:
|
||||
g_value_set_int (value, rtp_mux->ts_offset);
|
||||
|
@ -724,9 +833,7 @@ gst_rtp_mux_get_property (GObject * object,
|
|||
g_value_set_int (value, rtp_mux->seqnum_offset);
|
||||
break;
|
||||
case PROP_SEQNUM:
|
||||
GST_OBJECT_LOCK (rtp_mux);
|
||||
g_value_set_uint (value, rtp_mux->seqnum);
|
||||
GST_OBJECT_UNLOCK (rtp_mux);
|
||||
break;
|
||||
case PROP_SSRC:
|
||||
g_value_set_uint (value, rtp_mux->ssrc);
|
||||
|
@ -735,6 +842,7 @@ gst_rtp_mux_get_property (GObject * object,
|
|||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
GST_OBJECT_UNLOCK (rtp_mux);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -753,7 +861,11 @@ gst_rtp_mux_set_property (GObject * object,
|
|||
rtp_mux->seqnum_offset = g_value_get_int (value);
|
||||
break;
|
||||
case PROP_SSRC:
|
||||
GST_OBJECT_LOCK (rtp_mux);
|
||||
rtp_mux->ssrc = g_value_get_uint (value);
|
||||
rtp_mux->current_ssrc = rtp_mux->ssrc;
|
||||
rtp_mux->have_ssrc = TRUE;
|
||||
GST_OBJECT_UNLOCK (rtp_mux);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
|
@ -774,6 +886,8 @@ gst_rtp_mux_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
|
|||
GstCaps *caps;
|
||||
|
||||
gst_event_parse_caps (event, &caps);
|
||||
GST_LOG_OBJECT (pad, "Received caps-event with caps: %"
|
||||
GST_PTR_FORMAT, caps);
|
||||
ret = gst_rtp_mux_setcaps (pad, mux, caps);
|
||||
gst_event_unref (event);
|
||||
return ret;
|
||||
|
@ -823,11 +937,6 @@ gst_rtp_mux_ready_to_paused (GstRTPMux * rtp_mux)
|
|||
g_clear_object (&rtp_mux->last_pad);
|
||||
rtp_mux->send_stream_start = TRUE;
|
||||
|
||||
if (rtp_mux->ssrc == -1)
|
||||
rtp_mux->current_ssrc = g_random_int ();
|
||||
else
|
||||
rtp_mux->current_ssrc = rtp_mux->ssrc;
|
||||
|
||||
if (rtp_mux->seqnum_offset == -1)
|
||||
rtp_mux->seqnum_base = g_random_int_range (0, G_MAXUINT16);
|
||||
else
|
||||
|
@ -841,6 +950,13 @@ gst_rtp_mux_ready_to_paused (GstRTPMux * rtp_mux)
|
|||
|
||||
rtp_mux->last_stop = GST_CLOCK_TIME_NONE;
|
||||
|
||||
if (rtp_mux->ssrc == DEFAULT_SSRC) {
|
||||
rtp_mux->have_ssrc = FALSE;
|
||||
} else {
|
||||
rtp_mux->current_ssrc = rtp_mux->ssrc;
|
||||
rtp_mux->have_ssrc = TRUE;
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (rtp_mux, "set timestamp-offset to %u", rtp_mux->ts_base);
|
||||
|
||||
GST_OBJECT_UNLOCK (rtp_mux);
|
||||
|
|
|
@ -71,6 +71,7 @@ struct _GstRTPMux
|
|||
guint16 seqnum; /* protected by object lock */
|
||||
guint ssrc;
|
||||
guint current_ssrc;
|
||||
gboolean have_ssrc;
|
||||
|
||||
GstPad *last_pad; /* protected by object lock */
|
||||
|
||||
|
|
|
@ -61,6 +61,15 @@ query_func (GstPad * pad, GstObject * noparent, GstQuery * query)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static GstCaps *
|
||||
remove_ssrc_from_caps (GstCaps * caps)
|
||||
{
|
||||
GstCaps *copy = gst_caps_copy (caps);
|
||||
GstStructure *s = gst_caps_get_structure (copy, 0);
|
||||
gst_structure_remove_field (s, "ssrc");
|
||||
return copy;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
event_func (GstPad * pad, GstObject * noparent, GstEvent * event)
|
||||
{
|
||||
|
@ -69,12 +78,20 @@ event_func (GstPad * pad, GstObject * noparent, GstEvent * event)
|
|||
{
|
||||
GstCaps *caps;
|
||||
GstCaps **caps2 = g_object_get_data (G_OBJECT (pad), "caps");
|
||||
GstCaps *caps_no_ssrc;
|
||||
GstCaps *caps2_no_ssrc;
|
||||
|
||||
gst_event_parse_caps (event, &caps);
|
||||
caps_no_ssrc = remove_ssrc_from_caps (caps);
|
||||
caps2_no_ssrc = remove_ssrc_from_caps (*caps2);
|
||||
|
||||
fail_unless (caps2 != NULL && *caps2 != NULL);
|
||||
fail_unless (gst_caps_is_fixed (caps));
|
||||
fail_unless (gst_caps_is_fixed (*caps2));
|
||||
fail_unless (gst_caps_is_equal_fixed (caps, *caps2));
|
||||
|
||||
fail_unless (gst_caps_is_equal_fixed (caps_no_ssrc, caps2_no_ssrc));
|
||||
gst_caps_unref (caps_no_ssrc);
|
||||
gst_caps_unref (caps2_no_ssrc);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -137,7 +154,6 @@ test_basic (const gchar * elem_name, const gchar * sink2, int count,
|
|||
|
||||
gst_caps_set_simple (src2caps, "clock-rate", G_TYPE_INT, 3, NULL);
|
||||
caps = gst_pad_peer_query_caps (src1, NULL);
|
||||
fail_unless (gst_caps_is_equal (caps, sinkcaps));
|
||||
gst_caps_unref (caps);
|
||||
|
||||
g_object_set (rtpmux, "seqnum-offset", 100, "timestamp-offset", 1000,
|
||||
|
@ -231,10 +247,10 @@ basic_check_cb (GstPad * pad, int i)
|
|||
fail_unless (buffers && g_list_length (buffers) == 1);
|
||||
|
||||
gst_rtp_buffer_map (buffers->data, GST_MAP_READ, &rtpbuffer);
|
||||
fail_unless (gst_rtp_buffer_get_ssrc (&rtpbuffer) == 66);
|
||||
fail_unless (gst_rtp_buffer_get_timestamp (&rtpbuffer) ==
|
||||
200 - 57 + 1000 + i);
|
||||
fail_unless (gst_rtp_buffer_get_seq (&rtpbuffer) == 100 + 1 + i);
|
||||
fail_unless_equals_int (66, gst_rtp_buffer_get_ssrc (&rtpbuffer));
|
||||
fail_unless_equals_int64 (200 - 57 + 1000 + i,
|
||||
gst_rtp_buffer_get_timestamp (&rtpbuffer));
|
||||
fail_unless_equals_int (100 + 1 + i, gst_rtp_buffer_get_seq (&rtpbuffer));
|
||||
gst_rtp_buffer_unmap (&rtpbuffer);
|
||||
}
|
||||
|
||||
|
@ -265,10 +281,10 @@ lock_check_cb (GstPad * pad, int i)
|
|||
|
||||
fail_unless (buffers && g_list_length (buffers) == 1);
|
||||
gst_rtp_buffer_map (buffers->data, GST_MAP_READ, &rtpbuffer);
|
||||
fail_unless (gst_rtp_buffer_get_ssrc (&rtpbuffer) == 66);
|
||||
fail_unless (gst_rtp_buffer_get_timestamp (&rtpbuffer) ==
|
||||
200 - 57 + 1000 + i);
|
||||
fail_unless (gst_rtp_buffer_get_seq (&rtpbuffer) == 100 + 1 + i);
|
||||
fail_unless_equals_int (66, gst_rtp_buffer_get_ssrc (&rtpbuffer));
|
||||
fail_unless_equals_int64 (200 - 57 + 1000 + i,
|
||||
gst_rtp_buffer_get_timestamp (&rtpbuffer));
|
||||
fail_unless_equals_int (100 + 1 + i, gst_rtp_buffer_get_seq (&rtpbuffer));
|
||||
gst_rtp_buffer_unmap (&rtpbuffer);
|
||||
|
||||
inbuf = gst_rtp_buffer_new_allocate (10, 0, 0);
|
||||
|
@ -325,16 +341,63 @@ generate_test_buffer (guint seq_num, guint ssrc)
|
|||
return buf;
|
||||
}
|
||||
|
||||
GST_START_TEST (test_rtpmux_ssrc)
|
||||
static guint32
|
||||
_rtp_buffer_get_ssrc (GstBuffer * buf)
|
||||
{
|
||||
GstHarness * h = gst_harness_new_with_padnames ("rtpdtmfmux", NULL, "src");
|
||||
GstHarness * h0 = gst_harness_new_with_element (
|
||||
h->element, "sink_0", NULL);
|
||||
GstHarness * h1 = gst_harness_new_with_element (
|
||||
h->element, "sink_1", NULL);
|
||||
GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
|
||||
guint32 ret;
|
||||
g_assert (gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp));
|
||||
ret = gst_rtp_buffer_get_ssrc (&rtp);
|
||||
gst_rtp_buffer_unmap (&rtp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
GST_START_TEST (test_rtpmux_ssrc_property)
|
||||
{
|
||||
GstHarness *h = gst_harness_new_with_padnames ("rtpmux", NULL, "src");
|
||||
GstHarness *h0 = gst_harness_new_with_element (h->element, "sink_0", NULL);
|
||||
GstHarness *h1 = gst_harness_new_with_element (h->element, "sink_1", NULL);
|
||||
GstBuffer *buf0;
|
||||
GstBuffer *buf1;
|
||||
|
||||
/* set ssrc to 111111 */
|
||||
g_object_set (h->element, "ssrc", 111111, NULL);
|
||||
|
||||
/* both sinkpads have their own idea of what the ssrc should be */
|
||||
gst_harness_set_src_caps_str (h0, "application/x-rtp, ssrc=(uint)222222");
|
||||
gst_harness_set_src_caps_str (h1, "application/x-rtp, ssrc=(uint)333333");
|
||||
|
||||
/* push on both sinkpads with different ssrc */
|
||||
fail_unless_equals_int (GST_FLOW_OK,
|
||||
gst_harness_push (h0, generate_test_buffer (0, 222222)));
|
||||
fail_unless_equals_int (GST_FLOW_OK,
|
||||
gst_harness_push (h1, generate_test_buffer (0, 333333)));
|
||||
|
||||
buf0 = gst_harness_pull (h);
|
||||
buf1 = gst_harness_pull (h);
|
||||
|
||||
/* we expect the ssrc to be what we specified in the property */
|
||||
fail_unless_equals_int (111111, _rtp_buffer_get_ssrc (buf0));
|
||||
fail_unless_equals_int (111111, _rtp_buffer_get_ssrc (buf1));
|
||||
|
||||
gst_buffer_unref (buf0);
|
||||
gst_buffer_unref (buf1);
|
||||
|
||||
gst_harness_teardown (h0);
|
||||
gst_harness_teardown (h1);
|
||||
gst_harness_teardown (h);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_rtpmux_ssrc_property_not_set)
|
||||
{
|
||||
GstHarness *h = gst_harness_new_with_padnames ("rtpmux", NULL, "src");
|
||||
GstHarness *h0 = gst_harness_new_with_element (h->element, "sink_0", NULL);
|
||||
GstHarness *h1 = gst_harness_new_with_element (h->element, "sink_1", NULL);
|
||||
GstBuffer *buf0;
|
||||
GstBuffer *buf1;
|
||||
|
||||
gst_harness_set_src_caps_str (h0, "application/x-rtp, ssrc=(uint)222222");
|
||||
gst_harness_set_src_caps_str (h1, "application/x-rtp, ssrc=(uint)333333");
|
||||
|
||||
|
@ -343,10 +406,121 @@ GST_START_TEST (test_rtpmux_ssrc)
|
|||
fail_unless_equals_int (GST_FLOW_OK,
|
||||
gst_harness_push (h1, generate_test_buffer (0, 333333)));
|
||||
|
||||
buf0 = gst_harness_pull (h);
|
||||
buf1 = gst_harness_pull (h);
|
||||
|
||||
/* we expect the ssrc to be the first ssrc that came in */
|
||||
fail_unless_equals_int (222222, _rtp_buffer_get_ssrc (buf0));
|
||||
fail_unless_equals_int (222222, _rtp_buffer_get_ssrc (buf1));
|
||||
|
||||
gst_buffer_unref (buf0);
|
||||
gst_buffer_unref (buf1);
|
||||
|
||||
gst_harness_teardown (h0);
|
||||
gst_harness_teardown (h1);
|
||||
gst_harness_teardown (h);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_rtpmux_ssrc_downstream_can_overrule)
|
||||
{
|
||||
GstHarness *h = gst_harness_new_with_padnames ("rtpmux", NULL, "src");
|
||||
GstHarness *h0 = gst_harness_new_with_element (h->element, "sink_0", NULL);
|
||||
GstHarness *h1 = gst_harness_new_with_element (h->element, "sink_1", NULL);
|
||||
GstBuffer *buf0;
|
||||
GstBuffer *buf1;
|
||||
|
||||
/* downstream is specifying 444444 as ssrc */
|
||||
gst_harness_set_sink_caps_str (h, "application/x-rtp, ssrc=(uint)444444");
|
||||
|
||||
/* rtpmux ssrc is set to 111111 */
|
||||
g_object_set (h->element, "ssrc", 111111, NULL);
|
||||
|
||||
/* while upstream ssrc is 222222 and 333333 */
|
||||
gst_harness_set_src_caps_str (h0, "application/x-rtp, ssrc=(uint)222222");
|
||||
gst_harness_set_src_caps_str (h1, "application/x-rtp, ssrc=(uint)333333");
|
||||
|
||||
fail_unless_equals_int (GST_FLOW_OK,
|
||||
gst_harness_push (h0, generate_test_buffer (0, 222222)));
|
||||
fail_unless_equals_int (GST_FLOW_OK,
|
||||
gst_harness_push (h1, generate_test_buffer (0, 333333)));
|
||||
|
||||
buf0 = gst_harness_pull (h);
|
||||
buf1 = gst_harness_pull (h);
|
||||
|
||||
/* we expect the ssrc to be downstream ssrc */
|
||||
fail_unless_equals_int (444444, _rtp_buffer_get_ssrc (buf0));
|
||||
fail_unless_equals_int (444444, _rtp_buffer_get_ssrc (buf1));
|
||||
|
||||
gst_buffer_unref (buf0);
|
||||
gst_buffer_unref (buf1);
|
||||
|
||||
gst_harness_teardown (h0);
|
||||
gst_harness_teardown (h1);
|
||||
gst_harness_teardown (h);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_rtpmux_ssrc_downstream_dynamic)
|
||||
{
|
||||
GstHarness *h = gst_harness_new_parse ("rtpmux ! capsfilter");
|
||||
GstElement *rtpmux = gst_harness_find_element (h, "rtpmux");
|
||||
GstElement *capsfilter = gst_harness_find_element (h, "capsfilter");
|
||||
|
||||
GstHarness *h0 = gst_harness_new_with_element (rtpmux, "sink_0", NULL);
|
||||
GstHarness *h1 = gst_harness_new_with_element (rtpmux, "sink_1", NULL);
|
||||
GstCaps *caps;
|
||||
GstBuffer *buf0;
|
||||
GstBuffer *buf1;
|
||||
|
||||
gst_harness_play (h);
|
||||
|
||||
caps = gst_caps_from_string ("application/x-rtp, ssrc=(uint)444444");
|
||||
g_object_set (capsfilter, "caps", caps, NULL);
|
||||
gst_caps_unref (caps);
|
||||
|
||||
/* while upstream ssrc is 222222 and 333333 */
|
||||
gst_harness_set_src_caps_str (h0, "application/x-rtp, ssrc=(uint)222222");
|
||||
gst_harness_set_src_caps_str (h1, "application/x-rtp, ssrc=(uint)333333");
|
||||
|
||||
fail_unless_equals_int (GST_FLOW_OK,
|
||||
gst_harness_push (h0, generate_test_buffer (0, 222222)));
|
||||
fail_unless_equals_int (GST_FLOW_OK,
|
||||
gst_harness_push (h1, generate_test_buffer (0, 333333)));
|
||||
|
||||
/* we expect the ssrc to be downstream ssrc (444444) */
|
||||
buf0 = gst_harness_pull (h);
|
||||
buf1 = gst_harness_pull (h);
|
||||
fail_unless_equals_int (444444, _rtp_buffer_get_ssrc (buf0));
|
||||
fail_unless_equals_int (444444, _rtp_buffer_get_ssrc (buf1));
|
||||
gst_buffer_unref (buf0);
|
||||
gst_buffer_unref (buf1);
|
||||
|
||||
caps = gst_caps_from_string ("application/x-rtp, ssrc=(uint)555555");
|
||||
g_object_set (capsfilter, "caps", caps, NULL);
|
||||
gst_caps_unref (caps);
|
||||
|
||||
fail_unless_equals_int (GST_FLOW_OK,
|
||||
gst_harness_push (h0, generate_test_buffer (0, 222222)));
|
||||
fail_unless_equals_int (GST_FLOW_OK,
|
||||
gst_harness_push (h1, generate_test_buffer (0, 333333)));
|
||||
|
||||
/* we expect the ssrc to be the new downstream ssrc (555555) */
|
||||
buf0 = gst_harness_pull (h);
|
||||
buf1 = gst_harness_pull (h);
|
||||
fail_unless_equals_int (555555, _rtp_buffer_get_ssrc (buf0));
|
||||
fail_unless_equals_int (555555, _rtp_buffer_get_ssrc (buf1));
|
||||
gst_buffer_unref (buf0);
|
||||
gst_buffer_unref (buf1);
|
||||
|
||||
gst_object_unref (rtpmux);
|
||||
gst_harness_teardown (h0);
|
||||
gst_harness_teardown (h1);
|
||||
gst_harness_teardown (h);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
static Suite *
|
||||
|
@ -358,7 +532,10 @@ rtpmux_suite (void)
|
|||
tc_chain = tcase_create ("rtpmux_basic");
|
||||
suite_add_tcase (s, tc_chain);
|
||||
tcase_add_test (tc_chain, test_rtpmux_basic);
|
||||
tcase_add_test (tc_chain, test_rtpmux_ssrc);
|
||||
tcase_add_test (tc_chain, test_rtpmux_ssrc_property);
|
||||
tcase_add_test (tc_chain, test_rtpmux_ssrc_property_not_set);
|
||||
tcase_add_test (tc_chain, test_rtpmux_ssrc_downstream_can_overrule);
|
||||
tcase_add_test (tc_chain, test_rtpmux_ssrc_downstream_dynamic);
|
||||
|
||||
tc_chain = tcase_create ("rtpdtmfmux_basic");
|
||||
tcase_add_test (tc_chain, test_rtpdtmfmux_basic);
|
||||
|
|
Loading…
Reference in a new issue