Changeset 26f8df3b9bb2b1d3af666feafe1faf4e108c42ea

Show
Ignore:
Timestamp:
07/06/08 17:34:16 (5 months ago)
Author:
Rémi Denis-Courmont <rdenis@simphalempin.com>
git-committer:
Rémi Denis-Courmont <rdenis@simphalempin.com> 1212852856 +0300
git-parent:

[51a5b2bedc0dd99f556c3fb64ffa8450c5401a44]

git-author:
Rémi Denis-Courmont <rdenis@simphalempin.com> 1212852856 +0300
Message:

UDP: remove old RTP code

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • modules/access/udp.c

    r1b44115 r26f8df3  
    11/***************************************************************************** 
    2  * udp.c: raw UDP & RTP input module 
     2 * udp.c: raw UDP input module 
    33 ***************************************************************************** 
    44 * Copyright (C) 2001-2005 the VideoLAN team 
     
    5252    "value should be set in milliseconds." ) 
    5353 
    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  
    5954static int  Open ( vlc_object_t * ); 
    6055static void Close( vlc_object_t * ); 
    6156 
    6257vlc_module_begin(); 
    63     set_shortname( N_("UDP/RTP" ) ); 
    64     set_description( N_("UDP/RTP input") ); 
     58    set_shortname( N_("UDP" ) ); 
     59    set_description( N_("UDP input") ); 
    6560    set_category( CAT_INPUT ); 
    6661    set_subcategory( SUBCAT_INPUT_ACCESS ); 
     
    6863    add_integer( "udp-caching", DEFAULT_PTS_DELAY / 1000, NULL, CACHING_TEXT, 
    6964                 CACHING_LONGTEXT, true ); 
    70     add_integer( "rtp-late", 100, NULL, RTP_LATE_TEXT, RTP_LATE_LONGTEXT, true ); 
     65    add_obsolete_integer( "rtp-late" ); 
    7166    add_obsolete_bool( "udp-auto-mtu" ); 
    7267 
     
    7671    add_shortcut( "udp4" ); 
    7772    add_shortcut( "udp6" ); 
    78     add_shortcut( "rtptcp" ); /* tcp name is already taken */ 
    7973 
    8074    set_callbacks( Open, Close ); 
     
    8781 
    8882static block_t *BlockUDP( access_t * ); 
    89 static block_t *BlockStartRTP( access_t * ); 
    90 static block_t *BlockRTP( access_t * ); 
    9183static int Control( access_t *, int, va_list ); 
    9284 
    93 struct access_sys_t 
    94 { 
    95     int fd; 
    96  
    97     bool b_framed_rtp, b_comedia; 
    98  
    99     /* reorder rtp packets when out-of-sequence */ 
    100     uint16_t i_last_seqno; 
    101     mtime_t i_rtp_late; 
    102     block_t *p_list; 
    103     block_t *p_end; 
    104     block_t *p_partial_frame; /* Partial Framed RTP packet */ 
    105 }; 
    106  
    10785/***************************************************************************** 
    10886 * Open: open the socket 
     
    11189{ 
    11290    access_t     *p_access = (access_t*)p_this; 
    113     access_sys_t *p_sys; 
    11491 
    11592    char *psz_name = strdup( p_access->psz_path ); 
     
    11794    const char *psz_server_addr, *psz_bind_addr = ""; 
    11895    int  i_bind_port, i_server_port = 0; 
    119     int fam = AF_UNSPEC, proto = IPPROTO_UDP; 
     96    int fam = AF_UNSPEC; 
     97    int fd; 
    12098 
    12199    /* Set up p_access */ 
    122100    access_InitFields( p_access ); 
    123     ACCESS_SET_CALLBACKS( NULL, BlockStartRTP, Control, NULL ); 
     101    ACCESS_SET_CALLBACKS( NULL, BlockUDP, Control, NULL ); 
    124102    p_access->info.b_prebuffered = false; 
    125     MALLOC_ERR( p_access->p_sys, access_sys_t ); p_sys = p_access->p_sys; 
    126     memset (p_sys, 0, sizeof (*p_sys)); 
    127103 
    128104    if (strlen (p_access->psz_access) > 0) 
     
    138114                break; 
    139115        } 
    140  
    141         if (strncmp (p_access->psz_access, "udp", 3 ) == 0 ) 
    142             p_access->pf_block = BlockUDP; 
    143         else 
    144         if (strcmp (p_access->psz_access, "rtptcp") == 0) 
    145             proto = IPPROTO_TCP; 
    146116    } 
    147117 
     
    190160             psz_server_addr, i_server_port, psz_bind_addr, i_bind_port ); 
    191161 
    192     /* Hmm, the net_* connection functions may need to be unified... */ 
    193     switch (proto) 
    194     { 
    195         case IPPROTO_UDP: 
    196             p_sys->fd = net_OpenDgram( p_access, psz_bind_addr, i_bind_port, 
    197                                        psz_server_addr, i_server_port, fam, 
    198                                        proto ); 
    199             break; 
    200  
    201         case IPPROTO_TCP: 
    202             p_sys->fd = net_ConnectTCP( p_access, psz_server_addr, i_server_port ); 
    203             p_access->pf_block = BlockRTP; 
    204             p_sys->b_comedia = p_sys->b_framed_rtp = true; 
    205             break; 
    206     } 
     162    fd = net_OpenDgram( p_access, psz_bind_addr, i_bind_port, 
     163                        psz_server_addr, i_server_port, fam, IPPROTO_UDP ); 
    207164    free (psz_name); 
    208     if( p_sys->fd == -1 ) 
     165    if( fd == -1 ) 
    209166    { 
    210167        msg_Err( p_access, "cannot open socket" ); 
    211         free( p_sys ); 
    212168        return VLC_EGENERIC; 
    213169    } 
    214  
    215     shutdown( p_sys->fd, SHUT_WR ); 
    216     net_SetCSCov (p_sys->fd, -1, 12); 
     170    p_access->p_sys = (void *)(intptr_t)fd; 
    217171 
    218172    /* Update default_pts to a suitable value for udp access */ 
    219173    var_Create( p_access, "udp-caching", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); 
    220  
    221     /* RTP reordering for out-of-sequence packets */ 
    222     p_sys->i_rtp_late = var_CreateGetInteger( p_access, "rtp-late" ) * 1000; 
    223     p_sys->i_last_seqno = 0; 
    224     p_sys->p_list = NULL; 
    225     p_sys->p_end = NULL; 
    226174    return VLC_SUCCESS; 
    227175} 
     
    233181{ 
    234182    access_t     *p_access = (access_t*)p_this; 
    235     access_sys_t *p_sys = p_access->p_sys; 
    236  
    237     block_ChainRelease( p_sys->p_list ); 
    238     net_Close( p_sys->fd ); 
    239     free( p_sys ); 
     183 
     184    net_Close( (intptr_t)p_access->p_sys ); 
    240185} 
    241186 
     
    301246    /* Read data */ 
    302247    p_block = block_New( p_access, MTU ); 
    303     len = net_Read( p_access, p_sys->fd, NULL, 
     248    len = net_Read( p_access, (intptr_t)p_sys, NULL, 
    304249                    p_block->p_buffer, MTU, false ); 
    305     if( ( len < 0 ) 
    306      || ( p_sys->b_comedia && ( len == 0 ) ) ) 
    307     { 
    308         if( p_sys->b_comedia ) 
    309         { 
    310             p_access->info.b_eof = true; 
    311             msg_Dbg( p_access, "connection-oriented media hangup" ); 
    312         } 
     250    if( len < 0 ) 
     251    { 
    313252        block_Release( p_block ); 
    314253        return NULL; 
     
    317256    return block_Realloc( p_block, 0, p_block->i_buffer = len ); 
    318257} 
    319  
    320 /***************************************************************************** 
    321  * BlockTCP: Framed RTP/AVP packet reception for COMEDIA (see RFC4571) 
    322  *****************************************************************************/ 
    323 static block_t *BlockTCP( access_t *p_access ) 
    324 { 
    325     access_sys_t *p_sys = p_access->p_sys; 
    326     block_t      *p_block = p_sys->p_partial_frame; 
    327  
    328     if( p_access->info.b_eof ) 
    329         return NULL; 
    330  
    331     if( p_block == NULL ) 
    332     { 
    333         /* MTU should always be 65535 in this case */ 
    334         p_sys->p_partial_frame = p_block = block_New( p_access, 2 + MTU ); 
    335         if (p_block == NULL) 
    336             return NULL; 
    337     } 
    338  
    339     /* Read RTP framing */ 
    340     if (p_block->i_buffer < 2) 
    341     { 
    342         int i_read = net_Read( p_access, p_sys->fd, NULL, 
    343                                p_block->p_buffer + p_block->i_buffer, 
    344                                2 - p_block->i_buffer, false ); 
    345         if( i_read <= 0 ) 
    346             goto error; 
    347  
    348         p_block->i_buffer += i_read; 
    349         if (p_block->i_buffer < 2) 
    350             return NULL; 
    351     } 
    352  
    353     uint16_t framelen = GetWLE( p_block->p_buffer ); 
    354     /* Read RTP frame */ 
    355     if( framelen > 0 ) 
    356     { 
    357         int i_read = net_Read( p_access, p_sys->fd, NULL, 
    358                                p_block->p_buffer + p_block->i_buffer, 
    359                                2 + framelen - p_block->i_buffer, false ); 
    360         if( i_read <= 0 ) 
    361             goto error; 
    362  
    363         p_block->i_buffer += i_read; 
    364     } 
    365  
    366     if( p_block->i_buffer < (2u + framelen) ) 
    367         return NULL; // incomplete frame 
    368  
    369     /* Hide framing from RTP layer */ 
    370     p_block->p_buffer += 2; 
    371     p_block->i_buffer -= 2; 
    372     p_sys->p_partial_frame = NULL; 
    373     return p_block; 
    374  
    375 error: 
    376     p_access->info.b_eof = true; 
    377     block_Release( p_block ); 
    378     p_sys->p_partial_frame = NULL; 
    379     return NULL; 
    380 } 
    381  
    382  
    383 /* 
    384  * rtp_ChainInsert - insert a p_block in the chain and 
    385  * look at the sequence numbers. 
    386  */ 
    387 static inline bool rtp_ChainInsert( access_t *p_access, block_t *p_block ) 
    388 { 
    389     access_sys_t *p_sys = (access_sys_t *) p_access->p_sys; 
    390     block_t *p_prev = NULL; 
    391     block_t *p = p_sys->p_end; 
    392     uint16_t i_new = (uint16_t) p_block->i_dts; 
    393     uint16_t i_tmp = 0; 
    394  
    395     if( !p_sys->p_list ) 
    396     { 
    397         p_sys->p_list = p_block; 
    398         p_sys->p_end = p_block; 
    399         return true; 
    400     } 
    401     /* walk through the queue from top down since the new packet is in 
    402     most cases just appended to the end */ 
    403  
    404     for( ;; ) 
    405     { 
    406         i_tmp = i_new - (uint16_t) p->i_dts; 
    407  
    408         if( !i_tmp )   /* trash duplicate */ 
    409             break; 
    410  
    411         if ( i_tmp < 32768 ) 
    412         {   /* insert after this block ( i_new > p->i_dts ) */ 
    413             p_block->p_next = p->p_next; 
    414             p->p_next = p_block; 
    415             p_block->p_prev = p; 
    416             if (p_prev) 
    417             { 
    418                 p_prev->p_prev = p_block; 
    419                 msg_Dbg(p_access, "RTP reordering: insert after %d, new %d", 
    420                         (uint16_t) p->i_dts, i_new ); 
    421             } 
    422             else 
    423             { 
    424                 p_sys->p_end = p_block; 
    425             } 
    426             return true; 
    427         } 
    428         if( p == p_sys->p_list ) 
    429         {   /* we've reached bottom of chain */ 
    430             i_tmp = p_sys->i_last_seqno - i_new; 
    431             if( !p_access->info.b_prebuffered || (i_tmp > 32767) ) 
    432             { 
    433                 msg_Dbg(p_access, "RTP reordering: prepend %d before %d", 
    434                         i_new, (uint16_t) p->i_dts ); 
    435                 p_block->p_next = p; 
    436                 p->p_prev = p_block; 
    437                 p_sys->p_list = p_block; 
    438                 return true; 
    439             } 
    440  
    441             if( !i_tmp )   /* trash duplicate */ 
    442                 break; 
    443  
    444             /* reordering failed - append the packet to the end of queue */ 
    445             msg_Dbg(p_access, "RTP: sequence changed (or buffer too small) " 
    446                     "new: %d, buffer %d...%d", i_new, (uint16_t) p->i_dts, 
    447                 (uint16_t) p_sys->p_end->i_dts); 
    448             p_sys->p_end->p_next = p_block; 
    449             p_block->p_prev = p_sys->p_end; 
    450             p_sys->p_end = p_block; 
    451             return true; 
    452         } 
    453         p_prev = p; 
    454         p = p->p_prev; 
    455     } 
    456     block_Release( p_block ); 
    457     return false; 
    458 } 
    459  
    460 /***************************************************************************** 
    461  * BlockParseRTP: decapsulate the RTP packet and return it 
    462  *****************************************************************************/ 
    463 static block_t *BlockParseRTP( access_t *p_access, block_t *p_block ) 
    464 { 
    465     int      i_payload_type; 
    466     size_t   i_skip = RTP_HEADER_LEN; 
    467  
    468     if( p_block == NULL ) 
    469         return NULL; 
    470  
    471     if( p_block->i_buffer < RTP_HEADER_LEN ) 
    472     { 
    473         msg_Dbg( p_access, "short RTP packet received" ); 
    474         goto trash; 
    475     } 
    476  
    477     /* Parse the header and make some verifications. 
    478      * See RFC 3550. */ 
    479     // Version number: 
    480     if( ( p_block->p_buffer[0] >> 6 ) != 2) 
    481     { 
    482         msg_Dbg( p_access, "RTP version is %u instead of 2", 
    483                  p_block->p_buffer[0] >> 6 ); 
    484         goto trash; 
    485     } 
    486     // Padding bit: 
    487     uint8_t pad = (p_block->p_buffer[0] & 0x20) 
    488                     ? p_block->p_buffer[p_block->i_buffer - 1] : 0; 
    489     // CSRC count: 
    490     i_skip += (p_block->p_buffer[0] & 0x0F) * 4; 
    491     // Extension header: 
    492     if (p_block->p_buffer[0] & 0x10) /* Extension header */ 
    493     { 
    494         i_skip += 4; 
    495         if ((size_t)p_block->i_buffer < i_skip) 
    496             goto trash; 
    497  
    498         i_skip += 4 * GetWBE( p_block->p_buffer + i_skip - 2 ); 
    499     } 
    500  
    501     i_payload_type    = p_block->p_buffer[1] & 0x7F; 
    502  
    503     /* Remember sequence number in i_dts */ 
    504     p_block->i_pts = mdate(); 
    505     p_block->i_dts = (mtime_t) GetWBE( p_block->p_buffer + 2 ); 
    506  
    507     /* FIXME: use rtpmap */ 
    508     const char *psz_demux = NULL; 
    509  
    510     switch( i_payload_type ) 
    511     { 
    512         case 14: // MPA: MPEG Audio (RFC2250, §3.4) 
    513             i_skip += 4; // 32 bits RTP/MPA header 
    514             psz_demux = "mpga"; 
    515             break; 
    516  
    517         case 32: // MPV: MPEG Video (RFC2250, §3.5) 
    518             i_skip += 4; // 32 bits RTP/MPV header 
    519             if( (size_t)p_block->i_buffer < i_skip ) 
    520                 goto trash; 
    521             if( p_block->p_buffer[i_skip - 3] & 0x4 ) 
    522             { 
    523                 /* MPEG2 Video extension header */ 
    524                 /* TODO: shouldn't we skip this too ? */ 
    525             } 
    526             psz_demux = "mpgv"; 
    527             break; 
    528  
    529         case 33: // MP2: MPEG TS (RFC2250, §2) 
    530             /* plain TS over RTP */ 
    531             psz_demux = "ts"; 
    532             break; 
    533  
    534         case 72: /* muxed SR */ 
    535         case 73: /* muxed RR */ 
    536         case 74: /* muxed SDES */ 
    537         case 75: /* muxed BYE */ 
    538         case 76: /* muxed APP */ 
    539             goto trash; /* ooh! ignoring RTCP is evil! */ 
    540  
    541         default: 
    542             msg_Dbg( p_access, "unsupported RTP payload type: %u", i_payload_type ); 
    543             goto trash; 
    544     } 
    545  
    546     if( (size_t)p_block->i_buffer < (i_skip + pad) ) 
    547         goto trash; 
    548  
    549     /* Remove the RTP header */ 
    550     p_block->i_buffer -= i_skip; 
    551     p_block->p_buffer += i_skip; 
    552  
    553     /* This is the place for deciphering and authentication */ 
    554  
    555     /* Remove padding (at the end) */ 
    556     p_block->i_buffer -= pad; 
    557  
    558 #if 0 
    559     /* Emulate packet loss */ 
    560     if ( (i_sequence_number % 4000) == 0) 
    561     { 
    562         msg_Warn( p_access, "Emulating packet drop" ); 
    563         block_Release( p_block ); 
    564         return NULL; 
    565     } 
    566 #endif 
    567  
    568     if( !p_access->psz_demux || !*p_access->psz_demux ) 
    569     { 
    570         free( p_access->psz_demux ); 
    571         p_access->psz_demux = strdup( psz_demux ); 
    572     } 
    573  
    574     return p_block; 
    575  
    576 trash: 
    577     block_Release( p_block ); 
    578     return NULL; 
    579 } 
    580  
    581 /***************************************************************************** 
    582  * BlockRTP: receives an RTP packet, parses it, queues it queue, 
    583  * then dequeues the oldest packet and returns it to input/demux. 
    584  ****************************************************************************/ 
    585 static block_t *BlockRTP( access_t *p_access ) 
    586 { 
    587     access_sys_t *p_sys = p_access->p_sys; 
    588     block_t *p; 
    589  
    590     while ( !p_sys->p_list || 
    591              ( mdate() - p_sys->p_list->i_pts ) < p_sys->i_rtp_late ) 
    592     { 
    593         p = BlockParseRTP( p_access, 
    594                            p_sys->b_framed_rtp ? BlockTCP( p_access ) 
    595                                                : BlockUDP( p_access ) ); 
    596         if ( !p ) 
    597             return NULL; 
    598  
    599         rtp_ChainInsert( p_access, p ); 
    600     } 
    601  
    602     p = p_sys->p_list; 
    603     p_sys->p_list = p_sys->p_list->p_next; 
    604     p_sys->i_last_seqno++; 
    605     if( p_sys->i_last_seqno != (uint16_t) p->i_dts ) 
    606     { 
    607         msg_Dbg( p_access, "RTP: packet(s) lost, expected %d, got %d", 
    608                  p_sys->i_last_seqno, (uint16_t) p->i_dts ); 
    609         p_sys->i_last_seqno = (uint16_t) p->i_dts; 
    610     } 
    611     p->p_next = NULL; 
    612     return p; 
    613 } 
    614  
    615 /***************************************************************************** 
    616  * BlockPrebufferRTP: waits until we have at least two RTP datagrams, 
    617  * so that we can synchronize the RTP sequence number. 
    618  * This is only useful for non-reliable transport protocols. 
    619  ****************************************************************************/ 
    620 static block_t *BlockPrebufferRTP( access_t *p_access, block_t *p_block ) 
    621 { 
    622     access_sys_t *p_sys = p_access->p_sys; 
    623     mtime_t   i_first = mdate(); 
    624     int       i_count = 0; 
    625     block_t   *p = p_block; 
    626  
    627     if( BlockParseRTP( p_access, p_block ) == NULL ) 
    628         return NULL; 
    629  
    630     for( ;; ) 
    631     { 
    632         mtime_t i_date = mdate(); 
    633  
    634         if( p && rtp_ChainInsert( p_access, p )) 
    635             i_count++; 
    636  
    637         /* Require at least 2 packets in the buffer */ 
    638         if( i_count > 2 && (i_date - i_first) > p_sys->i_rtp_late ) 
    639             break; 
    640  
    641         p = BlockParseRTP( p_access, BlockUDP( p_access ) ); 
    642         if( !p && (i_date - i_first) > p_sys->i_rtp_late ) 
    643         { 
    644             msg_Err( p_access, "error in RTP prebuffering!" ); 
    645             return NULL; 
    646         } 
    647     } 
    648  
    649     msg_Dbg( p_access, "RTP: prebuffered %d packets", i_count - 1 ); 
    650     p_access->info.b_prebuffered = true; 
    651     p = p_sys->p_list; 
    652     p_sys->p_list = p_sys->p_list->p_next; 
    653     p_sys->i_last_seqno = (uint16_t) p->i_dts; 
    654     p->p_next = NULL; 
    655     return p; 
    656 } 
    657  
    658 static block_t *BlockStartRTP( access_t *p_access ) 
    659 { 
    660     p_access->pf_block = BlockRTP; 
    661     return BlockPrebufferRTP( p_access, BlockUDP( p_access ) ); 
    662 }