diff --git a/gst/rtpmanager/gstrtpmux.c b/gst/rtpmanager/gstrtpmux.c index 302600cc9f..5c9c7160ea 100644 --- a/gst/rtpmanager/gstrtpmux.c +++ b/gst/rtpmanager/gstrtpmux.c @@ -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); diff --git a/gst/rtpmanager/gstrtpmux.h b/gst/rtpmanager/gstrtpmux.h index 4b71deeaf2..b94d408bac 100644 --- a/gst/rtpmanager/gstrtpmux.h +++ b/gst/rtpmanager/gstrtpmux.h @@ -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 */ diff --git a/tests/check/elements/rtpmux.c b/tests/check/elements/rtpmux.c index 36b58e6189..6f83c0810c 100644 --- a/tests/check/elements/rtpmux.c +++ b/tests/check/elements/rtpmux.c @@ -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);