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:
parent
1532f137ed
commit
8e8b2d3c0a
11 changed files with 128 additions and 81 deletions
72
channels.c
72
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)
|
||||
{
|
||||
|
|
3
dvb.c
3
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;
|
||||
|
|
3
dvb.h
3
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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
97
iptv_input.c
97
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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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,
|
||||
|
|
8
tvhead.h
8
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
|
||||
|
|
4
v4l.c
4
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;
|
||||
}
|
||||
|
||||
|
|
3
v4l.h
3
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);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue