📄 udp.c
字号:
/***************************************************************************** * Close: close the target *****************************************************************************/static void Close( vlc_object_t * p_this ){ sout_access_out_t *p_access = (sout_access_out_t*)p_this; sout_access_out_sys_t *p_sys = p_access->p_sys; int i; p_sys->p_thread->b_die = 1; for( i = 0; i < 10; i++ ) { block_t *p_dummy = block_New( p_access, p_sys->i_mtu ); p_dummy->i_dts = 0; p_dummy->i_pts = 0; p_dummy->i_length = 0; memset( p_dummy->p_buffer, 0, p_dummy->i_buffer ); block_FifoPut( p_sys->p_thread->p_fifo, p_dummy ); } vlc_thread_join( p_sys->p_thread ); block_FifoRelease( p_sys->p_thread->p_fifo ); block_FifoRelease( p_sys->p_thread->p_empty_blocks ); if( p_sys->p_buffer ) block_Release( p_sys->p_buffer ); net_Close( p_sys->p_thread->i_handle ); vlc_object_detach( p_sys->p_thread ); vlc_object_destroy( p_sys->p_thread ); /* update p_sout->i_out_pace_nocontrol */ p_access->p_sout->i_out_pace_nocontrol--; msg_Dbg( p_access, "udp access output closed" ); free( p_sys );}/***************************************************************************** * Write: standard write on a file descriptor. *****************************************************************************/static int Write( sout_access_out_t *p_access, block_t *p_buffer ){ sout_access_out_sys_t *p_sys = p_access->p_sys; int i_len = 0; while( p_buffer ) { block_t *p_next; int i_packets = 0; if( !p_sys->b_mtu_warning && p_buffer->i_buffer > p_sys->i_mtu ) { msg_Warn( p_access, "packet size > MTU, you should probably " "increase the MTU" ); p_sys->b_mtu_warning = VLC_TRUE; } /* Check if there is enough space in the buffer */ if( p_sys->p_buffer && p_sys->p_buffer->i_buffer + p_buffer->i_buffer > p_sys->i_mtu ) { if( p_sys->p_buffer->i_dts + p_sys->p_thread->i_caching < mdate() ) { msg_Dbg( p_access, "late packet for udp input (" I64Fd ")", mdate() - p_sys->p_buffer->i_dts - p_sys->p_thread->i_caching ); } block_FifoPut( p_sys->p_thread->p_fifo, p_sys->p_buffer ); p_sys->p_buffer = NULL; } i_len += p_buffer->i_buffer; while( p_buffer->i_buffer ) { int i_write = __MIN( p_buffer->i_buffer, p_sys->i_mtu ); i_packets++; if( !p_sys->p_buffer ) { p_sys->p_buffer = NewUDPPacket( p_access, p_buffer->i_dts ); if( !p_sys->p_buffer ) break; } memcpy( p_sys->p_buffer->p_buffer + p_sys->p_buffer->i_buffer, p_buffer->p_buffer, i_write ); p_sys->p_buffer->i_buffer += i_write; p_buffer->p_buffer += i_write; p_buffer->i_buffer -= i_write; if ( p_buffer->i_flags & BLOCK_FLAG_CLOCK ) { if ( p_sys->p_buffer->i_flags & BLOCK_FLAG_CLOCK ) msg_Warn( p_access, "putting two PCRs at once" ); p_sys->p_buffer->i_flags |= BLOCK_FLAG_CLOCK; } if( p_sys->p_buffer->i_buffer == p_sys->i_mtu || i_packets > 1 ) { /* Flush */ if( p_sys->p_buffer->i_dts + p_sys->p_thread->i_caching < mdate() ) { msg_Dbg( p_access, "late packet for udp input (" I64Fd ")", mdate() - p_sys->p_buffer->i_dts - p_sys->p_thread->i_caching ); } block_FifoPut( p_sys->p_thread->p_fifo, p_sys->p_buffer ); p_sys->p_buffer = NULL; } } p_next = p_buffer->p_next; block_Release( p_buffer ); p_buffer = p_next; } return( p_sys->p_thread->b_error ? -1 : i_len );}/***************************************************************************** * WriteRaw: write p_buffer without trying to fill mtu *****************************************************************************/static int WriteRaw( sout_access_out_t *p_access, block_t *p_buffer ){ sout_access_out_sys_t *p_sys = p_access->p_sys; block_t *p_buf; int i_len; while ( p_sys->p_thread->p_empty_blocks->i_depth >= MAX_EMPTY_BLOCKS ) { p_buf = block_FifoGet(p_sys->p_thread->p_empty_blocks); block_Release( p_buf ); } i_len = p_buffer->i_buffer; block_FifoPut( p_sys->p_thread->p_fifo, p_buffer ); return( p_sys->p_thread->b_error ? -1 : i_len );}/***************************************************************************** * Seek: seek to a specific location in a file *****************************************************************************/static int Seek( sout_access_out_t *p_access, off_t i_pos ){ msg_Err( p_access, "UDP sout access cannot seek" ); return -1;}/***************************************************************************** * NewUDPPacket: allocate a new UDP packet of size p_sys->i_mtu *****************************************************************************/static block_t *NewUDPPacket( sout_access_out_t *p_access, mtime_t i_dts){ sout_access_out_sys_t *p_sys = p_access->p_sys; block_t *p_buffer; while ( p_sys->p_thread->p_empty_blocks->i_depth > MAX_EMPTY_BLOCKS ) { p_buffer = block_FifoGet( p_sys->p_thread->p_empty_blocks ); block_Release( p_buffer ); } if( p_sys->p_thread->p_empty_blocks->i_depth == 0 ) { p_buffer = block_New( p_access->p_sout, p_sys->i_mtu ); } else { p_buffer = block_FifoGet(p_sys->p_thread->p_empty_blocks ); p_buffer->i_flags = 0; p_buffer = block_Realloc( p_buffer, 0, p_sys->i_mtu ); } p_buffer->i_dts = i_dts; p_buffer->i_buffer = 0; if( p_sys->b_rtpts ) { mtime_t i_timestamp = p_buffer->i_dts * 9 / 100; /* add rtp/ts header */ p_buffer->p_buffer[0] = 0x80; p_buffer->p_buffer[1] = 0x21; // mpeg2-ts p_buffer->p_buffer[2] = ( p_sys->i_sequence_number >> 8 )&0xff; p_buffer->p_buffer[3] = p_sys->i_sequence_number&0xff; p_sys->i_sequence_number++; p_buffer->p_buffer[4] = ( i_timestamp >> 24 )&0xff; p_buffer->p_buffer[5] = ( i_timestamp >> 16 )&0xff; p_buffer->p_buffer[6] = ( i_timestamp >> 8 )&0xff; p_buffer->p_buffer[7] = i_timestamp&0xff; p_buffer->p_buffer[ 8] = ( p_sys->i_ssrc >> 24 )&0xff; p_buffer->p_buffer[ 9] = ( p_sys->i_ssrc >> 16 )&0xff; p_buffer->p_buffer[10] = ( p_sys->i_ssrc >> 8 )&0xff; p_buffer->p_buffer[11] = p_sys->i_ssrc&0xff; p_buffer->i_buffer = 12; } return p_buffer;}/***************************************************************************** * ThreadWrite: Write a packet on the network at the good time. *****************************************************************************/static void ThreadWrite( vlc_object_t *p_this ){ sout_access_thread_t *p_thread = (sout_access_thread_t*)p_this; mtime_t i_date_last = -1; mtime_t i_to_send = p_thread->i_group; int i_dropped_packets = 0;#if defined(WIN32) || defined(UNDER_CE) char strerror_buf[WINSOCK_STRERROR_SIZE];# define strerror( x ) winsock_strerror( strerror_buf )#endif while( !p_thread->b_die ) { block_t *p_pk; mtime_t i_date, i_sent;#if 0 if( (i++ % 1000)==0 ) { int i = 0; int j = 0; block_t *p_tmp = p_thread->p_empty_blocks->p_first; while( p_tmp ) { p_tmp = p_tmp->p_next; i++;} p_tmp = p_thread->p_fifo->p_first; while( p_tmp ) { p_tmp = p_tmp->p_next; j++;} msg_Err( p_thread, "fifo depth: %d/%d, empty blocks: %d/%d", p_thread->p_fifo->i_depth, j,p_thread->p_empty_blocks->i_depth,i ); }#endif p_pk = block_FifoGet( p_thread->p_fifo ); i_date = p_thread->i_caching + p_pk->i_dts; if( i_date_last > 0 ) { if( i_date - i_date_last > 2000000 ) { if( !i_dropped_packets ) msg_Dbg( p_thread, "mmh, hole ("I64Fd" > 2s) -> drop", i_date - i_date_last ); block_FifoPut( p_thread->p_empty_blocks, p_pk ); i_date_last = i_date; i_dropped_packets++; continue; } else if( i_date - i_date_last < -1000 ) { if( !i_dropped_packets ) msg_Dbg( p_thread, "mmh, packets in the past ("I64Fd")", i_date_last - i_date ); } } i_to_send--; if( !i_to_send || (p_pk->i_flags & BLOCK_FLAG_CLOCK) ) { mwait( i_date ); i_to_send = p_thread->i_group; } if( send( p_thread->i_handle, p_pk->p_buffer, p_pk->i_buffer, 0 ) == -1 ) { msg_Warn( p_thread, "send error: %s", strerror(errno) ); } if( i_dropped_packets ) { msg_Dbg( p_thread, "dropped %i packets", i_dropped_packets ); i_dropped_packets = 0; }#if 1 i_sent = mdate(); if ( i_sent > i_date + 20000 ) { msg_Dbg( p_thread, "packet has been sent too late (" I64Fd ")", i_sent - i_date ); }#endif block_FifoPut( p_thread->p_empty_blocks, p_pk ); i_date_last = i_date; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -