]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
DVR: improve the segmented event logic for EITp/f, issue #4989
authorJaroslav Kysela <perex@perex.cz>
Wed, 7 Mar 2018 09:07:34 +0000 (10:07 +0100)
committerJaroslav Kysela <perex@perex.cz>
Wed, 7 Mar 2018 09:07:34 +0000 (10:07 +0100)
src/dvr/dvr_db.c

index de4e7c4ae033c227d0b9d935649799471d2529b5..30be723ccdcfe6d9f0aadae19fad5ac4b91bd726 100644 (file)
@@ -1096,33 +1096,22 @@ dvr_entry_create_from_htsmsg(htsmsg_t *conf, epg_broadcast_t *e)
 }
 
 /**
- * Determine stop time for the broadcast taking in
- * to account segmented programmes via EIT.
+ * Return the event for the last segment.
  */
-static time_t dvr_entry_get_segment_stop_extra( dvr_entry_t *de )
+static epg_broadcast_t *dvr_entry_get_segment_last( dvr_entry_t *de )
 {
-  time_t segment_stop_extra, start, stop, maximum_stop_time;
+  time_t start, stop, maximum_stop_time;
   int max_progs_to_check;
-  epg_broadcast_t *e, *next;
+  epg_broadcast_t *e, *next, *ret;
   epg_set_t *eplink1, *eplink2;
 
   if (!de)
-    return 0;
-
-  if (dvr_entry_get_epg_running(de))
-    return 0;
-
-  /* Return any cached value we have previous calculated. */
-  segment_stop_extra = de->de_segment_stop_extra;
-  if (segment_stop_extra) {
-    return segment_stop_extra;
-  }
+    return NULL;
 
   /* If we have no broadcast data then can not search for matches */
   e = de->de_bcast;
-  if (!e) {
-    return 0;
-  }
+  if (!e)
+    return NULL;
 
   eplink1 = e->episodelink;
 
@@ -1156,6 +1145,7 @@ static time_t dvr_entry_get_segment_stop_extra( dvr_entry_t *de )
     MAX_STOP_TIME = 9 * 60 * 60
   };
 
+  ret = NULL;
   start = e->start;
   stop  = e->stop;
   maximum_stop_time = start + MAX_STOP_TIME;
@@ -1170,16 +1160,45 @@ static time_t dvr_entry_get_segment_stop_extra( dvr_entry_t *de )
        * segment part of this programme. So extend our stop time
        * to include this programme.
        */
-      segment_stop_extra = next->stop - stop;
-      tvhinfo(LS_DVR, "Increasing stop for \"%s\" on \"%s\" \"%s\" by %"PRId64
-                      " seconds at start %"PRId64" and original stop %"PRId64,
-                      lang_str_get(e->title, NULL), DVR_CH_NAME(de), eplink1->uri,
-                      (int64_t)segment_stop_extra, (int64_t)start, (int64_t)stop);
+      ret = next;
     }
   }
 
-  /* Cache the value */
-  return de->de_segment_stop_extra = segment_stop_extra;
+  return ret;
+}
+
+/**
+ * Determine stop time for the broadcast taking in
+ * to account segmented programmes via EIT.
+ */
+static time_t dvr_entry_get_segment_stop_extra( dvr_entry_t *de )
+{
+  time_t segment_stop_extra;
+  epg_broadcast_t *e;
+
+  if (!de)
+    return 0;
+
+  /* Return any cached value we have previous calculated. */
+  if (de->de_segment_stop_extra)
+    return de->de_segment_stop_extra;
+
+  /* Do not update stop extra without the last segment */
+  e = dvr_entry_get_segment_last(de);
+  if (!e)
+    return 0;
+
+  segment_stop_extra = e->stop - de->de_bcast->stop;
+  if (segment_stop_extra != de->de_segment_stop_extra) {
+    tvhinfo(LS_DVR, "Increasing stop for \"%s\" on \"%s\" \"%s\" by %"PRId64
+                    " seconds at start %"PRId64" and original stop %"PRId64,
+                    lang_str_get(e->title, NULL), DVR_CH_NAME(de), e->episodelink->uri,
+                    (int64_t)segment_stop_extra, (int64_t)de->de_bcast->start,
+                    (int64_t)de->de_bcast->stop);
+    de->de_segment_stop_extra = segment_stop_extra;
+  }
+
+  return segment_stop_extra;
 }
 
 /**
@@ -2287,6 +2306,7 @@ void dvr_event_updated(epg_broadcast_t *e)
 void dvr_event_running(epg_broadcast_t *e, epg_running_t running)
 {
   dvr_entry_t *de;
+  epg_broadcast_t *e2;
   const char *srcname;
   char ubuf[UUID_HEX_SIZE];
 
@@ -2329,10 +2349,16 @@ void dvr_event_running(epg_broadcast_t *e, epg_running_t running)
        * (by definition) the first segment will be marked as stop long
        * before the second segment is marked as started. Otherwise if we
        * processed the stop then we will stop the dvr_thread from
-       * recording tv packets.
+       * recording tv packets. But if the event is behind the last segment,
+       * stop it.
        */
       if (de->de_segment_stop_extra) {
-        continue;
+        e2 = dvr_entry_get_segment_last(de);
+        for ( ; e2; e2 = epg_broadcast_get_prev(e2))
+          if (e == e2)
+            break;
+        if (e2)
+          continue;
       }
       /*
        * make checking more robust