]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
linuxdvb: improve handling of la_exlusive mode, fixes #4278
authorJaroslav Kysela <perex@perex.cz>
Sat, 11 Mar 2017 18:58:58 +0000 (19:58 +0100)
committerJaroslav Kysela <perex@perex.cz>
Sat, 11 Mar 2017 18:59:05 +0000 (19:59 +0100)
src/input/mpegts/linuxdvb/linuxdvb_frontend.c

index 35a46c62f5c77757ef6c0381ff22b1adab3119c5..65bb711172ba4b5f2c0df404d242dc4d31cf31a1 100644 (file)
@@ -482,6 +482,7 @@ linuxdvb_frontend_is_enabled
   linuxdvb_adapter_t *la;
   tvh_hardware_t *th;
   char ubuf[UUID_HEX_SIZE];
+  int w;
 
   if (lfe->lfe_fe_path == NULL)
     return MI_IS_ENABLED_NEVER;
@@ -492,7 +493,7 @@ linuxdvb_frontend_is_enabled
   if (lfe->lfe_in_setup)
     return MI_IS_ENABLED_RETRY;
   if (lfe->lfe_type != DVB_TYPE_S)
-    return MI_IS_ENABLED_OK;
+    goto ok;
 
   /* check if any "blocking" tuner is running */
   LIST_FOREACH(th, &tvh_hardware, th_link) {
@@ -506,19 +507,34 @@ linuxdvb_frontend_is_enabled
           return MI_IS_ENABLED_NEVER; /* invalid master */
         if (lfe2->lfe_refcount <= 0)
           return MI_IS_ENABLED_RETRY; /* prefer master */
-        return linuxdvb_satconf_match_mux(lfe2->lfe_satconf, mm) ?
-               MI_IS_ENABLED_OK : MI_IS_ENABLED_RETRY;
+        if (linuxdvb_satconf_match_mux(lfe2->lfe_satconf, mm))
+          goto ok;
+        return MI_IS_ENABLED_RETRY;
       }
       if (lfe2->lfe_master &&
           !strcmp(lfe2->lfe_master, idnode_uuid_as_str(&lfe->ti_id, ubuf)) &&
           lfe2->lfe_refcount > 0) {
         if (lfe->lfe_satconf == NULL)
           return MI_IS_ENABLED_NEVER;
-        return linuxdvb_satconf_match_mux(lfe->lfe_satconf, mm) ?
-               MI_IS_ENABLED_OK : MI_IS_ENABLED_RETRY;
+        if (linuxdvb_satconf_match_mux(lfe->lfe_satconf, mm))
+          goto ok;
+        return MI_IS_ENABLED_RETRY;
       }
     }
   }
+
+
+ok:
+  if (lfe->lfe_adapter->la_exclusive) {
+    w = -1;
+    LIST_FOREACH(lfe2, &lfe->lfe_adapter->la_frontends, lfe_link) {
+      if (lfe2 == lfe) continue;
+      w = MAX(w, mpegts_input_get_weight((mpegts_input_t *)lfe2, mm, flags, weight));
+    }
+    if (w >= weight)
+      return MI_IS_ENABLED_RETRY;
+  }
+
   return MI_IS_ENABLED_OK;
 }
 
@@ -584,6 +600,31 @@ linuxdvb_frontend_stop_mux
   mpegts_pid_done(&lfe->lfe_pids);
 }
 
+static int
+linuxdvb_frontend_warm_mux ( mpegts_input_t *mi, mpegts_mux_instance_t *mmi )
+{
+  linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*)mi, *lfe2;
+  mpegts_mux_instance_t *lmmi;
+
+  if (!lfe->lfe_adapter->la_exclusive)
+    return 0;
+
+  /* Stop other active frontend */
+  LIST_FOREACH(lfe2, &lfe->lfe_adapter->la_frontends, lfe_link) {
+    if (lfe2 == lfe) continue;
+    pthread_mutex_lock(&lfe->mi_output_lock);
+    lmmi = LIST_FIRST(&lfe->mi_mux_active);
+    pthread_mutex_unlock(&lfe->mi_output_lock);
+    if (lmmi)
+      break;
+  }
+  if (lmmi) {
+    /* Stop */
+    lmmi->mmi_mux->mm_stop(lmmi->mmi_mux, 1, SM_CODE_ABORTED);
+  }
+  return 0;
+}
+
 static int
 linuxdvb_frontend_start_mux
   ( mpegts_input_t *mi, mpegts_mux_instance_t *mmi, int weight )
@@ -1989,6 +2030,7 @@ linuxdvb_frontend_create
   lfe->ti_wizard_get      = linuxdvb_frontend_wizard_get;
   lfe->ti_wizard_set      = linuxdvb_frontend_wizard_set;
   lfe->mi_is_enabled      = linuxdvb_frontend_is_enabled;
+  lfe->mi_warm_mux        = linuxdvb_frontend_warm_mux;
   lfe->mi_start_mux       = linuxdvb_frontend_start_mux;
   lfe->mi_stop_mux        = linuxdvb_frontend_stop_mux;
   lfe->mi_network_list    = linuxdvb_frontend_network_list;