]> git.sesse.net Git - vlc/blob - modules/access/udp.c
RTP reordering fixes.
[vlc] / modules / access / udp.c
1 /*****************************************************************************
2  * udp.c: raw UDP & RTP input module
3  *****************************************************************************
4  * Copyright (C) 2001-2005 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Christophe Massiot <massiot@via.ecp.fr>
8  *          Tristan Leteurtre <tooney@via.ecp.fr>
9  *          Laurent Aimar <fenrir@via.ecp.fr>
10  *          Jean-Paul Saman <jpsaman #_at_# m2x dot nl>
11  *
12  * Reviewed: 23 October 2003, Jean-Paul Saman <jpsaman@wxs.nl>
13  *
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 2 of the License, or
17  * (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
27  *****************************************************************************/
28
29 /*****************************************************************************
30  * Preamble
31  *****************************************************************************/
32 #include <stdlib.h>
33
34 #include <vlc/vlc.h>
35 #include <vlc/input.h>
36
37 #include "network.h"
38
39 /*****************************************************************************
40  * Module descriptor
41  *****************************************************************************/
42 #define CACHING_TEXT N_("Caching value in ms")
43 #define CACHING_LONGTEXT N_( \
44     "Allows you to modify the default caching value for UDP streams. This " \
45     "value should be set in millisecond units." )
46
47 #define AUTO_MTU_TEXT N_("Autodetection of MTU")
48 #define AUTO_MTU_LONGTEXT N_( \
49     "Allows growing the MTU if truncated packets are found" )
50
51 #define RTP_LATE_TEXT N_("Reorder timeout in ms for late RTP packets")
52 #define RTP_LATE_LONGTEXT N_( \
53     "Allows you to modify the RTP packets reorder and late behaviour. " \
54     "If enabled (value>0) then out-of-order packets will be held for the " \
55     "specified timeout in ms. " \
56     "The default behaviour is not to reorder." )
57
58 static int  Open ( vlc_object_t * );
59 static void Close( vlc_object_t * );
60
61 vlc_module_begin();
62     set_shortname( _("UDP/RTP" ) );
63     set_description( _("UDP/RTP input") );
64     set_category( CAT_INPUT );
65     set_subcategory( SUBCAT_INPUT_ACCESS );
66
67     add_integer( "udp-caching", DEFAULT_PTS_DELAY / 1000, NULL, CACHING_TEXT,
68                  CACHING_LONGTEXT, VLC_TRUE );
69     add_bool( "udp-auto-mtu", 1, NULL,
70               AUTO_MTU_TEXT, AUTO_MTU_LONGTEXT, VLC_TRUE );
71
72     add_integer( "rtp-late", 0, NULL, RTP_LATE_TEXT, RTP_LATE_LONGTEXT, VLC_TRUE );
73
74     set_capability( "access2", 0 );
75     add_shortcut( "udp" );
76     add_shortcut( "udpstream" );
77     add_shortcut( "udp4" );
78     add_shortcut( "udp6" );
79     add_shortcut( "rtp" );
80     add_shortcut( "rtp4" );
81     add_shortcut( "rtp6" );
82     set_callbacks( Open, Close );
83 vlc_module_end();
84
85 /*****************************************************************************
86  * Local prototypes
87  *****************************************************************************/
88 #define RTP_HEADER_LEN 12
89 #define RTP_SEQ_NUM_SIZE 65536
90
91 static block_t *BlockUDP( access_t * );
92 static block_t *BlockRTP( access_t * );
93 static block_t *BlockChoose( access_t * );
94 static int Control( access_t *, int, va_list );
95
96 struct access_sys_t
97 {
98     int fd;
99
100     int i_mtu;
101     vlc_bool_t b_auto_mtu;
102
103     /* rtp only */
104     uint16_t i_sequence_number;
105     vlc_bool_t b_first_seqno;
106
107     /* reorder rtp packets when out-of-bounds 
108      * the packets hold queue is one level deep
109      */
110     uint32_t i_rtp_late; /* number of ms an RTP packet may be too late*/
111     uint32_t i_last_pcr; /* last known good PCR */
112     block_t *p_list;     /* list of packets to rearrange */
113     block_t *p_end;      /* last packet in p_list */
114 };
115
116 /*****************************************************************************
117  * Open: open the socket
118  *****************************************************************************/
119 static int Open( vlc_object_t *p_this )
120 {
121     access_t     *p_access = (access_t*)p_this;
122     access_sys_t *p_sys;
123
124     char *psz_name = strdup( p_access->psz_path );
125     char *psz_parser, *psz_server_addr, *psz_bind_addr = "";
126     int  i_bind_port, i_server_port = 0;
127
128     /* First set ipv4/ipv6 */
129     var_Create( p_access, "ipv4", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
130     var_Create( p_access, "ipv6", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
131
132     if( *p_access->psz_access )
133     {
134         vlc_value_t val;
135         /* Find out which shortcut was used */
136         if( !strncmp( p_access->psz_access, "udp4", 6 ) ||
137             !strncmp( p_access->psz_access, "rtp4", 6 ))
138         {
139             val.b_bool = VLC_TRUE;
140             var_Set( p_access, "ipv4", val );
141
142             val.b_bool = VLC_FALSE;
143             var_Set( p_access, "ipv6", val );
144         }
145         else if( !strncmp( p_access->psz_access, "udp6", 6 ) ||
146                  !strncmp( p_access->psz_access, "rtp6", 6 ) )
147         {
148             val.b_bool = VLC_TRUE;
149             var_Set( p_access, "ipv6", val );
150
151             val.b_bool = VLC_FALSE;
152             var_Set( p_access, "ipv4", val );
153         }
154     }
155
156     i_bind_port = var_CreateGetInteger( p_access, "server-port" );
157
158     /* Parse psz_name syntax :
159      * [serveraddr[:serverport]][@[bindaddr]:[bindport]] */
160     psz_parser = strchr( psz_name, '@' );
161     if( psz_parser != NULL )
162     {
163         /* Found bind address and/or bind port */
164         *psz_parser++ = '\0';
165         psz_bind_addr = psz_parser;
166
167         if( *psz_parser == '[' )
168             /* skips bracket'd IPv6 address */
169             psz_parser = strchr( psz_parser, ']' );
170
171         if( psz_parser != NULL )
172         {
173             psz_parser = strchr( psz_parser, ':' );
174             if( psz_parser != NULL )
175             {
176                 *psz_parser++ = '\0';
177                 i_bind_port = atoi( psz_parser );
178             }
179         }
180     }
181
182     psz_server_addr = psz_name;
183     if( *psz_server_addr == '[' )
184         /* skips bracket'd IPv6 address */
185         psz_parser = strchr( psz_name, ']' );
186
187     if( psz_parser != NULL )
188     {
189         psz_parser = strchr( psz_parser, ':' );
190         if( psz_parser != NULL )
191         {
192             *psz_parser++ = '\0';
193             i_server_port = atoi( psz_parser );
194         }
195     }
196
197     msg_Dbg( p_access, "opening server=%s:%d local=%s:%d",
198              psz_server_addr, i_server_port, psz_bind_addr, i_bind_port );
199
200     /* Set up p_access */
201     p_access->pf_read = NULL;
202     if( !strcasecmp( p_access->psz_access, "rtp" )
203           || !strcasecmp( p_access->psz_access, "rtp4" )
204           || !strcasecmp( p_access->psz_access, "rtp6" ) )
205     {
206         p_access->pf_block = BlockRTP;
207     }
208     else
209     {
210         p_access->pf_block = BlockChoose;
211     }
212     p_access->pf_control = Control;
213     p_access->pf_seek = NULL;
214     p_access->info.i_update = 0;
215     p_access->info.i_size = 0;
216     p_access->info.i_pos = 0;
217     p_access->info.b_eof = VLC_FALSE;
218     p_access->info.i_title = 0;
219     p_access->info.i_seekpoint = 0;
220
221     p_access->p_sys = p_sys = malloc( sizeof( access_sys_t ) );
222     p_sys->fd = net_OpenUDP( p_access, psz_bind_addr, i_bind_port,
223                                       psz_server_addr, i_server_port );
224     if( p_sys->fd < 0 )
225     {
226         msg_Err( p_access, "cannot open socket" );
227         free( psz_name );
228         free( p_sys );
229         return VLC_EGENERIC;
230     }
231     free( psz_name );
232
233     net_StopSend( p_sys->fd );
234
235     /* FIXME */
236     p_sys->i_mtu = var_CreateGetInteger( p_access, "mtu" );
237     if( p_sys->i_mtu <= 1 )
238         p_sys->i_mtu  = 1500;   /* Avoid problem */
239
240     p_sys->b_auto_mtu = var_CreateGetBool( p_access, "udp-auto-mtu" );;
241
242     /* Update default_pts to a suitable value for udp access */
243     var_Create( p_access, "udp-caching", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
244
245     /* Keep track of RTP sequence number */
246     p_sys->i_sequence_number = 0;
247     p_sys->b_first_seqno = VLC_TRUE;
248
249     /* RTP reordering out-of-bound packets */
250     p_sys->i_last_pcr = 0;
251     p_sys->i_rtp_late = var_CreateGetInteger( p_access, "rtp-late" );
252     p_sys->p_list = NULL;
253     p_sys->p_end = NULL;
254
255     return VLC_SUCCESS;
256 }
257
258 /*****************************************************************************
259  * Close: free unused data structures
260  *****************************************************************************/
261 static void Close( vlc_object_t *p_this )
262 {
263     access_t     *p_access = (access_t*)p_this;
264     access_sys_t *p_sys = p_access->p_sys;
265
266     block_ChainRelease( p_sys->p_list );
267     net_Close( p_sys->fd );
268     free( p_sys );
269 }
270
271 /*****************************************************************************
272  * Control:
273  *****************************************************************************/
274 static int Control( access_t *p_access, int i_query, va_list args )
275 {
276     access_sys_t *p_sys = p_access->p_sys;
277     vlc_bool_t   *pb_bool;
278     int          *pi_int;
279     int64_t      *pi_64;
280
281     switch( i_query )
282     {
283         /* */
284         case ACCESS_CAN_SEEK:
285         case ACCESS_CAN_FASTSEEK:
286         case ACCESS_CAN_PAUSE:
287         case ACCESS_CAN_CONTROL_PACE:
288             pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );
289             *pb_bool = VLC_FALSE;
290             break;
291         /* */
292         case ACCESS_GET_MTU:
293             pi_int = (int*)va_arg( args, int * );
294             *pi_int = p_sys->i_mtu;
295             break;
296
297         case ACCESS_GET_PTS_DELAY:
298             pi_64 = (int64_t*)va_arg( args, int64_t * );
299             *pi_64 = var_GetInteger( p_access, "udp-caching" ) * 1000;
300             break;
301
302         /* */
303         case ACCESS_SET_PAUSE_STATE:
304         case ACCESS_GET_TITLE_INFO:
305         case ACCESS_SET_TITLE:
306         case ACCESS_SET_SEEKPOINT:
307         case ACCESS_SET_PRIVATE_ID_STATE:
308             return VLC_EGENERIC;
309
310         default:
311             msg_Warn( p_access, "unimplemented query in control" );
312             return VLC_EGENERIC;
313
314     }
315     return VLC_SUCCESS;
316 }
317
318 /*****************************************************************************
319  * BlockUDP:
320  *****************************************************************************/
321 static block_t *BlockUDP( access_t *p_access )
322 {
323     access_sys_t *p_sys = p_access->p_sys;
324     block_t      *p_block;
325
326     /* Read data */
327     p_block = block_New( p_access, p_sys->i_mtu );
328     p_block->i_buffer = net_Read( p_access, p_sys->fd, NULL,
329                                   p_block->p_buffer, p_sys->i_mtu,
330                                   VLC_FALSE );
331     if( p_block->i_buffer <= 0 )
332     {
333         block_Release( p_block );
334         return NULL;
335     }
336
337     if( (p_block->i_buffer >= p_sys->i_mtu) && p_sys->b_auto_mtu &&
338         p_sys->i_mtu < 32767 )
339     {
340         /* Increase by 100% */
341         p_sys->i_mtu *= 2;
342         msg_Dbg( p_access, "increasing MTU to %d", p_sys->i_mtu );
343     }
344
345     return p_block;
346 }
347
348 /*
349  * rtp_ChainInsert - insert a p_block in the chain and
350  * look at the sequence numbers.
351  */
352 static inline void rtp_ChainInsert( access_t *p_access, block_t *p_block )
353 {
354     access_sys_t *p_sys = (access_sys_t *) p_access->p_sys;
355     block_t *p_list = p_sys->p_list;
356     block_t *p_end  = p_sys->p_end;
357     block_t *p = NULL;
358     uint16_t i_new = 0;
359     uint16_t i_cur = 0;
360     uint16_t i_expected = 0;
361     uint32_t i_pcr_new = 0;
362
363     if( !p_block ) return;
364     if( !p_list )
365     {
366         p_sys->p_list = p_block;
367         p_sys->p_end  = p_block;
368         return;
369     }
370
371     /* Appending packets at the end of the chain is the normal case */
372     i_pcr_new = ( (p_block->p_buffer[4] << 24) +
373                   (p_block->p_buffer[5] << 16) +
374                   (p_block->p_buffer[6] << 8) +
375                    p_block->p_buffer[7] );
376     i_new = ( (p_block->p_buffer[2] << 8 ) + p_block->p_buffer[3] );
377     i_cur = ( (p_end->p_buffer[2] << 8 ) + p_end->p_buffer[3] );
378
379     i_expected = i_cur + 1;
380     if( (i_new - i_expected) >= 0 ) /* Append at the end? */
381     {
382         msg_Dbg( p_access, "RTP: append %u after %u", i_new, i_cur );
383         p_end->p_next = p_block;
384         p_sys->p_end  = p_end->p_next;
385         return;
386     }
387     /* Add to the front fo the chain? */
388     p = p_list;
389     i_cur = ( (p->p_buffer[2] << 8 ) + p->p_buffer[3] );
390     if( (i_expected - i_new) > 0 )
391     {
392         msg_Dbg( p_access, "RTP: prepend %u before %u", i_cur, i_new );
393         p_block->p_next = p;
394         p_sys->p_list = p_block;
395         return;
396     }
397     /* The packet can't be added to the front or the end of the chain,
398      * thus walk the chain from the start.
399      */
400     while( p )
401     {
402         i_cur = (p->p_buffer[2] << 8 ) + p->p_buffer[3];
403         i_expected = i_cur+1;
404
405         if( (i_cur - i_new) == 0 )
406         {
407             uint32_t i_pcr_cur = ( (p->p_buffer[4] << 24) +
408                                    (p->p_buffer[5] << 16) +
409                                    (p->p_buffer[6] << 8) +
410                                     p->p_buffer[7] );
411             /* This packet might be a duplicate, so check PCR's */
412             if( i_pcr_cur >= i_pcr_new )
413             {
414                 /* packet way too late drop it. */
415                 block_Release( p_block );
416                 return;
417             }
418             /* Add it to list later on
419              * else if( i_pcr_cur < i_pcr_new ) */
420             break;
421         }
422         else if( (i_expected - i_new) >= 0 ) /* insert in chain */
423         {
424             block_t *p_tmp = NULL;
425
426             p_tmp = p->p_next;
427             msg_Dbg( p_access, "RTP: insert %u after  %u", i_new, i_cur );
428             p->p_next = p_block;
429             p_block->p_next = p_tmp;
430             return;
431         }
432         if( !p->p_next ) break;
433         p = p->p_next;
434     }
435     msg_Dbg(p_access, "RTP: trashing duplicate %d", i_new );
436     block_Release( p_block );
437 }
438
439 /*
440  * rtp_ChainSend - look which packets are ready for sending.
441  */
442 static inline block_t *rtp_ChainSend( access_t *p_access, block_t **pp_list, uint16_t i_seq )
443 {
444     access_sys_t *p_sys = (access_sys_t *) p_access->p_sys;
445     uint16_t i_cur = 0;
446
447     if( *pp_list )
448     {
449         /* Parse RTP header */
450         int i_skip = 0;
451         int i_extension_bit = 0;
452         int i_extension_length = 0;
453         int i_CSRC_count = 0;
454         int i_payload_type = 0;
455         uint32_t i_pcr_prev = 0;
456         uint16_t i_seq_prev = 0;
457         /* Data pointers */
458         block_t *p_prev = NULL;
459         block_t *p_send = *pp_list;
460         block_t *p = *pp_list;
461
462         while( p )
463         {
464             i_cur = (p->p_buffer[2] << 8 ) + p->p_buffer[3];
465             if( (i_cur - i_seq) == 0 )
466             {
467                 msg_Dbg( p_access, "rtp_ChainSend: sequence number %u", i_seq );
468
469                 i_seq++; /* sent all packets that are received in order */
470
471                 /* Remember PCR and sequence number of packet
472                  * for next iteration */
473                 i_pcr_prev = ( (p->p_buffer[4] << 24) +
474                                (p->p_buffer[5] << 16) +
475                                (p->p_buffer[6] << 8) +
476                                 p->p_buffer[7] );
477                 i_seq_prev = ( (p->p_buffer[2] << 8 ) +
478                                 p->p_buffer[3] );
479
480                 /* Parse headerfields we need */
481                 i_CSRC_count = p->p_buffer[0] & 0x0F;
482                 i_payload_type = (p->p_buffer[1] & 0x7F);
483                 i_extension_bit  = ( p->p_buffer[0] & 0x10 ) >> 4;
484                 if ( i_extension_bit == 1)
485                     i_extension_length = ( (p->p_buffer[14] << 8 ) +
486                                             p->p_buffer[15] );
487
488                 /* Skip header + CSRC extension field n*(32 bits) + extention */
489                 i_skip = RTP_HEADER_LEN + 4*i_CSRC_count + i_extension_length;
490                 if( i_payload_type == 14 ) i_skip += 4;
491
492                 /* Return the packet without the RTP header. */
493                 p->i_buffer -= i_skip;
494                 p->p_buffer += i_skip;
495             }
496             else if( (i_cur - i_seq) > 0 )
497             {
498                 if( p_prev )
499                 {
500                     p_sys->p_list = p;
501                     p_prev->p_next = NULL;
502                     p_sys->i_last_pcr = i_pcr_prev;
503                     p_sys->i_sequence_number = i_seq_prev;
504                     return p_send;
505                 }
506                 goto out;
507             }
508             p_prev = p;
509             if (!p->p_next) break;
510             p = p->p_next;
511         }
512
513 out:
514         /* We have walked through the complete chain and all packets are
515          * in sequence - so send the whole chain
516          */
517         i_payload_type = (p->p_buffer[1] & 0x7F);
518         i_CSRC_count = p->p_buffer[0] & 0x0F;
519         i_extension_bit  = ( p->p_buffer[0] & 0x10 ) >> 4;
520         if( i_extension_bit == 1)
521             i_extension_length = ( (p->p_buffer[14] << 8 ) + p->p_buffer[15] );
522
523         /* Skip header + CSRC extension field n*(32 bits) + extention */
524         i_skip = RTP_HEADER_LEN + 4*i_CSRC_count + i_extension_length;
525         if( i_payload_type == 14 ) i_skip += 4;
526
527         /* Update the list pointers */
528         p_sys->p_list = NULL;
529         p_sys->p_end = NULL;
530         p_sys->i_sequence_number = ( (p->p_buffer[2] << 8 ) +
531                                       p->p_buffer[3] );
532         p_sys->i_last_pcr = ( (p->p_buffer[4] << 24) +
533                               (p->p_buffer[5] << 16) +
534                               (p->p_buffer[6] << 8) +
535                                p->p_buffer[7] );
536         /* Return the packet without the RTP header. */
537         p->i_buffer -= i_skip;
538         p->p_buffer += i_skip;
539         return p_send;
540     }
541     return NULL;
542 }
543
544 /*****************************************************************************
545  * BlockParseRTP/BlockRTP:
546  *****************************************************************************/
547 static block_t *BlockParseRTP( access_t *p_access, block_t *p_block )
548 {
549     access_sys_t *p_sys = (access_sys_t *) p_access->p_sys;
550     int      i_rtp_version;
551     int      i_CSRC_count;
552     int      i_payload_type;
553     int      i_skip = 0;
554     uint16_t i_sequence_number = 0;
555     uint16_t i_sequence_expected = 0;
556     int      i_extension_bit = 0;
557     int      i_extension_length = 0;
558     uint32_t i_pcr = 0;
559
560     if( p_block == NULL )
561         return NULL;
562
563     if( p_block->i_buffer < RTP_HEADER_LEN )
564     {
565         msg_Warn( p_access, "received a too short packet for RTP" );
566         block_Release( p_block );
567         return NULL;
568     }
569     /* Parse the header and make some verifications.
570      * See RFC 3550. */
571     i_rtp_version     = ( p_block->p_buffer[0] & 0xC0 ) >> 6;
572     i_CSRC_count      = p_block->p_buffer[0] & 0x0F;
573     i_payload_type    = p_block->p_buffer[1] & 0x7F;
574     i_sequence_number = (p_block->p_buffer[2] << 8) +
575                          p_block->p_buffer[3];
576     i_pcr = ( (p_block->p_buffer[4] << 24) +
577               (p_block->p_buffer[5] << 16) +
578               (p_block->p_buffer[6] << 8) +
579                p_block->p_buffer[7] );
580     i_extension_bit  = ( p_block->p_buffer[0] & 0x10 ) >> 4;
581
582     if( i_rtp_version != 2 )
583         msg_Dbg( p_access, "RTP version is %u, should be 2", i_rtp_version );
584
585     if( i_payload_type == 14 )
586         i_skip = 4;
587     else if( i_payload_type !=  33 && i_payload_type != 32 )
588         msg_Dbg( p_access, "unsupported RTP payload type (%u)", i_payload_type );
589
590     if( i_extension_bit == 1)
591         i_extension_length = 4 +
592             4 * ( (p_block->p_buffer[14] << 8) + p_block->p_buffer[15] );
593
594     /* Skip header + CSRC extension field n*(32 bits) + extention */
595     i_skip += RTP_HEADER_LEN + 4*i_CSRC_count + i_extension_length;
596     if( i_skip >= p_block->i_buffer )
597     {
598         msg_Warn( p_access, "received a too short packet for RTP" );
599         block_Release( p_block );
600         return NULL;
601     }
602
603     /* Detect RTP packet loss through tracking sequence numbers,
604      * and take RTP PCR into account.
605      * See RFC 3550.
606      */
607     if( p_sys->b_first_seqno )
608     {
609         p_sys->i_sequence_number = i_sequence_number;
610         p_sys->i_last_pcr = i_pcr;
611         p_sys->b_first_seqno = VLC_FALSE;
612         i_sequence_expected = i_sequence_number;
613     }
614     else
615         i_sequence_expected = p_sys->i_sequence_number + 1;
616
617 #if 0
618     /* Emulate packet loss */
619     if ( (i_sequence_number % 4000) == 0)
620     {
621         msg_Warn( p_access, "Emulating packet drop" );
622         block_Release( p_block );
623         return NULL;
624     }
625 #endif
626
627     if( (i_sequence_expected - i_sequence_number) != 0 )
628     {
629         /* Handle out of order packets */
630         if( p_sys->i_rtp_late > 0 )
631         {
632             if( (i_sequence_number - i_sequence_expected) > 0 )
633             {
634                 msg_Warn( p_access,
635                     "RTP packet out of order (too early) expected %u, current %u",
636                     i_sequence_expected, i_sequence_number );
637                 if( (i_pcr - p_sys->i_last_pcr) >= (p_sys->i_rtp_late*90) )
638                 {
639                     block_t *p_start = p_sys->p_list;
640                     uint16_t i_start = (!p_start) ? p_sys->i_sequence_number :
641                                        (p_start->p_buffer[2] << 8) +
642                                         p_start->p_buffer[3];
643                     /* Gap too big, we have been holding this data for too long,
644                      * send what we have.
645                      */
646                     msg_Warn( p_access,
647                         "Gap too big resyncing: delta %u, held for %d ms",
648                         (i_pcr - p_sys->i_last_pcr), p_sys->i_rtp_late );
649                     rtp_ChainInsert( p_access, p_block );
650                     return rtp_ChainSend( p_access, &p_sys->p_list, i_start );
651                 }
652                 /* hold packets that arrive too early. */
653                 rtp_ChainInsert( p_access, p_block );
654                 return rtp_ChainSend( p_access, &p_sys->p_list, i_sequence_expected );
655             }
656             else if( /* ((i_sequence_expected - i_sequence_number ) > 0) && */
657                      (p_sys->i_last_pcr - i_pcr) >= 0 )
658             {
659                 msg_Warn( p_access,
660                     "RTP packet out of order (duplicate or too late) expected %u, current %u .. trashing it",
661                     i_sequence_expected, i_sequence_number );
662                 block_Release( p_block );
663                 p_sys->i_sequence_number = i_sequence_number;
664                 p_sys->i_last_pcr = i_pcr;
665                 return NULL;
666             }
667
668             if( p_sys->p_list )
669             {
670                 block_t *p = NULL;
671                 block_t **p_send = &p_sys->p_list;
672
673                 msg_Warn( p_access,
674                     "RTP packet (unexpected condition) expected %u, current %u",
675                     i_sequence_expected, i_sequence_number );
676
677                 /* Append block to the end of chain and send whole chain */
678                 block_ChainLastAppend( &p_send, p_block );
679                 p_sys->p_list = p_sys->p_end = NULL;
680                 p_sys->i_sequence_number = i_sequence_number;
681                 p_sys->i_last_pcr = i_pcr;
682
683                 /* Return the packet without the RTP header. */
684                 p = *p_send;
685                 while( p )
686                 {
687                     p->i_buffer -= i_skip;
688                     p->p_buffer += i_skip;
689                     if( !p->p_next ) break;
690                     p = p->p_next;
691                 }
692                 return *p_send;
693             }
694             /* This code should never be reached !! */
695             msg_Err( p_access,
696                 "Bug in algorithme: (unexpected condition) expected %u (pcr=%u), current %u (pcr=%u)",
697                 i_sequence_expected, i_sequence_number, p_sys->i_last_pcr, i_pcr );
698         }
699         msg_Warn( p_access,
700                   "RTP packet(s) lost, expected sequence number %d got %d",
701                   i_sequence_expected, i_sequence_number );
702
703         /* Mark transport error in the first TS packet in the RTP stream. */
704         if( (i_payload_type == 33) && (p_block->p_buffer[0] == 0x47) )
705             p_block->p_buffer[1] |= 0x80;
706     }
707     else if( (p_sys->i_rtp_late > 0) && p_sys->p_list )
708     {
709         if( (p_sys->i_last_pcr - i_pcr) >= 0 )
710         {
711             msg_Warn( p_access,
712                 "RTP packet out of order (duplicate) expected %u, current %u .. trashing it",
713                 i_sequence_expected, i_sequence_number );
714             block_Release( p_block );
715             p_sys->i_sequence_number = i_sequence_number;
716             p_sys->i_last_pcr = i_pcr;
717             return NULL;
718         }
719         rtp_ChainInsert( p_access, p_block );
720         return rtp_ChainSend( p_access, &p_sys->p_list, i_sequence_expected );
721     }
722
723     /* This is the normal case when no packet reordering is effective */
724     p_sys->i_sequence_number = i_sequence_number;
725     p_sys->i_last_pcr = i_pcr;
726
727     /* Return the packet without the RTP header. */
728     p_block->i_buffer -= i_skip;
729     p_block->p_buffer += i_skip;
730     return p_block;
731 }
732
733 static block_t *BlockRTP( access_t *p_access )
734 {
735     block_t *p_block = BlockUDP( p_access );
736
737     if ( p_block != NULL )
738         return BlockParseRTP( p_access, p_block );
739     else
740         return NULL;
741 }
742
743 /*****************************************************************************
744  * BlockChoose: decide between RTP and UDP
745  *****************************************************************************/
746 static block_t *BlockChoose( access_t *p_access )
747 {
748     block_t *p_block;
749     int     i_rtp_version;
750     int     i_CSRC_count;
751     int     i_payload_type;
752
753     if( ( p_block = BlockUDP( p_access ) ) == NULL )
754         return NULL;
755
756     if( p_block->p_buffer[0] == 0x47 )
757     {
758         msg_Dbg( p_access, "detected TS over raw UDP" );
759         p_access->pf_block = BlockUDP;
760         return p_block;
761     }
762
763     if( p_block->i_buffer < RTP_HEADER_LEN )
764         return p_block;
765
766     /* Parse the header and make some verifications.
767      * See RFC 3550. */
768
769     i_rtp_version  = ( p_block->p_buffer[0] & 0xC0 ) >> 6;
770     i_CSRC_count   = ( p_block->p_buffer[0] & 0x0F );
771     i_payload_type = ( p_block->p_buffer[1] & 0x7F );
772
773     if( i_rtp_version != 2 )
774     {
775         msg_Dbg( p_access, "no supported RTP header detected" );
776         p_access->pf_block = BlockUDP;
777         return p_block;
778     }
779
780     switch( i_payload_type )
781     {
782         case 33:
783             msg_Dbg( p_access, "detected TS over RTP" );
784             p_access->psz_demux = strdup( "ts" );
785             break;
786
787         case 14:
788             msg_Dbg( p_access, "detected MPEG audio over RTP" );
789             p_access->psz_demux = strdup( "mpga" );
790             break;
791
792         case 32:
793             msg_Dbg( p_access, "detected MPEG video over RTP" );
794             p_access->psz_demux = strdup( "mpgv" );
795             break;
796
797         default:
798             msg_Dbg( p_access, "no RTP header detected" );
799             p_access->pf_block = BlockUDP;
800             return p_block;
801     }
802
803     p_access->pf_block = BlockRTP;
804
805     return BlockParseRTP( p_access, p_block );
806 }