📄 udp.c
字号:
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 + -