+ p_pat->i_version = p_dvbpsipat->i_version;
+ p_pat->i_ts_id = p_dvbpsipat->i_ts_id;
+
+ for(int i=0; i<old_pmt_rm.i_size; i++)
+ {
+ /* decref current or release now unreferenced */
+ PIDRelease( p_demux, old_pmt_rm.p_elems[i] );
+ }
+ ARRAY_RESET(old_pmt_rm);
+
+ dvbpsi_pat_delete( p_dvbpsipat );
+}
+
+static inline bool handle_Init( demux_t *p_demux, dvbpsi_t **handle )
+{
+ *handle = dvbpsi_new( &dvbpsi_messages, DVBPSI_MSG_DEBUG );
+ if( !*handle )
+ return false;
+ (*handle)->p_sys = (void *) p_demux;
+ return true;
+}
+
+static ts_pat_t *ts_pat_New( demux_t *p_demux )
+{
+ ts_pat_t *pat = malloc( sizeof( ts_pat_t ) );
+ if( !pat )
+ return NULL;
+
+ if( !handle_Init( p_demux, &pat->handle ) )
+ {
+ free( pat );
+ return NULL;
+ }
+
+ pat->i_version = -1;
+ pat->i_ts_id = -1;
+ ARRAY_INIT( pat->programs );
+
+ return pat;
+}
+
+static void ts_pat_Del( demux_t *p_demux, ts_pat_t *pat )
+{
+ if( dvbpsi_decoder_present( pat->handle ) )
+ dvbpsi_pat_detach( pat->handle );
+ dvbpsi_delete( pat->handle );
+ for( int i=0; i<pat->programs.i_size; i++ )
+ PIDRelease( p_demux, pat->programs.p_elems[i] );
+ ARRAY_RESET( pat->programs );
+ free( pat );
+}
+
+static ts_pmt_t *ts_pmt_New( demux_t *p_demux )
+{
+ ts_pmt_t *pmt = malloc( sizeof( ts_pmt_t ) );
+ if( !pmt )
+ return NULL;
+
+ if( !handle_Init( p_demux, &pmt->handle ) )
+ {
+ free( pmt );
+ return NULL;
+ }
+
+ ARRAY_INIT( pmt->e_streams );
+
+ pmt->i_version = -1;
+ pmt->i_number = -1;
+ pmt->i_pid_pcr = 0x1FFF;
+ pmt->iod = NULL;
+
+ pmt->i_last_dts = -1;
+
+ pmt->pcr.i_current = -1;
+ pmt->pcr.i_first = -1;
+ pmt->pcr.b_disable = false;
+ pmt->pcr.i_first_dts = VLC_TS_INVALID;
+ pmt->pcr.i_pcroffset = -1;
+
+ pmt->pcr.b_fix_done = false;
+
+ return pmt;
+}
+
+static void ts_pmt_Del( demux_t *p_demux, ts_pmt_t *pmt )
+{
+ if( dvbpsi_decoder_present( pmt->handle ) )
+ dvbpsi_pmt_detach( pmt->handle );
+ dvbpsi_delete( pmt->handle );
+ for( int i=0; i<pmt->e_streams.i_size; i++ )
+ PIDRelease( p_demux, pmt->e_streams.p_elems[i] );
+ ARRAY_RESET( pmt->e_streams );
+ if( pmt->iod )
+ IODFree( pmt->iod );
+ if( pmt->i_number > -1 )
+ es_out_Control( p_demux->out, ES_OUT_DEL_GROUP, pmt->i_number );
+ free( pmt );
+}
+
+static ts_pes_t *ts_pes_New( demux_t *p_demux )
+{
+ VLC_UNUSED(p_demux);
+ ts_pes_t *pes = malloc( sizeof( ts_pes_t ) );
+ if( !pes )
+ return NULL;
+
+ pes->es.id = NULL;
+ pes->es.p_mpeg4desc = NULL;
+ es_format_Init( &pes->es.fmt, UNKNOWN_ES, 0 );
+ ARRAY_INIT( pes->extra_es );
+ pes->data_type = TS_ES_DATA_PES;
+ pes->i_data_size = 0;
+ pes->i_data_gathered = 0;
+ pes->p_data = NULL;
+ pes->pp_last = &pes->p_data;
+ pes->p_prepcr_outqueue = NULL;
+
+ return pes;
+}
+
+static void ts_pes_Del( demux_t *p_demux, ts_pes_t *pes )
+{
+ if( pes->es.id )
+ {
+ es_out_Del( p_demux->out, pes->es.id );
+ p_demux->p_sys->i_pmt_es--;
+ }
+
+ if( pes->p_data )
+ block_ChainRelease( pes->p_data );
+
+ if( pes->p_prepcr_outqueue )
+ block_ChainRelease( pes->p_prepcr_outqueue );
+
+ es_format_Clean( &pes->es.fmt );
+
+ for( int i = 0; i < pes->extra_es.i_size; i++ )
+ {
+ if( pes->extra_es.p_elems[i]->id )
+ {
+ es_out_Del( p_demux->out, pes->extra_es.p_elems[i]->id );
+ p_demux->p_sys->i_pmt_es--;
+ }
+ es_format_Clean( &pes->extra_es.p_elems[i]->fmt );
+ free( pes->extra_es.p_elems[i] );
+ }
+ ARRAY_RESET( pes->extra_es );
+
+ free( pes );
+}
+
+static ts_psi_t *ts_psi_New( demux_t *p_demux )
+{
+ ts_psi_t *psi = malloc( sizeof( ts_psi_t ) );
+ if( !psi )
+ return NULL;
+
+ if( !handle_Init( p_demux, &psi->handle ) )
+ {
+ free( psi );
+ return NULL;
+ }