From 8e8b2d3c0a4ef1a017f2ebb88f8eda53ef156e0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Wed, 19 Sep 2007 12:30:08 +0000 Subject: [PATCH] IPTV revamp - Add correct probing of IPTV transports during startup - Remove the 'iptvmux' configuration entity, instead we configure this directly on the service --- channels.c | 72 +++++++----------------------------- dvb.c | 3 +- dvb.h | 3 +- dvb_muxconfig.c | 7 +++- iptv_input.c | 97 ++++++++++++++++++++++++++++++++++++++++++------- iptv_input.h | 6 ++- transports.c | 2 +- transports.h | 4 +- tvhead.h | 8 +++- v4l.c | 4 +- v4l.h | 3 +- 11 files changed, 128 insertions(+), 81 deletions(-) diff --git a/channels.c b/channels.c index 7a388aab..8719227f 100644 --- a/channels.c +++ b/channels.c @@ -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 6d9f9805..b08d16bb 100644 --- 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 e9d62c8e..bcd47b9c 100644 --- 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); diff --git a/dvb_muxconfig.c b/dvb_muxconfig.c index b655b598..49c35705 100644 --- a/dvb_muxconfig.c +++ b/dvb_muxconfig.c @@ -25,9 +25,11 @@ #include #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; } diff --git a/iptv_input.c b/iptv_input.c index 6e0814fe..10586f67 100644 --- a/iptv_input.c +++ b/iptv_input.c @@ -41,6 +41,14 @@ #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); + } diff --git a/iptv_input.h b/iptv_input.h index b2526e1e..4d1cc8d2 100644 --- a/iptv_input.h +++ b/iptv_input.h @@ -19,9 +19,11 @@ #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); diff --git a/transports.c b/transports.c index b6d232a5..86818ba2 100644 --- a/transports.c +++ b/transports.c @@ -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: diff --git a/transports.h b/transports.h index 804aac59..49acd261 100644 --- a/transports.h +++ b/transports.h @@ -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, diff --git a/tvhead.h b/tvhead.h index 5f7efb5e..1deeaaa4 100644 --- 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 7cb8a8b0..fe7b600c 100644 --- 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 b502e592..a066d266 100644 --- 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);