From: Jaroslav Kysela Date: Fri, 9 Feb 2018 16:01:54 +0000 (+0100) Subject: psi: fix ATSC VCT parsing when PAT has TSID 0 only, fixes #4908 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=6744ea1976e05d33e0383112f1ca75a7e7be0dfb;p=thirdparty%2Ftvheadend.git psi: fix ATSC VCT parsing when PAT has TSID 0 only, fixes #4908 --- diff --git a/src/input/mpegts.h b/src/input/mpegts.h index 76d81fe77..573b67513 100644 --- a/src/input/mpegts.h +++ b/src/input/mpegts.h @@ -1055,18 +1055,14 @@ static inline ssize_t sbuf_tsdebug_read(mpegts_mux_t *mm, sbuf_t *sb, int fd) { #endif -void mpegts_table_dispatch - (const uint8_t *sec, size_t r, void *mt); -static inline void mpegts_table_grab - (mpegts_table_t *mt) +void mpegts_table_dispatch(const uint8_t *sec, size_t r, void *mt); +static inline void mpegts_table_grab(mpegts_table_t *mt) { int v = atomic_add(&mt->mt_arefcount, 1); assert(v > 0); } -void mpegts_table_release_ - (mpegts_table_t *mt); -static inline int mpegts_table_release - (mpegts_table_t *mt) +void mpegts_table_release_(mpegts_table_t *mt); +static inline int mpegts_table_release(mpegts_table_t *mt) { int v = atomic_dec(&mt->mt_arefcount, 1); assert(v > 0); @@ -1077,20 +1073,20 @@ static inline int mpegts_table_release } return 0; } -int mpegts_table_type - ( mpegts_table_t *mt ); +int mpegts_table_type(mpegts_table_t *mt); mpegts_table_t *mpegts_table_add (mpegts_mux_t *mm, int tableid, int mask, mpegts_table_callback_t callback, void *opaque, const char *name, int subsys, int flags, int pid, int weight); -void mpegts_table_flush_all - (mpegts_mux_t *mm); -void mpegts_table_destroy ( mpegts_table_t *mt ); - -void mpegts_table_consistency_check( mpegts_mux_t *mm ); - -void dvb_bat_destroy - (struct mpegts_table *mt); +mpegts_table_t *mpegts_table_find + (mpegts_mux_t *mm, const char *name, void *opaque); +void mpegts_table_flush_all(mpegts_mux_t *mm); +void mpegts_table_destroy(mpegts_table_t *mt); +static inline void mpegts_table_reset(mpegts_table_t *mt) + { dvb_table_reset((mpegts_psi_table_t *)mt); } +void mpegts_table_consistency_check(mpegts_mux_t *mm); + +void dvb_bat_destroy(struct mpegts_table *mt); int dvb_pat_callback (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid); diff --git a/src/input/mpegts/dvb_psi.c b/src/input/mpegts/dvb_psi.c index b818251fc..415a9600a 100644 --- a/src/input/mpegts/dvb_psi.c +++ b/src/input/mpegts/dvb_psi.c @@ -169,6 +169,35 @@ dvberr: return priv; } +static int +mpegts_mux_tsid_check(mpegts_mux_t *mm, mpegts_table_t *mt, uint16_t tsid) +{ + if (tsid == 0 && !mm->mm_tsid_accept_zero_value) { + if (tvhlog_limit(&mm->mm_tsid_loglimit, 2)) { + tvhwarn(mt->mt_subsys, "%s: %s: TSID zero value detected, ignoring", mt->mt_name, mm->mm_nicename); + } + return 1; + } + tvhdebug(mt->mt_subsys, "%s: %p: tsid %04X (%d)", mt->mt_name, mm, tsid, tsid); + if (mm->mm_tsid != MPEGTS_TSID_NONE) { + if (mm->mm_tsid && mm->mm_tsid != tsid) { + if (++mm->mm_tsid_checks > 12) { + tvhwarn(mt->mt_subsys, "%s: %s: TSID change detected - old %04x (%d), new %04x (%d)", + mt->mt_name, mm->mm_nicename, mm->mm_tsid, mm->mm_tsid, tsid, tsid); + } else { + if (tvhtrace_enabled()) { + tvhtrace(mt->mt_subsys, "%s: %s: ignore TSID - old %04x (%d), new %04x (%d) (checks %d)", + mt->mt_name, mm->mm_nicename, mm->mm_tsid, mm->mm_tsid, tsid, tsid, mm->mm_tsid_checks); + } + return 0; /* keep rolling */ + } + } + mm->mm_tsid_checks = -100; + } + mpegts_mux_set_tsid(mm, tsid, 1); + return 0; +} + static void dvb_bouquet_comment ( bouquet_t *bq, mpegts_mux_t *mm ) { @@ -969,31 +998,9 @@ dvb_pat_callback tableid, tsid, 5, &st, §, &last, &ver, 3600); if (r != 1) return r; - if (tsid == 0 && !mm->mm_tsid_accept_zero_value) { - if (tvhlog_limit(&mm->mm_tsid_loglimit, 2)) { - tvhwarn(mt->mt_subsys, "%s: %s: TSID zero value detected, ignoring", mt->mt_name, mm->mm_nicename); - } - goto end; - } /* Multiplex */ - tvhdebug(mt->mt_subsys, "%s: %p: tsid %04X (%d)", mt->mt_name, mm, tsid, tsid); - if (mm->mm_tsid != MPEGTS_TSID_NONE) { - if (mm->mm_tsid && mm->mm_tsid != tsid) { - if (++mm->mm_tsid_checks > 12) { - tvhwarn(mt->mt_subsys, "%s: %s: TSID change detected - old %04x (%d), new %04x (%d)", - mt->mt_name, mm->mm_nicename, mm->mm_tsid, mm->mm_tsid, tsid, tsid); - } else { - if (tvhtrace_enabled()) { - tvhtrace(mt->mt_subsys, "%s: %s: ignore TSID - old %04x (%d), new %04x (%d) (checks %d)", - mt->mt_name, mm->mm_nicename, mm->mm_tsid, mm->mm_tsid, tsid, tsid, mm->mm_tsid_checks); - } - return 0; /* keep rolling */ - } - } - mm->mm_tsid_checks = -100; - } - mpegts_mux_set_tsid(mm, tsid, 1); + if (mpegts_mux_tsid_check(mm, mt, tsid)) goto end; /* Process each programme */ ptr += 5; @@ -1873,7 +1880,19 @@ atsc_vct_callback r = dvb_table_begin((mpegts_psi_table_t *)mt, ptr, len, tableid, extraid, 7, &st, §, &last, &ver, 0); if (r != 1) return r; - tvhdebug(mt->mt_subsys, "%s: tsid %04X (%d)", mt->mt_name, tsid, tsid); + + if (mm->mm_tsid == 0 && tsid) { + if (!LIST_EMPTY(&mm->mm_services)) { + mm->mm_tsid = tsid; + } else { + mpegts_table_t *mt2 = mpegts_table_find(mm, "pat", NULL); + if (mt2) mpegts_table_reset(mt2); + return -1; + } + } + + mm->mm_tsid_accept_zero_value = 1; /* ohh, we saw that */ + if (mpegts_mux_tsid_check(mm, mt, tsid)) goto end; /* # channels */ count = ptr[6]; @@ -1960,6 +1979,7 @@ next: len -= dlen + 32; } +end: return dvb_table_end((mpegts_psi_table_t *)mt, st, sect); } diff --git a/src/input/mpegts/mpegts_table.c b/src/input/mpegts/mpegts_table.c index 9a8f907b6..5f89450f3 100644 --- a/src/input/mpegts/mpegts_table.c +++ b/src/input/mpegts/mpegts_table.c @@ -173,6 +173,29 @@ mpegts_table_type ( mpegts_table_t *mt ) return type; } +/** + * Find a table + */ +mpegts_table_t *mpegts_table_find + ( mpegts_mux_t *mm, const char *name, void *opaque ) +{ + mpegts_table_t *mt; + + pthread_mutex_lock(&mm->mm_tables_lock); + mpegts_table_consistency_check(mm); + LIST_FOREACH(mt, &mm->mm_tables, mt_link) { + if (mt->mt_opaque != opaque) + continue; + if (strcmp(mt->mt_name, name)) + continue; + mpegts_table_consistency_check(mm); + break; + } + pthread_mutex_unlock(&mm->mm_tables_lock); + return mt; +} + + /** * Add a new DVB table */