]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
dvb psi reorganize - create parsing library
authorJaroslav Kysela <perex@perex.cz>
Mon, 23 Mar 2015 09:30:49 +0000 (10:30 +0100)
committerJaroslav Kysela <perex@perex.cz>
Mon, 23 Mar 2015 14:28:04 +0000 (15:28 +0100)
Makefile
src/input/mpegts.h
src/input/mpegts/dvb.h
src/input/mpegts/dvb_psi.c
src/input/mpegts/dvb_psi_lib.c [new file with mode: 0644]
src/input/mpegts/mpegts_table.c

index fb4549257220f57fb1f37db627b2c598c18d9e3f..9dac791a1d3d59f72e0dd547008636e5173efdfc 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -225,13 +225,15 @@ SRCS += src/muxer.c \
 # Optional code
 #
 
-# MPEGTS core
+# MPEGTS core, order by usage (psi lib, tsdemux)
 SRCS-$(CONFIG_MPEGTS) += \
        src/descrambler/descrambler.c \
        src/descrambler/caclient.c \
        src/input/mpegts.c \
        src/input/mpegts/mpegts_pid.c \
        src/input/mpegts/mpegts_input.c \
+       src/input/mpegts/tsdemux.c \
+       src/input/mpegts/dvb_psi_lib.c \
        src/input/mpegts/mpegts_network.c \
        src/input/mpegts/mpegts_mux.c \
        src/input/mpegts/mpegts_service.c \
@@ -240,9 +242,8 @@ SRCS-$(CONFIG_MPEGTS) += \
        src/input/mpegts/dvb_charset.c \
        src/input/mpegts/dvb_psi.c \
        src/input/mpegts/fastscan.c \
-       src/input/mpegts/tsdemux.c \
        src/input/mpegts/mpegts_mux_sched.c \
-  src/input/mpegts/mpegts_network_scan.c \
+        src/input/mpegts/mpegts_network_scan.c
 
 # MPEGTS DVB
 SRCS-${CONFIG_MPEGTS_DVB} += \
index 8d17964ed71fcf791b88d33d9de1eb1c5ed9c04f..3708c06f3cf75d9de07249593c4c4d33a21018fa 100644 (file)
@@ -32,7 +32,6 @@
 
 #define MPEGTS_ONID_NONE        0xFFFF
 #define MPEGTS_TSID_NONE        0xFFFF
-#define MPEGTS_PSI_SECTION_SIZE 5000
 #define MPEGTS_FULLMUX_PID      0x2000
 #define MPEGTS_TABLES_PID       0x2001
 #define MPEGTS_PID_NONE         0xFFFF
@@ -119,9 +118,6 @@ struct mpegts_packet
 typedef int (*mpegts_table_callback_t)
   ( mpegts_table_t*, const uint8_t *buf, int len, int tableid );
 
-typedef void (*mpegts_psi_section_callback_t)
-  ( const uint8_t *tsb, size_t len, void *opaque );
-
 struct mpegts_table_mux_cb
 {
   int tag;
@@ -129,13 +125,6 @@ struct mpegts_table_mux_cb
               const uint8_t dtag, const uint8_t *dptr, int dlen );
 };
 
-struct mpegts_psi_section
-{
-  int     ps_offset;
-  int     ps_lock;
-  uint8_t ps_data[MPEGTS_PSI_SECTION_SIZE];
-};
-
 typedef struct mpegts_table_state
 {
   int      tableid;
@@ -267,13 +256,6 @@ struct mpegts_table_feed {
   uint8_t mtf_tsb[0];
 };
 
-/*
- * Assemble SI section
- */
-void mpegts_psi_section_reassemble
-  ( mpegts_psi_section_t *ps, const uint8_t *tsb, int crc, int ccerr,
-    mpegts_psi_section_callback_t cb, void *opaque );
-
 /* **************************************************************************
  * Logical network
  * *************************************************************************/
@@ -963,6 +945,33 @@ 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);
+
+int dvb_pat_callback
+  (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid);
+int dvb_cat_callback
+  (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid);
+int dvb_pmt_callback
+  (struct mpegts_table *mt, const uint8_t *ptr, int len, int tabelid);
+int dvb_nit_callback
+  (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid);
+int dvb_bat_callback
+  (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid);
+int dvb_fs_sdt_callback
+  (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid);
+int dvb_sdt_callback
+  (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid);
+int dvb_tdt_callback
+  (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid);
+int atsc_vct_callback
+  (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid);
+
+void psi_tables_default ( struct mpegts_mux *mm );
+void psi_tables_dvb     ( struct mpegts_mux *mm );
+void psi_tables_atsc_t  ( struct mpegts_mux *mm );
+void psi_tables_atsc_c  ( struct mpegts_mux *mm );
+
 mpegts_service_t *mpegts_service_create0
   ( mpegts_service_t *ms, const idclass_t *class, const char *uuid,
     mpegts_mux_t *mm, uint16_t sid, uint16_t pmt_pid, htsmsg_t *conf );
index 034200ac1d92932c7450d0aace51ad4df49a1d15..8a74924662365e94b7d63f6d775f83fe65b4c371 100644 (file)
@@ -199,6 +199,29 @@ do {\
   DVB_LOOP_INIT(ptr, len, off, lptr, llen);\
   DVB_DESC_EACH(lptr, llen, dtag, dlen, dptr)\
 
+/*
+ * SI typedefs
+ */
+
+#define MPEGTS_PSI_SECTION_SIZE 5000
+
+typedef struct mpegts_psi_section
+{
+  int     ps_offset;
+  int     ps_lock;
+  uint8_t ps_data[MPEGTS_PSI_SECTION_SIZE];
+} mpegts_psi_section_t;
+
+typedef void (*mpegts_psi_section_callback_t)
+  ( const uint8_t *tsb, size_t len, void *opaque );
+
+/*
+ * Assemble SI section
+ */
+void mpegts_psi_section_reassemble
+ ( mpegts_psi_section_t *ps, const uint8_t *tsb, int crc, int ccerr,
+   mpegts_psi_section_callback_t cb, void *opaque );
+
 /* PSI table callbacks */
 
 int dvb_table_end
@@ -209,32 +232,6 @@ int dvb_table_begin
    struct mpegts_table_state **st, int *sect, int *last, int *ver);
 void dvb_table_reset
   (struct mpegts_table *mt);
-void dvb_bat_destroy
-  (struct mpegts_table *mt);
-
-int dvb_pat_callback
-  (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid);
-int dvb_cat_callback
-  (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid);
-int dvb_pmt_callback  
-  (struct mpegts_table *mt, const uint8_t *ptr, int len, int tabelid);
-int dvb_nit_callback
-  (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid);
-int dvb_bat_callback  
-  (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid);
-int dvb_fs_sdt_callback
-  (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid);
-int dvb_sdt_callback
-  (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid);
-int dvb_tdt_callback
-  (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid);
-int atsc_vct_callback
-  (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid);
-
-void psi_tables_default ( struct mpegts_mux *mm );
-void psi_tables_dvb     ( struct mpegts_mux *mm );
-void psi_tables_atsc_t  ( struct mpegts_mux *mm );
-void psi_tables_atsc_c  ( struct mpegts_mux *mm );
 
 extern htsmsg_t *satellites;
 
index 7f4fa584e2214df94e2be33f578767ebf1671429..beba4a72ec80e1345c27d35db4486c94e7bfd6ac 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  MPEG TS Program Specific Information code
- *  Copyright (C) 2007 - 2010 Andreas man
+ *  Copyright (C) 2007 - 2010 Andreas Öman
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -81,44 +81,11 @@ typedef struct dvb_bat {
   LIST_HEAD(,dvb_bat_id)          bats;
 } dvb_bat_t;
 
-SKEL_DECLARE(mpegts_table_state_skel, struct mpegts_table_state);
-
 int dvb_bouquets_parse = 1;
 
 static int
 psi_parse_pmt(mpegts_mux_t *mux, mpegts_service_t *t, const uint8_t *ptr, int len);
 
-/* **************************************************************************
- * Lookup tables
- * *************************************************************************/
-
-static const int dvb_servicetype_map[][2] = {
-  { 0x01, ST_SDTV  }, /* SDTV (MPEG2) */
-  { 0x02, ST_RADIO }, 
-  { 0x11, ST_HDTV  }, /* HDTV (MPEG2) */
-  { 0x16, ST_SDTV  }, /* Advanced codec SDTV */
-  { 0x19, ST_HDTV  }, /* Advanced codec HDTV */
-  { 0x80, ST_SDTV  }, /* NET POA - Cabo SDTV */
-  { 0x91, ST_HDTV  }, /* Bell TV HDTV */
-  { 0x96, ST_SDTV  }, /* Bell TV SDTV */
-  { 0xA0, ST_HDTV  }, /* Bell TV tiered HDTV */
-  { 0xA4, ST_HDTV  }, /* DN HDTV */
-  { 0xA6, ST_HDTV  }, /* Bell TV tiered HDTV */
-  { 0xA8, ST_SDTV  }, /* DN advanced SDTV */
-  { 0xD3, ST_SDTV  }, /* SKY TV SDTV */
-};
-
-int
-dvb_servicetype_lookup ( int t )
-{
-  int i;
-  for (i = 0; i < ARRAY_SIZE(dvb_servicetype_map); i++) {
-    if (dvb_servicetype_map[i][0] == t)
-      return dvb_servicetype_map[i][1];
-  }
-  return -1;
-}
-
 static inline int
 mpegts_mux_alive(mpegts_mux_t *mm)
 {
@@ -871,199 +838,6 @@ dvb_bskyb_local_channels
 
 #endif /* ENABLE_MPEGTS_DVB */
 
-/* **************************************************************************
- * Tables
- * *************************************************************************/
-
-static int sect_cmp
-  ( struct mpegts_table_state *a, struct mpegts_table_state *b )
-{
-  if (a->tableid != b->tableid)
-    return a->tableid - b->tableid;
-  if (a->extraid < b->extraid)
-    return -1;
-  if (a->extraid > b->extraid)
-    return 1;
-  return 0;
-}
-
-static void
-mpegts_table_state_reset
-  ( mpegts_table_t *mt, mpegts_table_state_t *st, int last )
-{
-  int i;
-  mt->mt_finished = 0;
-  st->complete = 0;
-  st->version = 0xff;  /* invalid */
-  memset(st->sections, 0, sizeof(st->sections));
-  for (i = 0; i < last / 32; i++)
-    st->sections[i] = 0xFFFFFFFF;
-  st->sections[last / 32] = 0xFFFFFFFF << (31 - (last % 32));
-}
-
-static struct mpegts_table_state *
-mpegts_table_state_find
-  ( mpegts_table_t *mt, int tableid, uint64_t extraid, int last )
-{
-  struct mpegts_table_state *st;
-
-  /* Find state */
-  SKEL_ALLOC(mpegts_table_state_skel);
-  mpegts_table_state_skel->tableid = tableid;
-  mpegts_table_state_skel->extraid = extraid;
-  st = RB_INSERT_SORTED(&mt->mt_state, mpegts_table_state_skel, link, sect_cmp);
-  if (!st) {
-    st   = mpegts_table_state_skel;
-    SKEL_USED(mpegts_table_state_skel);
-    mt->mt_incomplete++;
-    mpegts_table_state_reset(mt, st, last);
-  }
-  return st;
-}
-
-/*
- * End table
- */
-static int
-dvb_table_complete
-  (mpegts_table_t *mt)
-{
-  if (mt->mt_incomplete || !mt->mt_complete) {
-    int total = 0;
-    mpegts_table_state_t *st;
-    RB_FOREACH(st, &mt->mt_state, link)
-      total++;
-    tvhtrace(mt->mt_name, "incomplete %d complete %d total %d",
-             mt->mt_incomplete, mt->mt_complete, total);
-    return 2;
-  }
-  if (!mt->mt_finished)
-    tvhdebug(mt->mt_name, "completed pid %d table %08X / %08x", mt->mt_pid, mt->mt_table, mt->mt_mask);
-  mt->mt_finished = 1;
-  return 0;
-}
-
-int
-dvb_table_end
-  (mpegts_table_t *mt, mpegts_table_state_t *st, int sect)
-{
-  int sa, sb;
-  uint32_t rem;
-  if (st && !st->complete) {
-    assert(sect >= 0 && sect <= 255);
-    sa = sect / 32;
-    sb = sect % 32;
-    st->sections[sa] &= ~(0x1 << (31 - sb));
-    if (!st->sections[sa]) {
-      rem = 0;
-      for (sa = 0; sa < 8; sa++)
-        rem |= st->sections[sa];
-      if (rem) return 1;
-      tvhtrace(mt->mt_name, "  tableid %02X extraid %016" PRIx64 " completed",
-               st->tableid, st->extraid);
-      st->complete = 1;
-      mt->mt_incomplete--;
-      return dvb_table_complete(mt);
-    }
-  } else if (st)
-    return dvb_table_complete(mt);
-  return 2;
-}
-
-/*
- * Begin table
- */
-int
-dvb_table_begin
-  (mpegts_table_t *mt, const uint8_t *ptr, int len,
-   int tableid, uint64_t extraid, int minlen,
-   mpegts_table_state_t **ret, int *sect, int *last, int *ver)
-{
-  mpegts_table_state_t *st;
-  uint32_t sa, sb;
-
-  /* Not long enough */
-  if (len < minlen) {
-    tvhdebug(mt->mt_name, "invalid table length %d min %d", len, minlen);
-    return -1;
-  }
-
-  /* Ignore next */
-  if((ptr[2] & 1) == 0)
-    return -1;
-
-  tvhtrace(mt->mt_name, "pid %02X tableid %02X extraid %016" PRIx64 " len %d",
-           mt->mt_pid, tableid, extraid, len);
-
-  /* Section info */
-  if (sect && ret) {
-    *sect = ptr[3];
-    *last = ptr[4];
-    *ver  = (ptr[2] >> 1) & 0x1F;
-    *ret = st = mpegts_table_state_find(mt, tableid, extraid, *last);
-    tvhtrace(mt->mt_name, "  section %d last %d ver %d (ver %d st %d incomp %d comp %d)",
-             *sect, *last, *ver, st->version, st->complete, mt->mt_incomplete, mt->mt_complete);
-
-    /* Ignore previous version */
-    /* This check is for the broken PMT tables where:
-     * last 0 version 21 = PCR + Audio PID 0x0044
-     * last 0 version 22 = Audio PID 0x0044, PCR + Video PID 0x0045
-     */
-    if (*last == 0 && st->version - 1 == *ver)
-      return -1;
-
-    /* New version */
-    if (st->version != *ver) {
-      if (st->complete == 2)
-        mt->mt_complete--;
-      if (st->complete)
-        mt->mt_incomplete++;
-      tvhtrace(mt->mt_name, "  new version, restart");
-      mpegts_table_state_reset(mt, st, *last);
-      st->version = *ver;
-    }
-
-    /* Complete? */
-    if (st->complete) {
-      tvhtrace(mt->mt_name, "  skip, already complete (%i)", st->complete);
-      if (st->complete == 1) {
-        st->complete = 2;
-        mt->mt_complete++;
-        return dvb_table_complete(mt);
-      } else if (st->complete == 2) {
-        return dvb_table_complete(mt);
-      }
-      assert(0);
-    }
-
-    /* Already seen? */
-    sa = *sect / 32;
-    sb = *sect % 32;
-    if (!(st->sections[sa] & (0x1 << (31 - sb)))) {
-      tvhtrace(mt->mt_name, "  skip, already seen");
-      return -1;
-    }
-  }
-
-  tvhlog_hexdump(mt->mt_name, ptr, len);
-
-  return 1;
-}
-
-void
-dvb_table_reset(mpegts_table_t *mt)
-{
-  mpegts_table_state_t *st;
-
-  tvhtrace(mt->mt_name, "pid %02X complete reset", mt->mt_pid);
-  mt->mt_incomplete = 0;
-  mt->mt_complete   = 0;
-  while ((st = RB_FIRST(&mt->mt_state)) != NULL) {
-    RB_REMOVE(&mt->mt_state, st, link);
-    free(st);
-  }
-}
-
 /*
  * PAT processing
  */
diff --git a/src/input/mpegts/dvb_psi_lib.c b/src/input/mpegts/dvb_psi_lib.c
new file mode 100644 (file)
index 0000000..4960496
--- /dev/null
@@ -0,0 +1,340 @@
+/*
+ *  MPEG TS Program Specific Information Library code
+ *  Copyright (C) 2007 - 2010 Andreas Öman
+ *  Copyright (C) 2015 Jaroslav Kysela
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "tvheadend.h"
+#include "input.h"
+#include "dvb.h"
+
+SKEL_DECLARE(mpegts_table_state_skel, struct mpegts_table_state);
+
+/* **************************************************************************
+ * Lookup tables
+ * *************************************************************************/
+
+static const int dvb_servicetype_map[][2] = {
+  { 0x01, ST_SDTV  }, /* SDTV (MPEG2) */
+  { 0x02, ST_RADIO },
+  { 0x11, ST_HDTV  }, /* HDTV (MPEG2) */
+  { 0x16, ST_SDTV  }, /* Advanced codec SDTV */
+  { 0x19, ST_HDTV  }, /* Advanced codec HDTV */
+  { 0x80, ST_SDTV  }, /* NET POA - Cabo SDTV */
+  { 0x91, ST_HDTV  }, /* Bell TV HDTV */
+  { 0x96, ST_SDTV  }, /* Bell TV SDTV */
+  { 0xA0, ST_HDTV  }, /* Bell TV tiered HDTV */
+  { 0xA4, ST_HDTV  }, /* DN HDTV */
+  { 0xA6, ST_HDTV  }, /* Bell TV tiered HDTV */
+  { 0xA8, ST_SDTV  }, /* DN advanced SDTV */
+  { 0xD3, ST_SDTV  }, /* SKY TV SDTV */
+};
+
+int
+dvb_servicetype_lookup ( int t )
+{
+  int i;
+  for (i = 0; i < ARRAY_SIZE(dvb_servicetype_map); i++) {
+    if (dvb_servicetype_map[i][0] == t)
+      return dvb_servicetype_map[i][1];
+  }
+  return -1;
+}
+
+/* **************************************************************************
+ * Tables
+ * *************************************************************************/
+
+/*
+ * Section assembly
+ */
+static int
+mpegts_psi_section_reassemble0
+  ( mpegts_psi_section_t *ps, const uint8_t *data,
+    int len, int start, int crc,
+    mpegts_psi_section_callback_t cb, void *opaque)
+{
+  int excess, tsize;
+
+  if(start) {
+    // Payload unit start indicator
+    ps->ps_offset = 0;
+    ps->ps_lock = 1;
+  }
+
+  if(!ps->ps_lock)
+    return -1;
+
+  memcpy(ps->ps_data + ps->ps_offset, data, len);
+  ps->ps_offset += len;
+
+  if(ps->ps_offset < 3) {
+    /* We don't know the total length yet */
+    return len;
+  }
+
+  tsize = 3 + (((ps->ps_data[1] & 0xf) << 8) | ps->ps_data[2]);
+
+  if(ps->ps_offset < tsize)
+    return len; // Not there yet
+
+  excess = ps->ps_offset - tsize;
+
+  if(crc && tvh_crc32(ps->ps_data, tsize, 0xffffffff))
+    return -1;
+
+  ps->ps_offset = 0;
+  if (cb)
+    cb(ps->ps_data, tsize - (crc ? 4 : 0), opaque);
+  return len - excess;
+}
+
+/**
+ *
+ */
+void
+mpegts_psi_section_reassemble
+  (mpegts_psi_section_t *ps, const uint8_t *tsb, int crc, int ccerr,
+   mpegts_psi_section_callback_t cb, void *opaque)
+{
+  int off  = tsb[3] & 0x20 ? tsb[4] + 5 : 4;
+  int pusi = tsb[1] & 0x40;
+  int r;
+
+  if (ccerr)
+    ps->ps_lock = 0;
+
+  if(off >= 188) {
+    ps->ps_lock = 0;
+    return;
+  }
+
+  if(pusi) {
+    int len = tsb[off++];
+    if(len > 0) {
+      if(len > 188 - off) {
+        ps->ps_lock = 0;
+        return;
+      }
+      mpegts_psi_section_reassemble0(ps, tsb + off, len, 0, crc, cb, opaque);
+      off += len;
+    }
+  }
+
+  while(off < 188) {
+    r = mpegts_psi_section_reassemble0(ps, tsb + off, 188 - off, pusi, crc,
+        cb, opaque);
+    if(r < 0) {
+      ps->ps_lock = 0;
+      break;
+    }
+    off += r;
+    pusi = 0;
+  }
+}
+
+/*
+ *
+ */
+
+static int sect_cmp
+  ( struct mpegts_table_state *a, struct mpegts_table_state *b )
+{
+  if (a->tableid != b->tableid)
+    return a->tableid - b->tableid;
+  if (a->extraid < b->extraid)
+    return -1;
+  if (a->extraid > b->extraid)
+    return 1;
+  return 0;
+}
+
+static void
+mpegts_table_state_reset
+  ( mpegts_table_t *mt, mpegts_table_state_t *st, int last )
+{
+  int i;
+  mt->mt_finished = 0;
+  st->complete = 0;
+  st->version = 0xff;  /* invalid */
+  memset(st->sections, 0, sizeof(st->sections));
+  for (i = 0; i < last / 32; i++)
+    st->sections[i] = 0xFFFFFFFF;
+  st->sections[last / 32] = 0xFFFFFFFF << (31 - (last % 32));
+}
+
+static struct mpegts_table_state *
+mpegts_table_state_find
+  ( mpegts_table_t *mt, int tableid, uint64_t extraid, int last )
+{
+  struct mpegts_table_state *st;
+
+  /* Find state */
+  SKEL_ALLOC(mpegts_table_state_skel);
+  mpegts_table_state_skel->tableid = tableid;
+  mpegts_table_state_skel->extraid = extraid;
+  st = RB_INSERT_SORTED(&mt->mt_state, mpegts_table_state_skel, link, sect_cmp);
+  if (!st) {
+    st   = mpegts_table_state_skel;
+    SKEL_USED(mpegts_table_state_skel);
+    mt->mt_incomplete++;
+    mpegts_table_state_reset(mt, st, last);
+  }
+  return st;
+}
+
+/*
+ * End table
+ */
+static int
+dvb_table_complete
+  (mpegts_table_t *mt)
+{
+  if (mt->mt_incomplete || !mt->mt_complete) {
+    int total = 0;
+    mpegts_table_state_t *st;
+    RB_FOREACH(st, &mt->mt_state, link)
+      total++;
+    tvhtrace(mt->mt_name, "incomplete %d complete %d total %d",
+             mt->mt_incomplete, mt->mt_complete, total);
+    return 2;
+  }
+  if (!mt->mt_finished)
+    tvhdebug(mt->mt_name, "completed pid %d table %08X / %08x", mt->mt_pid, mt->mt_table, mt->mt_mask);
+  mt->mt_finished = 1;
+  return 0;
+}
+
+int
+dvb_table_end
+  (mpegts_table_t *mt, mpegts_table_state_t *st, int sect)
+{
+  int sa, sb;
+  uint32_t rem;
+  if (st && !st->complete) {
+    assert(sect >= 0 && sect <= 255);
+    sa = sect / 32;
+    sb = sect % 32;
+    st->sections[sa] &= ~(0x1 << (31 - sb));
+    if (!st->sections[sa]) {
+      rem = 0;
+      for (sa = 0; sa < 8; sa++)
+        rem |= st->sections[sa];
+      if (rem) return 1;
+      tvhtrace(mt->mt_name, "  tableid %02X extraid %016" PRIx64 " completed",
+               st->tableid, st->extraid);
+      st->complete = 1;
+      mt->mt_incomplete--;
+      return dvb_table_complete(mt);
+    }
+  } else if (st)
+    return dvb_table_complete(mt);
+  return 2;
+}
+
+/*
+ * Begin table
+ */
+int
+dvb_table_begin
+  (mpegts_table_t *mt, const uint8_t *ptr, int len,
+   int tableid, uint64_t extraid, int minlen,
+   mpegts_table_state_t **ret, int *sect, int *last, int *ver)
+{
+  mpegts_table_state_t *st;
+  uint32_t sa, sb;
+
+  /* Not long enough */
+  if (len < minlen) {
+    tvhdebug(mt->mt_name, "invalid table length %d min %d", len, minlen);
+    return -1;
+  }
+
+  /* Ignore next */
+  if((ptr[2] & 1) == 0)
+    return -1;
+
+  tvhtrace(mt->mt_name, "pid %02X tableid %02X extraid %016" PRIx64 " len %d",
+           mt->mt_pid, tableid, extraid, len);
+
+  /* Section info */
+  if (sect && ret) {
+    *sect = ptr[3];
+    *last = ptr[4];
+    *ver  = (ptr[2] >> 1) & 0x1F;
+    *ret = st = mpegts_table_state_find(mt, tableid, extraid, *last);
+    tvhtrace(mt->mt_name, "  section %d last %d ver %d (ver %d st %d incomp %d comp %d)",
+             *sect, *last, *ver, st->version, st->complete, mt->mt_incomplete, mt->mt_complete);
+
+    /* Ignore previous version */
+    /* This check is for the broken PMT tables where:
+     * last 0 version 21 = PCR + Audio PID 0x0044
+     * last 0 version 22 = Audio PID 0x0044, PCR + Video PID 0x0045
+     */
+    if (*last == 0 && st->version - 1 == *ver)
+      return -1;
+
+    /* New version */
+    if (st->version != *ver) {
+      if (st->complete == 2)
+        mt->mt_complete--;
+      if (st->complete)
+        mt->mt_incomplete++;
+      tvhtrace(mt->mt_name, "  new version, restart");
+      mpegts_table_state_reset(mt, st, *last);
+      st->version = *ver;
+    }
+
+    /* Complete? */
+    if (st->complete) {
+      tvhtrace(mt->mt_name, "  skip, already complete (%i)", st->complete);
+      if (st->complete == 1) {
+        st->complete = 2;
+        mt->mt_complete++;
+        return dvb_table_complete(mt);
+      } else if (st->complete == 2) {
+        return dvb_table_complete(mt);
+      }
+      assert(0);
+    }
+
+    /* Already seen? */
+    sa = *sect / 32;
+    sb = *sect % 32;
+    if (!(st->sections[sa] & (0x1 << (31 - sb)))) {
+      tvhtrace(mt->mt_name, "  skip, already seen");
+      return -1;
+    }
+  }
+
+  tvhlog_hexdump(mt->mt_name, ptr, len);
+
+  return 1;
+}
+
+void
+dvb_table_reset(mpegts_table_t *mt)
+{
+  mpegts_table_state_t *st;
+
+  tvhtrace(mt->mt_name, "pid %02X complete reset", mt->mt_pid);
+  mt->mt_incomplete = 0;
+  mt->mt_complete   = 0;
+  while ((st = RB_FIRST(&mt->mt_state)) != NULL) {
+    RB_REMOVE(&mt->mt_state, st, link);
+    free(st);
+  }
+}
index 2dfb8bb05c606e8fc3284da97beba4c1a4416c31..f27b671fb9738793c4e025a0200a959f87f335b4 100644 (file)
@@ -295,96 +295,6 @@ mpegts_table_flush_all ( mpegts_mux_t *mm )
   pthread_mutex_unlock(&mm->mm_tables_lock);
 }
 
-/*
- * Section assembly
- */
-static int
-mpegts_psi_section_reassemble0
-  ( mpegts_psi_section_t *ps, const uint8_t *data, 
-    int len, int start, int crc,
-    mpegts_psi_section_callback_t cb, void *opaque)
-{
-  int excess, tsize;
-
-  if(start) {
-    // Payload unit start indicator
-    ps->ps_offset = 0;
-    ps->ps_lock = 1;
-  }
-
-  if(!ps->ps_lock)
-    return -1;
-
-  memcpy(ps->ps_data + ps->ps_offset, data, len);
-  ps->ps_offset += len;
-
-  if(ps->ps_offset < 3) {
-    /* We don't know the total length yet */
-    return len;
-  }
-
-  tsize = 3 + (((ps->ps_data[1] & 0xf) << 8) | ps->ps_data[2]);
-  if(ps->ps_offset < tsize)
-    return len; // Not there yet
-  
-  excess = ps->ps_offset - tsize;
-
-  if(crc && tvh_crc32(ps->ps_data, tsize, 0xffffffff))
-    return -1;
-
-  ps->ps_offset = 0;
-  if (cb)
-    cb(ps->ps_data, tsize - (crc ? 4 : 0), opaque);
-  return len - excess;
-}
-
-
-/**
- *
- */
-void
-mpegts_psi_section_reassemble
-  (mpegts_psi_section_t *ps, const uint8_t *tsb, int crc, int ccerr,
-   mpegts_psi_section_callback_t cb, void *opaque)
-{
-  int off  = tsb[3] & 0x20 ? tsb[4] + 5 : 4;
-  int pusi = tsb[1] & 0x40;
-  int r;
-
-  if (ccerr)
-    ps->ps_lock = 0;
-
-  if(off >= 188) {
-    ps->ps_lock = 0;
-    return;
-  }
-  
-  if(pusi) {
-    int len = tsb[off++];
-    if(len > 0) {
-      if(len > 188 - off) {
-        ps->ps_lock = 0;
-        return;
-      }
-      mpegts_psi_section_reassemble0(ps, tsb + off, len, 0, crc, cb, opaque);
-      off += len;
-    }
-  }
-
-  while(off < 188) {
-    r = mpegts_psi_section_reassemble0(ps, tsb + off, 188 - off, pusi, crc,
-        cb, opaque);
-    if(r < 0) {
-      ps->ps_lock = 0;
-      break;
-    }
-    off += r;
-    pusi = 0;
-  }
-}
-
-
 
 /******************************************************************************
  * Editor Configuration