rtcpbuffer: add support XR packet parsing

According to RFC3611, the extended report blocks in XR packet can
have variable length. To visit each block, the iterator should look
into block header. Once XR type is extracted, users can parse the
detailed information by given functions.

Loss/Duplicate RLE
The Loss RLE and the Duplicate RLE have same format so
they can share parsers. For unit test, randomly generated
pseudo packet is used.

Packet Receipt Times
The packet receipt times report block has a list of receipt
times which are in [begin_seq, end_seq).

Receiver Reference Time paser for XR packet
The receiver reference time has ntptime which is 64 bit type.

DLRR
The DLRR report block consists of sub-blocks which has ssrc, last RR,
and delay since last RR. The number of sub-blocks should be calculated
from block length.

Statistics Summary
The Statistics Summary report block provides fixed length
information.

VoIP Metrics
VoIP Metrics consists of several metrics even though they are in
a report block. Data retrieving functions are added per metrics.

https://bugzilla.gnome.org/show_bug.cgi?id=789822
This commit is contained in:
Justin Kim 2017-11-01 10:54:06 +09:00 committed by Olivier Crête
parent 18c9babef9
commit 5303e2c32b
4 changed files with 1641 additions and 2 deletions

View file

@ -1457,6 +1457,7 @@ GstRTCPType
GstRTCPPacket
GstRTCPSDESType
GstRTCPFBType
GstRTCPXRType
gst_rtcp_buffer_new_take_data
gst_rtcp_buffer_new_copy_data
@ -1550,6 +1551,36 @@ gst_rtcp_unix_to_ntp
gst_rtcp_sdes_name_to_type
gst_rtcp_sdes_type_to_name
gst_rtcp_packet_xr_first_rb
gst_rtcp_packet_xr_next_rb
gst_rtcp_packet_xr_get_ssrc
gst_rtcp_packet_xr_get_block_length
gst_rtcp_packet_xr_get_block_type
gst_rtcp_packet_xr_get_dlrr_block
gst_rtcp_packet_xr_get_prt_by_seq
gst_rtcp_packet_xr_get_prt_info
gst_rtcp_packet_xr_get_rle_info
gst_rtcp_packet_xr_get_rle_nth_chunk
gst_rtcp_packet_xr_get_rrt
gst_rtcp_packet_xr_get_summary_info
gst_rtcp_packet_xr_get_summary_jitter
gst_rtcp_packet_xr_get_summary_pkt
gst_rtcp_packet_xr_get_summary_ttl
gst_rtcp_packet_xr_get_voip_burst_metrics
gst_rtcp_packet_xr_get_voip_configuration_params
gst_rtcp_packet_xr_get_voip_delay_metrics
gst_rtcp_packet_xr_get_voip_jitter_buffer_params
gst_rtcp_packet_xr_get_voip_metrics_ssrc
gst_rtcp_packet_xr_get_voip_packet_metrics
gst_rtcp_packet_xr_get_voip_quality_metrics
gst_rtcp_packet_xr_get_voip_signal_metrics
<SUBSECTION Standard>
GST_RTCP_RTPFB_TYPE_RCTP_SR_REQ
GST_TYPE_RTCPFB_TYPE
@ -1558,6 +1589,7 @@ GST_TYPE_RTCP_TYPE
gst_rtcp_type_get_type
gst_rtcpfb_type_get_type
gst_rtcpsdes_type_get_type
gst_rtcpxr_type_get_type
</SECTION>
<SECTION>

File diff suppressed because it is too large Load diff

View file

@ -137,6 +137,34 @@ typedef enum
GST_RTCP_SDES_PRIV = 8
} GstRTCPSDESType;
/**
* GstRTCPXRType:
* @GST_RTCP_XR_TYPE_INVALID: Invalid XR Report Block
* @GST_RTCP_XR_TYPE_LRLE: Loss RLE Report Block
* @GST_RTCP_XR_TYPE_DRLE: Duplicate RLE Report Block
* @GST_RTCP_XR_TYPE_PRT: Packet Receipt Times Report Block
* @GST_RTCP_XR_TYPE_RRT: Receiver Reference Time Report Block
* @GST_RTCP_XR_TYPE_DLRR: Delay since the last Receiver Report
* @GST_RTCP_XR_TYPE_SSUMM: Statistics Summary Report Block
* @GST_RTCP_XR_TYPE_VOIP_METRICS: VoIP Metrics Report Block
*
* Types of RTCP Extended Reports, those are defined in RFC 3611 and other RFCs
* according to the [IANA registry](https://www.iana.org/assignments/rtcp-xr-block-types/rtcp-xr-block-types.xhtml).
*
* Since: 1.16
*/
typedef enum
{
GST_RTCP_XR_TYPE_INVALID = -1,
GST_RTCP_XR_TYPE_LRLE = 1,
GST_RTCP_XR_TYPE_DRLE = 2,
GST_RTCP_XR_TYPE_PRT = 3,
GST_RTCP_XR_TYPE_RRT = 4,
GST_RTCP_XR_TYPE_DLRR = 5,
GST_RTCP_XR_TYPE_SSUMM = 6,
GST_RTCP_XR_TYPE_VOIP_METRICS = 7
} GstRTCPXRType;
/**
* GST_RTCP_MAX_SDES:
*
@ -217,7 +245,7 @@ struct _GstRTCPPacket
gboolean padding; /* padding field of current packet */
guint8 count; /* count field of current packet */
GstRTCPType type; /* type of current packet */
guint16 length; /* length of current packet in 32-bits words */
guint16 length; /* length of current packet in 32-bits words minus one, this is validated when doing _get_first_packet() and _move_to_next() */
guint item_offset; /* current item offset for navigating SDES */
guint item_count; /* current item count */
@ -479,6 +507,105 @@ const gchar * gst_rtcp_sdes_type_to_name (GstRTCPSDESType type);
GST_RTP_API
GstRTCPSDESType gst_rtcp_sdes_name_to_type (const gchar *name);
/* extended report */
GST_RTP_API
guint32 gst_rtcp_packet_xr_get_ssrc (GstRTCPPacket *packet);
GST_RTP_API
gboolean gst_rtcp_packet_xr_first_rb (GstRTCPPacket *packet);
GST_RTP_API
gboolean gst_rtcp_packet_xr_next_rb (GstRTCPPacket * packet);
GST_RTP_API
GstRTCPXRType gst_rtcp_packet_xr_get_block_type (GstRTCPPacket * packet);
GST_RTP_API
guint16 gst_rtcp_packet_xr_get_block_length (GstRTCPPacket * packet);
GST_RTP_API
gboolean gst_rtcp_packet_xr_get_rle_info (GstRTCPPacket * packet,
guint32 * ssrc, guint8 * thining,
guint16 * begin_seq, guint16 * end_seq,
guint32 * chunk_count);
GST_RTP_API
gboolean gst_rtcp_packet_xr_get_rle_nth_chunk (GstRTCPPacket * packet, guint nth,
guint16 * chunk);
GST_RTP_API
gboolean gst_rtcp_packet_xr_get_prt_info (GstRTCPPacket * packet,
guint32 * ssrc, guint8 * thining,
guint16 * begin_seq, guint16 * end_seq);
GST_RTP_API
gboolean gst_rtcp_packet_xr_get_prt_by_seq (GstRTCPPacket * packet, guint16 seq,
guint32 * receipt_time);
GST_RTP_API
gboolean gst_rtcp_packet_xr_get_rrt (GstRTCPPacket * packet, guint64 * timestamp);
GST_RTP_API
gboolean gst_rtcp_packet_xr_get_dlrr_block (GstRTCPPacket * packet,
guint nth, guint32 * ssrc,
guint32 * last_rr, guint32 * delay);
GST_RTP_API
gboolean gst_rtcp_packet_xr_get_summary_info (GstRTCPPacket * packet, guint32 * ssrc,
guint16 * begin_seq, guint16 * end_seq);
GST_RTP_API
gboolean gst_rtcp_packet_xr_get_summary_pkt (GstRTCPPacket * packet,
guint32 * lost_packets, guint32 * dup_packets);
GST_RTP_API
gboolean gst_rtcp_packet_xr_get_summary_jitter (GstRTCPPacket * packet,
guint32 * min_jitter, guint32 * max_jitter,
guint32 * mean_jitter, guint32 * dev_jitter);
GST_RTP_API
gboolean gst_rtcp_packet_xr_get_summary_ttl (GstRTCPPacket * packet, gboolean * is_ipv4,
guint8 * min_ttl, guint8 * max_ttl,
guint8 * mean_ttl, guint8 * dev_ttl);
GST_RTP_API
gboolean gst_rtcp_packet_xr_get_voip_metrics_ssrc (GstRTCPPacket * packet, guint32 * ssrc);
GST_RTP_API
gboolean gst_rtcp_packet_xr_get_voip_packet_metrics (GstRTCPPacket * packet,
guint8 * loss_rate, guint8 * discard_rate);
GST_RTP_API
gboolean gst_rtcp_packet_xr_get_voip_burst_metrics (GstRTCPPacket * packet,
guint8 * burst_density, guint8 * gap_density,
guint16 * burst_duration, guint16 * gap_duration);
GST_RTP_API
gboolean gst_rtcp_packet_xr_get_voip_delay_metrics (GstRTCPPacket * packet,
guint16 * roundtrip_delay,
guint16 * end_system_delay);
GST_RTP_API
gboolean gst_rtcp_packet_xr_get_voip_signal_metrics (GstRTCPPacket * packet,
guint8 * signal_level, guint8 * noise_level,
guint8 * rerl, guint8 * gmin);
GST_RTP_API
gboolean gst_rtcp_packet_xr_get_voip_quality_metrics (GstRTCPPacket * packet,
guint8 * r_factor, guint8 * ext_r_factor,
guint8 * mos_lq, guint8 * mos_cq);
GST_RTP_API
gboolean gst_rtcp_packet_xr_get_voip_configuration_params (GstRTCPPacket * packet,
guint8 * gmin, guint8 * rx_config);
GST_RTP_API
gboolean gst_rtcp_packet_xr_get_voip_jitter_buffer_params (GstRTCPPacket * packet,
guint16 * jb_nominal,
guint16 * jb_maximum,
guint16 * jb_abs_max);
G_END_DECLS
#endif /* __GST_RTCPBUFFER_H__ */

View file

@ -1137,6 +1137,467 @@ GST_START_TEST (test_rtcp_buffer_app)
GST_END_TEST;
GST_START_TEST (test_rtcp_buffer_xr)
{
GstBuffer *buffer;
GstRTCPPacket packet;
GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
guint8 rtcp_pkt[] = {
0x80, 0xCF, 0x00, 0x0e, /* Type XR, length = 14 */
0x97, 0x6d, 0x21, 0x6a,
0x01, 0x00, 0x00, 0x03, /* Loss RLE, No thining, length = 3 */
0x97, 0x6d, 0x21, 0x6a, /* SSRC of source */
0x00, 0x01, 0x00, 0x02,
0xcf, 0xb7, 0x8f, 0xb7,
0x02, 0x00, 0x00, 0x03, /* Dup RLE, No thining, length = 3 */
0x97, 0x6d, 0x21, 0x6a, /* SSRC of source */
0x00, 0x01, 0x00, 0x02,
0xcf, 0xb7, 0x8f, 0xb7,
0x03, 0x00, 0x00, 0x04, /* Packet Receipt Times, No thining, length = 4 */
0x97, 0x6d, 0x21, 0x6a, /* SSRC of source */
0x00, 0x01, 0x00, 0x02,
0x59, 0xf9, 0xdd, 0x7e,
0x59, 0xf9, 0xdd, 0x7e,
};
buffer = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
rtcp_pkt, sizeof (rtcp_pkt), 0, sizeof (rtcp_pkt), NULL, NULL);
fail_unless (gst_rtcp_buffer_map (buffer, GST_MAP_READ, &rtcp));
fail_unless (gst_rtcp_buffer_get_first_packet (&rtcp, &packet));
fail_unless (gst_rtcp_packet_get_type (&packet) == GST_RTCP_TYPE_XR);
fail_unless (gst_rtcp_packet_xr_get_ssrc (&packet) ==
GST_READ_UINT32_BE (rtcp_pkt + 12));
fail_unless (gst_rtcp_packet_xr_first_rb (&packet));
fail_unless (gst_rtcp_packet_xr_get_block_type (&packet) ==
GST_RTCP_XR_TYPE_LRLE);
fail_unless (gst_rtcp_packet_xr_next_rb (&packet));
fail_unless (gst_rtcp_packet_xr_get_block_type (&packet) ==
GST_RTCP_XR_TYPE_DRLE);
fail_unless (gst_rtcp_packet_xr_next_rb (&packet));
fail_unless (gst_rtcp_packet_xr_get_block_type (&packet) ==
GST_RTCP_XR_TYPE_PRT);
fail_if (gst_rtcp_packet_xr_next_rb (&packet));
gst_rtcp_buffer_unmap (&rtcp);
gst_buffer_unref (buffer);
}
GST_END_TEST;
GST_START_TEST (test_rtcp_buffer_xr_rle)
{
GstBuffer *buffer;
GstRTCPPacket packet;
guint32 ssrc, chunk_count;
guint8 thining;
guint16 begin_seq, end_seq, chunk;
GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
guint8 rtcp_pkt[] = {
0x80, 0xCF, 0x00, 0x0a, /* Type XR, length = 10 */
0x97, 0x6d, 0x21, 0x6a,
0x01, 0x00, 0x00, 0x03, /* Loss RLE, No thining, length = 3 */
0x97, 0x6d, 0x21, 0x6a, /* SSRC of source */
0x00, 0x01, 0x00, 0x02,
0x80, 0x12, 0x00, 0x00,
0x02, 0x00, 0x00, 0x04, /* Dup RLE, No thining, length = 4 */
0x97, 0x6d, 0x21, 0x7b, /* SSRC of source */
0x00, 0x01, 0x00, 0x04,
0x8f, 0x21, 0x8f, 0x22,
0x8f, 0x23, 0x8f, 0x24
};
guint8 rtcp_pkt_invalid_pkt_length[] = {
0x80, 0xCF, 0x00, 0x04, /* Type XR, length = 4 */
0x97, 0x6d, 0x21, 0x6a,
0x01, 0x00, 0x00, 0x02, /* Loss RLE, No thining, length = 1 (but really 3) */
0x97, 0x6d, 0x21, 0x6a, /* SSRC of source */
0x00, 0x01, 0x00, 0x02,
};
buffer = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
rtcp_pkt, sizeof (rtcp_pkt), 0, sizeof (rtcp_pkt), NULL, NULL);
gst_rtcp_buffer_map (buffer, GST_MAP_READ, &rtcp);
fail_unless (gst_rtcp_buffer_get_first_packet (&rtcp, &packet));
/* check LRLE */
fail_unless (gst_rtcp_packet_xr_first_rb (&packet));
fail_unless (gst_rtcp_packet_xr_get_block_type (&packet) ==
GST_RTCP_XR_TYPE_LRLE);
fail_unless (gst_rtcp_packet_xr_get_rle_info (&packet, &ssrc, &thining,
&begin_seq, &end_seq, &chunk_count));
fail_unless_equals_int (ssrc, GST_READ_UINT32_BE (rtcp_pkt + 12));
fail_unless_equals_int (thining, 0);
fail_unless_equals_int (begin_seq, 0x0001);
fail_unless_equals_int (end_seq, 0x0002);
fail_unless_equals_int (chunk_count, 2);
gst_rtcp_packet_xr_get_rle_nth_chunk (&packet, 0, &chunk);
fail_unless_equals_int (chunk, 0x8012);
gst_rtcp_packet_xr_get_rle_nth_chunk (&packet, 1, &chunk);
fail_unless_equals_int (chunk, 0x0);
/* check DRLE */
fail_unless (gst_rtcp_packet_xr_next_rb (&packet));
fail_unless (gst_rtcp_packet_xr_get_block_type (&packet) ==
GST_RTCP_XR_TYPE_DRLE);
fail_unless (gst_rtcp_packet_xr_get_rle_info (&packet, &ssrc, &thining,
&begin_seq, &end_seq, &chunk_count));
fail_unless_equals_int (ssrc, GST_READ_UINT32_BE (rtcp_pkt + 28));
fail_unless_equals_int (thining, 0);
fail_unless_equals_int (begin_seq, 0x0001);
fail_unless_equals_int (end_seq, 0x0004);
fail_unless_equals_int (chunk_count, 4);
gst_rtcp_packet_xr_get_rle_nth_chunk (&packet, 1, &chunk);
fail_unless_equals_int (chunk, 0x8f22);
gst_rtcp_packet_xr_get_rle_nth_chunk (&packet, 2, &chunk);
fail_unless_equals_int (chunk, 0x8f23);
gst_rtcp_buffer_unmap (&rtcp);
gst_buffer_unref (buffer);
/* Test invalid length */
buffer = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
rtcp_pkt_invalid_pkt_length, sizeof (rtcp_pkt_invalid_pkt_length), 0,
sizeof (rtcp_pkt_invalid_pkt_length), NULL, NULL);
gst_rtcp_buffer_map (buffer, GST_MAP_READ, &rtcp);
fail_unless (gst_rtcp_buffer_get_first_packet (&rtcp, &packet));
/* check LRLE (should fail because length is too short) */
fail_unless (gst_rtcp_packet_xr_first_rb (&packet));
fail_unless (gst_rtcp_packet_xr_get_block_type (&packet) ==
GST_RTCP_XR_TYPE_LRLE);
fail_if (gst_rtcp_packet_xr_get_rle_info (&packet, &ssrc, &thining,
&begin_seq, &end_seq, &chunk_count));
gst_rtcp_buffer_unmap (&rtcp);
gst_buffer_unref (buffer);
}
GST_END_TEST;
GST_START_TEST (test_rtcp_buffer_xr_prt)
{
GstBuffer *buffer;
GstRTCPPacket packet;
guint32 ssrc, receipt_time;
guint8 thining;
guint16 begin_seq, end_seq;
GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
guint8 rtcp_pkt[] = {
0x80, 0xCF, 0x00, 0x06, /* Type XR, length = 6 */
0x97, 0x6d, 0x21, 0x6a,
0x03, 0x00, 0x00, 0x04, /* Packet Receipt Times, No thining, length = 4 */
0x97, 0x6d, 0x21, 0x6a, /* SSRC of source */
0x00, 0x01, 0x00, 0x03,
0x59, 0xf9, 0xdd, 0x7e,
0x59, 0xf9, 0xde, 0x00,
};
guint8 rtcp_pkt_invalid_pkt_length[] = {
0x80, 0xCF, 0x00, 0x04, /* Type XR, length = 4 */
0x97, 0x6d, 0x21, 0x6a,
0x03, 0x00, 0x00, 0x02, /* Packet Receipt Times, No thining, length = 2 (but should be 4) */
0x97, 0x6d, 0x21, 0x6a, /* SSRC of source */
0x00, 0x01, 0x00, 0x03,
};
buffer = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
rtcp_pkt, sizeof (rtcp_pkt), 0, sizeof (rtcp_pkt), NULL, NULL);
gst_rtcp_buffer_map (buffer, GST_MAP_READ, &rtcp);
fail_unless (gst_rtcp_buffer_get_first_packet (&rtcp, &packet));
fail_unless (gst_rtcp_packet_xr_first_rb (&packet));
fail_unless (gst_rtcp_packet_xr_get_block_type (&packet) ==
GST_RTCP_XR_TYPE_PRT);
fail_unless (gst_rtcp_packet_xr_get_prt_info (&packet, &ssrc, &thining,
&begin_seq, &end_seq));
fail_unless (gst_rtcp_packet_xr_get_prt_by_seq (&packet, 2, &receipt_time));
fail_unless_equals_int_hex (receipt_time, 0x59f9de00L);
gst_rtcp_buffer_unmap (&rtcp);
gst_buffer_unref (buffer);
/* Test for invalid length */
buffer = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
rtcp_pkt_invalid_pkt_length, sizeof (rtcp_pkt_invalid_pkt_length), 0,
sizeof (rtcp_pkt_invalid_pkt_length), NULL, NULL);
gst_rtcp_buffer_map (buffer, GST_MAP_READ, &rtcp);
fail_unless (gst_rtcp_buffer_get_first_packet (&rtcp, &packet));
fail_unless (gst_rtcp_packet_xr_first_rb (&packet));
fail_unless (gst_rtcp_packet_xr_get_block_type (&packet) ==
GST_RTCP_XR_TYPE_PRT);
fail_if (gst_rtcp_packet_xr_get_prt_info (&packet, &ssrc, &thining,
&begin_seq, &end_seq));
gst_rtcp_buffer_unmap (&rtcp);
gst_buffer_unref (buffer);
}
GST_END_TEST;
GST_START_TEST (test_rtcp_buffer_xr_rrt)
{
GstBuffer *buffer;
GstRTCPPacket packet;
guint64 ntptime;
GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
guint8 rtcp_pkt[] = {
0x80, 0xCF, 0x00, 0x04, /* Type XR, length = 4 */
0x97, 0x6d, 0x21, 0x6a,
0x04, 0x00, 0x00, 0x02, /* Receiver Reference Time, length = 2 */
0x01, 0x23, 0x45, 0x67,
0x89, 0x01, 0x23, 0x45
};
guint8 rtcp_pkt_invalid_pkt_length[] = {
0x80, 0xCF, 0x00, 0x04, /* Type XR, length = 4 */
0x97, 0x6d, 0x21, 0x6a,
0x04, 0x00, 0x00, 0x01, /* Receiver Reference Time, length = 1 */
0x01, 0x23, 0x45, 0x67,
0x89, 0x01, 0x23, 0x45
};
buffer = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
rtcp_pkt, sizeof (rtcp_pkt), 0, sizeof (rtcp_pkt), NULL, NULL);
gst_rtcp_buffer_map (buffer, GST_MAP_READ, &rtcp);
fail_unless (gst_rtcp_buffer_get_first_packet (&rtcp, &packet));
fail_unless (gst_rtcp_packet_xr_first_rb (&packet));
fail_unless (gst_rtcp_packet_xr_get_block_type (&packet) ==
GST_RTCP_XR_TYPE_RRT);
fail_unless (gst_rtcp_packet_xr_get_rrt (&packet, &ntptime));
fail_unless_equals_uint64_hex (ntptime, 0x0123456789012345LL);
gst_rtcp_buffer_unmap (&rtcp);
gst_buffer_unref (buffer);
/* Test invalid length */
buffer = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
rtcp_pkt_invalid_pkt_length, sizeof (rtcp_pkt_invalid_pkt_length), 0,
sizeof (rtcp_pkt_invalid_pkt_length), NULL, NULL);
gst_rtcp_buffer_map (buffer, GST_MAP_READ, &rtcp);
fail_unless (gst_rtcp_buffer_get_first_packet (&rtcp, &packet));
fail_unless (gst_rtcp_packet_xr_first_rb (&packet));
fail_unless (gst_rtcp_packet_xr_get_block_type (&packet) ==
GST_RTCP_XR_TYPE_RRT);
fail_if (gst_rtcp_packet_xr_get_rrt (&packet, &ntptime));
gst_rtcp_buffer_unmap (&rtcp);
gst_buffer_unref (buffer);
}
GST_END_TEST;
GST_START_TEST (test_rtcp_buffer_xr_dlrr)
{
GstBuffer *buffer;
GstRTCPPacket packet;
guint32 ssrc, last_rr, delay;
GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
guint8 rtcp_pkt[] = {
0x80, 0xCF, 0x00, 0x08, /* Type XR, length = 8 */
0x97, 0x6d, 0x21, 0x6a,
0x05, 0x00, 0x00, 0x06, /* DLRR, length = 6 */
0x97, 0x6d, 0x21, 0x6a, /* SSRC of source */
0x01, 0x23, 0x45, 0x67,
0x89, 0x01, 0x23, 0x45,
0x97, 0x6d, 0x21, 0x6b, /* SSRC of source */
0x01, 0x23, 0x45, 0x67,
0x89, 0x01, 0x23, 0x45
};
buffer = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
rtcp_pkt, sizeof (rtcp_pkt), 0, sizeof (rtcp_pkt), NULL, NULL);
gst_rtcp_buffer_map (buffer, GST_MAP_READ, &rtcp);
fail_unless (gst_rtcp_buffer_get_first_packet (&rtcp, &packet));
fail_unless (gst_rtcp_packet_xr_first_rb (&packet));
fail_unless (gst_rtcp_packet_xr_get_block_type (&packet) ==
GST_RTCP_XR_TYPE_DLRR);
fail_unless (gst_rtcp_packet_xr_get_dlrr_block (&packet, 0, &ssrc, &last_rr,
&delay));
fail_unless_equals_int_hex (ssrc, GST_READ_UINT32_BE (rtcp_pkt + 12));
fail_unless (gst_rtcp_packet_xr_get_dlrr_block (&packet, 1, &ssrc, &last_rr,
&delay));
fail_unless_equals_int_hex (ssrc, GST_READ_UINT32_BE (rtcp_pkt + 24));
/* it has only two sub-blocks. */
fail_if (gst_rtcp_packet_xr_get_dlrr_block (&packet, 2, &ssrc, &last_rr,
&delay));
gst_rtcp_buffer_unmap (&rtcp);
gst_buffer_unref (buffer);
}
GST_END_TEST;
GST_START_TEST (test_rtcp_buffer_xr_ssumm)
{
GstBuffer *buffer;
GstRTCPPacket packet;
guint32 ssrc, lost_packets, dup_packets;
guint16 begin_seq, end_seq;
guint32 min_jitter, max_jitter, mean_jitter, dev_jitter;
guint8 min_ttl, max_ttl, mean_ttl, dev_ttl;
gboolean ipv4;
GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
guint8 rtcp_pkt[] = {
0x80, 0xCF, 0x00, 0x0b, /* Type XR, length = 11 */
0x97, 0x6d, 0x21, 0x6a,
0x06, 0xe8, 0x00, 0x09, /* Statistics summary, length = 9 */
0x97, 0x6d, 0x21, 0x6a, /* SSRC of source */
0x00, 0x01, 0x00, 0x02,
0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x02,
0x00, 0x00, 0x00, 0x03,
0x00, 0x00, 0x00, 0x04,
0x00, 0x00, 0x00, 0x05,
0x00, 0x00, 0x00, 0x06,
0x01, 0x80, 0x0f, 0x8f
};
buffer = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
rtcp_pkt, sizeof (rtcp_pkt), 0, sizeof (rtcp_pkt), NULL, NULL);
gst_rtcp_buffer_map (buffer, GST_MAP_READ, &rtcp);
fail_unless (gst_rtcp_buffer_get_first_packet (&rtcp, &packet));
fail_unless (gst_rtcp_packet_xr_first_rb (&packet));
fail_unless (gst_rtcp_packet_xr_get_block_type (&packet) ==
GST_RTCP_XR_TYPE_SSUMM);
fail_unless (gst_rtcp_packet_xr_get_summary_info (&packet, &ssrc, &begin_seq,
&end_seq));
fail_unless_equals_int_hex (ssrc, GST_READ_UINT32_BE (rtcp_pkt + 12));
fail_unless_equals_int (begin_seq, GST_READ_UINT16_BE (rtcp_pkt + 16));
fail_unless_equals_int (end_seq, GST_READ_UINT16_BE (rtcp_pkt + 18));
fail_unless (gst_rtcp_packet_xr_get_summary_pkt (&packet, &lost_packets,
&dup_packets));
fail_unless_equals_int (lost_packets, GST_READ_UINT32_BE (rtcp_pkt + 20));
fail_unless_equals_int (dup_packets, GST_READ_UINT32_BE (rtcp_pkt + 24));
fail_unless (gst_rtcp_packet_xr_get_summary_jitter (&packet, &min_jitter,
&max_jitter, &mean_jitter, &dev_jitter));
fail_unless_equals_int (min_jitter, GST_READ_UINT32_BE (rtcp_pkt + 28));
fail_unless_equals_int (max_jitter, GST_READ_UINT32_BE (rtcp_pkt + 32));
fail_unless_equals_int (mean_jitter, GST_READ_UINT32_BE (rtcp_pkt + 36));
fail_unless_equals_int (dev_jitter, GST_READ_UINT32_BE (rtcp_pkt + 40));
fail_unless (gst_rtcp_packet_xr_get_summary_ttl (&packet, &ipv4, &min_ttl,
&max_ttl, &mean_ttl, &dev_ttl));
fail_unless (ipv4);
fail_unless_equals_int (min_ttl, rtcp_pkt[44]);
fail_unless_equals_int (max_ttl, rtcp_pkt[45]);
fail_unless_equals_int (mean_ttl, rtcp_pkt[46]);
fail_unless_equals_int (dev_ttl, rtcp_pkt[47]);
gst_rtcp_buffer_unmap (&rtcp);
gst_buffer_unref (buffer);
}
GST_END_TEST;
GST_START_TEST (test_rtcp_buffer_xr_voipmtrx)
{
GstBuffer *buffer;
GstRTCPPacket packet;
guint32 ssrc;
guint8 loss_rate, discard_rate, burst_density, gap_density;
guint8 signal_level, noise_level, rerl, gmin;
guint8 r_factor, ext_r_factor, mos_lq, mos_cq, rx_config;
guint16 burst_duration, gap_duration;
guint16 roundtrip_delay, end_system_delay;
guint16 jb_nominal, jb_maximum, jb_abs_max;
GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
guint8 rtcp_pkt[] = {
0x80, 0xCF, 0x00, 0x0a, /* Type XR, length = 10 */
0x97, 0x6d, 0x21, 0x6a,
0x07, 0x00, 0x00, 0x08, /* VoIP Metrics, length = 8 */
0x97, 0x6d, 0x21, 0x6a, /* SSRC of source */
0x01, 0x02, 0x03, 0x04,
0x05, 0x06, 0x07, 0x08,
0x09, 0x0a, 0x0b, 0x0c,
0x0d, 0x0e, 0x0f, 0x10,
0x11, 0x12, 0x13, 0x14,
0x15, 0x00, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b
};
buffer = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
rtcp_pkt, sizeof (rtcp_pkt), 0, sizeof (rtcp_pkt), NULL, NULL);
gst_rtcp_buffer_map (buffer, GST_MAP_READ, &rtcp);
fail_unless (gst_rtcp_buffer_get_first_packet (&rtcp, &packet));
fail_unless (gst_rtcp_packet_xr_first_rb (&packet));
fail_unless (gst_rtcp_packet_xr_get_block_type (&packet) ==
GST_RTCP_XR_TYPE_VOIP_METRICS);
fail_unless (gst_rtcp_packet_xr_get_voip_metrics_ssrc (&packet, &ssrc));
fail_unless_equals_int_hex (ssrc, GST_READ_UINT32_BE (rtcp_pkt + 12));
fail_unless (gst_rtcp_packet_xr_get_voip_packet_metrics (&packet, &loss_rate,
&discard_rate));
fail_unless_equals_int (loss_rate, rtcp_pkt[16]);
fail_unless_equals_int (discard_rate, rtcp_pkt[17]);
fail_unless (gst_rtcp_packet_xr_get_voip_burst_metrics (&packet,
&burst_density, &gap_density, &burst_duration, &gap_duration));
fail_unless_equals_int (burst_density, rtcp_pkt[18]);
fail_unless_equals_int (gap_density, rtcp_pkt[19]);
fail_unless_equals_int (burst_duration, GST_READ_UINT16_BE (rtcp_pkt + 20));
fail_unless_equals_int (gap_duration, GST_READ_UINT16_BE (rtcp_pkt + 22));
fail_unless (gst_rtcp_packet_xr_get_voip_delay_metrics (&packet,
&roundtrip_delay, &end_system_delay));
fail_unless_equals_int (roundtrip_delay, GST_READ_UINT16_BE (rtcp_pkt + 24));
fail_unless_equals_int (end_system_delay, GST_READ_UINT16_BE (rtcp_pkt + 26));
fail_unless (gst_rtcp_packet_xr_get_voip_signal_metrics (&packet,
&signal_level, &noise_level, &rerl, &gmin));
fail_unless_equals_int (signal_level, rtcp_pkt[28]);
fail_unless_equals_int (noise_level, rtcp_pkt[29]);
fail_unless_equals_int (rerl, rtcp_pkt[30]);
fail_unless_equals_int (gmin, rtcp_pkt[31]);
fail_unless (gst_rtcp_packet_xr_get_voip_quality_metrics (&packet, &r_factor,
&ext_r_factor, &mos_lq, &mos_cq));
fail_unless_equals_int (r_factor, rtcp_pkt[32]);
fail_unless_equals_int (ext_r_factor, rtcp_pkt[33]);
fail_unless_equals_int (mos_lq, rtcp_pkt[34]);
fail_unless_equals_int (mos_cq, rtcp_pkt[35]);
fail_unless (gst_rtcp_packet_xr_get_voip_configuration_params (&packet, &gmin,
&rx_config));
fail_unless_equals_int (gmin, rtcp_pkt[31]);
fail_unless_equals_int (rx_config, rtcp_pkt[36]);
fail_unless (gst_rtcp_packet_xr_get_voip_jitter_buffer_params (&packet,
&jb_nominal, &jb_maximum, &jb_abs_max));
fail_unless_equals_int (jb_nominal, GST_READ_UINT16_BE (rtcp_pkt + 38));
fail_unless_equals_int (jb_maximum, GST_READ_UINT16_BE (rtcp_pkt + 40));
fail_unless_equals_int (jb_abs_max, GST_READ_UINT16_BE (rtcp_pkt + 42));
gst_rtcp_buffer_unmap (&rtcp);
gst_buffer_unref (buffer);
}
GST_END_TEST;
GST_START_TEST (test_rtp_ntp64_extension)
{
GstBuffer *buf;
@ -1463,6 +1924,13 @@ rtp_suite (void)
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_app);
tcase_add_test (tc_chain, test_rtcp_buffer_xr);
tcase_add_test (tc_chain, test_rtcp_buffer_xr_rle);
tcase_add_test (tc_chain, test_rtcp_buffer_xr_prt);
tcase_add_test (tc_chain, test_rtcp_buffer_xr_rrt);
tcase_add_test (tc_chain, test_rtcp_buffer_xr_dlrr);
tcase_add_test (tc_chain, test_rtcp_buffer_xr_ssumm);
tcase_add_test (tc_chain, test_rtcp_buffer_xr_voipmtrx);
tcase_add_test (tc_chain, test_rtp_ntp64_extension);
tcase_add_test (tc_chain, test_rtp_ntp56_extension);