From 0e6c46aa0fa53d22293fb71817919d3a1d676060 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 16 Jun 2014 17:36:44 +0200 Subject: [PATCH] esfilter: rewrite the CA filtering for the proper functionality --- src/descrambler.h | 2 + src/descrambler/capmt.c | 4 +- src/descrambler/cwc.c | 2 +- src/service.c | 150 ++++++++++++++++++++++++++++------------ 4 files changed, 111 insertions(+), 47 deletions(-) diff --git a/src/descrambler.h b/src/descrambler.h index 9dcdd3fb..dadc8441 100755 --- a/src/descrambler.h +++ b/src/descrambler.h @@ -98,6 +98,8 @@ typedef struct caid { uint16_t pid; uint16_t caid; uint32_t providerid; + uint8_t use; + uint8_t filter; } caid_t; diff --git a/src/descrambler/capmt.c b/src/descrambler/capmt.c index c02f8a76..d7a4be96 100644 --- a/src/descrambler/capmt.c +++ b/src/descrambler/capmt.c @@ -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", diff --git a/src/descrambler/cwc.c b/src/descrambler/cwc.c index 453169dd..e2f0b8ac 100755 --- a/src/descrambler/cwc.c +++ b/src/descrambler/cwc.c @@ -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; diff --git a/src/service.c b/src/service.c index 0c8a1121..2fac4b32 100644 --- a/src/service.c +++ b/src/service.c @@ -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); }