• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GStreamer
2  * Copyright (C) <2005> Philippe Khalaf <burger@speedy.org>
3  * Copyright (C) <2006> Wim Taymans <wim@fluendo.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20 
21 /**
22  * SECTION:gstrtpbuffer
23  * @title: GstRTPBuffer
24  * @short_description: Helper methods for dealing with RTP buffers
25  * @see_also: #GstRTPBasePayload, #GstRTPBaseDepayload, gstrtcpbuffer
26  *
27  * The GstRTPBuffer helper functions makes it easy to parse and create regular
28  * #GstBuffer objects that contain RTP payloads. These buffers are typically of
29  * 'application/x-rtp' #GstCaps.
30  *
31  */
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
35 
36 #include "gstrtpbuffer.h"
37 
38 #include <stdlib.h>
39 #include <string.h>
40 
41 #define GST_RTP_HEADER_LEN 12
42 
43 /* Note: we use bitfields here to make sure the compiler doesn't add padding
44  * between fields on certain architectures; can't assume aligned access either
45  */
46 typedef struct _GstRTPHeader
47 {
48 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
49   unsigned int csrc_count:4;    /* CSRC count */
50   unsigned int extension:1;     /* header extension flag */
51   unsigned int padding:1;       /* padding flag */
52   unsigned int version:2;       /* protocol version */
53   unsigned int payload_type:7;  /* payload type */
54   unsigned int marker:1;        /* marker bit */
55 #elif G_BYTE_ORDER == G_BIG_ENDIAN
56   unsigned int version:2;       /* protocol version */
57   unsigned int padding:1;       /* padding flag */
58   unsigned int extension:1;     /* header extension flag */
59   unsigned int csrc_count:4;    /* CSRC count */
60   unsigned int marker:1;        /* marker bit */
61   unsigned int payload_type:7;  /* payload type */
62 #else
63 #error "G_BYTE_ORDER should be big or little endian."
64 #endif
65   unsigned int seq:16;          /* sequence number */
66   unsigned int timestamp:32;    /* timestamp */
67   unsigned int ssrc:32;         /* synchronization source */
68   guint8 csrclist[4];           /* optional CSRC list, 32 bits each */
69 } GstRTPHeader;
70 
71 #define GST_RTP_HEADER_VERSION(data)      (((GstRTPHeader *)(data))->version)
72 #define GST_RTP_HEADER_PADDING(data)      (((GstRTPHeader *)(data))->padding)
73 #define GST_RTP_HEADER_EXTENSION(data)    (((GstRTPHeader *)(data))->extension)
74 #define GST_RTP_HEADER_CSRC_COUNT(data)   (((GstRTPHeader *)(data))->csrc_count)
75 #define GST_RTP_HEADER_MARKER(data)       (((GstRTPHeader *)(data))->marker)
76 #define GST_RTP_HEADER_PAYLOAD_TYPE(data) (((GstRTPHeader *)(data))->payload_type)
77 #define GST_RTP_HEADER_SEQ(data)          (((GstRTPHeader *)(data))->seq)
78 #define GST_RTP_HEADER_TIMESTAMP(data)    (((GstRTPHeader *)(data))->timestamp)
79 #define GST_RTP_HEADER_SSRC(data)         (((GstRTPHeader *)(data))->ssrc)
80 #define GST_RTP_HEADER_CSRC_LIST_OFFSET(data,i)        \
81     data + G_STRUCT_OFFSET(GstRTPHeader, csrclist) +   \
82     ((i) * sizeof(guint32))
83 #define GST_RTP_HEADER_CSRC_SIZE(data)   (GST_RTP_HEADER_CSRC_COUNT(data) * sizeof (guint32))
84 
85 /**
86  * gst_rtp_buffer_allocate_data:
87  * @buffer: a #GstBuffer
88  * @payload_len: the length of the payload
89  * @pad_len: the amount of padding
90  * @csrc_count: the number of CSRC entries
91  *
92  * Allocate enough data in @buffer to hold an RTP packet with @csrc_count CSRCs,
93  * a payload length of @payload_len and padding of @pad_len.
94  * @buffer must be writable and all previous memory in @buffer will be freed.
95  * If @pad_len is >0, the padding bit will be set. All other RTP header fields
96  * will be set to 0/FALSE.
97  */
98 void
gst_rtp_buffer_allocate_data(GstBuffer * buffer,guint payload_len,guint8 pad_len,guint8 csrc_count)99 gst_rtp_buffer_allocate_data (GstBuffer * buffer, guint payload_len,
100     guint8 pad_len, guint8 csrc_count)
101 {
102   GstMapInfo map;
103   GstMemory *mem;
104   gsize hlen;
105 
106   g_return_if_fail (csrc_count <= 15);
107   g_return_if_fail (GST_IS_BUFFER (buffer));
108   g_return_if_fail (gst_buffer_is_writable (buffer));
109 
110   gst_buffer_remove_all_memory (buffer);
111 
112   hlen = GST_RTP_HEADER_LEN + csrc_count * sizeof (guint32);
113 
114   mem = gst_allocator_alloc (NULL, hlen, NULL);
115 
116   gst_memory_map (mem, &map, GST_MAP_WRITE);
117   /* fill in defaults */
118   GST_RTP_HEADER_VERSION (map.data) = GST_RTP_VERSION;
119   if (pad_len)
120     GST_RTP_HEADER_PADDING (map.data) = TRUE;
121   else
122     GST_RTP_HEADER_PADDING (map.data) = FALSE;
123   GST_RTP_HEADER_EXTENSION (map.data) = FALSE;
124   GST_RTP_HEADER_CSRC_COUNT (map.data) = csrc_count;
125   memset (GST_RTP_HEADER_CSRC_LIST_OFFSET (map.data, 0), 0,
126       csrc_count * sizeof (guint32));
127   GST_RTP_HEADER_MARKER (map.data) = FALSE;
128   GST_RTP_HEADER_PAYLOAD_TYPE (map.data) = 0;
129   GST_RTP_HEADER_SEQ (map.data) = 0;
130   GST_RTP_HEADER_TIMESTAMP (map.data) = 0;
131   GST_RTP_HEADER_SSRC (map.data) = 0;
132   gst_memory_unmap (mem, &map);
133 
134   gst_buffer_append_memory (buffer, mem);
135 
136   if (payload_len) {
137     mem = gst_allocator_alloc (NULL, payload_len, NULL);
138     gst_buffer_append_memory (buffer, mem);
139   }
140   if (pad_len) {
141     mem = gst_allocator_alloc (NULL, pad_len, NULL);
142 
143     gst_memory_map (mem, &map, GST_MAP_WRITE);
144     map.data[pad_len - 1] = pad_len;
145     gst_memory_unmap (mem, &map);
146 
147     gst_buffer_append_memory (buffer, mem);
148   }
149 }
150 
151 /**
152  * gst_rtp_buffer_new_take_data:
153  * @data: (array length=len) (transfer full) (element-type guint8):
154  *   data for the new buffer
155  * @len: the length of data
156  *
157  * Create a new buffer and set the data and size of the buffer to @data and @len
158  * respectively. @data will be freed when the buffer is unreffed, so this
159  * function transfers ownership of @data to the new buffer.
160  *
161  * Returns: A newly allocated buffer with @data and of size @len.
162  */
163 GstBuffer *
gst_rtp_buffer_new_take_data(gpointer data,gsize len)164 gst_rtp_buffer_new_take_data (gpointer data, gsize len)
165 {
166   g_return_val_if_fail (data != NULL, NULL);
167   g_return_val_if_fail (len > 0, NULL);
168 
169   return gst_buffer_new_wrapped (data, len);
170 }
171 
172 /**
173  * gst_rtp_buffer_new_copy_data:
174  * @data: (array length=len) (element-type guint8): data for the new
175  *   buffer
176  * @len: the length of data
177  *
178  * Create a new buffer and set the data to a copy of @len
179  * bytes of @data and the size to @len. The data will be freed when the buffer
180  * is freed.
181  *
182  * Returns: A newly allocated buffer with a copy of @data and of size @len.
183  */
184 GstBuffer *
gst_rtp_buffer_new_copy_data(gconstpointer data,gsize len)185 gst_rtp_buffer_new_copy_data (gconstpointer data, gsize len)
186 {
187   return gst_rtp_buffer_new_take_data (g_memdup2 (data, len), len);
188 }
189 
190 /**
191  * gst_rtp_buffer_new_allocate:
192  * @payload_len: the length of the payload
193  * @pad_len: the amount of padding
194  * @csrc_count: the number of CSRC entries
195  *
196  * Allocate a new #GstBuffer with enough data to hold an RTP packet with
197  * @csrc_count CSRCs, a payload length of @payload_len and padding of @pad_len.
198  * All other RTP header fields will be set to 0/FALSE.
199  *
200  * Returns: A newly allocated buffer that can hold an RTP packet with given
201  * parameters.
202  */
203 GstBuffer *
gst_rtp_buffer_new_allocate(guint payload_len,guint8 pad_len,guint8 csrc_count)204 gst_rtp_buffer_new_allocate (guint payload_len, guint8 pad_len,
205     guint8 csrc_count)
206 {
207   GstBuffer *result;
208 
209   g_return_val_if_fail (csrc_count <= 15, NULL);
210 
211   result = gst_buffer_new ();
212   gst_rtp_buffer_allocate_data (result, payload_len, pad_len, csrc_count);
213 
214   return result;
215 }
216 
217 /**
218  * gst_rtp_buffer_new_allocate_len:
219  * @packet_len: the total length of the packet
220  * @pad_len: the amount of padding
221  * @csrc_count: the number of CSRC entries
222  *
223  * Create a new #GstBuffer that can hold an RTP packet that is exactly
224  * @packet_len long. The length of the payload depends on @pad_len and
225  * @csrc_count and can be calculated with gst_rtp_buffer_calc_payload_len().
226  * All RTP header fields will be set to 0/FALSE.
227  *
228  * Returns: A newly allocated buffer that can hold an RTP packet of @packet_len.
229  */
230 GstBuffer *
gst_rtp_buffer_new_allocate_len(guint packet_len,guint8 pad_len,guint8 csrc_count)231 gst_rtp_buffer_new_allocate_len (guint packet_len, guint8 pad_len,
232     guint8 csrc_count)
233 {
234   guint len;
235 
236   g_return_val_if_fail (csrc_count <= 15, NULL);
237 
238   len = gst_rtp_buffer_calc_payload_len (packet_len, pad_len, csrc_count);
239 
240   return gst_rtp_buffer_new_allocate (len, pad_len, csrc_count);
241 }
242 
243 /**
244  * gst_rtp_buffer_calc_header_len:
245  * @csrc_count: the number of CSRC entries
246  *
247  * Calculate the header length of an RTP packet with @csrc_count CSRC entries.
248  * An RTP packet can have at most 15 CSRC entries.
249  *
250  * Returns: The length of an RTP header with @csrc_count CSRC entries.
251  */
252 guint
gst_rtp_buffer_calc_header_len(guint8 csrc_count)253 gst_rtp_buffer_calc_header_len (guint8 csrc_count)
254 {
255   g_return_val_if_fail (csrc_count <= 15, 0);
256 
257   return GST_RTP_HEADER_LEN + (csrc_count * sizeof (guint32));
258 }
259 
260 /**
261  * gst_rtp_buffer_calc_packet_len:
262  * @payload_len: the length of the payload
263  * @pad_len: the amount of padding
264  * @csrc_count: the number of CSRC entries
265  *
266  * Calculate the total length of an RTP packet with a payload size of @payload_len,
267  * a padding of @pad_len and a @csrc_count CSRC entries.
268  *
269  * Returns: The total length of an RTP header with given parameters.
270  */
271 guint
gst_rtp_buffer_calc_packet_len(guint payload_len,guint8 pad_len,guint8 csrc_count)272 gst_rtp_buffer_calc_packet_len (guint payload_len, guint8 pad_len,
273     guint8 csrc_count)
274 {
275   g_return_val_if_fail (csrc_count <= 15, 0);
276 
277   return payload_len + GST_RTP_HEADER_LEN + (csrc_count * sizeof (guint32))
278       + pad_len;
279 }
280 
281 /**
282  * gst_rtp_buffer_calc_payload_len:
283  * @packet_len: the length of the total RTP packet
284  * @pad_len: the amount of padding
285  * @csrc_count: the number of CSRC entries
286  *
287  * Calculate the length of the payload of an RTP packet with size @packet_len,
288  * a padding of @pad_len and a @csrc_count CSRC entries.
289  *
290  * Returns: The length of the payload of an RTP packet  with given parameters.
291  */
292 guint
gst_rtp_buffer_calc_payload_len(guint packet_len,guint8 pad_len,guint8 csrc_count)293 gst_rtp_buffer_calc_payload_len (guint packet_len, guint8 pad_len,
294     guint8 csrc_count)
295 {
296   g_return_val_if_fail (csrc_count <= 15, 0);
297 
298   if (packet_len <
299       GST_RTP_HEADER_LEN + (csrc_count * sizeof (guint32)) + pad_len)
300     return 0;
301 
302   return packet_len - GST_RTP_HEADER_LEN - (csrc_count * sizeof (guint32))
303       - pad_len;
304 }
305 
306 /**
307  * gst_rtp_buffer_map:
308  * @buffer: a #GstBuffer
309  * @flags: #GstMapFlags
310  * @rtp: (out): a #GstRTPBuffer
311  *
312  * Map the contents of @buffer into @rtp.
313  *
314  * Returns: %TRUE if @buffer could be mapped.
315  */
316 gboolean
gst_rtp_buffer_map(GstBuffer * buffer,GstMapFlags flags,GstRTPBuffer * rtp)317 gst_rtp_buffer_map (GstBuffer * buffer, GstMapFlags flags, GstRTPBuffer * rtp)
318 {
319   guint8 padding;
320   guint8 csrc_count;
321   guint header_len;
322   guint8 version, pt;
323   guint8 *data;
324   guint size;
325   gsize bufsize, skip;
326   guint idx, length;
327   guint n_mem;
328 
329   g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
330   g_return_val_if_fail (rtp != NULL, FALSE);
331   g_return_val_if_fail (rtp->buffer == NULL, FALSE);
332 
333   n_mem = gst_buffer_n_memory (buffer);
334   if (n_mem < 1)
335     goto no_memory;
336 
337   /* map first memory, this should be the header */
338   if (!gst_buffer_map_range (buffer, 0, 1, &rtp->map[0], flags))
339     goto map_failed;
340 
341   data = rtp->data[0] = rtp->map[0].data;
342   size = rtp->map[0].size;
343 
344   /* the header must be completely in the first buffer */
345   header_len = GST_RTP_HEADER_LEN;
346   if (G_UNLIKELY (size < header_len))
347     goto wrong_length;
348 
349   /* check version */
350   version = (data[0] & 0xc0);
351   if (G_UNLIKELY (version != (GST_RTP_VERSION << 6)))
352     goto wrong_version;
353 
354   /* check reserved PT and marker bit, this is to check for RTCP
355    * packets. We do a relaxed check, you can still use 72-76 as long
356    * as the marker bit is cleared. */
357   pt = data[1];
358   if (G_UNLIKELY (pt >= 200 && pt <= 204))
359     goto reserved_pt;
360 
361   /* calc header length with csrc */
362   csrc_count = (data[0] & 0x0f);
363   header_len += csrc_count * sizeof (guint32);
364 
365   rtp->size[0] = header_len;
366 
367   bufsize = gst_buffer_get_size (buffer);
368 
369   /* calc extension length when present. */
370   if (data[0] & 0x10) {
371     guint8 *extdata;
372     gsize extlen;
373 
374     /* find memory for the extension bits, we find the block for the first 4
375      * bytes, all other extension bytes should also be in this block */
376     if (!gst_buffer_find_memory (buffer, header_len, 4, &idx, &length, &skip))
377       goto wrong_length;
378 
379     if (!gst_buffer_map_range (buffer, idx, length, &rtp->map[1], flags))
380       goto map_failed;
381 
382     extdata = rtp->data[1] = rtp->map[1].data + skip;
383     /* skip id */
384     extdata += 2;
385     /* read length as the number of 32 bits words */
386     extlen = GST_READ_UINT16_BE (extdata);
387     extlen *= sizeof (guint32);
388     /* add id and length */
389     extlen += 4;
390 
391     /* all extension bytes must be in this block */
392     if (G_UNLIKELY (rtp->map[1].size < extlen))
393       goto wrong_length;
394 
395     rtp->size[1] = extlen;
396 
397     header_len += rtp->size[1];
398   } else {
399     rtp->data[1] = NULL;
400     rtp->size[1] = 0;
401   }
402 
403   /* check for padding unless flags says to skip */
404   if ((data[0] & 0x20) != 0 &&
405       (flags & GST_RTP_BUFFER_MAP_FLAG_SKIP_PADDING) == 0) {
406     /* find memory for the padding bits */
407     if (!gst_buffer_find_memory (buffer, bufsize - 1, 1, &idx, &length, &skip))
408       goto wrong_length;
409 
410     if (!gst_buffer_map_range (buffer, idx, length, &rtp->map[3], flags))
411       goto map_failed;
412 
413     padding = rtp->map[3].data[skip];
414     rtp->data[3] = rtp->map[3].data + skip + 1 - padding;
415     rtp->size[3] = padding;
416 
417     if (skip + 1 < padding)
418       goto wrong_length;
419   } else {
420     rtp->data[3] = NULL;
421     rtp->size[3] = 0;
422     padding = 0;
423   }
424 
425   /* check if padding and header not bigger than packet length */
426   if (G_UNLIKELY (bufsize < padding + header_len))
427     goto wrong_padding;
428 
429   rtp->buffer = buffer;
430 
431   if (n_mem == 1) {
432     /* we have mapped the buffer already, so might just as well fill in the
433      * payload pointer and size and avoid another buffer map/unmap later */
434     rtp->data[2] = rtp->map[0].data + header_len;
435     rtp->size[2] = bufsize - header_len - padding;
436   } else {
437     /* we have not yet mapped the payload */
438     rtp->data[2] = NULL;
439     rtp->size[2] = 0;
440   }
441 
442   /* rtp->state = 0; *//* unused */
443 
444   return TRUE;
445 
446   /* ERRORS */
447 no_memory:
448   {
449     GST_ERROR ("buffer without memory");
450     return FALSE;
451   }
452 map_failed:
453   {
454     GST_ERROR ("failed to map memory");
455     return FALSE;
456   }
457 wrong_length:
458   {
459     GST_DEBUG ("length check failed");
460     goto dump_packet;
461   }
462 wrong_version:
463   {
464     GST_DEBUG ("version check failed (%d != %d)", version, GST_RTP_VERSION);
465     goto dump_packet;
466   }
467 reserved_pt:
468   {
469     GST_DEBUG ("reserved PT %d found", pt);
470     goto dump_packet;
471   }
472 wrong_padding:
473   {
474     GST_DEBUG ("padding check failed (%" G_GSIZE_FORMAT " - %d < %d)", bufsize,
475         header_len, padding);
476     goto dump_packet;
477   }
478 dump_packet:
479   {
480     gint i;
481 
482     GST_MEMDUMP ("buffer", data, size);
483 
484     for (i = 0; i < G_N_ELEMENTS (rtp->map); ++i) {
485       if (rtp->map[i].memory != NULL)
486         gst_buffer_unmap (buffer, &rtp->map[i]);
487     }
488     return FALSE;
489   }
490 }
491 
492 /**
493  * gst_rtp_buffer_unmap:
494  * @rtp: a #GstRTPBuffer
495  *
496  * Unmap @rtp previously mapped with gst_rtp_buffer_map().
497  */
498 void
gst_rtp_buffer_unmap(GstRTPBuffer * rtp)499 gst_rtp_buffer_unmap (GstRTPBuffer * rtp)
500 {
501   gint i;
502 
503   g_return_if_fail (rtp != NULL);
504   g_return_if_fail (rtp->buffer != NULL);
505 
506   for (i = 0; i < 4; i++) {
507     if (rtp->map[i].memory != NULL) {
508       gst_buffer_unmap (rtp->buffer, &rtp->map[i]);
509       rtp->map[i].memory = NULL;
510     }
511     rtp->data[i] = NULL;
512     rtp->size[i] = 0;
513   }
514   rtp->buffer = NULL;
515 }
516 
517 
518 /**
519  * gst_rtp_buffer_set_packet_len:
520  * @rtp: the RTP packet
521  * @len: the new packet length
522  *
523  * Set the total @rtp size to @len. The data in the buffer will be made
524  * larger if needed. Any padding will be removed from the packet.
525  */
526 void
gst_rtp_buffer_set_packet_len(GstRTPBuffer * rtp,guint len)527 gst_rtp_buffer_set_packet_len (GstRTPBuffer * rtp, guint len)
528 {
529   guint8 *data;
530 
531   data = rtp->data[0];
532 
533   /* FIXME */
534 
535   if (rtp->map[0].maxsize <= len) {
536     /* FIXME, realloc bigger space */
537     g_warning ("not implemented");
538   }
539 
540   gst_buffer_set_size (rtp->buffer, len);
541   rtp->map[0].size = len;
542 
543   /* remove any padding */
544   GST_RTP_HEADER_PADDING (data) = FALSE;
545 }
546 
547 /**
548  * gst_rtp_buffer_get_packet_len:
549  * @rtp: the RTP packet
550  *
551  * Return the total length of the packet in @buffer.
552  *
553  * Returns: The total length of the packet in @buffer.
554  */
555 guint
gst_rtp_buffer_get_packet_len(GstRTPBuffer * rtp)556 gst_rtp_buffer_get_packet_len (GstRTPBuffer * rtp)
557 {
558   return gst_buffer_get_size (rtp->buffer);
559 }
560 
561 /**
562  * gst_rtp_buffer_get_header_len:
563  * @rtp: the RTP packet
564  *
565  * Return the total length of the header in @buffer. This include the length of
566  * the fixed header, the CSRC list and the extension header.
567  *
568  * Returns: The total length of the header in @buffer.
569  */
570 guint
gst_rtp_buffer_get_header_len(GstRTPBuffer * rtp)571 gst_rtp_buffer_get_header_len (GstRTPBuffer * rtp)
572 {
573   return rtp->size[0] + rtp->size[1];
574 }
575 
576 /**
577  * gst_rtp_buffer_get_version:
578  * @rtp: the RTP packet
579  *
580  * Get the version number of the RTP packet in @buffer.
581  *
582  * Returns: The version of @buffer.
583  */
584 guint8
gst_rtp_buffer_get_version(GstRTPBuffer * rtp)585 gst_rtp_buffer_get_version (GstRTPBuffer * rtp)
586 {
587   return GST_RTP_HEADER_VERSION (rtp->data[0]);
588 }
589 
590 /**
591  * gst_rtp_buffer_set_version:
592  * @rtp: the RTP packet
593  * @version: the new version
594  *
595  * Set the version of the RTP packet in @buffer to @version.
596  */
597 void
gst_rtp_buffer_set_version(GstRTPBuffer * rtp,guint8 version)598 gst_rtp_buffer_set_version (GstRTPBuffer * rtp, guint8 version)
599 {
600   g_return_if_fail (version < 0x04);
601 
602   GST_RTP_HEADER_VERSION (rtp->data[0]) = version;
603 }
604 
605 /**
606  * gst_rtp_buffer_get_padding:
607  * @rtp: the RTP packet
608  *
609  * Check if the padding bit is set on the RTP packet in @buffer.
610  *
611  * Returns: TRUE if @buffer has the padding bit set.
612  */
613 gboolean
gst_rtp_buffer_get_padding(GstRTPBuffer * rtp)614 gst_rtp_buffer_get_padding (GstRTPBuffer * rtp)
615 {
616   return GST_RTP_HEADER_PADDING (rtp->data[0]);
617 }
618 
619 /**
620  * gst_rtp_buffer_set_padding:
621  * @rtp: the buffer
622  * @padding: the new padding
623  *
624  * Set the padding bit on the RTP packet in @buffer to @padding.
625  */
626 void
gst_rtp_buffer_set_padding(GstRTPBuffer * rtp,gboolean padding)627 gst_rtp_buffer_set_padding (GstRTPBuffer * rtp, gboolean padding)
628 {
629   GST_RTP_HEADER_PADDING (rtp->data[0]) = padding;
630 }
631 
632 /**
633  * gst_rtp_buffer_pad_to:
634  * @rtp: the RTP packet
635  * @len: the new amount of padding
636  *
637  * Set the amount of padding in the RTP packet in @buffer to
638  * @len. If @len is 0, the padding is removed.
639  *
640  * NOTE: This function does not work correctly.
641  */
642 void
gst_rtp_buffer_pad_to(GstRTPBuffer * rtp,guint len)643 gst_rtp_buffer_pad_to (GstRTPBuffer * rtp, guint len)
644 {
645   guint8 *data;
646 
647   data = rtp->data[0];
648 
649   if (len > 0)
650     GST_RTP_HEADER_PADDING (data) = TRUE;
651   else
652     GST_RTP_HEADER_PADDING (data) = FALSE;
653 
654   /* FIXME, set the padding byte at the end of the payload data */
655 }
656 
657 /**
658  * gst_rtp_buffer_get_extension:
659  * @rtp: the RTP packet
660  *
661  * Check if the extension bit is set on the RTP packet in @buffer.
662  *
663  * Returns: TRUE if @buffer has the extension bit set.
664  */
665 gboolean
gst_rtp_buffer_get_extension(GstRTPBuffer * rtp)666 gst_rtp_buffer_get_extension (GstRTPBuffer * rtp)
667 {
668   return GST_RTP_HEADER_EXTENSION (rtp->data[0]);
669 }
670 
671 /**
672  * gst_rtp_buffer_set_extension:
673  * @rtp: the RTP packet
674  * @extension: the new extension
675  *
676  * Set the extension bit on the RTP packet in @buffer to @extension.
677  */
678 void
gst_rtp_buffer_set_extension(GstRTPBuffer * rtp,gboolean extension)679 gst_rtp_buffer_set_extension (GstRTPBuffer * rtp, gboolean extension)
680 {
681   GST_RTP_HEADER_EXTENSION (rtp->data[0]) = extension;
682 }
683 
684 /**
685  * gst_rtp_buffer_get_extension_data: (skip)
686  * @rtp: the RTP packet
687  * @bits: (optional) (out): location for result bits
688  * @data: (optional) (out) (array) (element-type guint8) (transfer none): location for data
689  * @wordlen: (optional) (out): location for length of @data in 32 bits words
690  *
691  * Get the extension data. @bits will contain the extension 16 bits of custom
692  * data. @data will point to the data in the extension and @wordlen will contain
693  * the length of @data in 32 bits words.
694  *
695  * If @buffer did not contain an extension, this function will return %FALSE
696  * with @bits, @data and @wordlen unchanged.
697  *
698  * Returns: TRUE if @buffer had the extension bit set.
699  */
700 gboolean
gst_rtp_buffer_get_extension_data(GstRTPBuffer * rtp,guint16 * bits,gpointer * data,guint * wordlen)701 gst_rtp_buffer_get_extension_data (GstRTPBuffer * rtp, guint16 * bits,
702     gpointer * data, guint * wordlen)
703 {
704   guint8 *pdata;
705 
706   /* move to the extension */
707   pdata = rtp->data[1];
708   if (!pdata)
709     return FALSE;
710 
711   if (bits)
712     *bits = GST_READ_UINT16_BE (pdata);
713   if (wordlen)
714     *wordlen = GST_READ_UINT16_BE (pdata + 2);
715   pdata += 4;
716   if (data)
717     *data = (gpointer *) pdata;
718 
719   return TRUE;
720 }
721 
722 /**
723  * gst_rtp_buffer_get_extension_bytes: (rename-to gst_rtp_buffer_get_extension_data)
724  * @rtp: the RTP packet
725  * @bits: (out): location for header bits
726  *
727  * Similar to gst_rtp_buffer_get_extension_data, but more suitable for language
728  * bindings usage. @bits will contain the extension 16 bits of custom data and
729  * the extension data (not including the extension header) is placed in a new
730  * #GBytes structure.
731  *
732  * If @rtp did not contain an extension, this function will return %NULL, with
733  * @bits unchanged. If there is an extension header but no extension data then
734  * an empty #GBytes will be returned.
735  *
736  * Returns: (transfer full): A new #GBytes if an extension header was present
737  * and %NULL otherwise.
738  *
739  * Since: 1.2
740  */
741 GBytes *
gst_rtp_buffer_get_extension_bytes(GstRTPBuffer * rtp,guint16 * bits)742 gst_rtp_buffer_get_extension_bytes (GstRTPBuffer * rtp, guint16 * bits)
743 {
744   gpointer buf_data = NULL;
745   guint buf_len;
746 
747   g_return_val_if_fail (rtp != NULL, FALSE);
748 
749   if (!gst_rtp_buffer_get_extension_data (rtp, bits, &buf_data, &buf_len))
750     return NULL;
751 
752   if (buf_len == 0) {
753     /* if no extension data is present return an empty GBytes */
754     buf_data = NULL;
755   }
756 
757   /* multiply length with 4 to get length in bytes */
758   return g_bytes_new (buf_data, 4 * buf_len);
759 }
760 
761 static gboolean
gst_rtp_buffer_map_payload(GstRTPBuffer * rtp)762 gst_rtp_buffer_map_payload (GstRTPBuffer * rtp)
763 {
764   guint hlen, plen;
765   guint idx, length;
766   gsize skip;
767 
768   if (rtp->map[2].memory != NULL)
769     return TRUE;
770 
771   hlen = gst_rtp_buffer_get_header_len (rtp);
772   plen = gst_buffer_get_size (rtp->buffer) - hlen - rtp->size[3];
773 
774   if (!gst_buffer_find_memory (rtp->buffer, hlen, plen, &idx, &length, &skip))
775     return FALSE;
776 
777   if (!gst_buffer_map_range (rtp->buffer, idx, length, &rtp->map[2],
778           rtp->map[0].flags))
779     return FALSE;
780 
781   rtp->data[2] = rtp->map[2].data + skip;
782   rtp->size[2] = plen;
783 
784   return TRUE;
785 }
786 
787 /* ensure header, payload and padding are in separate buffers */
788 static void
ensure_buffers(GstRTPBuffer * rtp)789 ensure_buffers (GstRTPBuffer * rtp)
790 {
791   guint i, pos;
792   gboolean changed = FALSE;
793 
794   /* make sure payload is mapped */
795   gst_rtp_buffer_map_payload (rtp);
796 
797   for (i = 0, pos = 0; i < 4; i++) {
798     if (rtp->size[i]) {
799       gsize offset = (guint8 *) rtp->data[i] - rtp->map[i].data;
800 
801       if (offset != 0 || rtp->map[i].size != rtp->size[i]) {
802         GstMemory *mem;
803 
804         /* make copy */
805         mem = gst_memory_copy (rtp->map[i].memory, offset, rtp->size[i]);
806 
807         /* insert new memory */
808         gst_buffer_insert_memory (rtp->buffer, pos, mem);
809 
810         changed = TRUE;
811       }
812       pos++;
813     }
814   }
815 
816   if (changed) {
817     GstBuffer *buf = rtp->buffer;
818 
819     gst_rtp_buffer_unmap (rtp);
820     gst_buffer_remove_memory_range (buf, pos, -1);
821     gst_rtp_buffer_map (buf, GST_MAP_READWRITE, rtp);
822   }
823 }
824 
825 /**
826  * gst_rtp_buffer_set_extension_data:
827  * @rtp: the RTP packet
828  * @bits: the bits specific for the extension
829  * @length: the length that counts the number of 32-bit words in
830  * the extension, excluding the extension header ( therefore zero is a valid length)
831  *
832  * Set the extension bit of the rtp buffer and fill in the @bits and @length of the
833  * extension header. If the existing extension data is not large enough, it will
834  * be made larger.
835  *
836  * Will also shorten the extension data from 1.20.
837  *
838  * Returns: True if done.
839  */
840 gboolean
gst_rtp_buffer_set_extension_data(GstRTPBuffer * rtp,guint16 bits,guint16 length)841 gst_rtp_buffer_set_extension_data (GstRTPBuffer * rtp, guint16 bits,
842     guint16 length)
843 {
844   guint32 min_size = 0;
845   guint8 *data;
846   GstMemory *mem = NULL;
847 
848   ensure_buffers (rtp);
849 
850   /* this is the size of the extension data we need */
851   min_size = 4 + length * sizeof (guint32);
852 
853   /* we should allocate and map the extension data */
854   if (rtp->data[1] == NULL || min_size > rtp->size[1]) {
855     GstMapInfo map;
856 
857     /* we don't have (enough) extension data, make some */
858     mem = gst_allocator_alloc (NULL, min_size, NULL);
859 
860     if (rtp->data[1]) {
861       /* copy old data & initialize the remainder of the new buffer */
862       gst_memory_map (mem, &map, GST_MAP_WRITE);
863       memcpy (map.data, rtp->data[1], rtp->size[1]);
864       if (min_size > rtp->size[1]) {
865         memset (map.data + rtp->size[1], 0, min_size - rtp->size[1]);
866       }
867       gst_memory_unmap (mem, &map);
868 
869       /* unmap old */
870       gst_buffer_unmap (rtp->buffer, &rtp->map[1]);
871       gst_buffer_replace_memory (rtp->buffer, 1, mem);
872     } else {
873       /* don't leak data from uninitialized memory via the padding */
874       gst_memory_map (mem, &map, GST_MAP_WRITE);
875       memset (map.data, 0, map.size);
876       gst_memory_unmap (mem, &map);
877 
878       /* we didn't have extension data, add */
879       gst_buffer_insert_memory (rtp->buffer, 1, mem);
880     }
881 
882     /* map new */
883     gst_memory_map (mem, &rtp->map[1], GST_MAP_READWRITE);
884     gst_memory_ref (mem);
885     rtp->data[1] = rtp->map[1].data;
886     rtp->size[1] = rtp->map[1].size;
887   } else if (min_size < rtp->size[1]) {
888     GstMemory *mem = rtp->map[1].memory;
889 
890     gst_memory_ref (mem);
891     gst_buffer_unmap (rtp->buffer, &rtp->map[1]);
892     gst_memory_resize (mem, 0, min_size);
893     gst_memory_map (mem, &rtp->map[1], GST_MAP_READWRITE);
894     rtp->data[1] = rtp->map[1].data;
895     rtp->size[1] = rtp->map[1].size;
896   }
897 
898   /* now we can set the extension bit */
899   data = rtp->data[0];
900   GST_RTP_HEADER_EXTENSION (data) = TRUE;
901 
902   data = rtp->data[1];
903   GST_WRITE_UINT16_BE (data, bits);
904   GST_WRITE_UINT16_BE (data + 2, length);
905 
906   return TRUE;
907 }
908 
909 /**
910  * gst_rtp_buffer_remove_extension_data:
911  * @rtp: the RTP packet
912  *
913  * Unsets the extension bit of the RTP buffer and removes the extension header
914  * and data.
915  *
916  * If the RTP buffer has no header extension data, the action has no effect.
917  * The RTP buffer must be mapped READWRITE only once and the underlying
918  * GstBuffer must be writable.
919  *
920  * Since: 1.20
921  */
922 void
gst_rtp_buffer_remove_extension_data(GstRTPBuffer * rtp)923 gst_rtp_buffer_remove_extension_data (GstRTPBuffer * rtp)
924 {
925   g_return_if_fail (gst_buffer_is_writable (rtp->buffer));
926   g_return_if_fail (rtp->map[0].flags & GST_MAP_WRITE);
927 
928   if (rtp->data[1] != NULL) {
929     GstBuffer *buf = rtp->buffer;
930 
931     ensure_buffers (rtp);
932 
933     GST_RTP_HEADER_EXTENSION (rtp->data[0]) = FALSE;
934     gst_rtp_buffer_unmap (rtp);
935     gst_buffer_remove_memory (buf, 1);
936     gst_rtp_buffer_map (buf, GST_MAP_READWRITE, rtp);
937   }
938 }
939 
940 /**
941  * gst_rtp_buffer_get_ssrc:
942  * @rtp: the RTP packet
943  *
944  * Get the SSRC of the RTP packet in @buffer.
945  *
946  * Returns: the SSRC of @buffer in host order.
947  */
948 guint32
gst_rtp_buffer_get_ssrc(GstRTPBuffer * rtp)949 gst_rtp_buffer_get_ssrc (GstRTPBuffer * rtp)
950 {
951   return g_ntohl (GST_RTP_HEADER_SSRC (rtp->data[0]));
952 }
953 
954 /**
955  * gst_rtp_buffer_set_ssrc:
956  * @rtp: the RTP packet
957  * @ssrc: the new SSRC
958  *
959  * Set the SSRC on the RTP packet in @buffer to @ssrc.
960  */
961 void
gst_rtp_buffer_set_ssrc(GstRTPBuffer * rtp,guint32 ssrc)962 gst_rtp_buffer_set_ssrc (GstRTPBuffer * rtp, guint32 ssrc)
963 {
964   GST_RTP_HEADER_SSRC (rtp->data[0]) = g_htonl (ssrc);
965 }
966 
967 /**
968  * gst_rtp_buffer_get_csrc_count:
969  * @rtp: the RTP packet
970  *
971  * Get the CSRC count of the RTP packet in @buffer.
972  *
973  * Returns: the CSRC count of @buffer.
974  */
975 guint8
gst_rtp_buffer_get_csrc_count(GstRTPBuffer * rtp)976 gst_rtp_buffer_get_csrc_count (GstRTPBuffer * rtp)
977 {
978   return GST_RTP_HEADER_CSRC_COUNT (rtp->data[0]);
979 }
980 
981 /**
982  * gst_rtp_buffer_get_csrc:
983  * @rtp: the RTP packet
984  * @idx: the index of the CSRC to get
985  *
986  * Get the CSRC at index @idx in @buffer.
987  *
988  * Returns: the CSRC at index @idx in host order.
989  */
990 guint32
gst_rtp_buffer_get_csrc(GstRTPBuffer * rtp,guint8 idx)991 gst_rtp_buffer_get_csrc (GstRTPBuffer * rtp, guint8 idx)
992 {
993   guint8 *data;
994 
995   data = rtp->data[0];
996 
997   g_return_val_if_fail (idx < GST_RTP_HEADER_CSRC_COUNT (data), 0);
998 
999   return GST_READ_UINT32_BE (GST_RTP_HEADER_CSRC_LIST_OFFSET (data, idx));
1000 }
1001 
1002 /**
1003  * gst_rtp_buffer_set_csrc:
1004  * @rtp: the RTP packet
1005  * @idx: the CSRC index to set
1006  * @csrc: the CSRC in host order to set at @idx
1007  *
1008  * Modify the CSRC at index @idx in @buffer to @csrc.
1009  */
1010 void
gst_rtp_buffer_set_csrc(GstRTPBuffer * rtp,guint8 idx,guint32 csrc)1011 gst_rtp_buffer_set_csrc (GstRTPBuffer * rtp, guint8 idx, guint32 csrc)
1012 {
1013   guint8 *data;
1014 
1015   data = rtp->data[0];
1016 
1017   g_return_if_fail (idx < GST_RTP_HEADER_CSRC_COUNT (data));
1018 
1019   GST_WRITE_UINT32_BE (GST_RTP_HEADER_CSRC_LIST_OFFSET (data, idx), csrc);
1020 }
1021 
1022 /**
1023  * gst_rtp_buffer_get_marker:
1024  * @rtp: the RTP packet
1025  *
1026  * Check if the marker bit is set on the RTP packet in @buffer.
1027  *
1028  * Returns: TRUE if @buffer has the marker bit set.
1029  */
1030 gboolean
gst_rtp_buffer_get_marker(GstRTPBuffer * rtp)1031 gst_rtp_buffer_get_marker (GstRTPBuffer * rtp)
1032 {
1033   return GST_RTP_HEADER_MARKER (rtp->data[0]);
1034 }
1035 
1036 /**
1037  * gst_rtp_buffer_set_marker:
1038  * @rtp: the RTP packet
1039  * @marker: the new marker
1040  *
1041  * Set the marker bit on the RTP packet in @buffer to @marker.
1042  */
1043 void
gst_rtp_buffer_set_marker(GstRTPBuffer * rtp,gboolean marker)1044 gst_rtp_buffer_set_marker (GstRTPBuffer * rtp, gboolean marker)
1045 {
1046   GST_RTP_HEADER_MARKER (rtp->data[0]) = marker;
1047 }
1048 
1049 /**
1050  * gst_rtp_buffer_get_payload_type:
1051  * @rtp: the RTP packet
1052  *
1053  * Get the payload type of the RTP packet in @buffer.
1054  *
1055  * Returns: The payload type.
1056  */
1057 guint8
gst_rtp_buffer_get_payload_type(GstRTPBuffer * rtp)1058 gst_rtp_buffer_get_payload_type (GstRTPBuffer * rtp)
1059 {
1060   return GST_RTP_HEADER_PAYLOAD_TYPE (rtp->data[0]);
1061 }
1062 
1063 /**
1064  * gst_rtp_buffer_set_payload_type:
1065  * @rtp: the RTP packet
1066  * @payload_type: the new type
1067  *
1068  * Set the payload type of the RTP packet in @buffer to @payload_type.
1069  */
1070 void
gst_rtp_buffer_set_payload_type(GstRTPBuffer * rtp,guint8 payload_type)1071 gst_rtp_buffer_set_payload_type (GstRTPBuffer * rtp, guint8 payload_type)
1072 {
1073   g_return_if_fail (payload_type < 0x80);
1074 
1075   GST_RTP_HEADER_PAYLOAD_TYPE (rtp->data[0]) = payload_type;
1076 }
1077 
1078 /**
1079  * gst_rtp_buffer_get_seq:
1080  * @rtp: the RTP packet
1081  *
1082  * Get the sequence number of the RTP packet in @buffer.
1083  *
1084  * Returns: The sequence number in host order.
1085  */
1086 guint16
gst_rtp_buffer_get_seq(GstRTPBuffer * rtp)1087 gst_rtp_buffer_get_seq (GstRTPBuffer * rtp)
1088 {
1089   return g_ntohs (GST_RTP_HEADER_SEQ (rtp->data[0]));
1090 }
1091 
1092 /**
1093  * gst_rtp_buffer_set_seq:
1094  * @rtp: the RTP packet
1095  * @seq: the new sequence number
1096  *
1097  * Set the sequence number of the RTP packet in @buffer to @seq.
1098  */
1099 void
gst_rtp_buffer_set_seq(GstRTPBuffer * rtp,guint16 seq)1100 gst_rtp_buffer_set_seq (GstRTPBuffer * rtp, guint16 seq)
1101 {
1102   GST_RTP_HEADER_SEQ (rtp->data[0]) = g_htons (seq);
1103 }
1104 
1105 /**
1106  * gst_rtp_buffer_get_timestamp:
1107  * @rtp: the RTP packet
1108  *
1109  * Get the timestamp of the RTP packet in @buffer.
1110  *
1111  * Returns: The timestamp in host order.
1112  */
1113 guint32
gst_rtp_buffer_get_timestamp(GstRTPBuffer * rtp)1114 gst_rtp_buffer_get_timestamp (GstRTPBuffer * rtp)
1115 {
1116   return g_ntohl (GST_RTP_HEADER_TIMESTAMP (rtp->data[0]));
1117 }
1118 
1119 /**
1120  * gst_rtp_buffer_set_timestamp:
1121  * @rtp: the RTP packet
1122  * @timestamp: the new timestamp
1123  *
1124  * Set the timestamp of the RTP packet in @buffer to @timestamp.
1125  */
1126 void
gst_rtp_buffer_set_timestamp(GstRTPBuffer * rtp,guint32 timestamp)1127 gst_rtp_buffer_set_timestamp (GstRTPBuffer * rtp, guint32 timestamp)
1128 {
1129   GST_RTP_HEADER_TIMESTAMP (rtp->data[0]) = g_htonl (timestamp);
1130 }
1131 
1132 
1133 /**
1134  * gst_rtp_buffer_get_payload_subbuffer:
1135  * @rtp: the RTP packet
1136  * @offset: the offset in the payload
1137  * @len: the length in the payload
1138  *
1139  * Create a subbuffer of the payload of the RTP packet in @buffer. @offset bytes
1140  * are skipped in the payload and the subbuffer will be of size @len.
1141  * If @len is -1 the total payload starting from @offset is subbuffered.
1142  *
1143  * Returns: A new buffer with the specified data of the payload.
1144  */
1145 GstBuffer *
gst_rtp_buffer_get_payload_subbuffer(GstRTPBuffer * rtp,guint offset,guint len)1146 gst_rtp_buffer_get_payload_subbuffer (GstRTPBuffer * rtp, guint offset,
1147     guint len)
1148 {
1149   guint poffset, plen;
1150 
1151   plen = gst_rtp_buffer_get_payload_len (rtp);
1152   /* we can't go past the length */
1153   if (G_UNLIKELY (offset > plen))
1154     goto wrong_offset;
1155 
1156   /* apply offset */
1157   poffset = gst_rtp_buffer_get_header_len (rtp) + offset;
1158   plen -= offset;
1159 
1160   /* see if we need to shrink the buffer based on @len */
1161   if (len != -1 && len < plen)
1162     plen = len;
1163 
1164   return gst_buffer_copy_region (rtp->buffer, GST_BUFFER_COPY_ALL, poffset,
1165       plen);
1166 
1167   /* ERRORS */
1168 wrong_offset:
1169   {
1170     g_warning ("offset=%u should be less than plen=%u", offset, plen);
1171     return NULL;
1172   }
1173 }
1174 
1175 /**
1176  * gst_rtp_buffer_get_payload_buffer:
1177  * @rtp: the RTP packet
1178  *
1179  * Create a buffer of the payload of the RTP packet in @buffer. This function
1180  * will internally create a subbuffer of @buffer so that a memcpy can be
1181  * avoided.
1182  *
1183  * Returns: A new buffer with the data of the payload.
1184  */
1185 GstBuffer *
gst_rtp_buffer_get_payload_buffer(GstRTPBuffer * rtp)1186 gst_rtp_buffer_get_payload_buffer (GstRTPBuffer * rtp)
1187 {
1188   return gst_rtp_buffer_get_payload_subbuffer (rtp, 0, -1);
1189 }
1190 
1191 /**
1192  * gst_rtp_buffer_get_payload_len:
1193  * @rtp: the RTP packet
1194  *
1195  * Get the length of the payload of the RTP packet in @buffer.
1196  *
1197  * Returns: The length of the payload in @buffer.
1198  */
1199 guint
gst_rtp_buffer_get_payload_len(GstRTPBuffer * rtp)1200 gst_rtp_buffer_get_payload_len (GstRTPBuffer * rtp)
1201 {
1202   return gst_buffer_get_size (rtp->buffer) - gst_rtp_buffer_get_header_len (rtp)
1203       - rtp->size[3];
1204 }
1205 
1206 /**
1207  * gst_rtp_buffer_get_payload: (skip)
1208  * @rtp: the RTP packet
1209  *
1210  * Get a pointer to the payload data in @buffer. This pointer is valid as long
1211  * as a reference to @buffer is held.
1212  *
1213  * Returns: (array) (element-type guint8) (transfer none): A pointer
1214  * to the payload data in @buffer.
1215  */
1216 gpointer
gst_rtp_buffer_get_payload(GstRTPBuffer * rtp)1217 gst_rtp_buffer_get_payload (GstRTPBuffer * rtp)
1218 {
1219   if (rtp->data[2])
1220     return rtp->data[2];
1221 
1222   if (!gst_rtp_buffer_map_payload (rtp))
1223     return NULL;
1224 
1225   return rtp->data[2];
1226 }
1227 
1228 /**
1229  * gst_rtp_buffer_get_payload_bytes: (rename-to gst_rtp_buffer_get_payload)
1230  * @rtp: the RTP packet
1231  *
1232  * Similar to gst_rtp_buffer_get_payload, but more suitable for language
1233  * bindings usage. The return value is a pointer to a #GBytes structure
1234  * containing the payload data in @rtp.
1235  *
1236  * Returns: (transfer full): A new #GBytes containing the payload data in @rtp.
1237  *
1238  * Since: 1.2
1239  */
1240 GBytes *
gst_rtp_buffer_get_payload_bytes(GstRTPBuffer * rtp)1241 gst_rtp_buffer_get_payload_bytes (GstRTPBuffer * rtp)
1242 {
1243   gpointer data;
1244 
1245   g_return_val_if_fail (rtp != NULL, NULL);
1246 
1247   data = gst_rtp_buffer_get_payload (rtp);
1248   if (data == NULL)
1249     return NULL;
1250 
1251   return g_bytes_new (data, gst_rtp_buffer_get_payload_len (rtp));
1252 }
1253 
1254 /**
1255  * gst_rtp_buffer_default_clock_rate:
1256  * @payload_type: the static payload type
1257  *
1258  * Get the default clock-rate for the static payload type @payload_type.
1259  *
1260  * Returns: the default clock rate or -1 if the payload type is not static or
1261  * the clock-rate is undefined.
1262  */
1263 guint32
gst_rtp_buffer_default_clock_rate(guint8 payload_type)1264 gst_rtp_buffer_default_clock_rate (guint8 payload_type)
1265 {
1266   const GstRTPPayloadInfo *info;
1267   guint32 res;
1268 
1269   info = gst_rtp_payload_info_for_pt (payload_type);
1270   if (!info)
1271     return -1;
1272 
1273   res = info->clock_rate;
1274   /* 0 means unknown so we have to return -1 from this function */
1275   if (res == 0)
1276     res = -1;
1277 
1278   return res;
1279 }
1280 
1281 /**
1282  * gst_rtp_buffer_compare_seqnum:
1283  * @seqnum1: a sequence number
1284  * @seqnum2: a sequence number
1285  *
1286  * Compare two sequence numbers, taking care of wraparounds. This function
1287  * returns the difference between @seqnum1 and @seqnum2.
1288  *
1289  * Returns: a negative value if @seqnum1 is bigger than @seqnum2, 0 if they
1290  * are equal or a positive value if @seqnum1 is smaller than @segnum2.
1291  */
1292 gint
gst_rtp_buffer_compare_seqnum(guint16 seqnum1,guint16 seqnum2)1293 gst_rtp_buffer_compare_seqnum (guint16 seqnum1, guint16 seqnum2)
1294 {
1295   /* See http://en.wikipedia.org/wiki/Serial_number_arithmetic
1296    * for an explanation why this does the right thing even for
1297    * wraparounds, under the assumption that the difference is
1298    * never bigger than 2**15 sequence numbers
1299    */
1300   return (gint16) (seqnum2 - seqnum1);
1301 }
1302 
1303 /**
1304  * gst_rtp_buffer_ext_timestamp:
1305  * @exttimestamp: (inout): a previous extended timestamp
1306  * @timestamp: a new timestamp
1307  *
1308  * Update the @exttimestamp field with the extended timestamp of @timestamp
1309  * For the first call of the method, @exttimestamp should point to a location
1310  * with a value of -1.
1311  *
1312  * This function is able to handle both forward and backward timestamps taking
1313  * into account:
1314  *   - timestamp wraparound making sure that the returned value is properly increased.
1315  *   - timestamp unwraparound making sure that the returned value is properly decreased.
1316  *
1317  * Returns: The extended timestamp of @timestamp or 0 if the result can't go anywhere backwards.
1318  */
1319 guint64
gst_rtp_buffer_ext_timestamp(guint64 * exttimestamp,guint32 timestamp)1320 gst_rtp_buffer_ext_timestamp (guint64 * exttimestamp, guint32 timestamp)
1321 {
1322   guint64 result, ext;
1323 
1324   g_return_val_if_fail (exttimestamp != NULL, -1);
1325 
1326   ext = *exttimestamp;
1327 
1328   if (ext == -1) {
1329     result = timestamp;
1330   } else {
1331     /* pick wraparound counter from previous timestamp and add to new timestamp */
1332     result = timestamp + (ext & ~(G_GUINT64_CONSTANT (0xffffffff)));
1333 
1334     /* check for timestamp wraparound */
1335     if (result < ext) {
1336       guint64 diff = ext - result;
1337 
1338       if (diff > G_MAXINT32) {
1339         /* timestamp went backwards more than allowed, we wrap around and get
1340          * updated extended timestamp. */
1341         result += (G_GUINT64_CONSTANT (1) << 32);
1342       }
1343     } else {
1344       guint64 diff = result - ext;
1345 
1346       if (diff > G_MAXINT32) {
1347         if (result < (G_GUINT64_CONSTANT (1) << 32)) {
1348           GST_WARNING
1349               ("Cannot unwrap, any wrapping took place yet. Returning 0 without updating extended timestamp.");
1350           return 0;
1351         } else {
1352           /* timestamp went forwards more than allowed, we unwrap around and get
1353            * updated extended timestamp. */
1354           result -= (G_GUINT64_CONSTANT (1) << 32);
1355           /* We don't want the extended timestamp storage to go back, ever */
1356           return result;
1357         }
1358       }
1359     }
1360   }
1361 
1362   *exttimestamp = result;
1363 
1364   return result;
1365 }
1366 
1367 
1368 static gboolean
_get_extension_onebyte_header(const guint8 * pdata,guint len,guint16 bit_pattern,guint8 id,guint nth,gpointer * data,guint * size)1369 _get_extension_onebyte_header (const guint8 * pdata, guint len,
1370     guint16 bit_pattern, guint8 id, guint nth, gpointer * data, guint * size)
1371 {
1372   gulong offset = 0;
1373   guint count = 0;
1374 
1375   g_return_val_if_fail (id > 0 && id < 15, FALSE);
1376 
1377   if (bit_pattern != 0xBEDE)
1378     return FALSE;
1379 
1380   for (;;) {
1381     guint8 read_id, read_len;
1382 
1383     if (offset + 1 >= len)
1384       break;
1385 
1386     read_id = GST_READ_UINT8 (pdata + offset) >> 4;
1387     read_len = (GST_READ_UINT8 (pdata + offset) & 0x0F) + 1;
1388     offset += 1;
1389 
1390     /* ID 0 means its padding, skip */
1391     if (read_id == 0)
1392       continue;
1393 
1394     /* ID 15 is special and means we should stop parsing */
1395     if (read_id == 15)
1396       break;
1397 
1398     /* Ignore extension headers where the size does not fit */
1399     if (offset + read_len > len)
1400       break;
1401 
1402     /* If we have the right one */
1403     if (id == read_id) {
1404       if (nth == count) {
1405         if (data)
1406           *data = (gpointer) & pdata[offset];
1407         if (size)
1408           *size = read_len;
1409 
1410         return TRUE;
1411       }
1412 
1413       count++;
1414     }
1415     offset += read_len;
1416 
1417     if (offset >= len)
1418       break;
1419   }
1420 
1421   return FALSE;
1422 }
1423 
1424 
1425 /**
1426  * gst_rtp_buffer_get_extension_onebyte_header_from_bytes:
1427  * @bytes: #GBytes
1428  * @bit_pattern: The bit-pattern. Anything but 0xBEDE is rejected.
1429  * @id: The ID of the header extension to be read (between 1 and 14).
1430  * @nth: Read the nth extension packet with the requested ID
1431  * @data: (out) (array length=size) (element-type guint8) (transfer none):
1432  *   location for data
1433  * @size: (out): the size of the data in bytes
1434  *
1435  * Similar to gst_rtp_buffer_get_extension_onebyte_header, but working
1436  * on the #GBytes you get from gst_rtp_buffer_get_extension_bytes.
1437  * Parses RFC 5285 style header extensions with a one byte header. It will
1438  * return the nth extension with the requested id.
1439  *
1440  * Returns: TRUE if @bytes had the requested header extension
1441  *
1442  * Since: 1.18
1443  */
1444 gboolean
gst_rtp_buffer_get_extension_onebyte_header_from_bytes(GBytes * bytes,guint16 bit_pattern,guint8 id,guint nth,gpointer * data,guint * size)1445 gst_rtp_buffer_get_extension_onebyte_header_from_bytes (GBytes * bytes,
1446     guint16 bit_pattern, guint8 id, guint nth, gpointer * data, guint * size)
1447 {
1448   const guint8 *pdata = g_bytes_get_data (bytes, NULL);
1449   gsize len = g_bytes_get_size (bytes);
1450   return _get_extension_onebyte_header (pdata, len, bit_pattern, id, nth, data,
1451       size);
1452 }
1453 
1454 
1455 /**
1456  * gst_rtp_buffer_get_extension_onebyte_header:
1457  * @rtp: the RTP packet
1458  * @id: The ID of the header extension to be read (between 1 and 14).
1459  * @nth: Read the nth extension packet with the requested ID
1460  * @data: (optional) (out) (array length=size) (element-type guint8) (transfer none):
1461  *   location for data
1462  * @size: (optional) (out): the size of the data in bytes
1463  *
1464  * Parses RFC 5285 style header extensions with a one byte header. It will
1465  * return the nth extension with the requested id.
1466  *
1467  * Returns: TRUE if @buffer had the requested header extension
1468  */
1469 
1470 gboolean
gst_rtp_buffer_get_extension_onebyte_header(GstRTPBuffer * rtp,guint8 id,guint nth,gpointer * data,guint * size)1471 gst_rtp_buffer_get_extension_onebyte_header (GstRTPBuffer * rtp, guint8 id,
1472     guint nth, gpointer * data, guint * size)
1473 {
1474   guint16 bit_pattern;
1475   guint8 *pdata;
1476   guint wordlen;
1477 
1478   if (!gst_rtp_buffer_get_extension_data (rtp, &bit_pattern, (gpointer) & pdata,
1479           &wordlen))
1480     return FALSE;
1481 
1482   return _get_extension_onebyte_header (pdata, wordlen * 4, bit_pattern, id,
1483       nth, data, size);
1484 }
1485 
1486 
1487 /**
1488  * gst_rtp_buffer_get_extension_twobytes_header:
1489  * @rtp: the RTP packet
1490  * @appbits: (optional) (out): Application specific bits
1491  * @id: The ID of the header extension to be read (between 1 and 14).
1492  * @nth: Read the nth extension packet with the requested ID
1493  * @data: (optional) (out) (array length=size) (element-type guint8) (transfer none):
1494  *   location for data
1495  * @size: (optional) (out): the size of the data in bytes
1496  *
1497  * Parses RFC 5285 style header extensions with a two bytes header. It will
1498  * return the nth extension with the requested id.
1499  *
1500  * Returns: TRUE if @buffer had the requested header extension
1501  */
1502 
1503 gboolean
gst_rtp_buffer_get_extension_twobytes_header(GstRTPBuffer * rtp,guint8 * appbits,guint8 id,guint nth,gpointer * data,guint * size)1504 gst_rtp_buffer_get_extension_twobytes_header (GstRTPBuffer * rtp,
1505     guint8 * appbits, guint8 id, guint nth, gpointer * data, guint * size)
1506 {
1507   guint16 bits;
1508   guint8 *pdata = NULL;
1509   guint wordlen;
1510   guint bytelen;
1511   gulong offset = 0;
1512   guint count = 0;
1513 
1514   if (!gst_rtp_buffer_get_extension_data (rtp, &bits, (gpointer *) & pdata,
1515           &wordlen))
1516     return FALSE;
1517 
1518   if (bits >> 4 != 0x100)
1519     return FALSE;
1520 
1521   bytelen = wordlen * 4;
1522 
1523   for (;;) {
1524     guint8 read_id, read_len;
1525 
1526     if (offset + 2 >= bytelen)
1527       break;
1528 
1529     read_id = GST_READ_UINT8 (pdata + offset);
1530     offset += 1;
1531 
1532     if (read_id == 0)
1533       continue;
1534 
1535     read_len = GST_READ_UINT8 (pdata + offset);
1536     offset += 1;
1537 
1538     /* Ignore extension headers where the size does not fit */
1539     if (offset + read_len > bytelen)
1540       break;
1541 
1542     /* If we have the right one, return it */
1543     if (id == read_id) {
1544       if (nth == count) {
1545         if (data)
1546           *data = pdata + offset;
1547         if (size)
1548           *size = read_len;
1549         if (appbits)
1550           *appbits = bits;
1551 
1552         return TRUE;
1553       }
1554 
1555       count++;
1556     }
1557     offset += read_len;
1558   }
1559 
1560   return FALSE;
1561 }
1562 
1563 static gboolean
get_onebyte_header_end_offset(guint8 * pdata,guint wordlen,guint * offset)1564 get_onebyte_header_end_offset (guint8 * pdata, guint wordlen, guint * offset)
1565 {
1566   guint bytelen = wordlen * 4;
1567   guint paddingcount = 0;
1568 
1569   *offset = 0;
1570 
1571   while (*offset + 1 < bytelen) {
1572     guint8 read_id, read_len;
1573 
1574     read_id = GST_READ_UINT8 (pdata + *offset) >> 4;
1575     read_len = (GST_READ_UINT8 (pdata + *offset) & 0x0F) + 1;
1576     *offset += 1;
1577 
1578     /* ID 0 means its padding, skip */
1579     if (read_id == 0) {
1580       paddingcount++;
1581       continue;
1582     }
1583 
1584     paddingcount = 0;
1585 
1586     /* ID 15 is special and means we should stop parsing */
1587     /* It also means we can't add an extra packet */
1588     if (read_id == 15) {
1589       return FALSE;
1590     }
1591 
1592     /* Ignore extension headers where the size does not fit */
1593     if (*offset + read_len > bytelen) {
1594       return FALSE;
1595     }
1596 
1597     *offset += read_len;
1598   }
1599 
1600   *offset -= paddingcount;
1601 
1602   return TRUE;
1603 }
1604 
1605 /**
1606  * gst_rtp_buffer_add_extension_onebyte_header:
1607  * @rtp: the RTP packet
1608  * @id: The ID of the header extension (between 1 and 14).
1609  * @data: (array length=size) (element-type guint8): location for data
1610  * @size: the size of the data in bytes
1611  *
1612  * Adds a RFC 5285 header extension with a one byte header to the end of the
1613  * RTP header. If there is already a RFC 5285 header extension with a one byte
1614  * header, the new extension will be appended.
1615  * It will not work if there is already a header extension that does not follow
1616  * the mechanism described in RFC 5285 or if there is a header extension with
1617  * a two bytes header as described in RFC 5285. In that case, use
1618  * gst_rtp_buffer_add_extension_twobytes_header()
1619  *
1620  * Returns: %TRUE if header extension could be added
1621  */
1622 
1623 gboolean
gst_rtp_buffer_add_extension_onebyte_header(GstRTPBuffer * rtp,guint8 id,gconstpointer data,guint size)1624 gst_rtp_buffer_add_extension_onebyte_header (GstRTPBuffer * rtp, guint8 id,
1625     gconstpointer data, guint size)
1626 {
1627   guint16 bits;
1628   guint8 *pdata = 0;
1629   guint wordlen = 0;
1630   guint wordlen_new;
1631   gboolean has_bit;
1632   guint extlen, offset = 0;
1633 
1634   g_return_val_if_fail (id > 0 && id < 15, FALSE);
1635   g_return_val_if_fail (size >= 1 && size <= 16, FALSE);
1636   g_return_val_if_fail (gst_buffer_is_writable (rtp->buffer), FALSE);
1637 
1638   has_bit = gst_rtp_buffer_get_extension_data (rtp, &bits,
1639       (gpointer) & pdata, &wordlen);
1640 
1641   if (has_bit) {
1642     if (bits != 0xBEDE)
1643       return FALSE;
1644 
1645     if (!get_onebyte_header_end_offset (pdata, wordlen, &offset))
1646       return FALSE;
1647   }
1648 
1649   /* the required size of the new extension data */
1650   extlen = offset + size + 1;
1651   /* calculate amount of words */
1652   wordlen_new = extlen / 4 + ((extlen % 4) ? 1 : 0);
1653   wordlen_new = MAX (wordlen_new, wordlen);
1654 
1655   gst_rtp_buffer_set_extension_data (rtp, 0xBEDE, wordlen_new);
1656   gst_rtp_buffer_get_extension_data (rtp, &bits, (gpointer) & pdata, &wordlen);
1657 
1658   pdata += offset;
1659 
1660   pdata[0] = (id << 4) | (0x0F & (size - 1));
1661   memcpy (pdata + 1, data, size);
1662 
1663   if (extlen % 4)
1664     memset (pdata + 1 + size, 0, 4 - (extlen % 4));
1665 
1666   return TRUE;
1667 }
1668 
1669 
1670 static guint
get_twobytes_header_end_offset(const guint8 * pdata,guint wordlen)1671 get_twobytes_header_end_offset (const guint8 * pdata, guint wordlen)
1672 {
1673   guint offset = 0;
1674   guint bytelen = wordlen * 4;
1675   guint paddingcount = 0;
1676 
1677   while (offset + 2 < bytelen) {
1678     guint8 read_id, read_len;
1679 
1680     read_id = GST_READ_UINT8 (pdata + offset);
1681     offset += 1;
1682 
1683     /* ID 0 means its padding, skip */
1684     if (read_id == 0) {
1685       paddingcount++;
1686       continue;
1687     }
1688 
1689     paddingcount = 0;
1690 
1691     read_len = GST_READ_UINT8 (pdata + offset);
1692     offset += 1;
1693 
1694     /* Ignore extension headers where the size does not fit */
1695     if (offset + read_len > bytelen)
1696       return 0;
1697 
1698     offset += read_len;
1699   }
1700 
1701   return offset - paddingcount;
1702 }
1703 
1704 /**
1705  * gst_rtp_buffer_add_extension_twobytes_header:
1706  * @rtp: the RTP packet
1707  * @appbits: Application specific bits
1708  * @id: The ID of the header extension
1709  * @data: (array length=size) (element-type guint8): location for data
1710  * @size: the size of the data in bytes
1711  *
1712  * Adds a RFC 5285 header extension with a two bytes header to the end of the
1713  * RTP header. If there is already a RFC 5285 header extension with a two bytes
1714  * header, the new extension will be appended.
1715  * It will not work if there is already a header extension that does not follow
1716  * the mechanism described in RFC 5285 or if there is a header extension with
1717  * a one byte header as described in RFC 5285. In that case, use
1718  * gst_rtp_buffer_add_extension_onebyte_header()
1719  *
1720  * Returns: %TRUE if header extension could be added
1721  */
1722 
1723 gboolean
gst_rtp_buffer_add_extension_twobytes_header(GstRTPBuffer * rtp,guint8 appbits,guint8 id,gconstpointer data,guint size)1724 gst_rtp_buffer_add_extension_twobytes_header (GstRTPBuffer * rtp,
1725     guint8 appbits, guint8 id, gconstpointer data, guint size)
1726 {
1727   guint16 bits;
1728   guint8 *pdata = 0;
1729   guint wordlen;
1730   gboolean has_bit;
1731   gulong offset = 0;
1732   guint extlen;
1733 
1734   g_return_val_if_fail ((appbits & 0xF0) == 0, FALSE);
1735   g_return_val_if_fail (size < 256, FALSE);
1736   g_return_val_if_fail (gst_buffer_is_writable (rtp->buffer), FALSE);
1737 
1738   has_bit = gst_rtp_buffer_get_extension_data (rtp, &bits,
1739       (gpointer) & pdata, &wordlen);
1740 
1741   if (has_bit) {
1742     if (bits != ((0x100 << 4) | (appbits & 0x0f)))
1743       return FALSE;
1744 
1745     offset = get_twobytes_header_end_offset (pdata, wordlen);
1746     if (offset == 0)
1747       return FALSE;
1748   }
1749 
1750   /* the required size of the new extension data */
1751   extlen = offset + size + 2;
1752   /* calculate amount of words */
1753   wordlen = extlen / 4 + ((extlen % 4) ? 1 : 0);
1754 
1755   gst_rtp_buffer_set_extension_data (rtp, (0x100 << 4) | (appbits & 0x0F),
1756       wordlen);
1757   gst_rtp_buffer_get_extension_data (rtp, &bits, (gpointer) & pdata, &wordlen);
1758 
1759   pdata += offset;
1760 
1761   pdata[0] = id;
1762   pdata[1] = size;
1763   memcpy (pdata + 2, data, size);
1764   if (extlen % 4)
1765     memset (pdata + 2 + size, 0, 4 - (extlen % 4));
1766 
1767   return TRUE;
1768 }
1769