]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
DVR/EPG: improve the EPG running check (pause/warm)
authorJaroslav Kysela <perex@perex.cz>
Sun, 22 Nov 2015 20:34:08 +0000 (21:34 +0100)
committerJaroslav Kysela <perex@perex.cz>
Sun, 22 Nov 2015 20:34:08 +0000 (21:34 +0100)
src/dvr/dvr.h
src/dvr/dvr_db.c
src/dvr/dvr_rec.c
src/epg.c
src/epg.h
src/epggrab/module/eit.c

index b48ae3cce7995a1681734610e4f57639cc8795e3..784c042627079f368c10797a16af48769cf636b0 100644 (file)
@@ -155,6 +155,7 @@ typedef struct dvr_entry {
 
   time_t de_running_start;
   time_t de_running_stop;
+  time_t de_running_pause;
 
   char *de_owner;
   char *de_creator;
@@ -514,7 +515,7 @@ void dvr_event_removed(epg_broadcast_t *e);
 
 void dvr_event_updated(epg_broadcast_t *e);
 
-void dvr_event_running(epg_broadcast_t *e, epg_source_t esrc, int running);
+void dvr_event_running(epg_broadcast_t *e, epg_source_t esrc, epg_running_t running);
 
 dvr_entry_t *dvr_entry_find_by_id(int id);
 
index 6779286eac5d0dbc190732075934e79e2fb3013a..c8d80ef37bed70cfd43d948102524ac0ccf00b31 100644 (file)
@@ -1615,7 +1615,7 @@ void dvr_event_updated(epg_broadcast_t *e)
 /**
  * Event running status is updated
  */
-void dvr_event_running(epg_broadcast_t *e, epg_source_t esrc, int running)
+void dvr_event_running(epg_broadcast_t *e, epg_source_t esrc, epg_running_t running)
 {
   dvr_entry_t *de;
   const char *srcname;
@@ -1626,9 +1626,17 @@ void dvr_event_running(epg_broadcast_t *e, epg_source_t esrc, int running)
     if (!dvr_entry_get_epg_running(de)) {
       atomic_exchange_time_t(&de->de_running_start, 0);
       atomic_exchange_time_t(&de->de_running_stop, 0);
+      atomic_exchange_time_t(&de->de_running_pause, 0);
       continue;
     }
-    if (running && de->de_dvb_eid == e->dvb_eid) {
+    if (running == EPG_RUNNING_NOW && de->de_dvb_eid == e->dvb_eid) {
+      if (de->de_running_pause) {
+        tvhdebug("dvr", "dvr entry %s event %s on %s - EPG unpause",
+                 idnode_uuid_as_sstr(&de->de_id),
+                 epg_broadcast_get_title(e, NULL),
+                 channel_get_name(e->channel));
+        atomic_exchange_time_t(&de->de_running_pause, 0);
+      }
       if (!de->de_running_start) {
         tvhdebug("dvr", "dvr entry %s event %s on %s - EPG marking start",
                  idnode_uuid_as_sstr(&de->de_id),
@@ -1644,7 +1652,8 @@ void dvr_event_running(epg_broadcast_t *e, epg_source_t esrc, int running)
                  epg_broadcast_get_title(e, NULL),
                  channel_get_name(e->channel));
       }
-    } else if ((!running && de->de_dvb_eid == e->dvb_eid) || running) {
+    } else if ((running == EPG_RUNNING_STOP && de->de_dvb_eid == e->dvb_eid) ||
+                running == EPG_RUNNING_NOW) {
       /*
        * make checking more robust
        * sometimes, the running bits are parsed randomly for a few moments
@@ -1662,6 +1671,7 @@ void dvr_event_running(epg_broadcast_t *e, epg_source_t esrc, int running)
                  channel_get_name(de->de_channel));
       }
       atomic_exchange_time_t(&de->de_running_stop, dispatch_clock);
+      atomic_exchange_time_t(&de->de_running_pause, 0);
       if (de->de_sched_state == DVR_RECORDING && de->de_running_start) {
         de->de_dont_reschedule = 1;
         dvr_stop_recording(de, SM_CODE_OK, 0, 0);
@@ -1670,6 +1680,14 @@ void dvr_event_running(epg_broadcast_t *e, epg_source_t esrc, int running)
                  epg_broadcast_get_title(e, NULL),
                  channel_get_name(de->de_channel));
       }
+    } else if (running == EPG_RUNNING_PAUSE && de->de_dvb_eid == e->dvb_eid) {
+      if (!de->de_running_pause) {
+        tvhdebug("dvr", "dvr entry %s event %s on %s - EPG pause",
+                 idnode_uuid_as_sstr(&de->de_id),
+                 epg_broadcast_get_title(e, NULL),
+                 channel_get_name(e->channel));
+        atomic_exchange_time_t(&de->de_running_pause, dispatch_clock);
+      }
     }
   }
 }
index 2ffd9295225505db472dbaf2c3b86df44fd416ee..250fb8f2b720d2d2a2d931841508aa89a8af471d 100644 (file)
@@ -1195,7 +1195,8 @@ dvr_thread(void *aux)
   streaming_message_t *sm, *sm2;
   th_pkt_t *pkt, *pkt2, *pkt3;
   streaming_start_t *ss = NULL;
-  int run = 1, started = 0, muxing = 0, comm_skip, epg_running = 0, rs;
+  int run = 1, started = 0, muxing = 0, comm_skip, rs;
+  int epg_running = 0, epg_pause = 0;
   int commercial = COMMERCIAL_UNKNOWN;
   int running_disabled;
   int64_t packets = 0, dts_offset = PTS_UNSET;
@@ -1226,7 +1227,9 @@ dvr_thread(void *aux)
       running_start = atomic_add_time_t(&de->de_running_start, 0);
       running_stop  = atomic_add_time_t(&de->de_running_stop,  0);
       if (running_start > 0) {
-        epg_running = running_start >= running_stop;
+        epg_running = running_start >= running_stop ? 1 : 0;
+        if (epg_running && atomic_add_time_t(&de->de_running_pause, 0) >= running_start)
+          epg_running = 2;
       } else if (running_stop == 0) {
         if (start_time + 2 >= dispatch_clock) {
           TAILQ_INSERT_TAIL(&backlog, sm, sm_link);
@@ -1251,7 +1254,7 @@ dvr_thread(void *aux)
       rs = DVR_RS_RUNNING;
       if (!epg_running)
         rs = DVR_RS_EPG_WAIT;
-      else if (pkt->pkt_commercial == COMMERCIAL_YES)
+      else if (pkt->pkt_commercial == COMMERCIAL_YES || epg_running == 2)
         rs = DVR_RS_COMMERCIAL;
       dvr_rec_set_state(de, rs, 0);
 
@@ -1264,8 +1267,12 @@ dvr_thread(void *aux)
         break;
       }
 
-      if (commercial != pkt->pkt_commercial)
+      if (epg_pause != (epg_running == 2)) {
+        epg_pause = epg_running == 2;
        muxer_add_marker(prch->prch_muxer);
+      } else if (commercial != pkt->pkt_commercial) {
+        muxer_add_marker(prch->prch_muxer);
+      }
 
       commercial = pkt->pkt_commercial;
 
@@ -1313,12 +1320,17 @@ dvr_thread(void *aux)
       break;
 
     case SMT_MPEGTS:
-      dvr_rec_set_state(de, !epg_running ? DVR_RS_EPG_WAIT : DVR_RS_RUNNING, 0);
+      rs = DVR_RS_RUNNING;
+      if (!epg_running)
+        rs = DVR_RS_EPG_WAIT;
+      else if (epg_running == 2)
+        rs = DVR_RS_COMMERCIAL;
+      dvr_rec_set_state(de, rs, 0);
 
       if (ss == NULL)
         break;
 
-      if (!epg_running) {
+      if ((rs == DVR_RS_COMMERCIAL && comm_skip) || !epg_running) {
         if (packets && running_start == 0) {
           dvr_streaming_restart(de, &run);
           packets = 0;
index 41474b92030cb5324a8c95fbeb483e819ba92147..abb34104b9c6ba680522d1d1b7b8a2f250196e4f 100644 (file)
--- a/src/epg.c
+++ b/src/epg.c
@@ -1418,7 +1418,7 @@ static void _epg_channel_timer_callback ( void *p )
 
   /* Clear now/next */
   if ((cur = ch->ch_epg_now)) {
-    if (cur->running) {
+    if (cur->running != EPG_RUNNING_STOP) {
       /* running? don't do anything */
       gtimer_arm(&ch->ch_epg_timer, _epg_channel_timer_callback, ch, 2);
       return;
@@ -1685,22 +1685,22 @@ epg_broadcast_t *epg_broadcast_find_by_eid ( channel_t *ch, uint16_t eid )
 }
 
 void epg_broadcast_notify_running
-  ( epg_broadcast_t *broadcast, epg_source_t esrc, int running )
+  ( epg_broadcast_t *broadcast, epg_source_t esrc, epg_running_t running )
 {
   channel_t *ch;
   epg_broadcast_t *now;
   int orunning = broadcast->running;
 
-  broadcast->running = !!running;
+  broadcast->running = running;
   ch = broadcast->channel;
   now = ch ? ch->ch_epg_now : NULL;
-  if (!running) {
+  if (running == EPG_RUNNING_STOP) {
     if (now == broadcast && orunning == broadcast->running)
       broadcast->stop = dispatch_clock - 1;
   } else {
     if (broadcast != now && now) {
-      now->running = 0;
-      dvr_event_running(now, esrc, 0);
+      now->running = EPG_RUNNING_STOP;
+      dvr_event_running(now, esrc, EPG_RUNNING_STOP);
     }
   }
   dvr_event_running(broadcast, esrc, running);
index 9a06fbfe97346dff3eea07e1c3ea986c8f8ffeca..7130faec60fde783ef7a11de6e6dac59bcb2e9b8 100644 (file)
--- a/src/epg.h
+++ b/src/epg.h
@@ -60,10 +60,17 @@ extern int epg_in_load;
  *
  */
 typedef enum {
-  EPG_SOURCE_NONE = 0,
-  EPG_SOURCE_EIT = 1,
+  EPG_SOURCE_NONE   = 0,
+  EPG_SOURCE_EIT    = 1,
 } epg_source_t;
 
+typedef enum {
+  EPG_RUNNING_STOP  = 0,
+  EPG_RUNNING_WARM  = 1,
+  EPG_RUNNING_NOW   = 2,
+  EPG_RUNNING_PAUSE = 3,
+} epg_running_t;
+
 /* ************************************************************************
  * Genres
  * ***********************************************************************/
@@ -470,7 +477,7 @@ epg_broadcast_t *epg_broadcast_find_by_id  ( uint32_t id );
 epg_broadcast_t *epg_broadcast_clone
   ( struct channel *channel, epg_broadcast_t *src, int *save );
 void epg_broadcast_notify_running
-  ( epg_broadcast_t *b, epg_source_t esrc, int running );
+  ( epg_broadcast_t *b, epg_source_t esrc, epg_running_t running );
 
 /* Mutators */
 int epg_broadcast_set_episode
index f1fff22ad6d1c02a075ae79e446c3a9850e0d9d2..f611ba2e687b09eabf0748e2f9b1965f7f5942b8 100644 (file)
@@ -409,6 +409,7 @@ static int _eit_process_event_one
   epg_broadcast_t *ebc;
   epg_episode_t *ee;
   epg_serieslink_t *es;
+  epg_running_t run;
   eit_event_t ev;
 
   /* Core fields */
@@ -548,10 +549,19 @@ static int _eit_process_event_one
   if (ev.desc)    lang_str_destroy(ev.desc);
 
   /* use running flag only for current broadcast */
-  if (running && tableid == 0x4e && sect == 0)
-    epg_broadcast_notify_running(ebc, EPG_SOURCE_EIT, running == 4);
-  if (running && running != 4 && tableid == 0x4e && sect == 1)
-    epg_broadcast_notify_running(ebc, EPG_SOURCE_EIT, 0);
+  if (running && tableid == 0x4e) {
+    if (sect == 0) {
+      switch (running) {
+      case 2:  run = EPG_RUNNING_WARM;  break;
+      case 3:  run = EPG_RUNNING_PAUSE; break;
+      case 4:  run = EPG_RUNNING_NOW;   break;
+      default: run = EPG_RUNNING_STOP;  break;
+      }
+      epg_broadcast_notify_running(ebc, EPG_SOURCE_EIT, run);
+    } else if (sect == 1 && running != 2 && running != 3 && running != 4) {
+      epg_broadcast_notify_running(ebc, EPG_SOURCE_EIT, EPG_RUNNING_STOP);
+    }
+  }
 
   return 0;
 }