vlc | branch: master | Francois Cartegnie <[email protected]> | Fri Mar 6 22:36:25 2015 +0100| [2b09f7f039e2b9a4292f9838325ba8de2e431d9c] | committer: Francois Cartegnie
demux: ts: filter out es according to selection All ES packets are gathered if there's no access control/dvb filtering, adding lots of memcopy/realloc operations for packets which will be discarded later by ES out. > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=2b09f7f039e2b9a4292f9838325ba8de2e431d9c --- modules/demux/ts.c | 105 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 87 insertions(+), 18 deletions(-) diff --git a/modules/demux/ts.c b/modules/demux/ts.c index 51b6656..a86f1b3 100644 --- a/modules/demux/ts.c +++ b/modules/demux/ts.c @@ -343,7 +343,8 @@ enum { FLAGS_NONE = 0, FLAG_SEEN = 1, - FLAG_SCRAMBLED = 2 + FLAG_SCRAMBLED = 2, + FLAG_FILTERED = 4 }; #define SEEN(x) ((x).i_flags & FLAG_SEEN) @@ -423,6 +424,7 @@ struct demux_sys_t bool b_user_pmt; int i_pmt_es; + bool b_es_all; /* If we need to return all es/programs */ enum { @@ -495,6 +497,9 @@ static void ts_psi_Del( demux_t *, ts_psi_t * ); /* Helpers */ static ts_pmt_t * GetProgramByID( demux_sys_t *, int i_program ); +static bool ProgramIsSelected( demux_sys_t *, uint16_t i_pgrm ); +static void UpdatePESFilters( demux_t *p_demux, bool b_all ); +static inline void FlushESBuffer( ts_pes_t *p_pes ); static inline int PIDGet( block_t *p ) { return ( (p->p_buffer[1]&0x1f)<<8 )|p->p_buffer[2]; @@ -1089,6 +1094,7 @@ static int Open( vlc_object_t *p_this ) # undef VLC_DVBPSI_DEMUX_TABLE_INIT p_sys->i_pmt_es = 0; + p_sys->b_es_all = false; /* Read config */ p_sys->b_es_id_pid = var_CreateGetBool( p_demux, "ts-es-id-pid" ); @@ -1302,6 +1308,13 @@ static int Demux( demux_t *p_demux ) break; case TYPE_PES: + if( !p_sys->b_access_control && !(p_pid->i_flags & FLAG_FILTERED) ) + { + /* That packet is for an unselected ES, don't waste time/memory gathering its data */ + block_Release( p_pkt ); + continue; + } + p_sys->b_end_preparse = true; if( p_sys->es_creation == DELAY_ES ) /* No longer delay ES since that pid's program sends data */ { @@ -1376,6 +1389,45 @@ static int DVBEventInformation( demux_t *p_demux, int64_t *pi_time, int64_t *pi_ return VLC_EGENERIC; } +static void UpdatePESFilters( demux_t *p_demux, bool b_all ) +{ + demux_sys_t *p_sys = p_demux->p_sys; + ts_pat_t *p_pat = p_sys->pid[0].u.p_pat; + for( int i=0; i< p_pat->programs.i_size; i++ ) + { + ts_pmt_t *p_pmt = p_pat->programs.p_elems[i]->u.p_pmt; + bool b_program_selected; + if( (p_sys->b_default_selection && !p_sys->b_access_control) || b_all ) + b_program_selected = true; + else + b_program_selected = ProgramIsSelected( p_sys, p_pmt->i_number ); + + SetPIDFilter( p_sys, p_pat->programs.p_elems[i], b_program_selected ); + if( p_pmt->i_pid_pcr > 0 ) + SetPIDFilter( p_sys, &p_sys->pid[p_pmt->i_pid_pcr], b_program_selected ); + + for( int j=0; j<p_pmt->e_streams.i_size; j++ ) + { + ts_pid_t *espid = p_pmt->e_streams.p_elems[j]; + bool b_stream_selected = b_program_selected; + if( b_program_selected && !b_all && espid->u.p_pes->es.id ) + es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE, + espid->u.p_pes->es.id, &b_stream_selected ); + + if( !p_sys->b_es_all && espid->u.p_pes->es.fmt.i_cat == UNKNOWN_ES ) + b_stream_selected = false; + + if( b_stream_selected ) + msg_Dbg( p_demux, "enablind pid %d from program %d", espid->i_pid, p_pmt->i_number ); + + SetPIDFilter( p_sys, espid, b_stream_selected ); + if( !b_stream_selected ) + FlushESBuffer( espid->u.p_pes ); + } + + } +} + static int Control( demux_t *p_demux, int i_query, va_list args ) { demux_sys_t *p_sys = p_demux->p_sys; @@ -1555,25 +1607,27 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) if( i_int != 0 ) /* If not default program */ { /* Deselect/filter current ones */ - for( int i=0; i<p_sys->programs.i_size; i++ ) - SetPrgFilter( p_demux, p_sys->programs.p_elems[i], false ); - ARRAY_RESET( p_sys->programs ); if( i_int != -1 ) { + p_sys->b_es_all = false; ARRAY_APPEND( p_sys->programs, i_int ); + UpdatePESFilters( p_demux, false ); } else if( likely( p_list != NULL ) ) { + p_sys->b_es_all = false; for( int i = 0; i < p_list->i_count; i++ ) ARRAY_APPEND( p_sys->programs, p_list->p_values[i].i_int ); + UpdatePESFilters( p_demux, false ); } - - /* Select/filter current ones */ - for( int i=0; i<p_sys->programs.i_size; i++ ) + else // All ES Mode { - msg_Dbg( p_demux, "Program %d in new selection", p_sys->programs.p_elems[i] ); - SetPrgFilter( p_demux, p_sys->programs.p_elems[i], true ); + p_sys->b_es_all = true; + ts_pat_t *p_pat = p_sys->pid[0].u.p_pat; + for( int i = 0; i < p_pat->programs.i_size; i++ ) + ARRAY_APPEND( p_sys->programs, p_pat->programs.p_elems[i]->i_pid ); + UpdatePESFilters( p_demux, true ); } p_sys->b_default_selection = false; @@ -1582,6 +1636,17 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) return VLC_SUCCESS; } + case DEMUX_SET_ES: + { + i_int = (int)va_arg( args, int ); + msg_Dbg( p_demux, "DEMUX_SET_ES %d", i_int ); + + if( !p_sys->b_es_all ) /* Won't change anything */ + UpdatePESFilters( p_demux, false ); + + return VLC_SUCCESS; + } + case DEMUX_GET_TITLE_INFO: { struct input_title_t ***v = va_arg( args, struct input_title_t*** ); @@ -1756,6 +1821,11 @@ error: static int SetPIDFilter( demux_sys_t *p_sys, ts_pid_t *p_pid, bool b_selected ) { + if( b_selected ) + p_pid->i_flags |= FLAG_FILTERED; + else + p_pid->i_flags &= ~FLAG_FILTERED; + if( !p_sys->b_access_control ) return VLC_EGENERIC; @@ -2720,7 +2790,7 @@ static int ProbeChunk( demux_t *p_demux, int i_program, bool b_end, int64_t *pi_ } int i_pid = PIDGet( p_pkt ); - p_sys->pid[i_pid].i_flags = FLAG_SEEN; + p_sys->pid[i_pid].i_flags |= FLAG_SEEN; if( i_pid != 0x1FFF && p_sys->pid[i_pid].type == TYPE_PES && (p_pkt->p_buffer[1] & 0xC0) == 0x40 && /* Payload start but not corrupt */ @@ -3502,10 +3572,8 @@ static void IODFree( iod_descriptor_t *p_iod ) ** libdvbpsi callbacks **************************************************************************** ****************************************************************************/ -static bool ProgramIsSelected( demux_t *p_demux, uint16_t i_pgrm ) +static bool ProgramIsSelected( demux_sys_t *p_sys, uint16_t i_pgrm ) { - demux_sys_t *p_sys = p_demux->p_sys; - for(int i=0; i<p_sys->programs.i_size; i++) if( p_sys->programs.p_elems[i] == i_pgrm ) return true; @@ -4985,6 +5053,7 @@ static void AddAndCreateES( demux_t *p_demux, ts_pid_t *pid ) es_out_Add( p_demux->out, &pid->u.p_pes->extra_es.p_elems[i]->fmt ); } p_sys->i_pmt_es += 1 + pid->u.p_pes->extra_es.i_size; + UpdatePESFilters( p_demux, p_sys->b_es_all ); } } else if( p_sys->es_creation == DELAY_ES ) @@ -5017,6 +5086,7 @@ static void AddAndCreateES( demux_t *p_demux, ts_pid_t *pid ) SetPIDFilter( p_sys, pid, true ); } } + UpdatePESFilters( p_demux, p_sys->b_es_all ); } } @@ -5419,13 +5489,10 @@ static void PMTCallBack( void *data, dvbpsi_pmt_t *p_dvbpsipmt ) msg_Dbg( p_demux, " * PMT descriptor : CA (0x9) SysID 0x%x", (p_dr->p_data[0] << 8) | p_dr->p_data[1] ); } - - if( ProgramIsSelected( p_demux, p_pmt->i_number ) && pespid->u.p_pes->es.id != NULL ) - SetPIDFilter( p_sys, pespid, true ); /* Set demux filter */ } /* Set CAM descrambling */ - if( !ProgramIsSelected( p_demux, p_pmt->i_number ) ) + if( !ProgramIsSelected( p_sys, p_pmt->i_number ) ) { dvbpsi_pmt_delete( p_dvbpsipmt ); } @@ -5446,6 +5513,8 @@ static void PMTCallBack( void *data, dvbpsi_pmt_t *p_dvbpsipmt ) PIDRelease( p_demux, old_es_rm.p_elems[i] ); ARRAY_RESET( old_es_rm ); + UpdatePESFilters( p_demux, p_sys->b_es_all ); + if( !p_sys->b_trust_pcr ) { int i_cand = FindPCRCandidate( p_pmt ); @@ -5551,7 +5620,7 @@ static void PATCallBack( void *data, dvbpsi_pat_t *p_dvbpsipat ) /* Now select PID at access level */ if( p_sys->programs.i_size == 0 || - ProgramIsSelected( p_demux, p_program->i_number ) ) + ProgramIsSelected( p_sys, p_program->i_number ) ) { if( p_sys->programs.i_size == 0 ) { _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
