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
gst_rdt_buffer_validate_data(guint8 * data,guint len)24 gst_rdt_buffer_validate_data (guint8 * data, guint len)
25 {
26 return TRUE;
27 }
28
29 gboolean
gst_rdt_buffer_validate(GstBuffer * buffer)30 gst_rdt_buffer_validate (GstBuffer * buffer)
31 {
32 return TRUE;
33 }
34
35 guint
gst_rdt_buffer_get_packet_count(GstBuffer * buffer)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
read_packet_header(GstRDTPacket * packet)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
gst_rdt_buffer_get_first_packet(GstBuffer * buffer,GstRDTPacket * packet)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
gst_rdt_packet_move_to_next(GstRDTPacket * packet)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
gst_rdt_packet_get_type(GstRDTPacket * packet)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
gst_rdt_packet_get_length(GstRDTPacket * packet)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 *
gst_rdt_packet_to_buffer(GstRDTPacket * packet)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
gst_rdt_buffer_compare_seqnum(guint16 seqnum1,guint16 seqnum2)283 gst_rdt_buffer_compare_seqnum (guint16 seqnum1, guint16 seqnum2)
284 {
285 return (gint16) (seqnum2 - seqnum1);
286 }
287
288 guint16
gst_rdt_packet_data_get_seq(GstRDTPacket * packet)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 *
gst_rdt_packet_data_map(GstRDTPacket * packet,guint * size)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
gst_rdt_packet_data_unmap(GstRDTPacket * packet)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
gst_rdt_packet_data_get_stream_id(GstRDTPacket * packet)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
gst_rdt_packet_data_get_timestamp(GstRDTPacket * packet)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
gst_rdt_packet_data_get_flags(GstRDTPacket * packet)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 }
478