[vlc-commits] demux: ts: filter out es according to selection
Francois Cartegnie
git at videolan.org
Fri Mar 6 23:04:17 CET 2015
vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | 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 )
{
More information about the vlc-commits
mailing list