Use redblack trees for DVB muxes
This commit is contained in:
parent
b90404d8ed
commit
f60f556512
8 changed files with 94 additions and 68 deletions
|
@ -79,7 +79,7 @@ nicenum(unsigned int v)
|
|||
static void
|
||||
tdmi_displayname(th_dvb_mux_instance_t *tdmi, char *buf, size_t len)
|
||||
{
|
||||
int f = tdmi->tdmi_fe_params->frequency;
|
||||
int f = tdmi->tdmi_fe_params.frequency;
|
||||
|
||||
if(tdmi->tdmi_adapter->tda_type == FE_QPSK) {
|
||||
snprintf(buf, len, "%s kHz %s", nicenum(f),
|
||||
|
@ -661,8 +661,7 @@ ajax_adaptermuxlist(http_connection_t *hc, http_reply_t *hr,
|
|||
|
||||
/* List of muxes */
|
||||
|
||||
LIST_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link)
|
||||
nmuxes++;
|
||||
nmuxes = tda->tda_muxes.entries;
|
||||
|
||||
if(nmuxes == 0) {
|
||||
tcp_qprintf(tq, "<div style=\"text-align: center\">"
|
||||
|
@ -672,7 +671,7 @@ ajax_adaptermuxlist(http_connection_t *hc, http_reply_t *hr,
|
|||
|
||||
selvector = alloca(sizeof(char *) * (nmuxes + 1));
|
||||
n = 0;
|
||||
LIST_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link)
|
||||
RB_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link)
|
||||
selvector[n++] = tdmi->tdmi_identifier;
|
||||
selvector[n] = NULL;
|
||||
|
||||
|
@ -684,7 +683,7 @@ ajax_adaptermuxlist(http_connection_t *hc, http_reply_t *hr,
|
|||
(int[])
|
||||
{16,12,7,8,16,8,2});
|
||||
|
||||
LIST_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) {
|
||||
RB_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) {
|
||||
|
||||
tdmi_displayname(tdmi, buf, sizeof(buf));
|
||||
|
||||
|
@ -756,8 +755,8 @@ dvbsvccmp(th_transport_t *a, th_transport_t *b)
|
|||
if(a->tht_dvb_mux_instance == b->tht_dvb_mux_instance)
|
||||
return a->tht_dvb_service_id - b->tht_dvb_service_id;
|
||||
|
||||
return a->tht_dvb_mux_instance->tdmi_fe_params->frequency -
|
||||
b->tht_dvb_mux_instance->tdmi_fe_params->frequency;
|
||||
return a->tht_dvb_mux_instance->tdmi_fe_params.frequency -
|
||||
b->tht_dvb_mux_instance->tdmi_fe_params.frequency;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -818,7 +817,7 @@ ajax_dvbmuxall(http_connection_t *hc, http_reply_t *hr,
|
|||
|
||||
RB_INIT(&tree);
|
||||
|
||||
LIST_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) {
|
||||
RB_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) {
|
||||
LIST_FOREACH(t, &tdmi->tdmi_transports, tht_mux_link) {
|
||||
if(transport_is_available(t)) {
|
||||
RB_INSERT_SORTED(&tree, t, tht_tmp_link, dvbsvccmp);
|
||||
|
|
107
dvb.c
107
dvb.c
|
@ -51,7 +51,7 @@
|
|||
#include "notify.h"
|
||||
|
||||
struct th_dvb_adapter_queue dvb_adapters;
|
||||
struct th_dvb_mux_instance_list dvb_muxes;
|
||||
struct th_dvb_mux_instance_tree dvb_muxes;
|
||||
static void dvb_mux_scanner(void *aux, int64_t now);
|
||||
static void dvb_fec_monitor(void *aux, int64_t now);
|
||||
|
||||
|
@ -68,7 +68,6 @@ tda_alloc(void)
|
|||
pthread_mutex_init(&tda->tda_lock, NULL);
|
||||
pthread_cond_init(&tda->tda_cond, NULL);
|
||||
TAILQ_INIT(&tda->tda_fe_cmd_queue);
|
||||
|
||||
return tda;
|
||||
}
|
||||
|
||||
|
@ -321,11 +320,9 @@ dvb_mux_scanner(void *aux, int64_t now)
|
|||
return; /* someone is here */
|
||||
|
||||
/* Check if we have muxes pending for quickscan, if so, choose them */
|
||||
LIST_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link)
|
||||
if(tdmi->tdmi_quickscan == TDMI_QUICKSCAN_WAITING)
|
||||
break;
|
||||
|
||||
if(tdmi != NULL) {
|
||||
if((tdmi = RB_FIRST(&tda->tda_muxes_qscan_waiting)) != NULL) {
|
||||
RB_REMOVE(&tda->tda_muxes_qscan_waiting, tdmi, tdmi_qscan_link);
|
||||
tdmi->tdmi_quickscan = TDMI_QUICKSCAN_RUNNING;
|
||||
dvb_tune_tdmi(tdmi, 0, TDMI_IDLESCAN);
|
||||
return;
|
||||
|
@ -337,8 +334,8 @@ dvb_mux_scanner(void *aux, int64_t now)
|
|||
if(tdmi != NULL)
|
||||
tdmi->tdmi_quickscan = TDMI_QUICKSCAN_NONE;
|
||||
|
||||
tdmi = tdmi != NULL ? LIST_NEXT(tdmi, tdmi_adapter_link) : NULL;
|
||||
tdmi = tdmi != NULL ? tdmi : LIST_FIRST(&tda->tda_muxes);
|
||||
tdmi = tdmi != NULL ? RB_NEXT(tdmi, tdmi_adapter_link) : NULL;
|
||||
tdmi = tdmi != NULL ? tdmi : RB_FIRST(&tda->tda_muxes);
|
||||
|
||||
if(tdmi == NULL)
|
||||
return; /* no instances */
|
||||
|
@ -350,11 +347,27 @@ dvb_mux_scanner(void *aux, int64_t now)
|
|||
*
|
||||
*/
|
||||
static int
|
||||
tdmi_inssort(th_dvb_mux_instance_t *a, th_dvb_mux_instance_t *b)
|
||||
tdmi_cmp(th_dvb_mux_instance_t *a, th_dvb_mux_instance_t *b)
|
||||
{
|
||||
return a->tdmi_fe_params->frequency - b->tdmi_fe_params->frequency;
|
||||
if(a->tdmi_switchport != b->tdmi_switchport)
|
||||
return a->tdmi_switchport - b->tdmi_switchport;
|
||||
|
||||
if(a->tdmi_fe_params.frequency != b->tdmi_fe_params.frequency)
|
||||
return a->tdmi_fe_params.frequency - b->tdmi_fe_params.frequency;
|
||||
|
||||
return a->tdmi_polarisation - b->tdmi_polarisation;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static int
|
||||
tdmi_global_cmp(th_dvb_mux_instance_t *a, th_dvb_mux_instance_t *b)
|
||||
{
|
||||
return strcmp(a->tdmi_identifier, b->tdmi_identifier);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new mux on the given adapter, return NULL if it already exists
|
||||
*/
|
||||
|
@ -364,35 +377,44 @@ dvb_mux_create(th_dvb_adapter_t *tda, struct dvb_frontend_parameters *fe_param,
|
|||
uint16_t tsid, const char *network, int flags)
|
||||
{
|
||||
th_dvb_mux_instance_t *tdmi;
|
||||
static th_dvb_mux_instance_t *skel;
|
||||
char buf[200];
|
||||
char qpsktxt[20];
|
||||
int entries_before = tda->tda_muxes.entries;
|
||||
|
||||
LIST_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) {
|
||||
if(tdmi->tdmi_fe_params->frequency == fe_param->frequency &&
|
||||
tdmi->tdmi_polarisation == polarisation &&
|
||||
tdmi->tdmi_switchport == switchport)
|
||||
return NULL;
|
||||
}
|
||||
if(skel == NULL)
|
||||
skel = calloc(1, sizeof(th_dvb_mux_instance_t));
|
||||
|
||||
skel->tdmi_polarisation = polarisation;
|
||||
skel->tdmi_switchport = switchport;
|
||||
skel->tdmi_fe_params.frequency = fe_param->frequency;
|
||||
|
||||
tdmi = RB_INSERT_SORTED(&tda->tda_muxes, skel, tdmi_adapter_link, tdmi_cmp);
|
||||
if(tdmi != NULL)
|
||||
return NULL;
|
||||
|
||||
tdmi = skel;
|
||||
skel = NULL;
|
||||
|
||||
tdmi = calloc(1, sizeof(th_dvb_mux_instance_t));
|
||||
tdmi->tdmi_quickscan = TDMI_QUICKSCAN_WAITING;
|
||||
tdmi->tdmi_refcnt = 1;
|
||||
|
||||
RB_INSERT_SORTED(&tda->tda_muxes_qscan_waiting, tdmi, tdmi_qscan_link,
|
||||
tdmi_cmp);
|
||||
|
||||
tdmi->tdmi_quickscan = TDMI_QUICKSCAN_WAITING;
|
||||
|
||||
pthread_mutex_init(&tdmi->tdmi_table_lock, NULL);
|
||||
tdmi->tdmi_state = TDMI_IDLE;
|
||||
tdmi->tdmi_transport_stream_id = tsid;
|
||||
tdmi->tdmi_adapter = tda;
|
||||
tdmi->tdmi_network = network ? strdup(network) : NULL;
|
||||
|
||||
if(LIST_FIRST(&tda->tda_muxes) == NULL && tda->tda_rootpath != NULL) {
|
||||
if(entries_before == 0 && tda->tda_rootpath != NULL) {
|
||||
/* First mux on adapter with backing hardware, start scanner */
|
||||
dtimer_arm(&tda->tda_mux_scanner_timer, dvb_mux_scanner, tda, 1);
|
||||
}
|
||||
|
||||
|
||||
tdmi->tdmi_fe_params = malloc(sizeof(struct dvb_frontend_parameters));
|
||||
tdmi->tdmi_polarisation = polarisation;
|
||||
tdmi->tdmi_switchport = switchport;
|
||||
memcpy(tdmi->tdmi_fe_params, fe_param,
|
||||
memcpy(&tdmi->tdmi_fe_params, fe_param,
|
||||
sizeof(struct dvb_frontend_parameters));
|
||||
|
||||
if(tda->tda_type == FE_QPSK)
|
||||
|
@ -404,11 +426,10 @@ dvb_mux_create(th_dvb_adapter_t *tda, struct dvb_frontend_parameters *fe_param,
|
|||
snprintf(buf, sizeof(buf), "%s%d%s",
|
||||
tda->tda_identifier,fe_param->frequency, qpsktxt);
|
||||
|
||||
LIST_INSERT_SORTED(&tda->tda_muxes, tdmi, tdmi_adapter_link, tdmi_inssort);
|
||||
LIST_INSERT_HEAD(&dvb_muxes, tdmi, tdmi_global_link);
|
||||
|
||||
tdmi->tdmi_identifier = strdup(buf);
|
||||
|
||||
RB_INSERT_SORTED(&dvb_muxes, tdmi, tdmi_global_link, tdmi_global_cmp);
|
||||
|
||||
if(flags & DVB_MUX_SAVE) {
|
||||
dvb_tda_save(tda);
|
||||
notify_tda_change(tda);
|
||||
|
@ -432,7 +453,6 @@ dvb_mux_unref(th_dvb_mux_instance_t *tdmi)
|
|||
|
||||
free(tdmi->tdmi_network);
|
||||
free(tdmi->tdmi_identifier);
|
||||
free(tdmi->tdmi_fe_params);
|
||||
free(tdmi);
|
||||
}
|
||||
|
||||
|
@ -457,8 +477,11 @@ dvb_mux_destroy(th_dvb_mux_instance_t *tdmi)
|
|||
tdmi_stop(tda->tda_mux_current);
|
||||
|
||||
dtimer_disarm(&tdmi->tdmi_initial_scan_timer);
|
||||
LIST_REMOVE(tdmi, tdmi_global_link);
|
||||
LIST_REMOVE(tdmi, tdmi_adapter_link);
|
||||
RB_REMOVE(&dvb_muxes, tdmi, tdmi_global_link);
|
||||
RB_REMOVE(&tda->tda_muxes, tdmi, tdmi_adapter_link);
|
||||
|
||||
if(tdmi->tdmi_quickscan == TDMI_QUICKSCAN_WAITING)
|
||||
RB_REMOVE(&tda->tda_muxes_qscan_waiting, tdmi, tdmi_qscan_link);
|
||||
|
||||
pthread_mutex_lock(&tda->tda_lock);
|
||||
dvb_fe_flush(tdmi);
|
||||
|
@ -490,7 +513,7 @@ dvb_tda_save(th_dvb_adapter_t *tda)
|
|||
fprintf(fp, "type = %s\n", dvb_adaptertype_to_str(tda->tda_type));
|
||||
fprintf(fp, "displayname = %s\n", tda->tda_displayname);
|
||||
|
||||
LIST_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) {
|
||||
RB_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) {
|
||||
|
||||
fprintf(fp, "mux {\n");
|
||||
dvb_mux_store(fp, tdmi);
|
||||
|
@ -728,13 +751,13 @@ dvb_tda_clone(th_dvb_adapter_t *dst, th_dvb_adapter_t *src)
|
|||
th_transport_t *t_src, *t_dst;
|
||||
th_stream_t *st_src, *st_dst;
|
||||
|
||||
while((tdmi_dst = LIST_FIRST(&dst->tda_muxes)) != NULL)
|
||||
while((tdmi_dst = RB_FIRST(&dst->tda_muxes)) != NULL)
|
||||
dvb_mux_destroy(tdmi_dst);
|
||||
|
||||
LIST_FOREACH(tdmi_src, &src->tda_muxes, tdmi_adapter_link) {
|
||||
RB_FOREACH(tdmi_src, &src->tda_muxes, tdmi_adapter_link) {
|
||||
|
||||
tdmi_dst = dvb_mux_create(dst,
|
||||
tdmi_src->tdmi_fe_params,
|
||||
&tdmi_src->tdmi_fe_params,
|
||||
tdmi_src->tdmi_polarisation,
|
||||
tdmi_src->tdmi_switchport,
|
||||
tdmi_src->tdmi_transport_stream_id,
|
||||
|
@ -804,7 +827,7 @@ dvb_tda_destroy(th_dvb_adapter_t *tda)
|
|||
|
||||
unlink(buf);
|
||||
|
||||
while((tdmi = LIST_FIRST(&tda->tda_muxes)) != NULL)
|
||||
while((tdmi = RB_FIRST(&tda->tda_muxes)) != NULL)
|
||||
dvb_mux_destroy(tdmi);
|
||||
|
||||
TAILQ_REMOVE(&dvb_adapters, tda, tda_global_link);
|
||||
|
@ -842,3 +865,17 @@ dvb_tdmi_fastswitch(th_dvb_mux_instance_t *tdmi)
|
|||
dvb_mux_scanner(tdmi->tdmi_adapter, 0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
th_dvb_mux_instance_t *
|
||||
dvb_mux_find_by_identifier(const char *identifier)
|
||||
{
|
||||
th_dvb_mux_instance_t skel;
|
||||
|
||||
skel.tdmi_identifier = (char *)identifier;
|
||||
return RB_FIND(&dvb_muxes, &skel, tdmi_global_link, tdmi_global_cmp);
|
||||
}
|
||||
|
||||
|
|
2
dvb.h
2
dvb.h
|
@ -29,7 +29,7 @@ enum polarisation {
|
|||
#define DVB_FEC_ERROR_LIMIT 20
|
||||
|
||||
extern struct th_dvb_adapter_queue dvb_adapters;
|
||||
extern struct th_dvb_mux_instance_list dvb_muxes;
|
||||
extern struct th_dvb_mux_instance_tree dvb_muxes;
|
||||
|
||||
void dvb_init(void);
|
||||
|
||||
|
|
2
dvb_fe.c
2
dvb_fe.c
|
@ -96,7 +96,7 @@ dvb_fe_manager(void *aux)
|
|||
|
||||
pthread_mutex_unlock(&tda->tda_lock);
|
||||
|
||||
p = *tdmi->tdmi_fe_params;
|
||||
p = tdmi->tdmi_fe_params;
|
||||
|
||||
if(tda->tda_type == FE_QPSK) {
|
||||
/* DVB-S */
|
||||
|
|
|
@ -96,7 +96,7 @@ static struct strtab poltab[] = {
|
|||
void
|
||||
dvb_mux_store(FILE *fp, th_dvb_mux_instance_t *tdmi)
|
||||
{
|
||||
struct dvb_frontend_parameters *f = tdmi->tdmi_fe_params;
|
||||
struct dvb_frontend_parameters *f = &tdmi->tdmi_fe_params;
|
||||
|
||||
fprintf(fp, "\ttransportstreamid = %d\n", tdmi->tdmi_transport_stream_id);
|
||||
if(tdmi->tdmi_network != NULL)
|
||||
|
|
|
@ -253,19 +253,6 @@ dvb_polarisation_to_str_long(int pol)
|
|||
}
|
||||
|
||||
|
||||
th_dvb_mux_instance_t *
|
||||
dvb_mux_find_by_identifier(const char *identifier)
|
||||
{
|
||||
th_dvb_mux_instance_t *tdmi;
|
||||
|
||||
LIST_FOREACH(tdmi, &dvb_muxes, tdmi_global_link)
|
||||
if(!strcmp(identifier, tdmi->tdmi_identifier))
|
||||
return tdmi;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
th_dvb_adapter_t *
|
||||
dvb_adapter_find_by_identifier(const char *identifier)
|
||||
{
|
||||
|
@ -312,11 +299,11 @@ void
|
|||
dvb_mux_nicename(char *buf, size_t size, th_dvb_mux_instance_t *tdmi)
|
||||
{
|
||||
if(tdmi->tdmi_adapter->tda_type == FE_QPSK)
|
||||
snprintf(buf, size, "%dkHz %s port %d", tdmi->tdmi_fe_params->frequency,
|
||||
snprintf(buf, size, "%dkHz %s port %d", tdmi->tdmi_fe_params.frequency,
|
||||
dvb_polarisation_to_str_long(tdmi->tdmi_polarisation),
|
||||
tdmi->tdmi_switchport);
|
||||
else
|
||||
snprintf(buf, size, "%dHz", tdmi->tdmi_fe_params->frequency);
|
||||
snprintf(buf, size, "%dHz", tdmi->tdmi_fe_params.frequency);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -250,7 +250,7 @@ dvb_eit_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len,
|
|||
ptr += 11;
|
||||
|
||||
/* Search all muxes on adapter */
|
||||
LIST_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link)
|
||||
RB_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link)
|
||||
if(tdmi->tdmi_transport_stream_id == transport_stream_id)
|
||||
break;
|
||||
|
||||
|
|
15
tvhead.h
15
tvhead.h
|
@ -29,6 +29,7 @@
|
|||
#include <libhts/hts_strtab.h>
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libhts/redblack.h>
|
||||
#include <linux/dvb/frontend.h>
|
||||
|
||||
/*
|
||||
* Commercial status
|
||||
|
@ -82,8 +83,7 @@ TAILQ_HEAD(ref_update_queue, ref_update);
|
|||
LIST_HEAD(th_transport_list, th_transport);
|
||||
RB_HEAD(th_transport_tree, th_transport);
|
||||
TAILQ_HEAD(th_transport_queue, th_transport);
|
||||
LIST_HEAD(th_dvb_mux_list, th_dvb_mux);
|
||||
LIST_HEAD(th_dvb_mux_instance_list, th_dvb_mux_instance);
|
||||
RB_HEAD(th_dvb_mux_instance_tree, th_dvb_mux_instance);
|
||||
LIST_HEAD(th_stream_list, th_stream);
|
||||
TAILQ_HEAD(th_pkt_queue, th_pkt);
|
||||
LIST_HEAD(th_pkt_list, th_pkt);
|
||||
|
@ -157,8 +157,9 @@ typedef struct th_dvb_mux_instance {
|
|||
TDMI_QUICKSCAN_WAITING,
|
||||
} tdmi_quickscan;
|
||||
|
||||
LIST_ENTRY(th_dvb_mux_instance) tdmi_global_link;
|
||||
LIST_ENTRY(th_dvb_mux_instance) tdmi_adapter_link;
|
||||
RB_ENTRY(th_dvb_mux_instance) tdmi_global_link;
|
||||
RB_ENTRY(th_dvb_mux_instance) tdmi_adapter_link;
|
||||
RB_ENTRY(th_dvb_mux_instance) tdmi_qscan_link;
|
||||
|
||||
struct th_dvb_adapter *tdmi_adapter;
|
||||
|
||||
|
@ -185,7 +186,7 @@ typedef struct th_dvb_mux_instance {
|
|||
time_t tdmi_got_adapter;
|
||||
time_t tdmi_lost_adapter;
|
||||
|
||||
struct dvb_frontend_parameters *tdmi_fe_params;
|
||||
struct dvb_frontend_parameters tdmi_fe_params;
|
||||
uint8_t tdmi_polarisation; /* for DVB-S */
|
||||
uint8_t tdmi_switchport; /* for DVB-S */
|
||||
|
||||
|
@ -227,7 +228,9 @@ typedef struct th_dvb_adapter {
|
|||
|
||||
TAILQ_ENTRY(th_dvb_adapter) tda_global_link;
|
||||
|
||||
struct th_dvb_mux_instance_list tda_muxes;
|
||||
struct th_dvb_mux_instance_tree tda_muxes;
|
||||
struct th_dvb_mux_instance_tree tda_muxes_qscan_waiting;
|
||||
|
||||
th_dvb_mux_instance_t *tda_mux_current;
|
||||
|
||||
const char *tda_rootpath;
|
||||
|
|
Loading…
Add table
Reference in a new issue