rtcpbuffer: Add profile-specific extension API.

https://bugzilla.gnome.org/show_bug.cgi?id=761950
This commit is contained in:
Haakon Sporsheim 2014-07-29 15:37:12 +02:00 committed by Sebastian Dröge
parent 2d1c9f8c0f
commit d8e9a711a0
4 changed files with 257 additions and 0 deletions

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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