Commit 2b09f7f0 authored by Francois Cartegnie's avatar 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.
parent 7de965e3
...@@ -343,7 +343,8 @@ enum ...@@ -343,7 +343,8 @@ enum
{ {
FLAGS_NONE = 0, FLAGS_NONE = 0,
FLAG_SEEN = 1, FLAG_SEEN = 1,
FLAG_SCRAMBLED = 2 FLAG_SCRAMBLED = 2,
FLAG_FILTERED = 4
}; };
#define SEEN(x) ((x).i_flags & FLAG_SEEN) #define SEEN(x) ((x).i_flags & FLAG_SEEN)
...@@ -423,6 +424,7 @@ struct demux_sys_t ...@@ -423,6 +424,7 @@ struct demux_sys_t
bool b_user_pmt; bool b_user_pmt;
int i_pmt_es; int i_pmt_es;
bool b_es_all; /* If we need to return all es/programs */
enum enum
{ {
...@@ -495,6 +497,9 @@ static void ts_psi_Del( demux_t *, ts_psi_t * ); ...@@ -495,6 +497,9 @@ static void ts_psi_Del( demux_t *, ts_psi_t * );
/* Helpers */ /* Helpers */
static ts_pmt_t * GetProgramByID( demux_sys_t *, int i_program ); 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 ) static inline int PIDGet( block_t *p )
{ {
return ( (p->p_buffer[1]&0x1f)<<8 )|p->p_buffer[2]; return ( (p->p_buffer[1]&0x1f)<<8 )|p->p_buffer[2];
...@@ -1089,6 +1094,7 @@ static int Open( vlc_object_t *p_this ) ...@@ -1089,6 +1094,7 @@ static int Open( vlc_object_t *p_this )
# undef VLC_DVBPSI_DEMUX_TABLE_INIT # undef VLC_DVBPSI_DEMUX_TABLE_INIT
p_sys->i_pmt_es = 0; p_sys->i_pmt_es = 0;
p_sys->b_es_all = false;
/* Read config */ /* Read config */
p_sys->b_es_id_pid = var_CreateGetBool( p_demux, "ts-es-id-pid" ); 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 ) ...@@ -1302,6 +1308,13 @@ static int Demux( demux_t *p_demux )
break; break;
case TYPE_PES: 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; p_sys->b_end_preparse = true;
if( p_sys->es_creation == DELAY_ES ) /* No longer delay ES since that pid's program sends data */ 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_ ...@@ -1376,6 +1389,45 @@ static int DVBEventInformation( demux_t *p_demux, int64_t *pi_time, int64_t *pi_
return VLC_EGENERIC; 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 ) static int Control( demux_t *p_demux, int i_query, va_list args )
{ {
demux_sys_t *p_sys = p_demux->p_sys; 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 ) ...@@ -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 */ if( i_int != 0 ) /* If not default program */
{ {
/* Deselect/filter current ones */ /* 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 ) if( i_int != -1 )
{ {
p_sys->b_es_all = false;
ARRAY_APPEND( p_sys->programs, i_int ); ARRAY_APPEND( p_sys->programs, i_int );
UpdatePESFilters( p_demux, false );
} }
else if( likely( p_list != NULL ) ) else if( likely( p_list != NULL ) )
{ {
p_sys->b_es_all = false;
for( int i = 0; i < p_list->i_count; i++ ) for( int i = 0; i < p_list->i_count; i++ )
ARRAY_APPEND( p_sys->programs, p_list->p_values[i].i_int ); ARRAY_APPEND( p_sys->programs, p_list->p_values[i].i_int );
UpdatePESFilters( p_demux, false );
} }
else // All ES Mode
/* Select/filter current ones */
for( int i=0; i<p_sys->programs.i_size; i++ )
{ {
msg_Dbg( p_demux, "Program %d in new selection", p_sys->programs.p_elems[i] ); p_sys->b_es_all = true;
SetPrgFilter( p_demux, p_sys->programs.p_elems[i], 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; p_sys->b_default_selection = false;
...@@ -1582,6 +1636,17 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) ...@@ -1582,6 +1636,17 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
return VLC_SUCCESS; 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: case DEMUX_GET_TITLE_INFO:
{ {
struct input_title_t ***v = va_arg( args, struct input_title_t*** ); struct input_title_t ***v = va_arg( args, struct input_title_t*** );
...@@ -1756,6 +1821,11 @@ error: ...@@ -1756,6 +1821,11 @@ error:
static int SetPIDFilter( demux_sys_t *p_sys, ts_pid_t *p_pid, bool b_selected ) 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 ) if( !p_sys->b_access_control )
return VLC_EGENERIC; return VLC_EGENERIC;
...@@ -2720,7 +2790,7 @@ static int ProbeChunk( demux_t *p_demux, int i_program, bool b_end, int64_t *pi_ ...@@ -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 ); 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 && if( i_pid != 0x1FFF && p_sys->pid[i_pid].type == TYPE_PES &&
(p_pkt->p_buffer[1] & 0xC0) == 0x40 && /* Payload start but not corrupt */ (p_pkt->p_buffer[1] & 0xC0) == 0x40 && /* Payload start but not corrupt */
...@@ -3502,10 +3572,8 @@ static void IODFree( iod_descriptor_t *p_iod ) ...@@ -3502,10 +3572,8 @@ static void IODFree( iod_descriptor_t *p_iod )
** libdvbpsi callbacks ** 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++) for(int i=0; i<p_sys->programs.i_size; i++)
if( p_sys->programs.p_elems[i] == i_pgrm ) if( p_sys->programs.p_elems[i] == i_pgrm )
return true; return true;
...@@ -4985,6 +5053,7 @@ static void AddAndCreateES( demux_t *p_demux, ts_pid_t *pid ) ...@@ -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 ); 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; 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 ) else if( p_sys->es_creation == DELAY_ES )
...@@ -5017,6 +5086,7 @@ static void AddAndCreateES( demux_t *p_demux, ts_pid_t *pid ) ...@@ -5017,6 +5086,7 @@ static void AddAndCreateES( demux_t *p_demux, ts_pid_t *pid )
SetPIDFilter( p_sys, pid, true ); 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 ) ...@@ -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", msg_Dbg( p_demux, " * PMT descriptor : CA (0x9) SysID 0x%x",
(p_dr->p_data[0] << 8) | p_dr->p_data[1] ); (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 */ /* Set CAM descrambling */
if( !ProgramIsSelected( p_demux, p_pmt->i_number ) ) if( !ProgramIsSelected( p_sys, p_pmt->i_number ) )
{ {
dvbpsi_pmt_delete( p_dvbpsipmt ); dvbpsi_pmt_delete( p_dvbpsipmt );
} }
...@@ -5446,6 +5513,8 @@ static void PMTCallBack( void *data, dvbpsi_pmt_t *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] ); PIDRelease( p_demux, old_es_rm.p_elems[i] );
ARRAY_RESET( old_es_rm ); ARRAY_RESET( old_es_rm );
UpdatePESFilters( p_demux, p_sys->b_es_all );
if( !p_sys->b_trust_pcr ) if( !p_sys->b_trust_pcr )
{ {
int i_cand = FindPCRCandidate( p_pmt ); int i_cand = FindPCRCandidate( p_pmt );
...@@ -5551,7 +5620,7 @@ static void PATCallBack( void *data, dvbpsi_pat_t *p_dvbpsipat ) ...@@ -5551,7 +5620,7 @@ static void PATCallBack( void *data, dvbpsi_pat_t *p_dvbpsipat )
/* Now select PID at access level */ /* Now select PID at access level */
if( p_sys->programs.i_size == 0 || 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 ) if( p_sys->programs.i_size == 0 )
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment