mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-03-30 04:45:36 +00:00
rtcpbuffer: Add profile-specific extension API.
https://bugzilla.gnome.org/show_bug.cgi?id=761950
This commit is contained in:
parent
2d1c9f8c0f
commit
d8e9a711a0
4 changed files with 257 additions and 0 deletions
|
@ -956,6 +956,9 @@ gst_rtcp_packet_add_rb (GstRTCPPacket * packet, guint32 ssrc,
|
|||
packet->type == GST_RTCP_TYPE_SR, FALSE);
|
||||
g_return_val_if_fail (packet->rtcp != NULL, FALSE);
|
||||
g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE, FALSE);
|
||||
/* if profile-specific extension is added, fail for now!? */
|
||||
g_return_val_if_fail (
|
||||
gst_rtcp_packet_get_profile_specific_ext_length (packet) == 0, FALSE);
|
||||
|
||||
if (packet->count >= GST_RTCP_MAX_RB_COUNT)
|
||||
goto no_space;
|
||||
|
@ -1039,6 +1042,156 @@ gst_rtcp_packet_set_rb (GstRTCPPacket * packet, guint nth, guint32 ssrc,
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_rtcp_packet_set_profile_specific_ext:
|
||||
* @packet: a valid SR or RR #GstRTCPPacket
|
||||
* @data: (array length=len) (transfer none): profile-specific data
|
||||
* @len: length of the profile-specific data in bytes
|
||||
*
|
||||
* Add profile-specific extension @data to @packet. If @packet already
|
||||
* contains profile-specific extension @data will be appended to the existing
|
||||
* extension.
|
||||
*
|
||||
* Returns: %TRUE if the profile specific extension data was added.
|
||||
*/
|
||||
gboolean
|
||||
gst_rtcp_packet_add_profile_specific_ext (GstRTCPPacket * packet,
|
||||
const guint8 * data, guint len)
|
||||
{
|
||||
guint8 *bdata;
|
||||
guint maxsize, offset;
|
||||
|
||||
g_return_val_if_fail (packet != NULL, FALSE);
|
||||
g_return_val_if_fail (packet->type == GST_RTCP_TYPE_RR ||
|
||||
packet->type == GST_RTCP_TYPE_SR, FALSE);
|
||||
g_return_val_if_fail (packet->rtcp != NULL, FALSE);
|
||||
g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE, FALSE);
|
||||
g_return_val_if_fail ((len & 0x03) == 0, FALSE);
|
||||
|
||||
bdata = packet->rtcp->map.data;
|
||||
maxsize = packet->rtcp->map.maxsize;
|
||||
|
||||
/* skip to the end of the packet */
|
||||
offset = packet->offset + (packet->length << 2) + 4;
|
||||
|
||||
/* we need 'len' free bytes now */
|
||||
if (G_UNLIKELY (offset + len > maxsize))
|
||||
return FALSE;
|
||||
|
||||
memcpy (&bdata[offset], data, len);
|
||||
packet->length += len >> 2;
|
||||
bdata[packet->offset + 2] = (packet->length) >> 8;
|
||||
bdata[packet->offset + 3] = (packet->length) & 0xff;
|
||||
packet->rtcp->map.size += len;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_rtcp_packet_get_profile_specific_ext_length:
|
||||
* @packet: a valid SR or RR #GstRTCPPacket
|
||||
*
|
||||
* Returns: The number of 32-bit words containing profile-specific extension
|
||||
* data from @packet.
|
||||
*/
|
||||
guint16
|
||||
gst_rtcp_packet_get_profile_specific_ext_length (GstRTCPPacket * packet)
|
||||
{
|
||||
guint pse_offset = 2;
|
||||
|
||||
g_return_val_if_fail (packet != NULL, 0);
|
||||
g_return_val_if_fail (packet->type == GST_RTCP_TYPE_RR ||
|
||||
packet->type == GST_RTCP_TYPE_SR, 0);
|
||||
g_return_val_if_fail (packet->rtcp != NULL, 0);
|
||||
g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, 0);
|
||||
|
||||
if (packet->type == GST_RTCP_TYPE_SR)
|
||||
pse_offset += 5;
|
||||
pse_offset += (packet->count * 6);
|
||||
|
||||
if (pse_offset <= (packet->length + 1))
|
||||
return packet->length + 1 - pse_offset;
|
||||
|
||||
/* This means that the packet is invalid! */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_rtcp_packet_get_profile_specific_ext:
|
||||
* @packet: a valid SR or RR #GstRTCPPacket
|
||||
* @data: (out) (array length=len) (transfer none): result profile-specific data
|
||||
* @len: (out): result length of the profile-specific data
|
||||
*
|
||||
* Returns: %TRUE if there was valid data.
|
||||
*/
|
||||
gboolean
|
||||
gst_rtcp_packet_get_profile_specific_ext (GstRTCPPacket * packet,
|
||||
guint8 ** data, guint * len)
|
||||
{
|
||||
guint16 pse_len;
|
||||
|
||||
g_return_val_if_fail (packet != NULL, FALSE);
|
||||
g_return_val_if_fail (packet->type == GST_RTCP_TYPE_RR ||
|
||||
packet->type == GST_RTCP_TYPE_SR, FALSE);
|
||||
g_return_val_if_fail (packet->rtcp != NULL, FALSE);
|
||||
g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, FALSE);
|
||||
|
||||
pse_len = gst_rtcp_packet_get_profile_specific_ext_length (packet);
|
||||
if (pse_len > 0) {
|
||||
if (len != NULL)
|
||||
*len = pse_len * sizeof (guint32);
|
||||
if (data != NULL) {
|
||||
*data = packet->rtcp->map.data;
|
||||
*data += packet->offset;
|
||||
*data += ((packet->length + 1 - pse_len) * sizeof (guint32));
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_rtcp_packet_copy_profile_specific_ext:
|
||||
* @packet: a valid SR or RR #GstRTCPPacket
|
||||
* @data: (out) (array length=len): result profile-specific data
|
||||
* @len: (out): length of the profile-specific extension data
|
||||
*
|
||||
* The profile-specific extension data is copied into a new allocated
|
||||
* memory area @data. This must be freed with g_free() after usage.
|
||||
*
|
||||
* Returns: %TRUE if there was valid data.
|
||||
*/
|
||||
gboolean
|
||||
gst_rtcp_packet_copy_profile_specific_ext (GstRTCPPacket * packet,
|
||||
guint8 ** data, guint * len)
|
||||
{
|
||||
guint16 pse_len;
|
||||
|
||||
g_return_val_if_fail (packet != NULL, FALSE);
|
||||
g_return_val_if_fail (packet->type == GST_RTCP_TYPE_RR ||
|
||||
packet->type == GST_RTCP_TYPE_SR, FALSE);
|
||||
g_return_val_if_fail (packet->rtcp != NULL, FALSE);
|
||||
g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, FALSE);
|
||||
|
||||
pse_len = gst_rtcp_packet_get_profile_specific_ext_length (packet);
|
||||
if (pse_len > 0) {
|
||||
if (len != NULL)
|
||||
*len = pse_len * sizeof (guint32);
|
||||
if (data != NULL) {
|
||||
guint8 * ptr = packet->rtcp->map.data + packet->offset;
|
||||
ptr += ((packet->length + 1 - pse_len) * sizeof (guint32));
|
||||
*data = g_memdup (ptr, pse_len * sizeof (guint32));
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_rtcp_packet_sdes_get_item_count:
|
||||
* @packet: a valid SDES #GstRTCPPacket
|
||||
|
|
|
@ -279,6 +279,15 @@ void gst_rtcp_packet_set_rb (GstRTCPPacket *packet, gu
|
|||
guint32 exthighestseq, guint32 jitter,
|
||||
guint32 lsr, guint32 dlsr);
|
||||
|
||||
/* profile-specific extensions for SR and RR */
|
||||
gboolean gst_rtcp_packet_add_profile_specific_ext (GstRTCPPacket * packet,
|
||||
const guint8 * data, guint len);
|
||||
guint16 gst_rtcp_packet_get_profile_specific_ext_length (GstRTCPPacket * packet);
|
||||
gboolean gst_rtcp_packet_get_profile_specific_ext (GstRTCPPacket * packet,
|
||||
guint8 ** data, guint * len);
|
||||
gboolean gst_rtcp_packet_copy_profile_specific_ext (GstRTCPPacket * packet,
|
||||
guint8 ** data, guint * len);
|
||||
|
||||
/* source description packet */
|
||||
guint gst_rtcp_packet_sdes_get_item_count (GstRTCPPacket *packet);
|
||||
gboolean gst_rtcp_packet_sdes_first_item (GstRTCPPacket *packet);
|
||||
|
|
|
@ -991,6 +991,95 @@ GST_START_TEST (test_rtcp_validate_reduced_with_padding)
|
|||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_rtcp_buffer_profile_specific_extension)
|
||||
{
|
||||
GstBuffer *buf;
|
||||
GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
|
||||
GstRTCPPacket packet;
|
||||
const guint8 pse[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
|
||||
const guint8 pse2[] = { 0x01, 0x23, 0x45, 0x67 };
|
||||
|
||||
fail_unless ((buf = gst_rtcp_buffer_new (1400)) != NULL);
|
||||
gst_rtcp_buffer_map (buf, GST_MAP_READWRITE, &rtcp);
|
||||
|
||||
fail_unless (gst_rtcp_buffer_validate (buf) == FALSE);
|
||||
fail_unless (gst_rtcp_buffer_get_first_packet (&rtcp, &packet) == FALSE);
|
||||
fail_unless (gst_rtcp_buffer_get_packet_count (&rtcp) == 0);
|
||||
|
||||
/* add an SR packet with sender info */
|
||||
fail_unless (gst_rtcp_buffer_add_packet (&rtcp, GST_RTCP_TYPE_SR, &packet));
|
||||
gst_rtcp_packet_sr_set_sender_info (&packet, 0x44556677,
|
||||
G_GUINT64_CONSTANT (1), 0x11111111, 101, 123456);
|
||||
fail_unless_equals_int (0,
|
||||
gst_rtcp_packet_get_profile_specific_ext_length (&packet));
|
||||
fail_unless_equals_int (6, gst_rtcp_packet_get_length (&packet));
|
||||
|
||||
/* add profile-specific extension */
|
||||
fail_unless (gst_rtcp_packet_add_profile_specific_ext (&packet,
|
||||
pse, sizeof (pse)));
|
||||
{
|
||||
guint8 *data = NULL;
|
||||
guint len = 0;
|
||||
|
||||
fail_unless_equals_int (8, gst_rtcp_packet_get_length (&packet));
|
||||
fail_unless_equals_int (sizeof (pse) / 4,
|
||||
gst_rtcp_packet_get_profile_specific_ext_length (&packet));
|
||||
|
||||
/* gst_rtcp_packet_get_profile_specific_ext */
|
||||
fail_unless (gst_rtcp_packet_get_profile_specific_ext (&packet, &data, &len));
|
||||
fail_unless_equals_int (sizeof (pse), len);
|
||||
fail_unless (data != NULL);
|
||||
fail_unless_equals_int (0, memcmp (pse, data, sizeof (pse)));
|
||||
|
||||
/* gst_rtcp_packet_copy_profile_specific_ext */
|
||||
fail_unless (gst_rtcp_packet_copy_profile_specific_ext (&packet, &data, &len));
|
||||
fail_unless_equals_int (sizeof (pse), len);
|
||||
fail_unless (data != NULL);
|
||||
fail_unless_equals_int (0, memcmp (pse, data, sizeof (pse)));
|
||||
g_free (data);
|
||||
}
|
||||
|
||||
/* append more profile-specific extension */
|
||||
fail_unless (gst_rtcp_packet_add_profile_specific_ext (&packet,
|
||||
pse2, sizeof (pse2)));
|
||||
{
|
||||
guint8 *data = NULL;
|
||||
guint len = 0;
|
||||
guint concat_len;
|
||||
guint8 *concat_pse;
|
||||
|
||||
/* Expect the second extension to be appended to the first */
|
||||
concat_len = sizeof (pse) + sizeof (pse2);
|
||||
concat_pse = g_malloc (concat_len);
|
||||
memcpy (concat_pse, pse, sizeof (pse));
|
||||
memcpy (concat_pse + sizeof (pse), pse2, sizeof (pse2));
|
||||
|
||||
fail_unless_equals_int (9, gst_rtcp_packet_get_length (&packet));
|
||||
fail_unless_equals_int (concat_len / 4,
|
||||
gst_rtcp_packet_get_profile_specific_ext_length (&packet));
|
||||
|
||||
/* gst_rtcp_packet_get_profile_specific_ext */
|
||||
fail_unless (gst_rtcp_packet_get_profile_specific_ext (&packet, &data, &len));
|
||||
fail_unless_equals_int (concat_len, len);
|
||||
fail_unless (data != NULL);
|
||||
fail_unless_equals_int (0, memcmp (concat_pse, data, len));
|
||||
|
||||
/* gst_rtcp_packet_copy_profile_specific_ext */
|
||||
fail_unless (gst_rtcp_packet_copy_profile_specific_ext (&packet, &data, &len));
|
||||
fail_unless_equals_int (concat_len, len);
|
||||
fail_unless (data != NULL);
|
||||
fail_unless_equals_int (0, memcmp (concat_pse, data, len));
|
||||
g_free (data);
|
||||
g_free (concat_pse);
|
||||
}
|
||||
|
||||
/* close and validate */
|
||||
gst_rtcp_buffer_unmap (&rtcp);
|
||||
fail_unless (gst_rtcp_buffer_validate (buf) == TRUE);
|
||||
gst_buffer_unref (buf);
|
||||
}
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_rtp_ntp64_extension)
|
||||
{
|
||||
GstBuffer *buf;
|
||||
|
@ -1231,6 +1320,8 @@ rtp_suite (void)
|
|||
test_rtcp_validate_with_padding_set_in_first_packet);
|
||||
tcase_add_test (tc_chain, test_rtcp_validate_reduced_without_padding);
|
||||
tcase_add_test (tc_chain, test_rtcp_validate_reduced_with_padding);
|
||||
tcase_add_test (tc_chain, test_rtcp_buffer_profile_specific_extension);
|
||||
|
||||
tcase_add_test (tc_chain, test_rtp_ntp64_extension);
|
||||
tcase_add_test (tc_chain, test_rtp_ntp56_extension);
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ EXPORTS
|
|||
gst_rtcp_packet_bye_get_reason_len
|
||||
gst_rtcp_packet_bye_get_ssrc_count
|
||||
gst_rtcp_packet_bye_set_reason
|
||||
gst_rtcp_packet_copy_profile_specific_ext
|
||||
gst_rtcp_packet_fb_get_fci
|
||||
gst_rtcp_packet_fb_get_fci_length
|
||||
gst_rtcp_packet_fb_get_media_ssrc
|
||||
|
@ -32,6 +33,8 @@ EXPORTS
|
|||
gst_rtcp_packet_get_count
|
||||
gst_rtcp_packet_get_length
|
||||
gst_rtcp_packet_get_padding
|
||||
gst_rtcp_packet_get_profile_specific_ext
|
||||
gst_rtcp_packet_get_profile_specific_ext_len
|
||||
gst_rtcp_packet_get_rb
|
||||
gst_rtcp_packet_get_rb_count
|
||||
gst_rtcp_packet_get_type
|
||||
|
@ -49,6 +52,7 @@ EXPORTS
|
|||
gst_rtcp_packet_sdes_get_ssrc
|
||||
gst_rtcp_packet_sdes_next_entry
|
||||
gst_rtcp_packet_sdes_next_item
|
||||
gst_rtcp_packet_set_profile_specific_ext
|
||||
gst_rtcp_packet_set_rb
|
||||
gst_rtcp_packet_sr_get_sender_info
|
||||
gst_rtcp_packet_sr_set_sender_info
|
||||
|
|
Loading…
Reference in a new issue