]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
SAT>IP client: override tuners with lower weight for master/slave config
authorJaroslav Kysela <perex@perex.cz>
Sun, 20 Mar 2016 16:30:50 +0000 (17:30 +0100)
committerJaroslav Kysela <perex@perex.cz>
Mon, 21 Mar 2016 08:04:50 +0000 (09:04 +0100)
src/input/mpegts.h
src/input/mpegts/mpegts_input.c
src/input/mpegts/satip/satip_frontend.c
src/input/mpegts/satip/satip_private.h
src/input/mpegts/satip/satip_satconf.c

index ff515ad21258778855a2d459c95492080419a961..0642d0b45a1d2075f5646f6a23a9f70c0e3a7af8 100644 (file)
@@ -924,6 +924,7 @@ void mpegts_input_recv_packets
 int mpegts_input_get_weight ( mpegts_input_t *mi, mpegts_mux_t *mm, int flags );
 int mpegts_input_get_priority ( mpegts_input_t *mi, mpegts_mux_t *mm, int flags );
 int mpegts_input_get_grace ( mpegts_input_t *mi, mpegts_mux_t *mm );
+int mpegts_input_warm_mux ( mpegts_input_t *mi, mpegts_mux_instance_t *mmi );
 
 void mpegts_input_save ( mpegts_input_t *mi, htsmsg_t *c );
 
index a247bca66f265dce4a44ff56a7c370e62768da40..d7fc92bd44a6d33a2a8d4d8cdcfc7af5212e9303 100644 (file)
@@ -405,7 +405,7 @@ mpegts_input_get_priority ( mpegts_input_t *mi, mpegts_mux_t *mm, int flags )
   return mi->mi_priority;
 }
 
-static int
+int
 mpegts_input_warm_mux ( mpegts_input_t *mi, mpegts_mux_instance_t *mmi )
 {
   mpegts_mux_instance_t *cur;
index e464985dc2f8700134afe2f0e11ea56ea91d43d4..840c665c01f710e954efe1591d844a676be9ab22 100644 (file)
@@ -451,22 +451,48 @@ satip_frontend_get_grace ( mpegts_input_t *mi, mpegts_mux_t *mm )
 }
 
 static int
-satip_frontend_match_satcfg ( satip_frontend_t *lfe2, mpegts_mux_t *mm2 )
+satip_frontend_get_max_weight ( satip_frontend_t *lfe, mpegts_mux_t *mm, int flags )
+{
+  satip_frontend_t *lfe2;
+  int w = 0, w2;
+
+  TAILQ_FOREACH(lfe2, &lfe->sf_device->sd_frontends, sf_link) {
+    if (!lfe2->sf_running) continue;
+    if (lfe2->sf_type != DVB_TYPE_S) continue;
+    if (lfe2 != lfe) continue;
+    if (lfe->sf_master != lfe2->sf_number &&
+        lfe2->sf_master != lfe->sf_number) continue;
+    w2 = lfe2->mi_get_weight((mpegts_input_t *)lfe2, mm, flags);
+    if (w2 > w)
+      w = w2;
+  }
+  return w;
+}
+
+int
+satip_frontend_match_satcfg
+  ( satip_frontend_t *lfe2, mpegts_mux_t *mm2, int flags, int weight )
 {
   satip_frontend_t *lfe_master;
   mpegts_mux_t *mm1 = NULL;
   dvb_mux_conf_t *mc1, *mc2;
-  int position, high1, high2;
+  int position, weight2, high1, high2;
 
-  if (lfe2->sf_req == NULL || lfe2->sf_req->sf_mmi == NULL)
+  if (!lfe2->sf_running)
     return 0;
 
   lfe_master = lfe2;
   if (lfe2->sf_master)
     lfe_master = satip_frontend_find_by_number(lfe2->sf_device, lfe2->sf_master) ?: lfe2;
 
+  if (weight > 0) {
+    weight2 = satip_frontend_get_max_weight(lfe2, mm2, flags);
+    if (weight2 > 0 && weight2 < weight)
+      return 1;
+  }
+
   mm1 = lfe2->sf_req->sf_mmi->mmi_mux;
-  position = satip_satconf_get_position(lfe2, mm2, NULL, 0);
+  position = satip_satconf_get_position(lfe2, mm2, NULL, 0, 0, -1);
   if (position <= 0 || lfe_master->sf_position != position)
     return 0;
   mc1 = &((dvb_mux_t *)mm1)->lm_tuning;
@@ -479,7 +505,9 @@ satip_frontend_match_satcfg ( satip_frontend_t *lfe2, mpegts_mux_t *mm2 )
   high2 = mc2->dmc_fe_freq > 11700000;
   if (high1 != high2)
     return 0;
-  return 1;
+
+  /* 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);
 }
 
 static int
@@ -497,18 +525,18 @@ satip_frontend_is_enabled
   if (lfe->sf_type != DVB_TYPE_S) return 1;
   /* try to reuse any input for limited networks if allowed */
   if (lfe->sf_device->sd_all_tuners) {
-    position = satip_satconf_get_position(lfe, mm, &netlimit, 0);
+    position = satip_satconf_get_position(lfe, mm, &netlimit, 0, 0, -1);
     if (position <= 0) return 0;
     if (netlimit <= 0) goto cont;
     /* try to reuse any tuner input as slave */
     TAILQ_FOREACH(lfe2, &lfe->sf_device->sd_frontends, sf_link) {
       if (lfe2 == lfe) continue;
-      if (satip_frontend_match_satcfg(lfe2, mm))
+      if (satip_frontend_match_satcfg(lfe2, mm, flags, weight))
         return 1;
     }
   }
   /* check if the position is enabled */
-  position = satip_satconf_get_position(lfe, mm, NULL, 1);
+  position = satip_satconf_get_position(lfe, mm, NULL, 1, flags, weight);
   if (position <= 0)
     return 0;
   /* check if any "blocking" tuner is running */
@@ -519,13 +547,10 @@ cont:
     if (lfe->sf_master == lfe2->sf_number) {
       if (!lfe2->sf_running)
         return 0; /* master must be running */
-      return satip_frontend_match_satcfg(lfe2, mm);
-    }
-    if (lfe2->sf_master == lfe->sf_number && lfe2->sf_running) {
-      if (lfe2->sf_req == NULL || lfe2->sf_req->sf_mmi == NULL)
-        return 0;
-      return satip_frontend_match_satcfg(lfe2, mm);
+      return satip_frontend_match_satcfg(lfe2, mm, flags, weight);
     }
+    if (lfe2->sf_master == lfe->sf_number && lfe2->sf_running)
+      return satip_frontend_match_satcfg(lfe2, mm, flags, weight);
   }
   return 1;
 }
@@ -560,20 +585,34 @@ satip_frontend_stop_mux
 }
 
 static int
-satip_frontend_start_mux
-  ( mpegts_input_t *mi, mpegts_mux_instance_t *mmi, int weight )
+satip_frontend_warm_mux
+  ( mpegts_input_t *mi, mpegts_mux_instance_t *mmi )
 {
   satip_frontend_t *lfe = (satip_frontend_t*)mi;
-  dvb_mux_t *lm = (dvb_mux_t *)mmi->mmi_mux;
-  satip_tune_req_t *tr;
-  char buf1[256], buf2[256];
+  int r;
+
+  r = mpegts_input_warm_mux(mi, mmi);
+  if (r)
+    return r;
 
   if (lfe->sf_positions > 0) {
-    lfe->sf_position = satip_satconf_get_position(lfe, mmi->mmi_mux, NULL, 0);
+    lfe->sf_position = satip_satconf_get_position(lfe, mmi->mmi_mux, NULL, 2, 0, -1);
     if (lfe->sf_position <= 0)
       return SM_CODE_TUNING_FAILED;
   }
 
+  return 0;
+}
+
+static int
+satip_frontend_start_mux
+  ( mpegts_input_t *mi, mpegts_mux_instance_t *mmi, int weight )
+{
+  satip_frontend_t *lfe = (satip_frontend_t*)mi;
+  dvb_mux_t *lm = (dvb_mux_t *)mmi->mmi_mux;
+  satip_tune_req_t *tr;
+  char buf1[256], buf2[256];
+
   lfe->mi_display_name((mpegts_input_t*)lfe, buf1, sizeof(buf1));
   mpegts_mux_nice_name(mmi->mmi_mux, buf2, sizeof(buf2));
   tvhdebug("satip", "%s - starting %s", buf1, buf2);
@@ -1956,6 +1995,7 @@ satip_frontend_create
   lfe->ti_wizard_get     = satip_frontend_wizard_get;
   lfe->ti_wizard_set     = satip_frontend_wizard_set;
   lfe->mi_is_enabled     = satip_frontend_is_enabled;
+  lfe->mi_warm_mux       = satip_frontend_warm_mux;
   lfe->mi_start_mux      = satip_frontend_start_mux;
   lfe->mi_stop_mux       = satip_frontend_stop_mux;
   lfe->mi_network_list   = satip_frontend_network_list;
index a829f457e6c80515c59590009782b891507551f2..347bcedb29163c0555eb05e77e17da4362872fb7 100644 (file)
@@ -209,6 +209,9 @@ void satip_device_destroy_later( satip_device_t *sd, int after_ms );
 
 char *satip_device_nicename ( satip_device_t *sd, char *buf, int len );
 
+int satip_frontend_match_satcfg
+  ( satip_frontend_t *lfe2, mpegts_mux_t *mm2, int flags, int weight );
+
 satip_frontend_t *
 satip_frontend_create
   ( htsmsg_t *conf, satip_device_t *sd, dvb_fe_type_t type, int v2, int num );
@@ -237,7 +240,7 @@ int satip_satconf_get_grace
   ( satip_frontend_t *lfe, mpegts_mux_t *mm );
 
 int satip_satconf_get_position
-  ( satip_frontend_t *lfe, mpegts_mux_t *mm, int *netlimit, int check );
+  ( satip_frontend_t *lfe, mpegts_mux_t *mm, int *netlimit, int check, int flags, int weight );
 
 /*
  * RTSP part
index d835f5a0b848c4f1ecd664fc1993b51d6d92ec70..de8d2513ee3fc1dd93b7de528100ba3d4d74fdf8 100644 (file)
@@ -66,41 +66,121 @@ satip_satconf_get_grace
 }
 
 static int
-satip_satconf_check_network_limit
-  ( satip_frontend_t *lfe, satip_satconf_t *sfc, idnode_t *mn )
+satip_satconf_master_or_slave
+  ( satip_frontend_t *lfe1, satip_frontend_t *lfe2 )
+{
+  return lfe1->sf_number == lfe2->sf_master ||
+         lfe2->sf_number == lfe1->sf_master;
+}
+
+static int
+satip_satconf_in_network_group
+  ( satip_frontend_t *lfe, int network_group, idnode_t *mn )
 {
-  satip_frontend_t *lfe2;
   satip_satconf_t *sfc2;
-  int count;
 
-  count = 0;
+  TAILQ_FOREACH(sfc2, &lfe->sf_satconf, sfc_link) {
+    if (network_group > 0 &&
+        sfc2->sfc_network_group > 0 &&
+        sfc2->sfc_network_group == network_group)
+      break;
+    else if (idnode_set_exists(sfc2->sfc_networks, mn))
+      break;
+  }
+  return sfc2 != NULL;
+}
+
+static int
+satip_satconf_check_limits
+  ( satip_frontend_t *lfe, satip_satconf_t *sfc, mpegts_mux_t *mm,
+    int flags, int weight, int manage )
+{
+  satip_frontend_t *lfe2, *lowest_lfe;
+  mpegts_mux_t *mm2;
+  mpegts_input_t *mi2;
+  idnode_t *mn = &mm->mm_network->mn_id;
+  int count, size, lowest, w2, r, i, limit, *hashes;
+
+  size = 0;
   TAILQ_FOREACH(lfe2, &lfe->sf_device->sd_frontends, sf_link)
-    TAILQ_FOREACH(sfc2, &lfe2->sf_satconf, sfc_link) {
-      if (!lfe2->sf_running) continue;
-      if (sfc->sfc_network_group > 0 &&
-          sfc2->sfc_network_group > 0 &&
-          sfc2->sfc_network_group == sfc->sfc_network_group)
-        count++;
-      else if (idnode_set_exists(sfc2->sfc_networks, mn))
+    size++;
+  hashes = alloca(size * sizeof(int));
+
+  limit = sfc->sfc_network_limit > 0 ? sfc->sfc_network_limit : 1;
+
+retry:
+  memset(hashes, 0, size * sizeof(int));
+  count = 1;
+  lowest = INT_MAX;
+  lowest_lfe = NULL;
+  TAILQ_FOREACH(lfe2, &lfe->sf_device->sd_frontends, sf_link) {
+    if (lfe == lfe2 || !lfe2->sf_running || lfe2->sf_type != DVB_TYPE_S)
+      continue;
+    if (sfc->sfc_network_limit) {
+      if (!satip_satconf_in_network_group(lfe2, sfc->sfc_network_group, mn))
+        continue;
+    } else {
+      if (!satip_satconf_master_or_slave(lfe, lfe2))
+        continue;
+    }
+    mi2 = (mpegts_input_t *)lfe2;
+    mm2 = lfe2->sf_req->sf_mmi->mmi_mux;
+    if (weight > 0) {
+      w2 = lfe2->mi_get_weight(mi2, mm2, flags);
+      if (w2 < weight)
+        continue;
+    } else {
+      w2 = -1;
+    }
+    r = satip_frontend_match_satcfg(lfe2, mm, 0, -1);
+    if (r && manage) {
+      w2 = lfe2->mi_get_weight(mi2, mm2, flags);;
+      if (w2 < lowest) {
+        lowest = w2;
+        lowest_lfe = lfe2;
+      }
+    }
+    for (i = 0; i < size; i++) {
+      if (hashes[i] == r)
+        break;
+      if (!hashes[i]) {
+        hashes[i] = r;
         count++;
+        break;
+      }
     }
-
-  return count <= sfc->sfc_network_limit;
+  }
+  if (count <= limit)
+    return 1;
+  if (manage) {
+    /* free tuner with lowest weight */
+    mm2 = lowest_lfe->sf_req->sf_mmi->mmi_mux;
+    mm2->mm_stop(mm2, 1, SM_CODE_SUBSCRIPTION_OVERRIDDEN);
+    goto retry;
+  }
+  return 0;
 }
 
 int
 satip_satconf_get_position
-  ( satip_frontend_t *lfe, mpegts_mux_t *mm, int *netlimit, int check )
+  ( satip_frontend_t *lfe, mpegts_mux_t *mm, int *netlimit, int check, int flags, int weight )
 {
   satip_satconf_t *sfc;
   sfc = satip_satconf_find_ele(lfe, mm);
   if (sfc && sfc->sfc_enabled) {
     if (netlimit)
       *netlimit = sfc->sfc_network_limit;
-    if (!check || sfc->sfc_network_limit <= 0)
+    if (!check)
       return sfc->sfc_position;
-    if (satip_satconf_check_network_limit(lfe, sfc, &mm->mm_network->mn_id))
+    if (check > 1) {
+      satip_satconf_check_limits(lfe, sfc, mm, flags, weight, 1);
       return sfc->sfc_position;
+    } else {
+      if (sfc->sfc_network_limit <= 0)
+        return sfc->sfc_position;
+      if (satip_satconf_check_limits(lfe, sfc, mm, flags, weight, 0))
+        return sfc->sfc_position;
+    }
   } else {
     if (netlimit)
       *netlimit = 0;