Migrate tables into dvb_mux.

Also let some parts of the tuning work with dvb_mux
This commit is contained in:
Andreas Öman 2012-12-05 13:09:41 +01:00
parent 8681d71857
commit f991e1376e
12 changed files with 259 additions and 141 deletions

View file

@ -153,6 +153,7 @@ SRCS-${CONFIG_LINUXDVB} += \
src/dvb/dvb_tables.c \
src/dvb/diseqc.c \
src/dvb/dvb_adapter.c \
src/dvb/dvb_network.c \
src/dvb/dvb_multiplex.c \
src/dvb/dvb_service.c \
src/dvb/dvb_preconf.c \

View file

@ -40,6 +40,7 @@ TAILQ_HEAD(th_dvb_mux_instance_queue, th_dvb_mux_instance);
LIST_HEAD(th_dvb_mux_instance_list, th_dvb_mux_instance);
TAILQ_HEAD(dvb_satconf_queue, dvb_satconf);
LIST_HEAD(dvb_mux_list, dvb_mux);
TAILQ_HEAD(dvb_mux_queue, dvb_mux);
/**
* Satconf
@ -90,7 +91,7 @@ typedef struct dvb_network {
struct th_dvb_mux_instance_list dn_mux_instances; // Should go away
struct th_dvb_mux_instance_queue dn_initial_scan_queue;
struct dvb_mux_queue dn_initial_scan_queue;
int dn_initial_num_mux;
struct dvb_mux *dn_mux_epg;
@ -99,6 +100,8 @@ typedef struct dvb_network {
struct dvb_mux_list dn_muxes;
gtimer_t dn_mux_scanner_timer;
} dvb_network_t;
@ -124,6 +127,17 @@ typedef struct dvb_mux {
struct th_dvb_mux_instance *dm_tdmi; // wrong
TAILQ_ENTRY(dvb_mux) dm_scan_link;
struct dvb_mux_queue *dm_scan_queue;
LIST_HEAD(, th_dvb_table) dm_tables;
int dm_num_tables;
TAILQ_HEAD(, th_dvb_table) dm_table_queue;
int dm_table_initial;
struct th_dvb_mux_instance *dm_current_tdmi;
} dvb_mux_t;
@ -150,11 +164,6 @@ typedef struct th_dvb_mux_instance {
uint32_t tdmi_fec_err_histogram[TDMI_FEC_ERR_HISTOGRAM_SIZE];
int tdmi_fec_err_ptr;
LIST_HEAD(, th_dvb_table) tdmi_tables;
int tdmi_num_tables;
TAILQ_HEAD(, th_dvb_table) tdmi_table_queue;
int tdmi_table_initial;
enum {
TDMI_FE_UNKNOWN,
@ -173,9 +182,6 @@ typedef struct th_dvb_mux_instance {
char *tdmi_identifier;
TAILQ_ENTRY(th_dvb_mux_instance) tdmi_scan_link;
struct th_dvb_mux_instance_queue *tdmi_scan_queue;
struct th_subscription_list tdmi_subscriptions;
} th_dvb_mux_instance_t;
@ -210,7 +216,7 @@ typedef struct th_dvb_adapter {
dvb_network_t *tda_dn;
th_dvb_mux_instance_t *tda_mux_current;
th_dvb_mux_instance_t *tda_current_tdmi;
char *tda_tune_reason; // Reason for last tune
int tda_table_epollfd;
@ -246,8 +252,6 @@ typedef struct th_dvb_adapter {
int tda_hostconnection;
gtimer_t tda_mux_scanner_timer;
pthread_mutex_t tda_delivery_mutex;
struct service_list tda_transports; /* Currently bound transports */
@ -268,8 +272,8 @@ typedef struct th_dvb_adapter {
void (*tda_open_service)(struct th_dvb_adapter *tda, struct service *s);
void (*tda_close_service)(struct th_dvb_adapter *tda, struct service *s);
void (*tda_open_table)(struct th_dvb_mux_instance *tdmi, struct th_dvb_table *s);
void (*tda_close_table)(struct th_dvb_mux_instance *tdmi, struct th_dvb_table *s);
void (*tda_open_table)(struct dvb_mux *dm, struct th_dvb_table *s);
void (*tda_close_table)(struct dvb_mux *dm, struct th_dvb_table *s);
int tda_rawmode;
@ -346,8 +350,6 @@ void dvb_init(uint32_t adapter_mask, const char *rawfile);
*/
void dvb_adapter_init(uint32_t adapter_mask, const char *rawfile);
void dvb_adapter_mux_scanner(void *aux);
void dvb_adapter_start (th_dvb_adapter_t *tda);
void dvb_adapter_stop (th_dvb_adapter_t *tda);
@ -493,9 +495,9 @@ htsmsg_t *dvb_service_build_msg(struct service *t);
/**
* DVB Frontend
*/
int dvb_fe_tune(th_dvb_mux_instance_t *tdmi, const char *reason);
int dvb_fe_tune(dvb_mux_t *dm, const char *reason);
void dvb_fe_stop(th_dvb_mux_instance_t *tdmi, int retune);
void dvb_fe_stop(th_dvb_adapter_t *tda, int retune);
/**
@ -505,7 +507,7 @@ void dvb_table_init(th_dvb_adapter_t *tda);
void dvb_table_add_default(dvb_mux_t *dm);
void dvb_table_flush_all(th_dvb_mux_instance_t *tdmi);
void dvb_table_flush_all(dvb_mux_t *dm);
void dvb_table_add_pmt(dvb_mux_t *dm, int pmt_pid);
@ -528,6 +530,15 @@ void dvb_table_dispatch(uint8_t *sec, int r, th_dvb_table_t *tdt);
void dvb_table_release(th_dvb_table_t *tdt);
/**
*
*/
dvb_network_t *dvb_network_create(int fe_type);
void dvb_network_mux_scanner(void *aux);
/**
* Satellite configuration
*/

View file

@ -57,11 +57,7 @@ static th_dvb_adapter_t *
tda_alloc(void)
{
th_dvb_adapter_t *tda = calloc(1, sizeof(th_dvb_adapter_t));
dvb_network_t *dn = calloc(1, sizeof(dvb_network_t));
pthread_mutex_init(&tda->tda_delivery_mutex, NULL);
tda->tda_dn = dn;
TAILQ_INIT(&dn->dn_initial_scan_queue);
TAILQ_INIT(&tda->tda_satconfs);
streaming_pad_init(&tda->tda_streaming_pad);
return tda;
@ -467,7 +463,7 @@ tda_add(int adapter_num)
close(fe);
tda->tda_fe_type = tda->tda_fe_info->type;
tda->tda_dn->dn_fe_type = tda->tda_fe_type;
tda->tda_dn = dvb_network_create(tda->tda_fe_type);
snprintf(buf, sizeof(buf), "%s_%s", tda->tda_rootpath,
tda->tda_fe_info->name);
@ -495,8 +491,6 @@ tda_add(int adapter_num)
hostconnection2str(tda->tda_hostconnection));
TAILQ_INSERT_TAIL(&dvb_adapters, tda, tda_global_link);
gtimer_arm(&tda->tda_mux_scanner_timer, dvb_adapter_mux_scanner, tda, 1);
}
@ -587,7 +581,7 @@ dvb_adapter_start ( th_dvb_adapter_t *tda )
void
dvb_adapter_stop ( th_dvb_adapter_t *tda )
{
assert(tda->tda_mux_current == NULL);
assert(tda->tda_current_tdmi == NULL);
/* Poweroff */
dvb_adapter_poweroff(tda);
@ -696,7 +690,7 @@ dvb_adapter_init(uint32_t adapter_mask, const char *rawfile)
}
}
#if 0
/**
* If nobody is subscribing, cycle thru all muxes to get some stats
* and EIT updates
@ -757,6 +751,7 @@ dvb_adapter_mux_scanner(void *aux)
if (tda->tda_mux_current)
dvb_fe_stop(tda->tda_mux_current, 0);
}
#endif
/**
*
@ -945,7 +940,7 @@ dvb_adapter_input_dvr(void *aux)
}
} else {
LIST_FOREACH(t, &tda->tda_transports, s_active_link)
if(t->s_dvb_mux_instance == tda->tda_mux_current)
if(t->s_dvb_mux_instance == tda->tda_current_tdmi)
ts_recv_packet1(t, tsb + i, NULL);
}
@ -1009,10 +1004,10 @@ dvb_adapter_build_msg(th_dvb_adapter_t *tda)
htsmsg_add_u32(m, "muxes", nummux);
htsmsg_add_u32(m, "initialMuxes", tda->tda_dn->dn_initial_num_mux);
if(tda->tda_mux_current != NULL) {
th_dvb_mux_instance_t *tdmi = tda->tda_mux_current;
if(tda->tda_current_tdmi != NULL) {
th_dvb_mux_instance_t *tdmi = tda->tda_current_tdmi;
dvb_mux_nicename(buf, sizeof(buf), tda->tda_mux_current);
dvb_mux_nicename(buf, sizeof(buf), tda->tda_current_tdmi);
htsmsg_add_str(m, "currentMux", buf);
htsmsg_add_u32(m, "signal", MIN(tdmi->tdmi_signal * 100 / 65535, 100));

View file

@ -91,7 +91,7 @@ dvb_fe_monitor(void *aux)
th_dvb_adapter_t *tda = aux;
fe_status_t fe_status;
int status, v, vv, i, fec, q;
th_dvb_mux_instance_t *tdmi = tda->tda_mux_current;
th_dvb_mux_instance_t *tdmi = tda->tda_current_tdmi;
char buf[50];
signal_status_t sigstat;
streaming_message_t sm;
@ -245,7 +245,8 @@ dvb_fe_monitor(void *aux)
sm.sm_type = SMT_SIGNAL_STATUS;
sm.sm_data = &sigstat;
LIST_FOREACH(t, &tda->tda_transports, s_active_link)
if(t->s_dvb_mux_instance == tda->tda_mux_current && t->s_status == SERVICE_RUNNING ) {
if(t->s_dvb_mux_instance == tda->tda_current_tdmi &&
t->s_status == SERVICE_RUNNING ) {
pthread_mutex_lock(&t->s_stream_mutex);
streaming_pad_deliver(&t->s_streaming_pad, &sm);
pthread_mutex_unlock(&t->s_stream_mutex);
@ -258,31 +259,32 @@ dvb_fe_monitor(void *aux)
* Stop the given TDMI
*/
void
dvb_fe_stop(th_dvb_mux_instance_t *tdmi, int retune)
dvb_fe_stop(th_dvb_adapter_t *tda, int retune)
{
th_dvb_adapter_t *tda = tdmi->tdmi_adapter;
lock_assert(&global_lock);
assert(tdmi == tda->tda_mux_current);
tda->tda_mux_current = NULL;
th_dvb_mux_instance_t *tdmi = tda->tda_current_tdmi;
assert(tdmi != NULL);
dvb_mux_t *dm = tdmi->tdmi_mux;
if(tdmi->tdmi_table_initial) {
tdmi->tdmi_table_initial = 0;
tda->tda_dn->dn_initial_num_mux--;
dvb_mux_save(tdmi);
if(dm->dm_table_initial) {
dm->dm_table_initial = 0;
dm->dm_dn->dn_initial_num_mux--;
dvb_mux_save(dm->dm_tdmi);
}
dvb_table_flush_all(tdmi);
dvb_table_flush_all(dm);
assert(tdmi->tdmi_scan_queue == NULL);
assert(dm->dm_scan_queue == NULL);
epggrab_mux_stop(tdmi->tdmi_mux, 0);
epggrab_mux_stop(dm, 0);
if (!retune) {
#if 0 /// XXX(dvbreorg)
if(!retune) {
gtimer_disarm(&tda->tda_fe_monitor_timer);
dvb_adapter_stop(tda);
}
#endif
}
#if DVB_API_VERSION >= 5
@ -391,12 +393,14 @@ dvb_fe_tune_s2(th_dvb_mux_instance_t *tdmi, dvb_mux_conf_t *dmc)
*
*/
int
dvb_fe_tune(th_dvb_mux_instance_t *tdmi, const char *reason)
dvb_fe_tune(dvb_mux_t *dm, const char *reason)
{
th_dvb_adapter_t *tda = tdmi->tdmi_adapter;
th_dvb_adapter_t *tda = dm->dm_tdmi->tdmi_adapter;
dvb_network_t *dn = dm->dm_dn;
th_dvb_mux_instance_t *tdmi = dm->dm_tdmi;
// copy dmc, cause frequency may be change with FE_QPSK
const dvb_mux_t *dm = tdmi->tdmi_mux;
dvb_mux_conf_t dmc = dm->dm_conf;
dvb_frontend_parameters_t* p = &dmc.dmc_fe_params;
@ -409,18 +413,18 @@ dvb_fe_tune(th_dvb_mux_instance_t *tdmi, const char *reason)
free(tda->tda_tune_reason);
tda->tda_tune_reason = strdup(reason);
if(tda->tda_mux_current == tdmi) {
if(tda->tda_current_tdmi == tdmi) {
dvb_adapter_notify(tda);
return 0;
}
if(tdmi->tdmi_scan_queue != NULL) {
TAILQ_REMOVE(tdmi->tdmi_scan_queue, tdmi, tdmi_scan_link);
tdmi->tdmi_scan_queue = NULL;
if(dm->dm_scan_queue != NULL) {
TAILQ_REMOVE(dm->dm_scan_queue, dm, dm_scan_link);
dm->dm_scan_queue = NULL;
}
if(tda->tda_mux_current != NULL)
dvb_fe_stop(tda->tda_mux_current, 1);
if(tda->tda_current_tdmi != NULL)
dvb_fe_stop(tda, 1);
else
dvb_adapter_start(tda);
@ -497,9 +501,9 @@ dvb_fe_tune(th_dvb_mux_instance_t *tdmi, const char *reason)
tda->tda_rootpath, buf, strerror(errno), p->frequency);
/* Remove from initial scan set */
if(tdmi->tdmi_table_initial) {
tdmi->tdmi_table_initial = 0;
tda->tda_dn->dn_initial_num_mux--;
if(dm->dm_table_initial) {
dm->dm_table_initial = 0;
dn->dn_initial_num_mux--;
}
/* Mark as bad */
@ -507,7 +511,7 @@ dvb_fe_tune(th_dvb_mux_instance_t *tdmi, const char *reason)
return SM_CODE_TUNING_FAILED;
}
tda->tda_mux_current = tdmi;
tda->tda_current_tdmi = tdmi;
gtimer_arm(&tda->tda_fe_monitor_timer, dvb_fe_monitor, tda, 1);

View file

@ -110,9 +110,9 @@ close_service(th_dvb_adapter_t *tda, service_t *s)
*
*/
static void
open_table(th_dvb_mux_instance_t *tdmi, th_dvb_table_t *tdt)
open_table(dvb_mux_t *dm, th_dvb_table_t *tdt)
{
th_dvb_adapter_t *tda = tdmi->tdmi_adapter;
th_dvb_adapter_t *tda = dm->dm_current_tdmi->tdmi_adapter;
struct epoll_event e;
static int tdt_id_tally;
@ -148,7 +148,7 @@ open_table(th_dvb_mux_instance_t *tdmi, th_dvb_table_t *tdt)
}
if(tdt->tdt_fd == -1)
TAILQ_INSERT_TAIL(&tdmi->tdmi_table_queue, tdt, tdt_pending_link);
TAILQ_INSERT_TAIL(&dm->dm_table_queue, tdt, tdt_pending_link);
}
@ -156,9 +156,9 @@ open_table(th_dvb_mux_instance_t *tdmi, th_dvb_table_t *tdt)
* Close FD for the given table and put table on the pending list
*/
static void
tdt_close_fd(th_dvb_mux_instance_t *tdmi, th_dvb_table_t *tdt)
tdt_close_fd(dvb_mux_t *dm, th_dvb_table_t *tdt)
{
th_dvb_adapter_t *tda = tdmi->tdmi_adapter;
th_dvb_adapter_t *tda = dm->dm_current_tdmi->tdmi_adapter;
assert(tdt->tdt_fd != -1);
@ -166,7 +166,7 @@ tdt_close_fd(th_dvb_mux_instance_t *tdmi, th_dvb_table_t *tdt)
close(tdt->tdt_fd);
tdt->tdt_fd = -1;
TAILQ_INSERT_TAIL(&tdmi->tdmi_table_queue, tdt, tdt_pending_link);
TAILQ_INSERT_TAIL(&dm->dm_table_queue, tdt, tdt_pending_link);
}
@ -181,7 +181,7 @@ dvb_table_input(void *aux)
int r, i, tid, fd, x;
struct epoll_event ev[1];
uint8_t sec[4096];
th_dvb_mux_instance_t *tdmi;
dvb_mux_t *dm;
th_dvb_table_t *tdt;
int64_t cycle_barrier = 0;
@ -200,8 +200,8 @@ dvb_table_input(void *aux)
continue;
pthread_mutex_lock(&global_lock);
if((tdmi = tda->tda_mux_current) != NULL) {
LIST_FOREACH(tdt, &tdmi->tdmi_tables, tdt_link)
if((dm = tda->tda_current_tdmi->tdmi_mux) != NULL) {
LIST_FOREACH(tdt, &dm->dm_tables, tdt_link)
if(tdt->tdt_id == tid)
break;
@ -209,15 +209,15 @@ dvb_table_input(void *aux)
dvb_table_dispatch(sec, r, tdt);
/* Any tables pending (that wants a filter/fd), close this one */
if(TAILQ_FIRST(&tdmi->tdmi_table_queue) != NULL &&
if(TAILQ_FIRST(&dm->dm_table_queue) != NULL &&
cycle_barrier < getmonoclock()) {
tdt_close_fd(tdmi, tdt);
tdt_close_fd(dm, tdt);
cycle_barrier = getmonoclock() + 100000;
tdt = TAILQ_FIRST(&tdmi->tdmi_table_queue);
tdt = TAILQ_FIRST(&dm->dm_table_queue);
assert(tdt != NULL);
TAILQ_REMOVE(&tdmi->tdmi_table_queue, tdt, tdt_pending_link);
TAILQ_REMOVE(&dm->dm_table_queue, tdt, tdt_pending_link);
open_table(tdmi, tdt);
open_table(dm, tdt);
}
}
}
@ -229,13 +229,15 @@ dvb_table_input(void *aux)
static void
close_table(th_dvb_mux_instance_t *tdmi, th_dvb_table_t *tdt)
close_table(dvb_mux_t *dm, th_dvb_table_t *tdt)
{
th_dvb_adapter_t *tda = tdmi->tdmi_adapter;
if(tdt->tdt_fd == -1) {
TAILQ_REMOVE(&tdmi->tdmi_table_queue, tdt, tdt_pending_link);
TAILQ_REMOVE(&dm->dm_table_queue, tdt, tdt_pending_link);
} else {
th_dvb_mux_instance_t *tdmi = dm->dm_current_tdmi;
th_dvb_adapter_t *tda = tdmi->tdmi_adapter;
epoll_ctl(tda->tda_table_epollfd, EPOLL_CTL_DEL, tdt->tdt_fd, NULL);
close(tdt->tdt_fd);
}

View file

@ -62,8 +62,9 @@ close_service(th_dvb_adapter_t *tda, service_t *s)
*
*/
static void
open_table(th_dvb_mux_instance_t *tdmi, th_dvb_table_t *tdt)
open_table(dvb_mux_t *dm, th_dvb_table_t *tdt)
{
th_dvb_mux_instance_t *tdmi = dm->dm_current_tdmi;
th_dvb_adapter_t *tda = tdmi->tdmi_adapter;
assert(tdt->tdt_pid < 0x2000);
tda->tda_table_filter[tdt->tdt_pid] = 1;
@ -74,8 +75,9 @@ open_table(th_dvb_mux_instance_t *tdmi, th_dvb_table_t *tdt)
*
*/
static void
close_table(th_dvb_mux_instance_t *tdmi, th_dvb_table_t *tdt)
close_table(dvb_mux_t *dm, th_dvb_table_t *tdt)
{
th_dvb_mux_instance_t *tdmi = dm->dm_current_tdmi;
th_dvb_adapter_t *tda = tdmi->tdmi_adapter;
assert(tdt->tdt_pid < 0x2000);
tda->tda_table_filter[tdt->tdt_pid] = 0;
@ -99,18 +101,17 @@ got_section(const uint8_t *data, size_t len, void *opaque)
* so we need to be a bit careful here
*/
static void
dvb_table_raw_dispatch(th_dvb_mux_instance_t *tdmi,
const dvb_table_feed_t *dtf)
dvb_table_raw_dispatch(dvb_mux_t *dm, const dvb_table_feed_t *dtf)
{
int pid = (dtf->dtf_tsb[1] & 0x1f) << 8 | dtf->dtf_tsb[2];
th_dvb_table_t *vec[tdmi->tdmi_num_tables], *tdt;
th_dvb_table_t *vec[dm->dm_num_tables], *tdt;
int i = 0;
LIST_FOREACH(tdt, &tdmi->tdmi_tables, tdt_link) {
LIST_FOREACH(tdt, &dm->dm_tables, tdt_link) {
vec[i++] = tdt;
tdt->tdt_refcount++;
}
assert(i == tdmi->tdmi_num_tables);
int len = tdmi->tdmi_num_tables; // can change during callbacks
assert(i == dm->dm_num_tables);
int len = dm->dm_num_tables; // can change during callbacks
for(i = 0; i < len; i++) {
tdt = vec[i];
if(!tdt->tdt_destroyed) {
@ -144,8 +145,8 @@ dvb_table_input(void *aux)
pthread_mutex_lock(&global_lock);
if((tdmi = tda->tda_mux_current) != NULL)
dvb_table_raw_dispatch(tdmi, dtf);
if((tdmi = tda->tda_current_tdmi) != NULL)
dvb_table_raw_dispatch(tdmi->tdmi_mux, dtf);
pthread_mutex_unlock(&global_lock);
free(dtf);

View file

@ -65,16 +65,12 @@ static void tdmi_set_enable(th_dvb_mux_instance_t *tdmi, int enabled);
*
*/
static void
mux_link_initial(th_dvb_adapter_t *tda, th_dvb_mux_instance_t *tdmi)
mux_link_initial(dvb_network_t *dn, dvb_mux_t *dm)
{
int was_empty = TAILQ_FIRST(&tda->tda_dn->dn_initial_scan_queue) == NULL;
dm->dm_scan_queue = &dn->dn_initial_scan_queue;
TAILQ_INSERT_TAIL(dm->dm_scan_queue, dm, dm_scan_link);
tdmi->tdmi_scan_queue = &tda->tda_dn->dn_initial_scan_queue;
TAILQ_INSERT_TAIL(tdmi->tdmi_scan_queue, tdmi, tdmi_scan_link);
if(was_empty && (tda->tda_mux_current == NULL ||
tda->tda_mux_current->tdmi_table_initial == 0))
gtimer_arm(&tda->tda_mux_scanner_timer, dvb_adapter_mux_scanner, tda, 0);
gtimer_arm(&dn->dn_mux_scanner_timer, dvb_network_mux_scanner, dn, 0);
}
/**
@ -155,6 +151,7 @@ dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc,
uint16_t onid, uint16_t tsid, const char *network, const char *source,
int enabled, int initialscan, const char *identifier)
{
dvb_network_t *dn = tda->tda_dn;
th_dvb_mux_instance_t *tdmi, *c;
char buf[200];
@ -229,6 +226,7 @@ dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc,
dm->dm_transport_stream_id = tsid;
dm->dm_network_name = network ? strdup(network) : NULL;
TAILQ_INIT(&dm->dm_epg_grab);
TAILQ_INIT(&dm->dm_table_queue);
dm->dm_dn = tda->tda_dn;
LIST_INSERT_HEAD(&tda->tda_dn->dn_muxes, dm, dm_network_link);
@ -269,7 +267,6 @@ dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc,
tdmi->tdmi_enabled = enabled;
TAILQ_INIT(&tdmi->tdmi_table_queue);
tdmi->tdmi_adapter = tda;
@ -278,7 +275,7 @@ dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc,
memcpy(&tdmi->tdmi_mux->dm_conf, dmc, sizeof(struct dvb_mux_conf));
LIST_INSERT_HEAD(&tda->tda_dn->dn_mux_instances, tdmi, tdmi_adapter_link);
tdmi->tdmi_table_initial = initialscan;
dm->dm_table_initial = initialscan;
if(source != NULL) {
dvb_mux_nicename(buf, sizeof(buf), tdmi);
@ -291,9 +288,9 @@ dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc,
dvb_service_load(tdmi, identifier);
dvb_mux_notify(tdmi);
if(enabled && tdmi->tdmi_table_initial) {
tda->tda_dn->dn_initial_num_mux++;
mux_link_initial(tda, tdmi);
if(enabled && dm->dm_table_initial) {
dn->dn_initial_num_mux++;
mux_link_initial(dn, dm);
}
return tdmi;
@ -306,6 +303,7 @@ void
dvb_mux_destroy(th_dvb_mux_instance_t *tdmi)
{
th_dvb_adapter_t *tda = tdmi->tdmi_adapter;
dvb_mux_t *dm = tdmi->tdmi_mux;
service_t *t;
lock_assert(&global_lock);
@ -322,19 +320,19 @@ dvb_mux_destroy(th_dvb_mux_instance_t *tdmi)
dvb_service_notify_by_adapter(tda);
if(tda->tda_mux_current == tdmi)
dvb_fe_stop(tda->tda_mux_current, 0);
if(tda->tda_current_tdmi == tdmi)
dvb_fe_stop(tda, 0);
RB_REMOVE(&dvb_muxes, tdmi, tdmi_global_link);
LIST_REMOVE(tdmi, tdmi_adapter_link);
if(tdmi->tdmi_scan_queue != NULL)
TAILQ_REMOVE(tdmi->tdmi_scan_queue, tdmi, tdmi_scan_link);
if(dm->dm_scan_queue != NULL)
TAILQ_REMOVE(dm->dm_scan_queue, dm, dm_scan_link);
if(tdmi->tdmi_table_initial)
tda->tda_dn->dn_initial_num_mux--;
if(dm->dm_table_initial)
dm->dm_dn->dn_initial_num_mux--;
epggrab_mux_delete(tdmi->tdmi_mux); // XXX(dvbreorg)
epggrab_mux_delete(dm);
hts_settings_remove("dvbmuxes/%s", tdmi->tdmi_identifier);
@ -562,7 +560,7 @@ dvb_mux_save(th_dvb_mux_instance_t *tdmi)
htsmsg_add_u32(m, "frequency", f->frequency);
htsmsg_add_u32(m, "initialscan", tdmi->tdmi_table_initial);
htsmsg_add_u32(m, "initialscan", tdmi->tdmi_mux->dm_table_initial);
if(tdmi->tdmi_mux->dm_default_authority)
htsmsg_add_str(m, "default_authority", tdmi->tdmi_mux->dm_default_authority);
@ -877,26 +875,27 @@ dvb_mux_set_onid(dvb_mux_t *dm, uint16_t onid)
static void
tdmi_set_enable(th_dvb_mux_instance_t *tdmi, int enabled)
{
dvb_mux_t *dm = tdmi->tdmi_mux;
th_dvb_adapter_t *tda = tdmi->tdmi_adapter;
if(tdmi->tdmi_enabled == enabled)
return;
if(tdmi->tdmi_enabled) {
if(tda->tda_mux_current == tdmi)
dvb_fe_stop(tdmi, 0);
if(tda->tda_current_tdmi == tdmi)
dvb_fe_stop(tda, 0);
if(tdmi->tdmi_scan_queue != NULL) {
TAILQ_REMOVE(tdmi->tdmi_scan_queue, tdmi, tdmi_scan_link);
tdmi->tdmi_scan_queue = NULL;
if(dm->dm_scan_queue != NULL) {
TAILQ_REMOVE(dm->dm_scan_queue, dm, dm_scan_link);
dm->dm_scan_queue = NULL;
}
}
tdmi->tdmi_enabled = enabled;
if(enabled)
mux_link_initial(tda, tdmi);
mux_link_initial(tda->tda_dn, dm);
subscription_reschedule();
}
@ -1275,7 +1274,7 @@ dvb_subscription_create_from_tdmi(th_dvb_mux_instance_t *tdmi,
s->ths_tdmi = tdmi;
LIST_INSERT_HEAD(&tdmi->tdmi_subscriptions, s, ths_tdmi_link);
dvb_fe_tune(tdmi, "Full mux subscription");
dvb_fe_tune(tdmi->tdmi_mux, "Full mux subscription");
pthread_mutex_lock(&tda->tda_delivery_mutex);
streaming_target_connect(&tda->tda_streaming_pad, &s->ths_input);

102
src/dvb/dvb_network.c Normal file
View file

@ -0,0 +1,102 @@
/*
* TV Input - Linux DVB interface
* Copyright (C) 2007 - 2012 Andreas Öman
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "tvheadend.h"
#include "packet.h"
#include "dvb.h"
#include "epggrab.h"
/**
*
*/
dvb_network_t *
dvb_network_create(int fe_type)
{
dvb_network_t *dn = calloc(1, sizeof(dvb_network_t));
dn->dn_fe_type = fe_type;
TAILQ_INIT(&dn->dn_initial_scan_queue);
gtimer_arm(&dn->dn_mux_scanner_timer, dvb_network_mux_scanner, dn, 1);
return dn;
}
/**
*
*/
void
dvb_network_mux_scanner(void *aux)
{
dvb_network_t *dn = aux;
dvb_mux_t *dm;
// default period
gtimer_arm(&dn->dn_mux_scanner_timer, dvb_network_mux_scanner, dn, 20);
#if 0
/* No muxes */
if(LIST_FIRST(&dn->dn_mux_instances) == NULL) {
dvb_adapter_poweroff(tda);
return;
}
#endif
#if 0
/* Someone is actively using */
if(service_compute_weight(&tda->tda_transports) > 0)
return;
#endif
#if 0
if(tda->tda_mux_current != NULL &&
LIST_FIRST(&tda->tda_mux_current->tdmi_subscriptions) != NULL)
return; // Someone is doing full mux dump
#endif
/* Check if we have muxes pending for quickscan, if so, choose them */
if((dm = TAILQ_FIRST(&dn->dn_initial_scan_queue)) != NULL) {
dvb_fe_tune(dm, "Initial autoscan");
return;
}
/* Check EPG */
if (dn->dn_mux_epg) {
// timeout anything not complete
epggrab_mux_stop(dn->dn_mux_epg, 1);
dn->dn_mux_epg = NULL; // skip this time
} else {
dn->dn_mux_epg = epggrab_mux_next(dn);
}
/* EPG */
if (dn->dn_mux_epg) {
int period = epggrab_mux_period(dn->dn_mux_epg);
if (period > 20)
gtimer_arm(&dn->dn_mux_scanner_timer,
dvb_network_mux_scanner, dn, period);
dvb_fe_tune(dn->dn_mux_epg, "EPG scan");
return;
}
#if 0
/* Ensure we stop current mux and power off (if required) */
if (tda->tda_mux_current)
dvb_fe_stop(tda->tda_mux_current, 0);
#endif
}

View file

@ -59,7 +59,7 @@ dvb_service_start(service_t *t, unsigned int weight, int force_start)
{
int w, r;
th_dvb_adapter_t *tda = t->s_dvb_mux_instance->tdmi_adapter;
th_dvb_mux_instance_t *tdmi = tda->tda_mux_current;
th_dvb_mux_instance_t *tdmi = tda->tda_current_tdmi;
lock_assert(&global_lock);
@ -88,7 +88,7 @@ dvb_service_start(service_t *t, unsigned int weight, int force_start)
pthread_mutex_lock(&tda->tda_delivery_mutex);
r = dvb_fe_tune(t->s_dvb_mux_instance, "Transport start");
r = dvb_fe_tune(t->s_dvb_mux_instance->tdmi_mux, "Transport start");
if(!r)
LIST_INSERT_HEAD(&tda->tda_transports, t, s_active_link);

View file

@ -51,24 +51,26 @@ dvb_table_fastswitch(th_dvb_mux_instance_t *tdmi)
{
th_dvb_table_t *tdt;
th_dvb_adapter_t *tda = tdmi->tdmi_adapter;
dvb_mux_t *dm = tdmi->tdmi_mux;
dvb_network_t *dn = dm->dm_dn;
char buf[100];
if(!tdmi->tdmi_table_initial)
if(!dm->dm_table_initial)
return;
LIST_FOREACH(tdt, &tdmi->tdmi_tables, tdt_link)
LIST_FOREACH(tdt, &dm->dm_tables, tdt_link)
if((tdt->tdt_flags & TDT_QUICKREQ) && tdt->tdt_count == 0)
return;
tdmi->tdmi_table_initial = 0;
tda->tda_dn->dn_initial_num_mux--;
dm->dm_table_initial = 0;
dn->dn_initial_num_mux--;
dvb_mux_save(tdmi);
dvb_mux_nicename(buf, sizeof(buf), tdmi);
tvhlog(LOG_DEBUG, "dvb", "\"%s\" initial scan completed for \"%s\"",
tda->tda_rootpath, buf);
dvb_adapter_mux_scanner(tda);
dvb_network_mux_scanner(dn);
}
@ -140,11 +142,12 @@ static void
dvb_tdt_destroy(th_dvb_adapter_t *tda, th_dvb_mux_instance_t *tdmi,
th_dvb_table_t *tdt)
{
dvb_mux_t *dm = tdmi->tdmi_mux;
lock_assert(&global_lock);
assert(tdt->tdt_tdmi == tdmi);
LIST_REMOVE(tdt, tdt_link);
tdmi->tdmi_num_tables--;
tda->tda_close_table(tdmi, tdt);
dm->dm_num_tables--;
tda->tda_close_table(dm, tdt);
free(tdt->tdt_name);
tdt->tdt_destroyed = 1;
dvb_table_release(tdt);
@ -167,7 +170,7 @@ tdt_add(dvb_mux_t *dm, int tableid, int mask,
// TODO: this could mean reading the same data multiple times, and not
// sure how well this will work! I know Andreas has some thoughts on
// this
LIST_FOREACH(t, &tdmi->tdmi_tables, tdt_link) {
LIST_FOREACH(t, &dm->dm_tables, tdt_link) {
if(pid == t->tdt_pid &&
t->tdt_callback == callback && t->tdt_opaque == opaque) {
return;
@ -184,11 +187,11 @@ tdt_add(dvb_mux_t *dm, int tableid, int mask,
tdt->tdt_table = tableid;
tdt->tdt_mask = mask;
tdt->tdt_tdmi = tdmi;
LIST_INSERT_HEAD(&tdmi->tdmi_tables, tdt, tdt_link);
tdmi->tdmi_num_tables++;
LIST_INSERT_HEAD(&dm->dm_tables, tdt, tdt_link);
dm->dm_num_tables++;
tdt->tdt_fd = -1;
tdmi->tdmi_adapter->tda_open_table(tdmi, tdt);
tdmi->tdmi_adapter->tda_open_table(dm, tdt);
}
/**
@ -1095,7 +1098,7 @@ dvb_table_rem_pmt(dvb_mux_t *dm, int pmt_pid)
th_dvb_mux_instance_t *tdmi = dm->dm_tdmi;
th_dvb_adapter_t *tda = tdmi->tdmi_adapter;
th_dvb_table_t *tdt = NULL;
LIST_FOREACH(tdt, &tdmi->tdmi_tables, tdt_link)
LIST_FOREACH(tdt, &dm->dm_tables, tdt_link)
if (tdt->tdt_pid == pmt_pid && tdt->tdt_callback == dvb_pmt_callback)
break;
if (tdt)
@ -1107,12 +1110,12 @@ dvb_table_rem_pmt(dvb_mux_t *dm, int pmt_pid)
*
*/
void
dvb_table_flush_all(th_dvb_mux_instance_t *tdmi)
dvb_table_flush_all(dvb_mux_t *dm)
{
th_dvb_adapter_t *tda = tdmi->tdmi_adapter;
th_dvb_adapter_t *tda = dm->dm_tdmi->tdmi_adapter;
th_dvb_table_t *tdt;
while((tdt = LIST_FIRST(&tdmi->tdmi_tables)) != NULL)
dvb_tdt_destroy(tda, tdmi, tdt);
while((tdt = LIST_FIRST(&dm->dm_tables)) != NULL)
dvb_tdt_destroy(tda, dm->dm_tdmi, tdt);
}

View file

@ -26,7 +26,7 @@
* *************************************************************************/
struct th_dvb_mux_instance;
struct th_dvb_adapter;
struct dvb_network;
typedef struct epggrab_module epggrab_module_t;
typedef struct epggrab_module_int epggrab_module_int_t;
@ -263,7 +263,7 @@ void epggrab_mux_start ( struct dvb_mux *tdmi );
void epggrab_mux_stop ( struct dvb_mux *tdmi, int timeout );
void epggrab_mux_delete ( struct dvb_mux *tdmi );
int epggrab_mux_period ( struct dvb_mux *tdmi );
struct dvb_mux *epggrab_mux_next ( struct th_dvb_adapter *tda );
struct dvb_mux *epggrab_mux_next ( struct dvb_network *dn );
/*
* Re-schedule

View file

@ -83,7 +83,7 @@ int epggrab_mux_period ( dvb_mux_t *dm )
return period;
}
dvb_mux_t *epggrab_mux_next ( th_dvb_adapter_t *tda )
dvb_mux_t *epggrab_mux_next ( dvb_network_t *dn )
{
time_t now;
epggrab_ota_mux_t *ota;
@ -91,7 +91,7 @@ dvb_mux_t *epggrab_mux_next ( th_dvb_adapter_t *tda )
TAILQ_FOREACH(ota, &ota_mux_all, glob_link) {
if (ota->interval + ota->completed > now) return NULL;
if (!ota->is_reg) return NULL;
if (ota->dm->dm_tdmi->tdmi_adapter == tda) break;
if (ota->dm->dm_dn == dn) break;
}
return ota ? ota->dm : NULL;
}
@ -373,9 +373,9 @@ void epggrab_ota_complete ( epggrab_ota_mux_t *ota )
/* All complete (bring timer forward) */
if (!ota) {
th_dvb_mux_instance_t *tdmi = dm->dm_tdmi;
gtimer_arm(&tdmi->tdmi_adapter->tda_mux_scanner_timer,
dvb_adapter_mux_scanner, tdmi->tdmi_adapter, 20);
dvb_network_t *dn = dm->dm_dn;
gtimer_arm(&dn->dn_mux_scanner_timer,
dvb_network_mux_scanner, dn, 20);
}
}
}