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 /* no padding when mask succeeds */
119 /* get packet length */
120 header_len = (((data[2] << 8) | data[3]) + 1) << 2;
121 if (data_len < header_len)
124 /* move to next compound packet */
126 data_len -= header_len;
128 /* we are at the end now */
132 /* padding only allowed on last packet */
136 /* check version of new packet */
137 version = data[0] & 0xc0;
138 if (version != (GST_RTCP_VERSION << 6))
141 /* check padding of new packet */
142 if (data[0] & 0x20) {
144 /* last byte of padding contains the number of padded bytes including
145 * itself. must be a multiple of 4, but cannot be 0. */
146 pad_bytes = data[data_len - 1];
147 if (pad_bytes == 0 || (pad_bytes & 0x3))
152 /* some leftover bytes */
160 GST_DEBUG ("len check failed");
165 GST_DEBUG ("mask check failed (%04x != %04x)", header_mask, valid_mask);
170 GST_DEBUG ("wrong version (%d < 2)", version >> 6);
175 GST_DEBUG ("padding check failed");
181 * gst_rtcp_buffer_validate_data_reduced:
182 * @data: (array length=len): the data to validate
183 * @len: the length of @data to validate
185 * Check if the @data and @size point to the data of a valid RTCP packet.
186 * Use this function to validate a packet before using the other functions in
189 * This function is updated to support reduced size rtcp packets according to
190 * RFC 5506 and will validate full compound RTCP packets as well as reduced
193 * Returns: TRUE if the data points to a valid RTCP packet.
198 gst_rtcp_buffer_validate_data_reduced (guint8 * data, guint len)
200 return gst_rtcp_buffer_validate_data_internal (data, len,
201 GST_RTCP_REDUCED_SIZE_VALID_MASK);
205 * gst_rtcp_buffer_validate_data:
206 * @data: (array length=len): the data to validate
207 * @len: the length of @data to validate
209 * Check if the @data and @size point to the data of a valid compound,
210 * non-reduced size RTCP packet.
211 * Use this function to validate a packet before using the other functions in
214 * Returns: TRUE if the data points to a valid RTCP packet.
217 gst_rtcp_buffer_validate_data (guint8 * data, guint len)
219 return gst_rtcp_buffer_validate_data_internal (data, len,
220 GST_RTCP_VALID_MASK);
224 * gst_rtcp_buffer_validate_reduced:
225 * @buffer: the buffer to validate
227 * Check if the data pointed to by @buffer is a valid RTCP packet using
228 * gst_rtcp_buffer_validate_reduced().
230 * Returns: TRUE if @buffer is a valid RTCP packet.
235 gst_rtcp_buffer_validate_reduced (GstBuffer * buffer)
240 g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
242 gst_buffer_map (buffer, &map, GST_MAP_READ);
243 res = gst_rtcp_buffer_validate_data_reduced (map.data, map.size);
244 gst_buffer_unmap (buffer, &map);
250 * gst_rtcp_buffer_validate:
251 * @buffer: the buffer to validate
253 * Check if the data pointed to by @buffer is a valid RTCP packet using
254 * gst_rtcp_buffer_validate_data().
256 * Returns: TRUE if @buffer is a valid RTCP packet.
259 gst_rtcp_buffer_validate (GstBuffer * buffer)
264 g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
266 gst_buffer_map (buffer, &map, GST_MAP_READ);
267 res = gst_rtcp_buffer_validate_data (map.data, map.size);
268 gst_buffer_unmap (buffer, &map);
274 * gst_rtcp_buffer_new:
275 * @mtu: the maximum mtu size.
277 * Create a new buffer for constructing RTCP packets. The packet will have a
278 * maximum size of @mtu.
280 * Returns: A newly allocated buffer.
283 gst_rtcp_buffer_new (guint mtu)
288 g_return_val_if_fail (mtu > 0, NULL);
290 data = g_malloc0 (mtu);
292 result = gst_buffer_new_wrapped_full (0, data, mtu, 0, 0, data, g_free);
298 * gst_rtcp_buffer_map:
299 * @buffer: a buffer with an RTCP packet
300 * @flags: flags for the mapping
301 * @rtcp: resulting #GstRTCPBuffer
303 * Open @buffer for reading or writing, depending on @flags. The resulting RTCP
304 * buffer state is stored in @rtcp.
307 gst_rtcp_buffer_map (GstBuffer * buffer, GstMapFlags flags,
308 GstRTCPBuffer * rtcp)
310 g_return_val_if_fail (rtcp != NULL, FALSE);
311 g_return_val_if_fail (rtcp->buffer == NULL, FALSE);
312 g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
313 g_return_val_if_fail (flags & GST_MAP_READ, FALSE);
315 rtcp->buffer = buffer;
316 gst_buffer_map (buffer, &rtcp->map, flags);
322 * gst_rtcp_buffer_unmap:
323 * @rtcp: a buffer with an RTCP packet
325 * Finish @rtcp after being constructed. This function is usually called
326 * after gst_rtcp_buffer_map() and after adding the RTCP items to the new buffer.
328 * The function adjusts the size of @rtcp with the total length of all the
332 gst_rtcp_buffer_unmap (GstRTCPBuffer * rtcp)
334 g_return_val_if_fail (rtcp != NULL, FALSE);
335 g_return_val_if_fail (GST_IS_BUFFER (rtcp->buffer), FALSE);
337 if (rtcp->map.flags & GST_MAP_WRITE) {
339 gst_buffer_resize (rtcp->buffer, 0, rtcp->map.size);
342 gst_buffer_unmap (rtcp->buffer, &rtcp->map);
349 * gst_rtcp_buffer_get_packet_count:
350 * @rtcp: a valid RTCP buffer
352 * Get the number of RTCP packets in @rtcp.
354 * Returns: the number of RTCP packets in @rtcp.
357 gst_rtcp_buffer_get_packet_count (GstRTCPBuffer * rtcp)
359 GstRTCPPacket packet;
362 g_return_val_if_fail (rtcp != NULL, 0);
363 g_return_val_if_fail (GST_IS_BUFFER (rtcp->buffer), 0);
364 g_return_val_if_fail (rtcp != NULL, 0);
365 g_return_val_if_fail (rtcp->map.flags & GST_MAP_READ, 0);
368 if (gst_rtcp_buffer_get_first_packet (rtcp, &packet)) {
371 } while (gst_rtcp_packet_move_to_next (&packet));
378 rtcp_packet_min_length (GstRTCPType type)
381 case GST_RTCP_TYPE_SR:
383 case GST_RTCP_TYPE_RR:
385 case GST_RTCP_TYPE_SDES:
387 case GST_RTCP_TYPE_BYE:
389 case GST_RTCP_TYPE_APP:
391 case GST_RTCP_TYPE_RTPFB:
393 case GST_RTCP_TYPE_PSFB:
395 case GST_RTCP_TYPE_XR:
403 * read_packet_header:
406 * Read the packet headers for the packet pointed to by @packet.
408 * Returns: TRUE if @packet pointed to a valid header.
411 read_packet_header (GstRTCPPacket * packet)
419 g_return_val_if_fail (packet != NULL, FALSE);
421 data = packet->rtcp->map.data;
422 maxsize = packet->rtcp->map.size;
424 offset = packet->offset;
426 /* check if we are at the end of the buffer, we add 4 because we also want to
427 * ensure we can read the header. */
428 if (offset + 4 > maxsize)
431 if ((data[offset] & 0xc0) != (GST_RTCP_VERSION << 6))
434 /* read count, type and length */
435 packet->padding = (data[offset] & 0x20) == 0x20;
436 packet->count = data[offset] & 0x1f;
437 packet->type = data[offset + 1];
438 packet->length = (data[offset + 2] << 8) | data[offset + 3];
439 packet->item_offset = 4;
440 packet->item_count = 0;
441 packet->entry_offset = 4;
443 /* Ensure no overread from the claimed data size. The packet length
444 is expressed in multiple of 32 bits, to make things obvious. */
445 if (offset + 4 + packet->length * 4 > maxsize)
448 minsize = rtcp_packet_min_length (packet->type);
451 minlength = (minsize - 4) >> 2;
453 /* Validate the size */
454 if (packet->length < minlength)
461 * gst_rtcp_buffer_get_first_packet:
462 * @rtcp: a valid RTCP buffer
463 * @packet: a #GstRTCPPacket
465 * Initialize a new #GstRTCPPacket pointer that points to the first packet in
468 * Returns: TRUE if the packet existed in @rtcp.
471 gst_rtcp_buffer_get_first_packet (GstRTCPBuffer * rtcp, GstRTCPPacket * packet)
473 g_return_val_if_fail (rtcp != NULL, FALSE);
474 g_return_val_if_fail (GST_IS_BUFFER (rtcp->buffer), FALSE);
475 g_return_val_if_fail (packet != NULL, FALSE);
476 g_return_val_if_fail (rtcp != NULL, 0);
477 g_return_val_if_fail (rtcp->map.flags & GST_MAP_READ, 0);
482 packet->type = GST_RTCP_TYPE_INVALID;
484 if (!read_packet_header (packet))
491 * gst_rtcp_packet_move_to_next:
492 * @packet: a #GstRTCPPacket
494 * Move the packet pointer @packet to the next packet in the payload.
495 * Use gst_rtcp_buffer_get_first_packet() to initialize @packet.
497 * Returns: TRUE if @packet is pointing to a valid packet after calling this
501 gst_rtcp_packet_move_to_next (GstRTCPPacket * packet)
503 g_return_val_if_fail (packet != NULL, FALSE);
504 g_return_val_if_fail (packet->type != GST_RTCP_TYPE_INVALID, FALSE);
505 g_return_val_if_fail (packet->rtcp != NULL, FALSE);
506 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, FALSE);
508 /* if we have a padding or invalid packet, it must be the last,
510 if (packet->type == GST_RTCP_TYPE_INVALID || packet->padding)
513 /* move to next packet. Add 4 because the header is not included in length */
514 packet->offset += (packet->length << 2) + 4;
516 /* try to read new header */
517 if (!read_packet_header (packet))
525 packet->type = GST_RTCP_TYPE_INVALID;
531 * gst_rtcp_buffer_add_packet:
532 * @rtcp: a valid RTCP buffer
533 * @type: the #GstRTCPType of the new packet
534 * @packet: pointer to new packet
536 * Add a new packet of @type to @rtcp. @packet will point to the newly created
539 * Returns: %TRUE if the packet could be created. This function returns %FALSE
540 * if the max mtu is exceeded for the buffer.
543 gst_rtcp_buffer_add_packet (GstRTCPBuffer * rtcp, GstRTCPType type,
544 GstRTCPPacket * packet)
551 g_return_val_if_fail (rtcp != NULL, FALSE);
552 g_return_val_if_fail (GST_IS_BUFFER (rtcp->buffer), FALSE);
553 g_return_val_if_fail (type != GST_RTCP_TYPE_INVALID, FALSE);
554 g_return_val_if_fail (packet != NULL, FALSE);
555 g_return_val_if_fail (rtcp->map.flags & GST_MAP_WRITE, FALSE);
557 /* find free space */
558 if (gst_rtcp_buffer_get_first_packet (rtcp, packet)) {
559 while (gst_rtcp_packet_move_to_next (packet));
561 if (packet->padding) {
562 /* Last packet is a padding packet. Let's not replace it silently */
563 /* and let the application know that it could not be added because */
564 /* it would involve replacing a packet */
569 maxsize = rtcp->map.maxsize;
571 /* packet->offset is now pointing to the next free offset in the buffer to
572 * start a compound packet. Next we figure out if we have enough free space in
573 * the buffer to continue. */
574 len = rtcp_packet_min_length (type);
577 if (packet->offset + len >= maxsize)
580 rtcp->map.size += len;
582 data = rtcp->map.data + packet->offset;
584 data[0] = (GST_RTCP_VERSION << 6);
586 /* length is stored in multiples of 32 bit words minus the length of the
588 len = (len - 4) >> 2;
590 data[3] = len & 0xff;
592 /* now try to position to the packet */
593 result = read_packet_header (packet);
600 g_warning ("unknown type %d", type);
610 * gst_rtcp_packet_remove:
611 * @packet: a #GstRTCPPacket
613 * Removes the packet pointed to by @packet and moves pointer to the next one
615 * Returns: TRUE if @packet is pointing to a valid packet after calling this
619 gst_rtcp_packet_remove (GstRTCPPacket * packet)
621 gboolean ret = FALSE;
624 g_return_val_if_fail (packet != NULL, FALSE);
625 g_return_val_if_fail (packet->type != GST_RTCP_TYPE_INVALID, FALSE);
626 g_return_val_if_fail (packet->rtcp != NULL, FALSE);
627 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE, FALSE);
629 /* The next packet starts at offset + length + 4 (the header) */
630 offset = packet->offset + (packet->length << 2) + 4;
632 /* Overwrite this packet with the rest of the data */
633 memmove (packet->rtcp->map.data + packet->offset,
634 packet->rtcp->map.data + offset, packet->rtcp->map.size - offset);
636 packet->rtcp->map.size -= offset - packet->offset;
638 /* try to read next header */
639 ret = read_packet_header (packet);
641 packet->type = GST_RTCP_TYPE_INVALID;
647 * gst_rtcp_packet_get_padding:
648 * @packet: a valid #GstRTCPPacket
650 * Get the packet padding of the packet pointed to by @packet.
652 * Returns: If the packet has the padding bit set.
655 gst_rtcp_packet_get_padding (GstRTCPPacket * packet)
657 g_return_val_if_fail (packet != NULL, FALSE);
658 g_return_val_if_fail (packet->type != GST_RTCP_TYPE_INVALID, FALSE);
660 return packet->padding;
664 * gst_rtcp_packet_get_type:
665 * @packet: a valid #GstRTCPPacket
667 * Get the packet type of the packet pointed to by @packet.
669 * Returns: The packet type or GST_RTCP_TYPE_INVALID when @packet is not
670 * pointing to a valid packet.
673 gst_rtcp_packet_get_type (GstRTCPPacket * packet)
675 g_return_val_if_fail (packet != NULL, GST_RTCP_TYPE_INVALID);
681 * gst_rtcp_packet_get_count:
682 * @packet: a valid #GstRTCPPacket
684 * Get the count field in @packet.
686 * Returns: The count field in @packet or -1 if @packet does not point to a
690 gst_rtcp_packet_get_count (GstRTCPPacket * packet)
692 g_return_val_if_fail (packet != NULL, -1);
693 g_return_val_if_fail (packet->type != GST_RTCP_TYPE_INVALID, -1);
695 return packet->count;
699 * gst_rtcp_packet_get_length:
700 * @packet: a valid #GstRTCPPacket
702 * Get the length field of @packet. This is the length of the packet in
703 * 32-bit words minus one.
705 * Returns: The length field of @packet.
708 gst_rtcp_packet_get_length (GstRTCPPacket * packet)
710 g_return_val_if_fail (packet != NULL, 0);
711 g_return_val_if_fail (packet->type != GST_RTCP_TYPE_INVALID, 0);
713 return packet->length;
717 * gst_rtcp_packet_sr_get_sender_info:
718 * @packet: a valid SR #GstRTCPPacket
719 * @ssrc: (out): result SSRC
720 * @ntptime: (out): result NTP time
721 * @rtptime: (out): result RTP time
722 * @packet_count: (out): result packet count
723 * @octet_count: (out): result octet count
725 * Parse the SR sender info and store the values.
728 gst_rtcp_packet_sr_get_sender_info (GstRTCPPacket * packet, guint32 * ssrc,
729 guint64 * ntptime, guint32 * rtptime, guint32 * packet_count,
730 guint32 * octet_count)
734 g_return_if_fail (packet != NULL);
735 g_return_if_fail (packet->type == GST_RTCP_TYPE_SR);
736 g_return_if_fail (packet->rtcp != NULL);
737 g_return_if_fail (packet->rtcp->map.flags & GST_MAP_READ);
739 data = packet->rtcp->map.data;
742 data += packet->offset + 4;
744 *ssrc = GST_READ_UINT32_BE (data);
747 *ntptime = GST_READ_UINT64_BE (data);
750 *rtptime = GST_READ_UINT32_BE (data);
753 *packet_count = GST_READ_UINT32_BE (data);
756 *octet_count = GST_READ_UINT32_BE (data);
760 * gst_rtcp_packet_sr_set_sender_info:
761 * @packet: a valid SR #GstRTCPPacket
763 * @ntptime: the NTP time
764 * @rtptime: the RTP time
765 * @packet_count: the packet count
766 * @octet_count: the octet count
768 * Set the given values in the SR packet @packet.
771 gst_rtcp_packet_sr_set_sender_info (GstRTCPPacket * packet, guint32 ssrc,
772 guint64 ntptime, guint32 rtptime, guint32 packet_count, guint32 octet_count)
776 g_return_if_fail (packet != NULL);
777 g_return_if_fail (packet->type == GST_RTCP_TYPE_SR);
778 g_return_if_fail (packet->rtcp != NULL);
779 g_return_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE);
781 data = packet->rtcp->map.data;
784 data += packet->offset + 4;
785 GST_WRITE_UINT32_BE (data, ssrc);
787 GST_WRITE_UINT64_BE (data, ntptime);
789 GST_WRITE_UINT32_BE (data, rtptime);
791 GST_WRITE_UINT32_BE (data, packet_count);
793 GST_WRITE_UINT32_BE (data, octet_count);
797 * gst_rtcp_packet_rr_get_ssrc:
798 * @packet: a valid RR #GstRTCPPacket
800 * Get the ssrc field of the RR @packet.
805 gst_rtcp_packet_rr_get_ssrc (GstRTCPPacket * packet)
810 g_return_val_if_fail (packet != NULL, 0);
811 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_RR, 0);
812 g_return_val_if_fail (packet->rtcp != NULL, 0);
813 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, 0);
815 data = packet->rtcp->map.data;
818 data += packet->offset + 4;
819 ssrc = GST_READ_UINT32_BE (data);
825 * gst_rtcp_packet_rr_set_ssrc:
826 * @packet: a valid RR #GstRTCPPacket
827 * @ssrc: the SSRC to set
829 * Set the ssrc field of the RR @packet.
832 gst_rtcp_packet_rr_set_ssrc (GstRTCPPacket * packet, guint32 ssrc)
836 g_return_if_fail (packet != NULL);
837 g_return_if_fail (packet->type == GST_RTCP_TYPE_RR);
838 g_return_if_fail (packet->rtcp != NULL);
839 g_return_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE);
841 data = packet->rtcp->map.data;
844 data += packet->offset + 4;
845 GST_WRITE_UINT32_BE (data, ssrc);
849 * gst_rtcp_packet_get_rb_count:
850 * @packet: a valid SR or RR #GstRTCPPacket
852 * Get the number of report blocks in @packet.
854 * Returns: The number of report blocks in @packet.
857 gst_rtcp_packet_get_rb_count (GstRTCPPacket * packet)
859 g_return_val_if_fail (packet != NULL, 0);
860 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_RR ||
861 packet->type == GST_RTCP_TYPE_SR, 0);
862 g_return_val_if_fail (packet->rtcp != NULL, 0);
863 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, 0);
865 return packet->count;
869 * gst_rtcp_packet_get_rb:
870 * @packet: a valid SR or RR #GstRTCPPacket
871 * @nth: the nth report block in @packet
872 * @ssrc: (out): result for data source being reported
873 * @fractionlost: (out): result for fraction lost since last SR/RR
874 * @packetslost: (out): result for the cumululative number of packets lost
875 * @exthighestseq: (out): result for the extended last sequence number received
876 * @jitter: (out): result for the interarrival jitter
877 * @lsr: (out): result for the last SR packet from this source
878 * @dlsr: (out): result for the delay since last SR packet
880 * Parse the values of the @nth report block in @packet and store the result in
884 gst_rtcp_packet_get_rb (GstRTCPPacket * packet, guint nth, guint32 * ssrc,
885 guint8 * fractionlost, gint32 * packetslost, guint32 * exthighestseq,
886 guint32 * jitter, guint32 * lsr, guint32 * dlsr)
892 g_return_if_fail (packet != NULL);
893 g_return_if_fail (packet->type == GST_RTCP_TYPE_RR ||
894 packet->type == GST_RTCP_TYPE_SR);
895 g_return_if_fail (packet->rtcp != NULL);
896 g_return_if_fail (packet->rtcp->map.flags & GST_MAP_READ);
897 g_return_if_fail (nth < packet->count);
899 /* get offset in 32-bits words into packet, skip the header */
900 if (packet->type == GST_RTCP_TYPE_RR)
905 /* move to requested index */
908 /* check that we don't go past the packet length */
909 if (offset > packet->length)
914 offset += packet->offset;
916 /* check if the packet is valid */
917 if (offset + 24 > packet->rtcp->map.size)
920 data = packet->rtcp->map.data;
924 *ssrc = GST_READ_UINT32_BE (data);
926 tmp = GST_READ_UINT32_BE (data);
928 *fractionlost = (tmp >> 24);
931 if (tmp & 0x00800000)
935 *packetslost = (gint32) tmp;
939 *exthighestseq = GST_READ_UINT32_BE (data);
942 *jitter = GST_READ_UINT32_BE (data);
945 *lsr = GST_READ_UINT32_BE (data);
948 *dlsr = GST_READ_UINT32_BE (data);
952 * gst_rtcp_packet_add_rb:
953 * @packet: a valid SR or RR #GstRTCPPacket
954 * @ssrc: data source being reported
955 * @fractionlost: fraction lost since last SR/RR
956 * @packetslost: the cumululative number of packets lost
957 * @exthighestseq: the extended last sequence number received
958 * @jitter: the interarrival jitter
959 * @lsr: the last SR packet from this source
960 * @dlsr: the delay since last SR packet
962 * Add a new report block to @packet with the given values.
964 * Returns: %TRUE if the packet was created. This function can return %FALSE if
965 * the max MTU is exceeded or the number of report blocks is greater than
966 * #GST_RTCP_MAX_RB_COUNT.
969 gst_rtcp_packet_add_rb (GstRTCPPacket * packet, guint32 ssrc,
970 guint8 fractionlost, gint32 packetslost, guint32 exthighestseq,
971 guint32 jitter, guint32 lsr, guint32 dlsr)
974 guint maxsize, offset;
976 g_return_val_if_fail (packet != NULL, FALSE);
977 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_RR ||
978 packet->type == GST_RTCP_TYPE_SR, FALSE);
979 g_return_val_if_fail (packet->rtcp != NULL, FALSE);
980 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE, FALSE);
981 /* if profile-specific extension is added, fail for now!? */
982 g_return_val_if_fail (gst_rtcp_packet_get_profile_specific_ext_length (packet)
985 if (packet->count >= GST_RTCP_MAX_RB_COUNT)
988 data = packet->rtcp->map.data;
989 maxsize = packet->rtcp->map.maxsize;
992 offset = packet->offset + 4;
993 if (packet->type == GST_RTCP_TYPE_RR)
998 /* move to current index */
999 offset += (packet->count * 24);
1001 /* we need 24 free bytes now */
1002 if (offset + 24 >= maxsize)
1005 /* increment packet count and length */
1007 data[packet->offset]++;
1008 packet->length += 6;
1009 data[packet->offset + 2] = (packet->length) >> 8;
1010 data[packet->offset + 3] = (packet->length) & 0xff;
1011 packet->rtcp->map.size += 6 * 4;
1013 /* move to new report block offset */
1016 GST_WRITE_UINT32_BE (data, ssrc);
1018 GST_WRITE_UINT32_BE (data,
1019 ((guint32) fractionlost << 24) | (packetslost & 0xffffff));
1021 GST_WRITE_UINT32_BE (data, exthighestseq);
1023 GST_WRITE_UINT32_BE (data, jitter);
1025 GST_WRITE_UINT32_BE (data, lsr);
1027 GST_WRITE_UINT32_BE (data, dlsr);
1038 * gst_rtcp_packet_set_rb:
1039 * @packet: a valid SR or RR #GstRTCPPacket
1040 * @nth: the nth report block to set
1041 * @ssrc: data source being reported
1042 * @fractionlost: fraction lost since last SR/RR
1043 * @packetslost: the cumululative number of packets lost
1044 * @exthighestseq: the extended last sequence number received
1045 * @jitter: the interarrival jitter
1046 * @lsr: the last SR packet from this source
1047 * @dlsr: the delay since last SR packet
1049 * Set the @nth new report block in @packet with the given values.
1051 * Note: Not implemented.
1054 gst_rtcp_packet_set_rb (GstRTCPPacket * packet, guint nth, guint32 ssrc,
1055 guint8 fractionlost, gint32 packetslost, guint32 exthighestseq,
1056 guint32 jitter, guint32 lsr, guint32 dlsr)
1058 g_return_if_fail (packet != NULL);
1059 g_return_if_fail (packet->type == GST_RTCP_TYPE_RR ||
1060 packet->type == GST_RTCP_TYPE_SR);
1061 g_return_if_fail (packet->rtcp != NULL);
1062 g_return_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE);
1064 g_warning ("not implemented");
1069 * gst_rtcp_packet_add_profile_specific_ext:
1070 * @packet: a valid SR or RR #GstRTCPPacket
1071 * @data: (array length=len) (transfer none): profile-specific data
1072 * @len: length of the profile-specific data in bytes
1074 * Add profile-specific extension @data to @packet. If @packet already
1075 * contains profile-specific extension @data will be appended to the existing
1078 * Returns: %TRUE if the profile specific extension data was added.
1083 gst_rtcp_packet_add_profile_specific_ext (GstRTCPPacket * packet,
1084 const guint8 * data, guint len)
1087 guint maxsize, offset;
1089 g_return_val_if_fail (packet != NULL, FALSE);
1090 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_RR ||
1091 packet->type == GST_RTCP_TYPE_SR, FALSE);
1092 g_return_val_if_fail (packet->rtcp != NULL, FALSE);
1093 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE, FALSE);
1094 g_return_val_if_fail ((len & 0x03) == 0, FALSE);
1096 bdata = packet->rtcp->map.data;
1097 maxsize = packet->rtcp->map.maxsize;
1099 /* skip to the end of the packet */
1100 offset = packet->offset + (packet->length << 2) + 4;
1102 /* we need 'len' free bytes now */
1103 if (G_UNLIKELY (offset + len > maxsize))
1106 memcpy (&bdata[offset], data, len);
1107 packet->length += len >> 2;
1108 bdata[packet->offset + 2] = (packet->length) >> 8;
1109 bdata[packet->offset + 3] = (packet->length) & 0xff;
1110 packet->rtcp->map.size += len;
1116 * gst_rtcp_packet_get_profile_specific_ext_length:
1117 * @packet: a valid SR or RR #GstRTCPPacket
1119 * Returns: The number of 32-bit words containing profile-specific extension
1120 * data from @packet.
1125 gst_rtcp_packet_get_profile_specific_ext_length (GstRTCPPacket * packet)
1127 guint pse_offset = 2;
1129 g_return_val_if_fail (packet != NULL, 0);
1130 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_RR ||
1131 packet->type == GST_RTCP_TYPE_SR, 0);
1132 g_return_val_if_fail (packet->rtcp != NULL, 0);
1133 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, 0);
1135 if (packet->type == GST_RTCP_TYPE_SR)
1137 pse_offset += (packet->count * 6);
1139 if (pse_offset <= (packet->length + 1))
1140 return packet->length + 1 - pse_offset;
1142 /* This means that the packet is invalid! */
1147 * gst_rtcp_packet_get_profile_specific_ext:
1148 * @packet: a valid SR or RR #GstRTCPPacket
1149 * @data: (out) (array length=len) (transfer none): result profile-specific data
1150 * @len: (out): result length of the profile-specific data
1152 * Returns: %TRUE if there was valid data.
1157 gst_rtcp_packet_get_profile_specific_ext (GstRTCPPacket * packet,
1158 guint8 ** data, guint * len)
1162 g_return_val_if_fail (packet != NULL, FALSE);
1163 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_RR ||
1164 packet->type == GST_RTCP_TYPE_SR, FALSE);
1165 g_return_val_if_fail (packet->rtcp != NULL, FALSE);
1166 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, FALSE);
1168 pse_len = gst_rtcp_packet_get_profile_specific_ext_length (packet);
1171 *len = pse_len * sizeof (guint32);
1173 *data = packet->rtcp->map.data;
1174 *data += packet->offset;
1175 *data += ((packet->length + 1 - pse_len) * sizeof (guint32));
1185 * gst_rtcp_packet_copy_profile_specific_ext:
1186 * @packet: a valid SR or RR #GstRTCPPacket
1187 * @data: (out) (array length=len): result profile-specific data
1188 * @len: (out): length of the profile-specific extension data
1190 * The profile-specific extension data is copied into a new allocated
1191 * memory area @data. This must be freed with g_free() after usage.
1193 * Returns: %TRUE if there was valid data.
1198 gst_rtcp_packet_copy_profile_specific_ext (GstRTCPPacket * packet,
1199 guint8 ** data, guint * len)
1203 g_return_val_if_fail (packet != NULL, FALSE);
1204 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_RR ||
1205 packet->type == GST_RTCP_TYPE_SR, FALSE);
1206 g_return_val_if_fail (packet->rtcp != NULL, FALSE);
1207 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, FALSE);
1209 pse_len = gst_rtcp_packet_get_profile_specific_ext_length (packet);
1212 *len = pse_len * sizeof (guint32);
1214 guint8 *ptr = packet->rtcp->map.data + packet->offset;
1215 ptr += ((packet->length + 1 - pse_len) * sizeof (guint32));
1216 *data = g_memdup2 (ptr, pse_len * sizeof (guint32));
1227 * gst_rtcp_packet_sdes_get_item_count:
1228 * @packet: a valid SDES #GstRTCPPacket
1230 * Get the number of items in the SDES packet @packet.
1232 * Returns: The number of items in @packet.
1235 gst_rtcp_packet_sdes_get_item_count (GstRTCPPacket * packet)
1237 g_return_val_if_fail (packet != NULL, 0);
1238 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, 0);
1240 return packet->count;
1244 * gst_rtcp_packet_sdes_first_item:
1245 * @packet: a valid SDES #GstRTCPPacket
1247 * Move to the first SDES item in @packet.
1249 * Returns: TRUE if there was a first item.
1252 gst_rtcp_packet_sdes_first_item (GstRTCPPacket * packet)
1254 g_return_val_if_fail (packet != NULL, FALSE);
1255 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, FALSE);
1257 packet->item_offset = 4;
1258 packet->item_count = 0;
1259 packet->entry_offset = 4;
1261 if (packet->count == 0)
1268 * gst_rtcp_packet_sdes_next_item:
1269 * @packet: a valid SDES #GstRTCPPacket
1271 * Move to the next SDES item in @packet.
1273 * Returns: TRUE if there was a next item.
1276 gst_rtcp_packet_sdes_next_item (GstRTCPPacket * packet)
1282 g_return_val_if_fail (packet != NULL, FALSE);
1283 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, FALSE);
1284 g_return_val_if_fail (packet->rtcp != NULL, FALSE);
1285 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, FALSE);
1287 /* if we are at the last item, we are done */
1288 if (packet->item_count == packet->count)
1292 data = packet->rtcp->map.data;
1293 data += packet->offset;
1295 offset = packet->item_offset;
1300 len = (packet->length << 2);
1302 while (offset < len) {
1303 if (data[offset] == 0) {
1304 /* end of list, round to next 32-bit word */
1305 offset = (offset + 4) & ~3;
1308 offset += data[offset + 1] + 2;
1313 packet->item_offset = offset;
1314 packet->item_count++;
1315 packet->entry_offset = 4;
1321 * gst_rtcp_packet_sdes_get_ssrc:
1322 * @packet: a valid SDES #GstRTCPPacket
1324 * Get the SSRC of the current SDES item.
1326 * Returns: the SSRC of the current item.
1329 gst_rtcp_packet_sdes_get_ssrc (GstRTCPPacket * packet)
1334 g_return_val_if_fail (packet != NULL, 0);
1335 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, 0);
1336 g_return_val_if_fail (packet->rtcp != NULL, 0);
1337 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, 0);
1340 data = packet->rtcp->map.data;
1341 data += packet->offset;
1343 data += packet->item_offset;
1345 ssrc = GST_READ_UINT32_BE (data);
1351 * gst_rtcp_packet_sdes_first_entry:
1352 * @packet: a valid SDES #GstRTCPPacket
1354 * Move to the first SDES entry in the current item.
1356 * Returns: %TRUE if there was a first entry.
1359 gst_rtcp_packet_sdes_first_entry (GstRTCPPacket * packet)
1364 g_return_val_if_fail (packet != NULL, FALSE);
1365 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, FALSE);
1366 g_return_val_if_fail (packet->rtcp != NULL, FALSE);
1367 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, FALSE);
1370 data = packet->rtcp->map.data;
1371 data += packet->offset;
1373 offset = packet->item_offset;
1377 packet->entry_offset = 4;
1380 len = (packet->length << 2);
1384 if (data[offset] == 0)
1391 * gst_rtcp_packet_sdes_next_entry:
1392 * @packet: a valid SDES #GstRTCPPacket
1394 * Move to the next SDES entry in the current item.
1396 * Returns: %TRUE if there was a next entry.
1399 gst_rtcp_packet_sdes_next_entry (GstRTCPPacket * packet)
1402 guint len, offset, item_len;
1404 g_return_val_if_fail (packet != NULL, FALSE);
1405 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, FALSE);
1406 g_return_val_if_fail (packet->rtcp != NULL, FALSE);
1407 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, FALSE);
1410 data = packet->rtcp->map.data;
1411 data += packet->offset;
1413 offset = packet->item_offset;
1415 offset += packet->entry_offset;
1417 item_len = data[offset + 1] + 2;
1422 len = (packet->length << 2);
1426 packet->entry_offset += item_len;
1428 /* check for end of list */
1429 if (data[offset] == 0)
1436 * gst_rtcp_packet_sdes_get_entry:
1437 * @packet: a valid SDES #GstRTCPPacket
1438 * @type: result of the entry type
1439 * @len: (out): result length of the entry data
1440 * @data: (out) (array length=len) (transfer none): result entry data
1442 * Get the data of the current SDES item entry. @type (when not NULL) will
1443 * contain the type of the entry. @data (when not NULL) will point to @len
1446 * When @type refers to a text item, @data will point to a UTF8 string. Note
1447 * that this UTF8 string is NOT null-terminated. Use
1448 * gst_rtcp_packet_sdes_copy_entry() to get a null-terminated copy of the entry.
1450 * Returns: %TRUE if there was valid data.
1453 gst_rtcp_packet_sdes_get_entry (GstRTCPPacket * packet,
1454 GstRTCPSDESType * type, guint8 * len, guint8 ** data)
1459 g_return_val_if_fail (packet != NULL, FALSE);
1460 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, FALSE);
1461 g_return_val_if_fail (packet->rtcp != NULL, FALSE);
1462 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, FALSE);
1465 bdata = packet->rtcp->map.data;
1466 bdata += packet->offset;
1468 offset = packet->item_offset;
1470 offset += packet->entry_offset;
1472 if (bdata[offset] == 0)
1476 *type = bdata[offset];
1478 *len = bdata[offset + 1];
1480 *data = &bdata[offset + 2];
1486 * gst_rtcp_packet_sdes_copy_entry:
1487 * @packet: a valid SDES #GstRTCPPacket
1488 * @type: result of the entry type
1489 * @len: (out): result length of the entry data
1490 * @data: (out) (array length=len): result entry data
1492 * This function is like gst_rtcp_packet_sdes_get_entry() but it returns a
1493 * null-terminated copy of the data instead. use g_free() after usage.
1495 * Returns: %TRUE if there was valid data.
1498 gst_rtcp_packet_sdes_copy_entry (GstRTCPPacket * packet,
1499 GstRTCPSDESType * type, guint8 * len, guint8 ** data)
1504 g_return_val_if_fail (packet != NULL, FALSE);
1505 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, FALSE);
1506 g_return_val_if_fail (packet->rtcp != NULL, FALSE);
1507 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, FALSE);
1509 if (!gst_rtcp_packet_sdes_get_entry (packet, type, &tlen, &tdata))
1515 *data = (guint8 *) g_strndup ((gchar *) tdata, tlen);
1521 * gst_rtcp_packet_sdes_add_item:
1522 * @packet: a valid SDES #GstRTCPPacket
1523 * @ssrc: the SSRC of the new item to add
1525 * Add a new SDES item for @ssrc to @packet.
1527 * Returns: %TRUE if the item could be added, %FALSE if the maximum amount of
1528 * items has been exceeded for the SDES packet or the MTU has been reached.
1531 gst_rtcp_packet_sdes_add_item (GstRTCPPacket * packet, guint32 ssrc)
1537 g_return_val_if_fail (packet != NULL, FALSE);
1538 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, FALSE);
1539 g_return_val_if_fail (packet->rtcp != NULL, FALSE);
1540 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE, FALSE);
1542 /* increment item count when possible */
1543 if (packet->count >= GST_RTCP_MAX_SDES_ITEM_COUNT)
1546 /* pretend there is a next packet for the next call */
1549 /* jump over current item */
1550 gst_rtcp_packet_sdes_next_item (packet);
1553 data = packet->rtcp->map.data;
1554 maxsize = packet->rtcp->map.maxsize;
1555 data += packet->offset;
1556 /* move to current item */
1557 offset = packet->item_offset;
1559 /* we need 2 free words now */
1560 if (offset + 8 >= maxsize)
1564 GST_WRITE_UINT32_BE (&data[offset], ssrc);
1565 /* write 0 entry with padding */
1566 GST_WRITE_UINT32_BE (&data[offset + 4], 0);
1569 data[0] = (data[0] & 0xe0) | packet->count;
1570 /* update length, we added 2 words */
1571 packet->length += 2;
1572 data[2] = (packet->length) >> 8;
1573 data[3] = (packet->length) & 0xff;
1575 packet->rtcp->map.size += 8;
1592 * gst_rtcp_packet_sdes_add_entry:
1593 * @packet: a valid SDES #GstRTCPPacket
1594 * @type: the #GstRTCPSDESType of the SDES entry
1595 * @len: the data length
1596 * @data: (array length=len): the data
1598 * Add a new SDES entry to the current item in @packet.
1600 * Returns: %TRUE if the item could be added, %FALSE if the MTU has been
1604 gst_rtcp_packet_sdes_add_entry (GstRTCPPacket * packet, GstRTCPSDESType type,
1605 guint8 len, const guint8 * data)
1608 guint offset, padded;
1611 g_return_val_if_fail (packet != NULL, FALSE);
1612 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, FALSE);
1613 g_return_val_if_fail (packet->rtcp != NULL, FALSE);
1614 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE, FALSE);
1617 bdata = packet->rtcp->map.data;
1618 maxsize = packet->rtcp->map.maxsize;
1619 bdata += packet->offset;
1621 offset = packet->item_offset;
1623 offset += packet->entry_offset;
1625 /* add 1 byte end and up to 3 bytes padding to fill a full 32 bit word */
1626 padded = (offset + 2 + len + 1 + 3) & ~3;
1628 /* we need enough space for type, len, data and padding */
1629 if (packet->offset + padded >= maxsize)
1632 packet->rtcp->map.size = packet->offset + padded;
1634 bdata[offset] = type;
1635 bdata[offset + 1] = len;
1636 memcpy (&bdata[offset + 2], data, len);
1637 bdata[offset + 2 + len] = 0;
1639 /* calculate new packet length */
1640 packet->length = (padded - 4) >> 2;
1641 bdata[2] = (packet->length) >> 8;
1642 bdata[3] = (packet->length) & 0xff;
1644 /* position to new next entry */
1645 packet->entry_offset += 2 + len;
1657 * gst_rtcp_packet_bye_get_ssrc_count:
1658 * @packet: a valid BYE #GstRTCPPacket
1660 * Get the number of SSRC fields in @packet.
1662 * Returns: The number of SSRC fields in @packet.
1665 gst_rtcp_packet_bye_get_ssrc_count (GstRTCPPacket * packet)
1667 g_return_val_if_fail (packet != NULL, -1);
1668 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_BYE, -1);
1670 return packet->count;
1674 * gst_rtcp_packet_bye_get_nth_ssrc:
1675 * @packet: a valid BYE #GstRTCPPacket
1676 * @nth: the nth SSRC to get
1678 * Get the @nth SSRC of the BYE @packet.
1680 * Returns: The @nth SSRC of @packet.
1683 gst_rtcp_packet_bye_get_nth_ssrc (GstRTCPPacket * packet, guint nth)
1689 g_return_val_if_fail (packet != NULL, 0);
1690 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_BYE, 0);
1691 g_return_val_if_fail (packet->rtcp != NULL, 0);
1692 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, 0);
1693 g_return_val_if_fail (nth < packet->count, 0);
1695 /* get offset in 32-bits words into packet, skip the header */
1697 /* check that we don't go past the packet length */
1698 if (offset > packet->length)
1701 /* scale to bytes */
1703 offset += packet->offset;
1705 /* check if the packet is valid */
1706 if (offset + 4 > packet->rtcp->map.size)
1709 data = packet->rtcp->map.data;
1712 ssrc = GST_READ_UINT32_BE (data);
1718 * gst_rtcp_packet_bye_add_ssrc:
1719 * @packet: a valid BYE #GstRTCPPacket
1720 * @ssrc: an SSRC to add
1722 * Add @ssrc to the BYE @packet.
1724 * Returns: %TRUE if the ssrc was added. This function can return %FALSE if
1725 * the max MTU is exceeded or the number of sources blocks is greater than
1726 * #GST_RTCP_MAX_BYE_SSRC_COUNT.
1729 gst_rtcp_packet_bye_add_ssrc (GstRTCPPacket * packet, guint32 ssrc)
1735 g_return_val_if_fail (packet != NULL, FALSE);
1736 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_BYE, FALSE);
1737 g_return_val_if_fail (packet->rtcp != NULL, FALSE);
1738 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE, FALSE);
1740 if (packet->count >= GST_RTCP_MAX_BYE_SSRC_COUNT)
1743 data = packet->rtcp->map.data;
1744 maxsize = packet->rtcp->map.maxsize;
1747 offset = packet->offset + 4;
1749 /* move to current index */
1750 offset += (packet->count * 4);
1752 if (offset + 4 >= maxsize)
1755 /* increment packet count and length */
1757 data[packet->offset]++;
1758 packet->length += 1;
1759 data[packet->offset + 2] = (packet->length) >> 8;
1760 data[packet->offset + 3] = (packet->length) & 0xff;
1762 packet->rtcp->map.size += 4;
1764 /* move to new SSRC offset and write ssrc */
1766 GST_WRITE_UINT32_BE (data, ssrc);
1778 * gst_rtcp_packet_bye_add_ssrcs:
1779 * @packet: a valid BYE #GstRTCPPacket
1780 * @ssrc: (array length=len) (transfer none): an array of SSRCs to add
1781 * @len: number of elements in @ssrc
1783 * Adds @len SSRCs in @ssrc to BYE @packet.
1785 * Returns: %TRUE if the all the SSRCs were added. This function can return %FALSE if
1786 * the max MTU is exceeded or the number of sources blocks is greater than
1787 * #GST_RTCP_MAX_BYE_SSRC_COUNT.
1790 gst_rtcp_packet_bye_add_ssrcs (GstRTCPPacket * packet, guint32 * ssrc,
1796 g_return_val_if_fail (packet != NULL, FALSE);
1797 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_BYE, FALSE);
1798 g_return_val_if_fail (packet->rtcp != NULL, FALSE);
1799 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE, FALSE);
1802 for (i = 0; i < len && res; i++) {
1803 res = gst_rtcp_packet_bye_add_ssrc (packet, ssrc[i]);
1808 /* get the offset in packet of the reason length */
1810 get_reason_offset (GstRTCPPacket * packet)
1814 /* get amount of sources plus header */
1815 offset = 1 + packet->count;
1817 /* check that we don't go past the packet length */
1818 if (offset > packet->length)
1821 /* scale to bytes */
1823 offset += packet->offset;
1825 /* check if the packet is valid */
1826 if (offset + 1 > packet->rtcp->map.size)
1833 * gst_rtcp_packet_bye_get_reason_len:
1834 * @packet: a valid BYE #GstRTCPPacket
1836 * Get the length of the reason string.
1838 * Returns: The length of the reason string or 0 when there is no reason string
1842 gst_rtcp_packet_bye_get_reason_len (GstRTCPPacket * packet)
1847 g_return_val_if_fail (packet != NULL, 0);
1848 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_BYE, 0);
1849 g_return_val_if_fail (packet->rtcp != NULL, 0);
1850 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, 0);
1852 roffset = get_reason_offset (packet);
1856 data = packet->rtcp->map.data;
1858 return data[roffset];
1862 * gst_rtcp_packet_bye_get_reason:
1863 * @packet: a valid BYE #GstRTCPPacket
1865 * Get the reason in @packet.
1867 * Returns: The reason for the BYE @packet or NULL if the packet did not contain
1868 * a reason string. The string must be freed with g_free() after usage.
1871 gst_rtcp_packet_bye_get_reason (GstRTCPPacket * packet)
1877 g_return_val_if_fail (packet != NULL, NULL);
1878 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_BYE, NULL);
1879 g_return_val_if_fail (packet->rtcp != NULL, NULL);
1880 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, NULL);
1882 roffset = get_reason_offset (packet);
1886 data = packet->rtcp->map.data;
1888 /* get length of reason string */
1889 len = data[roffset];
1893 /* move to string */
1896 /* check if enough data to copy */
1897 if (roffset + len > packet->rtcp->map.size)
1900 return g_strndup ((gconstpointer) (data + roffset), len);
1904 * gst_rtcp_packet_bye_set_reason:
1905 * @packet: a valid BYE #GstRTCPPacket
1906 * @reason: a reason string
1908 * Set the reason string to @reason in @packet.
1910 * Returns: TRUE if the string could be set.
1913 gst_rtcp_packet_bye_set_reason (GstRTCPPacket * packet, const gchar * reason)
1920 g_return_val_if_fail (packet != NULL, FALSE);
1921 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_BYE, FALSE);
1922 g_return_val_if_fail (packet->rtcp != NULL, FALSE);
1923 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE, FALSE);
1928 len = strlen (reason);
1932 /* make room for the string before we get the offset */
1935 roffset = get_reason_offset (packet);
1939 data = packet->rtcp->map.data;
1940 maxsize = packet->rtcp->map.maxsize;
1942 /* we have 1 byte length and we need to pad to 4 bytes */
1943 padded = ((len + 1) + 3) & ~3;
1945 /* we need enough space for the padded length */
1946 if (roffset + padded >= maxsize)
1949 data[roffset] = len;
1950 memcpy (&data[roffset + 1], reason, len);
1952 /* update packet length, we made room for 1 double word already */
1953 packet->length += (padded >> 2) - 1;
1954 data[packet->offset + 2] = (packet->length) >> 8;
1955 data[packet->offset + 3] = (packet->length) & 0xff;
1957 packet->rtcp->map.size += padded;
1970 * gst_rtcp_packet_fb_get_sender_ssrc:
1971 * @packet: a valid RTPFB or PSFB #GstRTCPPacket
1973 * Get the sender SSRC field of the RTPFB or PSFB @packet.
1975 * Returns: the sender SSRC.
1978 gst_rtcp_packet_fb_get_sender_ssrc (GstRTCPPacket * packet)
1983 g_return_val_if_fail (packet != NULL, 0);
1984 g_return_val_if_fail ((packet->type == GST_RTCP_TYPE_RTPFB ||
1985 packet->type == GST_RTCP_TYPE_PSFB), 0);
1986 g_return_val_if_fail (packet->rtcp != NULL, 0);
1987 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, 0);
1989 data = packet->rtcp->map.data;
1992 data += packet->offset + 4;
1993 ssrc = GST_READ_UINT32_BE (data);
1999 * gst_rtcp_packet_fb_set_sender_ssrc:
2000 * @packet: a valid RTPFB or PSFB #GstRTCPPacket
2001 * @ssrc: a sender SSRC
2003 * Set the sender SSRC field of the RTPFB or PSFB @packet.
2006 gst_rtcp_packet_fb_set_sender_ssrc (GstRTCPPacket * packet, guint32 ssrc)
2010 g_return_if_fail (packet != NULL);
2011 g_return_if_fail (packet->type == GST_RTCP_TYPE_RTPFB ||
2012 packet->type == GST_RTCP_TYPE_PSFB);
2013 g_return_if_fail (packet->rtcp != NULL);
2014 g_return_if_fail (packet->rtcp->map.flags & GST_MAP_READ);
2016 data = packet->rtcp->map.data;
2019 data += packet->offset + 4;
2020 GST_WRITE_UINT32_BE (data, ssrc);
2024 * gst_rtcp_packet_fb_get_media_ssrc:
2025 * @packet: a valid RTPFB or PSFB #GstRTCPPacket
2027 * Get the media SSRC field of the RTPFB or PSFB @packet.
2029 * Returns: the media SSRC.
2032 gst_rtcp_packet_fb_get_media_ssrc (GstRTCPPacket * packet)
2037 g_return_val_if_fail (packet != NULL, 0);
2038 g_return_val_if_fail ((packet->type == GST_RTCP_TYPE_RTPFB ||
2039 packet->type == GST_RTCP_TYPE_PSFB), 0);
2040 g_return_val_if_fail (packet->rtcp != NULL, 0);
2041 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, 0);
2043 data = packet->rtcp->map.data;
2045 /* skip header and sender ssrc */
2046 data += packet->offset + 8;
2047 ssrc = GST_READ_UINT32_BE (data);
2053 * gst_rtcp_packet_fb_set_media_ssrc:
2054 * @packet: a valid RTPFB or PSFB #GstRTCPPacket
2055 * @ssrc: a media SSRC
2057 * Set the media SSRC field of the RTPFB or PSFB @packet.
2060 gst_rtcp_packet_fb_set_media_ssrc (GstRTCPPacket * packet, guint32 ssrc)
2064 g_return_if_fail (packet != NULL);
2065 g_return_if_fail (packet->type == GST_RTCP_TYPE_RTPFB ||
2066 packet->type == GST_RTCP_TYPE_PSFB);
2067 g_return_if_fail (packet->rtcp != NULL);
2068 g_return_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE);
2070 data = packet->rtcp->map.data;
2072 /* skip header and sender ssrc */
2073 data += packet->offset + 8;
2074 GST_WRITE_UINT32_BE (data, ssrc);
2078 * gst_rtcp_packet_fb_get_type:
2079 * @packet: a valid RTPFB or PSFB #GstRTCPPacket
2081 * Get the feedback message type of the FB @packet.
2083 * Returns: The feedback message type.
2086 gst_rtcp_packet_fb_get_type (GstRTCPPacket * packet)
2088 g_return_val_if_fail (packet != NULL, GST_RTCP_FB_TYPE_INVALID);
2089 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_RTPFB ||
2090 packet->type == GST_RTCP_TYPE_PSFB, GST_RTCP_FB_TYPE_INVALID);
2092 return packet->count;
2096 * gst_rtcp_packet_fb_set_type:
2097 * @packet: a valid RTPFB or PSFB #GstRTCPPacket
2098 * @type: the #GstRTCPFBType to set
2100 * Set the feedback message type of the FB @packet.
2103 gst_rtcp_packet_fb_set_type (GstRTCPPacket * packet, GstRTCPFBType type)
2107 g_return_if_fail (packet != NULL);
2108 g_return_if_fail (packet->type == GST_RTCP_TYPE_RTPFB ||
2109 packet->type == GST_RTCP_TYPE_PSFB);
2110 g_return_if_fail (packet->rtcp != NULL);
2111 g_return_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE);
2113 data = packet->rtcp->map.data;
2115 data[packet->offset] = (data[packet->offset] & 0xe0) | type;
2116 packet->count = type;
2120 * gst_rtcp_ntp_to_unix:
2121 * @ntptime: an NTP timestamp
2123 * Converts an NTP time to UNIX nanoseconds. @ntptime can typically be
2124 * the NTP time of an SR RTCP message and contains, in the upper 32 bits, the
2125 * number of seconds since 1900 and, in the lower 32 bits, the fractional
2126 * seconds. The resulting value will be the number of nanoseconds since 1970.
2128 * Returns: the UNIX time for @ntptime in nanoseconds.
2131 gst_rtcp_ntp_to_unix (guint64 ntptime)
2135 /* conversion from NTP timestamp (seconds since 1900) to seconds since
2137 unixtime = ntptime - (G_GUINT64_CONSTANT (2208988800) << 32);
2138 /* conversion to nanoseconds */
2140 gst_util_uint64_scale (unixtime, GST_SECOND,
2141 (G_GINT64_CONSTANT (1) << 32));
2147 * gst_rtcp_unix_to_ntp:
2148 * @unixtime: an UNIX timestamp in nanoseconds
2150 * Converts a UNIX timestamp in nanoseconds to an NTP time. The caller should
2151 * pass a value with nanoseconds since 1970. The NTP time will, in the upper
2152 * 32 bits, contain the number of seconds since 1900 and, in the lower 32
2153 * bits, the fractional seconds. The resulting value can be used as an ntptime
2154 * for constructing SR RTCP packets.
2156 * Returns: the NTP time for @unixtime.
2159 gst_rtcp_unix_to_ntp (guint64 unixtime)
2163 /* convert clock time to NTP time. upper 32 bits should contain the seconds
2164 * and the lower 32 bits, the fractions of a second. */
2166 gst_util_uint64_scale (unixtime, (G_GINT64_CONSTANT (1) << 32),
2168 /* conversion from UNIX timestamp (seconds since 1970) to NTP (seconds
2170 ntptime += (G_GUINT64_CONSTANT (2208988800) << 32);
2176 * gst_rtcp_sdes_type_to_name:
2177 * @type: a #GstRTCPSDESType
2179 * Converts @type to the string equivalent. The string is typically used as a
2180 * key in a #GstStructure containing SDES items.
2182 * Returns: the string equivalent of @type
2185 gst_rtcp_sdes_type_to_name (GstRTCPSDESType type)
2187 const gchar *result;
2190 case GST_RTCP_SDES_CNAME:
2193 case GST_RTCP_SDES_NAME:
2196 case GST_RTCP_SDES_EMAIL:
2199 case GST_RTCP_SDES_PHONE:
2202 case GST_RTCP_SDES_LOC:
2203 result = "location";
2205 case GST_RTCP_SDES_TOOL:
2208 case GST_RTCP_SDES_NOTE:
2211 case GST_RTCP_SDES_PRIV:
2222 * gst_rtcp_sdes_name_to_type:
2223 * @name: a SDES name
2225 * Convert @name into a @GstRTCPSDESType. @name is typically a key in a
2226 * #GstStructure containing SDES items.
2228 * Returns: the #GstRTCPSDESType for @name or #GST_RTCP_SDES_PRIV when @name
2229 * is a private sdes item.
2232 gst_rtcp_sdes_name_to_type (const gchar * name)
2234 if (name == NULL || strlen (name) == 0)
2235 return GST_RTCP_SDES_INVALID;
2237 if (strcmp ("cname", name) == 0)
2238 return GST_RTCP_SDES_CNAME;
2240 if (strcmp ("name", name) == 0)
2241 return GST_RTCP_SDES_NAME;
2243 if (strcmp ("email", name) == 0)
2244 return GST_RTCP_SDES_EMAIL;
2246 if (strcmp ("phone", name) == 0)
2247 return GST_RTCP_SDES_PHONE;
2249 if (strcmp ("location", name) == 0)
2250 return GST_RTCP_SDES_LOC;
2252 if (strcmp ("tool", name) == 0)
2253 return GST_RTCP_SDES_TOOL;
2255 if (strcmp ("note", name) == 0)
2256 return GST_RTCP_SDES_NOTE;
2258 return GST_RTCP_SDES_PRIV;
2262 * gst_rtcp_packet_fb_get_fci_length:
2263 * @packet: a valid RTPFB or PSFB #GstRTCPPacket
2265 * Get the length of the Feedback Control Information attached to a
2266 * RTPFB or PSFB @packet.
2268 * Returns: The length of the FCI in 32-bit words.
2271 gst_rtcp_packet_fb_get_fci_length (GstRTCPPacket * packet)
2275 g_return_val_if_fail (packet != NULL, 0);
2276 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_RTPFB ||
2277 packet->type == GST_RTCP_TYPE_PSFB, 0);
2278 g_return_val_if_fail (packet->rtcp != NULL, 0);
2279 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, 0);
2281 data = packet->rtcp->map.data + packet->offset + 2;
2283 return GST_READ_UINT16_BE (data) - 2;
2287 * gst_rtcp_packet_fb_set_fci_length:
2288 * @packet: a valid RTPFB or PSFB #GstRTCPPacket
2289 * @wordlen: Length of the FCI in 32-bit words
2291 * Set the length of the Feedback Control Information attached to a
2292 * RTPFB or PSFB @packet.
2294 * Returns: %TRUE if there was enough space in the packet to add this much FCI
2297 gst_rtcp_packet_fb_set_fci_length (GstRTCPPacket * packet, guint16 wordlen)
2301 g_return_val_if_fail (packet != NULL, FALSE);
2302 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_RTPFB ||
2303 packet->type == GST_RTCP_TYPE_PSFB, FALSE);
2304 g_return_val_if_fail (packet->rtcp != NULL, FALSE);
2305 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE, FALSE);
2307 if (packet->rtcp->map.maxsize < packet->offset + ((wordlen + 3) * 4))
2310 data = packet->rtcp->map.data + packet->offset + 2;
2312 GST_WRITE_UINT16_BE (data, wordlen);
2314 packet->rtcp->map.size = packet->offset + ((wordlen + 1) * 4);
2320 * gst_rtcp_packet_fb_get_fci:
2321 * @packet: a valid RTPFB or PSFB #GstRTCPPacket
2323 * Get the Feedback Control Information attached to a RTPFB or PSFB @packet.
2325 * Returns: a pointer to the FCI
2328 gst_rtcp_packet_fb_get_fci (GstRTCPPacket * packet)
2332 g_return_val_if_fail (packet != NULL, NULL);
2333 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_RTPFB ||
2334 packet->type == GST_RTCP_TYPE_PSFB, NULL);
2335 g_return_val_if_fail (packet->rtcp != NULL, NULL);
2336 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, NULL);
2338 data = packet->rtcp->map.data + packet->offset;
2340 if (GST_READ_UINT16_BE (data + 2) <= 2)
2347 * gst_rtcp_packet_app_set_subtype:
2348 * @packet: a valid APP #GstRTCPPacket
2349 * @subtype: subtype of the packet
2351 * Set the subtype field of the APP @packet.
2356 gst_rtcp_packet_app_set_subtype (GstRTCPPacket * packet, guint8 subtype)
2360 g_return_if_fail (packet != NULL);
2361 g_return_if_fail (packet->type == GST_RTCP_TYPE_APP);
2362 g_return_if_fail (packet->rtcp != NULL);
2363 g_return_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE);
2365 data = packet->rtcp->map.data + packet->offset;
2366 data[0] = (data[0] & 0xe0) | subtype;
2370 * gst_rtcp_packet_app_get_subtype:
2371 * @packet: a valid APP #GstRTCPPacket
2373 * Get the subtype field of the APP @packet.
2375 * Returns: The subtype.
2380 gst_rtcp_packet_app_get_subtype (GstRTCPPacket * packet)
2384 g_return_val_if_fail (packet != NULL, 0);
2385 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_APP, 0);
2386 g_return_val_if_fail (packet->rtcp != NULL, 0);
2387 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, 0);
2389 data = packet->rtcp->map.data + packet->offset;
2391 return data[0] & 0x1f;
2395 * gst_rtcp_packet_app_set_ssrc:
2396 * @packet: a valid APP #GstRTCPPacket
2397 * @ssrc: SSRC/CSRC of the packet
2399 * Set the SSRC/CSRC field of the APP @packet.
2404 gst_rtcp_packet_app_set_ssrc (GstRTCPPacket * packet, guint32 ssrc)
2408 g_return_if_fail (packet != NULL);
2409 g_return_if_fail (packet->type == GST_RTCP_TYPE_APP);
2410 g_return_if_fail (packet->rtcp != NULL);
2411 g_return_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE);
2413 data = packet->rtcp->map.data + packet->offset + 4;
2414 GST_WRITE_UINT32_BE (data, ssrc);
2418 * gst_rtcp_packet_app_get_ssrc:
2419 * @packet: a valid APP #GstRTCPPacket
2421 * Get the SSRC/CSRC field of the APP @packet.
2423 * Returns: The SSRC/CSRC.
2428 gst_rtcp_packet_app_get_ssrc (GstRTCPPacket * packet)
2432 g_return_val_if_fail (packet != NULL, 0);
2433 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_APP, 0);
2434 g_return_val_if_fail (packet->rtcp != NULL, 0);
2435 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, 0);
2437 data = packet->rtcp->map.data + packet->offset + 4;
2439 return GST_READ_UINT32_BE (data);
2443 * gst_rtcp_packet_app_set_name:
2444 * @packet: a valid APP #GstRTCPPacket
2445 * @name: 4-byte ASCII name
2447 * Set the name field of the APP @packet.
2452 gst_rtcp_packet_app_set_name (GstRTCPPacket * packet, const gchar * name)
2456 g_return_if_fail (packet != NULL);
2457 g_return_if_fail (packet->type == GST_RTCP_TYPE_APP);
2458 g_return_if_fail (packet->rtcp != NULL);
2459 g_return_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE);
2461 data = packet->rtcp->map.data + packet->offset + 8;
2462 memcpy (data, name, 4);
2466 * gst_rtcp_packet_app_get_name:
2467 * @packet: a valid APP #GstRTCPPacket
2469 * Get the name field of the APP @packet.
2471 * Returns: The 4-byte name field, not zero-terminated.
2476 gst_rtcp_packet_app_get_name (GstRTCPPacket * packet)
2478 g_return_val_if_fail (packet != NULL, NULL);
2479 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_APP, NULL);
2480 g_return_val_if_fail (packet->rtcp != NULL, NULL);
2481 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, NULL);
2483 return (const gchar *) &packet->rtcp->map.data[packet->offset + 8];
2487 * gst_rtcp_packet_app_get_data_length:
2488 * @packet: a valid APP #GstRTCPPacket
2490 * Get the length of the application-dependent data attached to an APP
2493 * Returns: The length of data in 32-bit words.
2498 gst_rtcp_packet_app_get_data_length (GstRTCPPacket * packet)
2502 g_return_val_if_fail (packet != NULL, 0);
2503 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_APP, 0);
2504 g_return_val_if_fail (packet->rtcp != NULL, 0);
2505 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, 0);
2507 data = packet->rtcp->map.data + packet->offset + 2;
2509 return GST_READ_UINT16_BE (data) - 2;
2513 * gst_rtcp_packet_app_set_data_length:
2514 * @packet: a valid APP #GstRTCPPacket
2515 * @wordlen: Length of the data in 32-bit words
2517 * Set the length of the application-dependent data attached to an APP
2520 * Returns: %TRUE if there was enough space in the packet to add this much
2526 gst_rtcp_packet_app_set_data_length (GstRTCPPacket * packet, guint16 wordlen)
2530 g_return_val_if_fail (packet != NULL, FALSE);
2531 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_APP, FALSE);
2532 g_return_val_if_fail (packet->rtcp != NULL, FALSE);
2533 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE, FALSE);
2535 if (packet->rtcp->map.maxsize < packet->offset + ((wordlen + 3) * 4))
2538 data = packet->rtcp->map.data + packet->offset + 2;
2540 GST_WRITE_UINT16_BE (data, wordlen);
2542 packet->rtcp->map.size = packet->offset + ((wordlen + 1) * 4);
2548 * gst_rtcp_packet_app_get_data:
2549 * @packet: a valid APP #GstRTCPPacket
2551 * Get the application-dependent data attached to a RTPFB or PSFB @packet.
2553 * Returns: A pointer to the data
2558 gst_rtcp_packet_app_get_data (GstRTCPPacket * packet)
2562 g_return_val_if_fail (packet != NULL, NULL);
2563 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_APP, NULL);
2564 g_return_val_if_fail (packet->rtcp != NULL, NULL);
2565 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, NULL);
2567 data = packet->rtcp->map.data + packet->offset;
2569 if (GST_READ_UINT16_BE (data + 2) <= 2)
2576 * gst_rtcp_packet_xr_get_ssrc:
2577 * @packet: a valid XR #GstRTCPPacket
2579 * Get the ssrc field of the XR @packet.
2581 * Returns: the ssrc.
2586 gst_rtcp_packet_xr_get_ssrc (GstRTCPPacket * packet)
2591 g_return_val_if_fail (packet != NULL, 0);
2592 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_XR, 0);
2593 g_return_val_if_fail (packet->rtcp != NULL, 0);
2594 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, 0);
2596 data = packet->rtcp->map.data;
2599 data += packet->offset + 4;
2600 ssrc = GST_READ_UINT32_BE (data);
2606 * gst_rtcp_packet_xr_first_rb:
2607 * @packet: a valid XR #GstRTCPPacket
2609 * Move to the first extended report block in XR @packet.
2611 * Returns: TRUE if there was a first extended report block.
2616 gst_rtcp_packet_xr_first_rb (GstRTCPPacket * packet)
2621 g_return_val_if_fail (packet != NULL, FALSE);
2622 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_XR, FALSE);
2624 if (packet->length < 2)
2627 /* skip header + ssrc */
2628 packet->item_offset = 8;
2630 /* Validate the block's length */
2631 block_len = gst_rtcp_packet_xr_get_block_length (packet);
2632 offset = 8 + (block_len * 1) + 4;
2634 len = packet->length << 2;
2636 if (offset >= len) {
2637 packet->item_offset = 0;
2645 * gst_rtcp_packet_xr_next_rb:
2646 * @packet: a valid XR #GstRTCPPacket
2648 * Move to the next extended report block in XR @packet.
2650 * Returns: TRUE if there was a next extended report block.
2655 gst_rtcp_packet_xr_next_rb (GstRTCPPacket * packet)
2661 g_return_val_if_fail (packet != NULL, FALSE);
2662 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_XR, FALSE);
2663 g_return_val_if_fail (packet->rtcp != NULL, FALSE);
2664 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, FALSE);
2666 block_len = gst_rtcp_packet_xr_get_block_length (packet);
2668 offset = packet->item_offset;
2669 offset += (block_len + 1) * 4;
2672 len = (packet->length << 2);
2677 packet->item_offset = offset;
2683 * gst_rtcp_packet_xr_get_block_type:
2684 * @packet: a valid XR #GstRTCPPacket
2686 * Get the extended report block type of the XR @packet.
2688 * Returns: The extended report block type.
2693 gst_rtcp_packet_xr_get_block_type (GstRTCPPacket * packet)
2697 GstRTCPXRType xr_type = GST_RTCP_XR_TYPE_INVALID;
2699 g_return_val_if_fail (packet != NULL, GST_RTCP_XR_TYPE_INVALID);
2700 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_XR,
2701 GST_RTCP_XR_TYPE_INVALID);
2702 g_return_val_if_fail (packet->rtcp != NULL, GST_RTCP_XR_TYPE_INVALID);
2703 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ,
2704 GST_RTCP_XR_TYPE_INVALID);
2705 g_return_val_if_fail (packet->length >= (packet->item_offset >> 2),
2706 GST_RTCP_XR_TYPE_INVALID);
2708 data = packet->rtcp->map.data;
2710 /* skip header + current item offset */
2711 data += packet->offset + packet->item_offset;
2713 /* XR block type can be defined more than described in RFC3611.
2714 * If undefined type is detected, user might want to know. */
2715 type = GST_READ_UINT8 (data);
2717 case GST_RTCP_XR_TYPE_LRLE:
2718 case GST_RTCP_XR_TYPE_DRLE:
2719 case GST_RTCP_XR_TYPE_PRT:
2720 case GST_RTCP_XR_TYPE_RRT:
2721 case GST_RTCP_XR_TYPE_DLRR:
2722 case GST_RTCP_XR_TYPE_SSUMM:
2723 case GST_RTCP_XR_TYPE_VOIP_METRICS:
2727 GST_DEBUG ("got 0x%x type, but that might be out of scope of RFC3611",
2736 * gst_rtcp_packet_xr_get_block_length:
2737 * @packet: a valid XR #GstRTCPPacket
2739 * Returns: The number of 32-bit words containing type-specific block
2740 * data from @packet.
2745 gst_rtcp_packet_xr_get_block_length (GstRTCPPacket * packet)
2750 g_return_val_if_fail (packet != NULL, 0);
2751 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_XR, 0);
2752 g_return_val_if_fail (packet->rtcp != NULL, 0);
2753 g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, 0);
2754 g_return_val_if_fail (packet->length >= (packet->item_offset >> 2), 0);
2756 data = packet->rtcp->map.data;
2757 data += packet->offset + packet->item_offset + 2;
2759 len = GST_READ_UINT16_BE (data);
2765 * gst_rtcp_packet_xr_get_rle_info:
2766 * @packet: a valid XR #GstRTCPPacket which is Loss RLE or Duplicate RLE report.
2767 * @ssrc: the SSRC of the RTP data packet source being reported upon by this report block.
2768 * @thinning: the amount of thinning performed on the sequence number space.
2769 * @begin_seq: the first sequence number that this block reports on.
2770 * @end_seq: the last sequence number that this block reports on plus one.
2771 * @chunk_count: the number of chunks calculated by block length.
2773 * Parse the extended report block for Loss RLE and Duplicated LRE block type.
2775 * Returns: %TRUE if the report block is correctly parsed.
2780 gst_rtcp_packet_xr_get_rle_info (GstRTCPPacket * packet, guint32 * ssrc,
2781 guint8 * thinning, guint16 * begin_seq, guint16 * end_seq,
2782 guint32 * chunk_count)
2787 g_return_val_if_fail (gst_rtcp_packet_xr_get_block_type (packet) ==
2788 GST_RTCP_XR_TYPE_LRLE
2789 || gst_rtcp_packet_xr_get_block_type (packet) == GST_RTCP_XR_TYPE_DRLE,
2792 block_len = gst_rtcp_packet_xr_get_block_length (packet);
2797 *chunk_count = (block_len - 2) * 2;
2799 data = packet->rtcp->map.data;
2800 /* skip header + current item offset */
2801 data += packet->offset + packet->item_offset;
2804 *thinning = data[1] & 0x0f;
2809 *ssrc = GST_READ_UINT32_BE (data);
2810 /* go to begin_seq */
2813 *begin_seq = ((data[0] << 8) | data[1]);
2817 *end_seq = ((data[0] << 8) | data[1]);
2823 * gst_rtcp_packet_xr_get_rle_nth_chunk:
2824 * @packet: a valid XR #GstRTCPPacket which is Loss RLE or Duplicate RLE report.
2825 * @nth: the index of chunk to retrieve.
2826 * @chunk: the @nth chunk.
2828 * Retrieve actual chunk data.
2830 * Returns: %TRUE if the report block returns chunk correctly.
2835 gst_rtcp_packet_xr_get_rle_nth_chunk (GstRTCPPacket * packet,
2836 guint nth, guint16 * chunk)
2838 guint32 chunk_count;
2841 if (!gst_rtcp_packet_xr_get_rle_info (packet, NULL, NULL, NULL, NULL,
2843 g_return_val_if_reached (FALSE);
2845 if (nth >= chunk_count)
2848 data = packet->rtcp->map.data;
2849 /* skip header + current item offset */
2850 data += packet->offset + packet->item_offset;
2852 /* skip ssrc, {begin,end}_seq */
2855 /* goto nth chunk */
2858 *chunk = ((data[0] << 8) | data[1]);
2864 * gst_rtcp_packet_xr_get_prt_info:
2865 * @packet: a valid XR #GstRTCPPacket which has a Packet Receipt Times Report Block
2866 * @ssrc: the SSRC of the RTP data packet source being reported upon by this report block.
2867 * @thinning: the amount of thinning performed on the sequence number space.
2868 * @begin_seq: the first sequence number that this block reports on.
2869 * @end_seq: the last sequence number that this block reports on plus one.
2871 * Parse the Packet Recept Times Report Block from a XR @packet
2873 * Returns: %TRUE if the report block is correctly parsed.
2878 gst_rtcp_packet_xr_get_prt_info (GstRTCPPacket * packet,
2879 guint32 * ssrc, guint8 * thinning, guint16 * begin_seq, guint16 * end_seq)
2884 g_return_val_if_fail (gst_rtcp_packet_xr_get_block_type (packet) ==
2885 GST_RTCP_XR_TYPE_PRT, FALSE);
2887 block_len = gst_rtcp_packet_xr_get_block_length (packet);
2891 data = packet->rtcp->map.data;
2892 /* skip header + current item offset */
2893 data += packet->offset + packet->item_offset;
2896 *thinning = data[1] & 0x0f;
2901 *ssrc = GST_READ_UINT32_BE (data);
2903 /* go to begin_seq */
2906 *begin_seq = ((data[0] << 8) | data[1]);
2910 *end_seq = ((data[0] << 8) | data[1]);
2916 * gst_rtcp_packet_xr_get_prt_by_seq:
2917 * @packet: a valid XR #GstRTCPPacket which has the Packet Recept Times Report Block.
2918 * @seq: the sequence to retrieve the time.
2919 * @receipt_time: the packet receipt time of @seq.
2921 * Retrieve the packet receipt time of @seq which ranges in [begin_seq, end_seq).
2923 * Returns: %TRUE if the report block returns the receipt time correctly.
2928 gst_rtcp_packet_xr_get_prt_by_seq (GstRTCPPacket * packet,
2929 guint16 seq, guint32 * receipt_time)
2931 guint16 begin_seq, end_seq;
2934 if (!gst_rtcp_packet_xr_get_prt_info (packet, NULL, NULL, &begin_seq,
2936 g_return_val_if_reached (FALSE);
2938 if (seq >= end_seq || seq < begin_seq)
2941 data = packet->rtcp->map.data;
2942 /* skip header + current item offset */
2943 data += packet->offset + packet->item_offset;
2945 /* skip ssrc, {begin,end}_seq */
2948 data += (seq - begin_seq) * 4;
2951 *receipt_time = GST_READ_UINT32_BE (data);
2957 * gst_rtcp_packet_xr_get_rrt:
2958 * @packet: a valid XR #GstRTCPPacket which has the Receiver Reference Time.
2959 * @timestamp: NTP timestamp
2961 * Returns: %TRUE if the report block returns the reference time correctly.
2966 gst_rtcp_packet_xr_get_rrt (GstRTCPPacket * packet, guint64 * timestamp)
2970 g_return_val_if_fail (gst_rtcp_packet_xr_get_block_type (packet) ==
2971 GST_RTCP_XR_TYPE_RRT, FALSE);
2973 if (gst_rtcp_packet_xr_get_block_length (packet) != 2)
2976 data = packet->rtcp->map.data;
2977 /* skip header + current item offset */
2978 data += packet->offset + packet->item_offset;
2980 /* skip block header */
2983 *timestamp = GST_READ_UINT64_BE (data);
2989 * gst_rtcp_packet_xr_get_dlrr_block:
2990 * @packet: a valid XR #GstRTCPPacket which has DLRR Report Block.
2991 * @nth: the index of sub-block to retrieve.
2992 * @ssrc: the SSRC of the receiver.
2993 * @last_rr: the last receiver reference timestamp of @ssrc.
2994 * @delay: the delay since @last_rr.
2996 * Parse the extended report block for DLRR report block type.
2998 * Returns: %TRUE if the report block is correctly parsed.
3003 gst_rtcp_packet_xr_get_dlrr_block (GstRTCPPacket * packet,
3004 guint nth, guint32 * ssrc, guint32 * last_rr, guint32 * delay)
3009 g_return_val_if_fail (gst_rtcp_packet_xr_get_block_type (packet) ==
3010 GST_RTCP_XR_TYPE_DLRR, FALSE);
3012 block_len = gst_rtcp_packet_xr_get_block_length (packet);
3014 if (nth * 3 >= block_len)
3017 data = packet->rtcp->map.data;
3018 /* skip header + current item offset */
3019 data += packet->offset + packet->item_offset;
3020 /* skip block header */
3022 data += nth * 3 * 4;
3025 *ssrc = GST_READ_UINT32_BE (data);
3029 *last_rr = GST_READ_UINT32_BE (data);
3033 *delay = GST_READ_UINT32_BE (data);
3039 * gst_rtcp_packet_xr_get_summary_info:
3040 * @packet: a valid XR #GstRTCPPacket which has Statics Summary Report Block.
3041 * @ssrc: the SSRC of the source.
3042 * @begin_seq: the first sequence number that this block reports on.
3043 * @end_seq: the last sequence number that this block reports on plus one.
3045 * Extract a basic information from static summary report block of XR @packet.
3047 * Returns: %TRUE if the report block is correctly parsed.
3052 gst_rtcp_packet_xr_get_summary_info (GstRTCPPacket * packet, guint32 * ssrc,
3053 guint16 * begin_seq, guint16 * end_seq)
3057 g_return_val_if_fail (gst_rtcp_packet_xr_get_block_type (packet) ==
3058 GST_RTCP_XR_TYPE_SSUMM, FALSE);
3060 if (gst_rtcp_packet_xr_get_block_length (packet) != 9)
3063 data = packet->rtcp->map.data;
3064 /* skip header + current item offset */
3065 data += packet->offset + packet->item_offset;
3066 /* skip block header */
3070 *ssrc = GST_READ_UINT32_BE (data);
3072 /* go to begin_seq */
3075 *begin_seq = ((data[0] << 8) | data[1]);
3079 *end_seq = ((data[0] << 8) | data[1]);
3085 * gst_rtcp_packet_xr_get_summary_pkt:
3086 * @packet: a valid XR #GstRTCPPacket which has Statics Summary Report Block.
3087 * @lost_packets: the number of lost packets between begin_seq and end_seq.
3088 * @dup_packets: the number of duplicate packets between begin_seq and end_seq.
3090 * Get the number of lost or duplicate packets. If the flag in a block header
3091 * is set as zero, @lost_packets or @dup_packets will be zero.
3093 * Returns: %TRUE if the report block is correctly parsed.
3098 gst_rtcp_packet_xr_get_summary_pkt (GstRTCPPacket * packet,
3099 guint32 * lost_packets, guint32 * dup_packets)
3104 g_return_val_if_fail (gst_rtcp_packet_xr_get_block_type (packet) ==
3105 GST_RTCP_XR_TYPE_SSUMM, FALSE);
3106 if (gst_rtcp_packet_xr_get_block_length (packet) != 9)
3109 data = packet->rtcp->map.data;
3110 /* skip header + current item offset */
3111 data += packet->offset + packet->item_offset;
3113 /* skip block header,ssrc, {begin,end}_seq */
3117 if (!(flags & 0x80))
3120 *lost_packets = GST_READ_UINT32_BE (data);
3125 if (!(flags & 0x40))
3128 *dup_packets = GST_READ_UINT32_BE (data);
3135 * gst_rtcp_packet_xr_get_summary_jitter:
3136 * @packet: a valid XR #GstRTCPPacket which has Statics Summary Report Block.
3137 * @min_jitter: the minimum relative transit time between two sequences.
3138 * @max_jitter: the maximum relative transit time between two sequences.
3139 * @mean_jitter: the mean relative transit time between two sequences.
3140 * @dev_jitter: the standard deviation of the relative transit time between two sequences.
3142 * Extract jitter information from the statistics summary. If the jitter flag in
3143 * a block header is set as zero, all of jitters will be zero.
3145 * Returns: %TRUE if the report block is correctly parsed.
3150 gst_rtcp_packet_xr_get_summary_jitter (GstRTCPPacket * packet,
3151 guint32 * min_jitter, guint32 * max_jitter,
3152 guint32 * mean_jitter, guint32 * dev_jitter)
3157 g_return_val_if_fail (gst_rtcp_packet_xr_get_block_type (packet) ==
3158 GST_RTCP_XR_TYPE_SSUMM, FALSE);
3160 if (gst_rtcp_packet_xr_get_block_length (packet) != 9)
3163 data = packet->rtcp->map.data;
3164 /* skip header + current item offset */
3165 data += packet->offset + packet->item_offset;
3168 if (!(flags & 0x20)) {
3181 /* skip block header,ssrc, {begin,end}_seq, packets */
3184 *min_jitter = GST_READ_UINT32_BE (data);
3188 *max_jitter = GST_READ_UINT32_BE (data);
3192 *mean_jitter = GST_READ_UINT32_BE (data);
3196 *dev_jitter = GST_READ_UINT32_BE (data);
3202 * gst_rtcp_packet_xr_get_summary_ttl:
3203 * @packet: a valid XR #GstRTCPPacket which has Statics Summary Report Block.
3204 * @is_ipv4: the flag to indicate that the return values are ipv4 ttl or ipv6 hop limits.
3205 * @min_ttl: the minimum TTL or Hop Limit value of data packets between two sequences.
3206 * @max_ttl: the maximum TTL or Hop Limit value of data packets between two sequences.
3207 * @mean_ttl: the mean TTL or Hop Limit value of data packets between two sequences.
3208 * @dev_ttl: the standard deviation of the TTL or Hop Limit value of data packets between two sequences.
3210 * Extract the value of ttl for ipv4, or hop limit for ipv6.
3212 * Returns: %TRUE if the report block is correctly parsed.
3217 gst_rtcp_packet_xr_get_summary_ttl (GstRTCPPacket * packet,
3218 gboolean * is_ipv4, guint8 * min_ttl, guint8 * max_ttl, guint8 * mean_ttl,
3224 g_return_val_if_fail (gst_rtcp_packet_xr_get_block_type (packet) ==
3225 GST_RTCP_XR_TYPE_SSUMM, FALSE);
3227 if (gst_rtcp_packet_xr_get_block_length (packet) != 9)
3230 data = packet->rtcp->map.data;
3231 /* skip header + current item offset */
3232 data += packet->offset + packet->item_offset;
3233 flags = (data[1] & 0x18) >> 3;
3239 *is_ipv4 = (flags == 1);
3241 /* skip block header,ssrc, {begin,end}_seq, packets, jitters */
3250 *mean_ttl = data[2];
3259 * gst_rtcp_packet_xr_get_voip_metrics_ssrc:
3260 * @packet: a valid XR #GstRTCPPacket which has VoIP Metrics Report Block.
3261 * @ssrc: the SSRC of source
3263 * Returns: %TRUE if the report block is correctly parsed.
3268 gst_rtcp_packet_xr_get_voip_metrics_ssrc (GstRTCPPacket * packet,
3273 g_return_val_if_fail (gst_rtcp_packet_xr_get_block_type (packet) ==
3274 GST_RTCP_XR_TYPE_VOIP_METRICS, FALSE);
3276 if (gst_rtcp_packet_xr_get_block_length (packet) != 8)
3279 data = packet->rtcp->map.data;
3280 /* skip header + current item offset */
3281 data += packet->offset + packet->item_offset;
3283 /* skip block header */
3286 *ssrc = GST_READ_UINT32_BE (data);
3292 * gst_rtcp_packet_xr_get_voip_packet_metrics:
3293 * @packet: a valid XR #GstRTCPPacket which has VoIP Metrics Report Block.
3294 * @loss_rate: the fraction of RTP data packets from the source lost.
3295 * @discard_rate: the fraction of RTP data packets from the source that have been discarded.
3297 * Returns: %TRUE if the report block is correctly parsed.
3302 gst_rtcp_packet_xr_get_voip_packet_metrics (GstRTCPPacket * packet,
3303 guint8 * loss_rate, guint8 * discard_rate)
3307 g_return_val_if_fail (gst_rtcp_packet_xr_get_block_type (packet) ==
3308 GST_RTCP_XR_TYPE_VOIP_METRICS, FALSE);
3310 if (gst_rtcp_packet_xr_get_block_length (packet) != 8)
3313 data = packet->rtcp->map.data;
3314 /* skip header + current item offset */
3315 data += packet->offset + packet->item_offset;
3317 /* skip block header, ssrc */
3320 *loss_rate = data[0];
3323 *discard_rate = data[1];
3329 * gst_rtcp_packet_xr_get_voip_burst_metrics:
3330 * @packet: a valid XR #GstRTCPPacket which has VoIP Metrics Report Block.
3331 * @burst_density: the fraction of RTP data packets within burst periods.
3332 * @gap_density: the fraction of RTP data packets within inter-burst gaps.
3333 * @burst_duration: the mean duration(ms) of the burst periods.
3334 * @gap_duration: the mean duration(ms) of the gap periods.
3336 * Returns: %TRUE if the report block is correctly parsed.
3341 gst_rtcp_packet_xr_get_voip_burst_metrics (GstRTCPPacket * packet,
3342 guint8 * burst_density, guint8 * gap_density, guint16 * burst_duration,
3343 guint16 * gap_duration)
3347 g_return_val_if_fail (gst_rtcp_packet_xr_get_block_type (packet) ==
3348 GST_RTCP_XR_TYPE_VOIP_METRICS, FALSE);
3350 if (gst_rtcp_packet_xr_get_block_length (packet) != 8)
3353 data = packet->rtcp->map.data;
3354 /* skip header + current item offset */
3355 data += packet->offset + packet->item_offset;
3357 /* skip block header, ssrc, packet metrics */
3360 *burst_density = data[0];
3363 *gap_density = data[1];
3367 *burst_duration = GST_READ_UINT16_BE (data);
3371 *gap_duration = GST_READ_UINT16_BE (data);
3377 * gst_rtcp_packet_xr_get_voip_delay_metrics:
3378 * @packet: a valid XR #GstRTCPPacket which has VoIP Metrics Report Block.
3379 * @roundtrip_delay: the most recently calculated round trip time between RTP interfaces(ms)
3380 * @end_system_delay: the most recently estimated end system delay(ms)
3382 * Returns: %TRUE if the report block is correctly parsed.
3387 gst_rtcp_packet_xr_get_voip_delay_metrics (GstRTCPPacket * packet,
3388 guint16 * roundtrip_delay, guint16 * end_system_delay)
3392 g_return_val_if_fail (gst_rtcp_packet_xr_get_block_type (packet) ==
3393 GST_RTCP_XR_TYPE_VOIP_METRICS, FALSE);
3395 if (gst_rtcp_packet_xr_get_block_length (packet) != 8)
3398 data = packet->rtcp->map.data;
3399 /* skip header + current item offset */
3400 data += packet->offset + packet->item_offset;
3402 /* skip block header, ssrc, packet metrics, burst metrics */
3404 if (roundtrip_delay)
3405 *roundtrip_delay = GST_READ_UINT16_BE (data);
3408 if (end_system_delay)
3409 *end_system_delay = GST_READ_UINT16_BE (data);
3415 * gst_rtcp_packet_xr_get_voip_signal_metrics:
3416 * @packet: a valid XR #GstRTCPPacket which has VoIP Metrics Report Block.
3417 * @signal_level: the ratio of the signal level to a 0 dBm reference.
3418 * @noise_level: the ratio of the silent period background noise level to a 0 dBm reference.
3419 * @rerl: the residual echo return loss value.
3420 * @gmin: the gap threshold.
3422 * Returns: %TRUE if the report block is correctly parsed.
3427 gst_rtcp_packet_xr_get_voip_signal_metrics (GstRTCPPacket * packet,
3428 guint8 * signal_level, guint8 * noise_level, guint8 * rerl, guint8 * gmin)
3432 g_return_val_if_fail (gst_rtcp_packet_xr_get_block_type (packet) ==
3433 GST_RTCP_XR_TYPE_VOIP_METRICS, FALSE);
3435 if (gst_rtcp_packet_xr_get_block_length (packet) != 8)
3438 data = packet->rtcp->map.data;
3439 /* skip header + current item offset */
3440 data += packet->offset + packet->item_offset;
3442 /* skip block header, ssrc, packet metrics, burst metrics,
3446 *signal_level = data[0];
3449 *noise_level = data[1];
3461 * gst_rtcp_packet_xr_get_voip_quality_metrics:
3462 * @packet: a valid XR #GstRTCPPacket which has VoIP Metrics Report Block.
3463 * @r_factor: the R factor is a voice quality metric describing the segment of the call.
3464 * @ext_r_factor: the external R factor is a voice quality metric.
3465 * @mos_lq: the estimated mean opinion score for listening quality.
3466 * @mos_cq: the estimated mean opinion score for conversational quality.
3468 * Returns: %TRUE if the report block is correctly parsed.
3473 gst_rtcp_packet_xr_get_voip_quality_metrics (GstRTCPPacket * packet,
3474 guint8 * r_factor, guint8 * ext_r_factor, guint8 * mos_lq, guint8 * mos_cq)
3478 g_return_val_if_fail (gst_rtcp_packet_xr_get_block_type (packet) ==
3479 GST_RTCP_XR_TYPE_VOIP_METRICS, FALSE);
3481 if (gst_rtcp_packet_xr_get_block_length (packet) != 8)
3484 data = packet->rtcp->map.data;
3485 /* skip header + current item offset */
3486 data += packet->offset + packet->item_offset;
3488 /* skip block header, ssrc, packet metrics, burst metrics,
3489 * delay metrics, signal metrics */
3492 *r_factor = data[0];
3495 *ext_r_factor = data[1];
3507 * gst_rtcp_packet_xr_get_voip_configuration_params:
3508 * @packet: a valid XR #GstRTCPPacket which has VoIP Metrics Report Block.
3509 * @gmin: the gap threshold.
3510 * @rx_config: the receiver configuration byte.
3512 * Returns: %TRUE if the report block is correctly parsed.
3517 gst_rtcp_packet_xr_get_voip_configuration_params (GstRTCPPacket * packet,
3518 guint8 * gmin, guint8 * rx_config)
3522 g_return_val_if_fail (gst_rtcp_packet_xr_get_block_type (packet) ==
3523 GST_RTCP_XR_TYPE_VOIP_METRICS, FALSE);
3525 if (gst_rtcp_packet_xr_get_block_length (packet) != 8)
3528 data = packet->rtcp->map.data;
3529 /* skip header + current item offset */
3530 data += packet->offset + packet->item_offset;
3536 *rx_config = data[28];
3542 * gst_rtcp_packet_xr_get_voip_jitter_buffer_params:
3543 * @packet: a valid XR #GstRTCPPacket which has VoIP Metrics Report Block.
3544 * @jb_nominal: the current nominal jitter buffer delay(ms)
3545 * @jb_maximum: the current maximum jitter buffer delay(ms)
3546 * @jb_abs_max: the absolute maximum delay(ms)
3548 * Returns: %TRUE if the report block is correctly parsed.
3553 gst_rtcp_packet_xr_get_voip_jitter_buffer_params (GstRTCPPacket * packet,
3554 guint16 * jb_nominal, guint16 * jb_maximum, guint16 * jb_abs_max)
3558 g_return_val_if_fail (gst_rtcp_packet_xr_get_block_type (packet) ==
3559 GST_RTCP_XR_TYPE_VOIP_METRICS, FALSE);
3561 if (gst_rtcp_packet_xr_get_block_length (packet) != 8)
3564 data = packet->rtcp->map.data;
3565 /* skip header + current item offset */
3566 data += packet->offset + packet->item_offset;
3568 /* skip block header, ssrc, packet metrics, burst metrics,
3569 * delay metrics, signal metrics, config */
3573 *jb_nominal = GST_READ_UINT16_BE (data);
3577 *jb_maximum = GST_READ_UINT16_BE (data);
3581 *jb_abs_max = GST_READ_UINT16_BE (data);