esfilter: rewrite the CA filtering for the proper functionality

This commit is contained in:
Jaroslav Kysela 2014-06-16 17:36:44 +02:00
parent 669b70180c
commit 0e6c46aa0f
4 changed files with 111 additions and 47 deletions

View file

@ -98,6 +98,8 @@ typedef struct caid {
uint16_t pid;
uint16_t caid;
uint32_t providerid;
uint8_t use;
uint8_t filter;
} caid_t;

View file

@ -1504,7 +1504,7 @@ capmt_caid_change(th_descrambler_t *td)
LIST_FOREACH(c, &st->es_caids, link) {
/* search ecmpid in list */
LIST_FOREACH(cce, &ct->ct_caid_ecm, cce_link)
if (cce->cce_caid == c->caid && cce->cce_providerid == c->providerid)
if (c->use && cce->cce_caid == c->caid && cce->cce_providerid == c->providerid)
break;
if (cce)
continue;
@ -1774,7 +1774,7 @@ capmt_service_start(service_t *s)
TAILQ_FOREACH(st, &t->s_filt_components, es_link) {
caid_t *c;
LIST_FOREACH(c, &st->es_caids, link) {
if(c == NULL)
if(c == NULL || c->use == 0)
continue;
tvhlog(LOG_DEBUG, "capmt",

View file

@ -1936,7 +1936,7 @@ cwc_service_start(service_t *t)
if (pcard->cwc_caid == 0) continue;
TAILQ_FOREACH(st, &t->s_filt_components, es_link) {
LIST_FOREACH(c, &st->es_caids, link) {
if (c->caid == pcard->cwc_caid)
if (c->use && c->caid == pcard->cwc_caid)
break;
}
if (c) break;

View file

@ -345,7 +345,7 @@ service_build_filter(service_t *t)
{
elementary_stream_t *st, *st2, **sta;
esfilter_t *esf;
caid_t *ca;
caid_t *ca, *ca2;
int i, n, p, o, exclusive;
uint32_t mask;
@ -364,6 +364,10 @@ filter:
n = 0;
TAILQ_FOREACH(st, &t->s_components, es_link) {
st->es_filter = 0;
LIST_FOREACH(ca, &st->es_caids, link) {
ca->use = 0;
ca->filter = 0;
}
n++;
}
@ -398,6 +402,7 @@ filter:
continue;
}
if (i == ESF_CLASS_CA) {
ca = NULL;
if ((esf->esf_caid != (uint16_t)-1 || esf->esf_caprovider != -1)) {
LIST_FOREACH(ca, &st->es_caids, link) {
if (esf->esf_caid != -1 && ca->caid != esf->esf_caid)
@ -410,55 +415,103 @@ filter:
continue;
}
if (esf->esf_log)
tvhlog(LOG_INFO, "service", "esfilter: CA match %04x %06x", esf->esf_caid,
esf->esf_caprovider);
}
if (esf->esf_log)
tvhlog(LOG_INFO, "service", "esfilter: %s %03d %05d %s %s %s %s",
esfilter_class2txt(i), esf->esf_index,
st->es_pid, streaming_component_type2txt(st->es_type),
lang_code_get(st->es_lang), t->s_nicename,
esfilter_action2txt(esf->esf_action));
switch (esf->esf_action) {
case ESFA_NONE:
break;
case ESFA_IGNORE:
st->es_filter |= ESFM_IGNORE;
break;
case ESFA_USE:
service_build_filter_add(t, st, sta, &p);
break;
case ESFA_ONCE:
if (esf->esf_language[0] == '\0') {
service_build_filter_add(t, st, sta, &p);
} else {
int present = 0;
TAILQ_FOREACH(st2, &t->s_components, es_link) {
if ((st2->es_filter & ESFM_USED) == 0)
continue;
if (strcmp(st2->es_lang, st->es_lang) == 0) {
present = 1;
tvhlog(LOG_INFO, "service", "esfilter: %s %03d %05d %04x %06x \"%s\" %s",
esfilter_class2txt(i), esf->esf_index, st->es_pid,
esf->esf_caid, esf->esf_caprovider, t->s_nicename,
esfilter_action2txt(esf->esf_action));
switch (esf->esf_action) {
case ESFA_NONE:
break;
case ESFA_IGNORE:
if (ca == NULL)
LIST_FOREACH(ca, &st->es_caids, link)
ca->filter |= ESFM_IGNORE;
else
ca->filter |= ESFM_IGNORE;
st->es_filter |= ESFM_IGNORE;
break;
case ESFA_ONCE:
TAILQ_FOREACH(st2, &t->s_components, es_link)
if (st2->es_type == SCT_CA && (st2->es_filter & ESFM_USED) != 0)
break;
}
}
if (!present)
service_build_filter_add(t, st, sta, &p);
}
break;
case ESFA_EXCLUSIVE:
break;
case ESFA_EMPTY:
if (p == o)
if (st2 != NULL) break;
/* fall through */
case ESFA_USE:
if (ca == NULL)
LIST_FOREACH(ca, &st->es_caids, link)
ca->filter |= ESFM_USED;
else
ca->filter |= ESFM_USED;
service_build_filter_add(t, st, sta, &p);
break;
default:
tvhlog(LOG_DEBUG, "service", "Unknown esfilter action %d", esf->esf_action);
break;
break;
case ESFA_EXCLUSIVE:
if (ca == NULL)
LIST_FOREACH(ca, &st->es_caids, link)
ca->use = 1;
else {
LIST_FOREACH(ca2, &st->es_caids, link)
ca2->use = 0;
ca->use = 1;
}
break;
case ESFA_EMPTY:
if (p == o)
service_build_filter_add(t, st, sta, &p);
break;
default:
tvhlog(LOG_DEBUG, "service", "Unknown esfilter action %d", esf->esf_action);
break;
}
} else {
if (esf->esf_log)
tvhlog(LOG_INFO, "service", "esfilter: %s %03d %05d %s %s \"%s\" %s",
esfilter_class2txt(i), esf->esf_index,
st->es_pid, streaming_component_type2txt(st->es_type),
lang_code_get(st->es_lang), t->s_nicename,
esfilter_action2txt(esf->esf_action));
switch (esf->esf_action) {
case ESFA_NONE:
break;
case ESFA_IGNORE:
st->es_filter |= ESFM_IGNORE;
break;
case ESFA_USE:
service_build_filter_add(t, st, sta, &p);
break;
case ESFA_ONCE:
if (esf->esf_language[0] == '\0') {
service_build_filter_add(t, st, sta, &p);
} else {
int present = 0;
TAILQ_FOREACH(st2, &t->s_components, es_link) {
if ((st2->es_filter & ESFM_USED) == 0)
continue;
if (strcmp(st2->es_lang, st->es_lang) == 0) {
present = 1;
break;
}
}
if (!present)
service_build_filter_add(t, st, sta, &p);
}
break;
case ESFA_EXCLUSIVE:
break;
case ESFA_EMPTY:
if (p == o)
service_build_filter_add(t, st, sta, &p);
break;
default:
tvhlog(LOG_DEBUG, "service", "Unknown esfilter action %d", esf->esf_action);
break;
}
}
if (esf->esf_action == ESFA_EXCLUSIVE) {
/* forget previous work */
while (p > o) {
p--;
LIST_FOREACH(ca, &sta[p]->es_caids, link)
ca->use = 0;
TAILQ_REMOVE(&t->s_filt_components, sta[p], es_filt_link);
}
st->es_filter = 0;
@ -472,8 +525,15 @@ filter:
if (!exclusive) {
TAILQ_FOREACH(st, &t->s_components, es_link) {
if ((mask & SCT_MASK(st->es_type)) != 0 &&
(st->es_filter & (ESFM_USED|ESFM_IGNORE)) == 0)
(st->es_filter & (ESFM_USED|ESFM_IGNORE)) == 0) {
service_build_filter_add(t, st, sta, &p);
LIST_FOREACH(ca, &st->es_caids, link)
ca->use = 1;
} else {
LIST_FOREACH(ca, &st->es_caids, link)
if (ca->filter & ESFM_USED)
ca->use = 1;
}
}
}
}
@ -1573,6 +1633,8 @@ add_caid(elementary_stream_t *st, uint16_t caid, uint32_t providerid)
c->caid = caid;
c->providerid = providerid;
c->pid = 0;
c->use = 1;
c->filter = 0;
LIST_INSERT_HEAD(&st->es_caids, c, link);
}