descrambler: improve the ECM handling

- for constcw (CAID 2600) do not expect any key change
- when the stream is broken, try to issue new ECM request

Note: The TS data might be wrong (which may cause the ECM late
situations). This patch tries to ask for new ECM to be sure
that the keys are correct. The constcw specific code is just
an optimization. The new ECM request is not required for it.
This commit is contained in:
Jaroslav Kysela 2014-07-07 11:47:34 +02:00
parent 41a6af0c76
commit f0b284065d
4 changed files with 62 additions and 6 deletions

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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)