?? ts.c
字號:
csa_Delete( p_sys->csa ); } free( p_sys );}/***************************************************************************** * Capability: *****************************************************************************/static int Capability( sout_mux_t *p_mux, int i_query, void *p_args, void *p_answer ){ switch( i_query ) { case SOUT_MUX_CAP_GET_ADD_STREAM_ANY_TIME: *(vlc_bool_t*)p_answer = VLC_TRUE; return( SOUT_MUX_CAP_ERR_OK ); default: return( SOUT_MUX_CAP_ERR_UNIMPLEMENTED ); }}/***************************************************************************** * AddStream: called for each stream addition *****************************************************************************/static int AddStream( 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; p_input->p_sys = (void*)p_stream = malloc( sizeof( ts_stream_t ) ); /* Init this new stream */ p_stream->i_pid = AllocatePID( p_sys, p_input->p_fmt->i_cat ); p_stream->i_continuity_counter = 0; p_stream->i_decoder_specific_info = 0; p_stream->p_decoder_specific_info = NULL; msg_Dbg( p_mux, "adding input codec=%4.4s pid=%d", (char*)&p_input->p_fmt->i_codec, p_stream->i_pid ); /* All others fields depand on codec */ switch( p_input->p_fmt->i_cat ) { case VIDEO_ES: switch( p_input->p_fmt->i_codec ) { case VLC_FOURCC( 'm', 'p','g', 'v' ): /* TODO: do we need to check MPEG-I/II ? */ p_stream->i_stream_type = 0x02; p_stream->i_stream_id = 0xe0; break; case VLC_FOURCC( 'm', 'p','4', 'v' ): p_stream->i_stream_type = 0x10; p_stream->i_stream_id = 0xfa; p_sys->i_mpeg4_streams++; p_stream->i_es_id = p_stream->i_pid; break; /* XXX dirty dirty but somebody want that : using crapy MS-codec XXX */ /* I didn't want to do that :P */ case VLC_FOURCC( 'H', '2', '6', '3' ): case VLC_FOURCC( 'I', '2', '6', '3' ): case VLC_FOURCC( 'W', 'M', 'V', '2' ): case VLC_FOURCC( 'W', 'M', 'V', '1' ): case VLC_FOURCC( 'D', 'I', 'V', '3' ): case VLC_FOURCC( 'D', 'I', 'V', '2' ): case VLC_FOURCC( 'D', 'I', 'V', '1' ): case VLC_FOURCC( 'M', 'J', 'P', 'G' ): p_stream->i_stream_type = 0xa0; // private p_stream->i_stream_id = 0xa0; // beurk p_stream->i_bih_codec = p_input->p_fmt->i_codec; p_stream->i_bih_width = p_input->p_fmt->video.i_width; p_stream->i_bih_height = p_input->p_fmt->video.i_height; break; default: free( p_stream ); return VLC_EGENERIC; } p_sys->i_video_bound++; break; case AUDIO_ES: switch( p_input->p_fmt->i_codec ) { case VLC_FOURCC( 'm', 'p','g', 'a' ): p_stream->i_stream_type = p_input->p_fmt->audio.i_rate >= 32000 ? 0x03 : 0x04; p_stream->i_stream_id = 0xc0; break; case VLC_FOURCC( 'a', '5','2', ' ' ): p_stream->i_stream_type = 0x81; p_stream->i_stream_id = 0xbd; break; case VLC_FOURCC( 'l', 'p','c', 'm' ): p_stream->i_stream_type = 0x83; p_stream->i_stream_id = 0xbd; break; case VLC_FOURCC( 'd', 't','s', ' ' ): p_stream->i_stream_type = 0x85; p_stream->i_stream_id = 0xbd; break; case VLC_FOURCC( 'm', 'p','4', 'a' ): p_stream->i_stream_type = 0x11; p_stream->i_stream_id = 0xfa; p_sys->i_mpeg4_streams++; p_stream->i_es_id = p_stream->i_pid; break; default: free( p_stream ); return VLC_EGENERIC; } p_sys->i_audio_bound++; break; case SPU_ES: switch( p_input->p_fmt->i_codec ) { case VLC_FOURCC( 's', 'p','u', ' ' ): p_stream->i_stream_type = 0x82; p_stream->i_stream_id = 0xbd; break; default: free( p_stream ); return VLC_EGENERIC; } break; default: free( p_stream ); return VLC_EGENERIC; } 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] ); } } /* 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 ); memcpy( p_stream->p_decoder_specific_info, p_input->p_fmt->p_extra, p_input->p_fmt->i_extra ); } /* 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; /* 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; char *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_sys->i_mpeg4_streams--; } if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pid-video" ) ) ) { int i_pid_video = strtol( val, NULL, 0 ); 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 ); } } if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pid-audio" ) ) ) { int i_pid_audio = strtol( val, NULL, 0 ); 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 ); } } 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 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; int i; /* 1: get enough PES packet for all input */ for( ;; ) { vlc_bool_t b_ok = VLC_TRUE; sout_buffer_t *p_data; /* Accumulate enough data in the pcr stream (>i_caching_delay) */ /* Accumulate enough data in all other stream ( >= length of pcr) */ for( i = 0; i < p_mux->i_nb_inputs; i++ ) { sout_input_t *p_input = p_mux->pp_inputs[i]; ts_stream_t *p_stream = (ts_stream_t*)p_input->p_sys; if( ( p_stream == p_pcr_stream && p_stream->i_pes_length <= p_sys->i_caching_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; } } b_ok = VLC_FALSE; p_data = sout_FifoGet( p_input->p_fifo ); if( p_input->p_fifo->i_depth > 0 ) { sout_buffer_t *p_next = sout_FifoShow( p_input->p_fifo ); p_data->i_length = p_next->i_dts - p_data->i_dts; } if( ( p_pcr_stream->i_pes_dts > 0 && p_data->i_dts - 2000000 > 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_data->i_dts - 2000000 > p_stream->i_pes_dts + p_stream->i_pes_length ) ) { msg_Warn( p_mux, "packet with too strange dts (dts=%lld,old=%lld,pcr=%lld)", p_data->i_dts, p_stream->i_pes_dts, p_pcr_stream->i_pes_dts ); sout_BufferDelete( p_mux->p_sout, 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; 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 { 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 */ E_( EStoPES )( p_mux->p_sout, &p_data, p_data, p_stream->i_stream_id, 1 ); BufferChainAppend( &p_stream->chain_pes, p_data ); } } } if( b_ok ) { break; } } /* save */ i_pcr_dts = p_pcr_stream->i_pes_dts; i_pcr_length = p_pcr_stream->i_pes_length; /* 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; sout_buffer_t *p_pes; /* False for pcr stream but it will be eough 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_size; 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 */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -