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);
{
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)
{
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;
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);
#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
*/
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;
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;
}
#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)
{
}
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;
}
t->tht_iptv_fd = fd;
- t->tht_status = TRANSPORT_RUNNING;
+ t->tht_status = status;
syslog(LOG_ERR, "\"%s\" joined group", t->tht_name);
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);
}
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);
*/
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;
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);
}
}
- 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);
+ }
#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);
#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:
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,
enum {
TRANSPORT_IDLE,
TRANSPORT_RUNNING,
-
+ TRANSPORT_PROBING,
} tht_status;
th_commercial_advice_t tht_tt_commercial_advice;
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
#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
*
*/
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];
(float)t->tht_v4l_frequency / 1000000.0f);
t->tht_name = strdup(buf);
+ transport_link(t, channel_find(channel_name, 1));
return 0;
}
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);