IPTV revamp

- Add correct probing of IPTV transports during startup
- Remove the 'iptvmux' configuration entity, instead we configure this directly on the service
This commit is contained in:
Andreas Öman 2007-09-19 12:30:08 +00:00
parent 1532f137ed
commit 8e8b2d3c0a
11 changed files with 128 additions and 81 deletions

View 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)
{

3
dvb.c
View file

@ -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;

3
dvb.h
View file

@ -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);

View file

@ -25,9 +25,11 @@
#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;
}

View file

@ -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);
}

View file

@ -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);

View 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:

View 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,

View file

@ -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

4
v4l.c
View file

@ -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;
}

3
v4l.h
View file

@ -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);