]> git.sesse.net Git - vlc/blob - modules/access/udp.c
UDP: remove unneeded DCCP support
[vlc] / modules / access / udp.c
1 /*****************************************************************************
2  * udp.c: raw UDP & RTP input module
3  *****************************************************************************
4  * Copyright (C) 2001-2005 the VideoLAN team
5  * Copyright (C) 2007 Remi Denis-Courmont
6  * $Id$
7  *
8  * Authors: Christophe Massiot <massiot@via.ecp.fr>
9  *          Tristan Leteurtre <tooney@via.ecp.fr>
10  *          Laurent Aimar <fenrir@via.ecp.fr>
11  *          Jean-Paul Saman <jpsaman #_at_# m2x dot nl>
12  *          Remi Denis-Courmont
13  *
14  * Reviewed: 23 October 2003, Jean-Paul Saman <jpsaman _at_ videolan _dot_ org>
15  *
16  * This program is free software; you can redistribute it and/or modify
17  * it under the terms of the GNU General Public License as published by
18  * the Free Software Foundation; either version 2 of the License, or
19  * (at your option) any later version.
20  *
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with this program; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
29  *****************************************************************************/
30
31 /*****************************************************************************
32  * Preamble
33  *****************************************************************************/
34
35 #ifdef HAVE_CONFIG_H
36 # include "config.h"
37 #endif
38
39 #include <vlc_common.h>
40 #include <vlc_plugin.h>
41 #include <vlc_access.h>
42 #include <vlc_network.h>
43
44 #define MTU 65535
45
46 /*****************************************************************************
47  * Module descriptor
48  *****************************************************************************/
49 #define CACHING_TEXT N_("Caching value in ms")
50 #define CACHING_LONGTEXT N_( \
51     "Caching value for UDP streams. This " \
52     "value should be set in milliseconds." )
53
54 #define RTP_LATE_TEXT N_("RTP reordering timeout in ms")
55 #define RTP_LATE_LONGTEXT N_( \
56     "VLC reorders RTP packets. The input will wait for late packets at most "\
57     "the time specified here (in milliseconds)." )
58
59 static int  Open ( vlc_object_t * );
60 static void Close( vlc_object_t * );
61
62 vlc_module_begin();
63     set_shortname( N_("UDP/RTP" ) );
64     set_description( N_("UDP/RTP input") );
65     set_category( CAT_INPUT );
66     set_subcategory( SUBCAT_INPUT_ACCESS );
67
68     add_integer( "udp-caching", DEFAULT_PTS_DELAY / 1000, NULL, CACHING_TEXT,
69                  CACHING_LONGTEXT, true );
70     add_integer( "rtp-late", 100, NULL, RTP_LATE_TEXT, RTP_LATE_LONGTEXT, true );
71     add_obsolete_bool( "udp-auto-mtu" );
72
73     set_capability( "access", 0 );
74     add_shortcut( "udp" );
75     add_shortcut( "udpstream" );
76     add_shortcut( "udp4" );
77     add_shortcut( "udp6" );
78     add_shortcut( "rtptcp" ); /* tcp name is already taken */
79
80     set_callbacks( Open, Close );
81 vlc_module_end();
82
83 /*****************************************************************************
84  * Local prototypes
85  *****************************************************************************/
86 #define RTP_HEADER_LEN 12
87
88 static block_t *BlockUDP( access_t * );
89 static block_t *BlockStartRTP( access_t * );
90 static block_t *BlockRTP( access_t * );
91 static block_t *BlockChoose( access_t * );
92 static int Control( access_t *, int, va_list );
93
94 struct access_sys_t
95 {
96     int fd;
97
98     bool b_framed_rtp, b_comedia;
99
100     /* reorder rtp packets when out-of-sequence */
101     uint16_t i_last_seqno;
102     mtime_t i_rtp_late;
103     block_t *p_list;
104     block_t *p_end;
105     block_t *p_partial_frame; /* Partial Framed RTP packet */
106 };
107
108 /*****************************************************************************
109  * Open: open the socket
110  *****************************************************************************/
111 static int Open( vlc_object_t *p_this )
112 {
113     access_t     *p_access = (access_t*)p_this;
114     access_sys_t *p_sys;
115
116     char *psz_name = strdup( p_access->psz_path );
117     char *psz_parser;
118     const char *psz_server_addr, *psz_bind_addr = "";
119     int  i_bind_port, i_server_port = 0;
120     int fam = AF_UNSPEC, proto = IPPROTO_UDP;
121
122     /* Set up p_access */
123     access_InitFields( p_access );
124     ACCESS_SET_CALLBACKS( NULL, BlockStartRTP, Control, NULL );
125     p_access->info.b_prebuffered = false;
126     MALLOC_ERR( p_access->p_sys, access_sys_t ); p_sys = p_access->p_sys;
127     memset (p_sys, 0, sizeof (*p_sys));
128
129     if (strlen (p_access->psz_access) > 0)
130     {
131         switch (p_access->psz_access[strlen (p_access->psz_access) - 1])
132         {
133             case '4':
134                 fam = AF_INET;
135                 break;
136
137             case '6':
138                 fam = AF_INET6;
139                 break;
140         }
141
142         if (strncmp (p_access->psz_access, "udp", 3 ) == 0 )
143             p_access->pf_block = BlockChoose;
144         else
145         if (strcmp (p_access->psz_access, "rtptcp") == 0)
146             proto = IPPROTO_TCP;
147     }
148
149     i_bind_port = var_CreateGetInteger( p_access, "server-port" );
150
151     /* Parse psz_name syntax :
152      * [serveraddr[:serverport]][@[bindaddr]:[bindport]] */
153     psz_parser = strchr( psz_name, '@' );
154     if( psz_parser != NULL )
155     {
156         /* Found bind address and/or bind port */
157         *psz_parser++ = '\0';
158         psz_bind_addr = psz_parser;
159
160         if( psz_bind_addr[0] == '[' )
161             /* skips bracket'd IPv6 address */
162             psz_parser = strchr( psz_parser, ']' );
163
164         if( psz_parser != NULL )
165         {
166             psz_parser = strchr( psz_parser, ':' );
167             if( psz_parser != NULL )
168             {
169                 *psz_parser++ = '\0';
170                 i_bind_port = atoi( psz_parser );
171             }
172         }
173     }
174
175     psz_server_addr = psz_name;
176     psz_parser = ( psz_server_addr[0] == '[' )
177         ? strchr( psz_name, ']' ) /* skips bracket'd IPv6 address */
178         : psz_name;
179
180     if( psz_parser != NULL )
181     {
182         psz_parser = strchr( psz_parser, ':' );
183         if( psz_parser != NULL )
184         {
185             *psz_parser++ = '\0';
186             i_server_port = atoi( psz_parser );
187         }
188     }
189
190     msg_Dbg( p_access, "opening server=%s:%d local=%s:%d",
191              psz_server_addr, i_server_port, psz_bind_addr, i_bind_port );
192
193     /* Hmm, the net_* connection functions may need to be unified... */
194     switch (proto)
195     {
196         case IPPROTO_UDP:
197             p_sys->fd = net_OpenDgram( p_access, psz_bind_addr, i_bind_port,
198                                        psz_server_addr, i_server_port, fam,
199                                        proto );
200             break;
201
202         case IPPROTO_TCP:
203             p_sys->fd = net_ConnectTCP( p_access, psz_server_addr, i_server_port );
204             p_access->pf_block = BlockRTP;
205             p_sys->b_comedia = p_sys->b_framed_rtp = true;
206             break;
207     }
208     free (psz_name);
209     if( p_sys->fd == -1 )
210     {
211         msg_Err( p_access, "cannot open socket" );
212         free( p_sys );
213         return VLC_EGENERIC;
214     }
215
216     shutdown( p_sys->fd, SHUT_WR );
217     net_SetCSCov (p_sys->fd, -1, 12);
218
219     /* Update default_pts to a suitable value for udp access */
220     var_Create( p_access, "udp-caching", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
221
222     /* RTP reordering for out-of-sequence packets */
223     p_sys->i_rtp_late = var_CreateGetInteger( p_access, "rtp-late" ) * 1000;
224     p_sys->i_last_seqno = 0;
225     p_sys->p_list = NULL;
226     p_sys->p_end = NULL;
227     return VLC_SUCCESS;
228 }
229
230 /*****************************************************************************
231  * Close: free unused data structures
232  *****************************************************************************/
233 static void Close( vlc_object_t *p_this )
234 {
235     access_t     *p_access = (access_t*)p_this;
236     access_sys_t *p_sys = p_access->p_sys;
237
238     block_ChainRelease( p_sys->p_list );
239     net_Close( p_sys->fd );
240     free( p_sys );
241 }
242
243 /*****************************************************************************
244  * Control:
245  *****************************************************************************/
246 static int Control( access_t *p_access, int i_query, va_list args )
247 {
248     bool   *pb_bool;
249     int          *pi_int;
250     int64_t      *pi_64;
251
252     switch( i_query )
253     {
254         /* */
255         case ACCESS_CAN_SEEK:
256         case ACCESS_CAN_FASTSEEK:
257         case ACCESS_CAN_PAUSE:
258         case ACCESS_CAN_CONTROL_PACE:
259             pb_bool = (bool*)va_arg( args, bool* );
260             *pb_bool = false;
261             break;
262         /* */
263         case ACCESS_GET_MTU:
264             pi_int = (int*)va_arg( args, int * );
265             *pi_int = MTU;
266             break;
267
268         case ACCESS_GET_PTS_DELAY:
269             pi_64 = (int64_t*)va_arg( args, int64_t * );
270             *pi_64 = var_GetInteger( p_access, "udp-caching" ) * 1000;
271             break;
272
273         /* */
274         case ACCESS_SET_PAUSE_STATE:
275         case ACCESS_GET_TITLE_INFO:
276         case ACCESS_SET_TITLE:
277         case ACCESS_SET_SEEKPOINT:
278         case ACCESS_SET_PRIVATE_ID_STATE:
279         case ACCESS_GET_CONTENT_TYPE:
280             return VLC_EGENERIC;
281
282         default:
283             msg_Warn( p_access, "unimplemented query in control" );
284             return VLC_EGENERIC;
285
286     }
287     return VLC_SUCCESS;
288 }
289
290 /*****************************************************************************
291  * BlockUDP:
292  *****************************************************************************/
293 static block_t *BlockUDP( access_t *p_access )
294 {
295     access_sys_t *p_sys = p_access->p_sys;
296     block_t      *p_block;
297     ssize_t len;
298
299     if( p_access->info.b_eof )
300         return NULL;
301
302     /* Read data */
303     p_block = block_New( p_access, MTU );
304     len = net_Read( p_access, p_sys->fd, NULL,
305                     p_block->p_buffer, MTU, false );
306     if( ( len < 0 )
307      || ( p_sys->b_comedia && ( len == 0 ) ) )
308     {
309         if( p_sys->b_comedia )
310         {
311             p_access->info.b_eof = true;
312             msg_Dbg( p_access, "connection-oriented media hangup" );
313         }
314         block_Release( p_block );
315         return NULL;
316     }
317
318     return block_Realloc( p_block, 0, p_block->i_buffer = len );
319 }
320
321 /*****************************************************************************
322  * BlockTCP: Framed RTP/AVP packet reception for COMEDIA (see RFC4571)
323  *****************************************************************************/
324 static block_t *BlockTCP( access_t *p_access )
325 {
326     access_sys_t *p_sys = p_access->p_sys;
327     block_t      *p_block = p_sys->p_partial_frame;
328
329     if( p_access->info.b_eof )
330         return NULL;
331
332     if( p_block == NULL )
333     {
334         /* MTU should always be 65535 in this case */
335         p_sys->p_partial_frame = p_block = block_New( p_access, 2 + MTU );
336         if (p_block == NULL)
337             return NULL;
338     }
339
340     /* Read RTP framing */
341     if (p_block->i_buffer < 2)
342     {
343         int i_read = net_Read( p_access, p_sys->fd, NULL,
344                                p_block->p_buffer + p_block->i_buffer,
345                                2 - p_block->i_buffer, false );
346         if( i_read <= 0 )
347             goto error;
348
349         p_block->i_buffer += i_read;
350         if (p_block->i_buffer < 2)
351             return NULL;
352     }
353
354     uint16_t framelen = GetWLE( p_block->p_buffer );
355     /* Read RTP frame */
356     if( framelen > 0 )
357     {
358         int i_read = net_Read( p_access, p_sys->fd, NULL,
359                                p_block->p_buffer + p_block->i_buffer,
360                                2 + framelen - p_block->i_buffer, false );
361         if( i_read <= 0 )
362             goto error;
363
364         p_block->i_buffer += i_read;
365     }
366
367     if( p_block->i_buffer < (2u + framelen) )
368         return NULL; // incomplete frame
369
370     /* Hide framing from RTP layer */
371     p_block->p_buffer += 2;
372     p_block->i_buffer -= 2;
373     p_sys->p_partial_frame = NULL;
374     return p_block;
375
376 error:
377     p_access->info.b_eof = true;
378     block_Release( p_block );
379     p_sys->p_partial_frame = NULL;
380     return NULL;
381 }
382
383
384 /*
385  * rtp_ChainInsert - insert a p_block in the chain and
386  * look at the sequence numbers.
387  */
388 static inline bool rtp_ChainInsert( access_t *p_access, block_t *p_block )
389 {
390     access_sys_t *p_sys = (access_sys_t *) p_access->p_sys;
391     block_t *p_prev = NULL;
392     block_t *p = p_sys->p_end;
393     uint16_t i_new = (uint16_t) p_block->i_dts;
394     uint16_t i_tmp = 0;
395
396     if( !p_sys->p_list )
397     {
398         p_sys->p_list = p_block;
399         p_sys->p_end = p_block;
400         return true;
401     }
402     /* walk through the queue from top down since the new packet is in
403     most cases just appended to the end */
404
405     for( ;; )
406     {
407         i_tmp = i_new - (uint16_t) p->i_dts;
408
409         if( !i_tmp )   /* trash duplicate */
410             break;
411
412         if ( i_tmp < 32768 )
413         {   /* insert after this block ( i_new > p->i_dts ) */
414             p_block->p_next = p->p_next;
415             p->p_next = p_block;
416             p_block->p_prev = p;
417             if (p_prev)
418             {
419                 p_prev->p_prev = p_block;
420                 msg_Dbg(p_access, "RTP reordering: insert after %d, new %d",
421                         (uint16_t) p->i_dts, i_new );
422             }
423             else
424             {
425                 p_sys->p_end = p_block;
426             }
427             return true;
428         }
429         if( p == p_sys->p_list )
430         {   /* we've reached bottom of chain */
431             i_tmp = p_sys->i_last_seqno - i_new;
432             if( !p_access->info.b_prebuffered || (i_tmp > 32767) )
433             {
434                 msg_Dbg(p_access, "RTP reordering: prepend %d before %d",
435                         i_new, (uint16_t) p->i_dts );
436                 p_block->p_next = p;
437                 p->p_prev = p_block;
438                 p_sys->p_list = p_block;
439                 return true;
440             }
441
442             if( !i_tmp )   /* trash duplicate */
443                 break;
444
445             /* reordering failed - append the packet to the end of queue */
446             msg_Dbg(p_access, "RTP: sequence changed (or buffer too small) "
447                     "new: %d, buffer %d...%d", i_new, (uint16_t) p->i_dts,
448                 (uint16_t) p_sys->p_end->i_dts);
449             p_sys->p_end->p_next = p_block;
450             p_block->p_prev = p_sys->p_end;
451             p_sys->p_end = p_block;
452             return true;
453         }
454         p_prev = p;
455         p = p->p_prev;
456     }
457     block_Release( p_block );
458     return false;
459 }
460
461 /*****************************************************************************
462  * BlockParseRTP: decapsulate the RTP packet and return it
463  *****************************************************************************/
464 static block_t *BlockParseRTP( access_t *p_access, block_t *p_block )
465 {
466     int      i_payload_type;
467     size_t   i_skip = RTP_HEADER_LEN;
468
469     if( p_block == NULL )
470         return NULL;
471
472     if( p_block->i_buffer < RTP_HEADER_LEN )
473     {
474         msg_Dbg( p_access, "short RTP packet received" );
475         goto trash;
476     }
477
478     /* Parse the header and make some verifications.
479      * See RFC 3550. */
480     // Version number:
481     if( ( p_block->p_buffer[0] >> 6 ) != 2)
482     {
483         msg_Dbg( p_access, "RTP version is %u instead of 2",
484                  p_block->p_buffer[0] >> 6 );
485         goto trash;
486     }
487     // Padding bit:
488     uint8_t pad = (p_block->p_buffer[0] & 0x20)
489                     ? p_block->p_buffer[p_block->i_buffer - 1] : 0;
490     // CSRC count:
491     i_skip += (p_block->p_buffer[0] & 0x0F) * 4;
492     // Extension header:
493     if (p_block->p_buffer[0] & 0x10) /* Extension header */
494     {
495         i_skip += 4;
496         if ((size_t)p_block->i_buffer < i_skip)
497             goto trash;
498
499         i_skip += 4 * GetWBE( p_block->p_buffer + i_skip - 2 );
500     }
501
502     i_payload_type    = p_block->p_buffer[1] & 0x7F;
503
504     /* Remember sequence number in i_dts */
505     p_block->i_pts = mdate();
506     p_block->i_dts = (mtime_t) GetWBE( p_block->p_buffer + 2 );
507
508     /* FIXME: use rtpmap */
509     const char *psz_demux = NULL;
510
511     switch( i_payload_type )
512     {
513         case 14: // MPA: MPEG Audio (RFC2250, §3.4)
514             i_skip += 4; // 32 bits RTP/MPA header
515             psz_demux = "mpga";
516             break;
517
518         case 32: // MPV: MPEG Video (RFC2250, §3.5)
519             i_skip += 4; // 32 bits RTP/MPV header
520             if( (size_t)p_block->i_buffer < i_skip )
521                 goto trash;
522             if( p_block->p_buffer[i_skip - 3] & 0x4 )
523             {
524                 /* MPEG2 Video extension header */
525                 /* TODO: shouldn't we skip this too ? */
526             }
527             psz_demux = "mpgv";
528             break;
529
530         case 33: // MP2: MPEG TS (RFC2250, §2)
531             /* plain TS over RTP */
532             psz_demux = "ts";
533             break;
534
535         case 72: /* muxed SR */
536         case 73: /* muxed RR */
537         case 74: /* muxed SDES */
538         case 75: /* muxed BYE */
539         case 76: /* muxed APP */
540             goto trash; /* ooh! ignoring RTCP is evil! */
541
542         default:
543             msg_Dbg( p_access, "unsupported RTP payload type: %u", i_payload_type );
544             goto trash;
545     }
546
547     if( (size_t)p_block->i_buffer < (i_skip + pad) )
548         goto trash;
549
550     /* Remove the RTP header */
551     p_block->i_buffer -= i_skip;
552     p_block->p_buffer += i_skip;
553
554     /* This is the place for deciphering and authentication */
555
556     /* Remove padding (at the end) */
557     p_block->i_buffer -= pad;
558
559 #if 0
560     /* Emulate packet loss */
561     if ( (i_sequence_number % 4000) == 0)
562     {
563         msg_Warn( p_access, "Emulating packet drop" );
564         block_Release( p_block );
565         return NULL;
566     }
567 #endif
568
569     if( !p_access->psz_demux || !*p_access->psz_demux )
570     {
571         free( p_access->psz_demux );
572         p_access->psz_demux = strdup( psz_demux );
573     }
574
575     return p_block;
576
577 trash:
578     block_Release( p_block );
579     return NULL;
580 }
581
582 /*****************************************************************************
583  * BlockRTP: receives an RTP packet, parses it, queues it queue,
584  * then dequeues the oldest packet and returns it to input/demux.
585  ****************************************************************************/
586 static block_t *BlockRTP( access_t *p_access )
587 {
588     access_sys_t *p_sys = p_access->p_sys;
589     block_t *p;
590
591     while ( !p_sys->p_list ||
592              ( mdate() - p_sys->p_list->i_pts ) < p_sys->i_rtp_late )
593     {
594         p = BlockParseRTP( p_access,
595                            p_sys->b_framed_rtp ? BlockTCP( p_access )
596                                                : BlockUDP( p_access ) );
597         if ( !p )
598             return NULL;
599
600         rtp_ChainInsert( p_access, p );
601     }
602
603     p = p_sys->p_list;
604     p_sys->p_list = p_sys->p_list->p_next;
605     p_sys->i_last_seqno++;
606     if( p_sys->i_last_seqno != (uint16_t) p->i_dts )
607     {
608         msg_Dbg( p_access, "RTP: packet(s) lost, expected %d, got %d",
609                  p_sys->i_last_seqno, (uint16_t) p->i_dts );
610         p_sys->i_last_seqno = (uint16_t) p->i_dts;
611     }
612     p->p_next = NULL;
613     return p;
614 }
615
616 /*****************************************************************************
617  * BlockPrebufferRTP: waits until we have at least two RTP datagrams,
618  * so that we can synchronize the RTP sequence number.
619  * This is only useful for non-reliable transport protocols.
620  ****************************************************************************/
621 static block_t *BlockPrebufferRTP( access_t *p_access, block_t *p_block )
622 {
623     access_sys_t *p_sys = p_access->p_sys;
624     mtime_t   i_first = mdate();
625     int       i_count = 0;
626     block_t   *p = p_block;
627
628     if( BlockParseRTP( p_access, p_block ) == NULL )
629         return NULL;
630
631     for( ;; )
632     {
633         mtime_t i_date = mdate();
634
635         if( p && rtp_ChainInsert( p_access, p ))
636             i_count++;
637
638         /* Require at least 2 packets in the buffer */
639         if( i_count > 2 && (i_date - i_first) > p_sys->i_rtp_late )
640             break;
641
642         p = BlockParseRTP( p_access, BlockUDP( p_access ) );
643         if( !p && (i_date - i_first) > p_sys->i_rtp_late )
644         {
645             msg_Err( p_access, "error in RTP prebuffering!" );
646             return NULL;
647         }
648     }
649
650     msg_Dbg( p_access, "RTP: prebuffered %d packets", i_count - 1 );
651     p_access->info.b_prebuffered = true;
652     p = p_sys->p_list;
653     p_sys->p_list = p_sys->p_list->p_next;
654     p_sys->i_last_seqno = (uint16_t) p->i_dts;
655     p->p_next = NULL;
656     return p;
657 }
658
659 static block_t *BlockStartRTP( access_t *p_access )
660 {
661     p_access->pf_block = BlockRTP;
662     return BlockPrebufferRTP( p_access, BlockUDP( p_access ) );
663 }
664
665
666 /*****************************************************************************
667  * BlockChoose: decide between RTP and UDP
668  *****************************************************************************/
669 static block_t *BlockChoose( access_t *p_access )
670 {
671     block_t *p_block;
672     int     i_rtp_version;
673     int     i_payload_type;
674
675     if( ( p_block = BlockUDP( p_access ) ) == NULL )
676         return NULL;
677
678     if( p_block->p_buffer[0] == 0x47 )
679     {
680         msg_Dbg( p_access, "detected TS over raw UDP" );
681         p_access->pf_block = BlockUDP;
682         p_access->info.b_prebuffered = true;
683         return p_block;
684     }
685
686     if( p_block->i_buffer < RTP_HEADER_LEN )
687         return p_block;
688
689     /* Parse the header and make some verifications.
690      * See RFC 3550. */
691
692     i_rtp_version  = p_block->p_buffer[0] >> 6;
693     i_payload_type = ( p_block->p_buffer[1] & 0x7F );
694
695     if( i_rtp_version != 2 )
696     {
697         msg_Dbg( p_access, "no supported RTP header detected" );
698         p_access->pf_block = BlockUDP;
699         p_access->info.b_prebuffered = true;
700         return p_block;
701     }
702
703     switch( i_payload_type )
704     {
705         case 33:
706             msg_Dbg( p_access, "detected MPEG2 TS over RTP" );
707             free( p_access->psz_demux );
708             p_access->psz_demux = strdup( "ts" );
709             break;
710
711         case 14:
712             msg_Dbg( p_access, "detected MPEG Audio over RTP" );
713             free( p_access->psz_demux );
714             p_access->psz_demux = strdup( "mpga" );
715             break;
716
717         case 32:
718             msg_Dbg( p_access, "detected MPEG Video over RTP" );
719             free( p_access->psz_demux );
720             p_access->psz_demux = strdup( "mpgv" );
721             break;
722
723         default:
724             msg_Dbg( p_access, "no RTP header detected" );
725             p_access->pf_block = BlockUDP;
726             p_access->info.b_prebuffered = true;
727             return p_block;
728     }
729
730     p_access->pf_block = BlockRTP;
731     return BlockPrebufferRTP( p_access, p_block );
732 }