📄 ts.c
字号:
i_header_size = 0x24; b_data_alignment = 1; } } else if( p_data->i_length < 0 || p_data->i_length > 2000000 ) { /* FIXME choose a better value, but anyway we * should never have to do that */ p_data->i_length = 1000; } p_stream->i_pes_length += p_data->i_length; if( p_stream->i_pes_dts == 0 ) { p_stream->i_pes_dts = p_data->i_dts; } /* Convert to pes */ if( p_stream->i_stream_id == 0xa0 && p_data->i_pts <= 0 ) { /* XXX yes I know, it's awfull, but it's needed, * so don't remove it ... */ p_data->i_pts = p_data->i_dts; } E_( EStoPES )( p_mux->p_sout, &p_data, p_data, p_input->p_fmt, p_stream->i_stream_id, 1, b_data_alignment, i_header_size, 0 ); BufferChainAppend( &p_stream->chain_pes, p_data ); if( p_sys->b_use_key_frames && p_stream == p_pcr_stream && (p_data->i_flags & BLOCK_FLAG_TYPE_I) && !(p_data->i_flags & BLOCK_FLAG_NO_KEYFRAME) && (p_stream->i_pes_length > 400000) ) { i_shaping_delay = p_stream->i_pes_length; p_stream->b_key_frame = 1; } } } } if( b_ok ) { break; } } /* save */ i_pcr_dts = p_pcr_stream->i_pes_dts; i_pcr_length = p_pcr_stream->i_pes_length; p_pcr_stream->b_key_frame = 0; /* msg_Dbg( p_mux, "starting muxing %lldms", i_pcr_length / 1000 ); */ /* 2: calculate non accurate total size of muxed ts */ i_packet_count = 0; for( i = 0; i < p_mux->i_nb_inputs; i++ ) { ts_stream_t *p_stream = (ts_stream_t*)p_mux->pp_inputs[i]->p_sys; block_t *p_pes; /* False for pcr stream but it will be enough to do PCR algo */ for( p_pes = p_stream->chain_pes.p_first; p_pes != NULL; p_pes = p_pes->p_next ) { int i_size = p_pes->i_buffer; if( p_pes->i_dts + p_pes->i_length > p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length ) { mtime_t i_frag = p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length - p_pes->i_dts; if( i_frag < 0 ) { /* Next stream */ break; } i_size = p_pes->i_buffer * i_frag / p_pes->i_length; } i_packet_count += ( i_size + 183 ) / 184; } } /* add overhead for PCR (not really exact) */ i_packet_count += (8 * i_pcr_length / p_sys->i_pcr_delay + 175) / 176; /* 3: mux PES into TS */ BufferChainInit( &chain_ts ); /* append PAT/PMT -> FIXME with big pcr delay it won't have enough pat/pmt */ GetPAT( p_mux, &chain_ts ); GetPMT( p_mux, &chain_ts ); i_packet_pos = 0; i_packet_count += chain_ts.i_depth; /* msg_Dbg( p_mux, "estimated pck=%d", i_packet_count ); */ for( ;; ) { int i_stream; mtime_t i_dts; ts_stream_t *p_stream; sout_input_t *p_input; block_t *p_ts; vlc_bool_t b_pcr; /* Select stream (lowest dts) */ for( i = 0, i_stream = -1, i_dts = 0; i < p_mux->i_nb_inputs; i++ ) { p_input = p_mux->pp_inputs[i]; p_stream = (ts_stream_t*)p_mux->pp_inputs[i]->p_sys; if( p_stream->i_pes_dts == 0 ) { continue; } if( i_stream == -1 || p_stream->i_pes_dts < i_dts ) { i_stream = i; i_dts = p_stream->i_pes_dts; } } if( i_stream == -1 || i_dts > i_pcr_dts + i_pcr_length ) { break; } p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys; /* do we need to issue pcr */ b_pcr = VLC_FALSE; if( p_stream == p_pcr_stream && i_pcr_dts + i_packet_pos * i_pcr_length / i_packet_count >= p_sys->i_pcr + p_sys->i_pcr_delay ) { b_pcr = VLC_TRUE; p_sys->i_pcr = i_pcr_dts + i_packet_pos * i_pcr_length / i_packet_count; } /* Build the TS packet */ p_ts = TSNew( p_mux, p_stream, b_pcr ); if( p_sys->csa != NULL && (p_input->p_fmt->i_cat != AUDIO_ES || p_sys->b_crypt_audio) ) { p_ts->i_flags |= BLOCK_FLAG_SCRAMBLED; } i_packet_pos++; /* */ BufferChainAppend( &chain_ts, p_ts ); } /* 4: date and send */ TSSchedule( p_mux, &chain_ts, i_pcr_length, i_pcr_dts ); }}#define STD_PES_PAYLOAD 170static block_t *FixPES( sout_mux_t *p_mux, block_fifo_t *p_fifo ){ block_t *p_data; int i_size; p_data = block_FifoShow( p_fifo ); i_size = p_data->i_buffer; if( i_size == STD_PES_PAYLOAD ) { return block_FifoGet( p_fifo ); } else if( i_size > STD_PES_PAYLOAD ) { block_t *p_new = block_New( p_mux, STD_PES_PAYLOAD ); p_mux->p_vlc->pf_memcpy( p_new->p_buffer, p_data->p_buffer, STD_PES_PAYLOAD ); p_new->i_pts = p_data->i_pts; p_new->i_dts = p_data->i_dts; p_new->i_length = p_data->i_length * STD_PES_PAYLOAD / p_data->i_buffer; p_data->i_buffer -= STD_PES_PAYLOAD; p_data->p_buffer += STD_PES_PAYLOAD; p_data->i_pts += p_new->i_length; p_data->i_dts += p_new->i_length; p_data->i_length -= p_new->i_length; p_data->i_flags |= BLOCK_FLAG_NO_KEYFRAME; return p_new; } else { block_t *p_next; int i_copy; p_data = block_FifoGet( p_fifo ); p_data = block_Realloc( p_data, 0, STD_PES_PAYLOAD ); p_next = block_FifoShow( p_fifo ); if ( p_data->i_flags & BLOCK_FLAG_NO_KEYFRAME ) { p_data->i_flags &= ~BLOCK_FLAG_NO_KEYFRAME; p_data->i_pts = p_next->i_pts; p_data->i_dts = p_next->i_dts; } i_copy = __MIN( STD_PES_PAYLOAD - i_size, p_next->i_buffer ); p_mux->p_vlc->pf_memcpy( &p_data->p_buffer[i_size], p_next->p_buffer, i_copy ); p_next->i_pts += p_next->i_length * i_copy / p_next->i_buffer; p_next->i_dts += p_next->i_length * i_copy / p_next->i_buffer; p_next->i_length -= p_next->i_length * i_copy / p_next->i_buffer; p_next->i_buffer -= i_copy; p_next->p_buffer += i_copy; p_next->i_flags |= BLOCK_FLAG_NO_KEYFRAME; if( !p_next->i_buffer ) { p_next = block_FifoGet( p_fifo ); block_Release( p_next ); } return p_data; }}static void TSSchedule( sout_mux_t *p_mux, sout_buffer_chain_t *p_chain_ts, mtime_t i_pcr_length, mtime_t i_pcr_dts ){ sout_mux_sys_t *p_sys = p_mux->p_sys; sout_buffer_chain_t new_chain; int i_packet_count = p_chain_ts->i_depth; int i; BufferChainInit( &new_chain ); if ( i_pcr_length <= 0 ) { i_pcr_length = i_packet_count; } for( i = 0; i < i_packet_count; i++ ) { block_t *p_ts = BufferChainGet( p_chain_ts ); mtime_t i_new_dts = i_pcr_dts + i_pcr_length * i / i_packet_count; BufferChainAppend( &new_chain, p_ts ); if( p_ts->i_dts && p_ts->i_dts + p_sys->i_dts_delay * 2/3 < i_new_dts ) { mtime_t i_max_diff = i_new_dts - p_ts->i_dts; mtime_t i_cut_dts = p_ts->i_dts; p_ts = BufferChainPeek( p_chain_ts ); i++; i_new_dts = i_pcr_dts + i_pcr_length * i / i_packet_count; while ( p_ts != NULL && i_new_dts - p_ts->i_dts >= i_max_diff ) { p_ts = BufferChainGet( p_chain_ts ); i_max_diff = i_new_dts - p_ts->i_dts; i_cut_dts = p_ts->i_dts; BufferChainAppend( &new_chain, p_ts ); p_ts = BufferChainPeek( p_chain_ts ); i++; i_new_dts = i_pcr_dts + i_pcr_length * i / i_packet_count; } msg_Dbg( p_mux, "adjusting rate at "I64Fd"/"I64Fd" (%d/%d)", i_cut_dts - i_pcr_dts, i_pcr_length, new_chain.i_depth, p_chain_ts->i_depth ); if ( new_chain.i_depth ) TSDate( p_mux, &new_chain, i_cut_dts - i_pcr_dts, i_pcr_dts ); if ( p_chain_ts->i_depth ) TSSchedule( p_mux, p_chain_ts, i_pcr_dts + i_pcr_length - i_cut_dts, i_cut_dts ); return; } } if ( new_chain.i_depth ) TSDate( p_mux, &new_chain, i_pcr_length, i_pcr_dts );}static void TSDate( sout_mux_t *p_mux, sout_buffer_chain_t *p_chain_ts, mtime_t i_pcr_length, mtime_t i_pcr_dts ){ sout_mux_sys_t *p_sys = p_mux->p_sys; int i_packet_count = p_chain_ts->i_depth; int i; if ( i_pcr_length / 1000 > 0 ) { int i_bitrate = ((uint64_t)i_packet_count * 188 * 8000) / (uint64_t)(i_pcr_length / 1000); if ( p_sys->i_bitrate_max && p_sys->i_bitrate_max < i_bitrate ) { msg_Warn( p_mux, "max bitrate exceeded at "I64Fd " (%d bi/s for %d pkt in "I64Fd" us)", i_pcr_dts + p_sys->i_shaping_delay * 3 / 2 - mdate(), i_bitrate, i_packet_count, i_pcr_length); }#if 0 else { msg_Dbg( p_mux, "starting at "I64Fd " (%d bi/s for %d packets in "I64Fd" us)", i_pcr_dts + p_sys->i_shaping_delay * 3 / 2 - mdate(), i_bitrate, i_packet_count, i_pcr_length); }#endif } else { /* This shouldn't happen, but happens in some rare heavy load * and packet losses conditions. */ i_pcr_length = i_packet_count; } /* msg_Dbg( p_mux, "real pck=%d", i_packet_count ); */ for( i = 0; i < i_packet_count; i++ ) { block_t *p_ts = BufferChainGet( p_chain_ts ); mtime_t i_new_dts = i_pcr_dts + i_pcr_length * i / i_packet_count; p_ts->i_dts = i_new_dts; p_ts->i_length = i_pcr_length / i_packet_count; if( p_ts->i_flags & BLOCK_FLAG_CLOCK ) { /* msg_Dbg( p_mux, "pcr=%lld ms", p_ts->i_dts / 1000 ); */ TSSetPCR( p_ts, p_ts->i_dts - p_sys->i_dts_delay ); } if( p_ts->i_flags & BLOCK_FLAG_SCRAMBLED ) { csa_Encrypt( p_sys->csa, p_ts->p_buffer, 0 ); } /* latency */ p_ts->i_dts += p_sys->i_shaping_delay * 3 / 2; sout_AccessOutWrite( p_mux->p_access, p_ts ); }}static block_t *TSNew( sout_mux_t *p_mux, ts_stream_t *p_stream, vlc_bool_t b_pcr ){ block_t *p_pes = p_stream->chain_pes.p_first; block_t *p_ts; vlc_bool_t b_new_pes = VLC_FALSE; vlc_bool_t b_adaptation_field = VLC_FALSE; int i_payload_max = 184 - ( b_pcr ? 8 : 0 ); int i_payload; if( p_stream->i_pes_used <= 0 ) { b_new_pes = VLC_TRUE; } i_payload = __MIN( (int)p_pes->i_buffer - p_stream->i_pes_used, i_payload_max ); if( b_pcr || i_payload < i_payload_max ) { b_adaptation_field = VLC_TRUE; } p_ts = block_New( p_mux, 188 ); p_ts->i_dts = p_pes->i_dts; p_ts->p_buffer[0] = 0x47; p_ts->p_buffer[1] = ( b_new_pes ? 0x40 : 0x00 ) | ( ( p_stream->i_pid >> 8 )&0x1f ); p_ts->p_buffer[2] = p_stream->i_pid & 0xff; p_ts->p_buffer[3] = ( b_adaptation_field ? 0x30 : 0x10 ) | p_stream->i_continuity_counter; p_stream->i_continuity_counter = (p_stream->i_continuity_counter+1)%16; if( b_adaptation_field ) { int i; if( b_pcr ) { int i_stuffing = i_payload_max - i_payload;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -