Commit 0953364d authored by François Cartegnie's avatar François Cartegnie 🤞

demux: ts: rework pmt inheritance and add shared pid support

parent 48a518b8
......@@ -210,6 +210,7 @@ typedef struct
int i_version;
int i_number;
int i_pid_pcr;
bool b_selected;
/* IOD stuff (mpeg4) */
od_descriptor_t *iod;
od_descriptors_t od;
......@@ -231,14 +232,19 @@ typedef struct
} ts_pmt_t;
typedef struct
typedef struct ts_pes_es_t ts_pes_es_t;
struct ts_pes_es_t
{
ts_pmt_t *p_program;
es_format_t fmt;
es_out_id_t *id;
uint16_t i_sl_es_id;
ts_pes_es_t *p_extraes; /* Some private streams encapsulate several ES (eg. DVB subtitles) */
ts_pes_es_t *p_next; /* Next es on same pid from different pmt (shared pid) */
/* J2K stuff */
uint8_t b_interlaced;
} ts_pes_es_t;
};
typedef enum
{
......@@ -248,9 +254,7 @@ typedef enum
typedef struct
{
ts_pes_es_t es;
/* Some private streams encapsulate several ES (eg. DVB subtitles)*/
DECL_ARRAY( ts_pes_es_t * ) extra_es;
ts_pes_es_t *p_es;
uint8_t i_stream_type;
......@@ -316,9 +320,7 @@ struct ts_pid_t
uint8_t i_cc; /* countinuity counter */
uint8_t type;
/* PSI owner (ie PMT -> PAT, ES -> PMT */
uint8_t i_refcount;
ts_pid_t *p_parent;
uint16_t i_refcount;
/* */
union
......@@ -460,18 +462,23 @@ static ts_pat_t *ts_pat_New( demux_t * );
static void ts_pat_Del( demux_t *, ts_pat_t * );
static ts_pmt_t *ts_pmt_New( demux_t * );
static void ts_pmt_Del( demux_t *, ts_pmt_t * );
static ts_pes_t *ts_pes_New( demux_t * );
static ts_pes_es_t * ts_pes_es_New( ts_pmt_t * );
static void ts_pes_Add_es( ts_pes_t *, ts_pes_es_t * );
static ts_pes_es_t * ts_pes_Extract_es( ts_pes_t *, const ts_pmt_t * );
static ts_pes_es_t * ts_pes_Find_es( ts_pes_t *, const ts_pmt_t * );
static size_t ts_pes_Count_es( const ts_pes_es_t *, bool, const ts_pmt_t * );
static ts_pes_t *ts_pes_New( demux_t *, ts_pmt_t * );
static void ts_pes_Del( demux_t *, ts_pes_t * );
static ts_psi_t *ts_psi_New( demux_t * );
static void ts_psi_Del( demux_t *, ts_psi_t * );
/* Helpers */
static ts_pid_t *GetPID( demux_sys_t *, uint16_t i_pid );
static ts_pmt_t * GetProgramByID( demux_sys_t *, int i_program );
static bool PIDReferencedByProgram( const ts_pmt_t *, uint16_t );
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 void UpdateScrambledState( demux_t *p_demux, ts_pid_t *p_pid, bool );
static void UpdatePIDScrambledState( demux_t *p_demux, ts_pid_t *p_pid, bool );
static inline int PIDGet( block_t *p )
{
return ( (p->p_buffer[1]&0x1f)<<8 )|p->p_buffer[2];
......@@ -484,11 +491,11 @@ static void ProgramSetPCR( demux_t *p_demux, ts_pmt_t *p_prg, mtime_t i_pcr );
static block_t* ReadTSPacket( demux_t *p_demux );
static int ProbeStart( demux_t *p_demux, int i_program );
static int ProbeEnd( demux_t *p_demux, int i_program );
static int SeekToTime( demux_t *p_demux, ts_pmt_t *, int64_t time );
static int SeekToTime( demux_t *p_demux, const ts_pmt_t *, int64_t time );
static void ReadyQueuesPostSeek( demux_t *p_demux );
static void PCRHandle( demux_t *p_demux, ts_pid_t *, block_t * );
static void PCRFixHandle( demux_t *, ts_pmt_t *, block_t * );
static int64_t TimeStampWrapAround( ts_pmt_t *, int64_t );
static int64_t TimeStampWrapAround( const ts_pmt_t *, int64_t );
/* MPEG4 related */
static const es_mpeg4_descriptor_t * GetMPEG4DescByEsId( const ts_pmt_t *, uint16_t );
......@@ -499,7 +506,8 @@ static bool SetupISO14496LogicalStream( demux_t *, const decoder_config_descript
#define TS_USER_PMT_NUMBER (0)
static int UserPmt( demux_t *p_demux, const char * );
static int SetPIDFilter( demux_sys_t *, ts_pid_t *, bool b_selected );
static int UpdateHWFilter( demux_sys_t *, ts_pid_t * );
static int SetPIDFilter( demux_sys_t *, ts_pid_t *, bool b_selected );
#define TS_PACKET_SIZE_188 188
#define TS_PACKET_SIZE_192 192
......@@ -1274,7 +1282,7 @@ static int Demux( demux_t *p_demux )
if( (p_pkt->p_buffer[1] & 0x40) && (p_pkt->p_buffer[3] & 0x10) &&
!SCRAMBLED(*p_pid) != !(p_pkt->p_buffer[3] & 0x80) )
{
UpdateScrambledState( p_demux, p_pid, p_pkt->p_buffer[3] & 0x80 );
UpdatePIDScrambledState( p_demux, p_pid, p_pkt->p_buffer[3] & 0x80 );
}
if( !SEEN(p_pid) )
......@@ -1322,6 +1330,7 @@ static int Demux( demux_t *p_demux )
AddAndCreateES( p_demux, p_pid, true );
}
/* Emulate HW filter */
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 */
......@@ -1382,62 +1391,104 @@ static int DVBEventInformation( demux_t *p_demux, int64_t *pi_time, int64_t *pi_
return VLC_EGENERIC;
}
static inline void HasSelectedES( es_out_t *out, const ts_pes_es_t *p_es,
const ts_pmt_t *p_pmt, bool *pb_stream_selected )
{
for( ; p_es && !*pb_stream_selected; p_es = p_es->p_next )
{
if( p_es->id )
es_out_Control( out, ES_OUT_GET_ES_STATE,
p_es->id, pb_stream_selected );
HasSelectedES( out, p_es->p_extraes, p_pmt, pb_stream_selected );
}
}
static void UpdatePESFilters( demux_t *p_demux, bool b_all )
{
demux_sys_t *p_sys = p_demux->p_sys;
ts_pat_t *p_pat = GetPID(p_sys, 0)->u.p_pat;
/* We need 3 pass to avoid loss on deselect/relesect with hw filters and
because pid could be shared and its state altered by another unselected pmt
First clear flag on every referenced pid
Then add flag if non on each selected pmt/pcr and active es
Then commit it at hardware level if any */
/* clear selection flag on every pmt referenced pid */
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;
ts_pid_t *p_pmt_pid = p_pat->programs.p_elems[i];
ts_pmt_t *p_pmt = p_pmt_pid->u.p_pmt;
p_pmt_pid->i_flags &= ~FLAG_FILTERED;
for( int j=0; j< p_pmt->e_streams.i_size; j++ )
p_pmt->e_streams.p_elems[j]->i_flags &= ~FLAG_FILTERED;
GetPID(p_sys, p_pmt->i_pid_pcr)->i_flags &= ~FLAG_FILTERED;
}
/* set selection flag on selected pmt referenced pid with active es */
for( int i=0; i< p_pat->programs.i_size; i++ )
{
ts_pid_t *p_pmt_pid = p_pat->programs.p_elems[i];
ts_pmt_t *p_pmt = p_pmt_pid->u.p_pmt;
if( (p_sys->b_default_selection && !p_sys->b_access_control) || b_all )
b_program_selected = true;
p_pmt->b_selected = true;
else
b_program_selected = ProgramIsSelected( p_sys, p_pmt->i_number );
p_pmt->b_selected = ProgramIsSelected( p_sys, p_pmt->i_number );
SetPIDFilter( p_sys, p_pat->programs.p_elems[i], b_program_selected );
for( int j=0; j<p_pmt->e_streams.i_size; j++ )
if( p_pmt->b_selected )
{
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 )
p_pmt_pid->i_flags |= FLAG_FILTERED;
for( int j=0; j<p_pmt->e_streams.i_size; j++ )
{
es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE,
espid->u.p_pes->es.id, &b_stream_selected );
for( int k=0; !b_stream_selected &&
k< espid->u.p_pes->extra_es.i_size; k++ )
ts_pid_t *espid = p_pmt->e_streams.p_elems[j];
ts_pes_t *p_pes = espid->u.p_pes;
bool b_stream_selected = true;
if( !b_all )
HasSelectedES( p_demux->out, p_pes->p_es, p_pmt, &b_stream_selected );
if( p_pes->p_es->fmt.i_cat == UNKNOWN_ES )
{
if( p_pes->i_stream_type == 0x13 ) /* Object channel */
b_stream_selected = true;
else if( !p_sys->b_es_all )
b_stream_selected = false;
}
if( b_stream_selected )
{
if( espid->u.p_pes->extra_es.p_elems[k]->id )
es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE,
espid->u.p_pes->extra_es.p_elems[k]->id,
&b_stream_selected );
msg_Dbg( p_demux, "enabling pid %d from program %d", espid->i_pid, p_pmt->i_number );
espid->i_flags |= FLAG_FILTERED;
}
}
if( espid->u.p_pes->es.fmt.i_cat == UNKNOWN_ES )
/* Select pcr last in case it is handled by unselected ES */
if( p_pmt->i_pid_pcr > 0 )
{
if( espid->u.p_pes->i_stream_type == 0x13 ) /* Object channel */
b_stream_selected = true;
else if( !p_sys->b_es_all )
b_stream_selected = false;
GetPID(p_sys, p_pmt->i_pid_pcr)->i_flags |= FLAG_FILTERED;
msg_Dbg( p_demux, "enabling pcr pid %d from program %d", p_pmt->i_pid_pcr, p_pmt->i_number );
}
if( b_stream_selected )
msg_Dbg( p_demux, "enabling 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 );
}
}
/* Commit HW changes based on flags */
for( int i=0; i< p_pat->programs.i_size; i++ )
{
ts_pid_t *p_pmt_pid = p_pat->programs.p_elems[i];
ts_pmt_t *p_pmt = p_pmt_pid->u.p_pmt;
/* Select pcr last in case it is handled by unselected ES */
if( p_pmt->i_pid_pcr > 0 )
UpdateHWFilter( p_sys, p_pmt_pid );
for( int j=0; j< p_pmt->e_streams.i_size; j++ )
{
SetPIDFilter( p_sys, GetPID(p_sys, p_pmt->i_pid_pcr), b_program_selected );
if( b_program_selected )
msg_Dbg( p_demux, "enabling pcr pid %d from program %d", p_pmt->i_pid_pcr, p_pmt->i_number );
ts_pid_t *espid = p_pmt->e_streams.p_elems[j];
UpdateHWFilter( p_sys, espid );
if( (espid->i_flags & FLAG_FILTERED) == 0 )
FlushESBuffer( espid->u.p_pes );
}
UpdateHWFilter( p_sys, GetPID(p_sys, p_pmt->i_pid_pcr) );
}
}
......@@ -1449,26 +1500,14 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
int64_t i64;
int64_t *pi64;
int i_int;
ts_pmt_t *p_pmt;
int i_first_program = ( p_sys->programs.i_size ) ? p_sys->programs.p_elems[0] : 0;
const ts_pmt_t *p_pmt = NULL;
const ts_pat_t *p_pat = GetPID(p_sys, 0)->u.p_pat;
if( PREPARSING || !i_first_program || p_sys->b_default_selection )
for( int i=0; i<p_pat->programs.i_size && !p_pmt; i++ )
{
if( likely(GetPID(p_sys, 0)->type == TYPE_PAT) )
{
ts_pat_t *p_pat = GetPID(p_sys, 0)->u.p_pat;
/* Set default program for preparse time (no program has been selected) */
for( int i = 0; i < p_pat->programs.i_size; i++ )
{
assert(p_pat->programs.p_elems[i]->type == TYPE_PMT);
p_pmt = p_pat->programs.p_elems[i]->u.p_pmt;
if( ( p_pmt->pcr.i_first > -1 || p_pmt->pcr.i_first_dts > VLC_TS_INVALID ) && p_pmt->i_last_dts > 0 )
{
i_first_program = p_pmt->i_number;
break;
}
}
}
p_pmt = p_pat->programs.p_elems[i]->u.p_pmt;
if( p_pat->programs.p_elems[i]->u.p_pmt->b_selected )
p_pmt = p_pat->programs.p_elems[i]->u.p_pmt;
}
switch( i_query )
......@@ -1491,7 +1530,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
}
}
if( (p_pmt = GetProgramByID( p_sys, i_first_program )) &&
if( p_pmt &&
p_pmt->pcr.i_first > -1 && p_pmt->i_last_dts > VLC_TS_INVALID &&
p_pmt->pcr.i_current > -1 )
{
......@@ -1519,8 +1558,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
break;
if( p_sys->b_dvb_meta && p_sys->b_access_control &&
!p_sys->b_force_seek_per_percent &&
(p_pmt = GetProgramByID( p_sys, i_first_program )) )
!p_sys->b_force_seek_per_percent && p_pmt )
{
int64_t i_time, i_length;
if( !DVBEventInformation( p_demux, &i_time, &i_length ) &&
......@@ -1533,8 +1571,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
}
}
if( !p_sys->b_force_seek_per_percent &&
(p_pmt = GetProgramByID( p_sys, i_first_program )) &&
if( !p_sys->b_force_seek_per_percent && p_pmt &&
p_pmt->pcr.i_first > -1 && p_pmt->i_last_dts > VLC_TS_INVALID &&
p_pmt->pcr.i_current > -1 )
{
......@@ -1564,9 +1601,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
case DEMUX_SET_TIME:
i64 = (int64_t)va_arg( args, int64_t );
if( p_sys->b_canseek &&
(p_pmt = GetProgramByID( p_sys, i_first_program )) &&
p_pmt->pcr.i_first > -1 &&
if( p_sys->b_canseek && p_pmt && p_pmt->pcr.i_first > -1 &&
!SeekToTime( p_demux, p_pmt, p_pmt->pcr.i_first + TO_SCALE(i64) ) )
{
ReadyQueuesPostSeek( p_demux );
......@@ -1585,8 +1620,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
return VLC_SUCCESS;
}
if( (p_pmt = GetProgramByID( p_sys, i_first_program )) &&
p_pmt->pcr.i_current > -1 && p_pmt->pcr.i_first > -1 )
if( p_pmt && p_pmt->pcr.i_current > -1 && p_pmt->pcr.i_first > -1 )
{
int64_t i_pcr = TimeStampWrapAround( p_pmt, p_pmt->pcr.i_current );
*pi64 = FROM_SCALE(i_pcr - p_pmt->pcr.i_first);
......@@ -1603,7 +1637,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
return VLC_SUCCESS;
}
if( (p_pmt = GetProgramByID( p_sys, i_first_program )) &&
if( p_pmt &&
( p_pmt->pcr.i_first > -1 || p_pmt->pcr.i_first_dts > VLC_TS_INVALID ) &&
p_pmt->i_last_dts > 0 )
{
......@@ -1627,6 +1661,7 @@ 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 */
ARRAY_RESET( p_sys->programs );
if( i_int != -1 )
{
......@@ -1789,7 +1824,7 @@ static int UserPmt( demux_t *p_demux, const char *psz_fmt )
if( p_pmt->i_pid_pcr <= 0 )
p_pmt->i_pid_pcr = i_pid;
es_format_t *fmt = &pid->u.p_pes->es.fmt;
es_format_t *fmt = &pid->u.p_pes->p_es->fmt;
if( psz_arg && strlen( psz_arg ) == 4 )
{
......@@ -1821,7 +1856,7 @@ static int UserPmt( demux_t *p_demux, const char *psz_fmt )
{
msg_Dbg( p_demux, " * es pid=%d fcc=%4.4s", i_pid,
(char*)&fmt->i_codec );
pid->u.p_pes->es.id = es_out_Add( p_demux->out, fmt );
pid->u.p_pes->p_es->id = es_out_Add( p_demux->out, fmt );
p_sys->i_pmt_es++;
}
}
......@@ -1839,6 +1874,15 @@ error:
return VLC_EGENERIC;
}
static int UpdateHWFilter( demux_sys_t *p_sys, ts_pid_t *p_pid )
{
if( !p_sys->b_access_control )
return VLC_EGENERIC;
return stream_Control( p_sys->stream, STREAM_SET_PRIVATE_ID_STATE,
p_pid->i_pid, !!(p_pid->i_flags & FLAG_FILTERED) );
}
static int SetPIDFilter( demux_sys_t *p_sys, ts_pid_t *p_pid, bool b_selected )
{
if( b_selected )
......@@ -1846,11 +1890,7 @@ static int SetPIDFilter( demux_sys_t *p_sys, ts_pid_t *p_pid, bool b_selected )
else
p_pid->i_flags &= ~FLAG_FILTERED;
if( !p_sys->b_access_control )
return VLC_EGENERIC;
return stream_Control( p_sys->stream, STREAM_SET_PRIVATE_ID_STATE,
p_pid->i_pid, b_selected );
return UpdateHWFilter( p_sys, p_pid );
}
static void PIDReset( ts_pid_t *pid )
......@@ -1858,7 +1898,6 @@ static void PIDReset( ts_pid_t *pid )
assert(pid->i_refcount == 0);
pid->i_cc = 0xff;
pid->i_flags &= ~FLAG_SCRAMBLED;
pid->p_parent = NULL;
pid->type = TYPE_FREE;
}
......@@ -1892,7 +1931,7 @@ static bool PIDSetup( demux_t *p_demux, ts_pid_type_t i_type, ts_pid_t *pid, ts_
case TYPE_PES:
PIDReset( pid );
pid->u.p_pes = ts_pes_New( p_demux );
pid->u.p_pes = ts_pes_New( p_demux, p_parent->u.p_pmt );
if( !pid->u.p_pes )
return false;
break;
......@@ -1913,9 +1952,8 @@ static bool PIDSetup( demux_t *p_demux, ts_pid_type_t i_type, ts_pid_t *pid, ts_
pid->i_refcount++;
pid->type = i_type;
pid->p_parent = p_parent;
}
else if( pid->type == i_type && pid->i_refcount < UINT8_MAX )
else if( pid->type == i_type && pid->i_refcount < UINT16_MAX )
{
pid->i_refcount++;
}
......@@ -2127,7 +2165,6 @@ static void ParsePES( demux_t *p_demux, ts_pid_t *pid, block_t *p_pes )
const es_mpeg4_descriptor_t *p_mpeg4desc = NULL;
assert(pid->type == TYPE_PES);
assert(pid->p_parent && pid->p_parent->type == TYPE_PMT);
const int i_max = block_ChainExtract( p_pes, header, 34 );
if ( i_max < 4 )
......@@ -2145,6 +2182,8 @@ static void ParsePES( demux_t *p_demux, ts_pid_t *pid, block_t *p_pes )
return;
}
ts_pes_es_t *p_es = pid->u.p_pes->p_es;
if( ParsePESHeader( VLC_OBJECT(p_demux), (uint8_t*)&header, i_max, &i_skip,
&i_dts, &i_pts, &i_stream_id ) == VLC_EGENERIC )
{
......@@ -2154,27 +2193,26 @@ static void ParsePES( demux_t *p_demux, ts_pid_t *pid, block_t *p_pes )
else
{
if( i_pts != -1 )
i_pts = TimeStampWrapAround( pid->p_parent->u.p_pmt, i_pts );
i_pts = TimeStampWrapAround( p_es->p_program, i_pts );
if( i_dts != -1 )
i_dts = TimeStampWrapAround( pid->p_parent->u.p_pmt, i_dts );
i_dts = TimeStampWrapAround( p_es->p_program, i_dts );
}
if( pid->u.p_pes->es.i_sl_es_id )
p_mpeg4desc = GetMPEG4DescByEsId( pid->p_parent->u.p_pmt,
pid->u.p_pes->es.i_sl_es_id );
if( p_es->i_sl_es_id )
p_mpeg4desc = GetMPEG4DescByEsId( p_es->p_program, p_es->i_sl_es_id );
if( pid->u.p_pes->es.fmt.i_codec == VLC_FOURCC( 'a', '5', '2', 'b' ) ||
pid->u.p_pes->es.fmt.i_codec == VLC_FOURCC( 'd', 't', 's', 'b' ) )
if( p_es->fmt.i_codec == VLC_FOURCC( 'a', '5', '2', 'b' ) ||
p_es->fmt.i_codec == VLC_FOURCC( 'd', 't', 's', 'b' ) )
{
i_skip += 4;
}
else if( pid->u.p_pes->es.fmt.i_codec == VLC_FOURCC( 'l', 'p', 'c', 'b' ) ||
pid->u.p_pes->es.fmt.i_codec == VLC_FOURCC( 's', 'p', 'u', 'b' ) ||
pid->u.p_pes->es.fmt.i_codec == VLC_FOURCC( 's', 'd', 'd', 'b' ) )
else if( p_es->fmt.i_codec == VLC_FOURCC( 'l', 'p', 'c', 'b' ) ||
p_es->fmt.i_codec == VLC_FOURCC( 's', 'p', 'u', 'b' ) ||
p_es->fmt.i_codec == VLC_FOURCC( 's', 'd', 'd', 'b' ) )
{
i_skip += 1;
}
else if( pid->u.p_pes->es.fmt.i_codec == VLC_CODEC_SUBT && p_mpeg4desc )
else if( p_es->fmt.i_codec == VLC_CODEC_SUBT && p_mpeg4desc )
{
const decoder_config_descriptor_t *dcd = &p_mpeg4desc->dec_descr;
......@@ -2230,7 +2268,7 @@ static void ParsePES( demux_t *p_demux, ts_pid_t *pid, block_t *p_pes )
p_pes->i_length = i_length * 100 / 9;
p_block = block_ChainGather( p_pes );
if( pid->u.p_pes->es.fmt.i_codec == VLC_CODEC_SUBT )
if( p_es->fmt.i_codec == VLC_CODEC_SUBT )
{
if( i_pes_size > 0 && p_block->i_buffer > i_pes_size )
{
......@@ -2242,23 +2280,19 @@ static void ParsePES( demux_t *p_demux, ts_pid_t *pid, block_t *p_pes )
return;
p_block->p_buffer[p_block->i_buffer -1] = '\0';
}
else if( pid->u.p_pes->es.fmt.i_codec == VLC_CODEC_TELETEXT )
else if( p_es->fmt.i_codec == VLC_CODEC_TELETEXT )
{
if( p_block->i_pts <= VLC_TS_INVALID && pid->p_parent )
if( p_block->i_pts <= VLC_TS_INVALID )
{
/* Teletext may have missing PTS (ETSI EN 300 472 Annexe A)
* In this case use the last PCR + 40ms */
assert( pid->p_parent->type == TYPE_PMT );
if( likely(pid->p_parent->type == TYPE_PMT) )
{
mtime_t i_pcr = pid->p_parent->u.p_pmt->pcr.i_current;
if( i_pcr > VLC_TS_INVALID )
p_block->i_pts = VLC_TS_0 + i_pcr * 100 / 9 + 40000;
}
mtime_t i_pcr = p_es->p_program->pcr.i_current;
if( i_pcr > VLC_TS_INVALID )
p_block->i_pts = VLC_TS_0 + i_pcr * 100 / 9 + 40000;
}
}
else if( pid->u.p_pes->es.fmt.i_codec == VLC_CODEC_ARIB_A ||
pid->u.p_pes->es.fmt.i_codec == VLC_CODEC_ARIB_C )
else if( p_es->fmt.i_codec == VLC_CODEC_ARIB_A ||
p_es->fmt.i_codec == VLC_CODEC_ARIB_C )
{
if( p_block->i_pts <= VLC_TS_INVALID )
{
......@@ -2273,11 +2307,11 @@ static void ParsePES( demux_t *p_demux, ts_pid_t *pid, block_t *p_pes )
p_block->p_buffer[p_block->i_buffer -1] = '\0';
}
}
else if( pid->u.p_pes->es.fmt.i_codec == VLC_CODEC_OPUS)
else if( p_es->fmt.i_codec == VLC_CODEC_OPUS)
{
p_block = Opus_Parse(p_demux, p_block);
}
else if( pid->u.p_pes->es.fmt.i_codec == VLC_CODEC_JPEG2000 )
else if( p_es->fmt.i_codec == VLC_CODEC_JPEG2000 )
{
if( unlikely(i_stream_id != 0xBD) )
{
......@@ -2286,19 +2320,13 @@ static void ParsePES( demux_t *p_demux, ts_pid_t *pid, block_t *p_pes )
}
else
{
p_block = J2K_Parse( p_demux, p_block, pid->u.p_pes->es.b_interlaced );
p_block = J2K_Parse( p_demux, p_block, p_es->b_interlaced );
}
if( !p_block )
return;
}
if( !pid->p_parent || pid->p_parent->type != TYPE_PMT )
{
block_Release( p_block );
return;
}
ts_pmt_t *p_pmt = pid->p_parent->u.p_pmt;
ts_pmt_t *p_pmt = p_es->p_program;
while (p_block) {
block_t *p_next = p_block->p_next;
......@@ -2307,7 +2335,7 @@ static void ParsePES( demux_t *p_demux, ts_pid_t *pid, block_t *p_pes )
if( !p_pmt->pcr.b_fix_done ) /* Not seen yet */
PCRFixHandle( p_demux, p_pmt, p_block );
if( pid->u.p_pes->es.id && (p_pmt->pcr.i_current > -1 || p_pmt->pcr.b_disable) )
if( p_es->id && (p_pmt->pcr.i_current > -1 || p_pmt->pcr.b_disable) )
{
if( pid->u.p_pes->p_prepcr_outqueue )
{
......@@ -2352,8 +2380,7 @@ static void ParsePES( demux_t *p_demux, ts_pid_t *pid, block_t *p_pes )
if( pid->u.p_pes->i_stream_type == 0x12 &&
((i_stream_id & 0xFE) == 0xFA) /* 0xFA || 0xFB */ )
{
const es_mpeg4_descriptor_t *p_desc =
GetMPEG4DescByEsId( p_pmt, pid->u.p_pes->es.i_sl_es_id );
const es_mpeg4_descriptor_t *p_desc = GetMPEG4DescByEsId( p_pmt, p_es->i_sl_es_id );
if(!p_desc)
{
block_Release( p_block );
......@@ -2388,13 +2415,43 @@ static void ParsePES( demux_t *p_demux, ts_pid_t *pid, block_t *p_pes )
if ( p_block )
{
for( int i = 0; i < pid->u.p_pes->extra_es.i_size; i++ )
ts_pes_es_t *p_es_send = p_es;
while( p_es_send )
{
es_out_Send( p_demux->out, pid->u.p_pes->extra_es.p_elems[i]->id,
block_Duplicate( p_block ) );
if( p_es_send->p_program->b_selected )
{
/* Send a copy to each extra es */
ts_pes_es_t *p_extra_es = p_es_send->p_extraes;
while( p_extra_es )
{
if( p_extra_es->id )
{
block_t *p_dup = block_Duplicate( p_block );
if( p_dup )
es_out_Send( p_demux->out, p_es_send->id, p_dup );
}
p_extra_es = p_extra_es->p_next;
}
if( p_es_send->p_next )
{
if( p_es_send->id )
{
block_t *p_dup = block_Duplicate( p_block );
if( p_dup )
es_out_Send( p_demux->out, p_es_send->id, p_dup );