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., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
24 * SECTION:gstrtcpbuffer
25 * @short_description: Helper methods for dealing with RTCP buffers
26 * @see_also: #GstRTPBasePayload, #GstRTPBaseDepayload, #gstrtpbuffer
28 * Note: The API in this module is not yet declared stable.
32 * The GstRTPCBuffer helper functions makes it easy to parse and create regular
33 * #GstBuffer objects that contain compound RTCP packets. These buffers are typically
34 * of 'application/x-rtcp' #GstCaps.
37 * An RTCP buffer consists of 1 or more #GstRTCPPacket structures that you can
38 * retrieve with gst_rtcp_buffer_get_first_packet(). #GstRTCPPacket acts as a pointer
39 * into the RTCP buffer; you can move to the next packet with
40 * gst_rtcp_packet_move_to_next().
44 * Last reviewed on 2007-03-26 (0.10.13)
51 #include "gstrtcpbuffer.h"
54 * gst_rtcp_buffer_new_take_data:
55 * @data: data for the new buffer
56 * @len: the length of data
58 * Create a new buffer and set the data and size of the buffer to @data and @len
59 * respectively. @data will be freed when the buffer is unreffed, so this
60 * function transfers ownership of @data to the new buffer.
62 * Returns: A newly allocated buffer with @data and of size @len.
65 gst_rtcp_buffer_new_take_data (gpointer data, guint len)
69 g_return_val_if_fail (data != NULL, NULL);
70 g_return_val_if_fail (len > 0, NULL);
72 result = gst_buffer_new ();
73 gst_buffer_take_memory (result, -1,
74 gst_memory_new_wrapped (0, data, g_free, len, 0, len));
80 * gst_rtcp_buffer_new_copy_data:
81 * @data: data for the new buffer
82 * @len: the length of data
84 * Create a new buffer and set the data to a copy of @len
85 * bytes of @data and the size to @len. The data will be freed when the buffer
88 * Returns: A newly allocated buffer with a copy of @data and of size @len.
91 gst_rtcp_buffer_new_copy_data (gpointer data, guint len)
93 return gst_rtcp_buffer_new_take_data (g_memdup (data, len), len);
97 * gst_rtcp_buffer_validate_data:
98 * @data: the data to validate
99 * @len: the length of @data to validate
101 * Check if the @data and @size point to the data of a valid RTCP (compound)
103 * Use this function to validate a packet before using the other functions in
106 * Returns: TRUE if the data points to a valid RTCP packet.
109 gst_rtcp_buffer_validate_data (guint8 * data, guint len)
118 g_return_val_if_fail (data != NULL, FALSE);
120 /* we need 4 bytes for the type and length */
121 if (G_UNLIKELY (len < 4))
124 /* first packet must be RR or SR and version must be 2 */
125 header_mask = ((data[0] << 8) | data[1]) & GST_RTCP_VALID_MASK;
126 if (G_UNLIKELY (header_mask != GST_RTCP_VALID_VALUE))
129 /* no padding when mask succeeds */
136 /* get packet length */
137 header_len = (((data[2] << 8) | data[3]) + 1) << 2;
138 if (data_len < header_len)
141 /* move to next compount packet */
143 data_len -= header_len;
145 /* we are at the end now */
149 /* check version of new packet */
150 version = data[0] & 0xc0;
151 if (version != (GST_RTCP_VERSION << 6))
154 /* padding only allowed on last packet */
155 if ((padding = data[0] & 0x20))
159 /* some leftover bytes, check padding */
164 pad_bytes = data[data_len - 1];
165 if (data_len != pad_bytes)
173 GST_DEBUG ("len check failed");
178 GST_DEBUG ("mask check failed (%04x != %04x)", header_mask,
179 GST_RTCP_VALID_VALUE);
184 GST_DEBUG ("wrong version (%d < 2)", version >> 6);
189 GST_DEBUG ("padding check failed");
195 * gst_rtcp_buffer_validate:
196 * @buffer: the buffer to validate
198 * Check if the data pointed to by @buffer is a valid RTCP packet using
199 * gst_rtcp_buffer_validate_data().
201 * Returns: TRUE if @buffer is a valid RTCP packet.
204 gst_rtcp_buffer_validate (GstBuffer * buffer)
210 g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
212 data = gst_buffer_map (buffer, &len, NULL, GST_MAP_READ);
213 res = gst_rtcp_buffer_validate_data (data, len);
214 gst_buffer_unmap (buffer, data, len);
220 * gst_rtcp_buffer_new:
221 * @mtu: the maximum mtu size.
223 * Create a new buffer for constructing RTCP packets. The packet will have a
224 * maximum size of @mtu.
226 * Returns: A newly allocated buffer.
229 gst_rtcp_buffer_new (guint mtu)
233 g_return_val_if_fail (mtu > 0, NULL);
235 result = gst_buffer_new ();
236 gst_buffer_take_memory (result, -1,
237 gst_memory_new_wrapped (0, g_malloc0 (mtu), g_free, mtu, 0, mtu));
243 * gst_rtcp_buffer_map:
244 * @buffer: a buffer with an RTCP packet
245 * @flags: flags for the mapping
246 * @rtcp: resulting #GstRTCPBuffer
248 * Open @buffer for reading or writing, depending on @flags. The resulting RTCP
249 * buffer state is stored in @rtcp.
252 gst_rtcp_buffer_map (GstBuffer * buffer, GstMapFlags flags,
253 GstRTCPBuffer * rtcp)
255 g_return_val_if_fail (rtcp != NULL, FALSE);
256 g_return_val_if_fail (rtcp->buffer == NULL, FALSE);
257 g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
259 rtcp->buffer = buffer;
261 rtcp->data = gst_buffer_map (buffer, &rtcp->size, &rtcp->maxsize, flags);
263 /* allow for expansion, e.g. adding packets, if needed */
264 if ((flags & GST_MAP_WRITE) != 0) {
265 /* unmap and adjust to max available, and remap */
266 gst_buffer_unmap (buffer, rtcp->data, rtcp->maxsize);
267 rtcp->data = gst_buffer_map (buffer, &rtcp->size, &rtcp->maxsize, flags);
274 * gst_rtcp_buffer_unmap:
275 * @rtcp: a buffer with an RTCP packet
277 * Finish @rtcp after being constructured. This function is usually called
278 * after gst_rtcp_buffer_map() and after adding the RTCP items to the new buffer.
280 * The function adjusts the size of @rtcp with the total length of all the
284 gst_rtcp_buffer_unmap (GstRTCPBuffer * rtcp)
287 GstRTCPPacket packet;
289 g_return_val_if_fail (rtcp != NULL, FALSE);
290 g_return_val_if_fail (GST_IS_BUFFER (rtcp->buffer), FALSE);
292 /* move to the first free space */
293 if (gst_rtcp_buffer_get_first_packet (rtcp, &packet))
294 while (gst_rtcp_packet_move_to_next (&packet));
297 res = gst_buffer_unmap (rtcp->buffer, rtcp->data, packet.offset);
304 * gst_rtcp_buffer_get_packet_count:
305 * @rtcp: a valid RTCP buffer
307 * Get the number of RTCP packets in @rtcp.
309 * Returns: the number of RTCP packets in @rtcp.
312 gst_rtcp_buffer_get_packet_count (GstRTCPBuffer * rtcp)
314 GstRTCPPacket packet;
317 g_return_val_if_fail (rtcp != NULL, 0);
318 g_return_val_if_fail (GST_IS_BUFFER (rtcp->buffer), 0);
321 if (gst_rtcp_buffer_get_first_packet (rtcp, &packet)) {
324 } while (gst_rtcp_packet_move_to_next (&packet));
331 * read_packet_header:
334 * Read the packet headers for the packet pointed to by @packet.
336 * Returns: TRUE if @packet pointed to a valid header.
339 read_packet_header (GstRTCPPacket * packet)
345 g_return_val_if_fail (packet != NULL, FALSE);
347 data = packet->rtcp->data;
348 size = packet->rtcp->size;
350 offset = packet->offset;
352 /* check if we are at the end of the buffer, we add 4 because we also want to
353 * ensure we can read the header. */
354 if (offset + 4 > size)
357 if ((data[offset] & 0xc0) != (GST_RTCP_VERSION << 6))
360 /* read count, type and length */
361 packet->padding = (data[offset] & 0x20) == 0x20;
362 packet->count = data[offset] & 0x1f;
363 packet->type = data[offset + 1];
364 packet->length = (data[offset + 2] << 8) | data[offset + 3];
365 packet->item_offset = 4;
366 packet->item_count = 0;
367 packet->entry_offset = 4;
373 * gst_rtcp_buffer_get_first_packet:
374 * @rtcp: a valid RTCP buffer
375 * @packet: a #GstRTCPPacket
377 * Initialize a new #GstRTCPPacket pointer that points to the first packet in
380 * Returns: TRUE if the packet existed in @rtcp.
383 gst_rtcp_buffer_get_first_packet (GstRTCPBuffer * rtcp, GstRTCPPacket * packet)
385 g_return_val_if_fail (rtcp != NULL, FALSE);
386 g_return_val_if_fail (GST_IS_BUFFER (rtcp->buffer), FALSE);
387 g_return_val_if_fail (packet != NULL, FALSE);
392 packet->type = GST_RTCP_TYPE_INVALID;
394 if (!read_packet_header (packet))
401 * gst_rtcp_packet_move_to_next:
402 * @packet: a #GstRTCPPacket
404 * Move the packet pointer @packet to the next packet in the payload.
405 * Use gst_rtcp_buffer_get_first_packet() to initialize @packet.
407 * Returns: TRUE if @packet is pointing to a valid packet after calling this
411 gst_rtcp_packet_move_to_next (GstRTCPPacket * packet)
413 g_return_val_if_fail (packet != NULL, FALSE);
414 g_return_val_if_fail (packet->type != GST_RTCP_TYPE_INVALID, FALSE);
416 /* if we have a padding or invalid packet, it must be the last,
418 if (packet->type == GST_RTCP_TYPE_INVALID || packet->padding)
421 /* move to next packet. Add 4 because the header is not included in length */
422 packet->offset += (packet->length << 2) + 4;
424 /* try to read new header */
425 if (!read_packet_header (packet))
433 packet->type = GST_RTCP_TYPE_INVALID;
439 * gst_rtcp_buffer_add_packet:
440 * @rtcp: a valid RTCP buffer
441 * @type: the #GstRTCPType of the new packet
442 * @packet: pointer to new packet
444 * Add a new packet of @type to @rtcp. @packet will point to the newly created
447 * Returns: %TRUE if the packet could be created. This function returns %FALSE
448 * if the max mtu is exceeded for the buffer.
451 gst_rtcp_buffer_add_packet (GstRTCPBuffer * rtcp, GstRTCPType type,
452 GstRTCPPacket * packet)
458 g_return_val_if_fail (rtcp != NULL, FALSE);
459 g_return_val_if_fail (GST_IS_BUFFER (rtcp->buffer), FALSE);
460 g_return_val_if_fail (type != GST_RTCP_TYPE_INVALID, FALSE);
461 g_return_val_if_fail (packet != NULL, FALSE);
463 /* find free space */
464 if (gst_rtcp_buffer_get_first_packet (rtcp, packet))
465 while (gst_rtcp_packet_move_to_next (packet));
469 /* packet->offset is now pointing to the next free offset in the buffer to
470 * start a compount packet. Next we figure out if we have enough free space in
471 * the buffer to continue. */
473 case GST_RTCP_TYPE_SR:
476 case GST_RTCP_TYPE_RR:
479 case GST_RTCP_TYPE_SDES:
482 case GST_RTCP_TYPE_BYE:
485 case GST_RTCP_TYPE_APP:
488 case GST_RTCP_TYPE_RTPFB:
491 case GST_RTCP_TYPE_PSFB:
497 if (packet->offset + len >= size)
500 data = rtcp->data + packet->offset;
502 data[0] = (GST_RTCP_VERSION << 6);
504 /* length is stored in multiples of 32 bit words minus the length of the
506 len = (len - 4) >> 2;
508 data[3] = len & 0xff;
510 /* now try to position to the packet */
511 result = read_packet_header (packet);
518 g_warning ("unknown type %d", type);
528 * gst_rtcp_packet_remove:
529 * @packet: a #GstRTCPPacket
531 * Removes the packet pointed to by @packet and moves pointer to the next one
533 * Returns: TRUE if @packet is pointing to a valid packet after calling this
537 gst_rtcp_packet_remove (GstRTCPPacket * packet)
539 gboolean ret = FALSE;
542 g_return_val_if_fail (packet != NULL, FALSE);
543 g_return_val_if_fail (packet->type != GST_RTCP_TYPE_INVALID, FALSE);
545 /* The next packet starts at offset + length + 4 (the header) */
546 offset = packet->offset + (packet->length << 2) + 4;
548 /* Overwrite this packet with the rest of the data */
549 memmove (packet->rtcp->data + packet->offset,
550 packet->rtcp->data + offset, packet->rtcp->size - offset);
552 /* try to read next header */
553 ret = read_packet_header (packet);
555 packet->type = GST_RTCP_TYPE_INVALID;
561 * gst_rtcp_packet_get_padding:
562 * @packet: a valid #GstRTCPPacket
564 * Get the packet padding of the packet pointed to by @packet.
566 * Returns: If the packet has the padding bit set.
569 gst_rtcp_packet_get_padding (GstRTCPPacket * packet)
571 g_return_val_if_fail (packet != NULL, FALSE);
572 g_return_val_if_fail (packet->type != GST_RTCP_TYPE_INVALID, FALSE);
574 return packet->padding;
578 * gst_rtcp_packet_get_type:
579 * @packet: a valid #GstRTCPPacket
581 * Get the packet type of the packet pointed to by @packet.
583 * Returns: The packet type or GST_RTCP_TYPE_INVALID when @packet is not
584 * pointing to a valid packet.
587 gst_rtcp_packet_get_type (GstRTCPPacket * packet)
589 g_return_val_if_fail (packet != NULL, GST_RTCP_TYPE_INVALID);
595 * gst_rtcp_packet_get_count:
596 * @packet: a valid #GstRTCPPacket
598 * Get the count field in @packet.
600 * Returns: The count field in @packet or -1 if @packet does not point to a
604 gst_rtcp_packet_get_count (GstRTCPPacket * packet)
606 g_return_val_if_fail (packet != NULL, -1);
607 g_return_val_if_fail (packet->type != GST_RTCP_TYPE_INVALID, -1);
609 return packet->count;
613 * gst_rtcp_packet_get_length:
614 * @packet: a valid #GstRTCPPacket
616 * Get the length field of @packet. This is the length of the packet in
617 * 32-bit words minus one.
619 * Returns: The length field of @packet.
622 gst_rtcp_packet_get_length (GstRTCPPacket * packet)
624 g_return_val_if_fail (packet != NULL, 0);
625 g_return_val_if_fail (packet->type != GST_RTCP_TYPE_INVALID, 0);
627 return packet->length;
631 * gst_rtcp_packet_sr_get_sender_info:
632 * @packet: a valid SR #GstRTCPPacket
634 * @ntptime: result NTP time
635 * @rtptime: result RTP time
636 * @packet_count: result packet count
637 * @octet_count: result octet count
639 * Parse the SR sender info and store the values.
642 gst_rtcp_packet_sr_get_sender_info (GstRTCPPacket * packet, guint32 * ssrc,
643 guint64 * ntptime, guint32 * rtptime, guint32 * packet_count,
644 guint32 * octet_count)
648 g_return_if_fail (packet != NULL);
649 g_return_if_fail (packet->type == GST_RTCP_TYPE_SR);
651 data = packet->rtcp->data;
654 data += packet->offset + 4;
656 *ssrc = GST_READ_UINT32_BE (data);
659 *ntptime = GST_READ_UINT64_BE (data);
662 *rtptime = GST_READ_UINT32_BE (data);
665 *packet_count = GST_READ_UINT32_BE (data);
668 *octet_count = GST_READ_UINT32_BE (data);
672 * gst_rtcp_packet_sr_set_sender_info:
673 * @packet: a valid SR #GstRTCPPacket
675 * @ntptime: the NTP time
676 * @rtptime: the RTP time
677 * @packet_count: the packet count
678 * @octet_count: the octet count
680 * Set the given values in the SR packet @packet.
683 gst_rtcp_packet_sr_set_sender_info (GstRTCPPacket * packet, guint32 ssrc,
684 guint64 ntptime, guint32 rtptime, guint32 packet_count, guint32 octet_count)
688 g_return_if_fail (packet != NULL);
689 g_return_if_fail (packet->type == GST_RTCP_TYPE_SR);
691 data = packet->rtcp->data;
694 data += packet->offset + 4;
695 GST_WRITE_UINT32_BE (data, ssrc);
697 GST_WRITE_UINT64_BE (data, ntptime);
699 GST_WRITE_UINT32_BE (data, rtptime);
701 GST_WRITE_UINT32_BE (data, packet_count);
703 GST_WRITE_UINT32_BE (data, octet_count);
707 * gst_rtcp_packet_rr_get_ssrc:
708 * @packet: a valid RR #GstRTCPPacket
710 * Get the ssrc field of the RR @packet.
715 gst_rtcp_packet_rr_get_ssrc (GstRTCPPacket * packet)
720 g_return_val_if_fail (packet != NULL, 0);
721 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_RR, 0);
723 data = packet->rtcp->data;
726 data += packet->offset + 4;
727 ssrc = GST_READ_UINT32_BE (data);
733 * gst_rtcp_packet_rr_set_ssrc:
734 * @packet: a valid RR #GstRTCPPacket
735 * @ssrc: the SSRC to set
737 * Set the ssrc field of the RR @packet.
740 gst_rtcp_packet_rr_set_ssrc (GstRTCPPacket * packet, guint32 ssrc)
744 g_return_if_fail (packet != NULL);
745 g_return_if_fail (packet->type == GST_RTCP_TYPE_RR);
747 data = packet->rtcp->data;
750 data += packet->offset + 4;
751 GST_WRITE_UINT32_BE (data, ssrc);
755 * gst_rtcp_packet_get_rb_count:
756 * @packet: a valid SR or RR #GstRTCPPacket
758 * Get the number of report blocks in @packet.
760 * Returns: The number of report blocks in @packet.
763 gst_rtcp_packet_get_rb_count (GstRTCPPacket * packet)
765 g_return_val_if_fail (packet != NULL, 0);
766 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_RR ||
767 packet->type == GST_RTCP_TYPE_SR, 0);
769 return packet->count;
773 * gst_rtcp_packet_get_rb:
774 * @packet: a valid SR or RR #GstRTCPPacket
775 * @nth: the nth report block in @packet
776 * @ssrc: result for data source being reported
777 * @fractionlost: result for fraction lost since last SR/RR
778 * @packetslost: result for the cumululative number of packets lost
779 * @exthighestseq: result for the extended last sequence number received
780 * @jitter: result for the interarrival jitter
781 * @lsr: result for the last SR packet from this source
782 * @dlsr: result for the delay since last SR packet
784 * Parse the values of the @nth report block in @packet and store the result in
788 gst_rtcp_packet_get_rb (GstRTCPPacket * packet, guint nth, guint32 * ssrc,
789 guint8 * fractionlost, gint32 * packetslost, guint32 * exthighestseq,
790 guint32 * jitter, guint32 * lsr, guint32 * dlsr)
795 g_return_if_fail (packet != NULL);
796 g_return_if_fail (packet->type == GST_RTCP_TYPE_RR ||
797 packet->type == GST_RTCP_TYPE_SR);
799 data = packet->rtcp->data;
802 data += packet->offset + 4;
803 if (packet->type == GST_RTCP_TYPE_RR)
808 /* move to requested index */
812 *ssrc = GST_READ_UINT32_BE (data);
814 tmp = GST_READ_UINT32_BE (data);
816 *fractionlost = (tmp >> 24);
819 if (tmp & 0x00800000)
823 *packetslost = (gint32) tmp;
827 *exthighestseq = GST_READ_UINT32_BE (data);
830 *jitter = GST_READ_UINT32_BE (data);
833 *lsr = GST_READ_UINT32_BE (data);
836 *dlsr = GST_READ_UINT32_BE (data);
840 * gst_rtcp_packet_add_rb:
841 * @packet: a valid SR or RR #GstRTCPPacket
842 * @ssrc: data source being reported
843 * @fractionlost: fraction lost since last SR/RR
844 * @packetslost: the cumululative number of packets lost
845 * @exthighestseq: the extended last sequence number received
846 * @jitter: the interarrival jitter
847 * @lsr: the last SR packet from this source
848 * @dlsr: the delay since last SR packet
850 * Add a new report block to @packet with the given values.
852 * Returns: %TRUE if the packet was created. This function can return %FALSE if
853 * the max MTU is exceeded or the number of report blocks is greater than
854 * #GST_RTCP_MAX_RB_COUNT.
857 gst_rtcp_packet_add_rb (GstRTCPPacket * packet, guint32 ssrc,
858 guint8 fractionlost, gint32 packetslost, guint32 exthighestseq,
859 guint32 jitter, guint32 lsr, guint32 dlsr)
864 g_return_val_if_fail (packet != NULL, FALSE);
865 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_RR ||
866 packet->type == GST_RTCP_TYPE_SR, FALSE);
868 if (packet->count >= GST_RTCP_MAX_RB_COUNT)
871 data = packet->rtcp->data;
872 size = packet->rtcp->size;
875 offset = packet->offset + 4;
876 if (packet->type == GST_RTCP_TYPE_RR)
881 /* move to current index */
882 offset += (packet->count * 24);
884 /* we need 24 free bytes now */
885 if (offset + 24 >= size)
888 /* increment packet count and length */
890 data[packet->offset]++;
892 data[packet->offset + 2] = (packet->length) >> 8;
893 data[packet->offset + 3] = (packet->length) & 0xff;
895 /* move to new report block offset */
898 GST_WRITE_UINT32_BE (data, ssrc);
900 GST_WRITE_UINT32_BE (data, (fractionlost << 24) | (packetslost & 0xffffff));
902 GST_WRITE_UINT32_BE (data, exthighestseq);
904 GST_WRITE_UINT32_BE (data, jitter);
906 GST_WRITE_UINT32_BE (data, lsr);
908 GST_WRITE_UINT32_BE (data, dlsr);
919 * gst_rtcp_packet_set_rb:
920 * @packet: a valid SR or RR #GstRTCPPacket
921 * @nth: the nth report block to set
922 * @ssrc: data source being reported
923 * @fractionlost: fraction lost since last SR/RR
924 * @packetslost: the cumululative number of packets lost
925 * @exthighestseq: the extended last sequence number received
926 * @jitter: the interarrival jitter
927 * @lsr: the last SR packet from this source
928 * @dlsr: the delay since last SR packet
930 * Set the @nth new report block in @packet with the given values.
932 * Note: Not implemented.
935 gst_rtcp_packet_set_rb (GstRTCPPacket * packet, guint nth, guint32 ssrc,
936 guint8 fractionlost, gint32 packetslost, guint32 exthighestseq,
937 guint32 jitter, guint32 lsr, guint32 dlsr)
939 g_return_if_fail (packet != NULL);
940 g_return_if_fail (packet->type == GST_RTCP_TYPE_RR ||
941 packet->type == GST_RTCP_TYPE_SR);
943 g_warning ("not implemented");
948 * gst_rtcp_packet_sdes_get_item_count:
949 * @packet: a valid SDES #GstRTCPPacket
951 * Get the number of items in the SDES packet @packet.
953 * Returns: The number of items in @packet.
956 gst_rtcp_packet_sdes_get_item_count (GstRTCPPacket * packet)
958 g_return_val_if_fail (packet != NULL, 0);
959 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, 0);
961 return packet->count;
965 * gst_rtcp_packet_sdes_first_item:
966 * @packet: a valid SDES #GstRTCPPacket
968 * Move to the first SDES item in @packet.
970 * Returns: TRUE if there was a first item.
973 gst_rtcp_packet_sdes_first_item (GstRTCPPacket * packet)
975 g_return_val_if_fail (packet != NULL, FALSE);
976 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, FALSE);
978 packet->item_offset = 4;
979 packet->item_count = 0;
980 packet->entry_offset = 4;
982 if (packet->count == 0)
989 * gst_rtcp_packet_sdes_next_item:
990 * @packet: a valid SDES #GstRTCPPacket
992 * Move to the next SDES item in @packet.
994 * Returns: TRUE if there was a next item.
997 gst_rtcp_packet_sdes_next_item (GstRTCPPacket * packet)
1003 g_return_val_if_fail (packet != NULL, FALSE);
1004 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, FALSE);
1006 /* if we are at the last item, we are done */
1007 if (packet->item_count == packet->count)
1011 data = packet->rtcp->data;
1012 data += packet->offset;
1014 offset = packet->item_offset;
1019 len = (packet->length << 2);
1021 while (offset < len) {
1022 if (data[offset] == 0) {
1023 /* end of list, round to next 32-bit word */
1024 offset = (offset + 4) & ~3;
1027 offset += data[offset + 1] + 2;
1032 packet->item_offset = offset;
1033 packet->item_count++;
1034 packet->entry_offset = 4;
1040 * gst_rtcp_packet_sdes_get_ssrc:
1041 * @packet: a valid SDES #GstRTCPPacket
1043 * Get the SSRC of the current SDES item.
1045 * Returns: the SSRC of the current item.
1048 gst_rtcp_packet_sdes_get_ssrc (GstRTCPPacket * packet)
1053 g_return_val_if_fail (packet != NULL, 0);
1054 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, 0);
1057 data = packet->rtcp->data;
1058 data += packet->offset;
1060 data += packet->item_offset;
1062 ssrc = GST_READ_UINT32_BE (data);
1068 * gst_rtcp_packet_sdes_first_entry:
1069 * @packet: a valid SDES #GstRTCPPacket
1071 * Move to the first SDES entry in the current item.
1073 * Returns: %TRUE if there was a first entry.
1076 gst_rtcp_packet_sdes_first_entry (GstRTCPPacket * packet)
1081 g_return_val_if_fail (packet != NULL, FALSE);
1082 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, FALSE);
1085 data = packet->rtcp->data;
1086 data += packet->offset;
1088 offset = packet->item_offset;
1092 packet->entry_offset = 4;
1095 len = (packet->length << 2);
1099 if (data[offset] == 0)
1106 * gst_rtcp_packet_sdes_next_entry:
1107 * @packet: a valid SDES #GstRTCPPacket
1109 * Move to the next SDES entry in the current item.
1111 * Returns: %TRUE if there was a next entry.
1114 gst_rtcp_packet_sdes_next_entry (GstRTCPPacket * packet)
1117 guint len, offset, item_len;
1119 g_return_val_if_fail (packet != NULL, FALSE);
1120 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, FALSE);
1123 data = packet->rtcp->data;
1124 data += packet->offset;
1126 offset = packet->item_offset;
1128 offset += packet->entry_offset;
1130 item_len = data[offset + 1] + 2;
1135 len = (packet->length << 2);
1139 packet->entry_offset += item_len;
1141 /* check for end of list */
1142 if (data[offset] == 0)
1149 * gst_rtcp_packet_sdes_get_entry:
1150 * @packet: a valid SDES #GstRTCPPacket
1151 * @type: result of the entry type
1152 * @len: result length of the entry data
1153 * @data: result entry data
1155 * Get the data of the current SDES item entry. @type (when not NULL) will
1156 * contain the type of the entry. @data (when not NULL) will point to @len
1159 * When @type refers to a text item, @data will point to a UTF8 string. Note
1160 * that this UTF8 string is NOT null-terminated. Use
1161 * gst_rtcp_packet_sdes_copy_entry() to get a null-terminated copy of the entry.
1163 * Returns: %TRUE if there was valid data.
1166 gst_rtcp_packet_sdes_get_entry (GstRTCPPacket * packet,
1167 GstRTCPSDESType * type, guint8 * len, guint8 ** data)
1172 g_return_val_if_fail (packet != NULL, FALSE);
1173 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, FALSE);
1176 bdata = packet->rtcp->data;
1177 bdata += packet->offset;
1179 offset = packet->item_offset;
1181 offset += packet->entry_offset;
1183 if (bdata[offset] == 0)
1187 *type = bdata[offset];
1189 *len = bdata[offset + 1];
1191 *data = &bdata[offset + 2];
1197 * gst_rtcp_packet_sdes_copy_entry:
1198 * @packet: a valid SDES #GstRTCPPacket
1199 * @type: result of the entry type
1200 * @len: result length of the entry data
1201 * @data: result entry data
1203 * This function is like gst_rtcp_packet_sdes_get_entry() but it returns a
1204 * null-terminated copy of the data instead. use g_free() after usage.
1206 * Returns: %TRUE if there was valid data.
1209 gst_rtcp_packet_sdes_copy_entry (GstRTCPPacket * packet,
1210 GstRTCPSDESType * type, guint8 * len, guint8 ** data)
1215 g_return_val_if_fail (packet != NULL, FALSE);
1216 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, FALSE);
1218 if (!gst_rtcp_packet_sdes_get_entry (packet, type, &tlen, &tdata))
1224 *data = (guint8 *) g_strndup ((gchar *) tdata, tlen);
1230 * gst_rtcp_packet_sdes_add_item:
1231 * @packet: a valid SDES #GstRTCPPacket
1232 * @ssrc: the SSRC of the new item to add
1234 * Add a new SDES item for @ssrc to @packet.
1236 * Returns: %TRUE if the item could be added, %FALSE if the maximum amount of
1237 * items has been exceeded for the SDES packet or the MTU has been reached.
1240 gst_rtcp_packet_sdes_add_item (GstRTCPPacket * packet, guint32 ssrc)
1245 g_return_val_if_fail (packet != NULL, FALSE);
1246 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, FALSE);
1248 /* increment item count when possible */
1249 if (packet->count >= GST_RTCP_MAX_SDES_ITEM_COUNT)
1252 /* pretend there is a next packet for the next call */
1255 /* jump over current item */
1256 gst_rtcp_packet_sdes_next_item (packet);
1259 data = packet->rtcp->data;
1260 size = packet->rtcp->size;
1261 data += packet->offset;
1262 /* move to current item */
1263 offset = packet->item_offset;
1265 /* we need 2 free words now */
1266 if (offset + 8 >= size)
1270 GST_WRITE_UINT32_BE (&data[offset], ssrc);
1271 /* write 0 entry with padding */
1272 GST_WRITE_UINT32_BE (&data[offset + 4], 0);
1275 data[0] = (data[0] & 0xe0) | packet->count;
1276 /* update length, we added 2 words */
1277 packet->length += 2;
1278 data[2] = (packet->length) >> 8;
1279 data[3] = (packet->length) & 0xff;
1296 * gst_rtcp_packet_sdes_add_entry:
1297 * @packet: a valid SDES #GstRTCPPacket
1298 * @type: the #GstRTCPSDESType of the SDES entry
1299 * @len: the data length
1302 * Add a new SDES entry to the current item in @packet.
1304 * Returns: %TRUE if the item could be added, %FALSE if the MTU has been
1308 gst_rtcp_packet_sdes_add_entry (GstRTCPPacket * packet, GstRTCPSDESType type,
1309 guint8 len, const guint8 * data)
1312 guint offset, size, padded;
1314 g_return_val_if_fail (packet != NULL, FALSE);
1315 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, FALSE);
1318 bdata = packet->rtcp->data;
1319 size = packet->rtcp->size;
1320 bdata += packet->offset;
1322 offset = packet->item_offset;
1324 offset += packet->entry_offset;
1326 /* add 1 byte end and up to 3 bytes padding to fill a full 32 bit word */
1327 padded = (offset + 2 + len + 1 + 3) & ~3;
1329 /* we need enough space for type, len, data and padding */
1330 if (packet->offset + padded >= size)
1333 bdata[offset] = type;
1334 bdata[offset + 1] = len;
1335 memcpy (&bdata[offset + 2], data, len);
1336 bdata[offset + 2 + len] = 0;
1338 /* calculate new packet length */
1339 packet->length = (padded - 4) >> 2;
1340 bdata[2] = (packet->length) >> 8;
1341 bdata[3] = (packet->length) & 0xff;
1343 /* position to new next entry */
1344 packet->entry_offset += 2 + len;
1356 * gst_rtcp_packet_bye_get_ssrc_count:
1357 * @packet: a valid BYE #GstRTCPPacket
1359 * Get the number of SSRC fields in @packet.
1361 * Returns: The number of SSRC fields in @packet.
1364 gst_rtcp_packet_bye_get_ssrc_count (GstRTCPPacket * packet)
1366 g_return_val_if_fail (packet != NULL, -1);
1367 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_BYE, -1);
1369 return packet->count;
1373 * gst_rtcp_packet_bye_get_nth_ssrc:
1374 * @packet: a valid BYE #GstRTCPPacket
1375 * @nth: the nth SSRC to get
1377 * Get the @nth SSRC of the BYE @packet.
1379 * Returns: The @nth SSRC of @packet.
1382 gst_rtcp_packet_bye_get_nth_ssrc (GstRTCPPacket * packet, guint nth)
1389 g_return_val_if_fail (packet != NULL, 0);
1390 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_BYE, 0);
1392 /* get amount of sources and check that we don't read too much */
1397 /* get offset in 32-bits words into packet, skip the header */
1399 /* check that we don't go past the packet length */
1400 if (offset > packet->length)
1403 /* scale to bytes */
1405 offset += packet->offset;
1407 /* check if the packet is valid */
1408 if (offset + 4 > packet->rtcp->size)
1411 data = packet->rtcp->data;
1414 ssrc = GST_READ_UINT32_BE (data);
1420 * gst_rtcp_packet_bye_add_ssrc:
1421 * @packet: a valid BYE #GstRTCPPacket
1422 * @ssrc: an SSRC to add
1424 * Add @ssrc to the BYE @packet.
1426 * Returns: %TRUE if the ssrc was added. This function can return %FALSE if
1427 * the max MTU is exceeded or the number of sources blocks is greater than
1428 * #GST_RTCP_MAX_BYE_SSRC_COUNT.
1431 gst_rtcp_packet_bye_add_ssrc (GstRTCPPacket * packet, guint32 ssrc)
1436 g_return_val_if_fail (packet != NULL, FALSE);
1437 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_BYE, FALSE);
1439 if (packet->count >= GST_RTCP_MAX_BYE_SSRC_COUNT)
1442 data = packet->rtcp->data;
1443 size = packet->rtcp->size;
1446 offset = packet->offset + 4;
1448 /* move to current index */
1449 offset += (packet->count * 4);
1451 if (offset + 4 >= size)
1454 /* increment packet count and length */
1456 data[packet->offset]++;
1457 packet->length += 1;
1458 data[packet->offset + 2] = (packet->length) >> 8;
1459 data[packet->offset + 3] = (packet->length) & 0xff;
1461 /* move to new SSRC offset and write ssrc */
1463 GST_WRITE_UINT32_BE (data, ssrc);
1475 * gst_rtcp_packet_bye_add_ssrcs:
1476 * @packet: a valid BYE #GstRTCPPacket
1477 * @ssrc: an array of SSRCs to add
1478 * @len: number of elements in @ssrc
1480 * Adds @len SSRCs in @ssrc to BYE @packet.
1482 * Returns: %TRUE if the all the SSRCs were added. This function can return %FALSE if
1483 * the max MTU is exceeded or the number of sources blocks is greater than
1484 * #GST_RTCP_MAX_BYE_SSRC_COUNT.
1487 gst_rtcp_packet_bye_add_ssrcs (GstRTCPPacket * packet, guint32 * ssrc,
1493 g_return_val_if_fail (packet != NULL, FALSE);
1494 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_BYE, FALSE);
1497 for (i = 0; i < len && res; i++) {
1498 res = gst_rtcp_packet_bye_add_ssrc (packet, ssrc[i]);
1503 /* get the offset in packet of the reason length */
1505 get_reason_offset (GstRTCPPacket * packet)
1509 /* get amount of sources plus header */
1510 offset = 1 + packet->count;
1512 /* check that we don't go past the packet length */
1513 if (offset > packet->length)
1516 /* scale to bytes */
1518 offset += packet->offset;
1520 /* check if the packet is valid */
1521 if (offset + 1 > packet->rtcp->size)
1528 * gst_rtcp_packet_bye_get_reason_len:
1529 * @packet: a valid BYE #GstRTCPPacket
1531 * Get the length of the reason string.
1533 * Returns: The length of the reason string or 0 when there is no reason string
1537 gst_rtcp_packet_bye_get_reason_len (GstRTCPPacket * packet)
1542 g_return_val_if_fail (packet != NULL, 0);
1543 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_BYE, 0);
1545 roffset = get_reason_offset (packet);
1549 data = packet->rtcp->data;
1551 return data[roffset];
1555 * gst_rtcp_packet_bye_get_reason:
1556 * @packet: a valid BYE #GstRTCPPacket
1558 * Get the reason in @packet.
1560 * Returns: The reason for the BYE @packet or NULL if the packet did not contain
1561 * a reason string. The string must be freed with g_free() after usage.
1564 gst_rtcp_packet_bye_get_reason (GstRTCPPacket * packet)
1570 g_return_val_if_fail (packet != NULL, NULL);
1571 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_BYE, NULL);
1573 roffset = get_reason_offset (packet);
1577 data = packet->rtcp->data;
1579 /* get length of reason string */
1580 len = data[roffset];
1584 /* move to string */
1587 /* check if enough data to copy */
1588 if (roffset + len > packet->rtcp->size)
1591 return g_strndup ((gconstpointer) (data + roffset), len);
1595 * gst_rtcp_packet_bye_set_reason:
1596 * @packet: a valid BYE #GstRTCPPacket
1597 * @reason: a reason string
1599 * Set the reason string to @reason in @packet.
1601 * Returns: TRUE if the string could be set.
1604 gst_rtcp_packet_bye_set_reason (GstRTCPPacket * packet, const gchar * reason)
1607 guint roffset, size;
1610 g_return_val_if_fail (packet != NULL, FALSE);
1611 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_BYE, FALSE);
1616 len = strlen (reason);
1620 /* make room for the string before we get the offset */
1623 roffset = get_reason_offset (packet);
1627 data = packet->rtcp->data;
1628 size = packet->rtcp->size;
1630 /* we have 1 byte length and we need to pad to 4 bytes */
1631 padded = ((len + 1) + 3) & ~3;
1633 /* we need enough space for the padded length */
1634 if (roffset + padded >= size)
1637 data[roffset] = len;
1638 memcpy (&data[roffset + 1], reason, len);
1640 /* update packet length, we made room for 1 double word already */
1641 packet->length += (padded >> 2) - 1;
1642 data[packet->offset + 2] = (packet->length) >> 8;
1643 data[packet->offset + 3] = (packet->length) & 0xff;
1656 * gst_rtcp_packet_fb_get_sender_ssrc:
1657 * @packet: a valid RTPFB or PSFB #GstRTCPPacket
1659 * Get the sender SSRC field of the RTPFB or PSFB @packet.
1661 * Returns: the sender SSRC.
1666 gst_rtcp_packet_fb_get_sender_ssrc (GstRTCPPacket * packet)
1671 g_return_val_if_fail (packet != NULL, 0);
1672 g_return_val_if_fail ((packet->type == GST_RTCP_TYPE_RTPFB ||
1673 packet->type == GST_RTCP_TYPE_PSFB), 0);
1675 data = packet->rtcp->data;
1678 data += packet->offset + 4;
1679 ssrc = GST_READ_UINT32_BE (data);
1685 * gst_rtcp_packet_fb_set_sender_ssrc:
1686 * @packet: a valid RTPFB or PSFB #GstRTCPPacket
1687 * @ssrc: a sender SSRC
1689 * Set the sender SSRC field of the RTPFB or PSFB @packet.
1694 gst_rtcp_packet_fb_set_sender_ssrc (GstRTCPPacket * packet, guint32 ssrc)
1698 g_return_if_fail (packet != NULL);
1699 g_return_if_fail (packet->type == GST_RTCP_TYPE_RTPFB ||
1700 packet->type == GST_RTCP_TYPE_PSFB);
1702 data = packet->rtcp->data;
1705 data += packet->offset + 4;
1706 GST_WRITE_UINT32_BE (data, ssrc);
1710 * gst_rtcp_packet_fb_get_media_ssrc:
1711 * @packet: a valid RTPFB or PSFB #GstRTCPPacket
1713 * Get the media SSRC field of the RTPFB or PSFB @packet.
1715 * Returns: the media SSRC.
1720 gst_rtcp_packet_fb_get_media_ssrc (GstRTCPPacket * packet)
1725 g_return_val_if_fail (packet != NULL, 0);
1726 g_return_val_if_fail ((packet->type == GST_RTCP_TYPE_RTPFB ||
1727 packet->type == GST_RTCP_TYPE_PSFB), 0);
1729 data = packet->rtcp->data;
1731 /* skip header and sender ssrc */
1732 data += packet->offset + 8;
1733 ssrc = GST_READ_UINT32_BE (data);
1739 * gst_rtcp_packet_fb_set_media_ssrc:
1740 * @packet: a valid RTPFB or PSFB #GstRTCPPacket
1741 * @ssrc: a media SSRC
1743 * Set the media SSRC field of the RTPFB or PSFB @packet.
1748 gst_rtcp_packet_fb_set_media_ssrc (GstRTCPPacket * packet, guint32 ssrc)
1752 g_return_if_fail (packet != NULL);
1753 g_return_if_fail (packet->type == GST_RTCP_TYPE_RTPFB ||
1754 packet->type == GST_RTCP_TYPE_PSFB);
1756 data = packet->rtcp->data;
1758 /* skip header and sender ssrc */
1759 data += packet->offset + 8;
1760 GST_WRITE_UINT32_BE (data, ssrc);
1764 * gst_rtcp_packet_fb_get_type:
1765 * @packet: a valid RTPFB or PSFB #GstRTCPPacket
1767 * Get the feedback message type of the FB @packet.
1769 * Returns: The feedback message type.
1774 gst_rtcp_packet_fb_get_type (GstRTCPPacket * packet)
1776 g_return_val_if_fail (packet != NULL, GST_RTCP_FB_TYPE_INVALID);
1777 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_RTPFB ||
1778 packet->type == GST_RTCP_TYPE_PSFB, GST_RTCP_FB_TYPE_INVALID);
1780 return packet->count;
1784 * gst_rtcp_packet_fb_set_type:
1785 * @packet: a valid RTPFB or PSFB #GstRTCPPacket
1786 * @type: the #GstRTCPFBType to set
1788 * Set the feedback message type of the FB @packet.
1793 gst_rtcp_packet_fb_set_type (GstRTCPPacket * packet, GstRTCPFBType type)
1797 g_return_if_fail (packet != NULL);
1798 g_return_if_fail (packet->type == GST_RTCP_TYPE_RTPFB ||
1799 packet->type == GST_RTCP_TYPE_PSFB);
1801 data = packet->rtcp->data;
1803 data[packet->offset] = (data[packet->offset] & 0xe0) | type;
1804 packet->count = type;
1808 * gst_rtcp_ntp_to_unix:
1809 * @ntptime: an NTP timestamp
1811 * Converts an NTP time to UNIX nanoseconds. @ntptime can typically be
1812 * the NTP time of an SR RTCP message and contains, in the upper 32 bits, the
1813 * number of seconds since 1900 and, in the lower 32 bits, the fractional
1814 * seconds. The resulting value will be the number of nanoseconds since 1970.
1816 * Returns: the UNIX time for @ntptime in nanoseconds.
1819 gst_rtcp_ntp_to_unix (guint64 ntptime)
1823 /* conversion from NTP timestamp (seconds since 1900) to seconds since
1825 unixtime = ntptime - (G_GUINT64_CONSTANT (2208988800) << 32);
1826 /* conversion to nanoseconds */
1828 gst_util_uint64_scale (unixtime, GST_SECOND,
1829 (G_GINT64_CONSTANT (1) << 32));
1835 * gst_rtcp_unix_to_ntp:
1836 * @unixtime: an UNIX timestamp in nanoseconds
1838 * Converts a UNIX timestamp in nanoseconds to an NTP time. The caller should
1839 * pass a value with nanoseconds since 1970. The NTP time will, in the upper
1840 * 32 bits, contain the number of seconds since 1900 and, in the lower 32
1841 * bits, the fractional seconds. The resulting value can be used as an ntptime
1842 * for constructing SR RTCP packets.
1844 * Returns: the NTP time for @unixtime.
1847 gst_rtcp_unix_to_ntp (guint64 unixtime)
1851 /* convert clock time to NTP time. upper 32 bits should contain the seconds
1852 * and the lower 32 bits, the fractions of a second. */
1854 gst_util_uint64_scale (unixtime, (G_GINT64_CONSTANT (1) << 32),
1856 /* conversion from UNIX timestamp (seconds since 1970) to NTP (seconds
1858 ntptime += (G_GUINT64_CONSTANT (2208988800) << 32);
1864 * gst_rtcp_sdes_type_to_name:
1865 * @type: a #GstRTCPSDESType
1867 * Converts @type to the string equivalent. The string is typically used as a
1868 * key in a #GstStructure containing SDES items.
1870 * Returns: the string equivalent of @type
1875 gst_rtcp_sdes_type_to_name (GstRTCPSDESType type)
1877 const gchar *result;
1880 case GST_RTCP_SDES_CNAME:
1883 case GST_RTCP_SDES_NAME:
1886 case GST_RTCP_SDES_EMAIL:
1889 case GST_RTCP_SDES_PHONE:
1892 case GST_RTCP_SDES_LOC:
1893 result = "location";
1895 case GST_RTCP_SDES_TOOL:
1898 case GST_RTCP_SDES_NOTE:
1901 case GST_RTCP_SDES_PRIV:
1912 * gst_rtcp_sdes_name_to_type:
1913 * @name: a SDES name
1915 * Convert @name into a @GstRTCPSDESType. @name is typically a key in a
1916 * #GstStructure containing SDES items.
1918 * Returns: the #GstRTCPSDESType for @name or #GST_RTCP_SDES_PRIV when @name
1919 * is a private sdes item.
1924 gst_rtcp_sdes_name_to_type (const gchar * name)
1926 if (name == NULL || strlen (name) == 0)
1927 return GST_RTCP_SDES_INVALID;
1929 if (strcmp ("cname", name) == 0)
1930 return GST_RTCP_SDES_CNAME;
1932 if (strcmp ("name", name) == 0)
1933 return GST_RTCP_SDES_NAME;
1935 if (strcmp ("email", name) == 0)
1936 return GST_RTCP_SDES_EMAIL;
1938 if (strcmp ("phone", name) == 0)
1939 return GST_RTCP_SDES_PHONE;
1941 if (strcmp ("location", name) == 0)
1942 return GST_RTCP_SDES_LOC;
1944 if (strcmp ("tool", name) == 0)
1945 return GST_RTCP_SDES_TOOL;
1947 if (strcmp ("note", name) == 0)
1948 return GST_RTCP_SDES_NOTE;
1950 return GST_RTCP_SDES_PRIV;
1954 * gst_rtcp_packet_fb_get_fci_length:
1955 * @packet: a valid RTPFB or PSFB #GstRTCPPacket
1957 * Get the length of the Feedback Control Information attached to a
1958 * RTPFB or PSFB @packet.
1960 * Returns: The length of the FCI in 32-bit words.
1965 gst_rtcp_packet_fb_get_fci_length (GstRTCPPacket * packet)
1969 g_return_val_if_fail (packet != NULL, 0);
1970 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_RTPFB ||
1971 packet->type == GST_RTCP_TYPE_PSFB, 0);
1973 data = packet->rtcp->data + packet->offset + 2;
1975 return GST_READ_UINT16_BE (data) - 2;
1979 * gst_rtcp_packet_fb_set_fci_length:
1980 * @packet: a valid RTPFB or PSFB #GstRTCPPacket
1981 * @wordlen: Length of the FCI in 32-bit words
1983 * Set the length of the Feedback Control Information attached to a
1984 * RTPFB or PSFB @packet.
1986 * Returns: %TRUE if there was enough space in the packet to add this much FCI
1991 gst_rtcp_packet_fb_set_fci_length (GstRTCPPacket * packet, guint16 wordlen)
1995 g_return_val_if_fail (packet != NULL, FALSE);
1996 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_RTPFB ||
1997 packet->type == GST_RTCP_TYPE_PSFB, FALSE);
1999 if (packet->rtcp->size < packet->offset + ((wordlen + 3) * 4))
2002 data = packet->rtcp->data + packet->offset + 2;
2004 GST_WRITE_UINT16_BE (data, wordlen);
2010 * gst_rtcp_packet_fb_get_fci:
2011 * @packet: a valid RTPFB or PSFB #GstRTCPPacket
2013 * Get the Feedback Control Information attached to a RTPFB or PSFB @packet.
2015 * Returns: a pointer to the FCI
2020 gst_rtcp_packet_fb_get_fci (GstRTCPPacket * packet)
2024 g_return_val_if_fail (packet != NULL, NULL);
2025 g_return_val_if_fail (packet->type == GST_RTCP_TYPE_RTPFB ||
2026 packet->type == GST_RTCP_TYPE_PSFB, NULL);
2028 data = packet->rtcp->data + packet->offset;
2030 if (GST_READ_UINT16_BE (data + 2) <= 2)