expand tabs
[platform/upstream/gstreamer.git] / gst-libs / gst / rtp / gstrtpbuffer.c
1 /* GStreamer
2  * Copyright (C) <2005> Philippe Khalaf <burger@speedy.org> 
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include "gstrtpbuffer.h"
21
22 #define GST_RTP_HEADER_LEN 12
23
24 typedef struct _GstRTPHeader
25 {
26 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
27   unsigned int csrc_count:4;    /* CSRC count */
28   unsigned int extension:1;     /* header extension flag */
29   unsigned int padding:1;       /* padding flag */
30   unsigned int version:2;       /* protocol version */
31   unsigned int payload_type:7;  /* payload type */
32   unsigned int marker:1;        /* marker bit */
33 #elif G_BYTE_ORDER == G_BIG_ENDIAN
34   unsigned int version:2;       /* protocol version */
35   unsigned int padding:1;       /* padding flag */
36   unsigned int extension:1;     /* header extension flag */
37   unsigned int csrc_count:4;    /* CSRC count */
38   unsigned int marker:1;        /* marker bit */
39   unsigned int payload_type:7;  /* payload type */
40 #else
41 #error "G_BYTE_ORDER should be big or little endian."
42 #endif
43   guint16 seq;                  /* sequence number */
44   guint32 timestamp;            /* timestamp */
45   guint32 ssrc;                 /* synchronization source */
46   guint32 csrc[1];              /* optional CSRC list */
47 } GstRTPHeader;
48
49 #define GST_RTP_HEADER_VERSION(buf)     (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->version)
50 #define GST_RTP_HEADER_PADDING(buf)     (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->padding)
51 #define GST_RTP_HEADER_EXTENSION(buf)   (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->extension)
52 #define GST_RTP_HEADER_CSRC_COUNT(buf)  (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->csrc_count)
53 #define GST_RTP_HEADER_MARKER(buf)      (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->marker)
54 #define GST_RTP_HEADER_PAYLOAD_TYPE(buf)(((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->payload_type)
55 #define GST_RTP_HEADER_SEQ(buf)         (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->seq)
56 #define GST_RTP_HEADER_TIMESTAMP(buf)   (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->timestamp)
57 #define GST_RTP_HEADER_SSRC(buf)        (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->ssrc)
58 #define GST_RTP_HEADER_CSRC(buf,i)      (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->csrc[i])
59
60 #define GST_RTP_HEADER_CSRC_SIZE(buf)   (GST_RTP_HEADER_CSRC_COUNT(buf) * sizeof (guint32))
61
62 void
63 gst_rtp_buffer_allocate_data (GstBuffer * buffer, guint payload_len,
64     guint8 pad_len, guint8 csrc_count)
65 {
66   guint len;
67
68   g_return_if_fail (csrc_count <= 15);
69   g_return_if_fail (GST_IS_BUFFER (buffer));
70
71   len = GST_RTP_HEADER_LEN + csrc_count * sizeof (guint32)
72       + payload_len + pad_len;
73
74   GST_BUFFER_MALLOCDATA (buffer) = g_malloc (len);
75   GST_BUFFER_DATA (buffer) = GST_BUFFER_MALLOCDATA (buffer);
76   GST_BUFFER_SIZE (buffer) = len;
77
78   /* fill in defaults */
79   GST_RTP_HEADER_VERSION (buffer) = GST_RTP_VERSION;
80   GST_RTP_HEADER_PADDING (buffer) = FALSE;
81   GST_RTP_HEADER_EXTENSION (buffer) = FALSE;
82   GST_RTP_HEADER_CSRC_COUNT (buffer) = 0;
83   GST_RTP_HEADER_MARKER (buffer) = FALSE;
84   GST_RTP_HEADER_PAYLOAD_TYPE (buffer) = 0;
85   GST_RTP_HEADER_SEQ (buffer) = 0;
86   GST_RTP_HEADER_TIMESTAMP (buffer) = 0;
87   GST_RTP_HEADER_SSRC (buffer) = 0;
88 }
89
90 GstBuffer *
91 gst_rtp_buffer_new_take_data (gpointer data, guint len)
92 {
93   GstBuffer *result;
94
95   g_return_val_if_fail (data != NULL, NULL);
96   g_return_val_if_fail (len > 0, NULL);
97
98   result = gst_buffer_new ();
99
100   GST_BUFFER_MALLOCDATA (result) = data;
101   GST_BUFFER_DATA (result) = data;
102   GST_BUFFER_SIZE (result) = len;
103
104   return result;
105 }
106
107 GstBuffer *
108 gst_rtp_buffer_new_copy_data (gpointer data, guint len)
109 {
110   return gst_rtp_buffer_new_take_data (g_memdup (data, len), len);
111 }
112
113 GstBuffer *
114 gst_rtp_buffer_new_allocate (guint payload_len, guint8 pad_len,
115     guint8 csrc_count)
116 {
117   GstBuffer *result;
118
119   g_return_val_if_fail (csrc_count <= 15, NULL);
120
121   result = gst_buffer_new ();
122   gst_rtp_buffer_allocate_data (result, payload_len, pad_len, csrc_count);
123
124   return result;
125 }
126
127 GstBuffer *
128 gst_rtp_buffer_new_allocate_len (guint packet_len, guint8 pad_len,
129     guint8 csrc_count)
130 {
131   guint len;
132
133   g_return_val_if_fail (csrc_count <= 15, NULL);
134
135   len = gst_rtp_buffer_calc_payload_len (packet_len, pad_len, csrc_count);
136
137   return gst_rtp_buffer_new_allocate (len, pad_len, csrc_count);
138 }
139
140 guint
141 gst_rtp_buffer_calc_header_len (guint8 csrc_count)
142 {
143   g_return_val_if_fail (csrc_count <= 15, 0);
144
145   return GST_RTP_HEADER_LEN + (csrc_count * sizeof (guint32));
146 }
147
148 guint
149 gst_rtp_buffer_calc_packet_len (guint payload_len, guint8 pad_len,
150     guint8 csrc_count)
151 {
152   g_return_val_if_fail (csrc_count <= 15, 0);
153
154   return payload_len + GST_RTP_HEADER_LEN + (csrc_count * sizeof (guint32))
155       + pad_len;
156 }
157
158 guint
159 gst_rtp_buffer_calc_payload_len (guint packet_len, guint8 pad_len,
160     guint8 csrc_count)
161 {
162   g_return_val_if_fail (csrc_count <= 15, 0);
163
164   return packet_len - GST_RTP_HEADER_LEN - (csrc_count * sizeof (guint32))
165       - pad_len;
166 }
167
168 gboolean
169 gst_rtp_buffer_validate_data (guint8 * data, guint len)
170 {
171   guint8 padding;
172   guint8 csrc_count;
173   guint header_len;
174   guint8 version;
175
176   g_return_val_if_fail (data != NULL, FALSE);
177
178   header_len = GST_RTP_HEADER_LEN;
179   if (len < header_len) {
180     GST_DEBUG ("len < header_len check failed (%d < %d)", len, header_len);
181     return FALSE;
182   }
183
184   /* check version */
185   version = (data[0] & 0xc0) >> 6;
186   if (version != GST_RTP_VERSION) {
187     GST_DEBUG ("version check failed (%d != %d)", version, GST_RTP_VERSION);
188     return FALSE;
189   }
190
191   /* calc header length with csrc */
192   csrc_count = (data[0] & 0x0f);
193   header_len += csrc_count * sizeof (guint32);
194
195   /* check for padding */
196   if (data[0] & 0x40)
197     padding = data[len - 1];
198   else
199     padding = 0;
200
201   /* check if padding not bigger than packet and header */
202   if (len - header_len <= padding) {
203     GST_DEBUG ("padding check failed (%d - %d <= %d)",
204         len, header_len, padding);
205     return FALSE;
206   }
207
208   return TRUE;
209 }
210
211 gboolean
212 gst_rtp_buffer_validate (GstBuffer * buffer)
213 {
214   guint8 *data;
215   guint len;
216
217   g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
218
219   data = GST_BUFFER_DATA (buffer);
220   len = GST_BUFFER_SIZE (buffer);
221
222   return gst_rtp_buffer_validate_data (data, len);
223 }
224
225
226 void
227 gst_rtp_buffer_set_packet_len (GstBuffer * buffer, guint len)
228 {
229   guint oldlen;
230
231   g_return_if_fail (GST_IS_BUFFER (buffer));
232
233   oldlen = GST_BUFFER_SIZE (buffer);
234
235   if (oldlen < len) {
236     guint8 *newdata;
237
238     newdata = g_realloc (GST_BUFFER_MALLOCDATA (buffer), len);
239     GST_BUFFER_MALLOCDATA (buffer) = newdata;
240     GST_BUFFER_DATA (buffer) = newdata;
241   }
242   GST_BUFFER_SIZE (buffer) = len;
243
244   /* remove any padding */
245   GST_RTP_HEADER_PADDING (buffer) = FALSE;
246
247 }
248
249 guint
250 gst_rtp_buffer_get_packet_len (GstBuffer * buffer)
251 {
252   g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
253
254   return GST_BUFFER_SIZE (buffer);
255 }
256
257 guint8
258 gst_rtp_buffer_get_version (GstBuffer * buffer)
259 {
260   g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
261   g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, 0);
262
263   return GST_RTP_HEADER_VERSION (buffer);
264 }
265
266 void
267 gst_rtp_buffer_set_version (GstBuffer * buffer, guint8 version)
268 {
269   g_return_if_fail (GST_IS_BUFFER (buffer));
270   g_return_if_fail (version < 0x04);
271   g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL);
272
273   GST_RTP_HEADER_VERSION (buffer) = version;
274 }
275
276
277 gboolean
278 gst_rtp_buffer_get_padding (GstBuffer * buffer)
279 {
280   g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
281   g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, FALSE);
282
283   return GST_RTP_HEADER_PADDING (buffer);
284 }
285
286 void
287 gst_rtp_buffer_set_padding (GstBuffer * buffer, gboolean padding)
288 {
289   g_return_if_fail (GST_IS_BUFFER (buffer));
290   g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL);
291
292   GST_RTP_HEADER_PADDING (buffer) = padding;
293 }
294
295 void
296 gst_rtp_buffer_pad_to (GstBuffer * buffer, guint len)
297 {
298   g_return_if_fail (GST_IS_BUFFER (buffer));
299   g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL);
300
301   if (len > 0)
302     GST_RTP_HEADER_PADDING (buffer) = TRUE;
303   else
304     GST_RTP_HEADER_PADDING (buffer) = FALSE;
305 }
306
307
308 gboolean
309 gst_rtp_buffer_get_extension (GstBuffer * buffer)
310 {
311   g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
312   g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, FALSE);
313
314   return GST_RTP_HEADER_EXTENSION (buffer);
315 }
316
317 void
318 gst_rtp_buffer_set_extension (GstBuffer * buffer, gboolean extension)
319 {
320   g_return_if_fail (GST_IS_BUFFER (buffer));
321   g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL);
322
323   GST_RTP_HEADER_EXTENSION (buffer) = extension;
324 }
325
326 guint32
327 gst_rtp_buffer_get_ssrc (GstBuffer * buffer)
328 {
329   g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
330   g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, 0);
331
332   return g_ntohl (GST_RTP_HEADER_SSRC (buffer));
333 }
334
335 void
336 gst_rtp_buffer_set_ssrc (GstBuffer * buffer, guint32 ssrc)
337 {
338   g_return_if_fail (GST_IS_BUFFER (buffer));
339   g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL);
340
341   GST_RTP_HEADER_SSRC (buffer) = g_htonl (ssrc);
342 }
343
344 guint8
345 gst_rtp_buffer_get_csrc_count (GstBuffer * buffer)
346 {
347   g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
348   g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, 0);
349
350   return GST_RTP_HEADER_CSRC_COUNT (buffer);
351 }
352
353 guint32
354 gst_rtp_buffer_get_csrc (GstBuffer * buffer, guint8 idx)
355 {
356   g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
357   g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, 0);
358   g_return_val_if_fail (GST_RTP_HEADER_CSRC_COUNT (buffer) < idx, 0);
359
360   return g_ntohl (GST_RTP_HEADER_CSRC (buffer, idx));
361 }
362
363 void
364 gst_rtp_buffer_set_csrc (GstBuffer * buffer, guint8 idx, guint32 csrc)
365 {
366   g_return_if_fail (GST_IS_BUFFER (buffer));
367   g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL);
368   g_return_if_fail (GST_RTP_HEADER_CSRC_COUNT (buffer) < idx);
369
370   GST_RTP_HEADER_CSRC (buffer, idx) = g_htonl (csrc);
371 }
372
373 gboolean
374 gst_rtp_buffer_get_marker (GstBuffer * buffer)
375 {
376   g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
377   g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, FALSE);
378
379   return GST_RTP_HEADER_MARKER (buffer);
380 }
381
382 void
383 gst_rtp_buffer_set_marker (GstBuffer * buffer, gboolean marker)
384 {
385   g_return_if_fail (GST_IS_BUFFER (buffer));
386   g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL);
387
388   GST_RTP_HEADER_MARKER (buffer) = marker;
389 }
390
391
392 guint8
393 gst_rtp_buffer_get_payload_type (GstBuffer * buffer)
394 {
395   g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
396   g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, 0);
397
398   return GST_RTP_HEADER_PAYLOAD_TYPE (buffer);
399 }
400
401 void
402 gst_rtp_buffer_set_payload_type (GstBuffer * buffer, guint8 payload_type)
403 {
404   g_return_if_fail (GST_IS_BUFFER (buffer));
405   g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL);
406   g_return_if_fail (payload_type < 0x80);
407
408   GST_RTP_HEADER_PAYLOAD_TYPE (buffer) = payload_type;
409 }
410
411
412 guint16
413 gst_rtp_buffer_get_seq (GstBuffer * buffer)
414 {
415   g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
416   g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, 0);
417
418   return g_ntohs (GST_RTP_HEADER_SEQ (buffer));
419 }
420
421 void
422 gst_rtp_buffer_set_seq (GstBuffer * buffer, guint16 seq)
423 {
424   g_return_if_fail (GST_IS_BUFFER (buffer));
425   g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL);
426
427   GST_RTP_HEADER_SEQ (buffer) = g_htons (seq);
428 }
429
430
431 guint32
432 gst_rtp_buffer_get_timestamp (GstBuffer * buffer)
433 {
434   g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
435   g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, 0);
436
437   return g_ntohl (GST_RTP_HEADER_TIMESTAMP (buffer));
438 }
439
440 void
441 gst_rtp_buffer_set_timestamp (GstBuffer * buffer, guint32 timestamp)
442 {
443   g_return_if_fail (GST_IS_BUFFER (buffer));
444   g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL);
445
446   GST_RTP_HEADER_TIMESTAMP (buffer) = g_htonl (timestamp);
447 }
448
449 GstBuffer *
450 gst_rtp_buffer_get_payload_buffer (GstBuffer * buffer)
451 {
452   guint len;
453
454   g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
455   g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, 0);
456
457   len = gst_rtp_buffer_get_payload_len (buffer);
458
459   return gst_buffer_create_sub (buffer, GST_RTP_HEADER_LEN
460       + GST_RTP_HEADER_CSRC_SIZE (buffer), len);
461 }
462
463 guint
464 gst_rtp_buffer_get_payload_len (GstBuffer * buffer)
465 {
466   guint len;
467
468   g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
469   g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, 0);
470
471   len = GST_BUFFER_SIZE (buffer)
472       - GST_RTP_HEADER_LEN - GST_RTP_HEADER_CSRC_SIZE (buffer);
473
474   if (GST_RTP_HEADER_PADDING (buffer))
475     len -= ((guint8 *) GST_BUFFER_DATA (buffer))[GST_BUFFER_SIZE (buffer) - 1];
476
477   return len;
478 }
479
480 gpointer
481 gst_rtp_buffer_get_payload (GstBuffer * buffer)
482 {
483   g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
484   g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, NULL);
485
486   return GST_BUFFER_DATA (buffer) + GST_RTP_HEADER_LEN
487       + GST_RTP_HEADER_CSRC_SIZE (buffer);
488 }