Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge remote-tracking branch 'upstream/master' into freebsd
* upstream/master:
  webui: enable file logging when the log file is set through GUI
  webui: remove dead code (tvhlog_level)
  webui: Stream directly for TVHeadend/ http client, too
  epggrab: ota - improve save caching and add no data timeout
  epggrab: ota - optimize the eit/opentv workflow
  epggrab: ota - requeue skipped muxes (network check)
  SAT>IP: finish the RTSP OPTIONS command to keep connection consistent
  SAT>IP: finish the RTSP command to keep connection consistent
  capmt: a slight optimization - remove the key data
  service_mapper: remove include "plumbing/tsfix.h"
  descrambler: add other odd/even key validity check based on the key update time
  capmt: do not cache keys for the descrambler layer
  • Loading branch information
dreamcat4 committed Jul 30, 2014
2 parents 974bbcb + 166a950 commit 156b24a
Show file tree
Hide file tree
Showing 11 changed files with 155 additions and 50 deletions.
1 change: 1 addition & 0 deletions src/descrambler.h
Expand Up @@ -63,6 +63,7 @@ typedef struct th_descrambler_runtime {
uint8_t dr_key_valid;
uint8_t dr_ecm_valid;
time_t dr_key_start;
time_t dr_key_timestamp[2];
time_t dr_ecm_start;
time_t dr_ecm_key_time;
sbuf_t dr_buf;
Expand Down
9 changes: 3 additions & 6 deletions src/descrambler/capmt.c
Expand Up @@ -125,8 +125,6 @@ static pthread_cond_t capmt_config_changed;
*/
typedef struct ca_info {
uint16_t seq; // sequence / service id number
uint8_t even[8];
uint8_t odd[8];
} ca_info_t;

/**
Expand Down Expand Up @@ -1043,6 +1041,7 @@ capmt_analyze_cmd(capmt_t *capmt, int adapter, sbuf_t *sb, int offset)

} else if (cmd == CA_SET_DESCR) {

static uint8_t empty[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
int32_t index = sbuf_peek_s32(sb, offset + 4);
int32_t parity = sbuf_peek_s32(sb, offset + 8);
uint8_t *cw = sbuf_peek (sb, offset + 12);
Expand All @@ -1055,11 +1054,9 @@ capmt_analyze_cmd(capmt_t *capmt, int adapter, sbuf_t *sb, int offset)
return;
cai = &capmt->capmt_adapters[adapter].ca_info[index];
if (parity == 0) {
memcpy(cai->even, cw, 8); // even key
capmt_process_key(capmt, adapter, cai->seq, cai->even, cai->odd, 1);
capmt_process_key(capmt, adapter, cai->seq, cw, empty, 1);
} else if (parity == 1) {
memcpy(cai->odd, cw, 8); // odd key
capmt_process_key(capmt, adapter, cai->seq, cai->even, cai->odd, 1);
capmt_process_key(capmt, adapter, cai->seq, empty, cw, 1);
} else
tvhlog(LOG_ERR, "capmt", "Invalid parity %d in CA_SET_DESCR for adapter%d", parity, adapter);

Expand Down
13 changes: 10 additions & 3 deletions src/descrambler/descrambler.c
Expand Up @@ -186,13 +186,15 @@ descrambler_keys ( th_descrambler_t *td,
j++;
tvhcsa_set_key_even(td->td_csa, even);
dr->dr_key_valid |= 0x40;
dr->dr_key_timestamp[0] = dispatch_clock;
break;
}
for (i = 0; i < 8; i++)
if (odd[i]) {
j++;
tvhcsa_set_key_odd(td->td_csa, odd);
dr->dr_key_valid |= 0x80;
dr->dr_key_timestamp[1] = dispatch_clock;
break;
}

Expand Down Expand Up @@ -260,10 +262,11 @@ descrambler_descramble ( service_t *t,
const uint8_t *tsb )
{
#define KEY_MASK(k) (((k) & 0x40) + 0x40) /* 0x40 (for even) or 0x80 (for odd) */
#define KEY_IDX(k) (((k) & 0x40) >> 6)
th_descrambler_t *td;
th_descrambler_runtime_t *dr = t->s_descramble;
int count, failed, off, size, flush_data = 0;
uint8_t *tsb2, ki;
uint8_t *tsb2, ki, kidx;

lock_assert(&t->s_stream_mutex);

Expand Down Expand Up @@ -292,7 +295,9 @@ descrambler_descramble ( service_t *t,
tvhtrace("descrambler", "stream key changed to %s for service \"%s\"",
(ki & 0x40) ? "odd" : "even",
((mpegts_service_t *)t)->s_dvb_svcname);
if (dr->dr_ecm_key_time +
kidx = KEY_IDX(ki);
if (dr->dr_key_timestamp[kidx] < dr->dr_key_timestamp[kidx^1] ||
dr->dr_ecm_key_time +
((dr->dr_ecm_valid & KEY_MASK(ki)) ? 0 : 2) < dr->dr_key_start) {
sbuf_cut(&dr->dr_buf, off);
if (!td->td_ecm_reset(td)) {
Expand Down Expand Up @@ -325,7 +330,9 @@ descrambler_descramble ( service_t *t,
tvhtrace("descrambler", "stream key changed to %s for service \"%s\"",
(ki & 0x40) ? "odd" : "even",
((mpegts_service_t *)t)->s_dvb_svcname);
if (dr->dr_ecm_key_time +
kidx = KEY_IDX(ki);
if (dr->dr_key_timestamp[kidx] < dr->dr_key_timestamp[kidx^1] ||
dr->dr_ecm_key_time +
((dr->dr_ecm_valid & KEY_MASK(ki)) ? 0 : 2) < dr->dr_key_start) {
tvhtrace("descrambler", "ECM late (%ld seconds) for service \"%s\"",
dispatch_clock - dr->dr_ecm_key_time,
Expand Down
2 changes: 2 additions & 0 deletions src/epggrab.h
Expand Up @@ -203,7 +203,9 @@ struct epggrab_ota_mux
LIST_HEAD(,epggrab_ota_map) om_modules; ///< List of linked mods

int om_complete; ///< Has completed a scan
int om_save; ///< something changed
gtimer_t om_timer; ///< Per mux active timer
gtimer_t om_data_timer; ///< Any EPG data seen?

char *om_force_modname;///< Force this module

Expand Down
10 changes: 5 additions & 5 deletions src/epggrab/module/eit.c
Expand Up @@ -608,16 +608,16 @@ _eit_callback
if(!mm)
goto done;

if (map->om_first) {
map->om_tune_count++;
map->om_first = 0;
}

/* Get service */
svc = mpegts_mux_find_service(mm, sid);
if (!svc)
goto done;

if (map->om_first) {
map->om_tune_count++;
map->om_first = 0;
}

/* Register this */
if (ota)
epggrab_ota_service_add(map, ota, idnode_uuid_as_str(&svc->s_id), 1);
Expand Down
3 changes: 3 additions & 0 deletions src/epggrab/module/opentv.c
Expand Up @@ -129,6 +129,7 @@ typedef struct opentv_event
typedef struct opentv_status
{
opentv_module_t *os_mod;
epggrab_ota_map_t *os_map;
int os_refcount;
epggrab_ota_mux_t *os_ota;
} opentv_status_t;
Expand Down Expand Up @@ -453,6 +454,7 @@ opentv_table_callback
/* Complete */
done:
if (!r) {
sta->os_map->om_first = 0; /* valid data mark */
tvhtrace(mt->mt_name, "pid %d complete remain %d",
mt->mt_pid, sta->os_refcount-1);

Expand Down Expand Up @@ -564,6 +566,7 @@ static int _opentv_start
if (!sta) {
sta = calloc(1, sizeof(opentv_status_t));
sta->os_mod = mod;
sta->os_map = map;
}
mt = mpegts_table_add(mm, DVB_BAT_BASE, DVB_BAT_MASK,
opentv_bat_callback, sta,
Expand Down
116 changes: 94 additions & 22 deletions src/epggrab/otamux.c
Expand Up @@ -36,7 +36,8 @@

#define EPGGRAB_OTA_DONE_COMPLETE 0
#define EPGGRAB_OTA_DONE_TIMEOUT 1
#define EPGGRAB_OTA_DONE_STOLEN 2
#define EPGGRAB_OTA_DONE_NO_DATA 2
#define EPGGRAB_OTA_DONE_STOLEN 3

typedef TAILQ_HEAD(epggrab_ota_head,epggrab_ota_mux) epggrab_ota_head_t;

Expand All @@ -60,6 +61,7 @@ SKEL_DECLARE(epggrab_ota_mux_skel, epggrab_ota_mux_t);
SKEL_DECLARE(epggrab_svc_link_skel, epggrab_ota_svc_link_t);

static void epggrab_ota_timeout_cb ( void *p );
static void epggrab_ota_data_timeout_cb ( void *p );
static void epggrab_ota_kick_cb ( void *p );

static void epggrab_ota_save ( epggrab_ota_mux_t *ota );
Expand Down Expand Up @@ -129,17 +131,25 @@ epggrab_ota_kick ( int delay )
static void
epggrab_ota_done ( epggrab_ota_mux_t *om, int reason )
{
static const char *reasons[] = {
[EPGGRAB_OTA_DONE_COMPLETE] = "complete",
[EPGGRAB_OTA_DONE_TIMEOUT] = "timeout",
[EPGGRAB_OTA_DONE_NO_DATA] = "no data",
[EPGGRAB_OTA_DONE_STOLEN] = "stolen"
};
char name[256];
mpegts_mux_t *mm;
epggrab_ota_map_t *map;

if (om->om_save)
epggrab_ota_save(om);

mm = mpegts_mux_find(om->om_mux_uuid);
mpegts_mux_nice_name(mm, name, sizeof(name));
tvhdebug("epggrab", "grab done for %s (%s)", name,
reason == EPGGRAB_OTA_DONE_TIMEOUT ? "timeout" :
(reason == EPGGRAB_OTA_DONE_STOLEN ? "stolen" : "complete"));
tvhdebug("epggrab", "grab done for %s (%s)", name, reasons[reason]);

gtimer_disarm(&om->om_timer);
gtimer_disarm(&om->om_data_timer);

assert(om->om_q_type == EPGGRAB_OTA_MUX_ACTIVE);
TAILQ_REMOVE(&epggrab_ota_active, om, om_q_link);
Expand All @@ -161,13 +171,23 @@ epggrab_ota_done ( epggrab_ota_mux_t *om, int reason )
epggrab_ota_kick(1);
}

static void
epggrab_ota_complete_mark ( epggrab_ota_mux_t *om )
{
if (!om->om_complete) {
om->om_complete = 1;
epggrab_ota_save(om);
}
}

static void
epggrab_ota_start ( epggrab_ota_mux_t *om, mpegts_mux_t *mm )
{
epggrab_module_t *m;
epggrab_ota_map_t *map;
char *modname = om->om_force_modname;
mpegts_mux_instance_t *mmi = mm->mm_active;
int grace;

/* In pending queue? Remove.. */
if (om->om_q_type == EPGGRAB_OTA_MUX_PENDING)
Expand All @@ -177,8 +197,11 @@ epggrab_ota_start ( epggrab_ota_mux_t *om, mpegts_mux_t *mm )

TAILQ_INSERT_TAIL(&epggrab_ota_active, om, om_q_link);
om->om_q_type = EPGGRAB_OTA_MUX_ACTIVE;
grace = mpegts_input_grace(mmi->mmi_input, mm);
gtimer_arm(&om->om_timer, epggrab_ota_timeout_cb, om,
epggrab_ota_timeout_get() + mpegts_input_grace(mmi->mmi_input, mm));
epggrab_ota_timeout_get() + grace);
gtimer_arm(&om->om_data_timer, epggrab_ota_data_timeout_cb, om,
30 + grace); /* 30 seconds to receive any EPG info */
if (modname) {
LIST_FOREACH(m, &epggrab_modules, link)
if (!strcmp(m->id, modname)) {
Expand Down Expand Up @@ -299,19 +322,17 @@ epggrab_ota_complete
lock_assert(&global_lock);
tvhdebug(mod->id, "grab complete");

/* Mark */
if (!ota->om_complete) {
ota->om_complete = 1;
epggrab_ota_save(ota);
}
epggrab_ota_complete_mark(ota);

/* Test for completion */
LIST_FOREACH(map, &ota->om_modules, om_link) {
if (map->om_module == mod) {
map->om_complete = 1;
} else if (!map->om_complete) {
} else if (!map->om_complete && !map->om_first) {
done = 0;
}
tvhtrace("epggrab", "%s complete %i first %i",
map->om_module->id, map->om_complete, map->om_first);
}
if (!done) return;

Expand All @@ -338,8 +359,36 @@ epggrab_ota_timeout_cb ( void *p )
if (!om)
return;

/* Re-queue */
/* Abort */
epggrab_ota_done(om, EPGGRAB_OTA_DONE_TIMEOUT);
/* Not completed, but no further data for a long period */
/* wait for a manual mux tuning */
epggrab_ota_complete_mark(om);
}

static void
epggrab_ota_data_timeout_cb ( void *p )
{
epggrab_ota_mux_t *om = p;
epggrab_ota_map_t *map;

lock_assert(&global_lock);

if (!om)
return;

/* Test for any valid data reception */
LIST_FOREACH(map, &om->om_modules, om_link) {
if (!map->om_first)
break;
}

if (map == NULL) {
/* Abort */
epggrab_ota_done(om, EPGGRAB_OTA_DONE_NO_DATA);
/* Not completed, but no data - wait for a manual mux tuning */
epggrab_ota_complete_mark(om);
}
}

static void
Expand Down Expand Up @@ -392,8 +441,11 @@ epggrab_ota_kick_cb ( void *p )
for (i = 0, net = NULL; i < networks_count; i++) {
net = &networks[i];
if (net->net == mm->mm_network) {
if (net->failed)
if (net->failed) {
TAILQ_INSERT_TAIL(&epggrab_ota_pending, om, om_q_link);
om->om_q_type = EPGGRAB_OTA_MUX_PENDING;
goto done;
}
break;
}
}
Expand Down Expand Up @@ -456,6 +508,15 @@ epggrab_ota_kick_cb ( void *p )
goto next_one;
if (kick)
epggrab_ota_kick(64); /* a random number? */

#if ENABLE_TRACE
i = r = 0;
RB_FOREACH(om, &epggrab_ota_all, om_global_link)
i++;
TAILQ_FOREACH(om, &epggrab_ota_pending, om_q_link)
r++;
tvhtrace("epggrab", "mux stats - all %i pending %i", i, r);
#endif
}

/*
Expand Down Expand Up @@ -514,7 +575,7 @@ epggrab_ota_service_trace ( epggrab_ota_mux_t *ota,
if (mm && svc) {
mpegts_mux_nice_name(mm, buf, sizeof(buf));
tvhtrace("epggrab", "ota %s %s service %s", buf, op, svc->s_nicename);
} else
} else if (tvheadend_running)
tvhtrace("epggrab", "ota %s, problem? (%p %p)", op, mm, svc);
#endif
}
Expand All @@ -534,8 +595,8 @@ epggrab_ota_service_add ( epggrab_ota_map_t *map, epggrab_ota_mux_t *ota,
svcl = epggrab_svc_link_skel;
SKEL_USED(epggrab_svc_link_skel);
svcl->uuid = strdup(uuid);
if (save && ota->om_complete)
epggrab_ota_save(ota);
if (save)
ota->om_save = 1;
epggrab_ota_service_trace(ota, svcl, "add new");
}
}
Expand All @@ -551,7 +612,7 @@ epggrab_ota_service_del ( epggrab_ota_map_t *map, epggrab_ota_mux_t *ota,
free(svcl->uuid);
free(svcl);
if (save)
epggrab_ota_save(ota);
ota->om_save = 1;
}

/* **************************************************************************
Expand All @@ -565,16 +626,19 @@ epggrab_ota_save ( epggrab_ota_mux_t *ota )
epggrab_ota_svc_link_t *svcl;
htsmsg_t *e, *l, *l2, *c = htsmsg_create_map();

ota->om_save = 0;
htsmsg_add_u32(c, "complete", ota->om_complete);
l = htsmsg_create_list();
LIST_FOREACH(map, &ota->om_modules, om_link) {
e = htsmsg_create_map();
htsmsg_add_str(e, "id", map->om_module->id);
l2 = htsmsg_create_list();
RB_FOREACH(svcl, &map->om_svcs, link)
if (svcl->uuid)
htsmsg_add_str(l2, NULL, svcl->uuid);
htsmsg_add_msg(e, "services", l2);
if (RB_FIRST(&map->om_svcs)) {
l2 = htsmsg_create_list();
RB_FOREACH(svcl, &map->om_svcs, link)
if (svcl->uuid)
htsmsg_add_str(l2, NULL, svcl->uuid);
htsmsg_add_msg(e, "services", l2);
}
htsmsg_add_msg(l, NULL, e);
}
htsmsg_add_msg(c, "modules", l);
Expand All @@ -599,6 +663,13 @@ epggrab_ota_load_one
hts_settings_remove("epggrab/otamux/%s", uuid);
return;
}
#if ENABLE_TRACE
{
char name[256];
mpegts_mux_nice_name(mm, name, sizeof(name));
tvhtrace("epggrab", "loading config for %s", name);
}
#endif

ota = calloc(1, sizeof(epggrab_ota_mux_t));
ota->om_mux_uuid = strdup(uuid);
Expand All @@ -607,6 +678,7 @@ epggrab_ota_load_one
free(ota);
return;
}
htsmsg_get_u32(c, "complete", (uint32_t *)&ota->om_complete);

if (!(l = htsmsg_get_list(c, "modules"))) return;
HTSMSG_FOREACH(f, l) {
Expand Down

0 comments on commit 156b24a

Please sign in to comment.