]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
SAT>IP client: block master tuners until slaves are fine
authorJaroslav Kysela <perex@perex.cz>
Mon, 21 Mar 2016 08:47:05 +0000 (09:47 +0100)
committerJaroslav Kysela <perex@perex.cz>
Mon, 21 Mar 2016 12:26:51 +0000 (13:26 +0100)
src/input/mpegts/satip/satip_frontend.c
src/input/mpegts/satip/satip_private.h
src/input/mpegts/satip/satip_satconf.c

index 840c665c01f710e954efe1591d844a676be9ab22..13c61c2bd32d056f7d92d7dda0afa7563ae3f247 100644 (file)
@@ -505,9 +505,7 @@ satip_frontend_match_satcfg
   high2 = mc2->dmc_fe_freq > 11700000;
   if (high1 != high2)
     return 0;
-
-  /* return unique hash for the active satcfg greater than zero */
-  return 1 | (high1 ? 2 : 0) | ((int)mc1->u.dmc_fe_qpsk.polarisation << 8) | (position << 16);
+  return 1;
 }
 
 static int
@@ -986,6 +984,39 @@ skip:
   return 0;
 }
 
+static int
+satip_frontend_other_is_waiting( satip_frontend_t *lfe )
+{
+  satip_frontend_t *lfe2;
+  int r;
+
+  TAILQ_FOREACH(lfe2, &lfe->sf_device->sd_frontends, sf_link) {
+    if (lfe == lfe2) continue;
+    pthread_mutex_lock(&lfe2->sf_dvr_lock);
+    r = lfe2->sf_wait_for & (1 << lfe->sf_number);
+    pthread_mutex_unlock(&lfe2->sf_dvr_lock);
+    if (r)
+      return 1;
+  }
+  return 0;
+}
+
+static void
+satip_frontend_wake_other_waiting( satip_frontend_t *lfe )
+{
+  satip_frontend_t *lfe2;
+
+  TAILQ_FOREACH(lfe2, &lfe->sf_device->sd_frontends, sf_link) {
+    if (lfe == lfe2) continue;
+    pthread_mutex_lock(&lfe2->sf_dvr_lock);
+    if (lfe2->sf_running && lfe2->sf_wait_for & (1 << lfe->sf_number)) {
+      lfe2->sf_wait_for &= ~(1 << lfe->sf_number);
+      tvh_write(lfe2->sf_dvr_pipe.wr, "o", 1);
+    }
+    pthread_mutex_unlock(&lfe2->sf_dvr_lock);
+  }
+}
+
 static void
 satip_frontend_extra_shutdown
   ( satip_frontend_t *lfe, uint8_t *session, long stream_id )
@@ -1120,6 +1151,7 @@ satip_frontend_close_rtsp
   tvhpoll_add(efd, &ev, 1);
 
   http_client_close(*rtsp);
+  satip_frontend_wake_other_waiting(lfe);
   *rtsp = NULL;
 }
 
@@ -1282,12 +1314,21 @@ new_tune:
 
   u64_2 = getfastmonoclock();
 
-  while (!start) {
+  pthread_mutex_lock(&lfe->sf_dvr_lock);
+  if (lfe->sf_wait_for == 0) start |= 2; else start &= ~2;
+  pthread_mutex_unlock(&lfe->sf_dvr_lock);
+
+  while (start != 3) {
+
+    nfds = tvhpoll_wait(efd, ev, 1, rtsp ? 55 : -1);
 
-    nfds = tvhpoll_wait(efd, ev, 1, rtsp ? 50 : -1);
+    pthread_mutex_lock(&lfe->sf_dvr_lock);
+    if (lfe->sf_wait_for == 0) start |= 2; else start &= ~2;
+    pthread_mutex_unlock(&lfe->sf_dvr_lock);
 
     if (!tvheadend_is_running()) { exit_flag = 1; goto done; }
-    if (rtsp && getfastmonoclock() - u64_2 > 50000) /* 50ms */
+    if (rtsp && (getfastmonoclock() - u64_2 > 50000 || /* 50ms */
+                 satip_frontend_other_is_waiting(lfe)))
       satip_frontend_close_rtsp(lfe, buf, efd, &rtsp);
     if (nfds <= 0) continue;
 
@@ -1428,6 +1469,8 @@ new_tune:
         } else if (b[0] == 's') {
           start = 1;
           goto done;
+        } else if (b[0] == 'o') {
+          continue;
         }
       }
       tvhtrace("satip", "%s - input thread received mux close", buf);
@@ -1544,6 +1587,8 @@ new_tune:
         } else if (b[0] == 's') {
           start = 1; running = 0;
           continue;
+        } else if (b[0] == 'o') {
+          continue;
         }
       }
       tvhtrace("satip", "%s - input thread received mux close", buf);
@@ -1607,6 +1652,7 @@ new_tune:
             satip_frontend_tuning_error(lfe, tr);
             fatal = 1;
           } else {
+            satip_frontend_wake_other_waiting(lfe);
             strncpy((char *)session, rtsp->hc_rtsp_session ?: "", sizeof(session));
             session[sizeof(session)-1] = '\0';
             stream_id = rtsp->hc_rtsp_stream_id;
@@ -1810,6 +1856,9 @@ done:
   tvhpoll_destroy(efd);
   lfe->sf_display_name = NULL;
   lfe->sf_curmux = NULL;
+
+  satip_frontend_wake_other_waiting(lfe);
+
   return NULL;
 #undef PKTS
 }
index 347bcedb29163c0555eb05e77e17da4362872fb7..42e6e814b1544c192d64b659adf7b3da5ccc5455 100644 (file)
@@ -157,6 +157,7 @@ struct satip_frontend
   uint32_t                   sf_seq;
   dvb_mux_t                 *sf_curmux;
   time_t                     sf_last_data_tstamp;
+  uint32_t                   sf_wait_for;
  
   /*
    * Configuration
index de8d2513ee3fc1dd93b7de528100ba3d4d74fdf8..5699c2346d8b2818a696e02b01af7f45c7721b56 100644 (file)
@@ -90,6 +90,16 @@ satip_satconf_in_network_group
   return sfc2 != NULL;
 }
 
+static int
+satip_satconf_hash ( mpegts_mux_t *mm, int position )
+{
+  dvb_mux_conf_t *mc = &((dvb_mux_t *)mm)->lm_tuning;
+  assert(position <= 0x7fff);
+  return 1 | (mc->dmc_fe_freq > 11700000 ? 2 : 0) |
+         ((int)mc->u.dmc_fe_qpsk.polarisation << 8) |
+         (position << 16);
+}
+
 static int
 satip_satconf_check_limits
   ( satip_frontend_t *lfe, satip_satconf_t *sfc, mpegts_mux_t *mm,
@@ -110,9 +120,13 @@ satip_satconf_check_limits
 
 retry:
   memset(hashes, 0, size * sizeof(int));
-  count = 1;
   lowest = INT_MAX;
   lowest_lfe = NULL;
+
+  /* add wanted mux to hashes */
+  hashes[0] = satip_satconf_hash(mm, sfc->sfc_position);
+  count = 1;
+
   TAILQ_FOREACH(lfe2, &lfe->sf_device->sd_frontends, sf_link) {
     if (lfe == lfe2 || !lfe2->sf_running || lfe2->sf_type != DVB_TYPE_S)
       continue;
@@ -132,14 +146,14 @@ retry:
     } else {
       w2 = -1;
     }
-    r = satip_frontend_match_satcfg(lfe2, mm, 0, -1);
-    if (r && manage) {
+    if (manage) {
       w2 = lfe2->mi_get_weight(mi2, mm2, flags);;
       if (w2 < lowest) {
         lowest = w2;
         lowest_lfe = lfe2;
       }
     }
+    r = satip_satconf_hash(mm2, lfe2->sf_position);
     for (i = 0; i < size; i++) {
       if (hashes[i] == r)
         break;
@@ -154,6 +168,9 @@ retry:
     return 1;
   if (manage) {
     /* free tuner with lowest weight */
+    pthread_mutex_lock(&lfe->sf_dvr_lock);
+    lfe->sf_wait_for |= 1 << lowest_lfe->sf_number;
+    pthread_mutex_unlock(&lfe->sf_dvr_lock);
     mm2 = lowest_lfe->sf_req->sf_mmi->mmi_mux;
     mm2->mm_stop(mm2, 1, SM_CODE_SUBSCRIPTION_OVERRIDDEN);
     goto retry;