⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 udp.c

📁 uclinux 下的vlc播放器源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
    block_t      *p_block;    /* Read data */    p_block = block_New( p_access, p_sys->i_mtu );    p_block->i_buffer = net_Read( p_access, p_sys->fd, NULL,                                  p_block->p_buffer, p_sys->i_mtu,                                  VLC_FALSE );    if( p_block->i_buffer <= 0 )    {        block_Release( p_block );        return NULL;    }    if( (p_block->i_buffer >= p_sys->i_mtu) && p_sys->b_auto_mtu &&        p_sys->i_mtu < 32767 )    {        /* Increase by 100% */        p_sys->i_mtu *= 2;        msg_Dbg( p_access, "increasing MTU to %d", p_sys->i_mtu );    }    return p_block;}/* * rtp_ChainInsert - insert a p_block in the chain and * look at the sequence numbers. */static inline vlc_bool_t rtp_ChainInsert( access_t *p_access, block_t *p_block ){    access_sys_t *p_sys = (access_sys_t *) p_access->p_sys;    block_t *p_prev = NULL;    block_t *p = p_sys->p_end;    uint16_t i_new = (uint16_t) p_block->i_dts;    uint16_t i_tmp = 0;    if( !p_sys->p_list )    {        p_sys->p_list = p_block;        p_sys->p_end = p_block;        return VLC_TRUE;    }    /* walk through the queue from top down since the new packet is in     most cases just appended to the end */    for( ;; )    {        i_tmp = i_new - (uint16_t) p->i_dts;        if( !i_tmp )   /* trash duplicate */            break;         if ( i_tmp < 32768 )        {   /* insert after this block ( i_new > p->i_dts ) */            p_block->p_next = p->p_next;            p->p_next = p_block;            p_block->p_prev = p;            if (p_prev)            {                p_prev->p_prev = p_block;                msg_Dbg(p_access, "RTP reordering: insert after %d, new %d",                     (uint16_t) p->i_dts, i_new );            }            else             {                p_sys->p_end = p_block;            }            return VLC_TRUE;        }        if( p == p_sys->p_list )        {   /* we've reached bottom of chain */            i_tmp = p_sys->i_last_seqno - i_new;            if( !p_access->info.b_prebuffered || (i_tmp > 32767) )            {                msg_Dbg(p_access, "RTP reordering: prepend %d before %d",                         i_new, (uint16_t) p->i_dts );                p_block->p_next = p;                p->p_prev = p_block;                p_sys->p_list = p_block;                return VLC_TRUE;            }            if( !i_tmp )   /* trash duplicate */                break;                /* reordering failed - append the packet to the end of queue */            msg_Dbg(p_access, "RTP: sequence changed (or buffer too small) "                "new: %d, buffer %d...%d", i_new, (uint16_t) p->i_dts,                 (uint16_t) p_sys->p_end->i_dts);            p_sys->p_end->p_next = p_block;            p_block->p_prev = p_sys->p_end;            p_sys->p_end = p_block;            return VLC_TRUE;        }        p_prev = p;        p = p->p_prev;    }    block_Release( p_block );    return VLC_FALSE;}/***************************************************************************** * BlockParseRTP/BlockRTP: *****************************************************************************/static block_t *BlockParseRTP( access_t *p_access, block_t *p_block ){    int      i_rtp_version;    int      i_CSRC_count;    int      i_payload_type;    int      i_skip = 0;    int      i_extension_flag = 0;    int      i_extension_length = 0;    uint16_t i_sequence_number = 0;    if( p_block == NULL )        return NULL;    if( p_block->i_buffer < RTP_HEADER_LEN )        goto trash;    /* Parse the header and make some verifications.     * See RFC 3550. */    i_rtp_version     = ( p_block->p_buffer[0] & 0xC0 ) >> 6;    i_CSRC_count      = p_block->p_buffer[0] & 0x0F;    i_extension_flag  = p_block->p_buffer[0] & 0x10;    i_payload_type    = p_block->p_buffer[1] & 0x7F;    i_sequence_number = (p_block->p_buffer[2] << 8 ) + p_block->p_buffer[3];    if( i_rtp_version != 2 )        msg_Dbg( p_access, "RTP version is %u, should be 2", i_rtp_version );    if( i_payload_type == 14 || i_payload_type == 32)        i_skip = 4;    else if( i_payload_type !=  33 )        msg_Dbg( p_access, "unsupported RTP payload type (%u)", i_payload_type );    if( i_extension_flag )        i_extension_length = 4 +            4 * ( (p_block->p_buffer[14] << 8) + p_block->p_buffer[15] );    /* Skip header + CSRC extension field n*(32 bits) + extension */    i_skip += RTP_HEADER_LEN + 4*i_CSRC_count + i_extension_length;    if( i_skip >= p_block->i_buffer )        goto trash;    /* Return the packet without the RTP header, remember seqno in i_dts */    p_block->i_buffer -= i_skip;    p_block->p_buffer += i_skip;    p_block->i_pts = mdate();    p_block->i_dts = (mtime_t) i_sequence_number;#if 0    /* Emulate packet loss */    if ( (i_sequence_number % 4000) == 0)    {        msg_Warn( p_access, "Emulating packet drop" );        block_Release( p_block );        return NULL;    }#endif    return p_block;trash:    msg_Warn( p_access, "received a too short packet for RTP" );    block_Release( p_block );    return NULL;}static block_t *BlockPrebufferRTP( access_t *p_access, block_t *p_block ){    access_sys_t *p_sys = p_access->p_sys;    mtime_t   i_first = mdate();    int       i_count = 0;    block_t   *p = p_block;    for( ;; )    {        mtime_t i_date = mdate();        if( p && rtp_ChainInsert( p_access, p ))            i_count++;        /* Require at least 2 packets in the buffer */        if( i_count > 2 && (i_date - i_first) > p_sys->i_rtp_late )            break;        p = BlockParseRTP( p_access, BlockUDP( p_access ));        if( !p && (i_date - i_first) > p_sys->i_rtp_late )         {            msg_Err( p_access, "error in RTP prebuffering!" );            break;        }    }    msg_Dbg( p_access, "RTP: prebuffered %d packets", i_count - 1 );    p_access->info.b_prebuffered = VLC_TRUE;    p = p_sys->p_list;    p_sys->p_list = p_sys->p_list->p_next;    p_sys->i_last_seqno = (uint16_t) p->i_dts;    p->p_next = NULL;    return p;}static block_t *BlockRTP( access_t *p_access ){    access_sys_t *p_sys = p_access->p_sys;    block_t *p;    while ( !p_sys->p_list ||              ( mdate() - p_sys->p_list->i_pts ) < p_sys->i_rtp_late )    {        p = BlockParseRTP( p_access, BlockUDP( p_access ));        if ( !p )             return NULL;        rtp_ChainInsert( p_access, p );    }    p = p_sys->p_list;    p_sys->p_list = p_sys->p_list->p_next;    p_sys->i_last_seqno++;    if( p_sys->i_last_seqno != (uint16_t) p->i_dts )    {        msg_Dbg( p_access, "RTP: packet(s) lost, expected %d, got %d",                 p_sys->i_last_seqno, (uint16_t) p->i_dts );        p_sys->i_last_seqno = (uint16_t) p->i_dts;    }    p->p_next = NULL;    return p;}/***************************************************************************** * BlockChoose: decide between RTP and UDP *****************************************************************************/static block_t *BlockChoose( access_t *p_access ){    block_t *p_block;    int     i_rtp_version;    int     i_CSRC_count;    int     i_payload_type;    if( ( p_block = BlockUDP( p_access ) ) == NULL )        return NULL;    if( p_block->p_buffer[0] == 0x47 )    {        msg_Dbg( p_access, "detected TS over raw UDP" );        p_access->pf_block = BlockUDP;        p_access->info.b_prebuffered = VLC_TRUE;        return p_block;    }    if( p_block->i_buffer < RTP_HEADER_LEN )        return p_block;    /* Parse the header and make some verifications.     * See RFC 3550. */    i_rtp_version  = ( p_block->p_buffer[0] & 0xC0 ) >> 6;    i_CSRC_count   = ( p_block->p_buffer[0] & 0x0F );    i_payload_type = ( p_block->p_buffer[1] & 0x7F );    if( i_rtp_version != 2 )    {        msg_Dbg( p_access, "no supported RTP header detected" );        p_access->pf_block = BlockUDP;        p_access->info.b_prebuffered = VLC_TRUE;        return p_block;    }    switch( i_payload_type )    {        case 33:            msg_Dbg( p_access, "detected TS over RTP" );            p_access->psz_demux = strdup( "ts" );            break;        case 14:            msg_Dbg( p_access, "detected MPEG audio over RTP" );            p_access->psz_demux = strdup( "mpga" );            break;        case 32:            msg_Dbg( p_access, "detected MPEG video over RTP" );            p_access->psz_demux = strdup( "mpgv" );            break;        default:            msg_Dbg( p_access, "no RTP header detected" );            p_access->pf_block = BlockUDP;            p_access->info.b_prebuffered = VLC_TRUE;            return p_block;    }    if( !BlockParseRTP( p_access, p_block )) return NULL;    p_access->pf_block = BlockRTP;    return BlockPrebufferRTP( p_access, p_block );}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -