From 092ea647bb630da3ce5facb868d7493202f84660 Mon Sep 17 00:00:00 2001 From: Matthew Waters Date: Fri, 10 Jul 2020 15:30:57 +1000 Subject: rtp/basedepayload: implement support for rtp header extensions New signals are added for managing the internal list of rtp header extension implementations read by a specific depayloader instance. If the 'extmap-$NUM' field is present in the sink caps, then an extension implementation will be requested but is not requited to be able to negotiate correctly. An extension will be requested using the 'request-extension' signal if none could be found internally. Part-of: --- tests/check/libs/rtpbasedepayload.c | 269 ++++++++++++++++++++++++++++++++++++ 1 file changed, 269 insertions(+) (limited to 'tests') diff --git a/tests/check/libs/rtpbasedepayload.c b/tests/check/libs/rtpbasedepayload.c index 472692d26..cc7b03e17 100644 --- a/tests/check/libs/rtpbasedepayload.c +++ b/tests/check/libs/rtpbasedepayload.c @@ -26,6 +26,8 @@ #include #include +#include "rtpdummyhdrextimpl.c" + #define DEFAULT_CLOCK_RATE (42) /* GstRtpDummyDepay */ @@ -392,6 +394,25 @@ rtp_buffer_set_valist (GstBuffer * buf, const gchar * field, va_list var_args, guint idx = va_arg (var_args, guint); guint csrc = va_arg (var_args, guint); gst_rtp_buffer_set_csrc (&rtp, idx, csrc); + } else if (g_str_has_prefix (field, "hdrext-")) { + GstRTPHeaderExtension *ext = va_arg (var_args, GstRTPHeaderExtension *); + guint id = gst_rtp_header_extension_get_id (ext); + gsize size = gst_rtp_header_extension_get_max_size (ext, buf); + guint8 *data = g_malloc0 (size); + + if (!g_strcmp0 (field, "hdrext-1")) { + fail_unless (gst_rtp_header_extension_write (ext, buf, + GST_RTP_HEADER_EXTENSION_ONE_BYTE, buf, data, size) > 0); + fail_unless (gst_rtp_buffer_add_extension_onebyte_header (&rtp, id, + data, size)); + } else if (!g_strcmp0 (field, "hdrext-2")) { + fail_unless (gst_rtp_header_extension_write (ext, buf, + GST_RTP_HEADER_EXTENSION_TWO_BYTE, buf, data, size) > 0); + fail_unless (gst_rtp_buffer_add_extension_twobytes_header (&rtp, 0, + id, data, size)); + } + + g_free (data); } else { fail ("test cannot set unknown buffer field '%s'", field); } @@ -1540,6 +1561,247 @@ GST_START_TEST (rtp_base_depayload_flow_return_push_list_func) GST_END_TEST; +GST_START_TEST (rtp_base_depayload_one_byte_hdr_ext) +{ + GstRTPHeaderExtension *ext; + State *state; + + state = create_depayloader ("application/x-rtp", NULL); + ext = rtp_dummy_hdr_ext_new (); + gst_rtp_header_extension_set_id (ext, 1); + + GST_RTP_DUMMY_DEPAY (state->element)->push_method = + GST_RTP_DUMMY_RETURN_TO_PUSH; + + g_signal_emit_by_name (state->element, "add-extension", ext); + + set_state (state, GST_STATE_PLAYING); + + push_rtp_buffer (state, "pts", 0 * GST_SECOND, + "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, "hdrext-1", ext, + NULL); + + set_state (state, GST_STATE_NULL); + + validate_buffers_received (1); + + validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL); + + fail_unless_equals_int (GST_RTP_DUMMY_HDR_EXT (ext)->read_count, 1); + + gst_object_unref (ext); + destroy_depayloader (state); +} + +GST_END_TEST; + +GST_START_TEST (rtp_base_depayload_two_byte_hdr_ext) +{ + GstRTPHeaderExtension *ext; + State *state; + + state = create_depayloader ("application/x-rtp", NULL); + ext = rtp_dummy_hdr_ext_new (); + gst_rtp_header_extension_set_id (ext, 1); + + GST_RTP_DUMMY_DEPAY (state->element)->push_method = + GST_RTP_DUMMY_RETURN_TO_PUSH; + + g_signal_emit_by_name (state->element, "add-extension", ext); + + set_state (state, GST_STATE_PLAYING); + + push_rtp_buffer (state, "pts", 0 * GST_SECOND, + "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, "hdrext-2", ext, + NULL); + + set_state (state, GST_STATE_NULL); + + validate_buffers_received (1); + + validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL); + + fail_unless_equals_int (GST_RTP_DUMMY_HDR_EXT (ext)->read_count, 1); + + gst_object_unref (ext); + destroy_depayloader (state); +} + +GST_END_TEST; + +static GstRTPHeaderExtension * +request_extension (GstRTPBaseDepayload * depayload, guint ext_id, + const gchar * ext_uri, gpointer user_data) +{ + GstRTPHeaderExtension *ext = user_data; + + if (ext && gst_rtp_header_extension_get_id (ext) == ext_id + && g_strcmp0 (ext_uri, gst_rtp_header_extension_get_uri (ext)) == 0) + return gst_object_ref (ext); + + return NULL; +} + +GST_START_TEST (rtp_base_depayload_request_extension) +{ + GstRTPHeaderExtension *ext; + State *state; + + state = + create_depayloader ("application/x-rtp,extmap-3=(string)" + DUMMY_HDR_EXT_URI, NULL); + ext = rtp_dummy_hdr_ext_new (); + gst_rtp_header_extension_set_id (ext, 3); + + GST_RTP_DUMMY_DEPAY (state->element)->push_method = + GST_RTP_DUMMY_RETURN_TO_PUSH; + + g_signal_connect (state->element, "request-extension", + G_CALLBACK (request_extension), ext); + + set_state (state, GST_STATE_PLAYING); + + push_rtp_buffer (state, "pts", 0 * GST_SECOND, + "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, "hdrext-1", ext, + NULL); + + set_state (state, GST_STATE_NULL); + + validate_buffers_received (1); + + validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL); + + fail_unless_equals_int (GST_RTP_DUMMY_HDR_EXT (ext)->read_count, 1); + + gst_object_unref (ext); + destroy_depayloader (state); +} + +GST_END_TEST; + +GST_START_TEST (rtp_base_depayload_clear_extensions) +{ + GstRTPHeaderExtension *ext; + State *state; + + state = create_depayloader ("application/x-rtp", NULL); + ext = rtp_dummy_hdr_ext_new (); + gst_rtp_header_extension_set_id (ext, 1); + + GST_RTP_DUMMY_DEPAY (state->element)->push_method = + GST_RTP_DUMMY_RETURN_TO_PUSH; + + g_signal_emit_by_name (state->element, "add-extension", ext); + + set_state (state, GST_STATE_PLAYING); + + push_rtp_buffer (state, "pts", 0 * GST_SECOND, + "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, "hdrext-1", ext, + NULL); + + g_signal_emit_by_name (state->element, "clear-extensions"); + + push_rtp_buffer (state, "pts", 1 * GST_SECOND, + "rtptime", G_GUINT64_CONSTANT (0x1234) + 1 * DEFAULT_CLOCK_RATE, + "seq", 0x4242 + 1, "hdrext-1", ext, NULL); + + set_state (state, GST_STATE_NULL); + + validate_buffers_received (2); + + validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL); + validate_buffer (1, "pts", 1 * GST_SECOND, "discont", FALSE, NULL); + + fail_unless_equals_int (GST_RTP_DUMMY_HDR_EXT (ext)->read_count, 1); + + gst_object_unref (ext); + destroy_depayloader (state); +} + +GST_END_TEST; + +GST_START_TEST (rtp_base_depayload_multiple_exts) +{ + GstRTPHeaderExtension *ext1; + GstRTPHeaderExtension *ext2; + State *state; + + state = create_depayloader ("application/x-rtp", NULL); + ext1 = rtp_dummy_hdr_ext_new (); + gst_rtp_header_extension_set_id (ext1, 1); + ext2 = rtp_dummy_hdr_ext_new (); + gst_rtp_header_extension_set_id (ext2, 2); + + GST_RTP_DUMMY_DEPAY (state->element)->push_method = + GST_RTP_DUMMY_RETURN_TO_PUSH; + + g_signal_emit_by_name (state->element, "add-extension", ext1); + g_signal_emit_by_name (state->element, "add-extension", ext2); + + set_state (state, GST_STATE_PLAYING); + + push_rtp_buffer (state, "pts", 0 * GST_SECOND, + "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, "hdrext-1", ext1, + "hdrext-1", ext2, NULL); + + set_state (state, GST_STATE_NULL); + + validate_buffers_received (1); + + validate_buffer (0, "pts", 0 * GST_SECOND, "discont", FALSE, NULL); + + fail_unless_equals_int (GST_RTP_DUMMY_HDR_EXT (ext1)->read_count, 1); + fail_unless_equals_int (GST_RTP_DUMMY_HDR_EXT (ext2)->read_count, 1); + + gst_object_unref (ext1); + gst_object_unref (ext2); + destroy_depayloader (state); +} + +GST_END_TEST; + +static GstRTPHeaderExtension * +request_extension_ignored (GstRTPBaseDepayload * depayload, guint ext_id, + const gchar * ext_uri, gpointer user_data) +{ + guint *request_counter = user_data; + + *request_counter += 1; + + return NULL; +} + +GST_START_TEST (rtp_base_depayload_caps_request_ignored) +{ + State *state; + guint request_counter = 0; + + state = + create_depayloader ("application/x-rtp,extmap-3=(string)" + DUMMY_HDR_EXT_URI, NULL); + + GST_RTP_DUMMY_DEPAY (state->element)->push_method = + GST_RTP_DUMMY_RETURN_TO_PUSH; + g_signal_connect (state->element, "request-extension", + G_CALLBACK (request_extension_ignored), &request_counter); + + set_state (state, GST_STATE_PLAYING); + + push_rtp_buffer (state, + "pts", 0 * GST_SECOND, + "rtptime", G_GUINT64_CONSTANT (0x1234), "seq", 0x4242, NULL); + + fail_unless_equals_int (request_counter, 1); + + set_state (state, GST_STATE_NULL); + + validate_buffers_received (1); + + destroy_depayloader (state); +} + +GST_END_TEST; + static Suite * rtp_basepayloading_suite (void) { @@ -1577,6 +1839,13 @@ rtp_basepayloading_suite (void) tcase_add_test (tc_chain, rtp_base_depayload_flow_return_push_func); tcase_add_test (tc_chain, rtp_base_depayload_flow_return_push_list_func); + tcase_add_test (tc_chain, rtp_base_depayload_one_byte_hdr_ext); + tcase_add_test (tc_chain, rtp_base_depayload_two_byte_hdr_ext); + tcase_add_test (tc_chain, rtp_base_depayload_request_extension); + tcase_add_test (tc_chain, rtp_base_depayload_clear_extensions); + tcase_add_test (tc_chain, rtp_base_depayload_multiple_exts); + tcase_add_test (tc_chain, rtp_base_depayload_caps_request_ignored); + return s; } -- cgit v1.2.1