]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
psi: fix ATSC VCT parsing when PAT has TSID 0 only, fixes #4908
authorJaroslav Kysela <perex@perex.cz>
Fri, 9 Feb 2018 16:01:54 +0000 (17:01 +0100)
committerJaroslav Kysela <perex@perex.cz>
Fri, 9 Feb 2018 16:31:43 +0000 (17:31 +0100)
src/input/mpegts.h
src/input/mpegts/dvb_psi.c
src/input/mpegts/mpegts_table.c

index 76d81fe7750c41bd6e1b267b30593c9db01fd91a..573b675133c3b33e4f456c6a199ff7a611ffabc4 100644 (file)
@@ -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);
index b818251fce663ac06bf809973777b6585b7cdf15..415a9600a6fbe855c038bc003c07519ad3a0a1de 100644 (file)
@@ -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, &sect, &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, &sect, &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);
 }
 
index 9a8f907b68ee1414f23f97e65822908e03da3164..5f89450f33a0da902e79dbf8753cfa89b7f45292 100644 (file)
@@ -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
  */