]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
dvb: Add table parsing when in raw mode
authorAndreas Öman <andreas@lonelycoder.com>
Mon, 22 Oct 2012 09:26:24 +0000 (11:26 +0200)
committerAndreas Öman <andreas@lonelycoder.com>
Thu, 25 Oct 2012 11:06:05 +0000 (13:06 +0200)
src/dvb/dvb.h
src/dvb/dvb_adapter.c
src/dvb/dvb_fe.c
src/dvb/dvb_input_filtered.c
src/dvb/dvb_input_raw.c
src/dvb/dvb_tables.c
src/epggrab/module/eit.c
src/epggrab/module/opentv.c
src/psi.c

index 4cdc7e4d50bef9cf6c9a16cd6304df87c91bf26f..8d7929a9af84d22e59c04875ce160f9f10e4d917 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/dvb/frontend.h>
 #include <pthread.h>
 #include "htsmsg.h"
+#include "psi.h"
 
 struct service;
 struct th_dvb_table;
@@ -107,6 +108,8 @@ typedef struct th_dvb_mux_instance {
 
 
   LIST_HEAD(, th_dvb_table) tdmi_tables;
+  int tdmi_num_tables;
+
   TAILQ_HEAD(, th_dvb_table) tdmi_table_queue;
   int tdmi_table_initial;
 
@@ -150,6 +153,22 @@ typedef struct th_dvb_mux_instance {
 } th_dvb_mux_instance_t;
 
 
+
+
+/**
+ * When in raw mode we need to enqueue raw TS packet
+ * to a different thread because we need to hold
+ * global_lock when doing delivery of the tables
+ */
+TAILQ_HEAD(dvb_table_feed_queue, dvb_table_feed);
+
+typedef struct dvb_table_feed {
+  TAILQ_ENTRY(dvb_table_feed) dtf_link;
+  uint8_t dtf_tsb[188];
+} dvb_table_feed_t;
+
+
+
 /**
  * DVB Adapter (one of these per physical adapter)
  */
@@ -236,6 +255,14 @@ typedef struct th_dvb_adapter {
 
   int tda_rawmode;
 
+
+  struct dvb_table_feed_queue tda_table_feed;
+  pthread_cond_t tda_table_feed_cond;  // Bound to tda_delivery_mutex
+
+  // PIDs that needs to be requeued and processed as tables
+  uint8_t tda_table_filter[8192];
+
+
 } th_dvb_adapter_t;
 
 /**
@@ -262,6 +289,7 @@ typedef struct th_dvb_table {
   int tdt_fd;
 
   LIST_ENTRY(th_dvb_table) tdt_link;
+  th_dvb_mux_instance_t *tdt_tdmi;
 
   char *tdt_name;
 
@@ -278,6 +306,10 @@ typedef struct th_dvb_table {
   int tdt_table;
   int tdt_mask;
 
+  int tdt_destroyed;
+  int tdt_refcount;
+
+  psi_section_t tdt_sect; // Manual reassembly
 
 } th_dvb_table_t;
 
@@ -459,12 +491,10 @@ void dvb_table_add_pmt(th_dvb_mux_instance_t *tdmi, int pmt_pid);
 
 void dvb_table_rem_pmt(th_dvb_mux_instance_t *tdmi, int pmt_pid);
 
-void dvb_table_fastswitch(th_dvb_mux_instance_t *tdmi);
-
 void tdt_add(th_dvb_mux_instance_t *tdmi, int table, int mask,
             int (*callback)(th_dvb_mux_instance_t *tdmi, uint8_t *buf, int len,
                             uint8_t tableid, void *opaque), void *opaque,
-            const char *name, int flags, int pid, th_dvb_table_t *tdt);
+            const char *name, int flags, int pid);
 
 int dvb_pidx11_callback
   (th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len,
@@ -475,6 +505,10 @@ int dvb_pidx11_callback
 #define TDT_CA                 0x4
 #define TDT_TDT           0x8
 
+void dvb_table_dispatch(uint8_t *sec, int r, th_dvb_table_t *tdt);
+
+void dvb_table_release(th_dvb_table_t *tdt);
+
 /**
  * Satellite configuration
  */
index 73c48b6ba8fb9baafb4c89a39d408a22e99dc3b5..c3ad82b76bc770367fc6ce256c8b146ea8da5616 100644 (file)
@@ -451,7 +451,7 @@ tda_add(int adapter_num)
 
   TAILQ_INSERT_TAIL(&dvb_adapters, tda, tda_global_link);
 
-  dvb_input_filtered_setup(tda);
+  dvb_input_raw_setup(tda);
 
   if(tda->tda_sat)
     dvb_satconf_init(tda);
@@ -796,12 +796,25 @@ dvb_adapter_input_dvr(void *aux)
     /* not enough data */
     if (r < 188) continue;
 
+    int wakeup_table_feed = 0;  // Just wanna wakeup once
+
     pthread_mutex_lock(&tda->tda_delivery_mutex);
     /* Process */
     while (r >= 188) {
   
       /* sync */
       if (tsb[i] == 0x47) {
+       
+       if(!(tsb[i+1] & 0x80)) { // Only dispatch to table parser if not error
+         int pid = (tsb[i+1] & 0x1f) << 8 | tsb[i+2];
+         if(tda->tda_table_filter[pid]) {
+           dvb_table_feed_t *dtf = malloc(sizeof(dvb_table_feed_t));
+           memcpy(dtf->dtf_tsb, tsb + i, 188);
+           TAILQ_INSERT_TAIL(&tda->tda_table_feed, dtf, dtf_link);
+           wakeup_table_feed = 1;
+         }
+       }
+
         LIST_FOREACH(t, &tda->tda_transports, s_active_link)
           if(t->s_dvb_mux_instance == tda->tda_mux_current)
             ts_recv_packet1(t, tsb + i, NULL);
@@ -816,6 +829,9 @@ dvb_adapter_input_dvr(void *aux)
       }
     }
 
+    if(wakeup_table_feed)
+      pthread_cond_signal(&tda->tda_table_feed_cond);
+
     pthread_mutex_unlock(&tda->tda_delivery_mutex);
 
     /* reset buffer */
index 321ae860c354a0628a6fa0026ae4d8b8a074c6ca..1ebfda3a0537b2b8e2f5f63f1e81c479ec141eb2 100644 (file)
@@ -226,6 +226,8 @@ dvb_fe_stop(th_dvb_mux_instance_t *tdmi, int retune)
 {
   th_dvb_adapter_t *tda = tdmi->tdmi_adapter;
 
+  lock_assert(&global_lock);
+
   assert(tdmi == tda->tda_mux_current);
   tda->tda_mux_current = NULL;
 
index 468b524f938eabd6cbeedf23296687500d75722d..a4dddf264a0932abec5ef0ea15d08db5d2b76aba 100644 (file)
@@ -116,9 +116,6 @@ open_table(th_dvb_mux_instance_t *tdmi, th_dvb_table_t *tdt)
   struct epoll_event e;
   static int tdt_id_tally;
 
-  assert(tdt->tdt_fd == -1);
-  TAILQ_REMOVE(&tdmi->tdmi_table_queue, tdt, tdt_pending_link);
-
   tdt->tdt_fd = tvh_open(tda->tda_demux_path, O_RDWR, 0);
 
   if(tdt->tdt_fd != -1) {
@@ -173,47 +170,6 @@ tdt_close_fd(th_dvb_mux_instance_t *tdmi, th_dvb_table_t *tdt)
 }
 
 
-/**
- *
- */
-static void
-dvb_proc_table(th_dvb_mux_instance_t *tdmi, th_dvb_table_t *tdt, uint8_t *sec,
-              int r)
-{
-  int chkcrc = tdt->tdt_flags & TDT_CRC;
-  int tableid, len;
-  uint8_t *ptr;
-  int ret;
-
-  /* It seems some hardware (or is it the dvb API?) does not
-     honour the DMX_CHECK_CRC flag, so we check it again */
-  if(chkcrc && tvh_crc32(sec, r, 0xffffffff))
-    return;
-      
-  r -= 3;
-  tableid = sec[0];
-  len = ((sec[1] & 0x0f) << 8) | sec[2];
-  
-  if(len < r)
-    return;
-
-  ptr = &sec[3];
-  if(chkcrc) len -= 4;   /* Strip trailing CRC */
-
-  if(tdt->tdt_flags & TDT_CA)
-    ret = tdt->tdt_callback((th_dvb_mux_instance_t *)tdt,
-                                sec, len + 3, tableid, tdt->tdt_opaque);
-  else if(tdt->tdt_flags & TDT_TDT)
-    ret = tdt->tdt_callback(tdmi, ptr, len, tableid, tdt);
-  else
-    ret = tdt->tdt_callback(tdmi, ptr, len, tableid, tdt->tdt_opaque);
-  
-  if(ret == 0)
-    tdt->tdt_count++;
-
-  if(tdt->tdt_flags & TDT_QUICKREQ)
-    dvb_table_fastswitch(tdmi);
-}
 
 /**
  *
@@ -250,7 +206,7 @@ dvb_table_input(void *aux)
            break;
 
        if(tdt != NULL) {
-         dvb_proc_table(tdmi, tdt, sec, r);
+         dvb_table_dispatch(sec, r, tdt);
 
          /* Any tables pending (that wants a filter/fd), close this one */
          if(TAILQ_FIRST(&tdmi->tdmi_table_queue) != NULL &&
@@ -259,6 +215,7 @@ dvb_table_input(void *aux)
            cycle_barrier = getmonoclock() + 100000;
            tdt = TAILQ_FIRST(&tdmi->tdmi_table_queue);
            assert(tdt != NULL);
+           TAILQ_REMOVE(&tdmi->tdmi_table_queue, tdt, tdt_pending_link);
 
            open_table(tdmi, tdt);
          }
index b1677805e4acd5996b9e21fe6ca3b79b3a2618cf..0c3f2a56307aef49884a168931395beecb8f8460 100644 (file)
@@ -42,6 +42,7 @@
 static void
 open_service(th_dvb_adapter_t *tda, service_t *s)
 {
+  // NOP -- We receive all PIDs anyway
 }
 
 
@@ -53,6 +54,7 @@ open_service(th_dvb_adapter_t *tda, service_t *s)
 static void
 close_service(th_dvb_adapter_t *tda, service_t *s)
 {
+  // NOP -- open_service() is a NOP
 }
 
 
@@ -62,6 +64,9 @@ close_service(th_dvb_adapter_t *tda, service_t *s)
 static void
 open_table(th_dvb_mux_instance_t *tdmi, th_dvb_table_t *tdt)
 {
+  th_dvb_adapter_t *tda = tdmi->tdmi_adapter;
+  assert(tdt->tdt_pid < 0x2000);
+  tda->tda_table_filter[tdt->tdt_pid] = 1;
 }
 
 
@@ -71,8 +76,84 @@ open_table(th_dvb_mux_instance_t *tdmi, th_dvb_table_t *tdt)
 static void
 close_table(th_dvb_mux_instance_t *tdmi, th_dvb_table_t *tdt)
 {
+  th_dvb_adapter_t *tda = tdmi->tdmi_adapter;
+  assert(tdt->tdt_pid < 0x2000);
+  tda->tda_table_filter[tdt->tdt_pid] = 0;
+}
+
+
+/**
+ *
+ */
+static void
+got_section(const uint8_t *data, size_t len, void *opaque)
+{
+  th_dvb_table_t *tdt = opaque;
+  dvb_table_dispatch((uint8_t *)data, len, tdt);
+}
+
+
+
+/**
+ * All the tables can be destroyed from any of the callbacks
+ * so we need to be a bit careful here
+ */
+static void
+dvb_table_raw_dispatch(th_dvb_mux_instance_t *tdmi,
+                      const dvb_table_feed_t *dtf)
+{
+  int pid = (dtf->dtf_tsb[1] & 0x1f) << 8 | dtf->dtf_tsb[2];
+  th_dvb_table_t *vec[tdmi->tdmi_num_tables], *tdt;
+  int i = 0;
+  LIST_FOREACH(tdt, &tdmi->tdmi_tables, tdt_link) {
+    vec[i++] = tdt;
+    tdt->tdt_refcount++;
+  }
+  assert(i == tdmi->tdmi_num_tables);
+  int len = tdmi->tdmi_num_tables; // can change during callbacks
+  for(i = 0; i < len; i++) {
+    tdt = vec[i];
+    if(!tdt->tdt_destroyed) {
+      if(tdt->tdt_pid == pid)
+       psi_section_reassemble(&tdt->tdt_sect, dtf->dtf_tsb,
+                              0, got_section, tdt);
+    }
+    dvb_table_release(tdt);
+  }
 }
 
+/**
+ *
+ */
+static void *
+dvb_table_input(void *aux)
+{
+  th_dvb_adapter_t *tda = aux;
+  th_dvb_mux_instance_t *tdmi;
+  dvb_table_feed_t *dtf;
+
+  while(1) {
+
+    pthread_mutex_lock(&tda->tda_delivery_mutex);
+  
+    while((dtf = TAILQ_FIRST(&tda->tda_table_feed)) == NULL)
+      pthread_cond_wait(&tda->tda_table_feed_cond, &tda->tda_delivery_mutex);
+    TAILQ_REMOVE(&tda->tda_table_feed, dtf, dtf_link);
+
+    pthread_mutex_unlock(&tda->tda_delivery_mutex);
+
+    pthread_mutex_lock(&global_lock);
+
+    if((tdmi = tda->tda_mux_current) != NULL)
+      dvb_table_raw_dispatch(tdmi, dtf);
+
+    pthread_mutex_unlock(&global_lock);
+    free(dtf);
+  }    
+  return NULL;
+}
+
+
 /**
  *
  */
@@ -84,5 +165,12 @@ dvb_input_raw_setup(th_dvb_adapter_t *tda)
   tda->tda_close_service = close_service;
   tda->tda_open_table    = open_table;
   tda->tda_close_table   = close_table;
+
+  TAILQ_INIT(&tda->tda_table_feed);
+  pthread_cond_init(&tda->tda_table_feed_cond, NULL);
+
+  pthread_t ptid;
+  pthread_create(&ptid, NULL, dvb_table_input, tda);
+
 }
 
index f292b4e588879f9be05356c830b696e4ed2bb4c9..529f5c505900c6f9a67794232baa37e6ea5675fd 100644 (file)
@@ -46,7 +46,7 @@
 /**
  *
  */
-void
+static void
 dvb_table_fastswitch(th_dvb_mux_instance_t *tdmi)
 {
   th_dvb_table_t *tdt;
@@ -72,6 +72,66 @@ dvb_table_fastswitch(th_dvb_mux_instance_t *tdmi)
 }
 
 
+/**
+ *
+ */
+void
+dvb_table_dispatch(uint8_t *sec, int r, th_dvb_table_t *tdt)
+{
+  if(tdt->tdt_destroyed)
+    return;
+
+  int chkcrc = tdt->tdt_flags & TDT_CRC;
+  int tableid, len;
+  uint8_t *ptr;
+  int ret;
+  th_dvb_mux_instance_t *tdmi = tdt->tdt_tdmi;
+
+  /* It seems some hardware (or is it the dvb API?) does not
+     honour the DMX_CHECK_CRC flag, so we check it again */
+  if(chkcrc && tvh_crc32(sec, r, 0xffffffff))
+    return;
+      
+  r -= 3;
+  tableid = sec[0];
+  len = ((sec[1] & 0x0f) << 8) | sec[2];
+  
+  if(len < r)
+    return;
+
+  if((tableid & tdt->tdt_mask) != tdt->tdt_table)
+    return;
+
+  ptr = &sec[3];
+  if(chkcrc) len -= 4;   /* Strip trailing CRC */
+
+  if(tdt->tdt_flags & TDT_CA)
+    ret = tdt->tdt_callback((th_dvb_mux_instance_t *)tdt,
+                                sec, len + 3, tableid, tdt->tdt_opaque);
+  else if(tdt->tdt_flags & TDT_TDT)
+    ret = tdt->tdt_callback(tdt->tdt_tdmi, ptr, len, tableid, tdt);
+  else
+    ret = tdt->tdt_callback(tdt->tdt_tdmi, ptr, len, tableid, tdt->tdt_opaque);
+  
+  if(ret == 0)
+    tdt->tdt_count++;
+
+  if(tdt->tdt_flags & TDT_QUICKREQ)
+    dvb_table_fastswitch(tdmi);
+}
+
+
+/**
+ *
+ */
+void
+dvb_table_release(th_dvb_table_t *tdt)
+{
+  if(--tdt->tdt_refcount == 0)
+    free(tdt);
+}
+
+
 /**
  *
  */
@@ -79,15 +139,17 @@ static void
 dvb_tdt_destroy(th_dvb_adapter_t *tda, th_dvb_mux_instance_t *tdmi,
                th_dvb_table_t *tdt)
 {
+  lock_assert(&global_lock);
+  assert(tdt->tdt_tdmi == tdmi);
   LIST_REMOVE(tdt, tdt_link);
+  tdmi->tdmi_num_tables--;
   tda->tda_close_table(tdmi, tdt);
   free(tdt->tdt_name);
-  free(tdt);
+  tdt->tdt_destroyed = 1;
+  dvb_table_release(tdt);
 }
 
 
-
-
 /**
  * Add a new DVB table
  */
@@ -95,7 +157,7 @@ void
 tdt_add(th_dvb_mux_instance_t *tdmi, int tableid, int mask,
        int (*callback)(th_dvb_mux_instance_t *tdmi, uint8_t *buf, int len,
                         uint8_t tableid, void *opaque), void *opaque,
-       const char *name, int flags, int pid, th_dvb_table_t *tdt)
+       const char *name, int flags, int pid)
 {
   th_dvb_table_t *t;
 
@@ -106,15 +168,12 @@ tdt_add(th_dvb_mux_instance_t *tdmi, int tableid, int mask,
   LIST_FOREACH(t, &tdmi->tdmi_tables, tdt_link) {
     if(pid == t->tdt_pid && 
        t->tdt_callback == callback && t->tdt_opaque == opaque) {
-      if (tdt)     free(tdt);
       return;
     }
   }
 
-
-  if(tdt == NULL)
-    tdt = calloc(1, sizeof(th_dvb_table_t));
-
+  th_dvb_table_t *tdt = calloc(1, sizeof(th_dvb_table_t));
+  tdt->tdt_refcount = 1;
   tdt->tdt_name = strdup(name);
   tdt->tdt_callback = callback;
   tdt->tdt_opaque = opaque;
@@ -122,9 +181,10 @@ tdt_add(th_dvb_mux_instance_t *tdmi, int tableid, int mask,
   tdt->tdt_flags = flags;
   tdt->tdt_table = tableid;
   tdt->tdt_mask = mask;
+  tdt->tdt_tdmi = tdmi;
   LIST_INSERT_HEAD(&tdmi->tdmi_tables, tdt, tdt_link);
+  tdmi->tdmi_num_tables++;
   tdt->tdt_fd = -1;
-  TAILQ_INSERT_TAIL(&tdmi->tdmi_table_queue, tdt, tdt_pending_link);
 
   tdmi->tdmi_adapter->tda_open_table(tdmi, tdt);
 }
@@ -510,7 +570,7 @@ dvb_cat_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len,
        break;
 
       tdt_add(tdmi, 0, 0, dvb_ca_callback, (void *)caid, "CA", 
-             TDT_CA, pid, NULL);
+             TDT_CA, pid);
       break;
 
     default:
@@ -959,12 +1019,12 @@ dvb_table_add_default_dvb(th_dvb_mux_instance_t *tdmi)
     table = 0x40;
   }
   tdt_add(tdmi, table, 0xff, dvb_nit_callback, NULL, "nit", 
-         TDT_QUICKREQ | TDT_CRC, 0x10, NULL);
+         TDT_QUICKREQ | TDT_CRC, 0x10);
 
   /* Service Descriptor Table and Bouqeut Allocation Table */
 
   tdt_add(tdmi, 0, 0, dvb_pidx11_callback, NULL, "pidx11", 
-         TDT_QUICKREQ | TDT_CRC, 0x11, NULL);
+         TDT_QUICKREQ | TDT_CRC, 0x11);
 }
 
 
@@ -983,7 +1043,7 @@ dvb_table_add_default_atsc(th_dvb_mux_instance_t *tdmi)
   }
 
   tdt_add(tdmi, tableid, 0xff, atsc_vct_callback, NULL, "vct",
-         TDT_QUICKREQ | TDT_CRC, 0x1ffb, NULL);
+         TDT_QUICKREQ | TDT_CRC, 0x1ffb);
 }
 
 
@@ -997,11 +1057,11 @@ dvb_table_add_default(th_dvb_mux_instance_t *tdmi)
 {
   /* Program Allocation Table */
   tdt_add(tdmi, 0x00, 0xff, dvb_pat_callback, NULL, "pat", 
-         TDT_QUICKREQ | TDT_CRC, 0, NULL);
+         TDT_QUICKREQ | TDT_CRC, 0);
 
   /* Conditional Access Table */
   tdt_add(tdmi, 0x1, 0xff, dvb_cat_callback, NULL, "cat", 
-         TDT_CRC, 1, NULL);
+         TDT_CRC, 1);
 
 
   switch(tdmi->tdmi_adapter->tda_type) {
@@ -1028,7 +1088,7 @@ dvb_table_add_pmt(th_dvb_mux_instance_t *tdmi, int pmt_pid)
 
   snprintf(pmtname, sizeof(pmtname), "PMT(%d)", pmt_pid);
   tdt_add(tdmi, 0x2, 0xff, dvb_pmt_callback, NULL, pmtname, 
-         TDT_CRC | TDT_QUICKREQ | TDT_TDT, pmt_pid, NULL);
+         TDT_CRC | TDT_QUICKREQ | TDT_TDT, pmt_pid);
 }
 
 void
index abad1ec281ed15fbca63266c5c1b13e61d0dfc2a..cb5bffd3511ecb9bf8e62631fa4ceb6290838ecc 100644 (file)
@@ -842,16 +842,16 @@ static void _eit_start
     tdt_add(tdmi, 0, 0, dvb_pidx11_callback, m, m->id, TDT_CRC, 3840, NULL);
     tdt_add(tdmi, 0, 0, _eit_callback, m, m->id, TDT_CRC, 3841, NULL);
 #endif
-    tdt_add(tdmi, 0, 0, dvb_pidx11_callback, m, m->id, TDT_CRC, 3002, NULL);
-    tdt_add(tdmi, 0, 0, _eit_callback, m, m->id, TDT_CRC, 3003, NULL);
+    tdt_add(tdmi, 0, 0, dvb_pidx11_callback, m, m->id, TDT_CRC, 3002);
+    tdt_add(tdmi, 0, 0, _eit_callback, m, m->id, TDT_CRC, 3003);
 
   /* Viasat Baltic (0x39) */
   } else if (!strcmp("viasat_baltic", m->id)) {
-    tdt_add(tdmi, 0, 0, _eit_callback, m, m->id, TDT_CRC, 0x39, NULL);
+    tdt_add(tdmi, 0, 0, _eit_callback, m, m->id, TDT_CRC, 0x39);
 
   /* Standard (0x12) */
   } else {
-    tdt_add(tdmi, 0, 0, _eit_callback, m, m->id, TDT_CRC, 0x12, NULL);
+    tdt_add(tdmi, 0, 0, _eit_callback, m, m->id, TDT_CRC, 0x12);
   }
   tvhlog(LOG_DEBUG, m->id, "install table handlers");
 }
index 8b6010aa197ad5e50506f4c334d6a311c1c60a93..0778ca82bb4260f36c04d16fceed825d7d1c7ffd 100644 (file)
@@ -669,7 +669,7 @@ static void _opentv_start
   while (*t) {
     // TODO: what about 0x46 (service description)
     tdt_add(tdmi, 0x4a, 0xff, _opentv_channel_callback, m,
-            m->id, TDT_CRC, *t++, NULL);
+            m->id, TDT_CRC, *t++);
   }
 
   /* Titles */
@@ -677,7 +677,7 @@ static void _opentv_start
   while (*t) {
     _opentv_status_get_pid(sta, *t);
     tdt_add(tdmi, 0xa0, 0xfc, _opentv_title_callback, m,
-            m->id, TDT_CRC | TDT_TDT, *t++, NULL);
+            m->id, TDT_CRC | TDT_TDT, *t++);
   }
 
   /* Summaries */
@@ -685,7 +685,7 @@ static void _opentv_start
   while (*t) {
     _opentv_status_get_pid(sta, *t);
     tdt_add(tdmi, 0xa8, 0xfc, _opentv_summary_callback, m,
-            m->id, TDT_CRC | TDT_TDT, *t++, NULL);
+            m->id, TDT_CRC | TDT_TDT, *t++);
   }
 }
 
index 7960ae2b29f11c80a6608ed8b020d3f4a2731b18..dcfec72a3184f48f73b3204b91d24da51997993c 100644 (file)
--- a/src/psi.c
+++ b/src/psi.c
@@ -63,8 +63,8 @@ psi_section_reassemble0(psi_section_t *ps, const uint8_t *data,
   if(crc && tvh_crc32(ps->ps_data, tsize, 0xffffffff))
     return -1;
 
-  cb(ps->ps_data, tsize - (crc ? 4 : 0), opaque);
   ps->ps_offset = 0;
+  cb(ps->ps_data, tsize - (crc ? 4 : 0), opaque);
   return len - excess;
 }