]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
mpegts service: auto-disable services not seen in the PAT table
authorJaroslav Kysela <perex@perex.cz>
Thu, 4 Dec 2014 15:24:37 +0000 (16:24 +0100)
committerJaroslav Kysela <perex@perex.cz>
Thu, 4 Dec 2014 15:24:37 +0000 (16:24 +0100)
src/input/mpegts.h
src/input/mpegts/dvb_psi.c
src/service.c
src/service.h

index 7563d38997cedc4f87bfbe01155aee8184a2a6f3..c9676e1722802880c7c9474e5eae76d192580254 100644 (file)
@@ -447,6 +447,7 @@ struct mpegts_service
   uint16_t s_dvb_forcecaid;
   time_t   s_dvb_created;
   time_t   s_dvb_last_seen;
+  time_t   s_dvb_check_seen;
 
   /*
    * EIT/EPG control
index 337be73248fee5e1872791d744bc4fb90b663403..0b4e8a0d90f3bfaf6a6c5d254a0f752925a5bbdd 100644 (file)
@@ -1012,13 +1012,36 @@ dvb_pat_callback
   uint16_t nit_pid = 0;
   mpegts_mux_t          *mm  = mt->mt_mux;
   mpegts_table_state_t  *st  = NULL;
-  mpegts_service_t *s;
+  mpegts_service_t *s, *snext;
+  time_t last_seen;
 
   /* Begin */
   if (tableid != 0) return -1;
   tsid = (ptr[0] << 8) | ptr[1];
   r    = dvb_table_begin(mt, ptr, len, tableid, tsid, 5,
                          &st, &sect, &last, &ver);
+  if (r == 0 && mt->mt_opaque == NULL) {
+    /*
+     * Disable "not seen" services. It's quite easy algorithm which
+     * compares the time for the most recent services with others.
+     * If there is a big gap (24 hours) the service will be removed.
+     *
+     * Note that this code is run only when the PAT table scan is
+     * fully completed (all live services are known at this point).
+     */
+    last_seen = 0;
+    LIST_FOREACH(s, &mm->mm_services, s_dvb_mux_link)
+      if (last_seen < s->s_dvb_check_seen)
+        last_seen = s->s_dvb_check_seen;
+    for (s = LIST_FIRST(&mm->mm_services); s; s = snext) {
+      snext = LIST_NEXT(s, s_dvb_mux_link);
+      if (s->s_enabled && s->s_dvb_check_seen + 24 * 3600 < last_seen) {
+        tvhinfo("mpegts", "disabling service %s (missing in PAT)", s->s_nicename ?: "<unknown>");
+        service_set_enabled((service_t *)s, 0);
+      }
+    }
+    mt->mt_opaque = mm;
+  }
   if (r != 1) return r;
 
   /* Multiplex */
@@ -1044,6 +1067,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_check_seen = dispatch_clock;
         mpegts_table_add(mm, DVB_PMT_BASE, DVB_PMT_MASK, dvb_pmt_callback,
                          NULL, "pmt", MT_CRC | MT_QUICKREQ | MT_SCANSUBS,
                          pid);
@@ -2397,6 +2421,10 @@ psi_parse_pmt
 void
 psi_tables_default ( mpegts_mux_t *mm )
 {
+  mpegts_service_t *s;
+
+  LIST_FOREACH(s, &mm->mm_services, s_dvb_mux_link)
+    s->s_dvb_check_seen = s->s_dvb_last_seen;
   mpegts_table_add(mm, DVB_PAT_BASE, DVB_PAT_MASK, dvb_pat_callback,
                    NULL, "pat", MT_QUICKREQ | MT_CRC | MT_RECORD,
                    DVB_PAT_PID);
index 12e57815a6c408f9e6b98b309929b41ce37f52f1..40a2d32a3914567dd0b7b12392bb90c3c6ded141 100644 (file)
@@ -820,6 +820,17 @@ service_destroy(service_t *t, int delconf)
   service_unref(t);
 }
 
+void
+service_set_enabled(service_t *t, int enabled)
+{
+  if (t->s_enabled != !!enabled) {
+    t->s_enabled = !!enabled;
+    service_class_notify_enabled(t);
+    service_request_save(t, 0);
+    idnode_notify_simple(&t->s_id);
+  }
+}
+
 static int64_t
 service_channel_number ( service_t *s )
 {
index ce44900fd6baa8dd2f216d006b7ac637d17668ab..36f8fe606d6f0b5ea67967ee31d697e605fb7269 100644 (file)
@@ -521,6 +521,8 @@ int service_is_other(service_t *t);
 
 int service_is_encrypted ( service_t *t );
 
+void service_set_enabled ( service_t *t, int enabled );
+
 void service_destroy(service_t *t, int delconf);
 
 void service_remove_subscriber(service_t *t, struct th_subscription *s,