X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fdemux%2Fts.c;h=051bdde1e3bbd0259099a1e887586964f5d7d719;hb=762ddf5b4396bf0fefde60a75617bfa5718dec8e;hp=724271429ec9a05f91cda7a56e48a7e95a2ef80c;hpb=316e42b355af4387cb3415e4c46bea83e469d6fe;p=vlc diff --git a/modules/demux/ts.c b/modules/demux/ts.c index 724271429e..051bdde1e3 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; @@ -273,7 +274,7 @@ typedef struct { es_format_t fmt; es_out_id_t *id; - es_mpeg4_descriptor_t *p_mpeg4desc; + const es_mpeg4_descriptor_t *p_mpeg4desc; } ts_pes_es_t; typedef enum @@ -313,21 +314,6 @@ typedef enum TS_PMT_REGISTRATION_HDMV } ts_pmt_registration_type_t; -typedef struct -{ - es_format_t fmt; - es_out_id_t *id; - ts_es_data_type_t data_type; - int i_data_size; - int i_data_gathered; - block_t *p_data; - block_t **pp_last; - - es_mpeg4_descriptor_t *p_mpeg4desc; - - block_t * p_prepcr_outqueue; -} ts_es_t; - typedef enum { TYPE_FREE = 0, @@ -347,7 +333,7 @@ enum FLAG_FILTERED = 4 }; -#define SEEN(x) ((x).i_flags & FLAG_SEEN) +#define SEEN(x) ((x)->i_flags & FLAG_SEEN) #define SCRAMBLED(x) ((x).i_flags & FLAG_SCRAMBLED) struct ts_pid_t @@ -392,6 +378,8 @@ typedef struct #define FROM_SCALE(x) (VLC_TS_0 + ((x) * 100 / 9)) #define TO_SCALE(x) (((x) - VLC_TS_0) * 9 / 100) +#define PID_ALLOC_CHUNK 16 + struct demux_sys_t { stream_t *stream; @@ -400,13 +388,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; @@ -420,7 +408,18 @@ struct demux_sys_t } arib; /* All pid */ - ts_pid_t pid[8192]; + struct + { + ts_pid_t pat; + ts_pid_t dummy; + /* all non commons ones, dynamically allocated */ + ts_pid_t **pp_all; + int i_all; + int i_all_alloc; + /* last recently used */ + uint16_t i_last_pid; + ts_pid_t *p_last; + } pids; bool b_user_pmt; int i_pmt_es; @@ -436,6 +435,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; @@ -496,6 +497,7 @@ static ts_psi_t *ts_psi_New( demux_t * ); static void ts_psi_Del( demux_t *, ts_psi_t * ); /* Helpers */ +static ts_pid_t *PID( demux_sys_t *, uint16_t i_pid ); 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 ); @@ -532,7 +534,7 @@ static int SetPIDFilter( demux_sys_t *, ts_pid_t *, 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; @@ -587,7 +589,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; @@ -894,23 +896,28 @@ static void MissingPATPMTFixup( demux_t *p_demux ) int i_pcr_pid = 0x1FFF; int i_num_pes = 0; - if( SEEN(p_sys->pid[i_program_pid]) ) + ts_pid_t *p_program_pid = PID( p_sys, i_program_pid ); + if( SEEN(p_program_pid) ) { /* Find a free one */ for( i_program_pid = MIN_ES_PID; - i_program_pid <= MAX_ES_PID && SEEN(p_sys->pid[i_program_pid]); - i_program_pid++ ); + i_program_pid <= MAX_ES_PID && SEEN(p_program_pid); + i_program_pid++ ) + { + p_program_pid = PID( p_sys, i_program_pid ); + } } - for( int i = MIN_ES_PID; i <= MAX_ES_PID; i++ ) + for( int i=0; ipids.i_all; i++ ) { - if( !SEEN(p_sys->pid[i]) || - p_sys->pid[i].probed.i_type == -1 ) + const ts_pid_t *p_pid = p_sys->pids.pp_all[i]; + if( !SEEN(p_pid) || + p_pid->probed.i_type == -1 ) continue; - if( i_pcr_pid == 0x1FFF && ( p_sys->pid[i].probed.i_type == 0x03 || - p_sys->pid[i].probed.i_pcr_count ) ) - i_pcr_pid = p_sys->pid[i].i_pid; + if( i_pcr_pid == 0x1FFF && ( p_pid->probed.i_type == 0x03 || + p_pid->probed.i_pcr_count ) ) + i_pcr_pid = p_pid->i_pid; i_num_pes++; } @@ -932,13 +939,14 @@ static void MissingPATPMTFixup( demux_t *p_demux ) .b_discontinuity = false }; - BuildPAT( p_sys->pid[0].u.p_pat->handle, - &p_sys->pid[0], BuildPATCallback, + BuildPAT( PID(p_sys, 0)->u.p_pat->handle, + &p_sys->pids.pat, BuildPATCallback, 0, 1, &patstream, 1, &pmtprogramstream, &i_program_number ); - if( p_sys->pid[i_program_pid].type != TYPE_PMT ) + /* PAT callback should have been triggered */ + if( p_program_pid->type != TYPE_PMT ) { msg_Err( p_demux, "PAT creation failed" ); return; @@ -955,23 +963,25 @@ static void MissingPATPMTFixup( demux_t *p_demux ) if( esstreams && mapped ) { int j=0; - for( int i = MIN_ES_PID; i <= MAX_ES_PID; i++ ) + for( int i=0; ipids.i_all; i++ ) { - if( !SEEN(p_sys->pid[i]) || - p_sys->pid[i].probed.i_type == -1 ) + const ts_pid_t *p_pid = p_sys->pids.pp_all[i]; + + if( !SEEN(p_pid) || + p_pid->probed.i_type == -1 ) continue; - esstreams[j].pes.i_stream_type = p_sys->pid[i].probed.i_type; - esstreams[j].pes.i_stream_type = p_sys->pid[i].probed.i_type; - esstreams[j].ts.i_pid = p_sys->pid[i].i_pid; + esstreams[j].pes.i_stream_type = p_pid->probed.i_type; + esstreams[j].pes.i_stream_type = p_pid->probed.i_type; + esstreams[j].ts.i_pid = p_pid->i_pid; mapped[j].pes = &esstreams[j].pes; mapped[j].ts = &esstreams[j].ts; mapped[j].fmt = &esfmt; j++; } - BuildPMT( p_sys->pid[0].u.p_pat->handle, VLC_OBJECT(p_demux), - &p_sys->pid[i_program_pid], BuildPMTCallback, + BuildPMT( PID(p_sys, 0)->u.p_pat->handle, VLC_OBJECT(p_demux), + p_program_pid, BuildPMTCallback, 0, 1, i_pcr_pid, NULL, @@ -990,7 +1000,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}; @@ -1026,16 +1037,9 @@ static int Open( vlc_object_t *p_this ) p_sys->b_broken_charset = false; - for( int i = 0; i < 8192; i++ ) - { - ts_pid_t *pid = &p_sys->pid[i]; - pid->i_pid = i; - pid->i_flags = FLAGS_NONE; - pid->probed.i_fourcc = 0; - pid->probed.i_type = 0; - } - /* PID 8191 is padding */ - p_sys->pid[8191].i_flags = FLAG_SEEN; + p_sys->pids.dummy.i_pid = 8191; + p_sys->pids.dummy.i_flags = FLAG_SEEN; + p_sys->i_packet_size = i_packet_size; p_sys->i_packet_header_size = i_packet_header_size; p_sys->i_ts_read = 50; @@ -1051,7 +1055,7 @@ static int Open( vlc_object_t *p_this ) } while (0) /* Init PAT handler */ - patpid = &p_sys->pid[0]; + patpid = PID(p_sys, 0); if ( !PIDSetup( p_demux, TYPE_PAT, patpid, NULL ) ) { vlc_mutex_destroy( &p_sys->csa_lock ); @@ -1068,24 +1072,24 @@ static int Open( vlc_object_t *p_this ) if( p_sys->b_dvb_meta ) { - if( !PIDSetup( p_demux, TYPE_SDT, &p_sys->pid[0x11], NULL ) || - !PIDSetup( p_demux, TYPE_EIT, &p_sys->pid[0x12], NULL ) || - !PIDSetup( p_demux, TYPE_TDT, &p_sys->pid[0x14], NULL ) ) + if( !PIDSetup( p_demux, TYPE_SDT, PID(p_sys, 0x11), NULL ) || + !PIDSetup( p_demux, TYPE_EIT, PID(p_sys, 0x12), NULL ) || + !PIDSetup( p_demux, TYPE_TDT, PID(p_sys, 0x14), NULL ) ) { - PIDRelease( p_demux, &p_sys->pid[0x11] ); - PIDRelease( p_demux, &p_sys->pid[0x12] ); - PIDRelease( p_demux, &p_sys->pid[0x14] ); + PIDRelease( p_demux, PID(p_sys, 0x11) ); + PIDRelease( p_demux, PID(p_sys, 0x12) ); + PIDRelease( p_demux, PID(p_sys, 0x14) ); p_sys->b_dvb_meta = false; } else { - VLC_DVBPSI_DEMUX_TABLE_INIT(&p_sys->pid[0x11], p_demux); - VLC_DVBPSI_DEMUX_TABLE_INIT(&p_sys->pid[0x12], p_demux); - VLC_DVBPSI_DEMUX_TABLE_INIT(&p_sys->pid[0x14], p_demux); + VLC_DVBPSI_DEMUX_TABLE_INIT(PID(p_sys, 0x11), p_demux); + VLC_DVBPSI_DEMUX_TABLE_INIT(PID(p_sys, 0x12), p_demux); + VLC_DVBPSI_DEMUX_TABLE_INIT(PID(p_sys, 0x14), p_demux); if( p_sys->b_access_control && - ( SetPIDFilter( p_sys, &p_sys->pid[0x11], true ) || - SetPIDFilter( p_sys, &p_sys->pid[0x14], true ) || - SetPIDFilter( p_sys, &p_sys->pid[0x12], true ) ) + ( SetPIDFilter( p_sys, PID(p_sys, 0x11), true ) || + SetPIDFilter( p_sys, PID(p_sys, 0x14), true ) || + SetPIDFilter( p_sys, PID(p_sys, 0x12), true ) ) ) p_sys->b_access_control = false; } @@ -1098,6 +1102,7 @@ static int Open( vlc_object_t *p_this ) /* 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" ); @@ -1189,24 +1194,15 @@ static void Close( vlc_object_t *p_this ) demux_t *p_demux = (demux_t*)p_this; demux_sys_t *p_sys = p_demux->p_sys; - PIDRelease( p_demux, &p_sys->pid[0] ); + PIDRelease( p_demux, PID(p_sys, 0) ); if( p_sys->b_dvb_meta ) { - PIDRelease( p_demux, &p_sys->pid[0x11] ); - PIDRelease( p_demux, &p_sys->pid[0x12] ); - PIDRelease( p_demux, &p_sys->pid[0x14] ); + PIDRelease( p_demux, PID(p_sys, 0x11) ); + PIDRelease( p_demux, PID(p_sys, 0x12) ); + PIDRelease( p_demux, PID(p_sys, 0x14) ); } -#ifndef NDEBUG - for( int i = 0; i < 8192; i++ ) - { - ts_pid_t *pid = &p_sys->pid[i]; - if( pid->type != TYPE_FREE ) - msg_Err( p_demux, "PID %d type %d not freed", pid->i_pid, pid->type ); - } -#endif - vlc_mutex_lock( &p_sys->csa_lock ); if( p_sys->csa ) { @@ -1230,6 +1226,19 @@ static void Close( vlc_object_t *p_this ) } vlc_mutex_destroy( &p_sys->csa_lock ); + + /* Release all non default pids */ + for( int i = 0; i < p_sys->pids.i_all; i++ ) + { + ts_pid_t *pid = p_sys->pids.pp_all[i]; +#ifndef NDEBUG + if( pid->type != TYPE_FREE ) + msg_Err( p_demux, "PID %d type %d not freed", pid->i_pid, pid->type ); +#endif + free( pid ); + } + free( p_sys->pids.pp_all ); + free( p_sys ); } @@ -1264,11 +1273,11 @@ static int Demux( demux_t *p_demux ) bool b_wait_es = p_sys->i_pmt_es <= 0; /* If we had no PAT within MIN_PAT_INTERVAL, create PAT/PMT from probed streams */ - if( p_sys->i_pmt_es == 0 && !SEEN(p_sys->pid[0]) && p_sys->patfix.b_pat_deadline ) + if( p_sys->i_pmt_es == 0 && !SEEN(PID(p_sys, 0)) && p_sys->patfix.b_pat_deadline ) 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; @@ -1285,12 +1294,12 @@ static int Demux( demux_t *p_demux ) } /* Parse the TS packet */ - ts_pid_t *p_pid = &p_sys->pid[PIDGet( p_pkt )]; + ts_pid_t *p_pid = PID( p_sys, 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( !SEEN(p_pid) ) { if( p_pid->type == TYPE_FREE ) msg_Dbg( p_demux, "pid[%d] unknown", p_pid->i_pid ); @@ -1304,7 +1313,7 @@ static int Demux( demux_t *p_demux ) } /* Probe streams to build PAT/PMT after MIN_PAT_INTERVAL in case we don't see any PAT */ - if( !SEEN(p_sys->pid[0]) && + if( !SEEN( PID( p_sys, 0 ) ) && (p_pid->probed.i_type == 0 || p_pid->i_pid == p_sys->patfix.i_timesourcepid) && (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 */ @@ -1397,7 +1406,7 @@ static int DVBEventInformation( demux_t *p_demux, int64_t *pi_time, int64_t *pi_ 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; + ts_pat_t *p_pat = PID(p_sys, 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; @@ -1431,7 +1440,7 @@ static void UpdatePESFilters( demux_t *p_demux, bool b_all ) /* 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 ); + SetPIDFilter( p_sys, PID(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 ); } @@ -1451,9 +1460,9 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) if( PREPARSING || !i_first_program || p_sys->b_default_selection ) { - if( likely(p_sys->pid[0].type == TYPE_PAT) ) + if( likely(PID(p_sys, 0)->type == TYPE_PAT) ) { - ts_pat_t *p_pat = p_sys->pid[0].u.p_pat; + ts_pat_t *p_pat = PID(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++ ) { @@ -1634,7 +1643,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) else // All ES Mode { p_sys->b_es_all = true; - ts_pat_t *p_pat = p_sys->pid[0].u.p_pat; + ts_pat_t *p_pat = PID(p_sys, 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 ); @@ -1724,10 +1733,10 @@ static int UserPmt( demux_t *p_demux, const char *psz_fmt ) i_number = strtol( &psz[1], &psz, 0 ); /* */ - ts_pid_t *pmtpid = &p_sys->pid[i_pid]; + ts_pid_t *pmtpid = PID(p_sys, i_pid); msg_Dbg( p_demux, "user pmt specified (pid=%d,number=%d)", i_pid, i_number ); - if ( !PIDSetup( p_demux, TYPE_PMT, pmtpid, &p_sys->pid[0] ) ) + if ( !PIDSetup( p_demux, TYPE_PMT, pmtpid, PID(p_sys, 0) ) ) goto error; /* Dummy PMT */ @@ -1741,7 +1750,7 @@ static int UserPmt( demux_t *p_demux, const char *psz_fmt ) goto error; } - ARRAY_APPEND( p_sys->pid[0].u.p_pat->programs, pmtpid ); + ARRAY_APPEND( PID(p_sys, 0)->u.p_pat->programs, pmtpid ); psz = strchr( psz, '=' ); if( psz ) @@ -1763,9 +1772,9 @@ static int UserPmt( demux_t *p_demux, const char *psz_fmt ) { p_pmt->i_pid_pcr = i_pid; } - else if( p_sys->pid[i_pid].type == TYPE_FREE ) + else if( PID(p_sys, i_pid)->type == TYPE_FREE ) { - ts_pid_t *pid = &p_sys->pid[i_pid]; + ts_pid_t *pid = PID(p_sys, i_pid); char *psz_arg = strchr( psz_opt, '=' ); if( psz_arg ) @@ -2056,7 +2065,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; @@ -2227,7 +2236,7 @@ static void ParsePES( demux_t *p_demux, ts_pid_t *pid, block_t *p_pes ) else if( pid->u.p_pes->es.fmt.i_codec == VLC_CODEC_SUBT && pid->u.p_pes->es.p_mpeg4desc ) { - decoder_config_descriptor_t *dcd = &pid->u.p_pes->es.p_mpeg4desc->dec_descr; + const decoder_config_descriptor_t *dcd = &pid->u.p_pes->es.p_mpeg4desc->dec_descr; if( dcd->i_extra > 2 && dcd->p_extra[0] == 0x10 && @@ -2341,15 +2350,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; } @@ -2393,7 +2404,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 ); @@ -2517,11 +2528,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; @@ -2620,7 +2632,7 @@ 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; + ts_pat_t *p_pat = PID(p_sys, 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; @@ -2631,7 +2643,7 @@ static void ReadyQueuesPostSeek( demux_t *p_demux ) if( pid->type != TYPE_PES ) continue; - if( !pid->u.p_pes->es.id ) + if( pid->u.p_pes->es.id ) { block_t *p_block = block_Alloc(1); if( p_block ) @@ -2700,8 +2712,8 @@ static int SeekToTime( demux_t *p_demux, ts_pmt_t *p_pmt, int64_t i_scaledtime ) i_pos = stream_Tell( p_sys->stream ); int i_pid = PIDGet( p_pkt ); - if( i_pid != 0x1FFF && p_sys->pid[i_pid].type == TYPE_PES && - p_sys->pid[i_pid].p_parent->u.p_pmt == p_pmt && + if( i_pid != 0x1FFF && PID(p_sys, i_pid)->type == TYPE_PES && + PID(p_sys, i_pid)->p_parent->u.p_pmt == p_pmt && (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 */ ) @@ -2755,12 +2767,62 @@ static int SeekToTime( demux_t *p_demux, ts_pmt_t *p_pmt, int64_t i_scaledtime ) return VLC_SUCCESS; } +static ts_pid_t *PID( demux_sys_t *p_sys, uint16_t i_pid ) +{ + switch( i_pid ) + { + case 0: + return &p_sys->pids.pat; + case 0x1FFF: + return &p_sys->pids.dummy; + default: + if( p_sys->pids.i_last_pid == i_pid ) + return p_sys->pids.p_last; + break; + } + + for( int i=0; i < p_sys->pids.i_all; i++ ) + { + if( p_sys->pids.pp_all[i]->i_pid == i_pid ) + { + p_sys->pids.p_last = p_sys->pids.pp_all[i]; + p_sys->pids.i_last_pid = i_pid; + return p_sys->pids.p_last; + } + } + + if( p_sys->pids.i_all >= p_sys->pids.i_all_alloc ) + { + ts_pid_t **p_realloc = realloc( p_sys->pids.pp_all, + (p_sys->pids.i_all_alloc + PID_ALLOC_CHUNK) * sizeof(ts_pid_t *) ); + if( !p_realloc ) + return NULL; + p_sys->pids.pp_all = p_realloc; + p_sys->pids.i_all_alloc += PID_ALLOC_CHUNK; + } + + ts_pid_t *p_pid = calloc( 1, sizeof(*p_pid) ); + if( !p_pid ) + { + abort(); + //return NULL; + } + + p_pid->i_pid = i_pid; + p_sys->pids.pp_all[p_sys->pids.i_all++] = p_pid; + + p_sys->pids.p_last = p_pid; + p_sys->pids.i_last_pid = i_pid; + + return p_pid; +} + static ts_pmt_t * GetProgramByID( demux_sys_t *p_sys, int i_program ) { - if(unlikely(p_sys->pid[0].type != TYPE_PAT)) + if(unlikely(PID(p_sys, 0)->type != TYPE_PAT)) return NULL; - ts_pat_t *p_pat = p_sys->pid[0].u.p_pat; + ts_pat_t *p_pat = PID(p_sys, 0)->u.p_pat; for( int i = 0; i < p_pat->programs.i_size; i++ ) { assert(p_pat->programs.p_elems[i]->type == TYPE_PMT); @@ -2778,35 +2840,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 = PID(p_sys, i_pid); + + p_pid->i_flags |= FLAG_SEEN; - 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 */ - ) + 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], @@ -2820,27 +2888,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 = PID(p_sys, 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 ) + 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 = *pi_pcr; - } - else if( pmtpid->u.p_pmt->pcr.i_first_dts < VLC_TS_0 ) - { - 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; } } } @@ -2917,11 +2990,11 @@ 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; - ts_pat_t *p_pat = p_sys->pid[0].u.p_pat; + ts_pat_t *p_pat = PID(p_sys, 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; @@ -2971,11 +3044,11 @@ static void PCRHandle( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk ) pid->probed.i_pcr_count++; - if(unlikely(p_sys->pid[0].type != TYPE_PAT)) + if(unlikely(PID(p_sys, 0)->type != TYPE_PAT)) return; /* Search program and set the PCR */ - ts_pat_t *p_pat = p_sys->pid[0].u.p_pat; + ts_pat_t *p_pat = PID(p_sys, 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; @@ -2983,16 +3056,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 */ { @@ -3015,7 +3083,7 @@ static int FindPCRCandidate( ts_pmt_t *p_pmt ) for( int i=0; ie_streams.i_size; i++ ) { ts_pid_t *p_pid = p_pmt->e_streams.p_elems[i]; - if( SEEN(*p_pid) && + if( SEEN(p_pid) && (!p_cand || p_cand->i_pid != i_previous) ) { if( p_pid->probed.i_pcr_count ) /* check PCR frequency first */ @@ -3046,24 +3114,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 ); - UpdatePESFilters( p_demux, p_demux->p_sys->b_es_all ); + 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; + } } } @@ -3170,7 +3243,7 @@ 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; @@ -3330,7 +3403,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; @@ -3349,9 +3422,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; @@ -3363,9 +3436,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 ); @@ -3374,7 +3447,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; @@ -3435,17 +3508,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; @@ -3460,7 +3533,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 */ @@ -3477,7 +3550,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 ); @@ -3574,9 +3647,9 @@ static void ValidateDVBMeta( demux_t *p_demux, int i_pid ) /* This doesn't look like a DVB stream so don't try * parsing the SDT/EDT/TDT */ - PIDRelease( p_demux, &p_sys->pid[0x11] ); - PIDRelease( p_demux, &p_sys->pid[0x12] ); - PIDRelease( p_demux, &p_sys->pid[0x14] ); + PIDRelease( p_demux, PID(p_sys, 0x11) ); + PIDRelease( p_demux, PID(p_sys, 0x12) ); + PIDRelease( p_demux, PID(p_sys, 0x14) ); p_sys->b_dvb_meta = false; } @@ -3632,7 +3705,7 @@ static char *EITConvertToUTF8( demux_t *p_demux, static void SDTCallBack( demux_t *p_demux, dvbpsi_sdt_t *p_sdt ) { demux_sys_t *p_sys = p_demux->p_sys; - ts_pid_t *sdt = &p_sys->pid[0x11]; + ts_pid_t *sdt = PID(p_sys, 0x11); dvbpsi_sdt_service_t *p_srv; msg_Dbg( p_demux, "SDTCallBack called" ); @@ -4067,7 +4140,7 @@ static void PSINewTableCallBack( dvbpsi_t *h, uint8_t i_table_id, msg_Dbg( p_demux, "PSINewTableCallBack: table 0x%x(%d) ext=0x%x(%d)", i_table_id, i_table_id, i_extension, i_extension ); #endif - if( p_sys->pid[0].u.p_pat->i_version != -1 && i_table_id == 0x42 ) + if( PID(p_sys, 0)->u.p_pat->i_version != -1 && i_table_id == 0x42 ) { msg_Dbg( p_demux, "PSINewTableCallBack: table 0x%x(%d) ext=0x%x(%d)", i_table_id, i_table_id, i_extension, i_extension ); @@ -4075,7 +4148,7 @@ static void PSINewTableCallBack( dvbpsi_t *h, uint8_t i_table_id, if( !dvbpsi_sdt_attach( h, i_table_id, i_extension, (dvbpsi_sdt_callback)SDTCallBack, p_demux ) ) msg_Err( p_demux, "PSINewTableCallback: failed attaching SDTCallback" ); } - else if( p_sys->pid[0x11].u.p_psi->i_version != -1 && + else if( PID(p_sys, 0x11)->u.p_psi->i_version != -1 && ( i_table_id == 0x4e || /* Current/Following */ (i_table_id >= 0x50 && i_table_id <= 0x5f) ) ) /* Schedule */ { @@ -4089,7 +4162,7 @@ static void PSINewTableCallBack( dvbpsi_t *h, uint8_t i_table_id, if( !dvbpsi_eit_attach( h, i_table_id, i_extension, cb, p_demux ) ) msg_Err( p_demux, "PSINewTableCallback: failed attaching EITCallback" ); } - else if( p_demux->p_sys->pid[0x11].u.p_psi->i_version != -1 && + else if( PID(p_sys, 0x11)->u.p_psi->i_version != -1 && (i_table_id == 0x70 /* TDT */ || i_table_id == 0x73 /* TOT */) ) { msg_Dbg( p_demux, "PSINewTableCallBack: table 0x%x(%d) ext=0x%x(%d)", @@ -4142,35 +4215,75 @@ static bool PMTEsHasComponentTag( const dvbpsi_pmt_es_t *p_es, return p_si->i_component_tag == i_component_tag; } +static const es_mpeg4_descriptor_t * GetMPEG4DescByEsId( const iod_descriptor_t *iod, + uint16_t i_es_id ) +{ + if( iod ) + for( int i = 0; i < ES_DESCRIPTOR_COUNT; i++ ) + { + if( iod->es_descr[i].i_es_id == i_es_id ) + { + if ( iod->es_descr[i].b_ok ) + return &iod->es_descr[i]; + } + } + return NULL; +} + static void PMTSetupEsISO14496( demux_t *p_demux, ts_pes_es_t *p_es, const ts_pmt_t *p_pmt, const dvbpsi_pmt_es_t *p_dvbpsies ) { es_format_t *p_fmt = &p_es->fmt; - /* MPEG-4 stream: search FMC_DESCRIPTOR (SL Packetized stream) */ - dvbpsi_descriptor_t *p_dr = PMTEsFindDescriptor( p_dvbpsies, 0x1f ); - - if( p_dr && p_dr->i_length == 2 ) + const dvbpsi_descriptor_t *p_dr = p_dvbpsies->p_first_descriptor; + while( p_dr ) { - const int i_es_id = ( p_dr->p_data[0] << 8 ) | p_dr->p_data[1]; + const es_mpeg4_descriptor_t *p_esdescr = NULL; + uint16_t i_es_id; + uint8_t i_length = p_dr->i_length; - msg_Dbg( p_demux, "found FMC_descriptor declaring sl packetization on es_id=%d", i_es_id ); - - p_es->p_mpeg4desc = NULL; + switch( p_dr->i_tag ) + { + case 0x1f: /* FMC Descriptor */ + while( i_length >= 3 && !p_esdescr ) + { + i_es_id = ( p_dr->p_data[0] << 8 ) | p_dr->p_data[1]; + p_esdescr = GetMPEG4DescByEsId( p_pmt->iod, i_es_id ); + /* FIXME: add flexmux channel */ + i_length -= 3; + if( p_esdescr ) + msg_Dbg( p_demux, "found FMC_descriptor declaring sl packetization on es_id=%"PRIu16, i_es_id ); + } + break; + case 0x1e: /* SL Descriptor */ + if( i_length == 2 ) + { + i_es_id = ( p_dr->p_data[0] << 8 ) | p_dr->p_data[1]; + p_esdescr = GetMPEG4DescByEsId( p_pmt->iod, i_es_id ); + if( p_esdescr ) + msg_Dbg( p_demux, "found SL_descriptor declaring sl packetization on es_id=%"PRIu16, i_es_id ); + } + break; + default: + break; + } - for( int i = 0; i < ES_DESCRIPTOR_COUNT; i++ ) + if( p_esdescr ) { - iod_descriptor_t *iod = p_pmt->iod; - if( iod->es_descr[i].i_es_id == i_es_id ) + if( !p_esdescr->b_ok ) { - if ( iod->es_descr[i].b_ok ) - p_es->p_mpeg4desc = &iod->es_descr[i]; - else - msg_Dbg( p_demux, "MPEG-4 descriptor not yet available on es_id=%d", i_es_id ); + msg_Dbg( p_demux, "MPEG-4 descriptor not yet available on es_id=%"PRIu16, i_es_id ); + } + else + { + p_es->p_mpeg4desc = p_esdescr; break; } } + + p_dr = p_dr->p_next; } + if( !p_es->p_mpeg4desc ) { switch( p_dvbpsies->i_type ) @@ -4256,7 +4369,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 ); @@ -4384,7 +4497,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; @@ -5012,6 +5125,14 @@ static void PMTParseEsIso639( demux_t *p_demux, ts_pes_es_t *p_es, #endif } +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; @@ -5021,11 +5142,13 @@ static void AddAndCreateES( demux_t *p_demux, ts_pid_t *pid, bool b_create_delay if( pid && p_sys->es_creation == CREATE_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++ ) { - 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 ); + 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; @@ -5042,7 +5165,7 @@ static void AddAndCreateES( demux_t *p_demux, ts_pid_t *pid, bool b_create_delay if( b_create_delayed ) { - ts_pat_t *p_pat = p_sys->pid[0].u.p_pat; + ts_pat_t *p_pat = PID(p_sys, 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; @@ -5055,8 +5178,9 @@ static void AddAndCreateES( demux_t *p_demux, ts_pid_t *pid, bool b_create_delay 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; } @@ -5076,13 +5200,13 @@ static void PMTCallBack( void *data, dvbpsi_pmt_t *p_dvbpsipmt ) msg_Dbg( p_demux, "PMTCallBack called" ); - if (unlikely(p_sys->pid[0].type != TYPE_PAT)) + if (unlikely(PID(p_sys, 0)->type != TYPE_PAT)) { - assert(p_sys->pid[0].type == TYPE_PAT); + assert(PID(p_sys, 0)->type == TYPE_PAT); dvbpsi_pmt_delete(p_dvbpsipmt); } - const ts_pat_t *p_pat = p_sys->pid[0].u.p_pat; + const ts_pat_t *p_pat = PID(p_sys, 0)->u.p_pat; /* First find this PMT declared in PAT */ for( int i = 0; !pmtpid && i < p_pat->programs.i_size; i++ ) @@ -5124,6 +5248,8 @@ static void PMTCallBack( void *data, dvbpsi_pmt_t *p_dvbpsipmt ) { IODFree( p_pmt->iod ); p_pmt->iod = NULL; + for( int i=0; iu.p_pes->es.p_mpeg4desc = NULL; } msg_Dbg( p_demux, "new PMT program number=%d version=%d pid_pcr=%d", @@ -5134,7 +5260,7 @@ static void PMTCallBack( void *data, dvbpsi_pmt_t *p_dvbpsipmt ) ValidateDVBMeta( p_demux, p_pmt->i_pid_pcr ); if( ProgramIsSelected( p_sys, p_pmt->i_number ) ) - SetPIDFilter( p_sys, &p_sys->pid[p_pmt->i_pid_pcr], true ); /* Set demux filter */ + SetPIDFilter( p_sys, PID(p_sys, p_pmt->i_pid_pcr), true ); /* Set demux filter */ /* Parse PMT descriptors */ ts_pmt_registration_type_t registration_type = TS_PMT_REGISTRATION_NONE; @@ -5220,7 +5346,12 @@ static void PMTCallBack( void *data, dvbpsi_pmt_t *p_dvbpsipmt ) bool b_reusing_pid = false; ts_pes_t *p_pes; - ts_pid_t *pespid = &p_sys->pid[p_dvbpsies->i_pid]; + ts_pid_t *pespid = PID(p_sys, 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++ ) @@ -5322,7 +5453,7 @@ static void PMTCallBack( void *data, dvbpsi_pmt_t *p_dvbpsipmt ) PIDFillFormat( &p_pes->es.fmt, p_dvbpsies->i_type ); - pespid->i_flags |= SEEN(p_sys->pid[p_dvbpsies->i_pid]); + pespid->i_flags |= SEEN(PID(p_sys, p_dvbpsies->i_pid)); bool b_registration_applied = false; if ( p_dvbpsies->i_type >= 0x80 ) /* non standard, extensions */ @@ -5391,9 +5522,10 @@ 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 ) { @@ -5406,8 +5538,6 @@ static void PMTCallBack( void *data, dvbpsi_pmt_t *p_dvbpsipmt ) 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 ) { @@ -5475,7 +5605,7 @@ static void PMTCallBack( void *data, dvbpsi_pmt_t *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; @@ -5532,14 +5662,14 @@ static void PATCallBack( void *data, dvbpsi_pat_t *p_dvbpsipat ) demux_t *p_demux = data; demux_sys_t *p_sys = p_demux->p_sys; dvbpsi_pat_program_t *p_program; - ts_pid_t *patpid = &p_sys->pid[0]; - ts_pat_t *p_pat = p_sys->pid[0].u.p_pat; + ts_pid_t *patpid = PID(p_sys, 0); + ts_pat_t *p_pat = PID(p_sys, 0)->u.p_pat; patpid->i_flags |= FLAG_SEEN; msg_Dbg( p_demux, "PATCallBack called" ); - if(unlikely( p_sys->pid[0].type != TYPE_PAT )) + if(unlikely( PID(p_sys, 0)->type != TYPE_PAT )) { msg_Warn( p_demux, "PATCallBack called on invalid pid" ); return; @@ -5574,7 +5704,7 @@ static void PATCallBack( void *data, dvbpsi_pat_t *p_dvbpsipat ) if( p_program->i_number == 0 ) continue; - ts_pid_t *pmtpid = &p_sys->pid[p_program->i_pid]; + ts_pid_t *pmtpid = PID(p_sys, p_program->i_pid); ValidateDVBMeta( p_demux, p_program->i_pid ); @@ -5679,7 +5809,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; @@ -5690,6 +5820,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; } @@ -5744,7 +5876,6 @@ static void ts_pes_Del( demux_t *p_demux, ts_pes_t *pes ) block_ChainRelease( pes->p_prepcr_outqueue ); es_format_Clean( &pes->es.fmt ); - free( pes->es.p_mpeg4desc ); for( int i = 0; i < pes->extra_es.i_size; i++ ) {