diff --git a/src/descrambler.h b/src/descrambler.h index dadc8441..9d3981b5 100755 --- a/src/descrambler.h +++ b/src/descrambler.h @@ -51,6 +51,7 @@ typedef struct th_descrambler { void (*td_stop) (struct th_descrambler *d); void (*td_caid_change)(struct th_descrambler *d); + int (*td_ecm_reset) (struct th_descrambler *d); } th_descrambler_t; diff --git a/src/descrambler/capmt.c b/src/descrambler/capmt.c index 8b11664b..64cd7a20 100644 --- a/src/descrambler/capmt.c +++ b/src/descrambler/capmt.c @@ -182,6 +182,7 @@ typedef struct capmt_service { /* list of used ca-systems with ids and last ecm */ struct capmt_caid_ecm_list ct_caid_ecm; + int ct_constcw; /* fast flag */ tvhcsa_t ct_csa; @@ -935,6 +936,17 @@ capmt_abort(capmt_t *capmt, int keystate) } #endif +static int +capmt_ecm_reset(th_descrambler_t *th) +{ + capmt_service_t *ct = (capmt_service_t *)th; + + if (ct->ct_constcw) + return 1; /* keys will not change */ + ct->td_keystate = DS_UNKNOWN; + return 0; +} + static void capmt_process_key(capmt_t *capmt, uint8_t adapter, uint16_t seq, const uint8_t *even, const uint8_t *odd, @@ -1538,6 +1550,7 @@ capmt_caid_change(th_descrambler_t *td) cce->cce_ecmpid = st->es_pid; cce->cce_providerid = c->providerid; LIST_INSERT_HEAD(&ct->ct_caid_ecm, cce, cce_link); + ct->ct_constcw |= c->caid == 0x2600 ? 1 : 0; change = 1; } } @@ -1812,6 +1825,7 @@ capmt_service_start(service_t *s) cce->cce_ecmpid = st->es_pid; cce->cce_providerid = c->providerid; LIST_INSERT_HEAD(&ct->ct_caid_ecm, cce, cce_link); + ct->ct_constcw |= c->caid == 0x2600 ? 1 : 0; change = 1; } } @@ -1826,6 +1840,7 @@ capmt_service_start(service_t *s) td->td_service = s; td->td_stop = capmt_service_destroy; td->td_caid_change = capmt_caid_change; + td->td_ecm_reset = capmt_ecm_reset; LIST_INSERT_HEAD(&t->s_descramblers, td, td_service_link); LIST_INSERT_HEAD(&capmt->capmt_services, ct, ct_link); diff --git a/src/descrambler/cwc.c b/src/descrambler/cwc.c index 0f249061..a4ff0065 100755 --- a/src/descrambler/cwc.c +++ b/src/descrambler/cwc.c @@ -147,6 +147,7 @@ typedef struct cwc_service { tvhcsa_t cs_csa; LIST_HEAD(, ecm_pid) cs_pids; + int cs_constcw; } cwc_service_t; @@ -692,7 +693,17 @@ cwc_send_login(cwc_t *cwc) return 0; } +static int +cwc_ecm_reset(th_descrambler_t *th) +{ + cwc_service_t *ct = (cwc_service_t *)th; + if (ct->cs_constcw) + return 1; /* keys will not change */ + ct->td_keystate = DS_UNKNOWN; + ct->ecm_state = ECM_RESET; + return 0; +} static void handle_ecm_reply(cwc_service_t *ct, ecm_section_t *es, uint8_t *msg, @@ -1991,6 +2002,7 @@ cwc_service_start(service_t *t) ct->cs_channel = -1; ct->cs_mux = ((mpegts_service_t *)t)->s_dvb_mux; ct->ecm_state = ECM_INIT; + ct->cs_constcw = pcard->cwc_caid == 0x2600; td = (th_descrambler_t *)ct; tvhcsa_init(td->td_csa = &ct->cs_csa); @@ -1998,6 +2010,7 @@ cwc_service_start(service_t *t) td->td_nicename = strdup(buf); td->td_service = t; td->td_stop = cwc_service_destroy; + td->td_ecm_reset = cwc_ecm_reset; LIST_INSERT_HEAD(&t->s_descramblers, td, td_service_link); LIST_INSERT_HEAD(&cwc->cwc_services, ct, cs_link); diff --git a/src/descrambler/descrambler.c b/src/descrambler/descrambler.c index 5408dc0d..ecbdda7e 100755 --- a/src/descrambler/descrambler.c +++ b/src/descrambler/descrambler.c @@ -222,6 +222,30 @@ fin: pthread_mutex_unlock(&t->s_stream_mutex); } +static void +descrambler_flush_table_data( service_t *t ) +{ + mpegts_service_t *ms = (mpegts_service_t *)t; + mpegts_mux_t *mux = ms->s_dvb_mux; + descrambler_table_t *dt; + descrambler_section_t *ds; + + if (mux == NULL) + return; + tvhtrace("descrabler", "flush table data for service \"%s\"", ms->s_dvb_svcname); + pthread_mutex_lock(&mux->mm_descrambler_lock); + TAILQ_FOREACH(dt, &mux->mm_descrambler_tables, link) { + if (dt->table == NULL || dt->table->mt_service != ms) + continue; + TAILQ_FOREACH(ds, &dt->sections, link) { + free(ds->last_data); + ds->last_data = NULL; + ds->last_data_len = 0; + } + } + pthread_mutex_unlock(&mux->mm_descrambler_lock); +} + static inline void key_update( th_descrambler_runtime_t *dr, uint8_t key ) { @@ -238,7 +262,7 @@ descrambler_descramble ( service_t *t, #define KEY_MASK(k) (((k) & 0x40) + 0x40) /* 0x40 (for even) or 0x80 (for odd) */ th_descrambler_t *td; th_descrambler_runtime_t *dr = t->s_descramble; - int count, failed, off, size; + int count, failed, off, size, flush_data = 0; uint8_t *tsb2, ki; lock_assert(&t->s_stream_mutex); @@ -270,7 +294,8 @@ descrambler_descramble ( service_t *t, ((mpegts_service_t *)t)->s_dvb_svcname); if (dr->dr_ecm_key_time + 2 < dr->dr_key_start) { sbuf_cut(&dr->dr_buf, off); - goto idle; + if (!td->td_ecm_reset(td)) + goto next; } key_update(dr, ki); } @@ -300,7 +325,8 @@ descrambler_descramble ( service_t *t, tvhtrace("descrambler", "ECM late (%ld seconds) for service \"%s\"", dispatch_clock - dr->dr_ecm_key_time, ((mpegts_service_t *)t)->s_dvb_svcname); - goto idle; + if (!td->td_ecm_reset(td)) + goto next; } key_update(dr, ki); } @@ -310,9 +336,8 @@ descrambler_descramble ( service_t *t, tsb); dr->dr_last_descramble = dispatch_clock; return 1; -idle: - td->td_keystate = DS_IDLE; - failed++; +next: + flush_data = 1; continue; } if (dr->dr_ecm_start) { /* ECM sent */ @@ -344,6 +369,8 @@ idle: sbuf_append(&dr->dr_buf, tsb, 188); } } + if (flush_data) + descrambler_flush_table_data(t); if (dr->dr_last_descramble + 25 < dispatch_clock) return -1; if (count && count == failed)