rtpbuffer: use proper format for gsize
[platform/upstream/gstreamer.git] / gst-libs / gst / rtp / gstrtpbuffer.c
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., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 /**
22  * SECTION:gstrtpbuffer
23  * @short_description: Helper methods for dealing with RTP buffers
24  * @see_also: #GstRTPBasePayload, #GstRTPBaseDepayload, gstrtcpbuffer
25  *
26  * <refsect2>
27  * <para>
28  * The GstRTPBuffer helper functions makes it easy to parse and create regular 
29  * #GstBuffer objects that contain RTP payloads. These buffers are typically of
30  * 'application/x-rtp' #GstCaps.
31  * </para>
32  * </refsect2>
33  *
34  * Last reviewed on 2006-07-17 (0.10.10)
35  */
36
37 #include "gstrtpbuffer.h"
38
39 #include <stdlib.h>
40 #include <string.h>
41
42 #define GST_RTP_HEADER_LEN 12
43
44 /* Note: we use bitfields here to make sure the compiler doesn't add padding
45  * between fields on certain architectures; can't assume aligned access either
46  */
47 typedef struct _GstRTPHeader
48 {
49 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
50   unsigned int csrc_count:4;    /* CSRC count */
51   unsigned int extension:1;     /* header extension flag */
52   unsigned int padding:1;       /* padding flag */
53   unsigned int version:2;       /* protocol version */
54   unsigned int payload_type:7;  /* payload type */
55   unsigned int marker:1;        /* marker bit */
56 #elif G_BYTE_ORDER == G_BIG_ENDIAN
57   unsigned int version:2;       /* protocol version */
58   unsigned int padding:1;       /* padding flag */
59   unsigned int extension:1;     /* header extension flag */
60   unsigned int csrc_count:4;    /* CSRC count */
61   unsigned int marker:1;        /* marker bit */
62   unsigned int payload_type:7;  /* payload type */
63 #else
64 #error "G_BYTE_ORDER should be big or little endian."
65 #endif
66   unsigned int seq:16;          /* sequence number */
67   unsigned int timestamp:32;    /* timestamp */
68   unsigned int ssrc:32;         /* synchronization source */
69   guint8 csrclist[4];           /* optional CSRC list, 32 bits each */
70 } GstRTPHeader;
71
72 #define GST_RTP_HEADER_VERSION(data)      (((GstRTPHeader *)(data))->version)
73 #define GST_RTP_HEADER_PADDING(data)      (((GstRTPHeader *)(data))->padding)
74 #define GST_RTP_HEADER_EXTENSION(data)    (((GstRTPHeader *)(data))->extension)
75 #define GST_RTP_HEADER_CSRC_COUNT(data)   (((GstRTPHeader *)(data))->csrc_count)
76 #define GST_RTP_HEADER_MARKER(data)       (((GstRTPHeader *)(data))->marker)
77 #define GST_RTP_HEADER_PAYLOAD_TYPE(data) (((GstRTPHeader *)(data))->payload_type)
78 #define GST_RTP_HEADER_SEQ(data)          (((GstRTPHeader *)(data))->seq)
79 #define GST_RTP_HEADER_TIMESTAMP(data)    (((GstRTPHeader *)(data))->timestamp)
80 #define GST_RTP_HEADER_SSRC(data)         (((GstRTPHeader *)(data))->ssrc)
81 #define GST_RTP_HEADER_CSRC_LIST_OFFSET(data,i)        \
82     data + G_STRUCT_OFFSET(GstRTPHeader, csrclist) +   \
83     ((i) * sizeof(guint32))
84 #define GST_RTP_HEADER_CSRC_SIZE(data)   (GST_RTP_HEADER_CSRC_COUNT(data) * sizeof (guint32))
85
86 /**
87  * gst_rtp_buffer_allocate_data:
88  * @buffer: a #GstBuffer
89  * @payload_len: the length of the payload
90  * @pad_len: the amount of padding
91  * @csrc_count: the number of CSRC entries
92  *
93  * Allocate enough data in @buffer to hold an RTP packet with @csrc_count CSRCs,
94  * a payload length of @payload_len and padding of @pad_len.
95  * @buffer must be writable and all previous memory in @buffer will be freed.
96  * All other RTP header fields will be set to 0/FALSE.
97  */
98 void
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 len;
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   len = GST_RTP_HEADER_LEN + csrc_count * sizeof (guint32)
113       + payload_len + pad_len;
114
115   mem = gst_allocator_alloc (NULL, len, NULL);
116
117   gst_memory_map (mem, &map, GST_MAP_WRITE);
118   /* fill in defaults */
119   GST_RTP_HEADER_VERSION (map.data) = GST_RTP_VERSION;
120   GST_RTP_HEADER_PADDING (map.data) = FALSE;
121   GST_RTP_HEADER_EXTENSION (map.data) = FALSE;
122   GST_RTP_HEADER_CSRC_COUNT (map.data) = csrc_count;
123   memset (GST_RTP_HEADER_CSRC_LIST_OFFSET (map.data, 0), 0,
124       csrc_count * sizeof (guint32));
125   GST_RTP_HEADER_MARKER (map.data) = FALSE;
126   GST_RTP_HEADER_PAYLOAD_TYPE (map.data) = 0;
127   GST_RTP_HEADER_SEQ (map.data) = 0;
128   GST_RTP_HEADER_TIMESTAMP (map.data) = 0;
129   GST_RTP_HEADER_SSRC (map.data) = 0;
130   gst_memory_unmap (mem, &map);
131
132   gst_buffer_append_memory (buffer, mem);
133 }
134
135 /**
136  * gst_rtp_buffer_new_take_data:
137  * @data: (array length=len) (transfer full) (element-type guint8):
138  *   data for the new buffer
139  * @len: the length of data
140  *
141  * Create a new buffer and set the data and size of the buffer to @data and @len
142  * respectively. @data will be freed when the buffer is unreffed, so this
143  * function transfers ownership of @data to the new buffer.
144  *
145  * Returns: A newly allocated buffer with @data and of size @len.
146  */
147 GstBuffer *
148 gst_rtp_buffer_new_take_data (gpointer data, gsize len)
149 {
150   g_return_val_if_fail (data != NULL, NULL);
151   g_return_val_if_fail (len > 0, NULL);
152
153   return gst_buffer_new_wrapped (data, len);
154 }
155
156 /**
157  * gst_rtp_buffer_new_copy_data:
158  * @data: (array length=len) (element-type guint8): data for the new
159  *   buffer
160  * @len: the length of data
161  *
162  * Create a new buffer and set the data to a copy of @len
163  * bytes of @data and the size to @len. The data will be freed when the buffer
164  * is freed.
165  *
166  * Returns: A newly allocated buffer with a copy of @data and of size @len.
167  */
168 GstBuffer *
169 gst_rtp_buffer_new_copy_data (gpointer data, gsize len)
170 {
171   return gst_rtp_buffer_new_take_data (g_memdup (data, len), len);
172 }
173
174 /**
175  * gst_rtp_buffer_new_allocate:
176  * @payload_len: the length of the payload
177  * @pad_len: the amount of padding
178  * @csrc_count: the number of CSRC entries
179  *
180  * Allocate a new #GstBuffer with enough data to hold an RTP packet with
181  * @csrc_count CSRCs, a payload length of @payload_len and padding of @pad_len.
182  * All other RTP header fields will be set to 0/FALSE.
183  *
184  * Returns: A newly allocated buffer that can hold an RTP packet with given
185  * parameters.
186  */
187 GstBuffer *
188 gst_rtp_buffer_new_allocate (guint payload_len, guint8 pad_len,
189     guint8 csrc_count)
190 {
191   GstBuffer *result;
192
193   g_return_val_if_fail (csrc_count <= 15, NULL);
194
195   result = gst_buffer_new ();
196   gst_rtp_buffer_allocate_data (result, payload_len, pad_len, csrc_count);
197
198   return result;
199 }
200
201 /**
202  * gst_rtp_buffer_new_allocate_len:
203  * @packet_len: the total length of the packet
204  * @pad_len: the amount of padding
205  * @csrc_count: the number of CSRC entries
206  *
207  * Create a new #GstBuffer that can hold an RTP packet that is exactly
208  * @packet_len long. The length of the payload depends on @pad_len and
209  * @csrc_count and can be calculated with gst_rtp_buffer_calc_payload_len().
210  * All RTP header fields will be set to 0/FALSE.
211  *
212  * Returns: A newly allocated buffer that can hold an RTP packet of @packet_len.
213  */
214 GstBuffer *
215 gst_rtp_buffer_new_allocate_len (guint packet_len, guint8 pad_len,
216     guint8 csrc_count)
217 {
218   guint len;
219
220   g_return_val_if_fail (csrc_count <= 15, NULL);
221
222   len = gst_rtp_buffer_calc_payload_len (packet_len, pad_len, csrc_count);
223
224   return gst_rtp_buffer_new_allocate (len, pad_len, csrc_count);
225 }
226
227 /**
228  * gst_rtp_buffer_calc_header_len:
229  * @csrc_count: the number of CSRC entries
230  *
231  * Calculate the header length of an RTP packet with @csrc_count CSRC entries.
232  * An RTP packet can have at most 15 CSRC entries.
233  *
234  * Returns: The length of an RTP header with @csrc_count CSRC entries.
235  */
236 guint
237 gst_rtp_buffer_calc_header_len (guint8 csrc_count)
238 {
239   g_return_val_if_fail (csrc_count <= 15, 0);
240
241   return GST_RTP_HEADER_LEN + (csrc_count * sizeof (guint32));
242 }
243
244 /**
245  * gst_rtp_buffer_calc_packet_len:
246  * @payload_len: the length of the payload
247  * @pad_len: the amount of padding
248  * @csrc_count: the number of CSRC entries
249  *
250  * Calculate the total length of an RTP packet with a payload size of @payload_len,
251  * a padding of @pad_len and a @csrc_count CSRC entries.
252  *
253  * Returns: The total length of an RTP header with given parameters.
254  */
255 guint
256 gst_rtp_buffer_calc_packet_len (guint payload_len, guint8 pad_len,
257     guint8 csrc_count)
258 {
259   g_return_val_if_fail (csrc_count <= 15, 0);
260
261   return payload_len + GST_RTP_HEADER_LEN + (csrc_count * sizeof (guint32))
262       + pad_len;
263 }
264
265 /**
266  * gst_rtp_buffer_calc_payload_len:
267  * @packet_len: the length of the total RTP packet
268  * @pad_len: the amount of padding
269  * @csrc_count: the number of CSRC entries
270  *
271  * Calculate the length of the payload of an RTP packet with size @packet_len,
272  * a padding of @pad_len and a @csrc_count CSRC entries.
273  *
274  * Returns: The length of the payload of an RTP packet  with given parameters.
275  */
276 guint
277 gst_rtp_buffer_calc_payload_len (guint packet_len, guint8 pad_len,
278     guint8 csrc_count)
279 {
280   g_return_val_if_fail (csrc_count <= 15, 0);
281
282   return packet_len - GST_RTP_HEADER_LEN - (csrc_count * sizeof (guint32))
283       - pad_len;
284 }
285
286 /**
287  * gst_rtp_buffer_map:
288  * @buffer: a #GstBuffer
289  * @flags: #GstMapFlags
290  * @rtp: (out): a #GstRTPBuffer
291  *
292  * Map the contents of @buffer into @rtp.
293  *
294  * Returns: %TRUE if @buffer could be mapped.
295  */
296 gboolean
297 gst_rtp_buffer_map (GstBuffer * buffer, GstMapFlags flags, GstRTPBuffer * rtp)
298 {
299   guint8 padding;
300   guint8 csrc_count;
301   guint header_len;
302   guint8 version;
303   guint8 *data;
304   guint size;
305   gsize bufsize, skip;
306   guint idx, length;
307
308   g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
309   g_return_val_if_fail (rtp != NULL, FALSE);
310   g_return_val_if_fail (rtp->buffer == NULL, FALSE);
311
312   /* map first memory, this should be the header */
313   if (!gst_buffer_map_range (buffer, 0, 1, &rtp->map[0], flags))
314     goto map_failed;
315
316   data = rtp->data[0] = rtp->map[0].data;
317   size = rtp->map[0].size;
318
319   header_len = GST_RTP_HEADER_LEN;
320   if (G_UNLIKELY (size < header_len))
321     goto wrong_length;
322
323   /* check version */
324   version = (data[0] & 0xc0);
325   if (G_UNLIKELY (version != (GST_RTP_VERSION << 6)))
326     goto wrong_version;
327
328   /* calc header length with csrc */
329   csrc_count = (data[0] & 0x0f);
330   header_len += csrc_count * sizeof (guint32);
331
332   rtp->size[0] = header_len;
333
334   bufsize = gst_buffer_get_size (buffer);
335
336   /* calc extension length when present. */
337   if (data[0] & 0x10) {
338     guint8 *extdata;
339     guint16 extlen;
340
341     /* find memory for the extension bits */
342     if (!gst_buffer_find_memory (buffer, header_len, 4, &idx, &length, &skip))
343       goto wrong_length;
344
345     if (!gst_buffer_map_range (buffer, idx, length, &rtp->map[1], flags))
346       goto map_failed;
347
348     extdata = rtp->data[1] = rtp->map[1].data + skip;
349     /* skip id */
350     extdata += 2;
351     /* read length as the number of 32 bits words */
352     extlen = GST_READ_UINT16_BE (extdata);
353
354     rtp->size[1] = extlen * sizeof (guint32);
355
356     header_len += rtp->size[1];
357   } else {
358     rtp->data[1] = NULL;
359     rtp->size[1] = 0;
360   }
361
362   /* check for padding */
363   if (data[0] & 0x20) {
364     /* find memory for the padding bits */
365     if (!gst_buffer_find_memory (buffer, bufsize - 1, 1, &idx, &length, &skip))
366       goto wrong_length;
367
368     if (!gst_buffer_map_range (buffer, idx, length, &rtp->map[3], flags))
369       goto map_failed;
370
371     padding = rtp->map[3].data[skip];
372     if (skip + 1 < padding)
373       goto wrong_length;
374
375     rtp->data[3] = rtp->map[3].data + skip + 1 - padding;
376     rtp->size[3] = padding;
377   } else {
378     rtp->data[3] = NULL;
379     rtp->size[3] = 0;
380     padding = 0;
381   }
382
383   /* check if padding and header not bigger than packet length */
384   if (G_UNLIKELY (bufsize < padding + header_len))
385     goto wrong_padding;
386
387   rtp->buffer = buffer;
388   /* we have not yet mapped the payload */
389   rtp->data[2] = NULL;
390   rtp->size[2] = 0;
391   rtp->state = 0;
392   rtp->n_map = 1;
393
394   return TRUE;
395
396   /* ERRORS */
397 map_failed:
398   {
399     GST_ERROR ("failed to map memory");
400     return FALSE;
401   }
402 wrong_length:
403   {
404     GST_DEBUG ("length check failed");
405     goto dump_packet;
406   }
407 wrong_version:
408   {
409     GST_DEBUG ("version check failed (%d != %d)", version, GST_RTP_VERSION);
410     goto dump_packet;
411   }
412 wrong_padding:
413   {
414     GST_DEBUG ("padding check failed (%" G_GSIZE_FORMAT " - %d < %d)", bufsize,
415         header_len, padding);
416     goto dump_packet;
417   }
418 dump_packet:
419   {
420     GST_MEMDUMP ("buffer", data, size);
421     return FALSE;
422   }
423 }
424
425 /**
426  * gst_rtp_buffer_unmap:
427  * @rtp: a #GstRTPBuffer
428  *
429  * Unmap @rtp previously mapped with gst_rtp_buffer_map().
430  */
431 void
432 gst_rtp_buffer_unmap (GstRTPBuffer * rtp)
433 {
434   gint i;
435
436   g_return_if_fail (rtp != NULL);
437   g_return_if_fail (rtp->buffer != NULL);
438
439   for (i = 0; i < 4; i++) {
440     if (rtp->data[i])
441       gst_buffer_unmap (rtp->buffer, &rtp->map[i]);
442   }
443   rtp->buffer = NULL;
444   rtp->n_map = 0;
445 }
446
447
448 /**
449  * gst_rtp_buffer_set_packet_len:
450  * @rtp: the RTP packet
451  * @len: the new packet length
452  *
453  * Set the total @rtp size to @len. The data in the buffer will be made
454  * larger if needed. Any padding will be removed from the packet.
455  */
456 void
457 gst_rtp_buffer_set_packet_len (GstRTPBuffer * rtp, guint len)
458 {
459   guint8 *data;
460
461   data = rtp->data[0];
462
463   /* FIXME */
464
465   if (rtp->map[0].maxsize <= len) {
466     /* FIXME, realloc bigger space */
467     g_warning ("not implemented");
468   }
469
470   gst_buffer_set_size (rtp->buffer, len);
471   rtp->map[0].size = len;
472
473   /* remove any padding */
474   GST_RTP_HEADER_PADDING (data) = FALSE;
475 }
476
477 /**
478  * gst_rtp_buffer_get_packet_len:
479  * @rtp: the RTP packet
480  *
481  * Return the total length of the packet in @buffer.
482  *
483  * Returns: The total length of the packet in @buffer.
484  */
485 guint
486 gst_rtp_buffer_get_packet_len (GstRTPBuffer * rtp)
487 {
488   return gst_buffer_get_size (rtp->buffer);
489 }
490
491 /**
492  * gst_rtp_buffer_get_header_len:
493  * @rtp: the RTP packet
494  *
495  * Return the total length of the header in @buffer. This include the length of
496  * the fixed header, the CSRC list and the extension header.
497  *
498  * Returns: The total length of the header in @buffer.
499  */
500 guint
501 gst_rtp_buffer_get_header_len (GstRTPBuffer * rtp)
502 {
503   return rtp->size[0] + rtp->size[1];
504 }
505
506 /**
507  * gst_rtp_buffer_get_version:
508  * @rtp: the RTP packet
509  *
510  * Get the version number of the RTP packet in @buffer.
511  *
512  * Returns: The version of @buffer.
513  */
514 guint8
515 gst_rtp_buffer_get_version (GstRTPBuffer * rtp)
516 {
517   return GST_RTP_HEADER_VERSION (rtp->data[0]);
518 }
519
520 /**
521  * gst_rtp_buffer_set_version:
522  * @rtp: the RTP packet
523  * @version: the new version
524  *
525  * Set the version of the RTP packet in @buffer to @version.
526  */
527 void
528 gst_rtp_buffer_set_version (GstRTPBuffer * rtp, guint8 version)
529 {
530   g_return_if_fail (version < 0x04);
531
532   GST_RTP_HEADER_VERSION (rtp->data[0]) = version;
533 }
534
535 /**
536  * gst_rtp_buffer_get_padding:
537  * @rtp: the RTP packet
538  *
539  * Check if the padding bit is set on the RTP packet in @buffer.
540  *
541  * Returns: TRUE if @buffer has the padding bit set.
542  */
543 gboolean
544 gst_rtp_buffer_get_padding (GstRTPBuffer * rtp)
545 {
546   return GST_RTP_HEADER_PADDING (rtp->data[0]);
547 }
548
549 /**
550  * gst_rtp_buffer_set_padding:
551  * @rtp: the buffer
552  * @padding: the new padding
553  *
554  * Set the padding bit on the RTP packet in @buffer to @padding.
555  */
556 void
557 gst_rtp_buffer_set_padding (GstRTPBuffer * rtp, gboolean padding)
558 {
559   GST_RTP_HEADER_PADDING (rtp->data[0]) = padding;
560 }
561
562 /**
563  * gst_rtp_buffer_pad_to:
564  * @rtp: the RTP packet
565  * @len: the new amount of padding
566  *
567  * Set the amount of padding in the RTP packet in @buffer to
568  * @len. If @len is 0, the padding is removed.
569  *
570  * NOTE: This function does not work correctly.
571  */
572 void
573 gst_rtp_buffer_pad_to (GstRTPBuffer * rtp, guint len)
574 {
575   guint8 *data;
576
577   data = rtp->data[0];
578
579   if (len > 0)
580     GST_RTP_HEADER_PADDING (data) = TRUE;
581   else
582     GST_RTP_HEADER_PADDING (data) = FALSE;
583
584   /* FIXME, set the padding byte at the end of the payload data */
585 }
586
587 /**
588  * gst_rtp_buffer_get_extension:
589  * @rtp: the RTP packet
590  *
591  * Check if the extension bit is set on the RTP packet in @buffer.
592  * 
593  * Returns: TRUE if @buffer has the extension bit set.
594  */
595 gboolean
596 gst_rtp_buffer_get_extension (GstRTPBuffer * rtp)
597 {
598   return GST_RTP_HEADER_EXTENSION (rtp->data[0]);
599 }
600
601 /**
602  * gst_rtp_buffer_set_extension:
603  * @rtp: the RTP packet
604  * @extension: the new extension
605  *
606  * Set the extension bit on the RTP packet in @buffer to @extension.
607  */
608 void
609 gst_rtp_buffer_set_extension (GstRTPBuffer * rtp, gboolean extension)
610 {
611   GST_RTP_HEADER_EXTENSION (rtp->data[0]) = extension;
612 }
613
614 /**
615  * gst_rtp_buffer_get_extension_data:
616  * @rtp: the RTP packet
617  * @bits: (out): location for result bits
618  * @data: (out) (array) (element-type guint8) (transfer none): location for data
619  * @wordlen: (out): location for length of @data in 32 bits words
620  *
621  * Get the extension data. @bits will contain the extension 16 bits of custom
622  * data. @data will point to the data in the extension and @wordlen will contain
623  * the length of @data in 32 bits words.
624  *
625  * If @buffer did not contain an extension, this function will return %FALSE
626  * with @bits, @data and @wordlen unchanged.
627  * 
628  * Returns: TRUE if @buffer had the extension bit set.
629  */
630 gboolean
631 gst_rtp_buffer_get_extension_data (GstRTPBuffer * rtp, guint16 * bits,
632     gpointer * data, guint * wordlen)
633 {
634   guint8 *pdata;
635
636   /* move to the extension */
637   pdata = rtp->data[1];
638   if (!pdata)
639     return FALSE;
640
641   if (bits)
642     *bits = GST_READ_UINT16_BE (pdata);
643   if (wordlen)
644     *wordlen = GST_READ_UINT16_BE (pdata + 2);
645   pdata += 4;
646   if (data)
647     *data = (gpointer *) pdata;
648
649   return TRUE;
650 }
651
652 /**
653  * gst_rtp_buffer_set_extension_data:
654  * @rtp: the RTP packet
655  * @bits: the bits specific for the extension
656  * @length: the length that counts the number of 32-bit words in
657  * the extension, excluding the extension header ( therefore zero is a valid length)
658  *
659  * Set the extension bit of the rtp buffer and fill in the @bits and @length of the
660  * extension header. It will refuse to set the extension data if the buffer is not
661  * large enough.
662  *
663  * Returns: True if done.
664  */
665 gboolean
666 gst_rtp_buffer_set_extension_data (GstRTPBuffer * rtp, guint16 bits,
667     guint16 length)
668 {
669   guint32 min_size = 0;
670   guint8 *data;
671
672   /* FIXME, we should allocate and map the extension data */
673   data = rtp->data[0];
674
675   /* check if the buffer is big enough to hold the extension */
676   min_size = 4 + length * sizeof (guint32);
677   if (G_UNLIKELY (min_size > rtp->size[1]))
678     goto too_small;
679
680   /* now we can set the extension bit */
681   GST_RTP_HEADER_EXTENSION (data) = TRUE;
682
683   data = rtp->data[1];
684   GST_WRITE_UINT16_BE (data, bits);
685   GST_WRITE_UINT16_BE (data + 2, length);
686
687   return TRUE;
688
689   /* ERRORS */
690 too_small:
691   {
692     g_warning
693         ("rtp buffer too small: need more than %d bytes but only have %"
694         G_GSIZE_FORMAT " bytes", min_size, rtp->size[1]);
695     return FALSE;
696   }
697 }
698
699 /**
700  * gst_rtp_buffer_get_ssrc:
701  * @rtp: the RTP packet
702  *
703  * Get the SSRC of the RTP packet in @buffer.
704  * 
705  * Returns: the SSRC of @buffer in host order.
706  */
707 guint32
708 gst_rtp_buffer_get_ssrc (GstRTPBuffer * rtp)
709 {
710   return g_ntohl (GST_RTP_HEADER_SSRC (rtp->data[0]));
711 }
712
713 /**
714  * gst_rtp_buffer_set_ssrc:
715  * @rtp: the RTP packet
716  * @ssrc: the new SSRC
717  *
718  * Set the SSRC on the RTP packet in @buffer to @ssrc.
719  */
720 void
721 gst_rtp_buffer_set_ssrc (GstRTPBuffer * rtp, guint32 ssrc)
722 {
723   GST_RTP_HEADER_SSRC (rtp->data[0]) = g_htonl (ssrc);
724 }
725
726 /**
727  * gst_rtp_buffer_get_csrc_count:
728  * @rtp: the RTP packet
729  *
730  * Get the CSRC count of the RTP packet in @buffer.
731  * 
732  * Returns: the CSRC count of @buffer.
733  */
734 guint8
735 gst_rtp_buffer_get_csrc_count (GstRTPBuffer * rtp)
736 {
737   return GST_RTP_HEADER_CSRC_COUNT (rtp->data[0]);
738 }
739
740 /**
741  * gst_rtp_buffer_get_csrc:
742  * @rtp: the RTP packet
743  * @idx: the index of the CSRC to get
744  *
745  * Get the CSRC at index @idx in @buffer.
746  * 
747  * Returns: the CSRC at index @idx in host order.
748  */
749 guint32
750 gst_rtp_buffer_get_csrc (GstRTPBuffer * rtp, guint8 idx)
751 {
752   guint8 *data;
753
754   data = rtp->data[0];
755
756   g_return_val_if_fail (idx < GST_RTP_HEADER_CSRC_COUNT (data), 0);
757
758   return GST_READ_UINT32_BE (GST_RTP_HEADER_CSRC_LIST_OFFSET (data, idx));
759 }
760
761 /**
762  * gst_rtp_buffer_set_csrc:
763  * @rtp: the RTP packet
764  * @idx: the CSRC index to set
765  * @csrc: the CSRC in host order to set at @idx
766  *
767  * Modify the CSRC at index @idx in @buffer to @csrc.
768  */
769 void
770 gst_rtp_buffer_set_csrc (GstRTPBuffer * rtp, guint8 idx, guint32 csrc)
771 {
772   guint8 *data;
773
774   data = rtp->data[0];
775
776   g_return_if_fail (idx < GST_RTP_HEADER_CSRC_COUNT (data));
777
778   GST_WRITE_UINT32_BE (GST_RTP_HEADER_CSRC_LIST_OFFSET (data, idx), csrc);
779 }
780
781 /**
782  * gst_rtp_buffer_get_marker:
783  * @rtp: the RTP packet
784  *
785  * Check if the marker bit is set on the RTP packet in @buffer.
786  *
787  * Returns: TRUE if @buffer has the marker bit set.
788  */
789 gboolean
790 gst_rtp_buffer_get_marker (GstRTPBuffer * rtp)
791 {
792   return GST_RTP_HEADER_MARKER (rtp->data[0]);
793 }
794
795 /**
796  * gst_rtp_buffer_set_marker:
797  * @rtp: the RTP packet
798  * @marker: the new marker
799  *
800  * Set the marker bit on the RTP packet in @buffer to @marker.
801  */
802 void
803 gst_rtp_buffer_set_marker (GstRTPBuffer * rtp, gboolean marker)
804 {
805   GST_RTP_HEADER_MARKER (rtp->data[0]) = marker;
806 }
807
808 /**
809  * gst_rtp_buffer_get_payload_type:
810  * @rtp: the RTP packet
811  *
812  * Get the payload type of the RTP packet in @buffer.
813  *
814  * Returns: The payload type.
815  */
816 guint8
817 gst_rtp_buffer_get_payload_type (GstRTPBuffer * rtp)
818 {
819   return GST_RTP_HEADER_PAYLOAD_TYPE (rtp->data[0]);
820 }
821
822 /**
823  * gst_rtp_buffer_set_payload_type:
824  * @rtp: the RTP packet
825  * @payload_type: the new type
826  *
827  * Set the payload type of the RTP packet in @buffer to @payload_type.
828  */
829 void
830 gst_rtp_buffer_set_payload_type (GstRTPBuffer * rtp, guint8 payload_type)
831 {
832   g_return_if_fail (payload_type < 0x80);
833
834   GST_RTP_HEADER_PAYLOAD_TYPE (rtp->data[0]) = payload_type;
835 }
836
837 /**
838  * gst_rtp_buffer_get_seq:
839  * @rtp: the RTP packet
840  *
841  * Get the sequence number of the RTP packet in @buffer.
842  *
843  * Returns: The sequence number in host order.
844  */
845 guint16
846 gst_rtp_buffer_get_seq (GstRTPBuffer * rtp)
847 {
848   return g_ntohs (GST_RTP_HEADER_SEQ (rtp->data[0]));
849 }
850
851 /**
852  * gst_rtp_buffer_set_seq:
853  * @rtp: the RTP packet
854  * @seq: the new sequence number
855  *
856  * Set the sequence number of the RTP packet in @buffer to @seq.
857  */
858 void
859 gst_rtp_buffer_set_seq (GstRTPBuffer * rtp, guint16 seq)
860 {
861   GST_RTP_HEADER_SEQ (rtp->data[0]) = g_htons (seq);
862 }
863
864 /**
865  * gst_rtp_buffer_get_timestamp:
866  * @rtp: the RTP packet
867  *
868  * Get the timestamp of the RTP packet in @buffer.
869  *
870  * Returns: The timestamp in host order.
871  */
872 guint32
873 gst_rtp_buffer_get_timestamp (GstRTPBuffer * rtp)
874 {
875   return g_ntohl (GST_RTP_HEADER_TIMESTAMP (rtp->data[0]));
876 }
877
878 /**
879  * gst_rtp_buffer_set_timestamp:
880  * @rtp: the RTP packet
881  * @timestamp: the new timestamp
882  *
883  * Set the timestamp of the RTP packet in @buffer to @timestamp.
884  */
885 void
886 gst_rtp_buffer_set_timestamp (GstRTPBuffer * rtp, guint32 timestamp)
887 {
888   GST_RTP_HEADER_TIMESTAMP (rtp->data[0]) = g_htonl (timestamp);
889 }
890
891
892 /**
893  * gst_rtp_buffer_get_payload_subbuffer:
894  * @rtp: the RTP packet
895  * @offset: the offset in the payload
896  * @len: the length in the payload
897  *
898  * Create a subbuffer of the payload of the RTP packet in @buffer. @offset bytes
899  * are skipped in the payload and the subbuffer will be of size @len.
900  * If @len is -1 the total payload starting from @offset if subbuffered.
901  *
902  * Returns: A new buffer with the specified data of the payload.
903  */
904 GstBuffer *
905 gst_rtp_buffer_get_payload_subbuffer (GstRTPBuffer * rtp, guint offset,
906     guint len)
907 {
908   guint poffset, plen;
909
910   plen = gst_rtp_buffer_get_payload_len (rtp);
911   /* we can't go past the length */
912   if (G_UNLIKELY (offset >= plen))
913     goto wrong_offset;
914
915   /* apply offset */
916   poffset = gst_rtp_buffer_get_header_len (rtp) + offset;
917   plen -= offset;
918
919   /* see if we need to shrink the buffer based on @len */
920   if (len != -1 && len < plen)
921     plen = len;
922
923   return gst_buffer_copy_region (rtp->buffer, GST_BUFFER_COPY_ALL, poffset,
924       plen);
925
926   /* ERRORS */
927 wrong_offset:
928   {
929     g_warning ("offset=%u should be less then plen=%u", offset, plen);
930     return NULL;
931   }
932 }
933
934 /**
935  * gst_rtp_buffer_get_payload_buffer:
936  * @rtp: the RTP packet
937  *
938  * Create a buffer of the payload of the RTP packet in @buffer. This function
939  * will internally create a subbuffer of @buffer so that a memcpy can be
940  * avoided.
941  *
942  * Returns: A new buffer with the data of the payload.
943  */
944 GstBuffer *
945 gst_rtp_buffer_get_payload_buffer (GstRTPBuffer * rtp)
946 {
947   return gst_rtp_buffer_get_payload_subbuffer (rtp, 0, -1);
948 }
949
950 /**
951  * gst_rtp_buffer_get_payload_len:
952  * @rtp: the RTP packet
953  *
954  * Get the length of the payload of the RTP packet in @buffer.
955  *
956  * Returns: The length of the payload in @buffer.
957  */
958 guint
959 gst_rtp_buffer_get_payload_len (GstRTPBuffer * rtp)
960 {
961   return gst_buffer_get_size (rtp->buffer) - gst_rtp_buffer_get_header_len (rtp)
962       - rtp->size[3];
963 }
964
965 /**
966  * gst_rtp_buffer_get_payload:
967  * @rtp: the RTP packet
968  *
969  * Get a pointer to the payload data in @buffer. This pointer is valid as long
970  * as a reference to @buffer is held.
971  *
972  * Returns: (array) (element-type guint8) (transfer none): A pointer
973  * to the payload data in @buffer.
974  */
975 gpointer
976 gst_rtp_buffer_get_payload (GstRTPBuffer * rtp)
977 {
978   guint hlen, plen;
979   guint idx, length;
980   gsize skip;
981
982   if (rtp->data[2])
983     return rtp->data[2];
984
985   hlen = gst_rtp_buffer_get_header_len (rtp);
986   plen = gst_buffer_get_size (rtp->buffer) - hlen - rtp->size[3];
987
988   if (!gst_buffer_find_memory (rtp->buffer, hlen, plen, &idx, &length, &skip))
989     return NULL;
990
991   if (!gst_buffer_map_range (rtp->buffer, idx, length, &rtp->map[2],
992           rtp->map[0].flags))
993     return NULL;
994
995   rtp->data[2] = rtp->map[2].data + skip;
996   rtp->size[2] = plen;
997
998   return rtp->data[2];
999 }
1000
1001 /**
1002  * gst_rtp_buffer_default_clock_rate:
1003  * @payload_type: the static payload type
1004  *
1005  * Get the default clock-rate for the static payload type @payload_type.
1006  *
1007  * Returns: the default clock rate or -1 if the payload type is not static or
1008  * the clock-rate is undefined.
1009  */
1010 guint32
1011 gst_rtp_buffer_default_clock_rate (guint8 payload_type)
1012 {
1013   const GstRTPPayloadInfo *info;
1014   guint32 res;
1015
1016   info = gst_rtp_payload_info_for_pt (payload_type);
1017   if (!info)
1018     return -1;
1019
1020   res = info->clock_rate;
1021   /* 0 means unknown so we have to return -1 from this function */
1022   if (res == 0)
1023     res = -1;
1024
1025   return res;
1026 }
1027
1028 /**
1029  * gst_rtp_buffer_compare_seqnum:
1030  * @seqnum1: a sequence number
1031  * @seqnum2: a sequence number
1032  *
1033  * Compare two sequence numbers, taking care of wraparounds. This function
1034  * returns the difference between @seqnum1 and @seqnum2.
1035  *
1036  * Returns: a negative value if @seqnum1 is bigger than @seqnum2, 0 if they
1037  * are equal or a positive value if @seqnum1 is smaller than @segnum2.
1038  */
1039 gint
1040 gst_rtp_buffer_compare_seqnum (guint16 seqnum1, guint16 seqnum2)
1041 {
1042   return (gint16) (seqnum2 - seqnum1);
1043 }
1044
1045 /**
1046  * gst_rtp_buffer_ext_timestamp:
1047  * @exttimestamp: a previous extended timestamp
1048  * @timestamp: a new timestamp
1049  *
1050  * Update the @exttimestamp field with @timestamp. For the first call of the
1051  * method, @exttimestamp should point to a location with a value of -1.
1052  *
1053  * This function makes sure that the returned value is a constantly increasing
1054  * value even in the case where there is a timestamp wraparound.
1055  *
1056  * Returns: The extended timestamp of @timestamp.
1057  */
1058 guint64
1059 gst_rtp_buffer_ext_timestamp (guint64 * exttimestamp, guint32 timestamp)
1060 {
1061   guint64 result, diff, ext;
1062
1063   g_return_val_if_fail (exttimestamp != NULL, -1);
1064
1065   ext = *exttimestamp;
1066
1067   if (ext == -1) {
1068     result = timestamp;
1069   } else {
1070     /* pick wraparound counter from previous timestamp and add to new timestamp */
1071     result = timestamp + (ext & ~(G_GINT64_CONSTANT (0xffffffff)));
1072
1073     /* check for timestamp wraparound */
1074     if (result < ext)
1075       diff = ext - result;
1076     else
1077       diff = result - ext;
1078
1079     if (diff > G_MAXINT32) {
1080       /* timestamp went backwards more than allowed, we wrap around and get
1081        * updated extended timestamp. */
1082       result += (G_GINT64_CONSTANT (1) << 32);
1083     }
1084   }
1085   *exttimestamp = result;
1086
1087   return result;
1088 }
1089
1090 /**
1091  * gst_rtp_buffer_get_extension_onebyte_header:
1092  * @rtp: the RTP packet
1093  * @id: The ID of the header extension to be read (between 1 and 14).
1094  * @nth: Read the nth extension packet with the requested ID
1095  * @data: (out) (array length=size) (element-type guint8) (transfer none):
1096  *   location for data
1097  * @size: (out): the size of the data in bytes
1098  *
1099  * Parses RFC 5285 style header extensions with a one byte header. It will
1100  * return the nth extension with the requested id.
1101  *
1102  * Returns: TRUE if @buffer had the requested header extension
1103  */
1104
1105 gboolean
1106 gst_rtp_buffer_get_extension_onebyte_header (GstRTPBuffer * rtp, guint8 id,
1107     guint nth, gpointer * data, guint * size)
1108 {
1109   guint16 bits;
1110   guint8 *pdata;
1111   guint wordlen;
1112   gulong offset = 0;
1113   guint count = 0;
1114
1115   g_return_val_if_fail (id > 0 && id < 15, FALSE);
1116
1117   if (!gst_rtp_buffer_get_extension_data (rtp, &bits, (gpointer) & pdata,
1118           &wordlen))
1119     return FALSE;
1120
1121   if (bits != 0xBEDE)
1122     return FALSE;
1123
1124   for (;;) {
1125     guint8 read_id, read_len;
1126
1127     if (offset + 1 >= wordlen * 4)
1128       break;
1129
1130     read_id = GST_READ_UINT8 (pdata + offset) >> 4;
1131     read_len = (GST_READ_UINT8 (pdata + offset) & 0x0F) + 1;
1132     offset += 1;
1133
1134     /* ID 0 means its padding, skip */
1135     if (read_id == 0)
1136       continue;
1137
1138     /* ID 15 is special and means we should stop parsing */
1139     if (read_id == 15)
1140       break;
1141
1142     /* Ignore extension headers where the size does not fit */
1143     if (offset + read_len > wordlen * 4)
1144       break;
1145
1146     /* If we have the right one */
1147     if (id == read_id) {
1148       if (nth == count) {
1149         if (data)
1150           *data = pdata + offset;
1151         if (size)
1152           *size = read_len;
1153
1154         return TRUE;
1155       }
1156
1157       count++;
1158     }
1159     offset += read_len;
1160
1161     if (offset >= wordlen * 4)
1162       break;
1163   }
1164
1165   return FALSE;
1166 }
1167
1168 /**
1169  * gst_rtp_buffer_get_extension_twobytes_header:
1170  * @rtp: the RTP packet
1171  * @appbits: (out): Application specific bits
1172  * @id: The ID of the header extension to be read (between 1 and 14).
1173  * @nth: Read the nth extension packet with the requested ID
1174  * @data: (out) (array length=size) (element-type guint8) (transfer none):
1175  *   location for data
1176  * @size: (out): the size of the data in bytes
1177  *
1178  * Parses RFC 5285 style header extensions with a two bytes header. It will
1179  * return the nth extension with the requested id.
1180  *
1181  * Returns: TRUE if @buffer had the requested header extension
1182  */
1183
1184 gboolean
1185 gst_rtp_buffer_get_extension_twobytes_header (GstRTPBuffer * rtp,
1186     guint8 * appbits, guint8 id, guint nth, gpointer * data, guint * size)
1187 {
1188   guint16 bits;
1189   guint8 *pdata = NULL;
1190   guint wordlen;
1191   guint bytelen;
1192   gulong offset = 0;
1193   guint count = 0;
1194
1195   if (!gst_rtp_buffer_get_extension_data (rtp, &bits, (gpointer *) & pdata,
1196           &wordlen))
1197     return FALSE;
1198
1199   if (bits >> 4 != 0x100)
1200     return FALSE;
1201
1202   bytelen = wordlen * 4;
1203
1204   for (;;) {
1205     guint8 read_id, read_len;
1206
1207     if (offset + 2 >= bytelen)
1208       break;
1209
1210     read_id = GST_READ_UINT8 (pdata + offset);
1211     offset += 1;
1212
1213     if (read_id == 0)
1214       continue;
1215
1216     read_len = GST_READ_UINT8 (pdata + offset);
1217     offset += 1;
1218
1219     /* Ignore extension headers where the size does not fit */
1220     if (offset + read_len > bytelen)
1221       break;
1222
1223     /* If we have the right one, return it */
1224     if (id == read_id) {
1225       if (nth == count) {
1226         if (data)
1227           *data = pdata + offset;
1228         if (size)
1229           *size = read_len;
1230         if (appbits)
1231           *appbits = bits;
1232
1233         return TRUE;
1234       }
1235
1236       count++;
1237     }
1238     offset += read_len;
1239   }
1240
1241   return FALSE;
1242 }
1243
1244 static guint
1245 get_onebyte_header_end_offset (guint8 * pdata, guint wordlen)
1246 {
1247   guint offset = 0;
1248   guint bytelen = wordlen * 4;
1249   guint paddingcount = 0;
1250
1251   while (offset + 1 < bytelen) {
1252     guint8 read_id, read_len;
1253
1254     read_id = GST_READ_UINT8 (pdata + offset) >> 4;
1255     read_len = (GST_READ_UINT8 (pdata + offset) & 0x0F) + 1;
1256     offset += 1;
1257
1258     /* ID 0 means its padding, skip */
1259     if (read_id == 0) {
1260       paddingcount++;
1261       continue;
1262     }
1263
1264     paddingcount = 0;
1265
1266     /* ID 15 is special and means we should stop parsing */
1267     /* It also means we can't add an extra packet */
1268     if (read_id == 15)
1269       return 0;
1270
1271     /* Ignore extension headers where the size does not fit */
1272     if (offset + read_len > bytelen)
1273       return 0;
1274
1275     offset += read_len;
1276   }
1277
1278   return offset - paddingcount;
1279 }
1280
1281 /**
1282  * gst_rtp_buffer_add_extension_onebyte_header:
1283  * @rtp: the RTP packet
1284  * @id: The ID of the header extension (between 1 and 14).
1285  * @data: (array length=size) (element-type guint8): location for data
1286  * @size: the size of the data in bytes
1287  *
1288  * Adds a RFC 5285 header extension with a one byte header to the end of the
1289  * RTP header. If there is already a RFC 5285 header extension with a one byte
1290  * header, the new extension will be appended.
1291  * It will not work if there is already a header extension that does not follow
1292  * the mecanism described in RFC 5285 or if there is a header extension with
1293  * a two bytes header as described in RFC 5285. In that case, use
1294  * gst_rtp_buffer_add_extension_twobytes_header()
1295  *
1296  * Returns: %TRUE if header extension could be added
1297  */
1298
1299 gboolean
1300 gst_rtp_buffer_add_extension_onebyte_header (GstRTPBuffer * rtp, guint8 id,
1301     gpointer data, guint size)
1302 {
1303   guint16 bits;
1304   guint8 *pdata = 0;
1305   guint wordlen;
1306   gboolean has_bit;
1307
1308   g_return_val_if_fail (id > 0 && id < 15, FALSE);
1309   g_return_val_if_fail (size >= 1 && size <= 16, FALSE);
1310   g_return_val_if_fail (gst_buffer_is_writable (rtp->buffer), FALSE);
1311
1312   has_bit = gst_rtp_buffer_get_extension_data (rtp, &bits,
1313       (gpointer) & pdata, &wordlen);
1314
1315   if (has_bit) {
1316     gulong offset = 0;
1317     guint8 *nextext;
1318     guint extlen;
1319
1320     if (bits != 0xBEDE)
1321       return FALSE;
1322
1323     offset = get_onebyte_header_end_offset (pdata, wordlen);
1324     if (offset == 0)
1325       return FALSE;
1326
1327     nextext = pdata + offset;
1328     offset = nextext - rtp->map[0].data;
1329
1330     /* Don't add extra header if there isn't enough space */
1331     if (rtp->map[0].size < offset + size + 1)
1332       return FALSE;
1333
1334     nextext[0] = (id << 4) | (0x0F & (size - 1));
1335     memcpy (nextext + 1, data, size);
1336
1337     extlen = nextext - pdata + size + 1;
1338     if (extlen % 4) {
1339       wordlen = extlen / 4 + 1;
1340       memset (nextext + size + 1, 0, 4 - extlen % 4);
1341     } else {
1342       wordlen = extlen / 4;
1343     }
1344
1345     gst_rtp_buffer_set_extension_data (rtp, 0xBEDE, wordlen);
1346   } else {
1347     wordlen = (size + 1) / 4 + (((size + 1) % 4) ? 1 : 0);
1348
1349     gst_rtp_buffer_set_extension_data (rtp, 0xBEDE, wordlen);
1350
1351     gst_rtp_buffer_get_extension_data (rtp, &bits,
1352         (gpointer) & pdata, &wordlen);
1353
1354     pdata[0] = (id << 4) | (0x0F & (size - 1));
1355     memcpy (pdata + 1, data, size);
1356
1357     if ((size + 1) % 4)
1358       memset (pdata + size + 1, 0, 4 - ((size + 1) % 4));
1359   }
1360
1361   return TRUE;
1362 }
1363
1364
1365 static guint
1366 get_twobytes_header_end_offset (guint8 * pdata, guint wordlen)
1367 {
1368   guint offset = 0;
1369   guint bytelen = wordlen * 4;
1370   guint paddingcount = 0;
1371
1372   while (offset + 2 < bytelen) {
1373     guint8 read_id, read_len;
1374
1375     read_id = GST_READ_UINT8 (pdata + offset);
1376     offset += 1;
1377
1378     /* ID 0 means its padding, skip */
1379     if (read_id == 0) {
1380       paddingcount++;
1381       continue;
1382     }
1383
1384     paddingcount = 0;
1385
1386     read_len = GST_READ_UINT8 (pdata + offset);
1387     offset += 1;
1388
1389     /* Ignore extension headers where the size does not fit */
1390     if (offset + read_len > bytelen)
1391       return 0;
1392
1393     offset += read_len;
1394   }
1395
1396   return offset - paddingcount;
1397 }
1398
1399 /**
1400  * gst_rtp_buffer_add_extension_twobytes_header:
1401  * @rtp: the RTP packet
1402  * @appbits: Application specific bits
1403  * @id: The ID of the header extension
1404  * @data: (array length=size) (element-type guint8): location for data
1405  * @size: the size of the data in bytes
1406  *
1407  * Adds a RFC 5285 header extension with a two bytes header to the end of the
1408  * RTP header. If there is already a RFC 5285 header extension with a two bytes
1409  * header, the new extension will be appended.
1410  * It will not work if there is already a header extension that does not follow
1411  * the mecanism described in RFC 5285 or if there is a header extension with
1412  * a one byte header as described in RFC 5285. In that case, use
1413  * gst_rtp_buffer_add_extension_onebyte_header()
1414  *
1415  * Returns: %TRUE if header extension could be added
1416  */
1417
1418 gboolean
1419 gst_rtp_buffer_add_extension_twobytes_header (GstRTPBuffer * rtp,
1420     guint8 appbits, guint8 id, gpointer data, guint size)
1421 {
1422   guint16 bits;
1423   guint8 *pdata = 0;
1424   guint wordlen;
1425   gboolean has_bit;
1426
1427   g_return_val_if_fail ((appbits & 0xF0) == 0, FALSE);
1428   g_return_val_if_fail (size < 256, FALSE);
1429   g_return_val_if_fail (gst_buffer_is_writable (rtp->buffer), FALSE);
1430
1431   has_bit = gst_rtp_buffer_get_extension_data (rtp, &bits,
1432       (gpointer) & pdata, &wordlen);
1433
1434   if (has_bit) {
1435     gulong offset = 0;
1436     guint8 *nextext;
1437     guint extlen;
1438
1439     if (bits != ((0x100 << 4) | (appbits & 0x0f)))
1440       return FALSE;
1441
1442     offset = get_twobytes_header_end_offset (pdata, wordlen);
1443
1444     nextext = pdata + offset;
1445
1446     offset = nextext - rtp->map[0].data;
1447
1448     /* Don't add extra header if there isn't enough space */
1449     if (rtp->map[0].size < offset + size + 2)
1450       return FALSE;
1451
1452     nextext[0] = id;
1453     nextext[1] = size;
1454     memcpy (nextext + 2, data, size);
1455
1456     extlen = nextext - pdata + size + 2;
1457     if (extlen % 4) {
1458       wordlen = extlen / 4 + 1;
1459       memset (nextext + size + 2, 0, 4 - extlen % 4);
1460     } else {
1461       wordlen = extlen / 4;
1462     }
1463
1464     gst_rtp_buffer_set_extension_data (rtp, (0x100 << 4) | (appbits & 0x0F),
1465         wordlen);
1466   } else {
1467     wordlen = (size + 2) / 4 + (((size + 2) % 4) ? 1 : 0);
1468
1469     gst_rtp_buffer_set_extension_data (rtp, (0x100 << 4) | (appbits & 0x0F),
1470         wordlen);
1471
1472     gst_rtp_buffer_get_extension_data (rtp, &bits,
1473         (gpointer) & pdata, &wordlen);
1474
1475     pdata[0] = id;
1476     pdata[1] = size;
1477     memcpy (pdata + 2, data, size);
1478     if ((size + 2) % 4)
1479       memset (pdata + size + 2, 0, 4 - ((size + 2) % 4));
1480   }
1481
1482   return TRUE;
1483 }