From dfffcb1f29f3d895e560b2aea53b1f2c4e842bdc Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 16 May 2016 16:25:11 +0200 Subject: [PATCH] capmt: rewrite the ECM PID change logic (works now), fixes #3784 --- src/descrambler/capmt.c | 104 ++++++++++++++++++++++++++----------- src/input/mpegts/dvb_psi.c | 5 +- src/service.c | 5 +- 3 files changed, 82 insertions(+), 32 deletions(-) diff --git a/src/descrambler/capmt.c b/src/descrambler/capmt.c index 6579d09dd..48a97500e 100644 --- a/src/descrambler/capmt.c +++ b/src/descrambler/capmt.c @@ -181,6 +181,8 @@ typedef struct capmt_caid_ecm { mpegts_service_t *cce_service; LIST_ENTRY(capmt_caid_ecm) cce_link; + + int cce_delete_me; } capmt_caid_ecm_t; /** @@ -670,10 +672,13 @@ capmt_queue_msg capmt_message_t *msg, *msg2; if (flags & CAPMT_MSG_CLEAR) { - while ((msg = TAILQ_FIRST(&capmt->capmt_writeq)) != NULL) { - TAILQ_REMOVE(&capmt->capmt_writeq, msg, cm_link); - sbuf_free(&msg->cm_sb); - free(msg); + for (msg = TAILQ_FIRST(&capmt->capmt_writeq); msg; msg = msg2) { + msg2 = TAILQ_NEXT(msg, cm_link); + if (msg->cm_sid == sid) { + TAILQ_REMOVE(&capmt->capmt_writeq, msg, cm_link); + sbuf_free(&msg->cm_sb); + free(msg); + } } } if (flags & CAPMT_MSG_NODUP) { @@ -792,9 +797,9 @@ capmt_send_stop(capmt_service_t *t) * */ static void -capmt_send_stop_descrambling(capmt_t *capmt) +capmt_send_stop_descrambling(capmt_t *capmt, uint8_t demuxer) { - static uint8_t buf[8] = { + uint8_t buf[8] = { 0x9F, 0x80, 0x3F, @@ -802,7 +807,7 @@ capmt_send_stop_descrambling(capmt_t *capmt) 0x83, 0x02, 0x00, - 0xFF, /* wildcard demux id */ + demuxer, /* 0xFF is wildcard demux id */ }; capmt_write_msg(capmt, 0, 0, buf, 8); } @@ -1866,30 +1871,83 @@ capmt_caid_change(th_descrambler_t *td) capmt_t *capmt = ct->ct_capmt; mpegts_service_t *t = (mpegts_service_t*)td->td_service; elementary_stream_t *st; - capmt_caid_ecm_t *cce; + capmt_caid_ecm_t *cce, *cce_next; caid_t *c; - int change = 0; + int i, change = 0; pthread_mutex_lock(&capmt->capmt_mutex); pthread_mutex_lock(&t->s_stream_mutex); + /* add missing A/V PIDs and ECM PIDs */ + i = 0; TAILQ_FOREACH(st, &t->s_filt_components, es_filt_link) { + if (i < MAX_PIDS && SCT_ISAV(st->es_type)) { + if (i == 0) change = 1; + ct->ct_pids[i++] = st->es_pid; + } if (t->s_dvb_prefcapid_lock == PREFCAPID_FORCE && t->s_dvb_prefcapid != st->es_pid) continue; LIST_FOREACH(c, &st->es_caids, link) { /* search ecmpid in list */ LIST_FOREACH(cce, &ct->ct_caid_ecm, cce_link) - if (c->use && cce->cce_caid == c->caid && cce->cce_providerid == c->providerid) - if (!t->s_dvb_forcecaid || t->s_dvb_forcecaid == cce->cce_caid) + if (c->use && cce->cce_caid == c->caid && + cce->cce_providerid == c->providerid && + st->es_pid == cce->cce_ecmpid && + (!t->s_dvb_forcecaid || t->s_dvb_forcecaid == cce->cce_caid)) + break; + if (!cce) { + capmt_caid_add(ct, t, st->es_pid, c); + change = 1; + } + } + } + + /* clear rest */ + for (; i < MAX_PIDS; i++) + ct->ct_pids[i] = 0; + + /* find removed ECM PIDs */ + LIST_FOREACH(cce, &ct->ct_caid_ecm, cce_link) { + if (t->s_dvb_prefcapid_lock == PREFCAPID_FORCE && + cce->cce_ecmpid != t->s_dvb_prefcapid) { + st = NULL; + } else { + TAILQ_FOREACH(st, &t->s_filt_components, es_filt_link) { + LIST_FOREACH(c, &st->es_caids, link) + if (c->use && cce->cce_caid == c->caid && + cce->cce_providerid == c->providerid && + st->es_pid == cce->cce_ecmpid) break; - if (cce) - continue; - capmt_caid_add(ct, t, st->es_pid, c); - change = 1; + if (c) break; + } + } + if (!st) { + change = 3; + cce->cce_delete_me = 1; + } else { + cce->cce_delete_me = 0; + } + } + + if (change & 2) { + /* remove marked ECM PIDs */ + for (cce = LIST_FIRST(&ct->ct_caid_ecm); cce; cce = cce_next) { + cce_next = LIST_NEXT(cce, cce_link); + if (cce->cce_delete_me) { + LIST_REMOVE(cce, cce_link); + free(cce); + } } } + if (change) { + if (capmt_oscam_netproto(capmt)) + capmt_send_stop_descrambling(capmt, ct->ct_adapter); + else + capmt_send_stop(ct); + } + pthread_mutex_unlock(&t->s_stream_mutex); pthread_mutex_unlock(&capmt->capmt_mutex); @@ -2052,7 +2110,7 @@ capmt_enumerate_services(capmt_t *capmt, int force) if (capmt->capmt_sock[0] >= 0) caclient_set_status((caclient_t *)capmt, CACLIENT_STATUS_READY); if (capmt_oscam_netproto(capmt)) { - capmt_send_stop_descrambling(capmt); + capmt_send_stop_descrambling(capmt, 0xff); capmt_pid_flush(capmt); } else @@ -2106,20 +2164,8 @@ capmt_service_start(caclient_t *cac, service_t *s) LIST_FOREACH(ct, &capmt->capmt_services, ct_link) /* skip, if we already have this service */ - if (ct->td_service == (service_t *)t) { - /* update PIDs only */ - i = 0; - TAILQ_FOREACH(st, &t->s_filt_components, es_filt_link) - if (i < MAX_PIDS && SCT_ISAV(st->es_type)) { - if (ct->ct_pids[i] != st->es_pid) change = 3; - ct->ct_pids[i++] = st->es_pid; - } - for ( ; i < MAX_PIDS; i++) { - if (ct->ct_pids[i]) change = 3; - ct->ct_pids[i] = 0; - } + if (ct->td_service == (service_t *)t) goto fin; - } if (tuner < 0 && capmt->capmt_oscam != CAPMT_OSCAM_TCP && capmt->capmt_oscam != CAPMT_OSCAM_NET_PROTO && diff --git a/src/input/mpegts/dvb_psi.c b/src/input/mpegts/dvb_psi.c index 9d691a45d..0046821b4 100644 --- a/src/input/mpegts/dvb_psi.c +++ b/src/input/mpegts/dvb_psi.c @@ -1018,10 +1018,11 @@ dvb_pmt_callback pthread_mutex_lock(&s->s_stream_mutex); r = psi_parse_pmt(mt->mt_mux, s, ptr, len, &update); pthread_mutex_unlock(&s->s_stream_mutex); - if (update & PMT_UPDATE_NEW_CAID) - descrambler_caid_changed((service_t *)s); if (r) service_restart((service_t*)s); + else if (update & (PMT_UPDATE_NEW_CA_STREAM|PMT_UPDATE_NEW_CAID| + PMT_UPDATE_CAID_DELETED|PMT_UPDATE_CAID_PID)) + descrambler_caid_changed((service_t *)s); #if ENABLE_LINUXDVB_CA /* DVBCAM requires full pmt data including header and crc */ diff --git a/src/service.c b/src/service.c index f00b9522e..6bc029172 100644 --- a/src/service.c +++ b/src/service.c @@ -687,9 +687,10 @@ service_start(service_t *t, int instance, int weight, int flags, pthread_mutex_lock(&t->s_stream_mutex); service_build_filter(t); - descrambler_caid_changed(t); pthread_mutex_unlock(&t->s_stream_mutex); + descrambler_caid_changed(t); + if((r = t->s_start_feed(t, instance, weight, flags))) return r; @@ -1408,6 +1409,8 @@ service_restart(service_t *t) pthread_mutex_unlock(&t->s_stream_mutex); + descrambler_caid_changed(t); + refresh: if(t->s_refresh_feed != NULL) t->s_refresh_feed(t); -- 2.47.3