2 * Copyright (C) <2007> Wim Taymans <wim@fluendo.com>
4 * gstrtcpbuffer.h: various helper functions to manipulate buffers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
24 * SECTION:gstrtcpbuffer
25 * @title: GstRTCPBuffer
26 * @short_description: Helper methods for dealing with RTCP buffers
27 * @see_also: #GstRTPBasePayload, #GstRTPBaseDepayload, #gstrtpbuffer
29 * Note: The API in this module is not yet declared stable.
31 * The GstRTPCBuffer helper functions makes it easy to parse and create regular
32 * #GstBuffer objects that contain compound RTCP packets. These buffers are typically
33 * of 'application/x-rtcp' #GstCaps.
35 * An RTCP buffer consists of 1 or more #GstRTCPPacket structures that you can
36 * retrieve with gst_rtcp_buffer_get_first_packet(). #GstRTCPPacket acts as a pointer
37 * into the RTCP buffer; you can move to the next packet with
38 * gst_rtcp_packet_move_to_next().
47 #include "gstrtcpbuffer.h"
50 * gst_rtcp_buffer_new_take_data:
51 * @data: (array length=len) (element-type guint8): data for the new buffer
52 * @len: the length of data
54 * Create a new buffer and set the data and size of the buffer to @data and @len
55 * respectively. @data will be freed when the buffer is unreffed, so this
56 * function transfers ownership of @data to the new buffer.
58 * Returns: A newly allocated buffer with @data and of size @len.
61 gst_rtcp_buffer_new_take_data (gpointer data, guint len)
65 g_return_val_if_fail (data != NULL, NULL);
66 g_return_val_if_fail (len > 0, NULL);
68 result = gst_buffer_new_wrapped (data, len);
74 * gst_rtcp_buffer_new_copy_data:
75 * @data: (array length=len) (element-type guint8): data for the new buffer
76 * @len: the length of data
78 * Create a new buffer and set the data to a copy of @len
79 * bytes of @data and the size to @len. The data will be freed when the buffer
82 * Returns: A newly allocated buffer with a copy of @data and of size @len.
85 gst_rtcp_buffer_new_copy_data (gconstpointer data, guint len)
87 return gst_rtcp_buffer_new_take_data (g_memdup2 (data, len), len);
91 gst_rtcp_buffer_validate_data_internal (guint8 * data, guint len,
101 g_return_val_if_fail (data != NULL, FALSE);
103 /* we need 4 bytes for the type and length */
104 if (G_UNLIKELY (len < 4))
107 /* first packet must be RR or SR and version must be 2 */
108 header_mask = ((data[0] << 8) | data[1]) & valid_mask;
109 if (G_UNLIKELY (header_mask != GST_RTCP_VALID_VALUE))
112 padding = data[0] & 0x20;
118 /* get packet length */
119 header_len = (((data[2] << 8) | data[3]) + 1) << 2;
120 if (data_len < header_len)
123 /* move to next compound packet */
125 data_len -= header_len;
127 /* we are at the end now */
131 /* Version already checked for first packet through mask */
135 /* check version of new packet */
136 version = data[0] & 0xc0;
137 if (version != (GST_RTCP_VERSION << 6))
140 /* check padding of new packet */
141 if (data[0] & 0x20) {
143 /* last byte of padding contains the number of padded bytes including
144 * itself. must be a multiple of 4, but cannot be 0. */
145 pad_bytes = data[data_len - 1];
146 if (pad_bytes == 0 || (pad_bytes & 0x3))
151 /* some leftover bytes */
159 GST_DEBUG ("len check failed");
164 GST_DEBUG ("mask check failed (%04x != %04x)", header_mask, valid_mask);
169 GST_DEBUG ("wrong version (%d < 2)", version >> 6);
174 GST_DEBUG ("padding check failed");
180 * gst_rtcp_buffer_validate_data_reduced:
181 * @data: (array length=len): the data to validate
182 * @len: the length of @data to validate
184 * Check if the @data and @size point to the data of a valid RTCP packet.
185 * Use this function to validate a packet before using the other functions in
188 * This function is updated to support reduced size rtcp packets according to
189 * RFC 5506 and will validate full compound RTCP packets as well as reduced
192 * Returns: TRUE if the data points to a valid RTCP packet.
197 gst_rtcp_buffer_validate_data_reduced (guint8 * data, guint len)
199 return gst_rtcp_buffer_validate_data_internal (data, len,
200 GST_RTCP_REDUCED_SIZE_VALID_MASK);
204 * gst_rtcp_buffer_validate_data:
205 * @data: (array length=len): the data to validate
206 * @len: the length of @data to validate
208 * Check if the @data and @size point to the data of a valid compound,
209 * non-reduced size RTCP packet.
210 * Use this function to validate a packet before using the other functions in
213 * Returns: TRUE if the data points to a valid RTCP packet.
216 gst_rtcp_buffer_validate_data (guint8 * data, guint len)
218 return gst_rtcp_buffer_validate_data_internal (data, len,
219 GST_RTCP_VALID_MASK);
223 * gst_rtcp_buffer_validate_reduced:
224 * @buffer: the buffer to validate
226 * Check if the data pointed to by @buffer is a valid RTCP packet using
227 * gst_rtcp_buffer_validate_reduced().
229 * Returns: TRUE if @buffer is a valid RTCP packet.
234 gst_rtcp_buffer_validate_reduced (GstBuffer * buffer)
239 g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
241 gst_buffer_map (buffer, &map, GST_MAP_READ);
242 res = gst_rtcp_buffer_validate_data_reduced (map.data, map.size);
243 gst_buffer_unmap (buffer, &map);
249 * gst_rtcp_buffer_validate:
250 * @buffer: the buffer to validate
252 * Check if the data pointed to by @buffer is a valid RTCP packet using
253 * gst_rtcp_buffer_validate_data().
255 * Returns: TRUE if @buffer is a valid RTCP packet.
258 gst_rtcp_buffer_validate (GstBuffer * buffer)
263 g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
265 gst_buffer_map (buffer, &map, GST_MAP_READ);
266 res = gst_rtcp_buffer_validate_data (map.data, map.size);
267 gst_buffer_unmap (buffer, &map);
273 * gst_rtcp_buffer_new:
274 * @mtu: the maximum mtu size.
276 * Create a new buffer for constructing RTCP packets. The packet will have a
277 * maximum size of @mtu.
279 * Returns: A newly allocated buffer.
282 gst_rtcp_buffer_new (guint mtu)
287 g_return_val_if_fail (mtu > 0, NULL);
289 data = g_malloc0 (mtu);
291 result = gst_buffer_new_wrapped_full (0, data, mtu, 0, 0, data, g_free);
297 * gst_rtcp_buffer_map:
298 * @buffer: a buffer with an RTCP packet
299 * @flags: flags for the mapping
300 * @rtcp: resulting #GstRTCPBuffer
302 * Open @buffer for reading or writing, depending on @flags. The resulting RTCP
303 * buffer state is stored in @rtcp.
306 gst_rtcp_buffer_map (GstBuffer * buffer, GstMapFlags flags,
307 GstRTCPBuffer * rtcp)
309 g_return_val_if_fail (rtcp != NULL, FALSE);
310 g_return_val_if_fail (rtcp->buffer == NULL, FALSE);
311 g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
312 g_return_val_if_fail (flags & GST_MAP_READ, FALSE);
314 rtcp->buffer = buffer;
315 gst_buffer_map (buffer, &rtcp->map, flags);
321 * gst_rtcp_buffer_unmap:
322 * @rtcp: a buffer with an RTCP packet
324 * Finish @rtcp after being constructed. This function is usually called
325 * after gst_rtcp_buffer_map() and after adding the RTCP items to the new buffer.
327 * The function adjusts the size of @rtcp with the total length of all the
331 gst_rtcp_buffer_unmap (GstRTCPBuffer * rtcp)
333 g_return_val_if_fail (rtcp != NULL, FALSE);
334 g_return_val_if_fail (GST_IS_BUFFER (rtcp->buffer), FALSE);
336 if (rtcp->map.flags & GST_MAP_WRITE) {
338 gst_buffer_resize (rtcp->buffer, 0, rtcp->map.size);
341 gst_buffer_unmap (rtcp->buffer, &rtcp->map);
348 * gst_rtcp_buffer_get_packet_count:
349 * @rtcp: a valid RTCP buffer
351 * Get the number of RTCP packets in @rtcp.
353 * Returns: the number of RTCP packets in @rtcp.
356 gst_rtcp_buffer_get_packet_count (GstRTCPBuffer * rtcp)
358 GstRTCPPacket packet;
361 g_return_val_if_fail (rtcp != NULL, 0);
362 g_return_val_if_fail (GST_IS_BUFFER (rtcp->buffer), 0);
363 g_return_val_if_fail (rtcp != NULL, 0);
364 g_return_val_if_fail (rtcp->map.flags & GST_MAP_READ, 0);
367 if (gst_rtcp_buffer_get_first_packet (rtcp, &packet)) {
370 } while (gst_rtcp_packet_move_to_next (&packet));
377 rtcp_packet_min_length (GstRTCPType type)
380 case GST_RTCP_TYPE_SR:
382 case GST_RTCP_TYPE_RR:
384 case GST_RTCP_TYPE_SDES:
386 case GST_RTCP_TYPE_BYE:
388 case GST_RTCP_TYPE_APP:
390 case GST_RTCP_TYPE_RTPFB:
392 case GST_RTCP_TYPE_PSFB:
394 case GST_RTCP_TYPE_XR:
402 * read_packet_header:
405 * Read the packet headers for the packet pointed to by @packet.
407 * Returns: TRUE if @packet pointed to a valid header.
410 read_packet_header (GstRTCPPacket * packet)
418 g_return_val_if_fail (packet != NULL, FALSE);
420 data = packet->rtcp->map.data;
421 maxsize = packet->rtcp->map.size;
423 offset = packet->offset;
425 /* check if we are at the end of the buffer, we add 4 because we also want to
426 * ensure we can read the header. */
427 if (offset + 4 > maxsize)
430 if ((data[offset] & 0xc0) != (GST_RTCP_VERSION << 6))
433 /* read count, type and length */
434 packet->padding = (data[offset] & 0x20) == 0x20;
435 packet->count = data[offset] & 0x1f;
436 packet->type = data[offset + 1];
437 packet->length = (data[offset + 2] << 8) | data[offset + 3];
438 packet->item_offset = 4;
439 packet->item_count = 0;
440 packet->entry_offset = 4;
442 /* Ensure no overread from the claimed data size. The packet length
443 is expressed in multiple of 32 bits, to make things obvious. */
444 if (offset + 4 + packet->length * 4 > maxsize)
447 minsize = rtcp_packet_min_length (packet->type);
450 minlength = (minsize - 4) >> 2;
452 /* Validate the size */
453 if (packet->length < minlength)
460 * gst_rtcp_buffer_get_first_packet:
461 * @rtcp: a valid RTCP buffer
462 * @packet: a #GstRTCPPacket
464 * Initialize a new #GstRTCPPacket pointer that points to the first packet in
467 * Returns: TRUE if the packet existed in @rtcp.
470 gst_rtcp_buffer_get_first_packet (GstRTCPBuffer * rtcp, GstRTCPPacket * packet)
472 g_return_val_if_fail (rtcp != NULL, FALSE);
473 g_return_val_if_fail (GST_IS_BUFFER (rtcp->buffer), FALSE);
474 g_return_val_if_fail (packet != NULL, FALSE);
475 g_return_val_if_fail (rtcp != NULL, 0);
476 g_return_val_if_fail (rtcp->map.flags & GST_MAP_READ, 0);
481 packet->type = GST_RTCP_TYPE_INVALID;
483 if (!read_packet_header (packet))
490 * gst_rtcp_packet_move_to_next:
491 * @packet: a #GstRTCPPacket
493 * Move the packet pointer @packet to the next packet in the payload.
494 * Use gst_rtcp_buffer_get_first_packet() to initialize @packet.
496 * Returns: TRUE if @packet is pointing to a valid packet after calling this
500 gst_rtcp_packet_move_to_next (GstRTCPPacket * packet)
502 g_return_val_if_fail (packet != NULL, FALSE);
503 g_return_val_if_fail (packet->type != GST_RTCP_TYPE_INVALID, FALSE);
504 g_return_val_if_fail (packet->rtcp != NULL, FALSE);
505 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, FALSE);
507 /* if we have a padding or invalid packet, it must be the last,
509 if (packet->type == GST_RTCP_TYPE_INVALID || packet->padding)
512 /* move to next packet. Add 4 because the header is not included in length */
513 packet->offset += (packet->length << 2) + 4;
515 /* try to read new header */
516 if (!read_packet_header (packet))
524 packet->type = GST_RTCP_TYPE_INVALID;
530 * gst_rtcp_buffer_add_packet:
531 * @rtcp: a valid RTCP buffer
532 * @type: the #GstRTCPType of the new packet
533 * @packet: pointer to new packet
535 * Add a new packet of @type to @rtcp. @packet will point to the newly created
538 * Returns: %TRUE if the packet could be created. This function returns %FALSE
539 * if the max mtu is exceeded for the buffer.
542 gst_rtcp_buffer_add_packet (GstRTCPBuffer * rtcp, GstRTCPType type,
543 GstRTCPPacket * packet)
550 g_return_val_if_fail (rtcp != NULL, FALSE);
551 g_return_val_if_fail (GST_IS_BUFFER (rtcp->buffer), FALSE);
552 g_return_val_if_fail (type != GST_RTCP_TYPE_INVALID, FALSE);
553 g_return_val_if_fail (packet != NULL, FALSE);
554 g_return_val_if_fail (rtcp->map.flags & GST_MAP_WRITE, FALSE);
556 /* find free space */
557 if (gst_rtcp_buffer_get_first_packet (rtcp, packet)) {
558 while (gst_rtcp_packet_move_to_next (packet));
560 if (packet->padding) {
561 /* Last packet is a padding packet. Let's not replace it silently */
562 /* and let the application know that it could not be added because */
563 /* it would involve replacing a packet */
568 maxsize = rtcp->map.maxsize;
570 /* packet->offset is now pointing to the next free offset in the buffer to
571 * start a compound packet. Next we figure out if we have enough free space in
572 * the buffer to continue. */
573 len = rtcp_packet_min_length (type);
576 if (packet->offset + len >= maxsize)
579 rtcp->map.size += len;
581 data = rtcp->map.data + packet->offset;
583 data[0] = (GST_RTCP_VERSION << 6);
585 /* length is stored in multiples of 32 bit words minus the length of the
587 len = (len - 4) >> 2;
589 data[3] = len & 0xff;
591 /* now try to position to the packet */
592 result = read_packet_header (packet);
599 g_warning ("unknown type %d", type);
609 * gst_rtcp_packet_remove:
610 * @packet: a #GstRTCPPacket
612 * Removes the packet pointed to by @packet and moves pointer to the next one
614 * Returns: TRUE if @packet is pointing to a valid packet after calling this
618 gst_rtcp_packet_remove (GstRTCPPacket * packet)
620 gboolean ret = FALSE;
623 g_return_val_if_fail (packet != NULL, FALSE);
624 g_return_val_if_fail (packet->type != GST_RTCP_TYPE_INVALID, FALSE);
625 g_return_val_if_fail (packet->rtcp != NULL, FALSE);
626 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE, FALSE);
628 /* The next packet starts at offset + length + 4 (the header) */
629 offset = packet->offset + (packet->length << 2) + 4;
631 /* Overwrite this packet with the rest of the data */
632 memmove (packet->rtcp->map.data + packet->offset,
633 packet->rtcp->map.data + offset, packet->rtcp->map.size - offset);
635 packet->rtcp->map.size -= offset - packet->offset;
637 /* try to read next header */
638 ret = read_packet_header (packet);
640 packet->type = GST_RTCP_TYPE_INVALID;
646 * gst_rtcp_packet_get_padding:
647 * @packet: a valid #GstRTCPPacket
649 * Get the packet padding of the packet pointed to by @packet.
651 * Returns: If the packet has the padding bit set.
654 gst_rtcp_packet_get_padding (GstRTCPPacket * packet)
656 g_return_val_if_fail (packet != NULL, FALSE);
657 g_return_val_if_fail (packet->type != GST_RTCP_TYPE_INVALID, FALSE);
659 return packet->padding;
663 * gst_rtcp_packet_get_type:
664 * @packet: a valid #GstRTCPPacket
666 * Get the packet type of the packet pointed to by @packet.
668 * Returns: The packet type or GST_RTCP_TYPE_INVALID when @packet is not
669 * pointing to a valid packet.
672 gst_rtcp_packet_get_type (GstRTCPPacket * packet)
674 g_return_val_if_fail (packet != NULL, GST_RTCP_TYPE_INVALID);
680 * gst_rtcp_packet_get_count:
681 * @packet: a valid #GstRTCPPacket
683 * Get the count field in @packet.
685 * Returns: The count field in @packet or -1 if @packet does not point to a
689 gst_rtcp_packet_get_count (GstRTCPPacket * packet)
691 g_return_val_if_fail (packet != NULL, -1);
692 g_return_val_if_fail (packet->type != GST_RTCP_TYPE_INVALID, -1);
694 return packet->count;
698 * gst_rtcp_packet_get_length:
699 * @packet: a valid #GstRTCPPacket
701 * Get the length field of @packet. This is the length of the packet in
702 * 32-bit words minus one.
704 * Returns: The length field of @packet.
707 gst_rtcp_packet_get_length (GstRTCPPacket * packet)
709 g_return_val_if_fail (packet != NULL, 0);
710 g_return_val_if_fail (packet->type != GST_RTCP_TYPE_INVALID, 0);
712 return packet->length;
716 * gst_rtcp_packet_sr_get_sender_info:
717 * @packet: a valid SR #GstRTCPPacket
718 * @ssrc: (out): result SSRC
719 * @ntptime: (out): result NTP time
720 * @rtptime: (out): result RTP time
721 * @packet_count: (out): result packet count
722 * @octet_count: (out): result octet count
724 * Parse the SR sender info and store the values.
727 gst_rtcp_packet_sr_get_sender_info (GstRTCPPacket * packet, guint32 * ssrc,
728 guint64 * ntptime, guint32 * rtptime, guint32 * packet_count,
729 guint32 * octet_count)
733 g_return_if_fail (packet != NULL);
734 g_return_if_fail (packet->type == GST_RTCP_TYPE_SR);
735 g_return_if_fail (packet->rtcp != NULL);
736 g_return_if_fail (packet->rtcp->map.flags & GST_MAP_READ);
738 data = packet->rtcp->map.data;
741 data += packet->offset + 4;
743 *ssrc = GST_READ_UINT32_BE (data);
746 *ntptime = GST_READ_UINT64_BE (data);
749 *rtptime = GST_READ_UINT32_BE (data);
752 *packet_count = GST_READ_UINT32_BE (data);
755 *octet_count = GST_READ_UINT32_BE (data);
759 * gst_rtcp_packet_sr_set_sender_info:
760 * @packet: a valid SR #GstRTCPPacket
762 * @ntptime: the NTP time
763 * @rtptime: the RTP time
764 * @packet_count: the packet count
765 * @octet_count: the octet count
767 * Set the given values in the SR packet @packet.
770 gst_rtcp_packet_sr_set_sender_info (GstRTCPPacket * packet, guint32 ssrc,
771 guint64 ntptime, guint32 rtptime, guint32 packet_count, guint32 octet_count)
775 g_return_if_fail (packet != NULL);
776 g_return_if_fail (packet->type == GST_RTCP_TYPE_SR);
777 g_return_if_fail (packet->rtcp != NULL);
778 g_return_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE);
780 data = packet->rtcp->map.data;
783 data += packet->offset + 4;
784 GST_WRITE_UINT32_BE (data, ssrc);
786 GST_WRITE_UINT64_BE (data, ntptime);
788 GST_WRITE_UINT32_BE (data, rtptime);
790 GST_WRITE_UINT32_BE (data, packet_count);
792 GST_WRITE_UINT32_BE (data, octet_count);
796 * gst_rtcp_packet_rr_get_ssrc:
797 * @packet: a valid RR #GstRTCPPacket
799 * Get the ssrc field of the RR @packet.
804 gst_rtcp_packet_rr_get_ssrc (GstRTCPPacket * packet)
809 g_return_val_if_fail (packet != NULL, 0);
810 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_RR, 0);
811 g_return_val_if_fail (packet->rtcp != NULL, 0);
812 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, 0);
814 data = packet->rtcp->map.data;
817 data += packet->offset + 4;
818 ssrc = GST_READ_UINT32_BE (data);
824 * gst_rtcp_packet_rr_set_ssrc:
825 * @packet: a valid RR #GstRTCPPacket
826 * @ssrc: the SSRC to set
828 * Set the ssrc field of the RR @packet.
831 gst_rtcp_packet_rr_set_ssrc (GstRTCPPacket * packet, guint32 ssrc)
835 g_return_if_fail (packet != NULL);
836 g_return_if_fail (packet->type == GST_RTCP_TYPE_RR);
837 g_return_if_fail (packet->rtcp != NULL);
838 g_return_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE);
840 data = packet->rtcp->map.data;
843 data += packet->offset + 4;
844 GST_WRITE_UINT32_BE (data, ssrc);
848 * gst_rtcp_packet_get_rb_count:
849 * @packet: a valid SR or RR #GstRTCPPacket
851 * Get the number of report blocks in @packet.
853 * Returns: The number of report blocks in @packet.
856 gst_rtcp_packet_get_rb_count (GstRTCPPacket * packet)
858 g_return_val_if_fail (packet != NULL, 0);
859 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_RR ||
860 packet->type == GST_RTCP_TYPE_SR, 0);
861 g_return_val_if_fail (packet->rtcp != NULL, 0);
862 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, 0);
864 return packet->count;
868 * gst_rtcp_packet_get_rb:
869 * @packet: a valid SR or RR #GstRTCPPacket
870 * @nth: the nth report block in @packet
871 * @ssrc: (out): result for data source being reported
872 * @fractionlost: (out): result for fraction lost since last SR/RR
873 * @packetslost: (out): result for the cumululative number of packets lost
874 * @exthighestseq: (out): result for the extended last sequence number received
875 * @jitter: (out): result for the interarrival jitter
876 * @lsr: (out): result for the last SR packet from this source
877 * @dlsr: (out): result for the delay since last SR packet
879 * Parse the values of the @nth report block in @packet and store the result in
883 gst_rtcp_packet_get_rb (GstRTCPPacket * packet, guint nth, guint32 * ssrc,
884 guint8 * fractionlost, gint32 * packetslost, guint32 * exthighestseq,
885 guint32 * jitter, guint32 * lsr, guint32 * dlsr)
891 g_return_if_fail (packet != NULL);
892 g_return_if_fail (packet->type == GST_RTCP_TYPE_RR ||
893 packet->type == GST_RTCP_TYPE_SR);
894 g_return_if_fail (packet->rtcp != NULL);
895 g_return_if_fail (packet->rtcp->map.flags & GST_MAP_READ);
896 g_return_if_fail (nth < packet->count);
898 /* get offset in 32-bits words into packet, skip the header */
899 if (packet->type == GST_RTCP_TYPE_RR)
904 /* move to requested index */
907 /* check that we don't go past the packet length */
908 if (offset > packet->length)
913 offset += packet->offset;
915 /* check if the packet is valid */
916 if (offset + 24 > packet->rtcp->map.size)
919 data = packet->rtcp->map.data;
923 *ssrc = GST_READ_UINT32_BE (data);
925 tmp = GST_READ_UINT32_BE (data);
927 *fractionlost = (tmp >> 24);
930 if (tmp & 0x00800000)
934 *packetslost = (gint32) tmp;
938 *exthighestseq = GST_READ_UINT32_BE (data);
941 *jitter = GST_READ_UINT32_BE (data);
944 *lsr = GST_READ_UINT32_BE (data);
947 *dlsr = GST_READ_UINT32_BE (data);
951 * gst_rtcp_packet_add_rb:
952 * @packet: a valid SR or RR #GstRTCPPacket
953 * @ssrc: data source being reported
954 * @fractionlost: fraction lost since last SR/RR
955 * @packetslost: the cumululative number of packets lost
956 * @exthighestseq: the extended last sequence number received
957 * @jitter: the interarrival jitter
958 * @lsr: the last SR packet from this source
959 * @dlsr: the delay since last SR packet
961 * Add a new report block to @packet with the given values.
963 * Returns: %TRUE if the packet was created. This function can return %FALSE if
964 * the max MTU is exceeded or the number of report blocks is greater than
965 * #GST_RTCP_MAX_RB_COUNT.
968 gst_rtcp_packet_add_rb (GstRTCPPacket * packet, guint32 ssrc,
969 guint8 fractionlost, gint32 packetslost, guint32 exthighestseq,
970 guint32 jitter, guint32 lsr, guint32 dlsr)
973 guint maxsize, offset;
975 g_return_val_if_fail (packet != NULL, FALSE);
976 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_RR ||
977 packet->type == GST_RTCP_TYPE_SR, FALSE);
978 g_return_val_if_fail (packet->rtcp != NULL, FALSE);
979 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE, FALSE);
980 /* if profile-specific extension is added, fail for now!? */
981 g_return_val_if_fail (gst_rtcp_packet_get_profile_specific_ext_length (packet)
984 if (packet->count >= GST_RTCP_MAX_RB_COUNT)
987 data = packet->rtcp->map.data;
988 maxsize = packet->rtcp->map.maxsize;
991 offset = packet->offset + 4;
992 if (packet->type == GST_RTCP_TYPE_RR)
997 /* move to current index */
998 offset += (packet->count * 24);
1000 /* we need 24 free bytes now */
1001 if (offset + 24 >= maxsize)
1004 /* increment packet count and length */
1006 data[packet->offset]++;
1007 packet->length += 6;
1008 data[packet->offset + 2] = (packet->length) >> 8;
1009 data[packet->offset + 3] = (packet->length) & 0xff;
1010 packet->rtcp->map.size += 6 * 4;
1012 /* move to new report block offset */
1015 GST_WRITE_UINT32_BE (data, ssrc);
1017 GST_WRITE_UINT32_BE (data,
1018 ((guint32) fractionlost << 24) | (packetslost & 0xffffff));
1020 GST_WRITE_UINT32_BE (data, exthighestseq);
1022 GST_WRITE_UINT32_BE (data, jitter);
1024 GST_WRITE_UINT32_BE (data, lsr);
1026 GST_WRITE_UINT32_BE (data, dlsr);
1037 * gst_rtcp_packet_set_rb:
1038 * @packet: a valid SR or RR #GstRTCPPacket
1039 * @nth: the nth report block to set
1040 * @ssrc: data source being reported
1041 * @fractionlost: fraction lost since last SR/RR
1042 * @packetslost: the cumululative number of packets lost
1043 * @exthighestseq: the extended last sequence number received
1044 * @jitter: the interarrival jitter
1045 * @lsr: the last SR packet from this source
1046 * @dlsr: the delay since last SR packet
1048 * Set the @nth new report block in @packet with the given values.
1050 * Note: Not implemented.
1053 gst_rtcp_packet_set_rb (GstRTCPPacket * packet, guint nth, guint32 ssrc,
1054 guint8 fractionlost, gint32 packetslost, guint32 exthighestseq,
1055 guint32 jitter, guint32 lsr, guint32 dlsr)
1057 g_return_if_fail (packet != NULL);
1058 g_return_if_fail (packet->type == GST_RTCP_TYPE_RR ||
1059 packet->type == GST_RTCP_TYPE_SR);
1060 g_return_if_fail (packet->rtcp != NULL);
1061 g_return_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE);
1063 g_warning ("not implemented");
1068 * gst_rtcp_packet_add_profile_specific_ext:
1069 * @packet: a valid SR or RR #GstRTCPPacket
1070 * @data: (array length=len) (transfer none): profile-specific data
1071 * @len: length of the profile-specific data in bytes
1073 * Add profile-specific extension @data to @packet. If @packet already
1074 * contains profile-specific extension @data will be appended to the existing
1077 * Returns: %TRUE if the profile specific extension data was added.
1082 gst_rtcp_packet_add_profile_specific_ext (GstRTCPPacket * packet,
1083 const guint8 * data, guint len)
1086 guint maxsize, offset;
1088 g_return_val_if_fail (packet != NULL, FALSE);
1089 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_RR ||
1090 packet->type == GST_RTCP_TYPE_SR, FALSE);
1091 g_return_val_if_fail (packet->rtcp != NULL, FALSE);
1092 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE, FALSE);
1093 g_return_val_if_fail ((len & 0x03) == 0, FALSE);
1095 bdata = packet->rtcp->map.data;
1096 maxsize = packet->rtcp->map.maxsize;
1098 /* skip to the end of the packet */
1099 offset = packet->offset + (packet->length << 2) + 4;
1101 /* we need 'len' free bytes now */
1102 if (G_UNLIKELY (offset + len > maxsize))
1105 memcpy (&bdata[offset], data, len);
1106 packet->length += len >> 2;
1107 bdata[packet->offset + 2] = (packet->length) >> 8;
1108 bdata[packet->offset + 3] = (packet->length) & 0xff;
1109 packet->rtcp->map.size += len;
1115 * gst_rtcp_packet_get_profile_specific_ext_length:
1116 * @packet: a valid SR or RR #GstRTCPPacket
1118 * Returns: The number of 32-bit words containing profile-specific extension
1119 * data from @packet.
1124 gst_rtcp_packet_get_profile_specific_ext_length (GstRTCPPacket * packet)
1126 guint pse_offset = 2;
1128 g_return_val_if_fail (packet != NULL, 0);
1129 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_RR ||
1130 packet->type == GST_RTCP_TYPE_SR, 0);
1131 g_return_val_if_fail (packet->rtcp != NULL, 0);
1132 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, 0);
1134 if (packet->type == GST_RTCP_TYPE_SR)
1136 pse_offset += (packet->count * 6);
1138 if (pse_offset <= (packet->length + 1))
1139 return packet->length + 1 - pse_offset;
1141 /* This means that the packet is invalid! */
1146 * gst_rtcp_packet_get_profile_specific_ext:
1147 * @packet: a valid SR or RR #GstRTCPPacket
1148 * @data: (out) (array length=len) (transfer none): result profile-specific data
1149 * @len: (out): result length of the profile-specific data
1151 * Returns: %TRUE if there was valid data.
1156 gst_rtcp_packet_get_profile_specific_ext (GstRTCPPacket * packet,
1157 guint8 ** data, guint * len)
1161 g_return_val_if_fail (packet != NULL, FALSE);
1162 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_RR ||
1163 packet->type == GST_RTCP_TYPE_SR, FALSE);
1164 g_return_val_if_fail (packet->rtcp != NULL, FALSE);
1165 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, FALSE);
1167 pse_len = gst_rtcp_packet_get_profile_specific_ext_length (packet);
1170 *len = pse_len * sizeof (guint32);
1172 *data = packet->rtcp->map.data;
1173 *data += packet->offset;
1174 *data += ((packet->length + 1 - pse_len) * sizeof (guint32));
1184 * gst_rtcp_packet_copy_profile_specific_ext:
1185 * @packet: a valid SR or RR #GstRTCPPacket
1186 * @data: (out) (array length=len): result profile-specific data
1187 * @len: (out): length of the profile-specific extension data
1189 * The profile-specific extension data is copied into a new allocated
1190 * memory area @data. This must be freed with g_free() after usage.
1192 * Returns: %TRUE if there was valid data.
1197 gst_rtcp_packet_copy_profile_specific_ext (GstRTCPPacket * packet,
1198 guint8 ** data, guint * len)
1202 g_return_val_if_fail (packet != NULL, FALSE);
1203 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_RR ||
1204 packet->type == GST_RTCP_TYPE_SR, FALSE);
1205 g_return_val_if_fail (packet->rtcp != NULL, FALSE);
1206 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, FALSE);
1208 pse_len = gst_rtcp_packet_get_profile_specific_ext_length (packet);
1211 *len = pse_len * sizeof (guint32);
1213 guint8 *ptr = packet->rtcp->map.data + packet->offset;
1214 ptr += ((packet->length + 1 - pse_len) * sizeof (guint32));
1215 *data = g_memdup2 (ptr, pse_len * sizeof (guint32));
1226 * gst_rtcp_packet_sdes_get_item_count:
1227 * @packet: a valid SDES #GstRTCPPacket
1229 * Get the number of items in the SDES packet @packet.
1231 * Returns: The number of items in @packet.
1234 gst_rtcp_packet_sdes_get_item_count (GstRTCPPacket * packet)
1236 g_return_val_if_fail (packet != NULL, 0);
1237 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, 0);
1239 return packet->count;
1243 * gst_rtcp_packet_sdes_first_item:
1244 * @packet: a valid SDES #GstRTCPPacket
1246 * Move to the first SDES item in @packet.
1248 * Returns: TRUE if there was a first item.
1251 gst_rtcp_packet_sdes_first_item (GstRTCPPacket * packet)
1253 g_return_val_if_fail (packet != NULL, FALSE);
1254 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, FALSE);
1256 packet->item_offset = 4;
1257 packet->item_count = 0;
1258 packet->entry_offset = 4;
1260 if (packet->count == 0)
1267 * gst_rtcp_packet_sdes_next_item:
1268 * @packet: a valid SDES #GstRTCPPacket
1270 * Move to the next SDES item in @packet.
1272 * Returns: TRUE if there was a next item.
1275 gst_rtcp_packet_sdes_next_item (GstRTCPPacket * packet)
1281 g_return_val_if_fail (packet != NULL, FALSE);
1282 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, FALSE);
1283 g_return_val_if_fail (packet->rtcp != NULL, FALSE);
1284 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, FALSE);
1286 /* if we are at the last item, we are done */
1287 if (packet->item_count == packet->count)
1291 data = packet->rtcp->map.data;
1292 data += packet->offset;
1294 offset = packet->item_offset;
1299 len = (packet->length << 2);
1301 while (offset < len) {
1302 if (data[offset] == 0) {
1303 /* end of list, round to next 32-bit word */
1304 offset = (offset + 4) & ~3;
1307 offset += data[offset + 1] + 2;
1312 packet->item_offset = offset;
1313 packet->item_count++;
1314 packet->entry_offset = 4;
1320 * gst_rtcp_packet_sdes_get_ssrc:
1321 * @packet: a valid SDES #GstRTCPPacket
1323 * Get the SSRC of the current SDES item.
1325 * Returns: the SSRC of the current item.
1328 gst_rtcp_packet_sdes_get_ssrc (GstRTCPPacket * packet)
1333 g_return_val_if_fail (packet != NULL, 0);
1334 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, 0);
1335 g_return_val_if_fail (packet->rtcp != NULL, 0);
1336 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, 0);
1339 data = packet->rtcp->map.data;
1340 data += packet->offset;
1342 data += packet->item_offset;
1344 ssrc = GST_READ_UINT32_BE (data);
1350 * gst_rtcp_packet_sdes_first_entry:
1351 * @packet: a valid SDES #GstRTCPPacket
1353 * Move to the first SDES entry in the current item.
1355 * Returns: %TRUE if there was a first entry.
1358 gst_rtcp_packet_sdes_first_entry (GstRTCPPacket * packet)
1363 g_return_val_if_fail (packet != NULL, FALSE);
1364 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, FALSE);
1365 g_return_val_if_fail (packet->rtcp != NULL, FALSE);
1366 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, FALSE);
1369 data = packet->rtcp->map.data;
1370 data += packet->offset;
1372 offset = packet->item_offset;
1376 packet->entry_offset = 4;
1379 len = (packet->length << 2);
1383 if (data[offset] == 0)
1390 * gst_rtcp_packet_sdes_next_entry:
1391 * @packet: a valid SDES #GstRTCPPacket
1393 * Move to the next SDES entry in the current item.
1395 * Returns: %TRUE if there was a next entry.
1398 gst_rtcp_packet_sdes_next_entry (GstRTCPPacket * packet)
1401 guint len, offset, item_len;
1403 g_return_val_if_fail (packet != NULL, FALSE);
1404 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, FALSE);
1405 g_return_val_if_fail (packet->rtcp != NULL, FALSE);
1406 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, FALSE);
1409 data = packet->rtcp->map.data;
1410 data += packet->offset;
1412 offset = packet->item_offset;
1414 offset += packet->entry_offset;
1416 item_len = data[offset + 1] + 2;
1421 len = (packet->length << 2);
1425 packet->entry_offset += item_len;
1427 /* check for end of list */
1428 if (data[offset] == 0)
1435 * gst_rtcp_packet_sdes_get_entry:
1436 * @packet: a valid SDES #GstRTCPPacket
1437 * @type: result of the entry type
1438 * @len: (out): result length of the entry data
1439 * @data: (out) (array length=len) (transfer none): result entry data
1441 * Get the data of the current SDES item entry. @type (when not NULL) will
1442 * contain the type of the entry. @data (when not NULL) will point to @len
1445 * When @type refers to a text item, @data will point to a UTF8 string. Note
1446 * that this UTF8 string is NOT null-terminated. Use
1447 * gst_rtcp_packet_sdes_copy_entry() to get a null-terminated copy of the entry.
1449 * Returns: %TRUE if there was valid data.
1452 gst_rtcp_packet_sdes_get_entry (GstRTCPPacket * packet,
1453 GstRTCPSDESType * type, guint8 * len, guint8 ** data)
1458 g_return_val_if_fail (packet != NULL, FALSE);
1459 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, FALSE);
1460 g_return_val_if_fail (packet->rtcp != NULL, FALSE);
1461 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, FALSE);
1464 bdata = packet->rtcp->map.data;
1465 bdata += packet->offset;
1467 offset = packet->item_offset;
1469 offset += packet->entry_offset;
1471 if (bdata[offset] == 0)
1475 *type = bdata[offset];
1477 *len = bdata[offset + 1];
1479 *data = &bdata[offset + 2];
1485 * gst_rtcp_packet_sdes_copy_entry:
1486 * @packet: a valid SDES #GstRTCPPacket
1487 * @type: result of the entry type
1488 * @len: (out): result length of the entry data
1489 * @data: (out) (array length=len): result entry data
1491 * This function is like gst_rtcp_packet_sdes_get_entry() but it returns a
1492 * null-terminated copy of the data instead. use g_free() after usage.
1494 * Returns: %TRUE if there was valid data.
1497 gst_rtcp_packet_sdes_copy_entry (GstRTCPPacket * packet,
1498 GstRTCPSDESType * type, guint8 * len, guint8 ** data)
1503 g_return_val_if_fail (packet != NULL, FALSE);
1504 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, FALSE);
1505 g_return_val_if_fail (packet->rtcp != NULL, FALSE);
1506 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, FALSE);
1508 if (!gst_rtcp_packet_sdes_get_entry (packet, type, &tlen, &tdata))
1514 *data = (guint8 *) g_strndup ((gchar *) tdata, tlen);
1520 * gst_rtcp_packet_sdes_add_item:
1521 * @packet: a valid SDES #GstRTCPPacket
1522 * @ssrc: the SSRC of the new item to add
1524 * Add a new SDES item for @ssrc to @packet.
1526 * Returns: %TRUE if the item could be added, %FALSE if the maximum amount of
1527 * items has been exceeded for the SDES packet or the MTU has been reached.
1530 gst_rtcp_packet_sdes_add_item (GstRTCPPacket * packet, guint32 ssrc)
1536 g_return_val_if_fail (packet != NULL, FALSE);
1537 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, FALSE);
1538 g_return_val_if_fail (packet->rtcp != NULL, FALSE);
1539 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE, FALSE);
1541 /* increment item count when possible */
1542 if (packet->count >= GST_RTCP_MAX_SDES_ITEM_COUNT)
1545 /* pretend there is a next packet for the next call */
1548 /* jump over current item */
1549 gst_rtcp_packet_sdes_next_item (packet);
1552 data = packet->rtcp->map.data;
1553 maxsize = packet->rtcp->map.maxsize;
1554 data += packet->offset;
1555 /* move to current item */
1556 offset = packet->item_offset;
1558 /* we need 2 free words now */
1559 if (offset + 8 >= maxsize)
1563 GST_WRITE_UINT32_BE (&data[offset], ssrc);
1564 /* write 0 entry with padding */
1565 GST_WRITE_UINT32_BE (&data[offset + 4], 0);
1568 data[0] = (data[0] & 0xe0) | packet->count;
1569 /* update length, we added 2 words */
1570 packet->length += 2;
1571 data[2] = (packet->length) >> 8;
1572 data[3] = (packet->length) & 0xff;
1574 packet->rtcp->map.size += 8;
1591 * gst_rtcp_packet_sdes_add_entry:
1592 * @packet: a valid SDES #GstRTCPPacket
1593 * @type: the #GstRTCPSDESType of the SDES entry
1594 * @len: the data length
1595 * @data: (array length=len): the data
1597 * Add a new SDES entry to the current item in @packet.
1599 * Returns: %TRUE if the item could be added, %FALSE if the MTU has been
1603 gst_rtcp_packet_sdes_add_entry (GstRTCPPacket * packet, GstRTCPSDESType type,
1604 guint8 len, const guint8 * data)
1607 guint offset, padded;
1610 g_return_val_if_fail (packet != NULL, FALSE);
1611 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, FALSE);
1612 g_return_val_if_fail (packet->rtcp != NULL, FALSE);
1613 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE, FALSE);
1616 bdata = packet->rtcp->map.data;
1617 maxsize = packet->rtcp->map.maxsize;
1618 bdata += packet->offset;
1620 offset = packet->item_offset;
1622 offset += packet->entry_offset;
1624 /* add 1 byte end and up to 3 bytes padding to fill a full 32 bit word */
1625 padded = (offset + 2 + len + 1 + 3) & ~3;
1627 /* we need enough space for type, len, data and padding */
1628 if (packet->offset + padded >= maxsize)
1631 packet->rtcp->map.size = packet->offset + padded;
1633 bdata[offset] = type;
1634 bdata[offset + 1] = len;
1635 memcpy (&bdata[offset + 2], data, len);
1636 bdata[offset + 2 + len] = 0;
1638 /* calculate new packet length */
1639 packet->length = (padded - 4) >> 2;
1640 bdata[2] = (packet->length) >> 8;
1641 bdata[3] = (packet->length) & 0xff;
1643 /* position to new next entry */
1644 packet->entry_offset += 2 + len;
1656 * gst_rtcp_packet_bye_get_ssrc_count:
1657 * @packet: a valid BYE #GstRTCPPacket
1659 * Get the number of SSRC fields in @packet.
1661 * Returns: The number of SSRC fields in @packet.
1664 gst_rtcp_packet_bye_get_ssrc_count (GstRTCPPacket * packet)
1666 g_return_val_if_fail (packet != NULL, -1);
1667 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_BYE, -1);
1669 return packet->count;
1673 * gst_rtcp_packet_bye_get_nth_ssrc:
1674 * @packet: a valid BYE #GstRTCPPacket
1675 * @nth: the nth SSRC to get
1677 * Get the @nth SSRC of the BYE @packet.
1679 * Returns: The @nth SSRC of @packet.
1682 gst_rtcp_packet_bye_get_nth_ssrc (GstRTCPPacket * packet, guint nth)
1688 g_return_val_if_fail (packet != NULL, 0);
1689 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_BYE, 0);
1690 g_return_val_if_fail (packet->rtcp != NULL, 0);
1691 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, 0);
1692 g_return_val_if_fail (nth < packet->count, 0);
1694 /* get offset in 32-bits words into packet, skip the header */
1696 /* check that we don't go past the packet length */
1697 if (offset > packet->length)
1700 /* scale to bytes */
1702 offset += packet->offset;
1704 /* check if the packet is valid */
1705 if (offset + 4 > packet->rtcp->map.size)
1708 data = packet->rtcp->map.data;
1711 ssrc = GST_READ_UINT32_BE (data);
1717 * gst_rtcp_packet_bye_add_ssrc:
1718 * @packet: a valid BYE #GstRTCPPacket
1719 * @ssrc: an SSRC to add
1721 * Add @ssrc to the BYE @packet.
1723 * Returns: %TRUE if the ssrc was added. This function can return %FALSE if
1724 * the max MTU is exceeded or the number of sources blocks is greater than
1725 * #GST_RTCP_MAX_BYE_SSRC_COUNT.
1728 gst_rtcp_packet_bye_add_ssrc (GstRTCPPacket * packet, guint32 ssrc)
1734 g_return_val_if_fail (packet != NULL, FALSE);
1735 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_BYE, FALSE);
1736 g_return_val_if_fail (packet->rtcp != NULL, FALSE);
1737 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE, FALSE);
1739 if (packet->count >= GST_RTCP_MAX_BYE_SSRC_COUNT)
1742 data = packet->rtcp->map.data;
1743 maxsize = packet->rtcp->map.maxsize;
1746 offset = packet->offset + 4;
1748 /* move to current index */
1749 offset += (packet->count * 4);
1751 if (offset + 4 >= maxsize)
1754 /* increment packet count and length */
1756 data[packet->offset]++;
1757 packet->length += 1;
1758 data[packet->offset + 2] = (packet->length) >> 8;
1759 data[packet->offset + 3] = (packet->length) & 0xff;
1761 packet->rtcp->map.size += 4;
1763 /* move to new SSRC offset and write ssrc */
1765 GST_WRITE_UINT32_BE (data, ssrc);
1777 * gst_rtcp_packet_bye_add_ssrcs:
1778 * @packet: a valid BYE #GstRTCPPacket
1779 * @ssrc: (array length=len) (transfer none): an array of SSRCs to add
1780 * @len: number of elements in @ssrc
1782 * Adds @len SSRCs in @ssrc to BYE @packet.
1784 * Returns: %TRUE if the all the SSRCs were added. This function can return %FALSE if
1785 * the max MTU is exceeded or the number of sources blocks is greater than
1786 * #GST_RTCP_MAX_BYE_SSRC_COUNT.
1789 gst_rtcp_packet_bye_add_ssrcs (GstRTCPPacket * packet, guint32 * ssrc,
1795 g_return_val_if_fail (packet != NULL, FALSE);
1796 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_BYE, FALSE);
1797 g_return_val_if_fail (packet->rtcp != NULL, FALSE);
1798 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE, FALSE);
1801 for (i = 0; i < len && res; i++) {
1802 res = gst_rtcp_packet_bye_add_ssrc (packet, ssrc[i]);
1807 /* get the offset in packet of the reason length */
1809 get_reason_offset (GstRTCPPacket * packet)
1813 /* get amount of sources plus header */
1814 offset = 1 + packet->count;
1816 /* check that we don't go past the packet length */
1817 if (offset > packet->length)
1820 /* scale to bytes */
1822 offset += packet->offset;
1824 /* check if the packet is valid */
1825 if (offset + 1 > packet->rtcp->map.size)
1832 * gst_rtcp_packet_bye_get_reason_len:
1833 * @packet: a valid BYE #GstRTCPPacket
1835 * Get the length of the reason string.
1837 * Returns: The length of the reason string or 0 when there is no reason string
1841 gst_rtcp_packet_bye_get_reason_len (GstRTCPPacket * packet)
1846 g_return_val_if_fail (packet != NULL, 0);
1847 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_BYE, 0);
1848 g_return_val_if_fail (packet->rtcp != NULL, 0);
1849 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, 0);
1851 roffset = get_reason_offset (packet);
1855 data = packet->rtcp->map.data;
1857 return data[roffset];
1861 * gst_rtcp_packet_bye_get_reason:
1862 * @packet: a valid BYE #GstRTCPPacket
1864 * Get the reason in @packet.
1866 * Returns: (nullable): The reason for the BYE @packet or NULL if the packet did not contain
1867 * a reason string. The string must be freed with g_free() after usage.
1870 gst_rtcp_packet_bye_get_reason (GstRTCPPacket * packet)
1876 g_return_val_if_fail (packet != NULL, NULL);
1877 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_BYE, NULL);
1878 g_return_val_if_fail (packet->rtcp != NULL, NULL);
1879 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, NULL);
1881 roffset = get_reason_offset (packet);
1885 data = packet->rtcp->map.data;
1887 /* get length of reason string */
1888 len = data[roffset];
1892 /* move to string */
1895 /* check if enough data to copy */
1896 if (roffset + len > packet->rtcp->map.size)
1899 return g_strndup ((gconstpointer) (data + roffset), len);
1903 * gst_rtcp_packet_bye_set_reason:
1904 * @packet: a valid BYE #GstRTCPPacket
1905 * @reason: a reason string
1907 * Set the reason string to @reason in @packet.
1909 * Returns: TRUE if the string could be set.
1912 gst_rtcp_packet_bye_set_reason (GstRTCPPacket * packet, const gchar * reason)
1919 g_return_val_if_fail (packet != NULL, FALSE);
1920 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_BYE, FALSE);
1921 g_return_val_if_fail (packet->rtcp != NULL, FALSE);
1922 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE, FALSE);
1927 len = strlen (reason);
1931 /* make room for the string before we get the offset */
1934 roffset = get_reason_offset (packet);
1938 data = packet->rtcp->map.data;
1939 maxsize = packet->rtcp->map.maxsize;
1941 /* we have 1 byte length and we need to pad to 4 bytes */
1942 padded = ((len + 1) + 3) & ~3;
1944 /* we need enough space for the padded length */
1945 if (roffset + padded >= maxsize)
1948 data[roffset] = len;
1949 memcpy (&data[roffset + 1], reason, len);
1951 /* update packet length, we made room for 1 double word already */
1952 packet->length += (padded >> 2) - 1;
1953 data[packet->offset + 2] = (packet->length) >> 8;
1954 data[packet->offset + 3] = (packet->length) & 0xff;
1956 packet->rtcp->map.size += padded;
1969 * gst_rtcp_packet_fb_get_sender_ssrc:
1970 * @packet: a valid RTPFB or PSFB #GstRTCPPacket
1972 * Get the sender SSRC field of the RTPFB or PSFB @packet.
1974 * Returns: the sender SSRC.
1977 gst_rtcp_packet_fb_get_sender_ssrc (GstRTCPPacket * packet)
1982 g_return_val_if_fail (packet != NULL, 0);
1983 g_return_val_if_fail ((packet->type == GST_RTCP_TYPE_RTPFB ||
1984 packet->type == GST_RTCP_TYPE_PSFB), 0);
1985 g_return_val_if_fail (packet->rtcp != NULL, 0);
1986 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, 0);
1988 data = packet->rtcp->map.data;
1991 data += packet->offset + 4;
1992 ssrc = GST_READ_UINT32_BE (data);
1998 * gst_rtcp_packet_fb_set_sender_ssrc:
1999 * @packet: a valid RTPFB or PSFB #GstRTCPPacket
2000 * @ssrc: a sender SSRC
2002 * Set the sender SSRC field of the RTPFB or PSFB @packet.
2005 gst_rtcp_packet_fb_set_sender_ssrc (GstRTCPPacket * packet, guint32 ssrc)
2009 g_return_if_fail (packet != NULL);
2010 g_return_if_fail (packet->type == GST_RTCP_TYPE_RTPFB ||
2011 packet->type == GST_RTCP_TYPE_PSFB);
2012 g_return_if_fail (packet->rtcp != NULL);
2013 g_return_if_fail (packet->rtcp->map.flags & GST_MAP_READ);
2015 data = packet->rtcp->map.data;
2018 data += packet->offset + 4;
2019 GST_WRITE_UINT32_BE (data, ssrc);
2023 * gst_rtcp_packet_fb_get_media_ssrc:
2024 * @packet: a valid RTPFB or PSFB #GstRTCPPacket
2026 * Get the media SSRC field of the RTPFB or PSFB @packet.
2028 * Returns: the media SSRC.
2031 gst_rtcp_packet_fb_get_media_ssrc (GstRTCPPacket * packet)
2036 g_return_val_if_fail (packet != NULL, 0);
2037 g_return_val_if_fail ((packet->type == GST_RTCP_TYPE_RTPFB ||
2038 packet->type == GST_RTCP_TYPE_PSFB), 0);
2039 g_return_val_if_fail (packet->rtcp != NULL, 0);
2040 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, 0);
2042 data = packet->rtcp->map.data;
2044 /* skip header and sender ssrc */
2045 data += packet->offset + 8;
2046 ssrc = GST_READ_UINT32_BE (data);
2052 * gst_rtcp_packet_fb_set_media_ssrc:
2053 * @packet: a valid RTPFB or PSFB #GstRTCPPacket
2054 * @ssrc: a media SSRC
2056 * Set the media SSRC field of the RTPFB or PSFB @packet.
2059 gst_rtcp_packet_fb_set_media_ssrc (GstRTCPPacket * packet, guint32 ssrc)
2063 g_return_if_fail (packet != NULL);
2064 g_return_if_fail (packet->type == GST_RTCP_TYPE_RTPFB ||
2065 packet->type == GST_RTCP_TYPE_PSFB);
2066 g_return_if_fail (packet->rtcp != NULL);
2067 g_return_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE);
2069 data = packet->rtcp->map.data;
2071 /* skip header and sender ssrc */
2072 data += packet->offset + 8;
2073 GST_WRITE_UINT32_BE (data, ssrc);
2077 * gst_rtcp_packet_fb_get_type:
2078 * @packet: a valid RTPFB or PSFB #GstRTCPPacket
2080 * Get the feedback message type of the FB @packet.
2082 * Returns: The feedback message type.
2085 gst_rtcp_packet_fb_get_type (GstRTCPPacket * packet)
2087 g_return_val_if_fail (packet != NULL, GST_RTCP_FB_TYPE_INVALID);
2088 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_RTPFB ||
2089 packet->type == GST_RTCP_TYPE_PSFB, GST_RTCP_FB_TYPE_INVALID);
2091 return packet->count;
2095 * gst_rtcp_packet_fb_set_type:
2096 * @packet: a valid RTPFB or PSFB #GstRTCPPacket
2097 * @type: the #GstRTCPFBType to set
2099 * Set the feedback message type of the FB @packet.
2102 gst_rtcp_packet_fb_set_type (GstRTCPPacket * packet, GstRTCPFBType type)
2106 g_return_if_fail (packet != NULL);
2107 g_return_if_fail (packet->type == GST_RTCP_TYPE_RTPFB ||
2108 packet->type == GST_RTCP_TYPE_PSFB);
2109 g_return_if_fail (packet->rtcp != NULL);
2110 g_return_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE);
2112 data = packet->rtcp->map.data;
2114 data[packet->offset] = (data[packet->offset] & 0xe0) | type;
2115 packet->count = type;
2119 * gst_rtcp_ntp_to_unix:
2120 * @ntptime: an NTP timestamp
2122 * Converts an NTP time to UNIX nanoseconds. @ntptime can typically be
2123 * the NTP time of an SR RTCP message and contains, in the upper 32 bits, the
2124 * number of seconds since 1900 and, in the lower 32 bits, the fractional
2125 * seconds. The resulting value will be the number of nanoseconds since 1970.
2127 * Returns: the UNIX time for @ntptime in nanoseconds.
2130 gst_rtcp_ntp_to_unix (guint64 ntptime)
2134 /* conversion from NTP timestamp (seconds since 1900) to seconds since
2136 unixtime = ntptime - (G_GUINT64_CONSTANT (2208988800) << 32);
2137 /* conversion to nanoseconds */
2139 gst_util_uint64_scale (unixtime, GST_SECOND,
2140 (G_GINT64_CONSTANT (1) << 32));
2146 * gst_rtcp_unix_to_ntp:
2147 * @unixtime: an UNIX timestamp in nanoseconds
2149 * Converts a UNIX timestamp in nanoseconds to an NTP time. The caller should
2150 * pass a value with nanoseconds since 1970. The NTP time will, in the upper
2151 * 32 bits, contain the number of seconds since 1900 and, in the lower 32
2152 * bits, the fractional seconds. The resulting value can be used as an ntptime
2153 * for constructing SR RTCP packets.
2155 * Returns: the NTP time for @unixtime.
2158 gst_rtcp_unix_to_ntp (guint64 unixtime)
2162 /* convert clock time to NTP time. upper 32 bits should contain the seconds
2163 * and the lower 32 bits, the fractions of a second. */
2165 gst_util_uint64_scale (unixtime, (G_GINT64_CONSTANT (1) << 32),
2167 /* conversion from UNIX timestamp (seconds since 1970) to NTP (seconds
2169 ntptime += (G_GUINT64_CONSTANT (2208988800) << 32);
2175 * gst_rtcp_sdes_type_to_name:
2176 * @type: a #GstRTCPSDESType
2178 * Converts @type to the string equivalent. The string is typically used as a
2179 * key in a #GstStructure containing SDES items.
2181 * Returns: the string equivalent of @type
2184 gst_rtcp_sdes_type_to_name (GstRTCPSDESType type)
2186 const gchar *result;
2189 case GST_RTCP_SDES_CNAME:
2192 case GST_RTCP_SDES_NAME:
2195 case GST_RTCP_SDES_EMAIL:
2198 case GST_RTCP_SDES_PHONE:
2201 case GST_RTCP_SDES_LOC:
2202 result = "location";
2204 case GST_RTCP_SDES_TOOL:
2207 case GST_RTCP_SDES_NOTE:
2210 case GST_RTCP_SDES_PRIV:
2213 case GST_RTCP_SDES_H323_CADDR:
2214 result = "h323-caddr";
2216 case GST_RTCP_SDES_APSI:
2219 case GST_RTCP_SDES_RGRP:
2222 case GST_RTCP_SDES_REPAIRED_RTP_STREAM_ID:
2223 result = "repaired-rtp-stream-id";
2225 case GST_RTCP_SDES_CCID:
2228 case GST_RTCP_SDES_RTP_STREAM_ID:
2229 result = "rtp-stream-id";
2231 case GST_RTCP_SDES_MID:
2242 * gst_rtcp_sdes_name_to_type:
2243 * @name: a SDES name
2245 * Convert @name into a @GstRTCPSDESType. @name is typically a key in a
2246 * #GstStructure containing SDES items.
2248 * Returns: the #GstRTCPSDESType for @name or #GST_RTCP_SDES_PRIV when @name
2249 * is a private sdes item.
2252 gst_rtcp_sdes_name_to_type (const gchar * name)
2254 if (name == NULL || strlen (name) == 0)
2255 return GST_RTCP_SDES_INVALID;
2257 if (strcmp ("cname", name) == 0)
2258 return GST_RTCP_SDES_CNAME;
2260 if (strcmp ("name", name) == 0)
2261 return GST_RTCP_SDES_NAME;
2263 if (strcmp ("email", name) == 0)
2264 return GST_RTCP_SDES_EMAIL;
2266 if (strcmp ("phone", name) == 0)
2267 return GST_RTCP_SDES_PHONE;
2269 if (strcmp ("location", name) == 0)
2270 return GST_RTCP_SDES_LOC;
2272 if (strcmp ("tool", name) == 0)
2273 return GST_RTCP_SDES_TOOL;
2275 if (strcmp ("note", name) == 0)
2276 return GST_RTCP_SDES_NOTE;
2278 if (strcmp ("h323-caddr", name) == 0)
2279 return GST_RTCP_SDES_H323_CADDR;
2281 if (strcmp ("apsi", name) == 0)
2282 return GST_RTCP_SDES_APSI;
2284 if (strcmp ("rgrp", name) == 0)
2285 return GST_RTCP_SDES_RGRP;
2287 if (strcmp ("rtp-stream-id", name) == 0)
2288 return GST_RTCP_SDES_RTP_STREAM_ID;
2290 if (strcmp ("repaired-rtp-stream-id", name) == 0)
2291 return GST_RTCP_SDES_REPAIRED_RTP_STREAM_ID;
2293 if (strcmp ("ccid", name) == 0)
2294 return GST_RTCP_SDES_CCID;
2296 if (strcmp ("mid", name) == 0)
2297 return GST_RTCP_SDES_MID;
2299 return GST_RTCP_SDES_PRIV;
2303 * gst_rtcp_packet_fb_get_fci_length:
2304 * @packet: a valid RTPFB or PSFB #GstRTCPPacket
2306 * Get the length of the Feedback Control Information attached to a
2307 * RTPFB or PSFB @packet.
2309 * Returns: The length of the FCI in 32-bit words.
2312 gst_rtcp_packet_fb_get_fci_length (GstRTCPPacket * packet)
2316 g_return_val_if_fail (packet != NULL, 0);
2317 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_RTPFB ||
2318 packet->type == GST_RTCP_TYPE_PSFB, 0);
2319 g_return_val_if_fail (packet->rtcp != NULL, 0);
2320 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, 0);
2322 data = packet->rtcp->map.data + packet->offset + 2;
2324 return GST_READ_UINT16_BE (data) - 2;
2328 * gst_rtcp_packet_fb_set_fci_length:
2329 * @packet: a valid RTPFB or PSFB #GstRTCPPacket
2330 * @wordlen: Length of the FCI in 32-bit words
2332 * Set the length of the Feedback Control Information attached to a
2333 * RTPFB or PSFB @packet.
2335 * Returns: %TRUE if there was enough space in the packet to add this much FCI
2338 gst_rtcp_packet_fb_set_fci_length (GstRTCPPacket * packet, guint16 wordlen)
2342 g_return_val_if_fail (packet != NULL, FALSE);
2343 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_RTPFB ||
2344 packet->type == GST_RTCP_TYPE_PSFB, FALSE);
2345 g_return_val_if_fail (packet->rtcp != NULL, FALSE);
2346 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE, FALSE);
2348 if (packet->rtcp->map.maxsize < packet->offset + ((wordlen + 3) * 4))
2351 data = packet->rtcp->map.data + packet->offset + 2;
2353 GST_WRITE_UINT16_BE (data, wordlen);
2355 packet->rtcp->map.size = packet->offset + ((wordlen + 1) * 4);
2361 * gst_rtcp_packet_fb_get_fci:
2362 * @packet: a valid RTPFB or PSFB #GstRTCPPacket
2364 * Get the Feedback Control Information attached to a RTPFB or PSFB @packet.
2366 * Returns: a pointer to the FCI
2369 gst_rtcp_packet_fb_get_fci (GstRTCPPacket * packet)
2373 g_return_val_if_fail (packet != NULL, NULL);
2374 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_RTPFB ||
2375 packet->type == GST_RTCP_TYPE_PSFB, NULL);
2376 g_return_val_if_fail (packet->rtcp != NULL, NULL);
2377 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, NULL);
2379 data = packet->rtcp->map.data + packet->offset;
2381 if (GST_READ_UINT16_BE (data + 2) <= 2)
2388 * gst_rtcp_packet_app_set_subtype:
2389 * @packet: a valid APP #GstRTCPPacket
2390 * @subtype: subtype of the packet
2392 * Set the subtype field of the APP @packet.
2397 gst_rtcp_packet_app_set_subtype (GstRTCPPacket * packet, guint8 subtype)
2401 g_return_if_fail (packet != NULL);
2402 g_return_if_fail (packet->type == GST_RTCP_TYPE_APP);
2403 g_return_if_fail (packet->rtcp != NULL);
2404 g_return_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE);
2406 data = packet->rtcp->map.data + packet->offset;
2407 data[0] = (data[0] & 0xe0) | subtype;
2411 * gst_rtcp_packet_app_get_subtype:
2412 * @packet: a valid APP #GstRTCPPacket
2414 * Get the subtype field of the APP @packet.
2416 * Returns: The subtype.
2421 gst_rtcp_packet_app_get_subtype (GstRTCPPacket * packet)
2425 g_return_val_if_fail (packet != NULL, 0);
2426 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_APP, 0);
2427 g_return_val_if_fail (packet->rtcp != NULL, 0);
2428 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, 0);
2430 data = packet->rtcp->map.data + packet->offset;
2432 return data[0] & 0x1f;
2436 * gst_rtcp_packet_app_set_ssrc:
2437 * @packet: a valid APP #GstRTCPPacket
2438 * @ssrc: SSRC/CSRC of the packet
2440 * Set the SSRC/CSRC field of the APP @packet.
2445 gst_rtcp_packet_app_set_ssrc (GstRTCPPacket * packet, guint32 ssrc)
2449 g_return_if_fail (packet != NULL);
2450 g_return_if_fail (packet->type == GST_RTCP_TYPE_APP);
2451 g_return_if_fail (packet->rtcp != NULL);
2452 g_return_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE);
2454 data = packet->rtcp->map.data + packet->offset + 4;
2455 GST_WRITE_UINT32_BE (data, ssrc);
2459 * gst_rtcp_packet_app_get_ssrc:
2460 * @packet: a valid APP #GstRTCPPacket
2462 * Get the SSRC/CSRC field of the APP @packet.
2464 * Returns: The SSRC/CSRC.
2469 gst_rtcp_packet_app_get_ssrc (GstRTCPPacket * packet)
2473 g_return_val_if_fail (packet != NULL, 0);
2474 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_APP, 0);
2475 g_return_val_if_fail (packet->rtcp != NULL, 0);
2476 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, 0);
2478 data = packet->rtcp->map.data + packet->offset + 4;
2480 return GST_READ_UINT32_BE (data);
2484 * gst_rtcp_packet_app_set_name:
2485 * @packet: a valid APP #GstRTCPPacket
2486 * @name: 4-byte ASCII name
2488 * Set the name field of the APP @packet.
2493 gst_rtcp_packet_app_set_name (GstRTCPPacket * packet, const gchar * name)
2497 g_return_if_fail (packet != NULL);
2498 g_return_if_fail (packet->type == GST_RTCP_TYPE_APP);
2499 g_return_if_fail (packet->rtcp != NULL);
2500 g_return_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE);
2502 data = packet->rtcp->map.data + packet->offset + 8;
2503 memcpy (data, name, 4);
2507 * gst_rtcp_packet_app_get_name:
2508 * @packet: a valid APP #GstRTCPPacket
2510 * Get the name field of the APP @packet.
2512 * Returns: The 4-byte name field, not zero-terminated.
2517 gst_rtcp_packet_app_get_name (GstRTCPPacket * packet)
2519 g_return_val_if_fail (packet != NULL, NULL);
2520 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_APP, NULL);
2521 g_return_val_if_fail (packet->rtcp != NULL, NULL);
2522 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, NULL);
2524 return (const gchar *) &packet->rtcp->map.data[packet->offset + 8];
2528 * gst_rtcp_packet_app_get_data_length:
2529 * @packet: a valid APP #GstRTCPPacket
2531 * Get the length of the application-dependent data attached to an APP
2534 * Returns: The length of data in 32-bit words.
2539 gst_rtcp_packet_app_get_data_length (GstRTCPPacket * packet)
2543 g_return_val_if_fail (packet != NULL, 0);
2544 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_APP, 0);
2545 g_return_val_if_fail (packet->rtcp != NULL, 0);
2546 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, 0);
2548 data = packet->rtcp->map.data + packet->offset + 2;
2550 return GST_READ_UINT16_BE (data) - 2;
2554 * gst_rtcp_packet_app_set_data_length:
2555 * @packet: a valid APP #GstRTCPPacket
2556 * @wordlen: Length of the data in 32-bit words
2558 * Set the length of the application-dependent data attached to an APP
2561 * Returns: %TRUE if there was enough space in the packet to add this much
2567 gst_rtcp_packet_app_set_data_length (GstRTCPPacket * packet, guint16 wordlen)
2571 g_return_val_if_fail (packet != NULL, FALSE);
2572 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_APP, FALSE);
2573 g_return_val_if_fail (packet->rtcp != NULL, FALSE);
2574 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE, FALSE);
2576 if (packet->rtcp->map.maxsize < packet->offset + ((wordlen + 3) * 4))
2579 data = packet->rtcp->map.data + packet->offset + 2;
2581 GST_WRITE_UINT16_BE (data, wordlen);
2583 packet->rtcp->map.size = packet->offset + ((wordlen + 1) * 4);
2589 * gst_rtcp_packet_app_get_data:
2590 * @packet: a valid APP #GstRTCPPacket
2592 * Get the application-dependent data attached to a RTPFB or PSFB @packet.
2594 * Returns: A pointer to the data
2599 gst_rtcp_packet_app_get_data (GstRTCPPacket * packet)
2603 g_return_val_if_fail (packet != NULL, NULL);
2604 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_APP, NULL);
2605 g_return_val_if_fail (packet->rtcp != NULL, NULL);
2606 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, NULL);
2608 data = packet->rtcp->map.data + packet->offset;
2610 if (GST_READ_UINT16_BE (data + 2) <= 2)
2617 * gst_rtcp_packet_xr_get_ssrc:
2618 * @packet: a valid XR #GstRTCPPacket
2620 * Get the ssrc field of the XR @packet.
2622 * Returns: the ssrc.
2627 gst_rtcp_packet_xr_get_ssrc (GstRTCPPacket * packet)
2632 g_return_val_if_fail (packet != NULL, 0);
2633 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_XR, 0);
2634 g_return_val_if_fail (packet->rtcp != NULL, 0);
2635 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, 0);
2637 data = packet->rtcp->map.data;
2640 data += packet->offset + 4;
2641 ssrc = GST_READ_UINT32_BE (data);
2647 * gst_rtcp_packet_xr_first_rb:
2648 * @packet: a valid XR #GstRTCPPacket
2650 * Move to the first extended report block in XR @packet.
2652 * Returns: TRUE if there was a first extended report block.
2657 gst_rtcp_packet_xr_first_rb (GstRTCPPacket * packet)
2662 g_return_val_if_fail (packet != NULL, FALSE);
2663 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_XR, FALSE);
2665 if (packet->length < 2)
2668 /* skip header + ssrc */
2669 packet->item_offset = 8;
2671 /* Validate the block's length */
2672 block_len = gst_rtcp_packet_xr_get_block_length (packet);
2673 offset = 8 + (block_len * 1) + 4;
2675 len = packet->length << 2;
2677 if (offset >= len) {
2678 packet->item_offset = 0;
2686 * gst_rtcp_packet_xr_next_rb:
2687 * @packet: a valid XR #GstRTCPPacket
2689 * Move to the next extended report block in XR @packet.
2691 * Returns: TRUE if there was a next extended report block.
2696 gst_rtcp_packet_xr_next_rb (GstRTCPPacket * packet)
2702 g_return_val_if_fail (packet != NULL, FALSE);
2703 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_XR, FALSE);
2704 g_return_val_if_fail (packet->rtcp != NULL, FALSE);
2705 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, FALSE);
2707 block_len = gst_rtcp_packet_xr_get_block_length (packet);
2709 offset = packet->item_offset;
2710 offset += (block_len + 1) * 4;
2713 len = (packet->length << 2);
2718 packet->item_offset = offset;
2724 * gst_rtcp_packet_xr_get_block_type:
2725 * @packet: a valid XR #GstRTCPPacket
2727 * Get the extended report block type of the XR @packet.
2729 * Returns: The extended report block type.
2734 gst_rtcp_packet_xr_get_block_type (GstRTCPPacket * packet)
2738 GstRTCPXRType xr_type = GST_RTCP_XR_TYPE_INVALID;
2740 g_return_val_if_fail (packet != NULL, GST_RTCP_XR_TYPE_INVALID);
2741 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_XR,
2742 GST_RTCP_XR_TYPE_INVALID);
2743 g_return_val_if_fail (packet->rtcp != NULL, GST_RTCP_XR_TYPE_INVALID);
2744 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ,
2745 GST_RTCP_XR_TYPE_INVALID);
2746 g_return_val_if_fail (packet->length >= (packet->item_offset >> 2),
2747 GST_RTCP_XR_TYPE_INVALID);
2749 data = packet->rtcp->map.data;
2751 /* skip header + current item offset */
2752 data += packet->offset + packet->item_offset;
2754 /* XR block type can be defined more than described in RFC3611.
2755 * If undefined type is detected, user might want to know. */
2756 type = GST_READ_UINT8 (data);
2758 case GST_RTCP_XR_TYPE_LRLE:
2759 case GST_RTCP_XR_TYPE_DRLE:
2760 case GST_RTCP_XR_TYPE_PRT:
2761 case GST_RTCP_XR_TYPE_RRT:
2762 case GST_RTCP_XR_TYPE_DLRR:
2763 case GST_RTCP_XR_TYPE_SSUMM:
2764 case GST_RTCP_XR_TYPE_VOIP_METRICS:
2768 GST_DEBUG ("got 0x%x type, but that might be out of scope of RFC3611",
2777 * gst_rtcp_packet_xr_get_block_length:
2778 * @packet: a valid XR #GstRTCPPacket
2780 * Returns: The number of 32-bit words containing type-specific block
2781 * data from @packet.
2786 gst_rtcp_packet_xr_get_block_length (GstRTCPPacket * packet)
2791 g_return_val_if_fail (packet != NULL, 0);
2792 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_XR, 0);
2793 g_return_val_if_fail (packet->rtcp != NULL, 0);
2794 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, 0);
2795 g_return_val_if_fail (packet->length >= (packet->item_offset >> 2), 0);
2797 data = packet->rtcp->map.data;
2798 data += packet->offset + packet->item_offset + 2;
2800 len = GST_READ_UINT16_BE (data);
2806 * gst_rtcp_packet_xr_get_rle_info:
2807 * @packet: a valid XR #GstRTCPPacket which is Loss RLE or Duplicate RLE report.
2808 * @ssrc: the SSRC of the RTP data packet source being reported upon by this report block.
2809 * @thinning: the amount of thinning performed on the sequence number space.
2810 * @begin_seq: the first sequence number that this block reports on.
2811 * @end_seq: the last sequence number that this block reports on plus one.
2812 * @chunk_count: the number of chunks calculated by block length.
2814 * Parse the extended report block for Loss RLE and Duplicated LRE block type.
2816 * Returns: %TRUE if the report block is correctly parsed.
2821 gst_rtcp_packet_xr_get_rle_info (GstRTCPPacket * packet, guint32 * ssrc,
2822 guint8 * thinning, guint16 * begin_seq, guint16 * end_seq,
2823 guint32 * chunk_count)
2828 g_return_val_if_fail (gst_rtcp_packet_xr_get_block_type (packet) ==
2829 GST_RTCP_XR_TYPE_LRLE
2830 || gst_rtcp_packet_xr_get_block_type (packet) == GST_RTCP_XR_TYPE_DRLE,
2833 block_len = gst_rtcp_packet_xr_get_block_length (packet);
2838 *chunk_count = (block_len - 2) * 2;
2840 data = packet->rtcp->map.data;
2841 /* skip header + current item offset */
2842 data += packet->offset + packet->item_offset;
2845 *thinning = data[1] & 0x0f;
2850 *ssrc = GST_READ_UINT32_BE (data);
2851 /* go to begin_seq */
2854 *begin_seq = ((data[0] << 8) | data[1]);
2858 *end_seq = ((data[0] << 8) | data[1]);
2864 * gst_rtcp_packet_xr_get_rle_nth_chunk:
2865 * @packet: a valid XR #GstRTCPPacket which is Loss RLE or Duplicate RLE report.
2866 * @nth: the index of chunk to retrieve.
2867 * @chunk: the @nth chunk.
2869 * Retrieve actual chunk data.
2871 * Returns: %TRUE if the report block returns chunk correctly.
2876 gst_rtcp_packet_xr_get_rle_nth_chunk (GstRTCPPacket * packet,
2877 guint nth, guint16 * chunk)
2879 guint32 chunk_count;
2882 if (!gst_rtcp_packet_xr_get_rle_info (packet, NULL, NULL, NULL, NULL,
2884 g_return_val_if_reached (FALSE);
2886 if (nth >= chunk_count)
2889 data = packet->rtcp->map.data;
2890 /* skip header + current item offset */
2891 data += packet->offset + packet->item_offset;
2893 /* skip ssrc, {begin,end}_seq */
2896 /* goto nth chunk */
2899 *chunk = ((data[0] << 8) | data[1]);
2905 * gst_rtcp_packet_xr_get_prt_info:
2906 * @packet: a valid XR #GstRTCPPacket which has a Packet Receipt Times Report Block
2907 * @ssrc: the SSRC of the RTP data packet source being reported upon by this report block.
2908 * @thinning: the amount of thinning performed on the sequence number space.
2909 * @begin_seq: the first sequence number that this block reports on.
2910 * @end_seq: the last sequence number that this block reports on plus one.
2912 * Parse the Packet Recept Times Report Block from a XR @packet
2914 * Returns: %TRUE if the report block is correctly parsed.
2919 gst_rtcp_packet_xr_get_prt_info (GstRTCPPacket * packet,
2920 guint32 * ssrc, guint8 * thinning, guint16 * begin_seq, guint16 * end_seq)
2925 g_return_val_if_fail (gst_rtcp_packet_xr_get_block_type (packet) ==
2926 GST_RTCP_XR_TYPE_PRT, FALSE);
2928 block_len = gst_rtcp_packet_xr_get_block_length (packet);
2932 data = packet->rtcp->map.data;
2933 /* skip header + current item offset */
2934 data += packet->offset + packet->item_offset;
2937 *thinning = data[1] & 0x0f;
2942 *ssrc = GST_READ_UINT32_BE (data);
2944 /* go to begin_seq */
2947 *begin_seq = ((data[0] << 8) | data[1]);
2951 *end_seq = ((data[0] << 8) | data[1]);
2957 * gst_rtcp_packet_xr_get_prt_by_seq:
2958 * @packet: a valid XR #GstRTCPPacket which has the Packet Recept Times Report Block.
2959 * @seq: the sequence to retrieve the time.
2960 * @receipt_time: the packet receipt time of @seq.
2962 * Retrieve the packet receipt time of @seq which ranges in [begin_seq, end_seq).
2964 * Returns: %TRUE if the report block returns the receipt time correctly.
2969 gst_rtcp_packet_xr_get_prt_by_seq (GstRTCPPacket * packet,
2970 guint16 seq, guint32 * receipt_time)
2972 guint16 begin_seq, end_seq;
2975 if (!gst_rtcp_packet_xr_get_prt_info (packet, NULL, NULL, &begin_seq,
2977 g_return_val_if_reached (FALSE);
2979 if (seq >= end_seq || seq < begin_seq)
2982 data = packet->rtcp->map.data;
2983 /* skip header + current item offset */
2984 data += packet->offset + packet->item_offset;
2986 /* skip ssrc, {begin,end}_seq */
2989 data += (seq - begin_seq) * 4;
2992 *receipt_time = GST_READ_UINT32_BE (data);
2998 * gst_rtcp_packet_xr_get_rrt:
2999 * @packet: a valid XR #GstRTCPPacket which has the Receiver Reference Time.
3000 * @timestamp: NTP timestamp
3002 * Returns: %TRUE if the report block returns the reference time correctly.
3007 gst_rtcp_packet_xr_get_rrt (GstRTCPPacket * packet, guint64 * timestamp)
3011 g_return_val_if_fail (gst_rtcp_packet_xr_get_block_type (packet) ==
3012 GST_RTCP_XR_TYPE_RRT, FALSE);
3014 if (gst_rtcp_packet_xr_get_block_length (packet) != 2)
3017 data = packet->rtcp->map.data;
3018 /* skip header + current item offset */
3019 data += packet->offset + packet->item_offset;
3021 /* skip block header */
3024 *timestamp = GST_READ_UINT64_BE (data);
3030 * gst_rtcp_packet_xr_get_dlrr_block:
3031 * @packet: a valid XR #GstRTCPPacket which has DLRR Report Block.
3032 * @nth: the index of sub-block to retrieve.
3033 * @ssrc: the SSRC of the receiver.
3034 * @last_rr: the last receiver reference timestamp of @ssrc.
3035 * @delay: the delay since @last_rr.
3037 * Parse the extended report block for DLRR report block type.
3039 * Returns: %TRUE if the report block is correctly parsed.
3044 gst_rtcp_packet_xr_get_dlrr_block (GstRTCPPacket * packet,
3045 guint nth, guint32 * ssrc, guint32 * last_rr, guint32 * delay)
3050 g_return_val_if_fail (gst_rtcp_packet_xr_get_block_type (packet) ==
3051 GST_RTCP_XR_TYPE_DLRR, FALSE);
3053 block_len = gst_rtcp_packet_xr_get_block_length (packet);
3055 if (nth * 3 >= block_len)
3058 data = packet->rtcp->map.data;
3059 /* skip header + current item offset */
3060 data += packet->offset + packet->item_offset;
3061 /* skip block header */
3063 data += nth * 3 * 4;
3066 *ssrc = GST_READ_UINT32_BE (data);
3070 *last_rr = GST_READ_UINT32_BE (data);
3074 *delay = GST_READ_UINT32_BE (data);
3080 * gst_rtcp_packet_xr_get_summary_info:
3081 * @packet: a valid XR #GstRTCPPacket which has Statics Summary Report Block.
3082 * @ssrc: the SSRC of the source.
3083 * @begin_seq: the first sequence number that this block reports on.
3084 * @end_seq: the last sequence number that this block reports on plus one.
3086 * Extract a basic information from static summary report block of XR @packet.
3088 * Returns: %TRUE if the report block is correctly parsed.
3093 gst_rtcp_packet_xr_get_summary_info (GstRTCPPacket * packet, guint32 * ssrc,
3094 guint16 * begin_seq, guint16 * end_seq)
3098 g_return_val_if_fail (gst_rtcp_packet_xr_get_block_type (packet) ==
3099 GST_RTCP_XR_TYPE_SSUMM, FALSE);
3101 if (gst_rtcp_packet_xr_get_block_length (packet) != 9)
3104 data = packet->rtcp->map.data;
3105 /* skip header + current item offset */
3106 data += packet->offset + packet->item_offset;
3107 /* skip block header */
3111 *ssrc = GST_READ_UINT32_BE (data);
3113 /* go to begin_seq */
3116 *begin_seq = ((data[0] << 8) | data[1]);
3120 *end_seq = ((data[0] << 8) | data[1]);
3126 * gst_rtcp_packet_xr_get_summary_pkt:
3127 * @packet: a valid XR #GstRTCPPacket which has Statics Summary Report Block.
3128 * @lost_packets: the number of lost packets between begin_seq and end_seq.
3129 * @dup_packets: the number of duplicate packets between begin_seq and end_seq.
3131 * Get the number of lost or duplicate packets. If the flag in a block header
3132 * is set as zero, @lost_packets or @dup_packets will be zero.
3134 * Returns: %TRUE if the report block is correctly parsed.
3139 gst_rtcp_packet_xr_get_summary_pkt (GstRTCPPacket * packet,
3140 guint32 * lost_packets, guint32 * dup_packets)
3145 g_return_val_if_fail (gst_rtcp_packet_xr_get_block_type (packet) ==
3146 GST_RTCP_XR_TYPE_SSUMM, FALSE);
3147 if (gst_rtcp_packet_xr_get_block_length (packet) != 9)
3150 data = packet->rtcp->map.data;
3151 /* skip header + current item offset */
3152 data += packet->offset + packet->item_offset;
3154 /* skip block header,ssrc, {begin,end}_seq */
3158 if (!(flags & 0x80))
3161 *lost_packets = GST_READ_UINT32_BE (data);
3166 if (!(flags & 0x40))
3169 *dup_packets = GST_READ_UINT32_BE (data);
3176 * gst_rtcp_packet_xr_get_summary_jitter:
3177 * @packet: a valid XR #GstRTCPPacket which has Statics Summary Report Block.
3178 * @min_jitter: the minimum relative transit time between two sequences.
3179 * @max_jitter: the maximum relative transit time between two sequences.
3180 * @mean_jitter: the mean relative transit time between two sequences.
3181 * @dev_jitter: the standard deviation of the relative transit time between two sequences.
3183 * Extract jitter information from the statistics summary. If the jitter flag in
3184 * a block header is set as zero, all of jitters will be zero.
3186 * Returns: %TRUE if the report block is correctly parsed.
3191 gst_rtcp_packet_xr_get_summary_jitter (GstRTCPPacket * packet,
3192 guint32 * min_jitter, guint32 * max_jitter,
3193 guint32 * mean_jitter, guint32 * dev_jitter)
3198 g_return_val_if_fail (gst_rtcp_packet_xr_get_block_type (packet) ==
3199 GST_RTCP_XR_TYPE_SSUMM, FALSE);
3201 if (gst_rtcp_packet_xr_get_block_length (packet) != 9)
3204 data = packet->rtcp->map.data;
3205 /* skip header + current item offset */
3206 data += packet->offset + packet->item_offset;
3209 if (!(flags & 0x20)) {
3222 /* skip block header,ssrc, {begin,end}_seq, packets */
3225 *min_jitter = GST_READ_UINT32_BE (data);
3229 *max_jitter = GST_READ_UINT32_BE (data);
3233 *mean_jitter = GST_READ_UINT32_BE (data);
3237 *dev_jitter = GST_READ_UINT32_BE (data);
3243 * gst_rtcp_packet_xr_get_summary_ttl:
3244 * @packet: a valid XR #GstRTCPPacket which has Statics Summary Report Block.
3245 * @is_ipv4: the flag to indicate that the return values are ipv4 ttl or ipv6 hop limits.
3246 * @min_ttl: the minimum TTL or Hop Limit value of data packets between two sequences.
3247 * @max_ttl: the maximum TTL or Hop Limit value of data packets between two sequences.
3248 * @mean_ttl: the mean TTL or Hop Limit value of data packets between two sequences.
3249 * @dev_ttl: the standard deviation of the TTL or Hop Limit value of data packets between two sequences.
3251 * Extract the value of ttl for ipv4, or hop limit for ipv6.
3253 * Returns: %TRUE if the report block is correctly parsed.
3258 gst_rtcp_packet_xr_get_summary_ttl (GstRTCPPacket * packet,
3259 gboolean * is_ipv4, guint8 * min_ttl, guint8 * max_ttl, guint8 * mean_ttl,
3265 g_return_val_if_fail (gst_rtcp_packet_xr_get_block_type (packet) ==
3266 GST_RTCP_XR_TYPE_SSUMM, FALSE);
3268 if (gst_rtcp_packet_xr_get_block_length (packet) != 9)
3271 data = packet->rtcp->map.data;
3272 /* skip header + current item offset */
3273 data += packet->offset + packet->item_offset;
3274 flags = (data[1] & 0x18) >> 3;
3280 *is_ipv4 = (flags == 1);
3282 /* skip block header,ssrc, {begin,end}_seq, packets, jitters */
3291 *mean_ttl = data[2];
3300 * gst_rtcp_packet_xr_get_voip_metrics_ssrc:
3301 * @packet: a valid XR #GstRTCPPacket which has VoIP Metrics Report Block.
3302 * @ssrc: the SSRC of source
3304 * Returns: %TRUE if the report block is correctly parsed.
3309 gst_rtcp_packet_xr_get_voip_metrics_ssrc (GstRTCPPacket * packet,
3314 g_return_val_if_fail (gst_rtcp_packet_xr_get_block_type (packet) ==
3315 GST_RTCP_XR_TYPE_VOIP_METRICS, FALSE);
3317 if (gst_rtcp_packet_xr_get_block_length (packet) != 8)
3320 data = packet->rtcp->map.data;
3321 /* skip header + current item offset */
3322 data += packet->offset + packet->item_offset;
3324 /* skip block header */
3327 *ssrc = GST_READ_UINT32_BE (data);
3333 * gst_rtcp_packet_xr_get_voip_packet_metrics:
3334 * @packet: a valid XR #GstRTCPPacket which has VoIP Metrics Report Block.
3335 * @loss_rate: the fraction of RTP data packets from the source lost.
3336 * @discard_rate: the fraction of RTP data packets from the source that have been discarded.
3338 * Returns: %TRUE if the report block is correctly parsed.
3343 gst_rtcp_packet_xr_get_voip_packet_metrics (GstRTCPPacket * packet,
3344 guint8 * loss_rate, guint8 * discard_rate)
3348 g_return_val_if_fail (gst_rtcp_packet_xr_get_block_type (packet) ==
3349 GST_RTCP_XR_TYPE_VOIP_METRICS, FALSE);
3351 if (gst_rtcp_packet_xr_get_block_length (packet) != 8)
3354 data = packet->rtcp->map.data;
3355 /* skip header + current item offset */
3356 data += packet->offset + packet->item_offset;
3358 /* skip block header, ssrc */
3361 *loss_rate = data[0];
3364 *discard_rate = data[1];
3370 * gst_rtcp_packet_xr_get_voip_burst_metrics:
3371 * @packet: a valid XR #GstRTCPPacket which has VoIP Metrics Report Block.
3372 * @burst_density: the fraction of RTP data packets within burst periods.
3373 * @gap_density: the fraction of RTP data packets within inter-burst gaps.
3374 * @burst_duration: the mean duration(ms) of the burst periods.
3375 * @gap_duration: the mean duration(ms) of the gap periods.
3377 * Returns: %TRUE if the report block is correctly parsed.
3382 gst_rtcp_packet_xr_get_voip_burst_metrics (GstRTCPPacket * packet,
3383 guint8 * burst_density, guint8 * gap_density, guint16 * burst_duration,
3384 guint16 * gap_duration)
3388 g_return_val_if_fail (gst_rtcp_packet_xr_get_block_type (packet) ==
3389 GST_RTCP_XR_TYPE_VOIP_METRICS, FALSE);
3391 if (gst_rtcp_packet_xr_get_block_length (packet) != 8)
3394 data = packet->rtcp->map.data;
3395 /* skip header + current item offset */
3396 data += packet->offset + packet->item_offset;
3398 /* skip block header, ssrc, packet metrics */
3401 *burst_density = data[0];
3404 *gap_density = data[1];
3408 *burst_duration = GST_READ_UINT16_BE (data);
3412 *gap_duration = GST_READ_UINT16_BE (data);
3418 * gst_rtcp_packet_xr_get_voip_delay_metrics:
3419 * @packet: a valid XR #GstRTCPPacket which has VoIP Metrics Report Block.
3420 * @roundtrip_delay: the most recently calculated round trip time between RTP interfaces(ms)
3421 * @end_system_delay: the most recently estimated end system delay(ms)
3423 * Returns: %TRUE if the report block is correctly parsed.
3428 gst_rtcp_packet_xr_get_voip_delay_metrics (GstRTCPPacket * packet,
3429 guint16 * roundtrip_delay, guint16 * end_system_delay)
3433 g_return_val_if_fail (gst_rtcp_packet_xr_get_block_type (packet) ==
3434 GST_RTCP_XR_TYPE_VOIP_METRICS, FALSE);
3436 if (gst_rtcp_packet_xr_get_block_length (packet) != 8)
3439 data = packet->rtcp->map.data;
3440 /* skip header + current item offset */
3441 data += packet->offset + packet->item_offset;
3443 /* skip block header, ssrc, packet metrics, burst metrics */
3445 if (roundtrip_delay)
3446 *roundtrip_delay = GST_READ_UINT16_BE (data);
3449 if (end_system_delay)
3450 *end_system_delay = GST_READ_UINT16_BE (data);
3456 * gst_rtcp_packet_xr_get_voip_signal_metrics:
3457 * @packet: a valid XR #GstRTCPPacket which has VoIP Metrics Report Block.
3458 * @signal_level: the ratio of the signal level to a 0 dBm reference.
3459 * @noise_level: the ratio of the silent period background noise level to a 0 dBm reference.
3460 * @rerl: the residual echo return loss value.
3461 * @gmin: the gap threshold.
3463 * Returns: %TRUE if the report block is correctly parsed.
3468 gst_rtcp_packet_xr_get_voip_signal_metrics (GstRTCPPacket * packet,
3469 guint8 * signal_level, guint8 * noise_level, guint8 * rerl, guint8 * gmin)
3473 g_return_val_if_fail (gst_rtcp_packet_xr_get_block_type (packet) ==
3474 GST_RTCP_XR_TYPE_VOIP_METRICS, FALSE);
3476 if (gst_rtcp_packet_xr_get_block_length (packet) != 8)
3479 data = packet->rtcp->map.data;
3480 /* skip header + current item offset */
3481 data += packet->offset + packet->item_offset;
3483 /* skip block header, ssrc, packet metrics, burst metrics,
3487 *signal_level = data[0];
3490 *noise_level = data[1];
3502 * gst_rtcp_packet_xr_get_voip_quality_metrics:
3503 * @packet: a valid XR #GstRTCPPacket which has VoIP Metrics Report Block.
3504 * @r_factor: the R factor is a voice quality metric describing the segment of the call.
3505 * @ext_r_factor: the external R factor is a voice quality metric.
3506 * @mos_lq: the estimated mean opinion score for listening quality.
3507 * @mos_cq: the estimated mean opinion score for conversational quality.
3509 * Returns: %TRUE if the report block is correctly parsed.
3514 gst_rtcp_packet_xr_get_voip_quality_metrics (GstRTCPPacket * packet,
3515 guint8 * r_factor, guint8 * ext_r_factor, guint8 * mos_lq, guint8 * mos_cq)
3519 g_return_val_if_fail (gst_rtcp_packet_xr_get_block_type (packet) ==
3520 GST_RTCP_XR_TYPE_VOIP_METRICS, FALSE);
3522 if (gst_rtcp_packet_xr_get_block_length (packet) != 8)
3525 data = packet->rtcp->map.data;
3526 /* skip header + current item offset */
3527 data += packet->offset + packet->item_offset;
3529 /* skip block header, ssrc, packet metrics, burst metrics,
3530 * delay metrics, signal metrics */
3533 *r_factor = data[0];
3536 *ext_r_factor = data[1];
3548 * gst_rtcp_packet_xr_get_voip_configuration_params:
3549 * @packet: a valid XR #GstRTCPPacket which has VoIP Metrics Report Block.
3550 * @gmin: the gap threshold.
3551 * @rx_config: the receiver configuration byte.
3553 * Returns: %TRUE if the report block is correctly parsed.
3558 gst_rtcp_packet_xr_get_voip_configuration_params (GstRTCPPacket * packet,
3559 guint8 * gmin, guint8 * rx_config)
3563 g_return_val_if_fail (gst_rtcp_packet_xr_get_block_type (packet) ==
3564 GST_RTCP_XR_TYPE_VOIP_METRICS, FALSE);
3566 if (gst_rtcp_packet_xr_get_block_length (packet) != 8)
3569 data = packet->rtcp->map.data;
3570 /* skip header + current item offset */
3571 data += packet->offset + packet->item_offset;
3577 *rx_config = data[28];
3583 * gst_rtcp_packet_xr_get_voip_jitter_buffer_params:
3584 * @packet: a valid XR #GstRTCPPacket which has VoIP Metrics Report Block.
3585 * @jb_nominal: the current nominal jitter buffer delay(ms)
3586 * @jb_maximum: the current maximum jitter buffer delay(ms)
3587 * @jb_abs_max: the absolute maximum delay(ms)
3589 * Returns: %TRUE if the report block is correctly parsed.
3594 gst_rtcp_packet_xr_get_voip_jitter_buffer_params (GstRTCPPacket * packet,
3595 guint16 * jb_nominal, guint16 * jb_maximum, guint16 * jb_abs_max)
3599 g_return_val_if_fail (gst_rtcp_packet_xr_get_block_type (packet) ==
3600 GST_RTCP_XR_TYPE_VOIP_METRICS, FALSE);
3602 if (gst_rtcp_packet_xr_get_block_length (packet) != 8)
3605 data = packet->rtcp->map.data;
3606 /* skip header + current item offset */
3607 data += packet->offset + packet->item_offset;
3609 /* skip block header, ssrc, packet metrics, burst metrics,
3610 * delay metrics, signal metrics, config */
3614 *jb_nominal = GST_READ_UINT16_BE (data);
3618 *jb_maximum = GST_READ_UINT16_BE (data);
3622 *jb_abs_max = GST_READ_UINT16_BE (data);