Merging gst-plugins-ugly
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-ugly / gst / realmedia / gstrdtbuffer.c
1 /* GStreamer
2  * Copyright (C) <2008> Wim Taymans <wim.taymans@gmail.com>
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., 51 Franklin St, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19 #include <string.h>
20
21 #include "gstrdtbuffer.h"
22
23 gboolean
24 gst_rdt_buffer_validate_data (guint8 * data, guint len)
25 {
26   return TRUE;
27 }
28
29 gboolean
30 gst_rdt_buffer_validate (GstBuffer * buffer)
31 {
32   return TRUE;
33 }
34
35 guint
36 gst_rdt_buffer_get_packet_count (GstBuffer * buffer)
37 {
38   GstRDTPacket packet;
39   guint count;
40
41   g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
42
43   count = 0;
44   if (gst_rdt_buffer_get_first_packet (buffer, &packet)) {
45     do {
46       count++;
47     } while (gst_rdt_packet_move_to_next (&packet));
48   }
49   return count;
50 }
51
52 static gboolean
53 read_packet_header (GstRDTPacket * packet)
54 {
55   GstMapInfo map;
56   guint8 *data;
57   gsize size;
58   guint offset;
59   guint length;
60   guint length_offset;
61
62   g_return_val_if_fail (packet != NULL, FALSE);
63   g_return_val_if_fail (GST_IS_BUFFER (packet->buffer), FALSE);
64
65   gst_buffer_map (packet->buffer, &map, GST_MAP_READ);
66   data = map.data;
67   size = map.size;
68
69   offset = packet->offset;
70
71   /* check if we are at the end of the buffer, we add 3 because we also want to
72    * ensure we can read the type, which is always at offset 1 and 2 bytes long. */
73   if (offset + 3 > size)
74     goto packet_end;
75
76   /* read type */
77   packet->type = GST_READ_UINT16_BE (&data[offset + 1]);
78
79   length = -1;
80   length_offset = -1;
81
82   /* figure out the length of the packet, this depends on the type */
83   if (GST_RDT_IS_DATA_TYPE (packet->type)) {
84     if (data[offset] & 0x80)
85       /* length is present */
86       length_offset = 3;
87   } else {
88     switch (packet->type) {
89       case GST_RDT_TYPE_ASMACTION:
90         if (data[offset] & 0x80)
91           length_offset = 5;
92         break;
93       case GST_RDT_TYPE_BWREPORT:
94         if (data[offset] & 0x80)
95           length_offset = 3;
96         break;
97       case GST_RDT_TYPE_ACK:
98         if (data[offset] & 0x80)
99           length_offset = 3;
100         break;
101       case GST_RDT_TYPE_RTTREQ:
102         length = 3;
103         break;
104       case GST_RDT_TYPE_RTTRESP:
105         length = 11;
106         break;
107       case GST_RDT_TYPE_CONGESTION:
108         length = 11;
109         break;
110       case GST_RDT_TYPE_STREAMEND:
111         length = 9;
112         /* total_reliable */
113         if (data[offset] & 0x80)
114           length += 2;
115         /* stream_id_expansion */
116         if ((data[offset] & 0x7c) == 0x7c)
117           length += 2;
118         /* ext_flag, FIXME, get string length */
119         if ((data[offset] & 0x1) == 0x1)
120           length += 7;
121         break;
122       case GST_RDT_TYPE_REPORT:
123         if (data[offset] & 0x80)
124           length_offset = 3;
125         break;
126       case GST_RDT_TYPE_LATENCY:
127         if (data[offset] & 0x80)
128           length_offset = 3;
129         break;
130       case GST_RDT_TYPE_INFOREQ:
131         length = 3;
132         /* request_time_ms */
133         if (data[offset] & 0x2)
134           length += 2;
135         break;
136       case GST_RDT_TYPE_INFORESP:
137         length = 3;
138         /* has_rtt_info */
139         if (data[offset] & 0x4) {
140           length += 4;
141           /* is_delayed */
142           if (data[offset] & 0x2) {
143             length += 4;
144           }
145         }
146         if (data[offset] & 0x1) {
147           /* buffer_info_count, FIXME read and skip */
148           length += 2;
149         }
150         break;
151       case GST_RDT_TYPE_AUTOBW:
152         if (data[offset] & 0x80)
153           length_offset = 3;
154         break;
155       case GST_RDT_TYPE_INVALID:
156       default:
157         goto unknown_packet;
158     }
159   }
160
161   if (length != -1) {
162     /* we have a fixed length */
163     packet->length = length;
164   } else if (length_offset != -1) {
165     /* we can read the length from an offset */
166     packet->length = GST_READ_UINT16_BE (&data[length_offset]);
167   } else {
168     /* length is remainder of packet */
169     packet->length = size - offset;
170   }
171   gst_buffer_unmap (packet->buffer, &map);
172
173   /* the length should be smaller than the remaining size */
174   if (packet->length + offset > size)
175     goto invalid_length;
176
177   return TRUE;
178
179   /* ERRORS */
180 packet_end:
181   {
182     gst_buffer_unmap (packet->buffer, &map);
183     return FALSE;
184   }
185 unknown_packet:
186   {
187     packet->type = GST_RDT_TYPE_INVALID;
188     gst_buffer_unmap (packet->buffer, &map);
189     return FALSE;
190   }
191 invalid_length:
192   {
193     packet->type = GST_RDT_TYPE_INVALID;
194     packet->length = 0;
195     return FALSE;
196   }
197 }
198
199 gboolean
200 gst_rdt_buffer_get_first_packet (GstBuffer * buffer, GstRDTPacket * packet)
201 {
202   g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
203   g_return_val_if_fail (packet != NULL, FALSE);
204
205   /* init to 0 */
206   packet->buffer = buffer;
207   packet->offset = 0;
208   packet->type = GST_RDT_TYPE_INVALID;
209   memset (&packet->map, 0, sizeof (GstMapInfo));
210
211   if (!read_packet_header (packet))
212     return FALSE;
213
214   return TRUE;
215 }
216
217 gboolean
218 gst_rdt_packet_move_to_next (GstRDTPacket * packet)
219 {
220   g_return_val_if_fail (packet != NULL, FALSE);
221   g_return_val_if_fail (packet->type != GST_RDT_TYPE_INVALID, FALSE);
222   g_return_val_if_fail (GST_IS_BUFFER (packet->buffer), FALSE);
223
224   /* if we have an invalid packet, it must be the last, 
225    * return FALSE */
226   if (packet->type == GST_RDT_TYPE_INVALID)
227     goto end;
228
229   /* move to next packet */
230   packet->offset += packet->length;
231
232   /* try to read new header */
233   if (!read_packet_header (packet))
234     goto end;
235
236   return TRUE;
237
238   /* ERRORS */
239 end:
240   {
241     packet->type = GST_RDT_TYPE_INVALID;
242     return FALSE;
243   }
244 }
245
246 GstRDTType
247 gst_rdt_packet_get_type (GstRDTPacket * packet)
248 {
249   g_return_val_if_fail (packet != NULL, GST_RDT_TYPE_INVALID);
250   g_return_val_if_fail (packet->type != GST_RDT_TYPE_INVALID,
251       GST_RDT_TYPE_INVALID);
252
253   return packet->type;
254 }
255
256 guint16
257 gst_rdt_packet_get_length (GstRDTPacket * packet)
258 {
259   g_return_val_if_fail (packet != NULL, 0);
260   g_return_val_if_fail (packet->type != GST_RDT_TYPE_INVALID, 0);
261
262   return packet->length;
263 }
264
265 GstBuffer *
266 gst_rdt_packet_to_buffer (GstRDTPacket * packet)
267 {
268   GstBuffer *result;
269
270   g_return_val_if_fail (packet != NULL, NULL);
271   g_return_val_if_fail (packet->type != GST_RDT_TYPE_INVALID, NULL);
272
273   result =
274       gst_buffer_copy_region (packet->buffer, GST_BUFFER_COPY_ALL,
275       packet->offset, packet->length);
276   /* timestamp applies to all packets in this buffer */
277   GST_BUFFER_TIMESTAMP (result) = GST_BUFFER_TIMESTAMP (packet->buffer);
278
279   return result;
280 }
281
282 gint
283 gst_rdt_buffer_compare_seqnum (guint16 seqnum1, guint16 seqnum2)
284 {
285   return (gint16) (seqnum2 - seqnum1);
286 }
287
288 guint16
289 gst_rdt_packet_data_get_seq (GstRDTPacket * packet)
290 {
291   GstMapInfo map;
292   guint header;
293   guint16 result;
294
295   g_return_val_if_fail (packet != NULL, FALSE);
296   g_return_val_if_fail (GST_RDT_IS_DATA_TYPE (packet->type), FALSE);
297
298   gst_buffer_map (packet->buffer, &map, GST_MAP_READ);
299
300   /* skip header bits */
301   header = packet->offset + 1;
302
303   /* read seq_no */
304   result = GST_READ_UINT16_BE (&map.data[header]);
305
306   gst_buffer_unmap (packet->buffer, &map);
307
308   return result;
309 }
310
311 guint8 *
312 gst_rdt_packet_data_map (GstRDTPacket * packet, guint * size)
313 {
314   GstMapInfo map;
315   guint header;
316   gboolean length_included_flag;
317   gboolean need_reliable_flag;
318   guint8 stream_id;
319   guint8 asm_rule_number;
320
321   g_return_val_if_fail (packet != NULL, NULL);
322   g_return_val_if_fail (packet->map.data == NULL, NULL);
323   g_return_val_if_fail (GST_RDT_IS_DATA_TYPE (packet->type), NULL);
324
325   gst_buffer_map (packet->buffer, &map, GST_MAP_READ);
326
327   header = packet->offset;
328
329   length_included_flag = (map.data[header] & 0x80) == 0x80;
330   need_reliable_flag = (map.data[header] & 0x40) == 0x40;
331   stream_id = (map.data[header] & 0x3e) >> 1;
332
333   /* skip seq_no and header bits */
334   header += 3;
335
336   if (length_included_flag) {
337     /* skip length */
338     header += 2;
339   }
340   asm_rule_number = (map.data[header] & 0x3f);
341
342   /* skip timestamp and asm_rule_number */
343   header += 5;
344
345   if (stream_id == 0x1f) {
346     /* skip stream_id_expansion */
347     header += 2;
348   }
349   if (need_reliable_flag) {
350     /* skip total_reliable */
351     header += 2;
352   }
353   if (asm_rule_number == 63) {
354     /* skip asm_rule_number_expansion */
355     header += 2;
356   }
357
358   if (size)
359     *size = packet->length - (header - packet->offset);
360
361   packet->map = map;
362
363   return &map.data[header];
364 }
365
366 gboolean
367 gst_rdt_packet_data_unmap (GstRDTPacket * packet)
368 {
369   g_return_val_if_fail (packet != NULL, FALSE);
370   g_return_val_if_fail (packet->map.data != NULL, FALSE);
371
372   gst_buffer_unmap (packet->buffer, &packet->map);
373   packet->map.data = NULL;
374
375   return TRUE;
376 }
377
378 guint16
379 gst_rdt_packet_data_get_stream_id (GstRDTPacket * packet)
380 {
381   GstMapInfo map;
382   guint16 result;
383   guint header;
384   gboolean length_included_flag;
385
386   g_return_val_if_fail (packet != NULL, 0);
387   g_return_val_if_fail (GST_RDT_IS_DATA_TYPE (packet->type), 0);
388
389   gst_buffer_map (packet->buffer, &map, GST_MAP_READ);
390
391   header = packet->offset;
392
393   length_included_flag = (map.data[header] & 0x80) == 0x80;
394   result = (map.data[header] & 0x3e) >> 1;
395   if (result == 31) {
396     /* skip seq_no and header bits */
397     header += 3;
398
399     if (length_included_flag) {
400       /* skip length */
401       header += 2;
402     }
403     /* skip asm_rule_number and timestamp */
404     header += 5;
405
406     /* stream_id_expansion */
407     result = GST_READ_UINT16_BE (&map.data[header]);
408   }
409   gst_buffer_unmap (packet->buffer, &map);
410
411   return result;
412 }
413
414 guint32
415 gst_rdt_packet_data_get_timestamp (GstRDTPacket * packet)
416 {
417   GstMapInfo map;
418   guint header;
419   gboolean length_included_flag;
420   guint32 result;
421
422   g_return_val_if_fail (packet != NULL, 0);
423   g_return_val_if_fail (GST_RDT_IS_DATA_TYPE (packet->type), 0);
424
425   gst_buffer_map (packet->buffer, &map, GST_MAP_READ);
426
427   header = packet->offset;
428
429   length_included_flag = (map.data[header] & 0x80) == 0x80;
430
431   /* skip seq_no and header bits */
432   header += 3;
433
434   if (length_included_flag) {
435     /* skip length */
436     header += 2;
437   }
438   /* skip asm_rule_number */
439   header += 1;
440
441   /* get timestamp */
442   result = GST_READ_UINT32_BE (&map.data[header]);
443   gst_buffer_unmap (packet->buffer, &map);
444
445   return result;
446 }
447
448 guint8
449 gst_rdt_packet_data_get_flags (GstRDTPacket * packet)
450 {
451   GstMapInfo map;
452   guint8 result;
453   guint header;
454   gboolean length_included_flag;
455
456   g_return_val_if_fail (packet != NULL, 0);
457   g_return_val_if_fail (GST_RDT_IS_DATA_TYPE (packet->type), 0);
458
459   gst_buffer_map (packet->buffer, &map, GST_MAP_READ);
460
461   header = packet->offset;
462
463   length_included_flag = (map.data[header] & 0x80) == 0x80;
464
465   /* skip seq_no and header bits */
466   header += 3;
467
468   if (length_included_flag) {
469     /* skip length */
470     header += 2;
471   }
472   /* get flags */
473   result = map.data[header];
474   gst_buffer_unmap (packet->buffer, &map);
475
476   return result;
477 }