]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
IPTV revamp
authorAndreas Öman <andreas@lonelycoder.com>
Wed, 19 Sep 2007 12:30:08 +0000 (12:30 +0000)
committerAndreas Öman <andreas@lonelycoder.com>
Wed, 19 Sep 2007 12:30:08 +0000 (12:30 +0000)
- Add correct probing of IPTV transports during startup
- Remove the 'iptvmux' configuration entity, instead we configure this directly on the service

channels.c
dvb.c
dvb.h
dvb_muxconfig.c
iptv_input.c
iptv_input.h
transports.c
transports.h
tvhead.h
v4l.c
v4l.h

index 7a388aabbe0ef6c4dc81b7794a5e7e631d16c7d7..8719227f45ceec7b76881e97933531dbed6a92ff 100644 (file)
@@ -76,19 +76,11 @@ transportcmp(th_transport_t *a, th_transport_t *b)
 
 
 int 
-transport_set_channel(th_transport_t *t, const char *name)
+transport_set_channel(th_transport_t *t, th_channel_t *ch)
 {
-  th_channel_t *ch;
   th_pid_t *tp;
   char *chname;
 
-  if(LIST_FIRST(&t->tht_pids) == NULL)
-    return -1;
-
-  if(t->tht_channel != NULL)
-    return 0;
-
-  ch = channel_find(name, 1);
   t->tht_channel = ch;
   LIST_INSERT_SORTED(&ch->ch_transports, t, tht_channel_link, transportcmp);
 
@@ -113,78 +105,42 @@ service_load(struct config_head *head)
 {
   const char *name,  *v;
   th_transport_t *t;
-  th_channel_t *ch;
+  int r = 1;
 
   if((name = config_get_str_sub(head, "channel", NULL)) == NULL)
     return;
 
-  ch = channel_find(name, 1);
-
   t = calloc(1, sizeof(th_transport_t));
+  t->tht_prio = atoi(config_get_str_sub(head, "prio", ""));
 
   if(0) {
 #ifdef ENABLE_INPUT_DVB
   } else if((v = config_get_str_sub(head, "dvbmux", NULL)) != NULL) {
-    if(dvb_configure_transport(t, v)) {
-      free(t);
-      return;
-    }
+    r = dvb_configure_transport(t, v, name);
 #endif
 #ifdef ENABLE_INPUT_IPTV
-  } else if((v = config_get_str_sub(head, "iptvmux", NULL)) != NULL) {
-    if(iptv_configure_transport(t, v)) {
-      free(t);
-      return;
-    }
+  } else if((v = config_get_str_sub(head, "iptv", NULL)) != NULL) {
+    r = iptv_configure_transport(t, v, head, name);
 #endif
 #ifdef ENABLE_INPUT_V4L
   } else if((v = config_get_str_sub(head, "v4lmux", NULL)) != NULL) {
-    if(v4l_configure_transport(t, v)) {
-      free(t);
-      return;
-    }
+    r = v4l_configure_transport(t, v, name);
 #endif
-  } else {
-    free(t);
-    return;
   }
+  if(r)
+    free(t);
+}
 
-  if((v = config_get_str_sub(head, "service_id", NULL)) != NULL)
-    t->tht_dvb_service_id = strtol(v, NULL, 0);
-
-  if((v = config_get_str_sub(head, "network_id", NULL)) != NULL)
-    t->tht_dvb_network_id = strtol(v, NULL, 0);
-
-  if((v = config_get_str_sub(head, "transport_id", NULL)) != NULL)
-    t->tht_dvb_transport_id = strtol(v, NULL, 0);
-
-  if((v = config_get_str_sub(head, "video", NULL)) != NULL)
-    transport_add_pid(t, strtol(v, NULL, 0), HTSTV_MPEG2VIDEO);
-
-  if((v = config_get_str_sub(head, "h264", NULL)) != NULL)
-    transport_add_pid(t, strtol(v, NULL, 0), HTSTV_H264);
-  
-  if((v = config_get_str_sub(head, "audio", NULL)) != NULL) 
-    transport_add_pid(t, strtol(v, NULL, 0), HTSTV_MPEG2AUDIO);
-  
-  if((v = config_get_str_sub(head, "ac3", NULL)) != NULL)
-    transport_add_pid(t, strtol(v, NULL, 0), HTSTV_AC3);
-
-  if((v = config_get_str_sub(head, "teletext", NULL)) != NULL)
-    transport_add_pid(t, strtol(v, NULL, 0), HTSTV_TELETEXT);
-
-  t->tht_prio = atoi(config_get_str_sub(head, "prio", ""));
-
-  transport_set_channel(t, name);
-
+void
+transport_link(th_transport_t *t, th_channel_t *ch)
+{
+  transport_set_channel(t, ch);
   transport_monitor_init(t);
   LIST_INSERT_HEAD(&all_transports, t, tht_global_link);
 }
 
 
 
-
-
 static void
 channel_load(struct config_head *head)
 {
diff --git a/dvb.c b/dvb.c
index 6d9f9805b6449f0376a8b385084ba1d965685f63..b08d16bbf2a0cd85e349d584bbf5f6b63d36b71c 100644 (file)
--- a/dvb.c
+++ b/dvb.c
@@ -782,7 +782,8 @@ dvb_sdt_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len,
                             transport_stream_id,
                             service_id, 1);
 
-      ret |= transport_set_channel(t, chname);
+       if(LIST_FIRST(&t->tht_pids) != NULL && t->tht_channel == NULL)
+        ret |= transport_set_channel(t, channel_find(chname, 1));
     }
   }
   return ret;
diff --git a/dvb.h b/dvb.h
index e9d62c8e7047d8f51fcc89d5ca8b4c4cde32e182..bcd47b9ce2c147a4128efb2cd0eb99044297e3ad 100644 (file)
--- a/dvb.h
+++ b/dvb.h
@@ -27,7 +27,8 @@ extern struct th_dvb_mux_list dvb_muxes;
 
 void dvb_init(void);
 
-int dvb_configure_transport(th_transport_t *t, const char *muxname);
+int dvb_configure_transport(th_transport_t *t, const char *muxname,
+                           const char *channel_name);
 
 int dvb_tune_tdmi(th_dvb_mux_instance_t *tdmi, int maylog, tdmi_state_t state);
 
index b655b5980f0f30b56f90cd767e0b0cfa1de0ce96..49c3570580bc1d8a5088bc99932ed71ebc99dd95 100644 (file)
 #include <linux/dvb/frontend.h>
 
 #include "tvhead.h"
+#include "channels.h"
 #include "dvb.h"
 #include "dvb_muxconfig.h"
 #include "strtab.h"
+#include "transports.h"
 
 
 static void
@@ -261,7 +263,8 @@ dvb_mux_setup(void)
  */
 
 int
-dvb_configure_transport(th_transport_t *t, const char *muxname)
+dvb_configure_transport(th_transport_t *t, const char *muxname,
+                       const char *channel_name)
 {
   th_dvb_mux_t *tdm;
 
@@ -275,6 +278,8 @@ dvb_configure_transport(th_transport_t *t, const char *muxname)
   t->tht_type = TRANSPORT_DVB;
   t->tht_dvb_mux = tdm;
   t->tht_name = strdup(tdm->tdm_title);
+
+  transport_link(t, channel_find(channel_name, 1));
   return 0;
 }
 
index 6e0814fe50951a3d7d1a1ee6275abbf1a148d5de..10586f67e0b0deafd8088f4bb1d37d30a79f8602 100644 (file)
 #include "dispatch.h"
 #include "psi.h"
 
+static struct th_transport_list iptv_probing_transports;
+static struct th_transport_list iptv_stale_transports;
+static void *iptv_probe_timer;
+
+static void iptv_probe_transport(th_transport_t *t);
+static void iptv_probe_callback(void *aux);
+static void iptv_probe_done(th_transport_t *t, int timeout);
+
 static void
 iptv_fd_callback(int events, void *opaque, int fd)
 {
@@ -60,7 +68,7 @@ iptv_fd_callback(int events, void *opaque, int fd)
 }
 
 int
-iptv_start_feed(th_transport_t *t, unsigned int weight)
+iptv_start_feed(th_transport_t *t, int status)
 {
   int fd;
   struct ip_mreqn m;
@@ -98,7 +106,7 @@ iptv_start_feed(th_transport_t *t, unsigned int weight)
   }
 
   t->tht_iptv_fd = fd;
-  t->tht_status = TRANSPORT_RUNNING;
+  t->tht_status = status;
 
   syslog(LOG_ERR, "\"%s\" joined group", t->tht_name);
 
@@ -130,10 +138,12 @@ static void
 iptv_parse_pmt(struct th_transport *t, struct th_pid *pi,
               uint8_t *table, int table_len)
 {
-  if(table[0] != 2)
+  if(table[0] != 2 || t->tht_status != TRANSPORT_PROBING)
     return;
 
   psi_parse_pmt(t, table + 3, table_len - 3, 0);
+
+  iptv_probe_done(t, 0);
 }
 
 
@@ -145,7 +155,7 @@ static void
 iptv_parse_pat(struct th_transport *t, struct th_pid *pi,
               uint8_t *table, int table_len)
 {
-  if(table[0] != 0)
+  if(table[0] != 0 || t->tht_status != TRANSPORT_PROBING)
     return;
 
   psi_parse_pat(t, table + 3, table_len - 3, iptv_parse_pmt);
@@ -156,28 +166,30 @@ iptv_parse_pat(struct th_transport *t, struct th_pid *pi,
  */
 
 int
-iptv_configure_transport(th_transport_t *t, const char *muxname)
+iptv_configure_transport(th_transport_t *t, const char *iptv_type,
+                        struct config_head *head, const char *channel_name)
 {
-  config_entry_t *ce;
   const char *s;
   int fd;
   char buf[100];
   char ifname[100];
   struct ifreq ifr;
   th_pid_t *pi;
-
-  if((ce = find_mux_config("iptvmux", muxname)) == NULL)
+  
+  if(!strcasecmp(iptv_type, "rawudp"))
+    t->tht_iptv_mode = IPTV_MODE_RAWUDP;
+  else
     return -1;
 
   t->tht_type = TRANSPORT_IPTV;
   
-  if((s = config_get_str_sub(&ce->ce_sub, "group-address", NULL)) == NULL)
+  if((s = config_get_str_sub(head, "group-address", NULL)) == NULL)
     return -1;
   t->tht_iptv_group_addr.s_addr = inet_addr(s);
 
   t->tht_iptv_ifindex = 0;
 
-  if((s = config_get_str_sub(&ce->ce_sub, "interface-address", NULL)) != NULL)
+  if((s = config_get_str_sub(head, "interface-address", NULL)) != NULL)
     t->tht_iptv_interface_addr.s_addr = inet_addr(s);
   else
     t->tht_iptv_interface_addr.s_addr = INADDR_ANY; 
@@ -185,7 +197,7 @@ iptv_configure_transport(th_transport_t *t, const char *muxname)
   snprintf(ifname, sizeof(ifname), "%s",
           inet_ntoa(t->tht_iptv_interface_addr));
 
-  if((s = config_get_str_sub(&ce->ce_sub, "interface", NULL)) != NULL) {
+  if((s = config_get_str_sub(head, "interface", NULL)) != NULL) {
 
     memset(&ifr, 0, sizeof(ifr));
     strncpy(ifr.ifr_name, s, IFNAMSIZ - 1);
@@ -201,16 +213,75 @@ iptv_configure_transport(th_transport_t *t, const char *muxname)
     }
   }
 
-  if((s = config_get_str_sub(&ce->ce_sub, "port", NULL)) == NULL)
+  if((s = config_get_str_sub(head, "port", NULL)) == NULL)
     return -1;
   t->tht_iptv_port = atoi(s);
 
-  snprintf(buf, sizeof(buf), "IPTV: %s (%s:%s:%d)", muxname, 
+  snprintf(buf, sizeof(buf), "IPTV: %s (%s:%s:%d)", channel_name,
           ifname, inet_ntoa(t->tht_iptv_group_addr), t->tht_iptv_port);
   t->tht_name = strdup(buf);
 
   pi = transport_add_pid(t, 0, HTSTV_TABLE);
   pi->tp_got_section = iptv_parse_pat;
 
+  t->tht_channel = channel_find(channel_name, 1);
+  LIST_INSERT_HEAD(&iptv_probing_transports, t, tht_adapter_link);
+
+  if(iptv_probe_timer == NULL) {
+    iptv_probe_transport(t);
+    iptv_probe_timer = stimer_add(iptv_probe_callback, t, 5);
+  }
+
   return 0;
 }
+
+static void
+iptv_probe_transport(th_transport_t *t)
+{
+  syslog(LOG_INFO, "iptv: Probing transport %s", t->tht_name);
+  iptv_start_feed(t, TRANSPORT_PROBING);
+}
+
+
+static void
+iptv_probe_done(th_transport_t *t, int timeout)
+{
+  int pidcnt = 0;
+  th_pid_t *tp;
+
+  if(!timeout)
+    stimer_del(iptv_probe_timer);
+
+  LIST_FOREACH(tp, &t->tht_pids, tp_link)
+    pidcnt++;
+  
+  LIST_REMOVE(t, tht_adapter_link);
+
+  syslog(LOG_INFO, "iptv: Transport %s probed, %d pids found%s", 
+        t->tht_name, pidcnt, timeout ? ", but probe timeouted" : "");
+
+  iptv_stop_feed(t);
+
+  if(!timeout)
+    transport_link(t, t->tht_channel);
+  else
+    LIST_INSERT_HEAD(&iptv_stale_transports, t, tht_adapter_link);
+
+  t = LIST_FIRST(&iptv_probing_transports);
+  if(t == NULL) {
+    iptv_probe_timer = NULL;
+    return;
+  }
+
+  iptv_probe_transport(t);
+  iptv_probe_timer = stimer_add(iptv_probe_callback, t, 5);
+}
+
+
+
+static void
+iptv_probe_callback(void *aux)
+{
+  th_transport_t *t = aux;
+  iptv_probe_done(t, 1);
+ }
index b2526e1e1cb78103a72079a0c0f02d5c99438a67..4d1cc8d20d17c0a00d44cb70e0bdebe466e92452 100644 (file)
 #ifndef IPTV_INPUT_H_
 #define IPTV_INPUT_H_
 
-int iptv_configure_transport(th_transport_t *t, const char *muxname);
+int iptv_configure_transport(th_transport_t *t, const char *muxname,
+                            struct config_head *head, 
+                            const char *channel_name);
 
-int iptv_start_feed(th_transport_t *t, unsigned int weight);
+int iptv_start_feed(th_transport_t *t, int status);
 
 int iptv_stop_feed(th_transport_t *t);
 
index b6d232a55032cc4f28c5fbc94d24d939b26530eb..86818ba23024685c263ecdc8b67f2cf7cd8686ff 100644 (file)
@@ -134,7 +134,7 @@ transport_start(th_transport_t *t, unsigned int weight)
 #endif
 #ifdef ENABLE_INPUT_IPTV
   case TRANSPORT_IPTV:
-    return iptv_start_feed(t, weight);
+    return iptv_start_feed(t, TRANSPORT_RUNNING);
 #endif
 #ifdef ENABLE_INPUT_V4L
   case TRANSPORT_V4L:
index 804aac59b78a8cf7ab31b9cc632318025958f5c0..49acd2618faea8c16b85204601c85f6bc2070f32 100644 (file)
@@ -39,10 +39,12 @@ void transport_monitor_init(th_transport_t *t);
 th_pid_t *transport_add_pid(th_transport_t *t, uint16_t pid,
                            tv_streamtype_t type);
 
-int transport_set_channel(th_transport_t *th, const char *name);
+int transport_set_channel(th_transport_t *th, th_channel_t *ch);
+void transport_link(th_transport_t *t, th_channel_t *ch);
 
 void transport_scheduler_init(void);
 
+
 th_subscription_t *channel_subscribe(th_channel_t *ch, void *opaque,
                                     void (*ths_callback)
                                     (struct th_subscription *s, 
index 5f7efb5e1b914822869db25b459c977e9414e569..1deeaaa4284d78259f07836579402216aacac5d0 100644 (file)
--- a/tvhead.h
+++ b/tvhead.h
@@ -252,7 +252,7 @@ typedef struct th_transport {
   enum {
     TRANSPORT_IDLE,
     TRANSPORT_RUNNING,
-
+    TRANSPORT_PROBING,
   } tht_status;
 
   th_commercial_advice_t tht_tt_commercial_advice;
@@ -304,12 +304,17 @@ typedef struct th_transport {
       int port;
       int fd;
       void *dispatch_handle;
+      enum {
+       IPTV_MODE_RAWUDP,
+      } mode;
     } iptv;
   } u;
 
 
 } th_transport_t;
 
+
+
 #define tht_v4l_frequency u.v4l.frequency
 #define tht_v4l_adapter   u.v4l.adapter
 
@@ -322,6 +327,7 @@ typedef struct th_transport {
 #define tht_iptv_port            u.iptv.port
 #define tht_iptv_dispatch_handle u.iptv.dispatch_handle
 #define tht_iptv_fd              u.iptv.fd
+#define tht_iptv_mode            u.iptv.mode
 
 /*
  *  Teletext
diff --git a/v4l.c b/v4l.c
index 7cb8a8b068e044a051cd71fd7afde4078c7e29e3..fe7b600c90c0a0b6106f03c3585aa3c4198df6c7 100644 (file)
--- a/v4l.c
+++ b/v4l.c
@@ -78,7 +78,8 @@ v4l_add_adapters(void)
  *
  */
 int
-v4l_configure_transport(th_transport_t *t, const char *muxname)
+v4l_configure_transport(th_transport_t *t, const char *muxname,
+                       const char *channel_name)
 {
   config_entry_t *ce;
   char buf[100];
@@ -98,6 +99,7 @@ v4l_configure_transport(th_transport_t *t, const char *muxname)
           (float)t->tht_v4l_frequency / 1000000.0f);
   t->tht_name = strdup(buf);
 
+  transport_link(t, channel_find(channel_name, 1));
   return 0;
 }
 
diff --git a/v4l.h b/v4l.h
index b502e592ff847e5a4403bd387c21dcc8c9c2d157..a066d2661dd266470e9be2f663975854f45a2075 100644 (file)
--- a/v4l.h
+++ b/v4l.h
@@ -21,7 +21,8 @@
 
 void v4l_add_adapters(void);
 
-int v4l_configure_transport(th_transport_t *t, const char *muxname);
+int v4l_configure_transport(th_transport_t *t, const char *muxname,
+                           const char *channel_name);
 
 int v4l_start_feed(th_transport_t *t, unsigned int weight);