X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fdemux%2Fts.c;h=d420f3a14864c7b9bbec80dd4a48936dd42edd70;hb=224bc2719216162565d06f0db92c5b3925bc7752;hp=eb40eace72f9ba703cc08e92d6dcbaffb21a7980;hpb=b2f2c6f8c479a44cad6128c5cb3c3f9eeb94e1ee;p=vlc diff --git a/modules/demux/ts.c b/modules/demux/ts.c index eb40eace72..d420f3a148 100644 --- a/modules/demux/ts.c +++ b/modules/demux/ts.c @@ -209,7 +209,7 @@ typedef struct uint8_t i_objectTypeIndication; uint8_t i_streamType; - int i_extra; + unsigned i_extra; uint8_t *p_extra; } decoder_config_descriptor_t; @@ -263,6 +263,7 @@ typedef struct mtime_t i_first_dts; mtime_t i_pcroffset; bool b_disable; /* ignore PCR field, use dts */ + bool b_fix_done; } pcr; mtime_t i_last_dts; @@ -343,7 +344,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) @@ -399,13 +401,13 @@ struct demux_sys_t vlc_mutex_t csa_lock; /* TS packet size (188, 192, 204) */ - int i_packet_size; + unsigned i_packet_size; /* Additional TS packet header size (BluRay TS packets have 4-byte header before sync byte) */ - int i_packet_header_size; + unsigned i_packet_header_size; /* how many TS packet we read at once */ - int i_ts_read; + unsigned i_ts_read; bool b_force_seek_per_percent; @@ -423,6 +425,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 { @@ -434,6 +437,8 @@ struct demux_sys_t /* */ bool b_es_id_pid; + uint16_t i_next_extraid; + csa_t *csa; int i_csa_pkt_size; bool b_split_es; @@ -495,20 +500,24 @@ 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 void UpdateScrambledState( 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]; } static bool GatherData( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk ); -static void AddAndCreateES( demux_t *p_demux, ts_pid_t *pid ); +static void AddAndCreateES( demux_t *p_demux, ts_pid_t *pid, bool ); 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 void ReadyQueuesPostSeek( demux_sys_t *p_sys ); +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 ); @@ -518,8 +527,7 @@ static void IODFree( iod_descriptor_t * ); #define TS_USER_PMT_NUMBER (0) static int UserPmt( demux_t *p_demux, const char * ); -static int SetPIDFilter( demux_t *, int i_pid, bool b_selected ); -static void SetPrgFilter( demux_t *, int i_prg, bool b_selected ); +static int SetPIDFilter( demux_sys_t *, ts_pid_t *, bool b_selected ); #define TS_PACKET_SIZE_188 188 #define TS_PACKET_SIZE_192 192 @@ -527,7 +535,7 @@ static void SetPrgFilter( demux_t *, int i_prg, bool b_selected ); #define TS_PACKET_SIZE_MAX 204 #define TS_HEADER_SIZE 4 -static int DetectPacketSize( demux_t *p_demux, int *pi_header_size, int i_offset ) +static int DetectPacketSize( demux_t *p_demux, unsigned *pi_header_size, int i_offset ) { const uint8_t *p_peek; @@ -582,7 +590,7 @@ static int DetectPacketSize( demux_t *p_demux, int *pi_header_size, int i_offset #define TOPFIELD_HEADER_SIZE 3712 -static int DetectPVRHeadersAndHeaderSize( demux_t *p_demux, int *pi_header_size, vdr_info_t *p_vdr ) +static int DetectPVRHeadersAndHeaderSize( demux_t *p_demux, unsigned *pi_header_size, vdr_info_t *p_vdr ) { const uint8_t *p_peek; *pi_header_size = 0; @@ -985,7 +993,8 @@ static int Open( vlc_object_t *p_this ) demux_t *p_demux = (demux_t*)p_this; demux_sys_t *p_sys; - int i_packet_size, i_packet_header_size = 0; + int i_packet_size; + unsigned i_packet_header_size = 0; ts_pid_t *patpid; vdr_info_t vdr = {0}; @@ -1078,9 +1087,9 @@ static int Open( vlc_object_t *p_this ) VLC_DVBPSI_DEMUX_TABLE_INIT(&p_sys->pid[0x12], p_demux); VLC_DVBPSI_DEMUX_TABLE_INIT(&p_sys->pid[0x14], p_demux); if( p_sys->b_access_control && - ( SetPIDFilter( p_demux, 0x11, true ) || - SetPIDFilter( p_demux, 0x14, true ) || - SetPIDFilter( p_demux, 0x12, true ) ) + ( SetPIDFilter( p_sys, &p_sys->pid[0x11], true ) || + SetPIDFilter( p_sys, &p_sys->pid[0x14], true ) || + SetPIDFilter( p_sys, &p_sys->pid[0x12], true ) ) ) p_sys->b_access_control = false; } @@ -1089,9 +1098,11 @@ 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" ); + p_sys->i_next_extraid = 1; p_sys->b_trust_pcr = var_CreateGetBool( p_demux, "ts-trust-pcr" ); @@ -1262,7 +1273,7 @@ static int Demux( demux_t *p_demux ) MissingPATPMTFixup( p_demux ); /* We read at most 100 TS packet or until a frame is completed */ - for( int i_pkt = 0; i_pkt < p_sys->i_ts_read; i_pkt++ ) + for( unsigned i_pkt = 0; i_pkt < p_sys->i_ts_read; i_pkt++ ) { bool b_frame = false; block_t *p_pkt; @@ -1281,6 +1292,22 @@ static int Demux( demux_t *p_demux ) /* Parse the TS packet */ ts_pid_t *p_pid = &p_sys->pid[PIDGet( p_pkt )]; + if( SCRAMBLED(*p_pid) != !!(p_pkt->p_buffer[3] & 0x80) ) + UpdateScrambledState( p_demux, p_pid, p_pkt->p_buffer[3] & 0x80 ); + + if( !SEEN(*p_pid) ) + { + if( p_pid->type == TYPE_FREE ) + msg_Dbg( p_demux, "pid[%d] unknown", p_pid->i_pid ); + p_pid->i_flags |= FLAG_SEEN; + } + + if ( SCRAMBLED(*p_pid) && !p_demux->p_sys->csa ) + { + block_Release( p_pkt ); + continue; + } + /* Probe streams to build PAT/PMT after MIN_PAT_INTERVAL in case we don't see any PAT */ if( !SEEN(p_sys->pid[0]) && (p_pid->probed.i_type == 0 || p_pid->i_pid == p_sys->patfix.i_timesourcepid) && @@ -1295,31 +1322,31 @@ static int Demux( demux_t *p_demux ) { case TYPE_PAT: dvbpsi_packet_push( p_pid->u.p_pat->handle, p_pkt->p_buffer ); + block_Release( p_pkt ); break; case TYPE_PMT: dvbpsi_packet_push( p_pid->u.p_pmt->handle, p_pkt->p_buffer ); + block_Release( p_pkt ); break; case TYPE_PES: p_sys->b_end_preparse = true; + if( p_sys->es_creation == DELAY_ES ) /* No longer delay ES since that pid's program sends data */ { - AddAndCreateES( p_demux, NULL ); + msg_Dbg( p_demux, "Creating delayed ES" ); + AddAndCreateES( p_demux, p_pid, true ); } - b_frame = GatherData( p_demux, p_pid, p_pkt ); - if( p_sys->b_default_selection ) + if( !p_sys->b_access_control && !(p_pid->i_flags & FLAG_FILTERED) ) { - p_sys->b_default_selection = false; - assert(p_sys->programs.i_size == 1); - if( p_sys->programs.p_elems[0] != p_pid->p_parent->u.p_pmt->i_number ) - { - SetPrgFilter( p_demux, p_sys->programs.p_elems[0], false ); - SetPrgFilter( p_demux, p_pid->p_parent->u.p_pmt->i_number, true ); - p_sys->programs.p_elems[0] = p_pid->p_parent->u.p_pmt->i_number; - } + /* That packet is for an unselected ES, don't waste time/memory gathering its data */ + block_Release( p_pkt ); + continue; } + + b_frame = GatherData( p_demux, p_pid, p_pkt ); break; case TYPE_SDT: @@ -1327,20 +1354,16 @@ static int Demux( demux_t *p_demux ) case TYPE_EIT: if( p_sys->b_dvb_meta ) dvbpsi_packet_push( p_pid->u.p_psi->handle, p_pkt->p_buffer ); + block_Release( p_pkt ); break; default: - if( !SEEN(*p_pid) ) - msg_Dbg( p_demux, "pid[%d] unknown", p_pid->i_pid ); - /* We have to handle PCR if present */ PCRHandle( p_demux, p_pid, p_pkt ); block_Release( p_pkt ); break; } - p_pid->i_flags |= FLAG_SEEN; - if( b_frame || ( b_wait_es && p_sys->i_pmt_es > 0 ) ) break; } @@ -1376,6 +1399,50 @@ 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 ); + + for( int j=0; je_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, "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 ); + } + + /* Select pcr last in case it is handled by unselected ES */ + if( p_pmt->i_pid_pcr > 0 ) + { + SetPIDFilter( p_sys, &p_sys->pid[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 ); + } + } +} + static int Control( demux_t *p_demux, int i_query, va_list args ) { demux_sys_t *p_sys = p_demux->p_sys; @@ -1457,7 +1524,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) if( !DVBEventInformation( p_demux, &i_time, &i_length ) && i_length > 0 && !SeekToTime( p_demux, p_pmt, TO_SCALE(i_length) * f ) ) { - ReadyQueuesPostSeek( p_sys ); + ReadyQueuesPostSeek( p_demux ); es_out_Control( p_demux->out, ES_OUT_SET_NEXT_DISPLAY_TIME, TO_SCALE(i_length) * f ); return VLC_SUCCESS; @@ -1473,7 +1540,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) p_pmt->i_last_dts ) - p_pmt->pcr.i_first; if( !SeekToTime( p_demux, p_pmt, p_pmt->pcr.i_first + i_length * f ) ) { - ReadyQueuesPostSeek( p_sys ); + ReadyQueuesPostSeek( p_demux ); es_out_Control( p_demux->out, ES_OUT_SET_NEXT_DISPLAY_TIME, FROM_SCALE(p_pmt->pcr.i_first + i_length * f) ); return VLC_SUCCESS; @@ -1484,7 +1551,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) if( i64 > 0 && stream_Seek( p_sys->stream, (int64_t)(i64 * f) ) == VLC_SUCCESS ) { - ReadyQueuesPostSeek( p_sys ); + ReadyQueuesPostSeek( p_demux ); return VLC_SUCCESS; } break; @@ -1497,7 +1564,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) p_pmt->pcr.i_first > -1 && !SeekToTime( p_demux, p_pmt, p_pmt->pcr.i_first + TO_SCALE(i64) ) ) { - ReadyQueuesPostSeek( p_sys ); + ReadyQueuesPostSeek( p_demux ); es_out_Control( p_demux->out, ES_OUT_SET_NEXT_DISPLAY_TIME, FROM_SCALE(p_pmt->pcr.i_first) + i64 - VLC_TS_0 ); return VLC_SUCCESS; @@ -1555,25 +1622,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; iprograms.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; iprograms.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 +1651,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*** ); @@ -1754,62 +1834,18 @@ error: return VLC_EGENERIC; } -static int SetPIDFilter( demux_t *p_demux, int i_pid, bool b_selected ) +static int SetPIDFilter( demux_sys_t *p_sys, ts_pid_t *p_pid, bool b_selected ) { - demux_sys_t *p_sys = p_demux->p_sys; + 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; return stream_Control( p_sys->stream, STREAM_SET_PRIVATE_ID_STATE, - i_pid, b_selected ); -} - -static void SetPrgFilter( demux_t *p_demux, int i_prg_id, bool b_selected ) -{ - demux_sys_t *p_sys = p_demux->p_sys; - ts_pmt_t *p_pmt = NULL; - int i_pmt_pid = -1; - - /* Search pmt to be unselected */ - if(unlikely(p_sys->pid[0].type != TYPE_PAT)) - return; - - ts_pat_t *p_pat = p_sys->pid[0].u.p_pat; - for( int i = 0; i < p_pat->programs.i_size; i++ ) - { - ts_pid_t *pmtpid = p_pat->programs.p_elems[i]; - assert(pmtpid->type == TYPE_PMT); - - if( pmtpid->u.p_pmt->i_number == i_prg_id ) - { - i_pmt_pid = pmtpid->i_pid; - p_pmt = pmtpid->u.p_pmt; - break; - } - - if( i_pmt_pid > 0 ) - break; - } - if( i_pmt_pid <= 0 ) - return; - assert( p_pmt ); - - p_pmt->pcr.b_disable = !p_sys->b_trust_pcr; - - SetPIDFilter( p_demux, i_pmt_pid, b_selected ); - if( p_pmt->i_pid_pcr > 0 ) - SetPIDFilter( p_demux, p_pmt->i_pid_pcr, b_selected ); - - /* All ES */ - for( int i = 0; i < p_pmt->e_streams.i_size; i++ ) - { - ts_pid_t *pespid = p_pmt->e_streams.p_elems[i]; - assert( pespid->type == TYPE_PES ); - /* We only remove/select es that aren't defined by extra pmt */ - if( pespid->u.p_pes->es.id || !b_selected ) - SetPIDFilter( p_demux, i, b_selected ); - } + p_pid->i_pid, b_selected ); } static void PIDReset( ts_pid_t *pid ) @@ -1938,7 +1974,7 @@ static void PIDRelease( demux_t *p_demux, ts_pid_t *pid ) } - SetPIDFilter( p_demux, pid->i_pid, false ); + SetPIDFilter( p_demux->p_sys, pid, false ); PIDReset( pid ); } } @@ -2025,7 +2061,7 @@ static block_t *Opus_Parse(demux_t *demux, block_t *block) last = &au->p_next; au->i_nb_samples = opus_frame_duration(buf, au_size); - if (end_trim && end_trim <= au->i_nb_samples) + if (end_trim && (uint16_t) end_trim <= au->i_nb_samples) au->i_length = end_trim; /* Blatant abuse of the i_length field. */ else au->i_length = 0; @@ -2072,8 +2108,6 @@ static int ParsePESHeader( demux_t *p_demux, const uint8_t *p_header, size_t i_h { /* mpeg2 PES */ i_skip = p_header[8] + 9; - if( i_header < i_skip ) - return VLC_EGENERIC; if( p_header[7]&0x80 ) /* has pts */ { @@ -2139,9 +2173,6 @@ static int ParsePESHeader( demux_t *p_demux, const uint8_t *p_header, size_t i_h break; } - if( i_header < i_skip ) - return VLC_EGENERIC; - *pi_skip = i_skip; return VLC_SUCCESS; } @@ -2315,15 +2346,17 @@ static void ParsePES( demux_t *p_demux, ts_pid_t *pid, block_t *p_pes ) block_t *p_next = p_block->p_next; p_block->p_next = NULL; - if( p_pmt->pcr.i_first == -1 ) /* Not seen yet */ + if( !p_pmt->pcr.b_fix_done ) /* Not seen yet */ PCRFixHandle( p_demux, p_pmt, p_block ); - if( p_pmt->pcr.i_current > -1 || p_pmt->pcr.b_disable ) + if( pid->u.p_pes->es.id && (p_pmt->pcr.i_current > -1 || p_pmt->pcr.b_disable) ) { if( pid->u.p_pes->p_prepcr_outqueue ) { block_ChainAppend( &pid->u.p_pes->p_prepcr_outqueue, p_block ); p_block = pid->u.p_pes->p_prepcr_outqueue; + p_next = p_block->p_next; + p_block->p_next = NULL; pid->u.p_pes->p_prepcr_outqueue = NULL; } @@ -2367,7 +2400,7 @@ static void ParsePES( demux_t *p_demux, ts_pid_t *pid, block_t *p_pes ) } else { - if( p_pmt->pcr.i_first == -1 ) /* Not seen yet */ + if( !p_pmt->pcr.b_fix_done ) /* Not seen yet */ PCRFixHandle( p_demux, p_pmt, p_block ); block_ChainAppend( &pid->u.p_pes->p_prepcr_outqueue, p_block ); @@ -2491,11 +2524,12 @@ static block_t* ReadTSPacket( demux_t *p_demux ) for( ;; ) { const uint8_t *p_peek; - int i_peek, i_skip = 0; + int i_peek = 0; + unsigned i_skip = 0; i_peek = stream_Peek( p_sys->stream, &p_peek, p_sys->i_packet_size * 10 ); - if( i_peek < p_sys->i_packet_size + 1 ) + if( i_peek < 0 || (unsigned)i_peek < p_sys->i_packet_size + 1 ) { msg_Dbg( p_demux, "eof ?" ); return NULL; @@ -2556,6 +2590,29 @@ static mtime_t GetPCR( block_t *p_pkt ) return i_pcr; } +static void UpdateScrambledState( demux_t *p_demux, ts_pid_t *p_pid, bool b_scrambled ) +{ + if( !SCRAMBLED(*p_pid) == !b_scrambled ) + return; + + msg_Warn( p_demux, "scrambled state changed on pid %d (%d->%d)", + p_pid->i_pid, SCRAMBLED(*p_pid), b_scrambled ); + + p_pid->i_flags |= (b_scrambled) ? FLAG_SCRAMBLED : FLAGS_NONE; + + if( p_pid->type == TYPE_PES && p_pid->u.p_pes->es.id ) + { + for( int i = 0; i < p_pid->u.p_pes->extra_es.i_size; i++ ) + { + if( p_pid->u.p_pes->extra_es.p_elems[i]->id ) + es_out_Control( p_demux->out, ES_OUT_SET_ES_SCRAMBLED_STATE, + p_pid->u.p_pes->extra_es.p_elems[i]->id, b_scrambled ); + } + es_out_Control( p_demux->out, ES_OUT_SET_ES_SCRAMBLED_STATE, + p_pid->u.p_pes->es.id, b_scrambled ); + } +} + static inline void FlushESBuffer( ts_pes_t *p_pes ) { if( p_pes->p_data ) @@ -2567,8 +2624,10 @@ static inline void FlushESBuffer( ts_pes_t *p_pes ) } } -static void ReadyQueuesPostSeek( demux_sys_t *p_sys ) +static void ReadyQueuesPostSeek( demux_t *p_demux ) { + 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++ ) { @@ -2580,6 +2639,17 @@ static void ReadyQueuesPostSeek( demux_sys_t *p_sys ) if( pid->type != TYPE_PES ) continue; + if( pid->u.p_pes->es.id ) + { + block_t *p_block = block_Alloc(1); + if( p_block ) + { + p_block->i_buffer = 0; + p_block->i_flags = BLOCK_FLAG_DISCONTINUITY | BLOCK_FLAG_CORRUPTED; + es_out_Send( p_demux->out, pid->u.p_pes->es.id, p_block ); + } + } + pid->i_cc = 0xff; if( pid->u.p_pes->p_prepcr_outqueue ) @@ -2716,35 +2786,41 @@ static int ProbeChunk( demux_t *p_demux, int i_program, bool b_end, int64_t *pi_ demux_sys_t *p_sys = p_demux->p_sys; int i_count = 0; block_t *p_pkt = NULL; - *pi_pcr = -1; for( ;; ) { + *pi_pcr = -1; + if( i_count++ > PROBE_CHUNK_COUNT || !( p_pkt = ReadTSPacket( p_demux ) ) ) { break; } - int i_pid = PIDGet( p_pkt ); - p_sys->pid[i_pid].i_flags = FLAG_SEEN; + const int i_pid = PIDGet( p_pkt ); + ts_pid_t *p_pid = &p_sys->pid[i_pid]; - 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[3] & 0xD0) == 0x10 /* Has payload but is not encrypted */ - ) + p_pid->i_flags |= FLAG_SEEN; + + if( i_pid != 0x1FFF && (p_pkt->p_buffer[1] & 0x80) == 0 ) /* not corrupt */ { bool b_pcrresult = true; + bool b_adaptfield = p_pkt->p_buffer[3] & 0x20; - if( p_pkt->i_buffer >= 4 + 2 + 5 ) + if( b_adaptfield && p_pkt->i_buffer >= 4 + 2 + 5 ) *pi_pcr = GetPCR( p_pkt ); - if( *pi_pcr == -1 ) + if( *pi_pcr == -1 && + (p_pkt->p_buffer[1] & 0xC0) == 0x40 && /* payload start */ + (p_pkt->p_buffer[3] & 0xD0) == 0x10 && /* Has payload but is not encrypted */ + p_pid->type == TYPE_PES && + p_pid->u.p_pes->es.fmt.i_cat != UNKNOWN_ES + ) { b_pcrresult = false; mtime_t i_dts = -1; mtime_t i_pts = -1; unsigned i_skip = 4; - if ( p_pkt->p_buffer[3] & 0x20 ) // adaptation field + if ( b_adaptfield ) // adaptation field i_skip += 1 + p_pkt->p_buffer[4]; if ( VLC_SUCCESS == ParsePESHeader( p_demux, &p_pkt->p_buffer[i_skip], @@ -2758,27 +2834,32 @@ static int ProbeChunk( demux_t *p_demux, int i_program, bool b_end, int64_t *pi_ } } - if( *pi_pcr != -1 ) // TODO: non ES PCR + if( *pi_pcr != -1 ) { - ts_pid_t *pmtpid = p_sys->pid[i_pid].p_parent; - assert(pmtpid->type == TYPE_PMT); - - if( i_program == 0 || i_program == pmtpid->u.p_pmt->i_number ) + ts_pat_t *p_pat = p_sys->pid[0].u.p_pat; + for( int i=0; iprograms.i_size; i++ ) { - if( b_end ) - { - pmtpid->u.p_pmt->i_last_dts = *pi_pcr; - } - /* Start, only keep first */ - else if( b_pcrresult && pmtpid->u.p_pmt->pcr.i_first == -1 ) - { - pmtpid->u.p_pmt->pcr.i_first = *pi_pcr; - } - else if( pmtpid->u.p_pmt->pcr.i_first_dts < VLC_TS_0 ) + ts_pmt_t *p_pmt = p_pat->programs.p_elems[i]->u.p_pmt; + if( ( p_pmt->i_pid_pcr == p_pid->i_pid || + ( p_pmt->i_pid_pcr == 0x1FFF && p_pid->p_parent == p_pat->programs.p_elems[i] ) ) ) { - pmtpid->u.p_pmt->pcr.i_first_dts = VLC_TS_0 + *pi_pcr * 100 / 9; + if( b_end ) + { + p_pmt->i_last_dts = *pi_pcr; + } + /* Start, only keep first */ + else if( b_pcrresult && p_pmt->pcr.i_first == -1 ) + { + p_pmt->pcr.i_first = *pi_pcr; + } + else if( p_pmt->pcr.i_first_dts < VLC_TS_0 ) + { + p_pmt->pcr.i_first_dts = FROM_SCALE(*pi_pcr); + } + + if( i_program == 0 || i_program == p_pmt->i_number ) + *pb_found = true; } - *pb_found = true; } } } @@ -2855,7 +2936,7 @@ static void ProgramSetPCR( demux_t *p_demux, ts_pmt_t *p_pmt, mtime_t i_pcr ) /* Check if we have enqueued blocks waiting the/before the PCR barrier, and then adapt pcr so they have valid PCR when dequeuing */ - if( p_pmt->pcr.i_current == -1 ) + if( p_pmt->pcr.i_current == -1 && p_pmt->pcr.b_fix_done ) { mtime_t i_mindts = -1; @@ -2921,16 +3002,11 @@ static void PCRHandle( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk ) if( p_pmt->i_pid_pcr == 0x1FFF ) /* That program has no dedicated PCR pid ISO/IEC 13818-1 2.4.4.9 */ { - if( pid->p_parent ) /* PCR shall be on pid itself */ + if( pid->p_parent == p_pat->programs.p_elems[i] ) /* PCR shall be on pid itself */ { /* ? update PCR for the whole group program ? */ ProgramSetPCR( p_demux, p_pmt, i_program_pcr ); } - else - { - msg_Warn(p_demux, "discarding PCR update from pid %d which has no owner", pid->i_pid); - } - break; } else /* set PCR provided by current pid to program(s) referencing it */ { @@ -2984,23 +3060,29 @@ static int FindPCRCandidate( ts_pmt_t *p_pmt ) return 0x1FFF; } +/* Tries to reselect a new PCR when none has been received */ static void PCRFixHandle( demux_t *p_demux, ts_pmt_t *p_pmt, block_t *p_block ) { - if( p_pmt->pcr.i_first > -1 || p_pmt->pcr.b_disable ) + if ( p_pmt->pcr.b_disable || p_pmt->pcr.b_fix_done ) + { return; - + } /* Record the first data packet timestamp in case there wont be any PCR */ - if( !p_pmt->pcr.i_first_dts ) + else if( !p_pmt->pcr.i_first_dts ) { p_pmt->pcr.i_first_dts = p_block->i_dts; } - else if( p_block->i_dts - p_pmt->pcr.i_first_dts > CLOCK_FREQ / 2 ) /* "shall not exceed 100ms" */ + else if( p_block->i_dts - p_pmt->pcr.i_first_dts > CLOCK_FREQ / 2 ) /* "PCR repeat rate shall not exceed 100ms" */ { - int i_cand = FindPCRCandidate( p_pmt ); - p_pmt->i_pid_pcr = i_cand; - p_pmt->pcr.b_disable = true; /* So we do not wait packet PCR flag as there might be none on the pid */ - msg_Warn( p_demux, "No PCR received for program %d, set up workaround using pid %d", - p_pmt->i_number, i_cand ); + if( p_pmt->pcr.i_current < 0 ) + { + int i_cand = FindPCRCandidate( p_pmt ); + p_pmt->i_pid_pcr = i_cand; + msg_Warn( p_demux, "No PCR received for program %d, set up workaround using pid %d", + p_pmt->i_number, i_cand ); + UpdatePESFilters( p_demux, p_demux->p_sys->b_es_all ); + p_pmt->pcr.b_fix_done = true; + } } } @@ -3008,7 +3090,6 @@ static bool GatherData( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk ) { const uint8_t *p = p_bk->p_buffer; const bool b_unit_start = p[1]&0x40; - const bool b_scrambled = p[3]&0x80; const bool b_adaptation = p[3]&0x20; const bool b_payload = p[3]&0x10; const int i_cc = p[3]&0x0f; /* continuity counter */ @@ -3108,29 +3189,12 @@ static bool GatherData( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk ) PCRHandle( p_demux, pid, p_bk ); - if( i_skip >= 188 || pid->u.p_pes->es.id == NULL ) + if( i_skip >= 188 ) { block_Release( p_bk ); return i_ret; } - /* */ - if( !SCRAMBLED(*pid) != !b_scrambled ) - { - msg_Warn( p_demux, "scrambled state changed on pid %d (%d->%d)", - pid->i_pid, SCRAMBLED(*pid), b_scrambled ); - - pid->i_flags |= (b_scrambled) ? FLAG_SCRAMBLED : FLAGS_NONE; - - for( int i = 0; i < pid->u.p_pes->extra_es.i_size; i++ ) - { - es_out_Control( p_demux->out, ES_OUT_SET_ES_SCRAMBLED_STATE, - pid->u.p_pes->extra_es.p_elems[i]->id, b_scrambled ); - } - es_out_Control( p_demux->out, ES_OUT_SET_ES_SCRAMBLED_STATE, - pid->u.p_pes->es.id, b_scrambled ); - } - /* We have to gather it */ p_bk->p_buffer += i_skip; p_bk->i_buffer -= i_skip; @@ -3285,7 +3349,7 @@ static void PIDFillFormat( es_format_t *fmt, int i_stream_type ) /***************************************************************************** * MP4 specific functions (IOD parser) *****************************************************************************/ -static int IODDescriptorLength( int *pi_data, uint8_t **pp_data ) +static unsigned IODDescriptorLength( unsigned *pi_data, uint8_t **pp_data ) { unsigned int i_b; unsigned int i_len = 0; @@ -3304,9 +3368,9 @@ static int IODDescriptorLength( int *pi_data, uint8_t **pp_data ) return i_len; } -static int IODGetBytes( int *pi_data, uint8_t **pp_data, size_t bytes ) +static unsigned IODGetBytes( unsigned *pi_data, uint8_t **pp_data, size_t bytes ) { - uint32_t res = 0; + unsigned res = 0; while( *pi_data > 0 && bytes-- ) { res <<= 8; @@ -3318,9 +3382,9 @@ static int IODGetBytes( int *pi_data, uint8_t **pp_data, size_t bytes ) return res; } -static char* IODGetURL( int *pi_data, uint8_t **pp_data ) +static char* IODGetURL( unsigned *pi_data, uint8_t **pp_data ) { - int len = IODGetBytes( pi_data, pp_data, 1 ); + unsigned len = IODGetBytes( pi_data, pp_data, 1 ); if (len > *pi_data) len = *pi_data; char *url = strndup( (char*)*pp_data, len ); @@ -3329,7 +3393,7 @@ static char* IODGetURL( int *pi_data, uint8_t **pp_data ) return url; } -static iod_descriptor_t *IODNew( int i_data, uint8_t *p_data ) +static iod_descriptor_t *IODNew( unsigned i_data, uint8_t *p_data ) { uint8_t i_iod_tag, i_iod_label, byte1, byte2, byte3; @@ -3390,17 +3454,17 @@ static iod_descriptor_t *IODNew( int i_data, uint8_t *p_data ) IODGetBytes( &i_data, &p_data, 1 ); /* visual */ IODGetBytes( &i_data, &p_data, 1 ); /* graphics */ - int i_length = 0; - int i_data_sav = i_data; + unsigned i_length = 0; + unsigned i_data_sav = i_data; uint8_t *p_data_sav = p_data; - for (int i = 0; i_data > 0 && i < ES_DESCRIPTOR_COUNT; i++) + for (unsigned i = 0; i_data > 0 && i < ES_DESCRIPTOR_COUNT; i++) { es_mpeg4_descriptor_t *es_descr = &p_iod->es_descr[i]; p_data = p_data_sav + i_length; i_data = i_data_sav - i_length; - int i_tag = IODGetBytes( &i_data, &p_data, 1 ); + uint8_t i_tag = IODGetBytes( &i_data, &p_data, 1 ); i_length = IODDescriptorLength( &i_data, &p_data ); i_data_sav = i_data; @@ -3415,7 +3479,7 @@ static iod_descriptor_t *IODNew( int i_data, uint8_t *p_data ) } es_descr->i_es_id = IODGetBytes( &i_data, &p_data, 2 ); - int i_flags = IODGetBytes( &i_data, &p_data, 1 ); + uint8_t i_flags = IODGetBytes( &i_data, &p_data, 1 ); bool b_streamDependenceFlag = ( i_flags >> 7 )&0x01; if( b_streamDependenceFlag ) IODGetBytes( &i_data, &p_data, 2 ); /* dependOn_es_id */ @@ -3432,7 +3496,7 @@ static iod_descriptor_t *IODNew( int i_data, uint8_t *p_data ) ts_debug( "\n* ERR missing DecoderConfigDescr" ); continue; } - int i_config_desc_length = IODDescriptorLength( &i_data, &p_data ); /* DecoderConfigDescr_length */ + unsigned i_config_desc_length = IODDescriptorLength( &i_data, &p_data ); /* DecoderConfigDescr_length */ decoder_config_descriptor_t *dec_descr = &es_descr->dec_descr; dec_descr->i_objectTypeIndication = IODGetBytes( &i_data, &p_data, 1 ); i_flags = IODGetBytes( &i_data, &p_data, 1 ); @@ -3508,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; iprograms.i_size; i++) if( p_sys->programs.p_elems[i] == i_pgrm ) return true; @@ -4213,7 +4275,7 @@ static void PMTSetupEsISO14496( demux_t *p_demux, ts_pes_es_t *p_es, if( p_fmt->i_cat != UNKNOWN_ES ) { - p_fmt->i_extra = dcd->i_extra; + p_fmt->i_extra = __MIN(dcd->i_extra, INT32_MAX); if( p_fmt->i_extra > 0 ) { p_fmt->p_extra = malloc( p_fmt->i_extra ); @@ -4341,7 +4403,7 @@ static void PMTSetupEsTeletext( demux_t *p_demux, ts_pes_t *p_pes, } else { - p_page_es = malloc( sizeof(*p_page_es) ); + p_page_es = calloc( 1, sizeof(*p_page_es) ); if( !p_page_es ) break; @@ -4969,35 +5031,43 @@ static void PMTParseEsIso639( demux_t *p_demux, ts_pes_es_t *p_es, #endif } -static void AddAndCreateES( demux_t *p_demux, ts_pid_t *pid ) +static inline void SetExtraESGroupAndID( demux_sys_t *p_sys, es_format_t *p_fmt, + const es_format_t *p_parent_fmt ) +{ + if ( p_sys->b_es_id_pid ) /* pid is 13 bits */ + p_fmt->i_id = (p_sys->i_next_extraid++ << 13) | p_parent_fmt->i_id; + p_fmt->i_group = p_parent_fmt->i_group; +} + +static void AddAndCreateES( demux_t *p_demux, ts_pid_t *pid, bool b_create_delayed ) { demux_sys_t *p_sys = p_demux->p_sys; - bool b_create_delayed = false; - if( pid ) + if( b_create_delayed ) + p_sys->es_creation = CREATE_ES; + + if( pid && p_sys->es_creation == CREATE_ES ) { - if( SEEN(*pid) && p_sys->es_creation == DELAY_ES ) + /* FIXME: other owners / shared pid */ + pid->u.p_pes->es.id = es_out_Add( p_demux->out, &pid->u.p_pes->es.fmt ); + for( int i = 0; i < pid->u.p_pes->extra_es.i_size; i++ ) { - p_sys->es_creation = CREATE_ES; - b_create_delayed = true; + es_format_t *p_fmt = &pid->u.p_pes->extra_es.p_elems[i]->fmt; + SetExtraESGroupAndID( p_sys, p_fmt, &pid->u.p_pes->es.fmt ); + pid->u.p_pes->extra_es.p_elems[i]->id = es_out_Add( p_demux->out, p_fmt ); } + p_sys->i_pmt_es += 1 + pid->u.p_pes->extra_es.i_size; - if( p_sys->es_creation == CREATE_ES ) + /* Update the default program == first created ES group */ + if( p_sys->b_default_selection ) { - pid->u.p_pes->es.id = es_out_Add( p_demux->out, &pid->u.p_pes->es.fmt ); - for( int i = 0; i < pid->u.p_pes->extra_es.i_size; i++ ) - { - pid->u.p_pes->extra_es.p_elems[i]->id = - 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->b_default_selection = false; + assert(p_sys->programs.i_size == 1); + if( p_sys->programs.p_elems[0] != pid->p_parent->u.p_pmt->i_number ) + p_sys->programs.p_elems[0] = pid->p_parent->u.p_pmt->i_number; + msg_Dbg( p_demux, "Default program is %d", pid->p_parent->u.p_pmt->i_number ); } } - else if( p_sys->es_creation == DELAY_ES ) - { - p_sys->es_creation = CREATE_ES; - b_create_delayed = true; - } if( b_create_delayed ) { @@ -5014,16 +5084,16 @@ static void AddAndCreateES( demux_t *p_demux, ts_pid_t *pid ) pid->u.p_pes->es.id = es_out_Add( p_demux->out, &pid->u.p_pes->es.fmt ); for( int k = 0; k < pid->u.p_pes->extra_es.i_size; k++ ) { - pid->u.p_pes->extra_es.p_elems[k]->id = - es_out_Add( p_demux->out, &pid->u.p_pes->extra_es.p_elems[k]->fmt ); + es_format_t *p_fmt = &pid->u.p_pes->extra_es.p_elems[k]->fmt; + SetExtraESGroupAndID( p_sys, p_fmt, &pid->u.p_pes->es.fmt ); + pid->u.p_pes->extra_es.p_elems[k]->id = es_out_Add( p_demux->out, p_fmt ); } p_sys->i_pmt_es += 1 + pid->u.p_pes->extra_es.i_size; - - if( pid->u.p_pes->es.id != NULL && ProgramIsSelected( p_demux, pid->p_parent->u.p_pmt->i_number ) ) - SetPIDFilter( p_demux, pid->i_pid, true ); } } } + + UpdatePESFilters( p_demux, p_sys->b_es_all ); } static void PMTCallBack( void *data, dvbpsi_pmt_t *p_dvbpsipmt ) @@ -5093,8 +5163,8 @@ static void PMTCallBack( void *data, dvbpsi_pmt_t *p_dvbpsipmt ) ValidateDVBMeta( p_demux, p_pmt->i_pid_pcr ); - if( ProgramIsSelected( p_demux, p_pmt->i_number ) ) - SetPIDFilter( p_demux, p_pmt->i_pid_pcr, true ); /* Set demux filter */ + if( ProgramIsSelected( p_sys, p_pmt->i_number ) ) + SetPIDFilter( p_sys, &p_sys->pid[p_pmt->i_pid_pcr], true ); /* Set demux filter */ /* Parse PMT descriptors */ ts_pmt_registration_type_t registration_type = TS_PMT_REGISTRATION_NONE; @@ -5181,6 +5251,11 @@ static void PMTCallBack( void *data, dvbpsi_pmt_t *p_dvbpsipmt ) ts_pes_t *p_pes; ts_pid_t *pespid = &p_sys->pid[p_dvbpsies->i_pid]; + if ( pespid->type == TYPE_PES && pespid->p_parent->u.p_pmt->i_number != p_pmt->i_number ) + { + msg_Warn( p_demux, " * PMT wants to get a share or pid %d (unsupported)", pespid->i_pid ); + continue; + } /* Find out if the PID was already declared */ for( int i = 0; i < old_es_rm.i_size; i++ ) @@ -5351,22 +5426,22 @@ static void PMTCallBack( void *data, dvbpsi_pmt_t *p_dvbpsipmt ) break; } + /* Set Groups / ID */ p_pes->es.fmt.i_group = p_dvbpsipmt->i_program_number; - for( int i = 0; i < p_pes->extra_es.i_size; i++ ) - p_pes->extra_es.p_elems[i]->fmt.i_group = p_dvbpsipmt->i_program_number; + if( p_sys->b_es_id_pid ) + p_pes->es.fmt.i_id = p_dvbpsies->i_pid; if( p_pes->es.fmt.i_cat == UNKNOWN_ES ) { msg_Dbg( p_demux, " => pid %d content is *unknown*", p_dvbpsies->i_pid ); + p_pes->es.fmt.psz_description = strdup( psz_typedesc ); } else { msg_Dbg( p_demux, " => pid %d has now es fcc=%4.4s", p_dvbpsies->i_pid, (char*)&p_pes->es.fmt.i_codec ); - if( p_sys->b_es_id_pid ) p_pes->es.fmt.i_id = p_dvbpsies->i_pid; - /* Check if we can avoid restarting the ES */ if( b_reusing_pid ) { @@ -5414,7 +5489,7 @@ static void PMTCallBack( void *data, dvbpsi_pmt_t *p_dvbpsipmt ) } else { - AddAndCreateES( p_demux, pespid ); + AddAndCreateES( p_demux, pespid, false ); } } @@ -5424,20 +5499,17 @@ 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_demux, p_dvbpsies->i_pid, 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 ); } else if( stream_Control( p_sys->stream, STREAM_SET_PRIVATE_ID_CA, p_dvbpsipmt ) != VLC_SUCCESS ) { - if ( p_sys->arib.e_mode == ARIBMODE_ENABLED ) + if ( p_sys->arib.e_mode == ARIBMODE_ENABLED && !p_sys->arib.b25stream ) { p_sys->arib.b25stream = stream_FilterNew( p_demux->s, "aribcam" ); p_sys->stream = ( p_sys->arib.b25stream ) ? p_sys->arib.b25stream : p_demux->s; @@ -5451,6 +5523,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 ); @@ -5556,15 +5630,16 @@ 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 ) { + msg_Dbg( p_demux, "temporary receiving program %d", p_program->i_number ); p_sys->b_default_selection = true; ARRAY_APPEND( p_sys->programs, p_program->i_number ); } - if( SetPIDFilter( p_demux, p_program->i_pid, true ) ) + if( SetPIDFilter( p_sys, pmtpid, true ) ) p_sys->b_access_control = false; else if ( p_sys->es_creation == DELAY_ES ) p_sys->es_creation = CREATE_ES; @@ -5638,7 +5713,7 @@ static ts_pmt_t *ts_pmt_New( demux_t *p_demux ) pmt->i_version = -1; pmt->i_number = -1; - pmt->i_pid_pcr = -1; + pmt->i_pid_pcr = 0x1FFF; pmt->iod = NULL; pmt->i_last_dts = -1; @@ -5649,6 +5724,8 @@ static ts_pmt_t *ts_pmt_New( demux_t *p_demux ) pmt->pcr.i_first_dts = VLC_TS_INVALID; pmt->pcr.i_pcroffset = -1; + pmt->pcr.b_fix_done = false; + return pmt; } @@ -5662,7 +5739,8 @@ static void ts_pmt_Del( demux_t *p_demux, ts_pmt_t *pmt ) ARRAY_RESET( pmt->e_streams ); if( pmt->iod ) IODFree( pmt->iod ); - es_out_Control( p_demux->out, ES_OUT_DEL_GROUP, pmt->i_number ); + if( pmt->i_number > -1 ) + es_out_Control( p_demux->out, ES_OUT_DEL_GROUP, pmt->i_number ); free( pmt ); }