📄 ts.c
字号:
if( p_stream->i_decoder_specific_info > 0 ) { p_stream->p_decoder_specific_info = malloc( p_stream->i_decoder_specific_info ); memcpy( p_stream->p_decoder_specific_info, p_input->p_fmt->p_extra, p_input->p_fmt->i_extra ); } /* Create decoder specific info for subt */ if( p_stream->i_codec == VLC_FOURCC( 's', 'u','b', 't' ) ) { uint8_t *p; p_stream->i_decoder_specific_info = 55; p_stream->p_decoder_specific_info = p = malloc( p_stream->i_decoder_specific_info ); p[0] = 0x10; /* textFormat, 0x10 for 3GPP TS 26.245 */ p[1] = 0x00; /* flags: 1b: associated video info flag 3b: reserved 1b: duration flag 3b: reserved */ p[2] = 52; /* remaining size */ p += 3; p[0] = p[1] = p[2] = p[3] = 0; p+=4; /* display flags */ *p++ = 0; /* horizontal justification (-1: left, 0 center, 1 right) */ *p++ = 1; /* vertical justification (-1: top, 0 center, 1 bottom) */ p[0] = p[1] = p[2] = 0x00; p+=3;/* background rgb */ *p++ = 0xff; /* background a */ p[0] = p[1] = 0; p += 2; /* text box top */ p[0] = p[1] = 0; p += 2; /* text box left */ p[0] = p[1] = 0; p += 2; /* text box bottom */ p[0] = p[1] = 0; p += 2; /* text box right */ p[0] = p[1] = 0; p += 2; /* start char */ p[0] = p[1] = 0; p += 2; /* end char */ p[0] = p[1] = 0; p += 2; /* default font id */ *p++ = 0; /* font style flags */ *p++ = 12; /* font size */ p[0] = p[1] = p[2] = 0x00; p+=3;/* foreground rgb */ *p++ = 0x00; /* foreground a */ p[0] = p[1] = p[2] = 0; p[3] = 22; p += 4; memcpy( p, "ftab", 4 ); p += 4; *p++ = 0; *p++ = 1; /* entry count */ p[0] = p[1] = 0; p += 2; /* font id */ *p++ = 9; /* font name length */ memcpy( p, "Helvetica", 9 ); /* font name */ } /* Init pes chain */ BufferChainInit( &p_stream->chain_pes ); p_stream->i_pes_dts = 0; p_stream->i_pes_length = 0; p_stream->i_pes_used = 0; p_stream->b_key_frame = 0; /* We only change PMT version (PAT isn't changed) */ p_sys->i_pmt_version_number = ( p_sys->i_pmt_version_number + 1 )%32; /* Update pcr_pid */ if( p_input->p_fmt->i_cat != SPU_ES && ( p_sys->i_pcr_pid == 0x1fff || p_input->p_fmt->i_cat == VIDEO_ES ) ) { if( p_sys->p_pcr_input ) { /* There was already a PCR stream, so clean context */ /* FIXME */ } p_sys->i_pcr_pid = p_stream->i_pid; p_sys->p_pcr_input = p_input; msg_Dbg( p_mux, "new PCR PID is %d", p_sys->i_pcr_pid ); } return VLC_SUCCESS;}/***************************************************************************** * DelStream: called before a stream deletion *****************************************************************************/static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input ){ sout_mux_sys_t *p_sys = p_mux->p_sys; ts_stream_t *p_stream; vlc_value_t val; p_stream = (ts_stream_t*)p_input->p_sys; msg_Dbg( p_mux, "removing input pid=%d", p_stream->i_pid ); if( p_sys->i_pcr_pid == p_stream->i_pid ) { int i; /* Find a new pcr stream (Prefer Video Stream) */ p_sys->i_pcr_pid = 0x1fff; p_sys->p_pcr_input = NULL; for( i = 0; i < p_mux->i_nb_inputs; i++ ) { if( p_mux->pp_inputs[i] == p_input ) { continue; } if( p_mux->pp_inputs[i]->p_fmt->i_cat == VIDEO_ES ) { p_sys->i_pcr_pid = ((ts_stream_t*)p_mux->pp_inputs[i]->p_sys)->i_pid; p_sys->p_pcr_input= p_mux->pp_inputs[i]; break; } else if( p_mux->pp_inputs[i]->p_fmt->i_cat != SPU_ES && p_sys->i_pcr_pid == 0x1fff ) { p_sys->i_pcr_pid = ((ts_stream_t*)p_mux->pp_inputs[i]->p_sys)->i_pid; p_sys->p_pcr_input= p_mux->pp_inputs[i]; } } if( p_sys->p_pcr_input ) { /* Empty TS buffer */ /* FIXME */ } msg_Dbg( p_mux, "new PCR PID is %d", p_sys->i_pcr_pid ); } /* Empty all data in chain_pes */ BufferChainClean( p_mux->p_sout, &p_stream->chain_pes ); if( p_stream->p_decoder_specific_info ) { free( p_stream->p_decoder_specific_info ); } if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb || p_stream->i_stream_id == 0xfe ) { p_sys->i_mpeg4_streams--; } var_Get( p_mux, SOUT_CFG_PREFIX "pid-video", &val ); if( val.i_int > 0 ) { int i_pid_video = val.i_int; if ( i_pid_video == p_stream->i_pid ) { p_sys->i_pid_video = i_pid_video; msg_Dbg( p_mux, "freeing video PID %d", i_pid_video ); } } var_Get( p_mux, SOUT_CFG_PREFIX "pid-audio", &val ); if( val.i_int > 0 ) { int i_pid_audio = val.i_int; if ( i_pid_audio == p_stream->i_pid ) { p_sys->i_pid_audio = i_pid_audio; msg_Dbg( p_mux, "freeing audio PID %d", i_pid_audio ); } } var_Get( p_mux, SOUT_CFG_PREFIX "pid-spu", &val ); if( val.i_int > 0 ) { int i_pid_spu = val.i_int; if ( i_pid_spu == p_stream->i_pid ) { p_sys->i_pid_spu = i_pid_spu; msg_Dbg( p_mux, "freeing spu PID %d", i_pid_spu ); } } free( p_stream ); /* We only change PMT version (PAT isn't changed) */ p_sys->i_pmt_version_number++; p_sys->i_pmt_version_number %= 32; return VLC_SUCCESS;}/***************************************************************************** * Mux: Call each time there is new data for at least one stream ***************************************************************************** * *****************************************************************************/static int Mux( sout_mux_t *p_mux ){ sout_mux_sys_t *p_sys = p_mux->p_sys; ts_stream_t *p_pcr_stream; if( p_sys->i_pcr_pid == 0x1fff ) { msg_Dbg( p_mux, "waiting for PCR streams" ); msleep( 1000 ); return VLC_SUCCESS; } p_pcr_stream = (ts_stream_t*)p_sys->p_pcr_input->p_sys; for( ;; ) { sout_buffer_chain_t chain_ts; int i_packet_count; int i_packet_pos; mtime_t i_pcr_dts; mtime_t i_pcr_length; mtime_t i_shaping_delay; int i; if( p_pcr_stream->b_key_frame ) { i_shaping_delay = p_pcr_stream->i_pes_length; } else { i_shaping_delay = p_sys->i_shaping_delay; } /* 1: get enough PES packet for all input */ for( ;; ) { vlc_bool_t b_ok = VLC_TRUE; block_t *p_data; /* Accumulate enough data in the pcr stream (>i_shaping_delay) */ /* Accumulate enough data in all other stream ( >= length of pcr)*/ for( i = -1; i < p_mux->i_nb_inputs; i++ ) { sout_input_t *p_input; ts_stream_t *p_stream; int64_t i_spu_delay = 0; if( i == -1 ) p_input = p_sys->p_pcr_input; else if( p_mux->pp_inputs[i]->p_sys == p_pcr_stream ) continue; else p_input = p_mux->pp_inputs[i]; p_stream = (ts_stream_t*)p_input->p_sys; if( ( p_stream == p_pcr_stream && p_stream->i_pes_length < i_shaping_delay ) || p_stream->i_pes_dts + p_stream->i_pes_length < p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length ) { /* Need more data */ if( p_input->p_fifo->i_depth <= 1 ) { if( p_input->p_fmt->i_cat == AUDIO_ES || p_input->p_fmt->i_cat == VIDEO_ES ) { /* We need more data */ return VLC_SUCCESS; } else if( p_input->p_fifo->i_depth <= 0 ) { /* spu, only one packet is needed */ continue; } else { /* Don't mux the SPU yet if it is too early */ block_t *p_spu = block_FifoShow( p_input->p_fifo ); i_spu_delay = p_spu->i_dts - p_pcr_stream->i_pes_dts; if( i_spu_delay > i_shaping_delay && i_spu_delay < I64C(100000000) ) continue; if ( i_spu_delay >= I64C(100000000) || i_spu_delay < 10000 ) { BufferChainClean( p_mux->p_sout, &p_stream->chain_pes ); p_stream->i_pes_dts = 0; p_stream->i_pes_used = 0; p_stream->i_pes_length = 0; continue; } } } b_ok = VLC_FALSE; if( p_stream == p_pcr_stream || p_input->p_fmt->i_codec != VLC_FOURCC('m', 'p', 'g', 'a') ) p_data = block_FifoGet( p_input->p_fifo ); else p_data = FixPES( p_mux, p_input->p_fifo ); if( p_input->p_fifo->i_depth > 0 && p_input->p_fmt->i_cat != SPU_ES ) { block_t *p_next = block_FifoShow( p_input->p_fifo ); p_data->i_length = p_next->i_dts - p_data->i_dts; } else if( p_input->p_fmt->i_codec != VLC_FOURCC('s', 'u', 'b', 't' ) ) p_data->i_length = 1000; if( ( p_pcr_stream->i_pes_dts > 0 && p_data->i_dts - 10000000 > p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length ) || p_data->i_dts < p_stream->i_pes_dts || ( p_stream->i_pes_dts > 0 && p_input->p_fmt->i_cat != SPU_ES && p_data->i_dts - 10000000 > p_stream->i_pes_dts + p_stream->i_pes_length ) ) { msg_Warn( p_mux, "packet with too strange dts " "(dts="I64Fd",old="I64Fd",pcr="I64Fd")", p_data->i_dts, p_stream->i_pes_dts, p_pcr_stream->i_pes_dts ); block_Release( p_data ); BufferChainClean( p_mux->p_sout, &p_stream->chain_pes ); p_stream->i_pes_dts = 0; p_stream->i_pes_used = 0; p_stream->i_pes_length = 0; if( p_input->p_fmt->i_cat != SPU_ES ) { BufferChainClean( p_mux->p_sout, &p_pcr_stream->chain_pes ); p_pcr_stream->i_pes_dts = 0; p_pcr_stream->i_pes_used = 0; p_pcr_stream->i_pes_length = 0; } } else { int i_header_size = 0; int b_data_alignment = 0; if( p_input->p_fmt->i_cat == SPU_ES ) { if( p_input->p_fmt->i_codec == VLC_FOURCC('s','u','b','t') ) { /* Prepend header */ p_data = block_Realloc( p_data, 2, p_data->i_buffer ); p_data->p_buffer[0] = ( (p_data->i_buffer - 2) >> 8) & 0xff; p_data->p_buffer[1] = ( (p_data->i_buffer - 2) ) & 0xff; /* remove trailling \0 if any */ if( p_data->i_buffer > 2 && p_data->p_buffer[p_data->i_buffer -1] == '\0' ) p_data->i_buffer--; /* Append a empty sub (sub text only) */ if( p_data->i_length > 0 && !( p_data->i_buffer == 1 && *p_data->p_buffer == ' ' ) ) { block_t *p_spu = block_New( p_mux, 3 ); p_spu->i_dts = p_spu->i_pts = p_data->i_dts + p_data->i_length; p_spu->i_length = 1000; p_spu->p_buffer[0] = 0; p_spu->p_buffer[1] = 1; p_spu->p_buffer[2] = ' '; E_(EStoPES)( p_mux->p_sout, &p_spu, p_spu, p_input->p_fmt, p_stream->i_stream_id, 1, 0, 0, 0 ); p_data->p_next = p_spu; } } else if( p_input->p_fmt->i_codec == VLC_FOURCC('t','e','l','x') ) { /* EN 300 472 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -