{
+ "caid_comment": "
+ *
+ * The CAID list contains configuration for separate CA systems.
+ *
+ * TVHeadend uses some techniques to decode the previous queued data to offer
+ * faster client input and data queing when the keys are late.
+ * Here is the descrambling layer configuration to do this properly.
+ *
+ * name - CA nice name
+ * caid - CAID (hexadecimal)
+ * mask - CAID mask (hexadecimal - use FFFF for single CAID)
+ * interval - expected ECM interval (in milliseconds)
+ * multipid - multiple keys for different PIDs
+ * quickecm - key is changed quickly upon the ECM change
+ * constcw - the key won't change (it may be used also to turn off
+ * the extra logic in TVH's code - may help for other CAs)
+ * paritycheck - number of TS packets to decide when the key parity was changed
+ * in the input TS stream
+ * ecmparity - can be a string from this list:
+ * 'standard' - ECM 0x80 means even, ECM 0x81 means odd
+ * 'inverted' - ECM 0x81 means even, ECM 0x80 means odd
+ ",
"caid": [
{
"name": "BISS",
#endif
+#define ECM_PARITY_DEFAULT 0
+#define ECM_PARITY_80EVEN_81ODD 1
+#define ECM_PARITY_81EVEN_80ODD 2
+
typedef struct th_descrambler_data {
TAILQ_ENTRY(th_descrambler_data) dd_link;
int64_t dd_timestamp;
uint16_t dh_mask;
uint32_t dh_interval;
uint32_t dh_paritycheck;
+ uint32_t dh_ecmparity;
uint32_t dh_constcw: 1;
uint32_t dh_quickecm: 1;
uint32_t dh_multipid: 1;
return 0;
}
+/*
+ *
+ */
+static struct strtab ecmparitytab[] = {
+ { "default", ECM_PARITY_DEFAULT },
+ { "standard", ECM_PARITY_80EVEN_81ODD },
+ { "inverted", ECM_PARITY_81EVEN_80ODD },
+};
+
/*
*
*/
hint.dh_multipid = htsmsg_get_bool_or_default(e, "multipid", 0);
hint.dh_interval = htsmsg_get_s32_or_default(e, "interval", 10000);
hint.dh_paritycheck = htsmsg_get_s32_or_default(e, "paritycheck", 20);
- tvhinfo(LS_DESCRAMBLER, "adding CAID %04X/%04X as%s%s%s interval %ums pc %d (%s)",
+ hint.dh_ecmparity = str2val_def(htsmsg_get_str(e, "ecmparity"), ecmparitytab, ECM_PARITY_DEFAULT);
+ tvhinfo(LS_DESCRAMBLER, "adding CAID %04X/%04X as%s%s%s interval %ums pc %d ep %s (%s)",
hint.dh_caid, hint.dh_mask,
hint.dh_constcw ? " ConstCW" : "",
hint.dh_quickecm ? " QuickECM" : "",
hint.dh_multipid ? " MultiPID" : "",
hint.dh_interval,
hint.dh_paritycheck,
+ val2str(hint.dh_ecmparity, ecmparitytab),
htsmsg_get_str(e, "name") ?: "unknown");
dhint = malloc(sizeof(*dhint));
*dhint = hint;
elementary_stream_t *st;
caid_t *ca;
int i, count, constcw = 0, multipid = 0, interval = 10000, paritycheck = 20;
+ int ecmparity = ECM_PARITY_DEFAULT;
if (t->s_scrambled_pass)
return;
if (hint->dh_multipid) multipid = 1;
if (hint->dh_interval) interval = hint->dh_interval;
if (hint->dh_paritycheck) paritycheck = hint->dh_paritycheck;
+ if (hint->dh_ecmparity != ECM_PARITY_DEFAULT)
+ ecmparity = hint->dh_ecmparity;
}
}
count++;
dr->dr_ecm_key_margin = ms2mono(interval) / 5;
dr->dr_key_const = constcw;
dr->dr_key_multipid = multipid;
+ dr->dr_ecm_parity = ecmparity ?: ECM_PARITY_80EVEN_81ODD;
if (constcw)
tvhtrace(LS_DESCRAMBLER, "using constcw for \"%s\"", t->s_nicename);
if (multipid)
}
if ((ptr[0] & 0xfe) == 0x80) { /* 0x80 = even, 0x81 = odd */
j = ptr[0] & 1;
+ if (dr->dr_ecm_parity == ECM_PARITY_81EVEN_80ODD)
+ j ^= 1;
dr->dr_ecm_start[j] = clk;
if (dr->dr_quick_ecm) {
ki = 1 << (j + 6); /* 0x40 = even, 0x80 = odd */