📄 ts.c
字号:
break; default: free( p_stream ); return VLC_EGENERIC; } p_stream->i_langs = 1+p_input->p_fmt->i_extra_languages; p_stream->lang = malloc(p_stream->i_langs*3); if( !p_stream->lang ) { p_stream->i_langs = 0; free( p_stream ); return VLC_ENOMEM; } i = 1; p_stream->lang[0] = p_stream->lang[1] = p_stream->lang[2] = '\0'; if( p_input->p_fmt->psz_language ) { char *psz = p_input->p_fmt->psz_language; const iso639_lang_t *pl = NULL; if( strlen( psz ) == 2 ) { pl = GetLang_1( psz ); } else if( strlen( psz ) == 3 ) { pl = GetLang_2B( psz ); if( !strcmp( pl->psz_iso639_1, "??" ) ) { pl = GetLang_2T( psz ); } } if( pl && strcmp( pl->psz_iso639_1, "??" ) ) { p_stream->lang[0] = pl->psz_iso639_2T[0]; p_stream->lang[1] = pl->psz_iso639_2T[1]; p_stream->lang[2] = pl->psz_iso639_2T[2]; msg_Dbg( p_mux, " - lang=%c%c%c", p_stream->lang[0], p_stream->lang[1], p_stream->lang[2] ); } } while( i < p_stream->i_langs ) { if( p_input->p_fmt->p_extra_languages[i-1].psz_language ) { char *psz = p_input->p_fmt->p_extra_languages[i-1].psz_language; const iso639_lang_t *pl = NULL; if( strlen( psz ) == 2 ) { pl = GetLang_1( psz ); } else if( strlen( psz ) == 3 ) { pl = GetLang_2B( psz ); if( !strcmp( pl->psz_iso639_1, "??" ) ) { pl = GetLang_2T( psz ); } } if( pl && strcmp( pl->psz_iso639_1, "??" ) ) { p_stream->lang[i*3+0] = pl->psz_iso639_2T[0]; p_stream->lang[i*3+1] = pl->psz_iso639_2T[1]; p_stream->lang[i*3+2] = pl->psz_iso639_2T[2]; msg_Dbg( p_mux, " - lang=%c%c%c", p_stream->lang[i*3+0], p_stream->lang[i*3+1], p_stream->lang[i*3+2] ); } } i++; } /* 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 ); if( p ) { 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 */ } else p_stream->i_decoder_specific_info = 0; } else { /* Copy extra data (VOL for MPEG-4 and extra BitMapInfoHeader for VFW */ p_stream->i_decoder_specific_info = p_input->p_fmt->i_extra; if( p_stream->i_decoder_specific_info > 0 ) { p_stream->p_decoder_specific_info = malloc( p_stream->i_decoder_specific_info ); if( p_stream->p_decoder_specific_info ) { memcpy( p_stream->p_decoder_specific_info, p_input->p_fmt->p_extra, p_input->p_fmt->i_extra ); } else p_stream->i_decoder_specific_info = 0; } } /* 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_stream->chain_pes ); free(p_stream->lang); 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 ) { int i; for( i = 0; i < p_mux->i_nb_inputs; i++ ) { block_FifoEmpty( p_mux->pp_inputs[i]->p_fifo ); } 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( ;; ) { bool b_ok = 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( block_FifoCount( p_input->p_fifo ) <= 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( block_FifoCount( p_input->p_fifo ) <= 0 ) { /* spu, only one packet is needed */ continue; } else if( p_input->p_fmt->i_cat == SPU_ES ) { /* 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 < INT64_C(100000000) ) ) continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -