fb99c4a7f184db5ae2c381c40d0694120a6b5a4d
[platform/upstream/gstreamer.git] / gst-libs / gst / rtp / gstrtcpbuffer.c
1 /* GStreamer
2  * Copyright (C) <2007> Wim Taymans <wim@fluendo.com>
3  *
4  * gstrtcpbuffer.h: various helper functions to manipulate buffers
5  *     with RTCP payload.
6  *
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.
11  *
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.
16  *
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.
21  */
22
23 /**
24  * SECTION:gstrtcpbuffer
25  * @short_description: Helper methods for dealing with RTCP buffers
26  * @see_also: #GstRTPBasePayload, #GstRTPBaseDepayload, #gstrtpbuffer
27  *
28  * Note: The API in this module is not yet declared stable.
29  *
30  * <refsect2>
31  * <para>
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.
35  * </para>
36  * <para>
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().
41  * </para>
42  * </refsect2>
43  *
44  * Last reviewed on 2007-03-26 (0.10.13)
45  *
46  * Since: 0.10.13
47  */
48
49 #include <string.h>
50
51 #include "gstrtcpbuffer.h"
52
53 /**
54  * gst_rtcp_buffer_new_take_data:
55  * @data: data for the new buffer
56  * @len: the length of data
57  *
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.
61  *
62  * Returns: A newly allocated buffer with @data and of size @len.
63  */
64 GstBuffer *
65 gst_rtcp_buffer_new_take_data (gpointer data, guint len)
66 {
67   GstBuffer *result;
68
69   g_return_val_if_fail (data != NULL, NULL);
70   g_return_val_if_fail (len > 0, NULL);
71
72   result = gst_buffer_new ();
73   gst_buffer_take_memory (result, -1,
74       gst_memory_new_wrapped (0, data, g_free, len, 0, len));
75
76   return result;
77 }
78
79 /**
80  * gst_rtcp_buffer_new_copy_data:
81  * @data: data for the new buffer
82  * @len: the length of data
83  *
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
86  * is freed.
87  *
88  * Returns: A newly allocated buffer with a copy of @data and of size @len.
89  */
90 GstBuffer *
91 gst_rtcp_buffer_new_copy_data (gpointer data, guint len)
92 {
93   return gst_rtcp_buffer_new_take_data (g_memdup (data, len), len);
94 }
95
96 /**
97  * gst_rtcp_buffer_validate_data:
98  * @data: the data to validate
99  * @len: the length of @data to validate
100  *
101  * Check if the @data and @size point to the data of a valid RTCP (compound)
102  * packet. 
103  * Use this function to validate a packet before using the other functions in
104  * this module.
105  *
106  * Returns: TRUE if the data points to a valid RTCP packet.
107  */
108 gboolean
109 gst_rtcp_buffer_validate_data (guint8 * data, guint len)
110 {
111   guint16 header_mask;
112   guint header_len;
113   guint8 version;
114   guint data_len;
115   gboolean padding;
116   guint8 pad_bytes;
117
118   g_return_val_if_fail (data != NULL, FALSE);
119
120   /* we need 4 bytes for the type and length */
121   if (G_UNLIKELY (len < 4))
122     goto wrong_length;
123
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))
127     goto wrong_mask;
128
129   /* no padding when mask succeeds */
130   padding = FALSE;
131
132   /* store len */
133   data_len = len;
134
135   while (TRUE) {
136     /* get packet length */
137     header_len = (((data[2] << 8) | data[3]) + 1) << 2;
138     if (data_len < header_len)
139       goto wrong_length;
140
141     /* move to next compount packet */
142     data += header_len;
143     data_len -= header_len;
144
145     /* we are at the end now */
146     if (data_len < 4)
147       break;
148
149     /* check version of new packet */
150     version = data[0] & 0xc0;
151     if (version != (GST_RTCP_VERSION << 6))
152       goto wrong_version;
153
154     /* padding only allowed on last packet */
155     if ((padding = data[0] & 0x20))
156       break;
157   }
158   if (data_len > 0) {
159     /* some leftover bytes, check padding */
160     if (!padding)
161       goto wrong_length;
162
163     /* get padding */
164     pad_bytes = data[data_len - 1];
165     if (data_len != pad_bytes)
166       goto wrong_padding;
167   }
168   return TRUE;
169
170   /* ERRORS */
171 wrong_length:
172   {
173     GST_DEBUG ("len check failed");
174     return FALSE;
175   }
176 wrong_mask:
177   {
178     GST_DEBUG ("mask check failed (%04x != %04x)", header_mask,
179         GST_RTCP_VALID_VALUE);
180     return FALSE;
181   }
182 wrong_version:
183   {
184     GST_DEBUG ("wrong version (%d < 2)", version >> 6);
185     return FALSE;
186   }
187 wrong_padding:
188   {
189     GST_DEBUG ("padding check failed");
190     return FALSE;
191   }
192 }
193
194 /**
195  * gst_rtcp_buffer_validate:
196  * @buffer: the buffer to validate
197  *
198  * Check if the data pointed to by @buffer is a valid RTCP packet using
199  * gst_rtcp_buffer_validate_data().
200  *  
201  * Returns: TRUE if @buffer is a valid RTCP packet.
202  */
203 gboolean
204 gst_rtcp_buffer_validate (GstBuffer * buffer)
205 {
206   gboolean res;
207   guint8 *data;
208   gsize len;
209
210   g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
211
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);
215
216   return res;
217 }
218
219 /**
220  * gst_rtcp_buffer_new:
221  * @mtu: the maximum mtu size.
222  *
223  * Create a new buffer for constructing RTCP packets. The packet will have a
224  * maximum size of @mtu.
225  *
226  * Returns: A newly allocated buffer.
227  */
228 GstBuffer *
229 gst_rtcp_buffer_new (guint mtu)
230 {
231   GstBuffer *result;
232
233   g_return_val_if_fail (mtu > 0, NULL);
234
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));
238
239   return result;
240 }
241
242 /**
243  * gst_rtcp_buffer_map:
244  * @buffer: a buffer with an RTCP packet
245  * @flags: flags for the mapping
246  * @rtcp: resulting #GstRTCPBuffer
247  *
248  * Open @buffer for reading or writing, depending on @flags. The resulting RTCP
249  * buffer state is stored in @rtcp.
250  */
251 gboolean
252 gst_rtcp_buffer_map (GstBuffer * buffer, GstMapFlags flags,
253     GstRTCPBuffer * rtcp)
254 {
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);
258
259   rtcp->buffer = buffer;
260   rtcp->flags = flags;
261   rtcp->data = gst_buffer_map (buffer, &rtcp->size, &rtcp->maxsize, flags);
262
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);
268   }
269
270   return TRUE;
271 }
272
273 /**
274  * gst_rtcp_buffer_unmap:
275  * @rtcp: a buffer with an RTCP packet
276  *
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.
279  *
280  * The function adjusts the size of @rtcp with the total length of all the
281  * added packets.
282  */
283 gboolean
284 gst_rtcp_buffer_unmap (GstRTCPBuffer * rtcp)
285 {
286   gboolean res;
287   GstRTCPPacket packet;
288
289   g_return_val_if_fail (rtcp != NULL, FALSE);
290   g_return_val_if_fail (GST_IS_BUFFER (rtcp->buffer), FALSE);
291
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));
295
296   /* shrink size */
297   res = gst_buffer_unmap (rtcp->buffer, rtcp->data, packet.offset);
298   rtcp->buffer = NULL;
299
300   return res;
301 }
302
303 /**
304  * gst_rtcp_buffer_get_packet_count:
305  * @rtcp: a valid RTCP buffer
306  *
307  * Get the number of RTCP packets in @rtcp.
308  *
309  * Returns: the number of RTCP packets in @rtcp.
310  */
311 guint
312 gst_rtcp_buffer_get_packet_count (GstRTCPBuffer * rtcp)
313 {
314   GstRTCPPacket packet;
315   guint count;
316
317   g_return_val_if_fail (rtcp != NULL, 0);
318   g_return_val_if_fail (GST_IS_BUFFER (rtcp->buffer), 0);
319
320   count = 0;
321   if (gst_rtcp_buffer_get_first_packet (rtcp, &packet)) {
322     do {
323       count++;
324     } while (gst_rtcp_packet_move_to_next (&packet));
325   }
326
327   return count;
328 }
329
330 /**
331  * read_packet_header:
332  * @packet: a packet
333  *
334  * Read the packet headers for the packet pointed to by @packet.
335  *
336  * Returns: TRUE if @packet pointed to a valid header.
337  */
338 static gboolean
339 read_packet_header (GstRTCPPacket * packet)
340 {
341   guint8 *data;
342   guint size;
343   guint offset;
344
345   g_return_val_if_fail (packet != NULL, FALSE);
346
347   data = packet->rtcp->data;
348   size = packet->rtcp->size;
349
350   offset = packet->offset;
351
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)
355     return FALSE;
356
357   if ((data[offset] & 0xc0) != (GST_RTCP_VERSION << 6))
358     return FALSE;
359
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;
368
369   return TRUE;
370 }
371
372 /**
373  * gst_rtcp_buffer_get_first_packet:
374  * @rtcp: a valid RTCP buffer
375  * @packet: a #GstRTCPPacket
376  *
377  * Initialize a new #GstRTCPPacket pointer that points to the first packet in
378  * @rtcp.
379  *
380  * Returns: TRUE if the packet existed in @rtcp.
381  */
382 gboolean
383 gst_rtcp_buffer_get_first_packet (GstRTCPBuffer * rtcp, GstRTCPPacket * packet)
384 {
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);
388
389   /* init to 0 */
390   packet->rtcp = rtcp;
391   packet->offset = 0;
392   packet->type = GST_RTCP_TYPE_INVALID;
393
394   if (!read_packet_header (packet))
395     return FALSE;
396
397   return TRUE;
398 }
399
400 /**
401  * gst_rtcp_packet_move_to_next:
402  * @packet: a #GstRTCPPacket
403  *
404  * Move the packet pointer @packet to the next packet in the payload.
405  * Use gst_rtcp_buffer_get_first_packet() to initialize @packet.
406  *
407  * Returns: TRUE if @packet is pointing to a valid packet after calling this
408  * function.
409  */
410 gboolean
411 gst_rtcp_packet_move_to_next (GstRTCPPacket * packet)
412 {
413   g_return_val_if_fail (packet != NULL, FALSE);
414   g_return_val_if_fail (packet->type != GST_RTCP_TYPE_INVALID, FALSE);
415
416   /* if we have a padding or invalid packet, it must be the last, 
417    * return FALSE */
418   if (packet->type == GST_RTCP_TYPE_INVALID || packet->padding)
419     goto end;
420
421   /* move to next packet. Add 4 because the header is not included in length */
422   packet->offset += (packet->length << 2) + 4;
423
424   /* try to read new header */
425   if (!read_packet_header (packet))
426     goto end;
427
428   return TRUE;
429
430   /* ERRORS */
431 end:
432   {
433     packet->type = GST_RTCP_TYPE_INVALID;
434     return FALSE;
435   }
436 }
437
438 /**
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
443  *
444  * Add a new packet of @type to @rtcp. @packet will point to the newly created 
445  * packet.
446  *
447  * Returns: %TRUE if the packet could be created. This function returns %FALSE
448  * if the max mtu is exceeded for the buffer.
449  */
450 gboolean
451 gst_rtcp_buffer_add_packet (GstRTCPBuffer * rtcp, GstRTCPType type,
452     GstRTCPPacket * packet)
453 {
454   guint len, size;
455   guint8 *data;
456   gboolean result;
457
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);
462
463   /* find free space */
464   if (gst_rtcp_buffer_get_first_packet (rtcp, packet))
465     while (gst_rtcp_packet_move_to_next (packet));
466
467   size = rtcp->size;
468
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. */
472   switch (type) {
473     case GST_RTCP_TYPE_SR:
474       len = 28;
475       break;
476     case GST_RTCP_TYPE_RR:
477       len = 8;
478       break;
479     case GST_RTCP_TYPE_SDES:
480       len = 4;
481       break;
482     case GST_RTCP_TYPE_BYE:
483       len = 4;
484       break;
485     case GST_RTCP_TYPE_APP:
486       len = 12;
487       break;
488     case GST_RTCP_TYPE_RTPFB:
489       len = 12;
490       break;
491     case GST_RTCP_TYPE_PSFB:
492       len = 12;
493       break;
494     default:
495       goto unknown_type;
496   }
497   if (packet->offset + len >= size)
498     goto no_space;
499
500   data = rtcp->data + packet->offset;
501
502   data[0] = (GST_RTCP_VERSION << 6);
503   data[1] = type;
504   /* length is stored in multiples of 32 bit words minus the length of the
505    * header */
506   len = (len - 4) >> 2;
507   data[2] = len >> 8;
508   data[3] = len & 0xff;
509
510   /* now try to position to the packet */
511   result = read_packet_header (packet);
512
513   return result;
514
515   /* ERRORS */
516 unknown_type:
517   {
518     g_warning ("unknown type %d", type);
519     return FALSE;
520   }
521 no_space:
522   {
523     return FALSE;
524   }
525 }
526
527 /**
528  * gst_rtcp_packet_remove:
529  * @packet: a #GstRTCPPacket
530  *
531  * Removes the packet pointed to by @packet and moves pointer to the next one
532  *
533  * Returns: TRUE if @packet is pointing to a valid packet after calling this
534  * function.
535  */
536 gboolean
537 gst_rtcp_packet_remove (GstRTCPPacket * packet)
538 {
539   gboolean ret = FALSE;
540   guint offset = 0;
541
542   g_return_val_if_fail (packet != NULL, FALSE);
543   g_return_val_if_fail (packet->type != GST_RTCP_TYPE_INVALID, FALSE);
544
545   /* The next packet starts at offset + length + 4 (the header) */
546   offset = packet->offset + (packet->length << 2) + 4;
547
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);
551
552   /* try to read next header */
553   ret = read_packet_header (packet);
554   if (!ret)
555     packet->type = GST_RTCP_TYPE_INVALID;
556
557   return ret;
558 }
559
560 /**
561  * gst_rtcp_packet_get_padding:
562  * @packet: a valid #GstRTCPPacket
563  *
564  * Get the packet padding of the packet pointed to by @packet.
565  *
566  * Returns: If the packet has the padding bit set.
567  */
568 gboolean
569 gst_rtcp_packet_get_padding (GstRTCPPacket * packet)
570 {
571   g_return_val_if_fail (packet != NULL, FALSE);
572   g_return_val_if_fail (packet->type != GST_RTCP_TYPE_INVALID, FALSE);
573
574   return packet->padding;
575 }
576
577 /**
578  * gst_rtcp_packet_get_type:
579  * @packet: a valid #GstRTCPPacket
580  *
581  * Get the packet type of the packet pointed to by @packet.
582  *
583  * Returns: The packet type or GST_RTCP_TYPE_INVALID when @packet is not
584  * pointing to a valid packet.
585  */
586 GstRTCPType
587 gst_rtcp_packet_get_type (GstRTCPPacket * packet)
588 {
589   g_return_val_if_fail (packet != NULL, GST_RTCP_TYPE_INVALID);
590
591   return packet->type;
592 }
593
594 /**
595  * gst_rtcp_packet_get_count:
596  * @packet: a valid #GstRTCPPacket
597  *
598  * Get the count field in @packet.
599  *
600  * Returns: The count field in @packet or -1 if @packet does not point to a
601  * valid packet.
602  */
603 guint8
604 gst_rtcp_packet_get_count (GstRTCPPacket * packet)
605 {
606   g_return_val_if_fail (packet != NULL, -1);
607   g_return_val_if_fail (packet->type != GST_RTCP_TYPE_INVALID, -1);
608
609   return packet->count;
610 }
611
612 /**
613  * gst_rtcp_packet_get_length:
614  * @packet: a valid #GstRTCPPacket
615  *
616  * Get the length field of @packet. This is the length of the packet in 
617  * 32-bit words minus one.
618  *
619  * Returns: The length field of @packet.
620  */
621 guint16
622 gst_rtcp_packet_get_length (GstRTCPPacket * packet)
623 {
624   g_return_val_if_fail (packet != NULL, 0);
625   g_return_val_if_fail (packet->type != GST_RTCP_TYPE_INVALID, 0);
626
627   return packet->length;
628 }
629
630 /**
631  * gst_rtcp_packet_sr_get_sender_info:
632  * @packet: a valid SR #GstRTCPPacket
633  * @ssrc: result SSRC
634  * @ntptime: result NTP time
635  * @rtptime: result RTP time
636  * @packet_count: result packet count
637  * @octet_count: result octet count
638  *
639  * Parse the SR sender info and store the values.
640  */
641 void
642 gst_rtcp_packet_sr_get_sender_info (GstRTCPPacket * packet, guint32 * ssrc,
643     guint64 * ntptime, guint32 * rtptime, guint32 * packet_count,
644     guint32 * octet_count)
645 {
646   guint8 *data;
647
648   g_return_if_fail (packet != NULL);
649   g_return_if_fail (packet->type == GST_RTCP_TYPE_SR);
650
651   data = packet->rtcp->data;
652
653   /* skip header */
654   data += packet->offset + 4;
655   if (ssrc)
656     *ssrc = GST_READ_UINT32_BE (data);
657   data += 4;
658   if (ntptime)
659     *ntptime = GST_READ_UINT64_BE (data);
660   data += 8;
661   if (rtptime)
662     *rtptime = GST_READ_UINT32_BE (data);
663   data += 4;
664   if (packet_count)
665     *packet_count = GST_READ_UINT32_BE (data);
666   data += 4;
667   if (octet_count)
668     *octet_count = GST_READ_UINT32_BE (data);
669 }
670
671 /**
672  * gst_rtcp_packet_sr_set_sender_info:
673  * @packet: a valid SR #GstRTCPPacket
674  * @ssrc: the SSRC 
675  * @ntptime: the NTP time
676  * @rtptime: the RTP time
677  * @packet_count: the packet count
678  * @octet_count: the octet count
679  *
680  * Set the given values in the SR packet @packet.
681  */
682 void
683 gst_rtcp_packet_sr_set_sender_info (GstRTCPPacket * packet, guint32 ssrc,
684     guint64 ntptime, guint32 rtptime, guint32 packet_count, guint32 octet_count)
685 {
686   guint8 *data;
687
688   g_return_if_fail (packet != NULL);
689   g_return_if_fail (packet->type == GST_RTCP_TYPE_SR);
690
691   data = packet->rtcp->data;
692
693   /* skip header */
694   data += packet->offset + 4;
695   GST_WRITE_UINT32_BE (data, ssrc);
696   data += 4;
697   GST_WRITE_UINT64_BE (data, ntptime);
698   data += 8;
699   GST_WRITE_UINT32_BE (data, rtptime);
700   data += 4;
701   GST_WRITE_UINT32_BE (data, packet_count);
702   data += 4;
703   GST_WRITE_UINT32_BE (data, octet_count);
704 }
705
706 /**
707  * gst_rtcp_packet_rr_get_ssrc:
708  * @packet: a valid RR #GstRTCPPacket
709  *
710  * Get the ssrc field of the RR @packet.
711  *
712  * Returns: the ssrc.
713  */
714 guint32
715 gst_rtcp_packet_rr_get_ssrc (GstRTCPPacket * packet)
716 {
717   guint8 *data;
718   guint32 ssrc;
719
720   g_return_val_if_fail (packet != NULL, 0);
721   g_return_val_if_fail (packet->type == GST_RTCP_TYPE_RR, 0);
722
723   data = packet->rtcp->data;
724
725   /* skip header */
726   data += packet->offset + 4;
727   ssrc = GST_READ_UINT32_BE (data);
728
729   return ssrc;
730 }
731
732 /**
733  * gst_rtcp_packet_rr_set_ssrc:
734  * @packet: a valid RR #GstRTCPPacket
735  * @ssrc: the SSRC to set
736  *
737  * Set the ssrc field of the RR @packet.
738  */
739 void
740 gst_rtcp_packet_rr_set_ssrc (GstRTCPPacket * packet, guint32 ssrc)
741 {
742   guint8 *data;
743
744   g_return_if_fail (packet != NULL);
745   g_return_if_fail (packet->type == GST_RTCP_TYPE_RR);
746
747   data = packet->rtcp->data;
748
749   /* skip header */
750   data += packet->offset + 4;
751   GST_WRITE_UINT32_BE (data, ssrc);
752 }
753
754 /**
755  * gst_rtcp_packet_get_rb_count:
756  * @packet: a valid SR or RR #GstRTCPPacket
757  *
758  * Get the number of report blocks in @packet.
759  *
760  * Returns: The number of report blocks in @packet.
761  */
762 guint
763 gst_rtcp_packet_get_rb_count (GstRTCPPacket * packet)
764 {
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);
768
769   return packet->count;
770 }
771
772 /**
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
783  *
784  * Parse the values of the @nth report block in @packet and store the result in
785  * the values.
786  */
787 void
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)
791 {
792   guint8 *data;
793   guint32 tmp;
794
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);
798
799   data = packet->rtcp->data;
800
801   /* skip header */
802   data += packet->offset + 4;
803   if (packet->type == GST_RTCP_TYPE_RR)
804     data += 4;
805   else
806     data += 24;
807
808   /* move to requested index */
809   data += (nth * 24);
810
811   if (ssrc)
812     *ssrc = GST_READ_UINT32_BE (data);
813   data += 4;
814   tmp = GST_READ_UINT32_BE (data);
815   if (fractionlost)
816     *fractionlost = (tmp >> 24);
817   if (packetslost) {
818     /* sign extend */
819     if (tmp & 0x00800000)
820       tmp |= 0xff000000;
821     else
822       tmp &= 0x00ffffff;
823     *packetslost = (gint32) tmp;
824   }
825   data += 4;
826   if (exthighestseq)
827     *exthighestseq = GST_READ_UINT32_BE (data);
828   data += 4;
829   if (jitter)
830     *jitter = GST_READ_UINT32_BE (data);
831   data += 4;
832   if (lsr)
833     *lsr = GST_READ_UINT32_BE (data);
834   data += 4;
835   if (dlsr)
836     *dlsr = GST_READ_UINT32_BE (data);
837 }
838
839 /**
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
849  *
850  * Add a new report block to @packet with the given values.
851  *
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.
855  */
856 gboolean
857 gst_rtcp_packet_add_rb (GstRTCPPacket * packet, guint32 ssrc,
858     guint8 fractionlost, gint32 packetslost, guint32 exthighestseq,
859     guint32 jitter, guint32 lsr, guint32 dlsr)
860 {
861   guint8 *data;
862   guint size, offset;
863
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);
867
868   if (packet->count >= GST_RTCP_MAX_RB_COUNT)
869     goto no_space;
870
871   data = packet->rtcp->data;
872   size = packet->rtcp->size;
873
874   /* skip header */
875   offset = packet->offset + 4;
876   if (packet->type == GST_RTCP_TYPE_RR)
877     offset += 4;
878   else
879     offset += 24;
880
881   /* move to current index */
882   offset += (packet->count * 24);
883
884   /* we need 24 free bytes now */
885   if (offset + 24 >= size)
886     goto no_space;
887
888   /* increment packet count and length */
889   packet->count++;
890   data[packet->offset]++;
891   packet->length += 6;
892   data[packet->offset + 2] = (packet->length) >> 8;
893   data[packet->offset + 3] = (packet->length) & 0xff;
894
895   /* move to new report block offset */
896   data += offset;
897
898   GST_WRITE_UINT32_BE (data, ssrc);
899   data += 4;
900   GST_WRITE_UINT32_BE (data, (fractionlost << 24) | (packetslost & 0xffffff));
901   data += 4;
902   GST_WRITE_UINT32_BE (data, exthighestseq);
903   data += 4;
904   GST_WRITE_UINT32_BE (data, jitter);
905   data += 4;
906   GST_WRITE_UINT32_BE (data, lsr);
907   data += 4;
908   GST_WRITE_UINT32_BE (data, dlsr);
909
910   return TRUE;
911
912 no_space:
913   {
914     return FALSE;
915   }
916 }
917
918 /**
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
929  *
930  * Set the @nth new report block in @packet with the given values.
931  *
932  * Note: Not implemented.
933  */
934 void
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)
938 {
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);
942
943   g_warning ("not implemented");
944 }
945
946
947 /**
948  * gst_rtcp_packet_sdes_get_item_count:
949  * @packet: a valid SDES #GstRTCPPacket
950  *
951  * Get the number of items in the SDES packet @packet.
952  *
953  * Returns: The number of items in @packet.
954  */
955 guint
956 gst_rtcp_packet_sdes_get_item_count (GstRTCPPacket * packet)
957 {
958   g_return_val_if_fail (packet != NULL, 0);
959   g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, 0);
960
961   return packet->count;
962 }
963
964 /**
965  * gst_rtcp_packet_sdes_first_item:
966  * @packet: a valid SDES #GstRTCPPacket
967  *
968  * Move to the first SDES item in @packet.
969  *
970  * Returns: TRUE if there was a first item.
971  */
972 gboolean
973 gst_rtcp_packet_sdes_first_item (GstRTCPPacket * packet)
974 {
975   g_return_val_if_fail (packet != NULL, FALSE);
976   g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, FALSE);
977
978   packet->item_offset = 4;
979   packet->item_count = 0;
980   packet->entry_offset = 4;
981
982   if (packet->count == 0)
983     return FALSE;
984
985   return TRUE;
986 }
987
988 /**
989  * gst_rtcp_packet_sdes_next_item:
990  * @packet: a valid SDES #GstRTCPPacket
991  *
992  * Move to the next SDES item in @packet.
993  *
994  * Returns: TRUE if there was a next item.
995  */
996 gboolean
997 gst_rtcp_packet_sdes_next_item (GstRTCPPacket * packet)
998 {
999   guint8 *data;
1000   guint offset;
1001   guint len;
1002
1003   g_return_val_if_fail (packet != NULL, FALSE);
1004   g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, FALSE);
1005
1006   /* if we are at the last item, we are done */
1007   if (packet->item_count == packet->count)
1008     return FALSE;
1009
1010   /* move to SDES */
1011   data = packet->rtcp->data;
1012   data += packet->offset;
1013   /* move to item */
1014   offset = packet->item_offset;
1015   /* skip SSRC */
1016   offset += 4;
1017
1018   /* don't overrun */
1019   len = (packet->length << 2);
1020
1021   while (offset < len) {
1022     if (data[offset] == 0) {
1023       /* end of list, round to next 32-bit word */
1024       offset = (offset + 4) & ~3;
1025       break;
1026     }
1027     offset += data[offset + 1] + 2;
1028   }
1029   if (offset >= len)
1030     return FALSE;
1031
1032   packet->item_offset = offset;
1033   packet->item_count++;
1034   packet->entry_offset = 4;
1035
1036   return TRUE;
1037 }
1038
1039 /**
1040  * gst_rtcp_packet_sdes_get_ssrc:
1041  * @packet: a valid SDES #GstRTCPPacket
1042  *
1043  * Get the SSRC of the current SDES item.
1044  *
1045  * Returns: the SSRC of the current item.
1046  */
1047 guint32
1048 gst_rtcp_packet_sdes_get_ssrc (GstRTCPPacket * packet)
1049 {
1050   guint32 ssrc;
1051   guint8 *data;
1052
1053   g_return_val_if_fail (packet != NULL, 0);
1054   g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, 0);
1055
1056   /* move to SDES */
1057   data = packet->rtcp->data;
1058   data += packet->offset;
1059   /* move to item */
1060   data += packet->item_offset;
1061
1062   ssrc = GST_READ_UINT32_BE (data);
1063
1064   return ssrc;
1065 }
1066
1067 /**
1068  * gst_rtcp_packet_sdes_first_entry:
1069  * @packet: a valid SDES #GstRTCPPacket
1070  *
1071  * Move to the first SDES entry in the current item.
1072  *
1073  * Returns: %TRUE if there was a first entry.
1074  */
1075 gboolean
1076 gst_rtcp_packet_sdes_first_entry (GstRTCPPacket * packet)
1077 {
1078   guint8 *data;
1079   guint len, offset;
1080
1081   g_return_val_if_fail (packet != NULL, FALSE);
1082   g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, FALSE);
1083
1084   /* move to SDES */
1085   data = packet->rtcp->data;
1086   data += packet->offset;
1087   /* move to item */
1088   offset = packet->item_offset;
1089   /* skip SSRC */
1090   offset += 4;
1091
1092   packet->entry_offset = 4;
1093
1094   /* don't overrun */
1095   len = (packet->length << 2);
1096   if (offset >= len)
1097     return FALSE;
1098
1099   if (data[offset] == 0)
1100     return FALSE;
1101
1102   return TRUE;
1103 }
1104
1105 /**
1106  * gst_rtcp_packet_sdes_next_entry:
1107  * @packet: a valid SDES #GstRTCPPacket
1108  *
1109  * Move to the next SDES entry in the current item.
1110  *
1111  * Returns: %TRUE if there was a next entry.
1112  */
1113 gboolean
1114 gst_rtcp_packet_sdes_next_entry (GstRTCPPacket * packet)
1115 {
1116   guint8 *data;
1117   guint len, offset, item_len;
1118
1119   g_return_val_if_fail (packet != NULL, FALSE);
1120   g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, FALSE);
1121
1122   /* move to SDES */
1123   data = packet->rtcp->data;
1124   data += packet->offset;
1125   /* move to item */
1126   offset = packet->item_offset;
1127   /* move to entry */
1128   offset += packet->entry_offset;
1129
1130   item_len = data[offset + 1] + 2;
1131   /* skip item */
1132   offset += item_len;
1133
1134   /* don't overrun */
1135   len = (packet->length << 2);
1136   if (offset >= len)
1137     return FALSE;
1138
1139   packet->entry_offset += item_len;
1140
1141   /* check for end of list */
1142   if (data[offset] == 0)
1143     return FALSE;
1144
1145   return TRUE;
1146 }
1147
1148 /**
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
1154  *
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
1157  * bytes.
1158  *
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.
1162  *
1163  * Returns: %TRUE if there was valid data.
1164  */
1165 gboolean
1166 gst_rtcp_packet_sdes_get_entry (GstRTCPPacket * packet,
1167     GstRTCPSDESType * type, guint8 * len, guint8 ** data)
1168 {
1169   guint8 *bdata;
1170   guint offset;
1171
1172   g_return_val_if_fail (packet != NULL, FALSE);
1173   g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, FALSE);
1174
1175   /* move to SDES */
1176   bdata = packet->rtcp->data;
1177   bdata += packet->offset;
1178   /* move to item */
1179   offset = packet->item_offset;
1180   /* move to entry */
1181   offset += packet->entry_offset;
1182
1183   if (bdata[offset] == 0)
1184     return FALSE;
1185
1186   if (type)
1187     *type = bdata[offset];
1188   if (len)
1189     *len = bdata[offset + 1];
1190   if (data)
1191     *data = &bdata[offset + 2];
1192
1193   return TRUE;
1194 }
1195
1196 /**
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
1202  *
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.
1205  *
1206  * Returns: %TRUE if there was valid data.
1207  */
1208 gboolean
1209 gst_rtcp_packet_sdes_copy_entry (GstRTCPPacket * packet,
1210     GstRTCPSDESType * type, guint8 * len, guint8 ** data)
1211 {
1212   guint8 *tdata;
1213   guint8 tlen;
1214
1215   g_return_val_if_fail (packet != NULL, FALSE);
1216   g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, FALSE);
1217
1218   if (!gst_rtcp_packet_sdes_get_entry (packet, type, &tlen, &tdata))
1219     return FALSE;
1220
1221   if (len)
1222     *len = tlen;
1223   if (data)
1224     *data = (guint8 *) g_strndup ((gchar *) tdata, tlen);
1225
1226   return TRUE;
1227 }
1228
1229 /**
1230  * gst_rtcp_packet_sdes_add_item:
1231  * @packet: a valid SDES #GstRTCPPacket
1232  * @ssrc: the SSRC of the new item to add
1233  *
1234  * Add a new SDES item for @ssrc to @packet.
1235  *
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.
1238  */
1239 gboolean
1240 gst_rtcp_packet_sdes_add_item (GstRTCPPacket * packet, guint32 ssrc)
1241 {
1242   guint8 *data;
1243   guint offset, size;
1244
1245   g_return_val_if_fail (packet != NULL, FALSE);
1246   g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, FALSE);
1247
1248   /* increment item count when possible */
1249   if (packet->count >= GST_RTCP_MAX_SDES_ITEM_COUNT)
1250     goto no_space;
1251
1252   /* pretend there is a next packet for the next call */
1253   packet->count++;
1254
1255   /* jump over current item */
1256   gst_rtcp_packet_sdes_next_item (packet);
1257
1258   /* move to SDES */
1259   data = packet->rtcp->data;
1260   size = packet->rtcp->size;
1261   data += packet->offset;
1262   /* move to current item */
1263   offset = packet->item_offset;
1264
1265   /* we need 2 free words now */
1266   if (offset + 8 >= size)
1267     goto no_next;
1268
1269   /* write SSRC */
1270   GST_WRITE_UINT32_BE (&data[offset], ssrc);
1271   /* write 0 entry with padding */
1272   GST_WRITE_UINT32_BE (&data[offset + 4], 0);
1273
1274   /* update count */
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;
1280
1281   return TRUE;
1282
1283   /* ERRORS */
1284 no_space:
1285   {
1286     return FALSE;
1287   }
1288 no_next:
1289   {
1290     packet->count--;
1291     return FALSE;
1292   }
1293 }
1294
1295 /**
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
1300  * @data: the data
1301  *
1302  * Add a new SDES entry to the current item in @packet.
1303  *
1304  * Returns: %TRUE if the item could be added, %FALSE if the MTU has been
1305  * reached.
1306  */
1307 gboolean
1308 gst_rtcp_packet_sdes_add_entry (GstRTCPPacket * packet, GstRTCPSDESType type,
1309     guint8 len, const guint8 * data)
1310 {
1311   guint8 *bdata;
1312   guint offset, size, padded;
1313
1314   g_return_val_if_fail (packet != NULL, FALSE);
1315   g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, FALSE);
1316
1317   /* move to SDES */
1318   bdata = packet->rtcp->data;
1319   size = packet->rtcp->size;
1320   bdata += packet->offset;
1321   /* move to item */
1322   offset = packet->item_offset;
1323   /* move to entry */
1324   offset += packet->entry_offset;
1325
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;
1328
1329   /* we need enough space for type, len, data and padding */
1330   if (packet->offset + padded >= size)
1331     goto no_space;
1332
1333   bdata[offset] = type;
1334   bdata[offset + 1] = len;
1335   memcpy (&bdata[offset + 2], data, len);
1336   bdata[offset + 2 + len] = 0;
1337
1338   /* calculate new packet length */
1339   packet->length = (padded - 4) >> 2;
1340   bdata[2] = (packet->length) >> 8;
1341   bdata[3] = (packet->length) & 0xff;
1342
1343   /* position to new next entry */
1344   packet->entry_offset += 2 + len;
1345
1346   return TRUE;
1347
1348   /* ERRORS */
1349 no_space:
1350   {
1351     return FALSE;
1352   }
1353 }
1354
1355 /**
1356  * gst_rtcp_packet_bye_get_ssrc_count:
1357  * @packet: a valid BYE #GstRTCPPacket
1358  *
1359  * Get the number of SSRC fields in @packet.
1360  *
1361  * Returns: The number of SSRC fields in @packet.
1362  */
1363 guint
1364 gst_rtcp_packet_bye_get_ssrc_count (GstRTCPPacket * packet)
1365 {
1366   g_return_val_if_fail (packet != NULL, -1);
1367   g_return_val_if_fail (packet->type == GST_RTCP_TYPE_BYE, -1);
1368
1369   return packet->count;
1370 }
1371
1372 /**
1373  * gst_rtcp_packet_bye_get_nth_ssrc:
1374  * @packet: a valid BYE #GstRTCPPacket
1375  * @nth: the nth SSRC to get
1376  *
1377  * Get the @nth SSRC of the BYE @packet.
1378  *
1379  * Returns: The @nth SSRC of @packet.
1380  */
1381 guint32
1382 gst_rtcp_packet_bye_get_nth_ssrc (GstRTCPPacket * packet, guint nth)
1383 {
1384   guint8 *data;
1385   guint offset;
1386   guint32 ssrc;
1387   guint8 sc;
1388
1389   g_return_val_if_fail (packet != NULL, 0);
1390   g_return_val_if_fail (packet->type == GST_RTCP_TYPE_BYE, 0);
1391
1392   /* get amount of sources and check that we don't read too much */
1393   sc = packet->count;
1394   if (nth >= sc)
1395     return 0;
1396
1397   /* get offset in 32-bits words into packet, skip the header */
1398   offset = 1 + nth;
1399   /* check that we don't go past the packet length */
1400   if (offset > packet->length)
1401     return 0;
1402
1403   /* scale to bytes */
1404   offset <<= 2;
1405   offset += packet->offset;
1406
1407   /* check if the packet is valid */
1408   if (offset + 4 > packet->rtcp->size)
1409     return 0;
1410
1411   data = packet->rtcp->data;
1412   data += offset;
1413
1414   ssrc = GST_READ_UINT32_BE (data);
1415
1416   return ssrc;
1417 }
1418
1419 /**
1420  * gst_rtcp_packet_bye_add_ssrc:
1421  * @packet: a valid BYE #GstRTCPPacket
1422  * @ssrc: an SSRC to add
1423  *
1424  * Add @ssrc to the BYE @packet.
1425  *
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.
1429  */
1430 gboolean
1431 gst_rtcp_packet_bye_add_ssrc (GstRTCPPacket * packet, guint32 ssrc)
1432 {
1433   guint8 *data;
1434   guint size, offset;
1435
1436   g_return_val_if_fail (packet != NULL, FALSE);
1437   g_return_val_if_fail (packet->type == GST_RTCP_TYPE_BYE, FALSE);
1438
1439   if (packet->count >= GST_RTCP_MAX_BYE_SSRC_COUNT)
1440     goto no_space;
1441
1442   data = packet->rtcp->data;
1443   size = packet->rtcp->size;
1444
1445   /* skip header */
1446   offset = packet->offset + 4;
1447
1448   /* move to current index */
1449   offset += (packet->count * 4);
1450
1451   if (offset + 4 >= size)
1452     goto no_space;
1453
1454   /* increment packet count and length */
1455   packet->count++;
1456   data[packet->offset]++;
1457   packet->length += 1;
1458   data[packet->offset + 2] = (packet->length) >> 8;
1459   data[packet->offset + 3] = (packet->length) & 0xff;
1460
1461   /* move to new SSRC offset and write ssrc */
1462   data += offset;
1463   GST_WRITE_UINT32_BE (data, ssrc);
1464
1465   return TRUE;
1466
1467   /* ERRORS */
1468 no_space:
1469   {
1470     return FALSE;
1471   }
1472 }
1473
1474 /**
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
1479  *
1480  * Adds @len SSRCs in @ssrc to BYE @packet.
1481  *
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.
1485  */
1486 gboolean
1487 gst_rtcp_packet_bye_add_ssrcs (GstRTCPPacket * packet, guint32 * ssrc,
1488     guint len)
1489 {
1490   guint i;
1491   gboolean res;
1492
1493   g_return_val_if_fail (packet != NULL, FALSE);
1494   g_return_val_if_fail (packet->type == GST_RTCP_TYPE_BYE, FALSE);
1495
1496   res = TRUE;
1497   for (i = 0; i < len && res; i++) {
1498     res = gst_rtcp_packet_bye_add_ssrc (packet, ssrc[i]);
1499   }
1500   return res;
1501 }
1502
1503 /* get the offset in packet of the reason length */
1504 static guint
1505 get_reason_offset (GstRTCPPacket * packet)
1506 {
1507   guint offset;
1508
1509   /* get amount of sources plus header */
1510   offset = 1 + packet->count;
1511
1512   /* check that we don't go past the packet length */
1513   if (offset > packet->length)
1514     return 0;
1515
1516   /* scale to bytes */
1517   offset <<= 2;
1518   offset += packet->offset;
1519
1520   /* check if the packet is valid */
1521   if (offset + 1 > packet->rtcp->size)
1522     return 0;
1523
1524   return offset;
1525 }
1526
1527 /**
1528  * gst_rtcp_packet_bye_get_reason_len:
1529  * @packet: a valid BYE #GstRTCPPacket
1530  *
1531  * Get the length of the reason string.
1532  *
1533  * Returns: The length of the reason string or 0 when there is no reason string
1534  * present.
1535  */
1536 guint8
1537 gst_rtcp_packet_bye_get_reason_len (GstRTCPPacket * packet)
1538 {
1539   guint8 *data;
1540   guint roffset;
1541
1542   g_return_val_if_fail (packet != NULL, 0);
1543   g_return_val_if_fail (packet->type == GST_RTCP_TYPE_BYE, 0);
1544
1545   roffset = get_reason_offset (packet);
1546   if (roffset == 0)
1547     return 0;
1548
1549   data = packet->rtcp->data;
1550
1551   return data[roffset];
1552 }
1553
1554 /**
1555  * gst_rtcp_packet_bye_get_reason:
1556  * @packet: a valid BYE #GstRTCPPacket
1557  *
1558  * Get the reason in @packet.
1559  *
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.
1562  */
1563 gchar *
1564 gst_rtcp_packet_bye_get_reason (GstRTCPPacket * packet)
1565 {
1566   guint8 *data;
1567   guint roffset;
1568   guint8 len;
1569
1570   g_return_val_if_fail (packet != NULL, NULL);
1571   g_return_val_if_fail (packet->type == GST_RTCP_TYPE_BYE, NULL);
1572
1573   roffset = get_reason_offset (packet);
1574   if (roffset == 0)
1575     return NULL;
1576
1577   data = packet->rtcp->data;
1578
1579   /* get length of reason string */
1580   len = data[roffset];
1581   if (len == 0)
1582     return NULL;
1583
1584   /* move to string */
1585   roffset += 1;
1586
1587   /* check if enough data to copy */
1588   if (roffset + len > packet->rtcp->size)
1589     return NULL;
1590
1591   return g_strndup ((gconstpointer) (data + roffset), len);
1592 }
1593
1594 /**
1595  * gst_rtcp_packet_bye_set_reason:
1596  * @packet: a valid BYE #GstRTCPPacket
1597  * @reason: a reason string
1598  *
1599  * Set the reason string to @reason in @packet.
1600  *
1601  * Returns: TRUE if the string could be set.
1602  */
1603 gboolean
1604 gst_rtcp_packet_bye_set_reason (GstRTCPPacket * packet, const gchar * reason)
1605 {
1606   guint8 *data;
1607   guint roffset, size;
1608   guint8 len, padded;
1609
1610   g_return_val_if_fail (packet != NULL, FALSE);
1611   g_return_val_if_fail (packet->type == GST_RTCP_TYPE_BYE, FALSE);
1612
1613   if (reason == NULL)
1614     return TRUE;
1615
1616   len = strlen (reason);
1617   if (len == 0)
1618     return TRUE;
1619
1620   /* make room for the string before we get the offset */
1621   packet->length++;
1622
1623   roffset = get_reason_offset (packet);
1624   if (roffset == 0)
1625     goto no_space;
1626
1627   data = packet->rtcp->data;
1628   size = packet->rtcp->size;
1629
1630   /* we have 1 byte length and we need to pad to 4 bytes */
1631   padded = ((len + 1) + 3) & ~3;
1632
1633   /* we need enough space for the padded length */
1634   if (roffset + padded >= size)
1635     goto no_space;
1636
1637   data[roffset] = len;
1638   memcpy (&data[roffset + 1], reason, len);
1639
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;
1644
1645   return TRUE;
1646
1647   /* ERRORS */
1648 no_space:
1649   {
1650     packet->length--;
1651     return FALSE;
1652   }
1653 }
1654
1655 /**
1656  * gst_rtcp_packet_fb_get_sender_ssrc:
1657  * @packet: a valid RTPFB or PSFB #GstRTCPPacket
1658  *
1659  * Get the sender SSRC field of the RTPFB or PSFB @packet.
1660  *
1661  * Returns: the sender SSRC.
1662  *
1663  * Since: 0.10.23
1664  */
1665 guint32
1666 gst_rtcp_packet_fb_get_sender_ssrc (GstRTCPPacket * packet)
1667 {
1668   guint8 *data;
1669   guint32 ssrc;
1670
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);
1674
1675   data = packet->rtcp->data;
1676
1677   /* skip header */
1678   data += packet->offset + 4;
1679   ssrc = GST_READ_UINT32_BE (data);
1680
1681   return ssrc;
1682 }
1683
1684 /**
1685  * gst_rtcp_packet_fb_set_sender_ssrc:
1686  * @packet: a valid RTPFB or PSFB #GstRTCPPacket
1687  * @ssrc: a sender SSRC
1688  *
1689  * Set the sender SSRC field of the RTPFB or PSFB @packet.
1690  *
1691  * Since: 0.10.23
1692  */
1693 void
1694 gst_rtcp_packet_fb_set_sender_ssrc (GstRTCPPacket * packet, guint32 ssrc)
1695 {
1696   guint8 *data;
1697
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);
1701
1702   data = packet->rtcp->data;
1703
1704   /* skip header */
1705   data += packet->offset + 4;
1706   GST_WRITE_UINT32_BE (data, ssrc);
1707 }
1708
1709 /**
1710  * gst_rtcp_packet_fb_get_media_ssrc:
1711  * @packet: a valid RTPFB or PSFB #GstRTCPPacket
1712  *
1713  * Get the media SSRC field of the RTPFB or PSFB @packet.
1714  *
1715  * Returns: the media SSRC.
1716  *
1717  * Since: 0.10.23
1718  */
1719 guint32
1720 gst_rtcp_packet_fb_get_media_ssrc (GstRTCPPacket * packet)
1721 {
1722   guint8 *data;
1723   guint32 ssrc;
1724
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);
1728
1729   data = packet->rtcp->data;
1730
1731   /* skip header and sender ssrc */
1732   data += packet->offset + 8;
1733   ssrc = GST_READ_UINT32_BE (data);
1734
1735   return ssrc;
1736 }
1737
1738 /**
1739  * gst_rtcp_packet_fb_set_media_ssrc:
1740  * @packet: a valid RTPFB or PSFB #GstRTCPPacket
1741  * @ssrc: a media SSRC
1742  *
1743  * Set the media SSRC field of the RTPFB or PSFB @packet.
1744  *
1745  * Since: 0.10.23
1746  */
1747 void
1748 gst_rtcp_packet_fb_set_media_ssrc (GstRTCPPacket * packet, guint32 ssrc)
1749 {
1750   guint8 *data;
1751
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);
1755
1756   data = packet->rtcp->data;
1757
1758   /* skip header and sender ssrc */
1759   data += packet->offset + 8;
1760   GST_WRITE_UINT32_BE (data, ssrc);
1761 }
1762
1763 /**
1764  * gst_rtcp_packet_fb_get_type:
1765  * @packet: a valid RTPFB or PSFB #GstRTCPPacket
1766  *
1767  * Get the feedback message type of the FB @packet.
1768  *
1769  * Returns: The feedback message type.
1770  *
1771  * Since: 0.10.23
1772  */
1773 GstRTCPFBType
1774 gst_rtcp_packet_fb_get_type (GstRTCPPacket * packet)
1775 {
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);
1779
1780   return packet->count;
1781 }
1782
1783 /**
1784  * gst_rtcp_packet_fb_set_type:
1785  * @packet: a valid RTPFB or PSFB #GstRTCPPacket
1786  * @type: the #GstRTCPFBType to set
1787  *
1788  * Set the feedback message type of the FB @packet.
1789  *
1790  * Since: 0.10.23
1791  */
1792 void
1793 gst_rtcp_packet_fb_set_type (GstRTCPPacket * packet, GstRTCPFBType type)
1794 {
1795   guint8 *data;
1796
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);
1800
1801   data = packet->rtcp->data;
1802
1803   data[packet->offset] = (data[packet->offset] & 0xe0) | type;
1804   packet->count = type;
1805 }
1806
1807 /**
1808  * gst_rtcp_ntp_to_unix:
1809  * @ntptime: an NTP timestamp
1810  *
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.
1815  *
1816  * Returns: the UNIX time for @ntptime in nanoseconds.
1817  */
1818 guint64
1819 gst_rtcp_ntp_to_unix (guint64 ntptime)
1820 {
1821   guint64 unixtime;
1822
1823   /* conversion from NTP timestamp (seconds since 1900) to seconds since
1824    * 1970. */
1825   unixtime = ntptime - (G_GUINT64_CONSTANT (2208988800) << 32);
1826   /* conversion to nanoseconds */
1827   unixtime =
1828       gst_util_uint64_scale (unixtime, GST_SECOND,
1829       (G_GINT64_CONSTANT (1) << 32));
1830
1831   return unixtime;
1832 }
1833
1834 /**
1835  * gst_rtcp_unix_to_ntp:
1836  * @unixtime: an UNIX timestamp in nanoseconds
1837  *
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.
1843  *
1844  * Returns: the NTP time for @unixtime.
1845  */
1846 guint64
1847 gst_rtcp_unix_to_ntp (guint64 unixtime)
1848 {
1849   guint64 ntptime;
1850
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. */
1853   ntptime =
1854       gst_util_uint64_scale (unixtime, (G_GINT64_CONSTANT (1) << 32),
1855       GST_SECOND);
1856   /* conversion from UNIX timestamp (seconds since 1970) to NTP (seconds
1857    * since 1900). */
1858   ntptime += (G_GUINT64_CONSTANT (2208988800) << 32);
1859
1860   return ntptime;
1861 }
1862
1863 /**
1864  * gst_rtcp_sdes_type_to_name:
1865  * @type: a #GstRTCPSDESType
1866  *
1867  * Converts @type to the string equivalent. The string is typically used as a
1868  * key in a #GstStructure containing SDES items.
1869  *
1870  * Returns: the string equivalent of @type
1871  *
1872  * Since: 0.10.26
1873  */
1874 const gchar *
1875 gst_rtcp_sdes_type_to_name (GstRTCPSDESType type)
1876 {
1877   const gchar *result;
1878
1879   switch (type) {
1880     case GST_RTCP_SDES_CNAME:
1881       result = "cname";
1882       break;
1883     case GST_RTCP_SDES_NAME:
1884       result = "name";
1885       break;
1886     case GST_RTCP_SDES_EMAIL:
1887       result = "email";
1888       break;
1889     case GST_RTCP_SDES_PHONE:
1890       result = "phone";
1891       break;
1892     case GST_RTCP_SDES_LOC:
1893       result = "location";
1894       break;
1895     case GST_RTCP_SDES_TOOL:
1896       result = "tool";
1897       break;
1898     case GST_RTCP_SDES_NOTE:
1899       result = "note";
1900       break;
1901     case GST_RTCP_SDES_PRIV:
1902       result = "priv";
1903       break;
1904     default:
1905       result = NULL;
1906       break;
1907   }
1908   return result;
1909 }
1910
1911 /**
1912  * gst_rtcp_sdes_name_to_type:
1913  * @name: a SDES name
1914  *
1915  * Convert @name into a @GstRTCPSDESType. @name is typically a key in a
1916  * #GstStructure containing SDES items.
1917  *
1918  * Returns: the #GstRTCPSDESType for @name or #GST_RTCP_SDES_PRIV when @name
1919  * is a private sdes item.
1920  *
1921  * Since: 0.10.26
1922  */
1923 GstRTCPSDESType
1924 gst_rtcp_sdes_name_to_type (const gchar * name)
1925 {
1926   if (name == NULL || strlen (name) == 0)
1927     return GST_RTCP_SDES_INVALID;
1928
1929   if (strcmp ("cname", name) == 0)
1930     return GST_RTCP_SDES_CNAME;
1931
1932   if (strcmp ("name", name) == 0)
1933     return GST_RTCP_SDES_NAME;
1934
1935   if (strcmp ("email", name) == 0)
1936     return GST_RTCP_SDES_EMAIL;
1937
1938   if (strcmp ("phone", name) == 0)
1939     return GST_RTCP_SDES_PHONE;
1940
1941   if (strcmp ("location", name) == 0)
1942     return GST_RTCP_SDES_LOC;
1943
1944   if (strcmp ("tool", name) == 0)
1945     return GST_RTCP_SDES_TOOL;
1946
1947   if (strcmp ("note", name) == 0)
1948     return GST_RTCP_SDES_NOTE;
1949
1950   return GST_RTCP_SDES_PRIV;
1951 }
1952
1953 /**
1954  * gst_rtcp_packet_fb_get_fci_length:
1955  * @packet: a valid RTPFB or PSFB #GstRTCPPacket
1956  *
1957  * Get the length of the Feedback Control Information attached to a
1958  * RTPFB or PSFB @packet.
1959  *
1960  * Returns: The length of the FCI in 32-bit words.
1961  *
1962  * Since: 0.10.31
1963  */
1964 guint16
1965 gst_rtcp_packet_fb_get_fci_length (GstRTCPPacket * packet)
1966 {
1967   guint8 *data;
1968
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);
1972
1973   data = packet->rtcp->data + packet->offset + 2;
1974
1975   return GST_READ_UINT16_BE (data) - 2;
1976 }
1977
1978 /**
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
1982  *
1983  * Set the length of the Feedback Control Information attached to a
1984  * RTPFB or PSFB @packet.
1985  *
1986  * Returns: %TRUE if there was enough space in the packet to add this much FCI
1987  *
1988  * Since: 0.10.31
1989  */
1990 gboolean
1991 gst_rtcp_packet_fb_set_fci_length (GstRTCPPacket * packet, guint16 wordlen)
1992 {
1993   guint8 *data;
1994
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);
1998
1999   if (packet->rtcp->size < packet->offset + ((wordlen + 3) * 4))
2000     return FALSE;
2001
2002   data = packet->rtcp->data + packet->offset + 2;
2003   wordlen += 2;
2004   GST_WRITE_UINT16_BE (data, wordlen);
2005
2006   return TRUE;
2007 }
2008
2009 /**
2010  * gst_rtcp_packet_fb_get_fci:
2011  * @packet: a valid RTPFB or PSFB #GstRTCPPacket
2012  *
2013  * Get the Feedback Control Information attached to a RTPFB or PSFB @packet.
2014  *
2015  * Returns: a pointer to the FCI
2016  *
2017  * Since: 0.10.31
2018  */
2019 guint8 *
2020 gst_rtcp_packet_fb_get_fci (GstRTCPPacket * packet)
2021 {
2022   guint8 *data;
2023
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);
2027
2028   data = packet->rtcp->data + packet->offset;
2029
2030   if (GST_READ_UINT16_BE (data + 2) <= 2)
2031     return NULL;
2032
2033   return data + 12;
2034 }