Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
descrambler: added quick ECM handling and configurable descrambler bu…
…ffer settings (bug 3073)
  • Loading branch information
perexg committed Oct 1, 2015
1 parent bfe6bd5 commit e9c9344
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 12 deletions.
8 changes: 8 additions & 0 deletions src/config.c
Expand Up @@ -1549,6 +1549,7 @@ config_boot ( const char *path, gid_t gid, uid_t uid )
config.info_area = strdup("login,storage,time");
config.cookie_expires = 7;
config.dscp = -1;
config.descrambler_buffer = 9000;

/* Generate default */
if (!path) {
Expand Down Expand Up @@ -1889,6 +1890,13 @@ const idclass_t config_class = {
.list = config_class_dscp_list,
.group = 1
},
{
.type = PT_U32,
.id = "descrambler_buffer",
.name = N_("Descrambler buffer (TS packets)"),
.off = offsetof(config_t, descrambler_buffer),
.group = 1
},
{
.type = PT_STR,
.islist = 1,
Expand Down
1 change: 1 addition & 0 deletions src/config.h
Expand Up @@ -46,6 +46,7 @@ typedef struct config {
char *cors_origin;
uint32_t cookie_expires;
int dscp;
uint32_t descrambler_buffer;
} config_t;

extern const idclass_t config_class;
Expand Down
5 changes: 3 additions & 2 deletions src/descrambler.h
Expand Up @@ -62,15 +62,16 @@ typedef struct th_descrambler {

typedef struct th_descrambler_runtime {
tvhcsa_t dr_csa;
uint32_t dr_quick_ecm:1;
uint32_t dr_key:1;
uint32_t dr_key_first:1;
uint8_t dr_key_index;
uint8_t dr_key_valid;
uint8_t dr_key_changed;
time_t dr_key_start;
time_t dr_key_timestamp[2];
time_t dr_ecm_start;
time_t dr_ecm_key_time;
time_t dr_ecm_start[2];
time_t dr_ecm_last_key_time;
time_t dr_last_err;
sbuf_t dr_buf;
tvhlog_limit_t dr_loglimit_key;
Expand Down
47 changes: 37 additions & 10 deletions src/descrambler/descrambler.c
@@ -1,6 +1,8 @@
/*
* Tvheadend
* Copyright (C) 2013 Andreas Öman
* Copyright (C) 2014,2015 Jaroslav Kysela
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand All @@ -17,7 +19,9 @@
*/

#include "tvheadend.h"
#include "config.h"
#include "descrambler.h"
#include "caid.h"
#include "caclient.h"
#include "ffdecsa/FFdecsa.h"
#include "input.h"
Expand Down Expand Up @@ -52,12 +56,17 @@ descrambler_service_start ( service_t *t )
{
th_descrambler_runtime_t *dr;
elementary_stream_t *st;
caid_t *ca;
int quick_ecm = 0;

if (!((mpegts_service_t *)t)->s_dvb_forcecaid) {

TAILQ_FOREACH(st, &t->s_filt_components, es_filt_link)
if (LIST_FIRST(&st->es_caids))
if ((ca = LIST_FIRST(&st->es_caids)) != NULL) {
if (detect_card_type(ca->caid) == CARD_NDS)
quick_ecm = 1;
break;
}

/* Do not run descrambler on FTA channels */
if (!st)
Expand All @@ -68,6 +77,11 @@ descrambler_service_start ( service_t *t )
((mpegts_service_t *)t)->s_dvb_mux->mm_descrambler_flush = 0;
if (t->s_descramble == NULL) {
t->s_descramble = dr = calloc(1, sizeof(th_descrambler_runtime_t));
if (quick_ecm) {
tvhdebug("descrambler", "quick ECM enabled for service '%s'",
((mpegts_service_t *)t)->s_dvb_svcname);
dr->dr_quick_ecm = 1;
}
sbuf_init(&dr->dr_buf);
dr->dr_key_index = 0xff;
tvhcsa_init(&dr->dr_csa);
Expand Down Expand Up @@ -199,7 +213,7 @@ descrambler_keys ( th_descrambler_t *td, int type,
tvhtrace("descrambler", "Unknown keys from %s for for service \"%s\"",
td->td_nicename, ((mpegts_service_t *)t)->s_dvb_svcname);
}
dr->dr_ecm_key_time = dispatch_clock;
dr->dr_ecm_last_key_time = dispatch_clock;
td->td_keystate = DS_RESOLVED;
} else {
tvhlog(LOG_DEBUG, "descrambler",
Expand Down Expand Up @@ -305,7 +319,15 @@ key_late( th_descrambler_runtime_t *dr, uint8_t ki )
return 1;
}
/* ECM was sent, but no new key was received */
return dr->dr_ecm_key_time + 2 < dr->dr_key_start;
return dr->dr_ecm_last_key_time + 2 < dr->dr_key_start &&
(!dr->dr_quick_ecm || dr->dr_ecm_start[kidx] + 4 < dr->dr_key_start);
}

static inline int
key_started( th_descrambler_runtime_t *dr, uint8_t ki )
{
uint8_t kidx = (ki & 0x40) >> 6;
return (int64_t)dispatch_clock - (int64_t)dr->dr_ecm_start[kidx] < 5;
}

static int
Expand Down Expand Up @@ -333,6 +355,7 @@ descrambler_descramble ( service_t *t,
th_descrambler_t *td;
th_descrambler_runtime_t *dr = t->s_descramble;
int count, failed, resolved, off, len2, len3, flush_data = 0;
uint32_t dbuflen;
const uint8_t *tsb2;
uint8_t ki;

Expand Down Expand Up @@ -382,7 +405,6 @@ descrambler_descramble ( service_t *t,
if ((ki & 0x80) != 0x00) {
if (key_valid(dr, ki) == 0) {
sbuf_cut(&dr->dr_buf, tsb2 - dr->dr_buf.sb_data);
flush_data = 1;
goto next;
}
if (dr->dr_key_index != (ki & 0x40) &&
Expand Down Expand Up @@ -412,7 +434,7 @@ descrambler_descramble ( service_t *t,
ki = tsb[3];
if ((ki & 0x80) != 0x00) {
if (key_valid(dr, ki) == 0) {
if (tvhlog_limit(&dr->dr_loglimit_key, 10))
if (!key_started(dr, ki) && tvhlog_limit(&dr->dr_loglimit_key, 10))
tvhwarn("descrambler", "%s %s",
((mpegts_service_t *)t)->s_dvb_svcname,
(ki & 0x40) ? "odd stream key is not valid" :
Expand All @@ -426,7 +448,7 @@ descrambler_descramble ( service_t *t,
((mpegts_service_t *)t)->s_dvb_svcname);
if (key_late(dr, ki)) {
tvherror("descrambler", "ECM late (%ld seconds) for service \"%s\"",
dispatch_clock - dr->dr_ecm_key_time,
dispatch_clock - dr->dr_ecm_last_key_time,
((mpegts_service_t *)t)->s_dvb_svcname);
if (ecm_reset(t, dr)) {
flush_data = 1;
Expand All @@ -441,7 +463,7 @@ descrambler_descramble ( service_t *t,
return 1;
}
next:
if (dr->dr_ecm_start) { /* ECM sent */
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) {
Expand Down Expand Up @@ -472,8 +494,9 @@ descrambler_descramble ( service_t *t,
* Fill a temporary buffer until the keys are known to make
* streaming faster.
*/
if (dr->dr_buf.sb_ptr >= 3000 * 188) {
sbuf_cut(&dr->dr_buf, 300 * 188);
dbuflen = MAX(300, config.descrambler_buffer);
if (dr->dr_buf.sb_ptr >= dbuflen * 188) {
sbuf_cut(&dr->dr_buf, MAX((dbuflen / 10) * 188, len));
if (dr->dr_last_err + 10 < dispatch_clock) {
dr->dr_last_err = dispatch_clock;
tvherror("descrambler", "cannot decode packets for service \"%s\"",
Expand Down Expand Up @@ -539,7 +562,11 @@ descrambler_table_callback
/* The keys are requested from this moment */
dr = t->s_descramble;
if (dr) {
dr->dr_ecm_start = dispatch_clock;
if ((ptr[0] & 0xfe) == 0x80) { /* 0x80 = even, 0x81 = odd */
dr->dr_ecm_start[ptr[0] & 1] = dispatch_clock;
if (dr->dr_quick_ecm)
dr->dr_key_valid &= ~(1 << ((ptr[0] & 1) + 6)); /* 0x40 = even, 0x80 = odd */
}
tvhtrace("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);
}
Expand Down

0 comments on commit e9c9344

Please sign in to comment.