📄 udp.c
字号:
#endif { msg_Err( p_access->p_sout, "cannot spawn sout access thread" ); vlc_object_destroy( p_sys->p_thread ); return VLC_EGENERIC; } srand( (uint32_t)mdate()); p_sys->p_buffer = NULL; p_sys->i_sequence_number = rand()&0xffff; p_sys->i_ssrc = rand()&0xffffffff; var_Get( p_access, SOUT_CFG_PREFIX "raw", &val ); if( val.b_bool ) p_access->pf_write = WriteRaw; else p_access->pf_write = Write; p_access->pf_seek = Seek; msg_Dbg( p_access, "udp access output opened(%s:%d)", psz_dst_addr, i_dst_port ); free( psz_dst_addr ); /* update p_sout->i_out_pace_nocontrol */ p_access->p_sout->i_out_pace_nocontrol++; return VLC_SUCCESS;}/***************************************************************************** * 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; 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 ); if( p_sys->p_buffer ) block_Release( p_sys->p_buffer ); net_Close( p_sys->p_thread->i_handle ); /* 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; 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 ) { block_FifoPut( p_sys->p_thread->p_fifo, p_sys->p_buffer ); p_sys->p_buffer = NULL; } 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 */ 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 : 0 );}/***************************************************************************** * 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_FifoPut( p_sys->p_thread->p_fifo, p_buffer ); return( p_sys->p_thread->b_error ? -1 : 0 );}/***************************************************************************** * 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; p_buffer = block_New( p_access->p_sout, 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; while( !p_thread->b_die ) { block_t *p_pk; mtime_t i_date, i_sent; 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_Release( p_pk ); i_date_last = i_date; i_dropped_packets++; continue; } else if( i_date - i_date_last < -15000 ) { if( !i_dropped_packets ) msg_Dbg( p_thread, "mmh, packets in the past ("I64Fd")" " -> drop", i_date - i_date_last ); block_Release( p_pk ); i_date_last = i_date; i_dropped_packets++; continue; } } i_sent = mdate(); if( p_thread->i_late > 0 && i_sent > i_date + p_thread->i_late ) { if( !i_dropped_packets ) { msg_Dbg( p_thread, "late packet to send (" I64Fd ") -> drop", i_sent - i_date ); } block_Release( p_pk ); i_date_last = i_date; i_dropped_packets++; continue; } i_to_send--; if ( !i_to_send || (p_pk->i_flags & BLOCK_FLAG_CLOCK) ) { mwait( i_date ); i_to_send = p_thread->i_group; } send( p_thread->i_handle, p_pk->p_buffer, p_pk->i_buffer, 0 ); 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_Release( p_pk ); i_date_last = i_date; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -