mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-26 06:54:49 +00:00
rtcpbuffer: Add API for APP packets
https://bugzilla.gnome.org/show_bug.cgi?id=761944
This commit is contained in:
parent
d8e9a711a0
commit
93196092d1
3 changed files with 291 additions and 0 deletions
|
@ -2311,3 +2311,232 @@ gst_rtcp_packet_fb_get_fci (GstRTCPPacket * packet)
|
||||||
|
|
||||||
return data + 12;
|
return data + 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_rtcp_packet_app_set_subtype:
|
||||||
|
* @packet: a valid APP #GstRTCPPacket
|
||||||
|
* @subtype: subtype of the packet
|
||||||
|
*
|
||||||
|
* Set the subtype field of the APP @packet.
|
||||||
|
*
|
||||||
|
* Since: 1.8
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
gst_rtcp_packet_app_set_subtype (GstRTCPPacket * packet, guint8 subtype)
|
||||||
|
{
|
||||||
|
guint8 *data;
|
||||||
|
|
||||||
|
g_return_if_fail (packet != NULL);
|
||||||
|
g_return_if_fail (packet->type == GST_RTCP_TYPE_APP);
|
||||||
|
g_return_if_fail (packet->rtcp != NULL);
|
||||||
|
g_return_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE);
|
||||||
|
|
||||||
|
data = packet->rtcp->map.data + packet->offset;
|
||||||
|
data[0] = (data[0] & 0xe0) | subtype;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_rtcp_packet_app_get_subtype:
|
||||||
|
* @packet: a valid APP #GstRTCPPacket
|
||||||
|
*
|
||||||
|
* Get the subtype field of the APP @packet.
|
||||||
|
*
|
||||||
|
* Returns: The subtype.
|
||||||
|
*
|
||||||
|
* Since: 1.8
|
||||||
|
*/
|
||||||
|
guint8
|
||||||
|
gst_rtcp_packet_app_get_subtype (GstRTCPPacket * packet)
|
||||||
|
{
|
||||||
|
guint8 *data;
|
||||||
|
|
||||||
|
g_return_val_if_fail (packet != NULL, 0);
|
||||||
|
g_return_val_if_fail (packet->type == GST_RTCP_TYPE_APP, 0);
|
||||||
|
g_return_val_if_fail (packet->rtcp != NULL, 0);
|
||||||
|
g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, 0);
|
||||||
|
|
||||||
|
data = packet->rtcp->map.data + packet->offset;
|
||||||
|
|
||||||
|
return data[0] & 0x1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_rtcp_packet_app_set_ssrc:
|
||||||
|
* @packet: a valid APP #GstRTCPPacket
|
||||||
|
* @ssrc: SSRC/CSRC of the packet
|
||||||
|
*
|
||||||
|
* Set the SSRC/CSRC field of the APP @packet.
|
||||||
|
*
|
||||||
|
* Since: 1.8
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
gst_rtcp_packet_app_set_ssrc (GstRTCPPacket * packet, guint32 ssrc)
|
||||||
|
{
|
||||||
|
guint8 *data;
|
||||||
|
|
||||||
|
g_return_if_fail (packet != NULL);
|
||||||
|
g_return_if_fail (packet->type == GST_RTCP_TYPE_APP);
|
||||||
|
g_return_if_fail (packet->rtcp != NULL);
|
||||||
|
g_return_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE);
|
||||||
|
|
||||||
|
data = packet->rtcp->map.data + packet->offset + 4;
|
||||||
|
GST_WRITE_UINT32_BE (data, ssrc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_rtcp_packet_app_get_ssrc:
|
||||||
|
* @packet: a valid APP #GstRTCPPacket
|
||||||
|
*
|
||||||
|
* Get the SSRC/CSRC field of the APP @packet.
|
||||||
|
*
|
||||||
|
* Returns: The SSRC/CSRC.
|
||||||
|
*
|
||||||
|
* Since: 1.8
|
||||||
|
**/
|
||||||
|
guint32
|
||||||
|
gst_rtcp_packet_app_get_ssrc (GstRTCPPacket * packet)
|
||||||
|
{
|
||||||
|
guint8 *data;
|
||||||
|
|
||||||
|
g_return_val_if_fail (packet != NULL, 0);
|
||||||
|
g_return_val_if_fail (packet->type == GST_RTCP_TYPE_APP, 0);
|
||||||
|
g_return_val_if_fail (packet->rtcp != NULL, 0);
|
||||||
|
g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, 0);
|
||||||
|
|
||||||
|
data = packet->rtcp->map.data + packet->offset + 4;
|
||||||
|
|
||||||
|
return GST_READ_UINT32_BE (data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_rtcp_packet_app_set_name:
|
||||||
|
* @packet: a valid APP #GstRTCPPacket
|
||||||
|
* @name: 4-byte ASCII name
|
||||||
|
*
|
||||||
|
* Set the name field of the APP @packet.
|
||||||
|
*
|
||||||
|
* Since: 1.8
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
gst_rtcp_packet_app_set_name (GstRTCPPacket * packet, const gchar * name)
|
||||||
|
{
|
||||||
|
guint8 *data;
|
||||||
|
|
||||||
|
g_return_if_fail (packet != NULL);
|
||||||
|
g_return_if_fail (packet->type == GST_RTCP_TYPE_APP);
|
||||||
|
g_return_if_fail (packet->rtcp != NULL);
|
||||||
|
g_return_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE);
|
||||||
|
|
||||||
|
data = packet->rtcp->map.data + packet->offset + 8;
|
||||||
|
memcpy (data, name, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_rtcp_packet_app_get_name:
|
||||||
|
* @packet: a valid APP #GstRTCPPacket
|
||||||
|
*
|
||||||
|
* Get the name field of the APP @packet.
|
||||||
|
*
|
||||||
|
* Returns: The 4-byte name field, not zero-terminated.
|
||||||
|
*
|
||||||
|
* Since: 1.8
|
||||||
|
**/
|
||||||
|
const gchar *
|
||||||
|
gst_rtcp_packet_app_get_name (GstRTCPPacket * packet)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (packet != NULL, NULL);
|
||||||
|
g_return_val_if_fail (packet->type == GST_RTCP_TYPE_APP, NULL);
|
||||||
|
g_return_val_if_fail (packet->rtcp != NULL, NULL);
|
||||||
|
g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, NULL);
|
||||||
|
|
||||||
|
return (const gchar *)&packet->rtcp->map.data[packet->offset + 8];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_rtcp_packet_app_get_data_length:
|
||||||
|
* @packet: a valid APP #GstRTCPPacket
|
||||||
|
*
|
||||||
|
* Get the length of the application-dependent data attached to an APP
|
||||||
|
* @packet.
|
||||||
|
*
|
||||||
|
* Returns: The length of data in 32-bit words.
|
||||||
|
*
|
||||||
|
* Since: 1.8
|
||||||
|
**/
|
||||||
|
guint16
|
||||||
|
gst_rtcp_packet_app_get_data_length (GstRTCPPacket * packet)
|
||||||
|
{
|
||||||
|
guint8 *data;
|
||||||
|
|
||||||
|
g_return_val_if_fail (packet != NULL, 0);
|
||||||
|
g_return_val_if_fail (packet->type == GST_RTCP_TYPE_APP, 0);
|
||||||
|
g_return_val_if_fail (packet->rtcp != NULL, 0);
|
||||||
|
g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, 0);
|
||||||
|
|
||||||
|
data = packet->rtcp->map.data + packet->offset + 2;
|
||||||
|
|
||||||
|
return GST_READ_UINT16_BE (data) - 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_rtcp_packet_app_set_data_length:
|
||||||
|
* @packet: a valid APP #GstRTCPPacket
|
||||||
|
* @wordlen: Length of the data in 32-bit words
|
||||||
|
*
|
||||||
|
* Set the length of the application-dependent data attached to an APP
|
||||||
|
* @packet.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if there was enough space in the packet to add this much
|
||||||
|
* data.
|
||||||
|
*
|
||||||
|
* Since: 1.8
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
gst_rtcp_packet_app_set_data_length (GstRTCPPacket * packet, guint16 wordlen)
|
||||||
|
{
|
||||||
|
guint8 *data;
|
||||||
|
|
||||||
|
g_return_val_if_fail (packet != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (packet->type == GST_RTCP_TYPE_APP, FALSE);
|
||||||
|
g_return_val_if_fail (packet->rtcp != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE, FALSE);
|
||||||
|
|
||||||
|
if (packet->rtcp->map.maxsize < packet->offset + ((wordlen + 3) * 4))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
data = packet->rtcp->map.data + packet->offset + 2;
|
||||||
|
wordlen += 2;
|
||||||
|
GST_WRITE_UINT16_BE (data, wordlen);
|
||||||
|
|
||||||
|
packet->rtcp->map.size = packet->offset + ((wordlen + 1) * 4);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_rtcp_packet_app_get_data:
|
||||||
|
* @packet: a valid APP #GstRTCPPacket
|
||||||
|
*
|
||||||
|
* Get the application-dependent data attached to a RTPFB or PSFB @packet.
|
||||||
|
*
|
||||||
|
* Returns: A pointer to the data
|
||||||
|
*
|
||||||
|
* Since: 1.8
|
||||||
|
*/
|
||||||
|
guint8 *
|
||||||
|
gst_rtcp_packet_app_get_data (GstRTCPPacket * packet)
|
||||||
|
{
|
||||||
|
guint8 *data;
|
||||||
|
|
||||||
|
g_return_val_if_fail (packet != NULL, NULL);
|
||||||
|
g_return_val_if_fail (packet->type == GST_RTCP_TYPE_APP, NULL);
|
||||||
|
g_return_val_if_fail (packet->rtcp != NULL, NULL);
|
||||||
|
g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, NULL);
|
||||||
|
|
||||||
|
data = packet->rtcp->map.data + packet->offset;
|
||||||
|
|
||||||
|
if (GST_READ_UINT16_BE (data + 2) <= 2)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return data + 12;
|
||||||
|
}
|
||||||
|
|
|
@ -315,6 +315,17 @@ guint8 gst_rtcp_packet_bye_get_reason_len (GstRTCPPacket *packet);
|
||||||
gchar* gst_rtcp_packet_bye_get_reason (GstRTCPPacket *packet);
|
gchar* gst_rtcp_packet_bye_get_reason (GstRTCPPacket *packet);
|
||||||
gboolean gst_rtcp_packet_bye_set_reason (GstRTCPPacket *packet, const gchar *reason);
|
gboolean gst_rtcp_packet_bye_set_reason (GstRTCPPacket *packet, const gchar *reason);
|
||||||
|
|
||||||
|
/* app packets */
|
||||||
|
void gst_rtcp_packet_app_set_subtype (GstRTCPPacket * packet, guint8 subtype);
|
||||||
|
guint8 gst_rtcp_packet_app_get_subtype (GstRTCPPacket * packet);
|
||||||
|
void gst_rtcp_packet_app_set_ssrc (GstRTCPPacket * packet, guint32 ssrc);
|
||||||
|
guint32 gst_rtcp_packet_app_get_ssrc (GstRTCPPacket * packet);
|
||||||
|
void gst_rtcp_packet_app_set_name (GstRTCPPacket * packet, const gchar *name);
|
||||||
|
const gchar* gst_rtcp_packet_app_get_name (GstRTCPPacket * packet);
|
||||||
|
guint16 gst_rtcp_packet_app_get_data_length (GstRTCPPacket * packet);
|
||||||
|
gboolean gst_rtcp_packet_app_set_data_length (GstRTCPPacket * packet, guint16 wordlen);
|
||||||
|
guint8* gst_rtcp_packet_app_get_data (GstRTCPPacket * packet);
|
||||||
|
|
||||||
/* feedback packets */
|
/* feedback packets */
|
||||||
guint32 gst_rtcp_packet_fb_get_sender_ssrc (GstRTCPPacket *packet);
|
guint32 gst_rtcp_packet_fb_get_sender_ssrc (GstRTCPPacket *packet);
|
||||||
void gst_rtcp_packet_fb_set_sender_ssrc (GstRTCPPacket *packet, guint32 ssrc);
|
void gst_rtcp_packet_fb_set_sender_ssrc (GstRTCPPacket *packet, guint32 ssrc);
|
||||||
|
|
|
@ -1080,6 +1080,56 @@ GST_START_TEST (test_rtcp_buffer_profile_specific_extension)
|
||||||
}
|
}
|
||||||
GST_END_TEST;
|
GST_END_TEST;
|
||||||
|
|
||||||
|
GST_START_TEST (test_rtcp_buffer_app)
|
||||||
|
{
|
||||||
|
GstBuffer *buf;
|
||||||
|
GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
|
||||||
|
GstRTCPPacket packet;
|
||||||
|
guint mtu = 1000;
|
||||||
|
const guint8 data[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
|
||||||
|
guint max_data_length = (mtu - 12) / 4;
|
||||||
|
guint8 *data_ptr;
|
||||||
|
|
||||||
|
fail_unless ((buf = gst_rtcp_buffer_new (mtu)) != NULL);
|
||||||
|
gst_rtcp_buffer_map (buf, GST_MAP_READWRITE, &rtcp);
|
||||||
|
|
||||||
|
/* Not a valid packet yet */
|
||||||
|
fail_if (gst_rtcp_buffer_validate (buf));
|
||||||
|
fail_if (gst_rtcp_buffer_get_first_packet (&rtcp, &packet));
|
||||||
|
fail_unless_equals_int (gst_rtcp_buffer_get_packet_count (&rtcp), 0);
|
||||||
|
|
||||||
|
/* Add APP packet */
|
||||||
|
fail_unless (gst_rtcp_buffer_add_packet (&rtcp, GST_RTCP_TYPE_APP, &packet));
|
||||||
|
gst_rtcp_packet_app_set_subtype (&packet, 0x15);
|
||||||
|
gst_rtcp_packet_app_set_ssrc (&packet, 0x01234567);
|
||||||
|
gst_rtcp_packet_app_set_name (&packet, "Test");
|
||||||
|
|
||||||
|
/* Check maximum allowed data */
|
||||||
|
fail_if (gst_rtcp_packet_app_set_data_length (&packet, max_data_length + 1));
|
||||||
|
fail_unless (gst_rtcp_packet_app_set_data_length (&packet, max_data_length));
|
||||||
|
|
||||||
|
/* Add data */
|
||||||
|
fail_unless (gst_rtcp_packet_app_set_data_length (&packet, (sizeof (data) + 3) / 4));
|
||||||
|
fail_unless_equals_int (gst_rtcp_packet_app_get_data_length (&packet), 2);
|
||||||
|
fail_unless ((data_ptr = gst_rtcp_packet_app_get_data (&packet)));
|
||||||
|
memcpy (data_ptr, data, sizeof (data));
|
||||||
|
|
||||||
|
gst_rtcp_buffer_unmap (&rtcp);
|
||||||
|
|
||||||
|
/* Map again with only the READ flag and check fields */
|
||||||
|
gst_rtcp_buffer_map (buf, GST_MAP_READ, &rtcp);
|
||||||
|
fail_unless_equals_int (gst_rtcp_packet_app_get_subtype (&packet), 0x15);
|
||||||
|
fail_unless_equals_int (gst_rtcp_packet_app_get_ssrc (&packet), 0x01234567);
|
||||||
|
fail_unless (memcmp (gst_rtcp_packet_app_get_name (&packet), "Test", 4) == 0);
|
||||||
|
fail_unless_equals_int (gst_rtcp_packet_app_get_data_length (&packet), 2);
|
||||||
|
fail_unless ((data_ptr = gst_rtcp_packet_app_get_data (&packet)));
|
||||||
|
fail_unless (memcmp (data_ptr, data, sizeof (data)) == 0);
|
||||||
|
gst_rtcp_buffer_unmap (&rtcp);
|
||||||
|
|
||||||
|
gst_buffer_unref (buf);
|
||||||
|
}
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
GST_START_TEST (test_rtp_ntp64_extension)
|
GST_START_TEST (test_rtp_ntp64_extension)
|
||||||
{
|
{
|
||||||
GstBuffer *buf;
|
GstBuffer *buf;
|
||||||
|
@ -1321,6 +1371,7 @@ rtp_suite (void)
|
||||||
tcase_add_test (tc_chain, test_rtcp_validate_reduced_without_padding);
|
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_validate_reduced_with_padding);
|
||||||
tcase_add_test (tc_chain, test_rtcp_buffer_profile_specific_extension);
|
tcase_add_test (tc_chain, test_rtcp_buffer_profile_specific_extension);
|
||||||
|
tcase_add_test (tc_chain, test_rtcp_buffer_app);
|
||||||
|
|
||||||
tcase_add_test (tc_chain, test_rtp_ntp64_extension);
|
tcase_add_test (tc_chain, test_rtp_ntp64_extension);
|
||||||
tcase_add_test (tc_chain, test_rtp_ntp56_extension);
|
tcase_add_test (tc_chain, test_rtp_ntp56_extension);
|
||||||
|
|
Loading…
Reference in a new issue