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