]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
mpegts: add service and mux cleaning code feature/service-cleanup 423/head
authorAdam Sutton <dev@adamsutton.me.uk>
Tue, 10 Jun 2014 23:31:02 +0000 (00:31 +0100)
committerAdam Sutton <dev@adamsutton.me.uk>
Sun, 16 Nov 2014 19:53:25 +0000 (19:53 +0000)
src/input/mpegts.h
src/input/mpegts/dvb_psi.c
src/input/mpegts/mpegts_mux.c
src/input/mpegts/mpegts_network.c
src/input/mpegts/mpegts_service.c

index cf899a82848b3c4ee62d49b3bcbde7f17486929e..4c91caa0652ea9508bdc990a23daf62a8e132c0c 100644 (file)
@@ -298,6 +298,8 @@ struct mpegts_network
   char    *mn_charset;
   int      mn_idlescan;
   int      mn_ignore_chnum;
+  int      mn_autoclean_svc;
+  int      mn_autoclean_mux;
 };
 
 typedef enum mpegts_mux_scan_state
@@ -343,6 +345,12 @@ struct mpegts_mux
   uint16_t                mm_onid;
   uint16_t                mm_tsid;
 
+  /*
+   * Versioning
+   */
+  int64_t mm_created;
+  int64_t mm_updated;
+
   /*
    * Services
    */
@@ -445,6 +453,12 @@ struct mpegts_service
   int      s_dvb_prefcapid_lock;
   uint16_t s_dvb_forcecaid;
 
+  /*
+   * History
+   */
+  int64_t s_dvb_created;
+  int64_t s_dvb_updated;
+
   /*
    * EIT/EPG control
    */
index 817b0b74169543ae2d8525c4dd12bc5f5990981e..ab0045dae1f403d9d99a5afd7443672d02a3ac12 100644 (file)
@@ -1011,6 +1011,7 @@ dvb_pat_callback
   /* Multiplex */
   tvhdebug("pat", "tsid %04X (%d)", tsid, tsid);
   mpegts_mux_set_tsid(mm, tsid, 1);
+  mm->mm_updated = dispatch_clock;
   
   /* Process each programme */
   ptr += 5;
@@ -1031,6 +1032,7 @@ dvb_pat_callback
       tvhdebug("pat", "  sid %04X (%d) on pid %04X (%d)", sid, sid, pid, pid);
       int save = 0;
       if ((s = mpegts_service_find(mm, sid, pid, 1, &save))) {
+        s->s_dvb_updated = dispatch_clock;
         mpegts_table_add(mm, DVB_PMT_BASE, DVB_PMT_MASK, dvb_pmt_callback,
                          NULL, "pmt", MT_CRC | MT_QUICKREQ | MT_SCANSUBS,
                          pid);
@@ -1121,11 +1123,13 @@ dvb_pmt_callback
   sid = ptr[0] << 8 | ptr[1];
   r   = dvb_table_begin(mt, ptr, len, tableid, sid, 9, &st, &sect, &last, &ver);
   if (r != 1) return r;
+  mm->mm_updated = dispatch_clock;
 
   /* Find service */
   LIST_FOREACH(s, &mm->mm_services, s_dvb_mux_link)
     if (s->s_dvb_service_id == sid) break;
   if (!s) return -1;
+  s->s_dvb_updated = dispatch_clock;
 
   /* Process */
   tvhdebug("pmt", "sid %04X (%d)", sid, sid);
@@ -1486,6 +1490,10 @@ dvb_nit_callback
 #endif
           break;
       }
+
+      /* Update */
+      if (mux)
+        mm->mm_updated  = dispatch_clock;
     }
   }
 
@@ -1528,8 +1536,9 @@ dvb_sdt_callback
     LIST_FOREACH(mm, &mn->mn_muxes, mm_network_link)
       if (mm->mm_onid == onid && mm->mm_tsid == tsid)
         break;
-    goto done;
+    if (!mm) goto done;
   }
+  mm->mm_updated = dispatch_clock;
 
   /* Service loop */
   len -= 8;
@@ -1554,6 +1563,9 @@ dvb_sdt_callback
     s       = mpegts_service_find(mm, service_id, 0, 1, &save);
     charset = dvb_charset_find(mn, mm, s);
 
+    /* Update time and version */
+    s->s_dvb_updated = dispatch_clock;
+
     /* Descriptor loop */
     DVB_DESC_EACH(lptr, llen, dtag, dlen, dptr) {
       tvhtrace("sdt", "    dtag %02X dlen %d", dtag, dlen);
@@ -1645,7 +1657,8 @@ dvb_sdt_callback
 
   /* Done */
 done:
-  return dvb_table_end(mt, st, sect);
+  r = dvb_table_end(mt, st, sect);
+  return r;
 }
 
 /*
@@ -1677,6 +1690,7 @@ atsc_vct_callback
                       &st, &sect, &last, &ver);
   if (r != 1) return r;
   tvhdebug("vct", "tsid %04X (%d)", tsid, tsid);
+  mm->mm_updated = dispatch_clock;
 
   /* # channels */
   count = ptr[6];
@@ -1713,6 +1727,7 @@ atsc_vct_callback
     /* Find the service */
     if (!(s = mpegts_service_find(mm, sid, 0, 1, &save)))
       goto next;
+    s->s_dvb_updated = dispatch_clock;
 
     /* Update */
     if (strcmp(s->s_dvb_svcname ?: "", chname)) {
index dbb17f0c2610fc8d6f5559be677d4e8035a550ce..89733ecc9a864c33078b428918e337474fa6cac1 100644 (file)
@@ -440,7 +440,23 @@ const idclass_t mpegts_mux_class =
       .off      = offsetof(mpegts_mux_t, mm_pmt_06_ac3),
       .opts     = PO_ADVANCED,
     },
-    {}
+    {
+      .type     = PT_S64,
+      .id       = "created",
+      .name     = "Created",
+      .off      = offsetof(mpegts_mux_t, mm_created),
+      .opts     = PO_ADVANCED | PO_RDONLY,
+      .istime   = "%F %T",
+    },
+    {
+      .type     = PT_S64,
+      .id       = "updated",
+      .name     = "Updated",
+      .off      = offsetof(mpegts_mux_t, mm_updated),
+      .opts     = PO_ADVANCED | PO_RDONLY,
+      .istime   = "%F %T",
+    },
+    {},
   }
 };
 
@@ -463,7 +479,10 @@ mpegts_mux_delete ( mpegts_mux_t *mm, int delconf )
   char buf[256];
 
   mpegts_mux_nice_name(mm, buf, sizeof(buf));
-  tvhinfo("mpegts", "%s (%p) - deleting", buf, mm);
+  if (delconf)
+    tvhinfo("mpegts", "%s (%p) - deleting", buf, mm);
+  else
+    tvhtrace("mpegts", "%s (%p) - deleting", buf, mm);
   
   /* Stop */
   mm->mm_stop(mm, 1);
@@ -831,6 +850,21 @@ mpegts_mux_close_table ( mpegts_mux_t *mm, mpegts_table_t *mt )
  * Scanning
  * *************************************************************************/
 
+#define MPEGTS_AUTOCLEAN_PERIOD (86400L * 7) // 1 week
+
+static void
+mpegts_mux_clean_services ( const char *mname, mpegts_mux_t *mm )
+{
+  mpegts_service_t *s, *n;
+  for (s = LIST_FIRST(&mm->mm_services); s != NULL; s = n) {
+    n = LIST_NEXT(s, s_dvb_mux_link);
+    if (dispatch_clock < (s->s_dvb_updated + MPEGTS_AUTOCLEAN_PERIOD))
+      continue;
+    tvhinfo("mpegts", "%s - autoclean svc %s", mname, s->s_nicename);
+    service_destroy((service_t*)s, 1);
+  }
+}
+
 void
 mpegts_mux_scan_done ( mpegts_mux_t *mm, const char *buf, int res )
 {
@@ -853,6 +887,10 @@ mpegts_mux_scan_done ( mpegts_mux_t *mm, const char *buf, int res )
   }
   pthread_mutex_unlock(&mm->mm_tables_lock);
 
+  /* Check for out of date services */
+  if (mm->mm_network->mn_autoclean_svc)
+    mpegts_mux_clean_services(buf, mm);
+
   if (res)
     mpegts_network_scan_mux_done(mm);
   else
@@ -904,6 +942,15 @@ again:
     tvhinfo("mpegts", "%s - scan no data, failed", buf);
     mpegts_mux_scan_done(mm, buf, 0);
 
+    /* Mark disabled */
+    if (mm->mm_network->mn_autoclean_mux) {
+      if (dispatch_clock > (mm->mm_updated + MPEGTS_AUTOCLEAN_PERIOD)) {
+       tvhinfo("mpegts", "%s - autoclean mux", buf);
+        mm->mm_delete(mm, 1);
+        return;
+      }
+    }
+
   /* Pending tables (another 20s or 30s - bit arbitrary) */
   } else if (q) {
     tvhinfo("mpegts", "%s - scan needs more time", buf);
@@ -935,6 +982,9 @@ mpegts_mux_create0
     return NULL;
   }
 
+  /* Set time */
+  mm->mm_created             = dispatch_clock;
+
   /* Enabled by default */
   mm->mm_enabled             = 1;
   mm->mm_epg                 = 1;
index 4a0ac58fcd0976e8078fbadf7401f25d0aa8c581..c15cd1701098e2275619459eae9451228a07c542 100644 (file)
@@ -154,21 +154,14 @@ const idclass_t mpegts_network_class =
     {
       .type     = PT_BOOL,
       .id       = "autodiscovery",
-      .name     = "Network Discovery",
+      .name     = "Autodiscover Muxes",
       .off      = offsetof(mpegts_network_t, mn_autodiscovery),
       .def.i    = 1
     },
-    {
-      .type     = PT_BOOL,
-      .id       = "skipinitscan",
-      .name     = "Skip Initial Scan",
-      .off      = offsetof(mpegts_network_t, mn_skipinitscan),
-      .def.i    = 1
-    },
     {
       .type     = PT_BOOL,
       .id       = "idlescan",
-      .name     = "Idle Scan Muxes",
+      .name     = "Autoscan Muxes",
       .off      = offsetof(mpegts_network_t, mn_idlescan),
       .def.i    = 0,
       .notify   = mpegts_network_class_idlescan_notify,
@@ -180,6 +173,27 @@ const idclass_t mpegts_network_class =
       .off      = offsetof(mpegts_network_t, mn_ignore_chnum),
       .def.i    = 0,
     },
+    {
+      .type     = PT_BOOL,
+      .id       = "autoclean_svc`",
+      .name     = "Autoclean Services", 
+      .off      = offsetof(mpegts_network_t, mn_autoclean_svc),
+      .def.i    = 1,
+    },
+    {
+      .type     = PT_BOOL,
+      .id       = "autoclean_mux",
+      .name     = "Autoclean Muxes",
+      .off      = offsetof(mpegts_network_t, mn_autoclean_mux),
+      .def.i    = 1,
+    },
+    {
+      .type     = PT_BOOL,
+      .id       = "skipinitscan",
+      .name     = "Skip Initial Scan",
+      .off      = offsetof(mpegts_network_t, mn_skipinitscan),
+      .def.i    = 1
+    },
     {
       .type     = PT_STR,
       .id       = "charset",
index 1d561e09f30456d8446aa45dbd10e106effc5984..8831c84ae76d81e4ec5d1cfb7b5b19d3e24daf73 100644 (file)
@@ -183,6 +183,22 @@ const idclass_t mpegts_service_class =
       .off      = offsetof(mpegts_service_t, s_dvb_forcecaid),
       .opts     = PO_ADVANCED | PO_HEXA,
     },
+    {
+      .type   = PT_S64,
+      .id     = "created",
+      .name   = "Created",
+      .off    = offsetof(mpegts_service_t, s_dvb_created),
+      .opts   = PO_ADVANCED | PO_RDONLY,
+      .istime   = "%F %T",
+    },
+    {
+      .type   = PT_S64,
+      .id     = "updated",
+      .name   = "Updated",
+      .off    = offsetof(mpegts_service_t, s_dvb_updated),
+      .opts   = PO_ADVANCED | PO_RDONLY,
+      .istime   = "%F %T",
+    },
     {},
   }
 };
@@ -514,7 +530,8 @@ mpegts_service_create0
 
   if (service_create0((service_t*)s, class, uuid, S_MPEG_TS, conf) == NULL)
     return NULL;
-
+  s->s_dvb_created = dispatch_clock;
+  
   /* Create */
   sbuf_init(&s->s_tsbuf);
   if (!conf) {