]> git.sesse.net Git - vlc/blobdiff - modules/demux/ts.c
demux: ts: only interpolate PCR on missing PCR
[vlc] / modules / demux / ts.c
index eb40eace72f9ba703cc08e92d6dcbaffb21a7980..d420f3a14864c7b9bbec80dd4a48936dd42edd70 100644 (file)
@@ -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; 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, "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; 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 +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; i<p_pat->programs.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; i<p_sys->programs.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 );
 }