#define MAX_QUICK_ECM_ENTRIES 100
#define MAX_CONSTCW_ENTRIES 100
+#define MAX_MULTI_PID_ENTRIES 100
typedef struct th_descrambler_data {
TAILQ_ENTRY(th_descrambler_data) dd_link;
TAILQ_HEAD(th_descrambler_queue, th_descrambler_data);
+uint16_t *multi_pid_table = NULL;
uint16_t *quick_ecm_table = NULL;
uint16_t *constcw_table = NULL;
/*
*
*/
-void
-descrambler_init ( void )
+static uint16_t *
+descrambler_load_table(htsmsg_t *c, const char *name, const char *field, int max)
{
- htsmsg_t *c, *e, *q;
+ htsmsg_t *e, *q;
htsmsg_field_t *f;
const char *s;
uint32_t caid;
int idx;
+ uint16_t *table = NULL;
+
+ idx = 0;
+ if ((q = htsmsg_get_list(c, field)) != NULL) {
+ HTSMSG_FOREACH(f, q) {
+ if (!(e = htsmsg_field_get_map(f))) continue;
+ if (idx + 1 >= max) break;
+ if ((s = htsmsg_get_str(e, "caid")) == NULL) continue;
+ caid = strtol(s, NULL, 16);
+ tvhinfo(LS_DESCRAMBLER, "adding CAID %04X as %s (%s)",
+ caid, name, htsmsg_get_str(e, "name") ?: "unknown");
+ if (!quick_ecm_table)
+ quick_ecm_table = malloc(sizeof(uint16_t) * max);
+ quick_ecm_table[idx++] = caid;
+ }
+ if (table)
+ table[idx] = 0;
+ }
+ return table;
+}
+
+/*
+ *
+ */
+void
+descrambler_init ( void )
+{
+ htsmsg_t *c;
#if (ENABLE_CWC || ENABLE_CAPMT || ENABLE_CCCAM) && !ENABLE_DVBCSA
ffdecsa_init();
#endif
if ((c = hts_settings_load("descrambler")) != NULL) {
- idx = 0;
- if ((q = htsmsg_get_list(c, "quick_ecm")) != NULL) {
- HTSMSG_FOREACH(f, q) {
- if (!(e = htsmsg_field_get_map(f))) continue;
- if (idx + 1 >= MAX_QUICK_ECM_ENTRIES) continue;
- if ((s = htsmsg_get_str(e, "caid")) == NULL) continue;
- caid = strtol(s, NULL, 16);
- tvhinfo(LS_DESCRAMBLER, "adding CAID %04X as quick ECM (%s)", caid, htsmsg_get_str(e, "name") ?: "unknown");
- if (!quick_ecm_table)
- quick_ecm_table = malloc(sizeof(uint16_t) * MAX_QUICK_ECM_ENTRIES);
- quick_ecm_table[idx++] = caid;
- }
- if (quick_ecm_table)
- quick_ecm_table[idx] = 0;
- }
- idx = 0;
- if ((q = htsmsg_get_list(c, "const_cw")) != NULL) {
- HTSMSG_FOREACH(f, q) {
- if (!(e = htsmsg_field_get_map(f))) continue;
- if (idx + 1 >= MAX_CONSTCW_ENTRIES) continue;
- if ((s = htsmsg_get_str(e, "caid")) == NULL) continue;
- caid = strtol(s, NULL, 16);
- tvhinfo(LS_DESCRAMBLER, "adding CAID %04X as constant crypto-word (%s)", caid, htsmsg_get_str(e, "name") ?: "unknown");
- if (!constcw_table)
- constcw_table = malloc(sizeof(uint16_t) * MAX_CONSTCW_ENTRIES);
- constcw_table[idx++] = caid;
- }
- if (constcw_table)
- constcw_table[idx] = 0;
- }
+ quick_ecm_table = descrambler_load_table(c, "quick ECM", "quick_ecm", MAX_QUICK_ECM_ENTRIES);
+ constcw_table = descrambler_load_table(c, "const_cw", "constant crypto-word", MAX_CONSTCW_ENTRIES);
+ multi_pid_table = descrambler_load_table(c, "multi_pid", "multiple PIDs", MAX_MULTI_PID_ENTRIES);
htsmsg_destroy(c);
}
}
quick_ecm_table = NULL;
free(constcw_table);
constcw_table = NULL;
+ free(multi_pid_table);
+ multi_pid_table = NULL;
}
/*
descrambler_service_start ( service_t *t )
{
th_descrambler_runtime_t *dr;
+ th_descrambler_key_t *tk;
elementary_stream_t *st;
caid_t *ca;
- int count, constcw = 0;
+ int i, count, constcw = 0, multipid = 0;
uint16_t *p;
if (t->s_scrambled_pass)
for (p = constcw_table; p && *p; p++)
if (ca->caid == *p) {
constcw = 1;
- break;
+ }
+ for (p = multi_pid_table; p && *p; p++)
+ if (ca->caid == *p) {
+ multipid = 1;
}
count++;
}
}
}
+ if (multi_pid_table) {
+ for (p = multi_pid_table; *p; p++)
+ if (*p == t->s_dvb_forcecaid) {
+ multipid = 1;
+ break;
+ }
+ }
+
}
((mpegts_service_t *)t)->s_dvb_mux->mm_descrambler_flush = 0;
t->s_descramble = dr = calloc(1, sizeof(th_descrambler_runtime_t));
dr->dr_service = t;
TAILQ_INIT(&dr->dr_queue);
- dr->dr_key_index = 0xff;
- dr->dr_key_interval = sec2mono(10);
+ for (i = 0; i < DESCRAMBLER_MAX_KEYS; i++) {
+ tk = &dr->dr_keys[i];
+ tk->key_index = 0xff;
+ tk->key_interval = multipid ? sec2mono(2) : sec2mono(10);
+ tvhcsa_init(&tk->key_csa);
+ if (!multipid) break;
+ }
dr->dr_key_const = constcw;
+ dr->dr_key_multipid = multipid;
if (constcw)
tvhtrace(LS_DESCRAMBLER, "using constcw for \"%s\"", t->s_nicename);
+ if (multipid)
+ tvhtrace(LS_DESCRAMBLER, "using multipid for \"%s\"", t->s_nicename);
dr->dr_skip = 0;
dr->dr_force_skip = 0;
- tvhcsa_init(&dr->dr_csa);
}
if (t->s_dvb_forcecaid != 0xffff)
{
th_descrambler_t *td;
th_descrambler_runtime_t *dr = t->s_descramble;
+ th_descrambler_key_t *tk;
th_descrambler_data_t *dd;
void *p;
+ int i;
#if ENABLE_LINUXDVB_CA
dvbcam_service_stop(t);
t->s_descramble_info = NULL;
free(p);
if (dr) {
- tvhcsa_destroy(&dr->dr_csa);
+ for (i = 0; i < DESCRAMBLER_MAX_KEYS; i++) {
+ tk = &dr->dr_keys[i];
+ tvhcsa_destroy(&tk->key_csa);
+ if (!dr->dr_key_multipid) break;
+ }
while ((dd = TAILQ_FIRST(&dr->dr_queue)) != NULL)
descrambler_data_destroy(dr, dd, 0);
free(dr);
}
void
-descrambler_keys ( th_descrambler_t *td, int type,
+descrambler_keys ( th_descrambler_t *td, int type, uint16_t pid,
const uint8_t *even, const uint8_t *odd )
{
static uint8_t empty[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
service_t *t = td->td_service;
th_descrambler_runtime_t *dr;
+ th_descrambler_key_t *tk;
th_descrambler_t *td2;
+ char pidname[16];
+ uint16_t pid2;
int j = 0;
if (t == NULL || (dr = t->s_descramble) == NULL) {
pthread_mutex_lock(&t->s_stream_mutex);
- if (tvhcsa_set_type(&dr->dr_csa, type) < 0)
+ if (!dr->dr_key_multipid)
+ pid = 0;
+
+ for (j = 0; j < DESCRAMBLER_MAX_KEYS; j++) {
+ tk = &dr->dr_keys[j];
+ pid2 = tk->key_pid;
+ if (pid2 == 0 || pid2 == pid) break;
+ }
+
+ if (j >= DESCRAMBLER_MAX_KEYS) {
+ tvherror(LS_DESCRAMBLER, "too many keys");
+ goto fin;
+ }
+
+ if (tvhcsa_set_type(&tk->key_csa, type) < 0)
goto fin;
LIST_FOREACH(td2, &t->s_descramblers, td_service_link)
if (td2 != td && td2->td_keystate == DS_RESOLVED) {
tvhdebug(LS_DESCRAMBLER,
- "Already has a key from %s for service \"%s\", "
+ "Already has a key[%d] from %s for service \"%s\", "
"ignoring key from \"%s\"%s",
- td2->td_nicename,
+ tk->key_pid, td2->td_nicename,
((mpegts_service_t *)td2->td_service)->s_dvb_svcname,
td->td_nicename,
dr->dr_key_const ? " (const)" : "");
goto fin;
}
- if (memcmp(empty, even, dr->dr_csa.csa_keylen)) {
+ if (memcmp(empty, even, tk->key_csa.csa_keylen)) {
j++;
- memcpy(dr->dr_key_even, even, dr->dr_csa.csa_keylen);
- dr->dr_key_changed |= 1;
- dr->dr_key_valid |= 0x40;
- dr->dr_key_timestamp[0] = mclk();
+ memcpy(tk->key_data[0], even, tk->key_csa.csa_keylen);
+ tk->key_changed |= 1;
+ tk->key_valid |= 0x40;
+ tk->key_timestamp[0] = mclk();
}
- if (memcmp(empty, odd, dr->dr_csa.csa_keylen)) {
+ if (memcmp(empty, odd, tk->key_csa.csa_keylen)) {
j++;
- memcpy(dr->dr_key_odd, odd, dr->dr_csa.csa_keylen);
- dr->dr_key_changed |= 2;
- dr->dr_key_valid |= 0x80;
- dr->dr_key_timestamp[1] = mclk();
+ memcpy(tk->key_data[1], odd, tk->key_csa.csa_keylen);
+ tk->key_changed |= 2;
+ tk->key_valid |= 0x80;
+ tk->key_timestamp[1] = mclk();
}
+ if (pid == 0)
+ pidname[0] = '\0';
+ else
+ snprintf(pidname, sizeof(pidname), "[%d]", pid);
if (j) {
if (td->td_keystate != DS_RESOLVED)
- tvhdebug( LS_DESCRAMBLER,
- "Obtained keys from %s for service \"%s\"%s",
- td->td_nicename,
+ tvhdebug(LS_DESCRAMBLER,
+ "Obtained keys%s from %s for service \"%s\"%s",
+ pidname, td->td_nicename,
((mpegts_service_t *)t)->s_dvb_svcname,
dr->dr_key_const ? " (const)" : "");
- if (dr->dr_csa.csa_keylen == 8) {
- tvhtrace(LS_DESCRAMBLER, "Obtained keys "
+ if (tk->key_csa.csa_keylen == 8) {
+ tvhtrace(LS_DESCRAMBLER, "Obtained keys%s "
"%02X%02X%02X%02X%02X%02X%02X%02X:%02X%02X%02X%02X%02X%02X%02X%02X"
- " from %s for service \"%s\"",
+ " pid %04X from %s for service \"%s\"",
+ pidname,
even[0], even[1], even[2], even[3], even[4], even[5], even[6], even[7],
odd[0], odd[1], odd[2], odd[3], odd[4], odd[5], odd[6], odd[7],
- td->td_nicename,
+ pid, td->td_nicename,
((mpegts_service_t *)t)->s_dvb_svcname);
- } else if (dr->dr_csa.csa_keylen == 16) {
- tvhtrace(LS_DESCRAMBLER, "Obtained keys "
+ } else if (tk->key_csa.csa_keylen == 16) {
+ tvhtrace(LS_DESCRAMBLER, "Obtained keys%s "
"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X:"
"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X"
- " from %s for service \"%s\"",
+ " pid %04X from %s for service \"%s\"",
+ pidname,
even[0], even[1], even[2], even[3], even[4], even[5], even[6], even[7],
even[8], even[9], even[10], even[11], even[12], even[13], even[14], even[15],
odd[0], odd[1], odd[2], odd[3], odd[4], odd[5], odd[6], odd[7],
odd[8], odd[9], odd[10], odd[11], odd[12], odd[13], odd[14], odd[15],
- td->td_nicename,
+ pid, td->td_nicename,
((mpegts_service_t *)t)->s_dvb_svcname);
} else {
- tvhtrace(LS_DESCRAMBLER, "Unknown keys from %s for for service \"%s\"",
- td->td_nicename, ((mpegts_service_t *)t)->s_dvb_svcname);
+ tvhtrace(LS_DESCRAMBLER, "Unknown keys%s pid %04X from %s for for service \"%s\"",
+ pidname, pid, td->td_nicename, ((mpegts_service_t *)t)->s_dvb_svcname);
}
dr->dr_ecm_last_key_time = mclk();
td->td_keystate = DS_RESOLVED;
td->td_service->s_descrambler = td;
} else {
tvhdebug(LS_DESCRAMBLER,
- "Empty keys received from %s for service \"%s\"%s",
- td->td_nicename,
+ "Empty keys%s received from %s for service \"%s\"%s",
+ pidname, td->td_nicename,
((mpegts_service_t *)t)->s_dvb_svcname,
dr->dr_key_const ? " (const)" : "");
}
#if ENABLE_TSDEBUG
if (j) {
tsdebug_packet_t *tp = malloc(sizeof(*tp));
- uint16_t keylen = dr->dr_csa.csa_keylen;
+ uint16_t keylen = tk->key_csa.csa_keylen;
uint16_t sid = ((mpegts_service_t *)td->td_service)->s_dvb_service_id;
uint32_t pos = 0, crc;
mpegts_mux_t *mm = ((mpegts_service_t *)td->td_service)->s_dvb_mux;
tp->pkt[pos++] = keylen & 0xff;
tp->pkt[pos++] = (sid >> 8) & 0xff;
tp->pkt[pos++] = sid & 0xff;
+ tp->pkt[pos++] = (pid >> 8) & 0xff;
+ tp->pkt[pos++] = pid & 0xff;
memcpy(tp->pkt + pos, even, keylen);
memcpy(tp->pkt + pos + keylen, odd, keylen);
pos += 2 * keylen;
pthread_mutex_unlock(&mux->mm_descrambler_lock);
}
-static inline void
-key_update( th_descrambler_runtime_t *dr, uint8_t key, int64_t timestamp )
+static inline void
+key_update( th_descrambler_key_t *tk, uint8_t key, int64_t timestamp )
{
/* set the even (0) or odd (0x40) key index */
- dr->dr_key_index = key & 0x40;
- if (dr->dr_key_start) {
- dr->dr_key_interval = dr->dr_key_start + sec2mono(50) < timestamp ?
- sec2mono(10) : timestamp - dr->dr_key_start;
- dr->dr_key_start = timestamp;
+ tk->key_index = key & 0x40;
+ if (tk->key_start) {
+ tk->key_interval = tk->key_start + sec2mono(50) < timestamp ?
+ sec2mono(10) : timestamp - tk->key_start;
+ tk->key_start = timestamp;
} else {
/* We don't know the exact start key switch time */
- dr->dr_key_start = timestamp - sec2mono(60);
+ tk->key_start = timestamp - sec2mono(60);
}
}
static inline int
-key_changed ( th_descrambler_runtime_t *dr, uint8_t ki, int64_t timestamp )
+key_changed ( th_descrambler_key_t *tk, uint8_t ki, int64_t timestamp )
{
- return dr->dr_key_index != (ki & 0x40) &&
- dr->dr_key_start + sec2mono(2) < timestamp;
+ return tk->key_index != (ki & 0x40) &&
+ tk->key_start + sec2mono(2) < timestamp;
}
static inline int
-key_valid ( th_descrambler_runtime_t *dr, uint8_t ki )
+key_valid ( th_descrambler_key_t *tk, uint8_t ki )
{
/* 0x40 (for even) or 0x80 (for odd) */
uint8_t mask = ((ki & 0x40) + 0x40);
- return dr->dr_key_valid & mask;
+ return tk->key_valid & mask;
}
static inline int
-key_late( th_descrambler_runtime_t *dr, uint8_t ki, int64_t timestamp )
+key_late( th_descrambler_runtime_t *dr, th_descrambler_key_t *tk, uint8_t ki, int64_t timestamp )
{
uint8_t kidx = (ki & 0x40) >> 6;
/* constcw - do not handle keys */
if (dr->dr_key_const)
return 0;
/* required key is older than previous? */
- if (dr->dr_key_timestamp[kidx] < dr->dr_key_timestamp[kidx^1]) {
+ if (tk->key_timestamp[kidx] < tk->key_timestamp[kidx^1]) {
/* but don't take in account the keys modified just now */
- if (dr->dr_key_timestamp[kidx^1] + 2 < timestamp)
+ if (tk->key_timestamp[kidx^1] + 2 < timestamp)
goto late;
}
/* ECM was sent, but no new key was received */
- if (dr->dr_ecm_last_key_time + sec2mono(2) < dr->dr_key_start &&
- (!dr->dr_quick_ecm || dr->dr_ecm_start[kidx] + 4 < dr->dr_key_start)) {
+ if (dr->dr_ecm_last_key_time + sec2mono(2) < tk->key_start &&
+ (!dr->dr_quick_ecm || dr->dr_ecm_start[kidx] + 4 < tk->key_start)) {
late:
- dr->dr_key_valid &= ~((ki & 0x40) + 0x40);
+ tk->key_valid &= ~((ki & 0x40) + 0x40);
return 1;
}
return 0;
return mclk() - dr->dr_ecm_start[kidx] < sec2mono(5);
}
+static void
+key_flush( th_descrambler_key_t *tk, service_t *t )
+{
+ /* update the keys */
+ if (tk->key_changed) {
+ tk->key_csa.csa_flush(&tk->key_csa, (mpegts_service_t *)t);
+ if (tk->key_changed & 1)
+ tvhcsa_set_key_odd(&tk->key_csa, tk->key_data[0]);
+ if (tk->key_changed & 2)
+ tvhcsa_set_key_odd(&tk->key_csa, tk->key_data[1]);
+ tk->key_changed = 0;
+ }
+}
+
+static th_descrambler_key_t *
+key_find_struct( th_descrambler_runtime_t *dr,
+ th_descrambler_key_t *tk_old,
+ const uint8_t *tsb,
+ service_t *t )
+{
+ th_descrambler_key_t *tk;
+ int i, pid = (tsb[1] & 0x1f) << 8 | tsb[2];
+ for (i = 0; i < DESCRAMBLER_MAX_KEYS; i++) {
+ tk = &dr->dr_keys[i];
+ if (tk->key_pid == pid) {
+ if (tk != tk_old && tk_old)
+ key_flush(tk_old, t);
+ return tk;
+ }
+ }
+ return NULL;
+}
+
static int
ecm_reset( service_t *t, th_descrambler_runtime_t *dr )
{
th_descrambler_t *td;
- int ret = 0;
+ th_descrambler_key_t *tk;
+ int ret = 0, i;
/* reset the reader ECM state */
LIST_FOREACH(td, &t->s_descramblers, td_service_link) {
if (!td->td_ecm_reset(td)) {
- dr->dr_key_valid = 0;
+ for (i = 0; i < DESCRAMBLER_MAX_KEYS; i++) {
+ tk = &dr->dr_keys[i];
+ tk->key_valid = 0;
+ if (tk->key_pid == 0)
+ break;
+ }
ret = 1;
}
}
{
th_descrambler_t *td;
th_descrambler_runtime_t *dr = t->s_descramble;
+ th_descrambler_key_t *tk;
th_descrambler_data_t *dd, *dd_next;
int count, failed, resolved, len2, len3, flush_data = 0;
uint32_t dbuflen;
return dr && dr->dr_external ? 1 : -1;
}
- if (dr->dr_csa.csa_type == DESCRAMBLER_NONE && dr->dr_queue_total == 0)
+ if (!dr->dr_key_multipid) {
+ tk = &dr->dr_keys[0];
+ } else {
+ tk = key_find_struct(dr, NULL, tsb, t);
+ }
+ if ((tk == NULL || tk->key_csa.csa_type == DESCRAMBLER_NONE) && dr->dr_queue_total == 0)
if ((tsb[3] & 0x80) == 0) {
ts_recv_packet0((mpegts_service_t *)t, st, tsb, len);
return 1;
if (resolved) {
- /* update the keys */
- if (dr->dr_key_changed) {
- dr->dr_csa.csa_flush(&dr->dr_csa, (mpegts_service_t *)t);
- if (dr->dr_key_changed & 1)
- tvhcsa_set_key_even(&dr->dr_csa, dr->dr_key_even);
- if (dr->dr_key_changed & 2)
- tvhcsa_set_key_odd(&dr->dr_csa, dr->dr_key_odd);
- dr->dr_key_changed = 0;
+ if (!dr->dr_key_multipid) {
+ tk = &dr->dr_keys[0];
+ key_flush(tk, t);
+ } else {
+ tk = NULL;
}
/* process the queued TS packets */
if (dr->dr_queue_total > 0) {
- descrambler_data_time_flush(dr, mclk() - (dr->dr_key_interval - sec2mono(2)));
+ if (!dr->dr_key_multipid)
+ descrambler_data_time_flush(dr, mclk() - (tk->key_interval - sec2mono(2)));
for (dd = TAILQ_FIRST(&dr->dr_queue); dd; dd = dd_next) {
dd_next = TAILQ_NEXT(dd, dd_link);
sb = &dd->dd_sbuf;
for (; len2 > 0; tsb2 += len3, len2 -= len3) {
ki = tsb2[3];
if ((ki & 0x80) != 0x00) {
- if (key_valid(dr, ki) == 0)
+ if (dr->dr_key_multipid) {
+ tk = key_find_struct(dr, tk, tsb2, t);
+ if (tk == NULL) goto next;
+ }
+ if (key_valid(tk, ki) == 0)
goto next;
- if (key_changed(dr, ki, dd->dd_timestamp)) {
- tvhtrace(LS_DESCRAMBLER, "stream key changed to %s for service \"%s\"",
- (ki & 0x40) ? "odd" : "even",
+ if (key_changed(tk, ki, dd->dd_timestamp)) {
+ tvhtrace(LS_DESCRAMBLER, "stream key[%d] changed to %s for service \"%s\"",
+ tk->key_pid, (ki & 0x40) ? "odd" : "even",
((mpegts_service_t *)t)->s_dvb_svcname);
- if (key_late(dr, ki, dd->dd_timestamp)) {
+ if (key_late(dr, tk, ki, dd->dd_timestamp)) {
descrambler_notify_nokey(dr);
if (ecm_reset(t, dr)) {
descrambler_data_cut(dr, tsb2 - sb->sb_data);
goto next;
}
}
- key_update(dr, ki, dd->dd_timestamp);
+ key_update(tk, ki, dd->dd_timestamp);
}
}
- len3 = mpegts_word_count(tsb2, len2, 0xFF0000C0);
- dr->dr_csa.csa_descramble(&dr->dr_csa, (mpegts_service_t *)t, tsb2, len3);
+ len3 = mpegts_word_count(tsb2, len2, dr->dr_key_multipid ? 0xFF1FFFC0 : 0xFF0000C0);
+ tk->key_csa.csa_descramble(&tk->key_csa, (mpegts_service_t *)t, tsb2, len3);
}
if (len2 == 0)
service_reset_streaming_status_flags(t, TSS_NO_ACCESS);
/* check for key change */
ki = tsb[3];
if ((ki & 0x80) != 0x00) {
- if (key_valid(dr, ki) == 0) {
+ if (dr->dr_key_multipid) {
+ tk = key_find_struct(dr, tk, tsb, t);
+ if (tk == NULL) goto next;
+ }
+ if (key_valid(tk, ki) == 0) {
if (!key_started(dr, ki) && tvhlog_limit(&dr->dr_loglimit_key, 10))
- tvhwarn(LS_DESCRAMBLER, "%s %s",
+ tvhwarn(LS_DESCRAMBLER, "%s %s stream key[%d] is not valid",
((mpegts_service_t *)t)->s_dvb_svcname,
- (ki & 0x40) ? "odd stream key is not valid" :
- "even stream key is not valid");
+ (ki & 0x40) ? "odd" : "even", tk->key_pid);
goto next;
}
- if (key_changed(dr, ki, mclk())) {
- tvhtrace(LS_DESCRAMBLER, "stream key changed to %s for service \"%s\"",
- (ki & 0x40) ? "odd" : "even",
+ if (key_changed(tk, ki, mclk())) {
+ tvhtrace(LS_DESCRAMBLER, "stream key[%d] changed to %s for service \"%s\"",
+ tk->key_pid, (ki & 0x40) ? "odd" : "even",
((mpegts_service_t *)t)->s_dvb_svcname);
- if (key_late(dr, ki, mclk())) {
- tvherror(LS_DESCRAMBLER, "ECM - key late (%"PRId64" ms) for service \"%s\"",
+ if (key_late(dr, tk, ki, mclk())) {
+ tvherror(LS_DESCRAMBLER, "ECM - key[%d] late (%"PRId64" ms) for service \"%s\"",
+ tk->key_pid,
mono2ms(mclk() - dr->dr_ecm_last_key_time),
((mpegts_service_t *)t)->s_dvb_svcname);
descrambler_notify_nokey(dr);
goto next;
}
}
- key_update(dr, ki, mclk());
+ key_update(tk, ki, mclk());
}
}
dr->dr_skip = 1;
- dr->dr_csa.csa_descramble(&dr->dr_csa, (mpegts_service_t *)t, tsb, len);
+ tk->key_csa.csa_descramble(&tk->key_csa, (mpegts_service_t *)t, tsb, len);
service_reset_streaming_status_flags(t, TSS_NO_ACCESS);
return 1;
}
if (dr->dr_ecm_start[0] || dr->dr_ecm_start[1]) { /* ECM sent */
ki = tsb[3];
if ((ki & 0x80) != 0x00) {
- if (dr->dr_key_start == 0) {
+ if (dr->dr_key_multipid) {
+ tk = key_find_struct(dr, tk, tsb, t);
+ if (tk == NULL) goto queue;
+ } else {
+ tk = &dr->dr_keys[0];
+ }
+ if (tk->key_start == 0) {
+ if (dr->dr_key_multipid)
+ goto update;
/* do not use the first TS packet to decide - it may be wrong */
while (dr->dr_queue_total > 20 * 188) {
if (descrambler_data_key_check(dr, ki & 0xc0, 20 * 188)) {
tvhtrace(LS_DESCRAMBLER, "initial stream key set to %s for service \"%s\"",
(ki & 0x40) ? "odd" : "even",
((mpegts_service_t *)t)->s_dvb_svcname);
- key_update(dr, ki, mclk());
+ key_update(tk, ki, mclk());
break;
} else {
descrambler_data_cut(dr, 188);
}
}
- } else if (dr->dr_key_index != (ki & 0x40) &&
- dr->dr_key_start + sec2mono(2) < mclk()) {
+ } else if (tk->key_index != (ki & 0x40) &&
+ tk->key_start + sec2mono(2) < mclk()) {
+update:
tvhtrace(LS_DESCRAMBLER, "stream key changed to %s for service \"%s\"",
(ki & 0x40) ? "odd" : "even",
((mpegts_service_t *)t)->s_dvb_svcname);
- key_update(dr, ki, mclk());
+ key_update(tk, ki, mclk());
}
}
+queue:
if (count != failed) {
/*
* Fill a temporary buffer until the keys are known to make
descrambler_section_t *ds;
descrambler_ecmsec_t *des;
th_descrambler_runtime_t *dr;
+ th_descrambler_key_t *tk;
int emm = (mt->mt_flags & MT_FAST) == 0;
+ uint8_t ki;
+ int i;
if (len < 6)
return 0;
}
if ((ptr[0] & 0xfe) == 0x80) { /* 0x80 = even, 0x81 = odd */
dr->dr_ecm_start[ptr[0] & 1] = mclk();
- if (dr->dr_quick_ecm)
- dr->dr_key_valid &= ~(1 << ((ptr[0] & 1) + 6)); /* 0x40 = even, 0x80 = odd */
+ if (dr->dr_quick_ecm) {
+ ki = 1 << ((ptr[0] & 1) + 6); /* 0x40 = even, 0x80 = odd */
+ for (i = 0; i < DESCRAMBLER_MAX_KEYS; i++) {
+ tk = &dr->dr_keys[i];
+ tk->key_valid &= ~ki;
+ if (tk->key_pid == 0) break;
+ }
+ }
}
tvhtrace(LS_DESCRAMBLER, "ECM message %02x (section %d, len %d, pid %d) for service \"%s\"",
ptr[0], des->number, len, mt->mt_pid, t->s_dvb_svcname);