descrambler: use buffer to make streaming of scrambled streams faster
This commit is contained in:
parent
476d8b77b8
commit
5eb3255186
6 changed files with 79 additions and 34 deletions
|
@ -133,7 +133,8 @@ int descrambler_descramble ( struct service *t,
|
|||
struct elementary_stream *st,
|
||||
const uint8_t *tsb );
|
||||
int descrambler_open_pid ( struct mpegts_mux *mux, void *opaque, int pid,
|
||||
descrambler_section_callback_t callback );
|
||||
descrambler_section_callback_t callback,
|
||||
struct service *service );
|
||||
int descrambler_close_pid ( struct mpegts_mux *mux, void *opaque, int pid );
|
||||
void descrambler_flush_tables ( struct mpegts_mux *mux );
|
||||
void descrambler_cat_data ( struct mpegts_mux *mux, const uint8_t *data, int len );
|
||||
|
|
|
@ -72,17 +72,6 @@ typedef struct dmx_filter {
|
|||
uint8_t mode[DMX_FILTER_SIZE];
|
||||
} dmx_filter_t;
|
||||
|
||||
typedef struct dmx_sct_filter_params {
|
||||
uint16_t pid;
|
||||
dmx_filter_t filter;
|
||||
uint32_t timeout;
|
||||
uint32_t flags;
|
||||
#define DMX_CHECK_CRC 1
|
||||
#define DMX_ONESHOT 2
|
||||
#define DMX_IMMEDIATE_START 4
|
||||
#define DMX_KERNEL_CLIENT 0x8000
|
||||
} dmx_filter_params_t;
|
||||
|
||||
#define CA_SET_DESCR 0x40106f86
|
||||
#define CA_SET_DESCR_X 0x866f1040
|
||||
#define CA_SET_PID 0x40086f87
|
||||
|
@ -203,10 +192,16 @@ typedef struct capmt_service {
|
|||
/**
|
||||
**
|
||||
*/
|
||||
typedef struct capmt_dmx {
|
||||
dmx_filter_t filter;
|
||||
uint16_t pid;
|
||||
uint32_t flags;
|
||||
} capmt_dmx_t;
|
||||
|
||||
typedef struct capmt_filters {
|
||||
int max;
|
||||
int adapter;
|
||||
dmx_filter_params_t dmx[MAX_FILTER];
|
||||
capmt_dmx_t dmx[MAX_FILTER];
|
||||
} capmt_filters_t;
|
||||
|
||||
typedef struct capmt_demuxes {
|
||||
|
@ -348,7 +343,7 @@ capmt_poll_rem(capmt_t *capmt, int fd)
|
|||
}
|
||||
|
||||
static void
|
||||
capmt_pid_add(capmt_t *capmt, int adapter, int pid)
|
||||
capmt_pid_add(capmt_t *capmt, int adapter, int pid, mpegts_service_t *s)
|
||||
{
|
||||
capmt_adapter_t *ca = &capmt->capmt_adapters[adapter];
|
||||
capmt_opaque_t *o = NULL, *t;
|
||||
|
@ -367,7 +362,9 @@ capmt_pid_add(capmt_t *capmt, int adapter, int pid)
|
|||
o->adapter = adapter;
|
||||
o->pid = pid;
|
||||
mmi = LIST_FIRST(&capmt->capmt_adapters[adapter].ca_tuner->mi_mux_active);
|
||||
descrambler_open_pid(mmi->mmi_mux, o, pid, capmt_table_input);
|
||||
descrambler_open_pid(mmi->mmi_mux, o,
|
||||
s ? DESCRAMBLER_ECM_PID(pid) : pid,
|
||||
capmt_table_input, (service_t *)s);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -766,8 +763,7 @@ capmt_set_filter(capmt_t *capmt, int adapter, sbuf_t *sb, int offset)
|
|||
uint8_t demux_index = sbuf_peek_u8 (sb, offset + 4);
|
||||
uint8_t filter_index = sbuf_peek_u8 (sb, offset + 5);
|
||||
uint16_t pid = sbuf_peek_u16(sb, offset + 6);
|
||||
dmx_filter_params_t *filter;
|
||||
dmx_filter_params_t *params = (dmx_filter_params_t *)sbuf_peek(sb, offset + 6);
|
||||
capmt_dmx_t *filter;
|
||||
capmt_filters_t *cf;
|
||||
capmt_service_t *ct;
|
||||
mpegts_service_t *t;
|
||||
|
@ -788,11 +784,10 @@ capmt_set_filter(capmt_t *capmt, int adapter, sbuf_t *sb, int offset)
|
|||
cf->adapter = adapter;
|
||||
filter = &cf->dmx[filter_index];
|
||||
filter->pid = pid;
|
||||
capmt_pid_add(capmt, adapter, pid);
|
||||
memcpy(&filter->filter, ¶ms->filter, sizeof(params->filter));
|
||||
filter->timeout = 0;
|
||||
memcpy(&filter->filter, sbuf_peek(sb, offset + 10), sizeof(filter->filter));
|
||||
filter->flags = 0;
|
||||
/* ECM messages have the higher priority */
|
||||
t = NULL;
|
||||
LIST_FOREACH(ct, &capmt->capmt_services, ct_link) {
|
||||
t = (mpegts_service_t *)ct->td_service;
|
||||
pthread_mutex_lock(&t->s_stream_mutex);
|
||||
|
@ -808,6 +803,7 @@ capmt_set_filter(capmt_t *capmt, int adapter, sbuf_t *sb, int offset)
|
|||
pthread_mutex_unlock(&t->s_stream_mutex);
|
||||
if (st) break;
|
||||
}
|
||||
capmt_pid_add(capmt, adapter, pid, t);
|
||||
/* Update the max values */
|
||||
if (capmt->capmt_demuxes.max <= demux_index)
|
||||
capmt->capmt_demuxes.max = demux_index + 1;
|
||||
|
@ -827,7 +823,7 @@ capmt_stop_filter(capmt_t *capmt, int adapter, sbuf_t *sb, int offset)
|
|||
uint8_t demux_index = sbuf_peek_u8 (sb, offset + 4);
|
||||
uint8_t filter_index = sbuf_peek_u8 (sb, offset + 5);
|
||||
int16_t pid = sbuf_peek_s16le(sb, offset + 6);
|
||||
dmx_filter_params_t *filter;
|
||||
capmt_dmx_t *filter;
|
||||
capmt_filters_t *cf;
|
||||
|
||||
tvhtrace("capmt", "stopping filter: adapter=%d, demux=%d, filter=%d, pid=%d",
|
||||
|
@ -950,7 +946,7 @@ capmt_msg_size(capmt_t *capmt, sbuf_t *sb, int offset)
|
|||
else if (cmd == CA_SET_DESCR)
|
||||
return 4 + 16;
|
||||
else if (oscam_new && cmd == DMX_SET_FILTER)
|
||||
return 4 + 2 + sizeof(dmx_filter_params_t);
|
||||
return 4 + 2 + 60;
|
||||
else if (oscam_new && cmd == DMX_STOP)
|
||||
return 4 + 4;
|
||||
else {
|
||||
|
@ -1320,6 +1316,8 @@ capmt_thread(void *aux)
|
|||
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
|
||||
if (!capmt->capmt_running) continue;
|
||||
|
||||
/* open connection to camd.socket */
|
||||
capmt_connect(capmt, 0);
|
||||
|
||||
|
@ -1379,8 +1377,7 @@ capmt_thread(void *aux)
|
|||
if (capmt->capmt_adapters[i].ca_sock >= 0)
|
||||
close(capmt->capmt_adapters[i].ca_sock);
|
||||
|
||||
if (!capmt->capmt_running)
|
||||
break;
|
||||
if (!capmt->capmt_running) continue;
|
||||
|
||||
/* schedule reconnection */
|
||||
if(subscriptions_active() && !fatal) {
|
||||
|
|
|
@ -1983,7 +1983,7 @@ cwc_service_start(service_t *t)
|
|||
|
||||
descrambler_open_pid(ct->cs_mux, ct,
|
||||
DESCRAMBLER_ECM_PID(ct->cs_estream->es_pid),
|
||||
cwc_table_input);
|
||||
cwc_table_input, t);
|
||||
|
||||
tvhlog(LOG_DEBUG, "cwc", "%s using CWC %s:%d",
|
||||
service_nicename(t), cwc->cwc_hostname, cwc->cwc_port);
|
||||
|
|
|
@ -132,12 +132,15 @@ descrambler_done ( void )
|
|||
void
|
||||
descrambler_service_start ( service_t *t )
|
||||
{
|
||||
t->s_descramble_key = 0;
|
||||
#if ENABLE_CWC
|
||||
cwc_service_start(t);
|
||||
#endif
|
||||
#if ENABLE_CAPMT
|
||||
capmt_service_start(t);
|
||||
#endif
|
||||
t->s_descramble_buf = calloc(1, sizeof(sbuf_t));
|
||||
sbuf_init(t->s_descramble_buf);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -147,6 +150,10 @@ descrambler_service_stop ( service_t *t )
|
|||
|
||||
while ((td = LIST_FIRST(&t->s_descramblers)) != NULL)
|
||||
td->td_stop(td);
|
||||
if (t->s_descramble_buf) {
|
||||
sbuf_free(t->s_descramble_buf);
|
||||
t->s_descramble_buf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -189,8 +196,9 @@ descrambler_descramble ( service_t *t,
|
|||
const uint8_t *tsb )
|
||||
{
|
||||
th_descrambler_t *td;
|
||||
int count, failed;
|
||||
int count, failed, off, size;
|
||||
|
||||
count = failed = 0;
|
||||
LIST_FOREACH(td, &t->s_descramblers, td_service_link) {
|
||||
count++;
|
||||
if (td->td_keystate == DS_FORBIDDEN) {
|
||||
|
@ -199,12 +207,37 @@ descrambler_descramble ( service_t *t,
|
|||
}
|
||||
if (td->td_keystate != DS_RESOLVED)
|
||||
continue;
|
||||
if (t->s_descramble_buf) {
|
||||
for (off = 0, size = t->s_descramble_buf->sb_ptr; off < size; off += 188)
|
||||
tvhcsa_descramble(td->td_csa,
|
||||
(mpegts_service_t *)td->td_service,
|
||||
st, t->s_descramble_buf->sb_data + off);
|
||||
sbuf_free(t->s_descramble_buf);
|
||||
free(t->s_descramble_buf);
|
||||
t->s_descramble_buf = NULL;
|
||||
}
|
||||
tvhcsa_descramble(td->td_csa,
|
||||
(struct mpegts_service *)td->td_service,
|
||||
(mpegts_service_t *)td->td_service,
|
||||
st, tsb);
|
||||
return 1;
|
||||
}
|
||||
return count == failed ? -1 : 0;
|
||||
if (t->s_descramble_key && count != failed) {
|
||||
/*
|
||||
* Fill a temporary buffer until the keys are known to make
|
||||
* streaming faster.
|
||||
*/
|
||||
if (t->s_descramble_buf == NULL) {
|
||||
t->s_descramble_buf = calloc(1, sizeof(sbuf_t));
|
||||
if (t->s_descramble_buf)
|
||||
sbuf_init(t->s_descramble_buf);
|
||||
}
|
||||
if (t->s_descramble_buf) {
|
||||
if (t->s_descramble_buf->sb_ptr >= 3000 * 188)
|
||||
sbuf_cut(t->s_descramble_buf, 300 * 188);
|
||||
sbuf_append(t->s_descramble_buf, tsb, 188);
|
||||
}
|
||||
}
|
||||
return count && count == failed ? -1 : count;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -227,6 +260,12 @@ descrambler_table_callback
|
|||
ds->last_data_len = 0;
|
||||
}
|
||||
ds->callback(ds->opaque, mt->mt_pid, ptr, len);
|
||||
if ((mt->mt_flags & MT_FAST) != 0) { /* ECM */
|
||||
if (mt->mt_service) {
|
||||
/* The keys are requested from this moment */
|
||||
mt->mt_service->s_descramble_key |= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&mt->mt_mux->mm_descrambler_lock);
|
||||
return 0;
|
||||
|
@ -234,7 +273,8 @@ descrambler_table_callback
|
|||
|
||||
static int
|
||||
descrambler_open_pid_( mpegts_mux_t *mux, void *opaque, int pid,
|
||||
descrambler_section_callback_t callback )
|
||||
descrambler_section_callback_t callback,
|
||||
service_t *service )
|
||||
{
|
||||
descrambler_table_t *dt;
|
||||
descrambler_section_t *ds;
|
||||
|
@ -257,6 +297,8 @@ descrambler_open_pid_( mpegts_mux_t *mux, void *opaque, int pid,
|
|||
TAILQ_INIT(&dt->sections);
|
||||
dt->table = mpegts_table_add(mux, 0, 0, descrambler_table_callback,
|
||||
dt, "descrambler", MT_FULL | flags, pid);
|
||||
if (dt->table)
|
||||
dt->table->mt_service = (mpegts_service_t *)service;
|
||||
TAILQ_INSERT_TAIL(&mux->mm_descrambler_tables, dt, link);
|
||||
}
|
||||
ds = calloc(1, sizeof(*ds));
|
||||
|
@ -269,12 +311,13 @@ descrambler_open_pid_( mpegts_mux_t *mux, void *opaque, int pid,
|
|||
|
||||
int
|
||||
descrambler_open_pid( mpegts_mux_t *mux, void *opaque, int pid,
|
||||
descrambler_section_callback_t callback )
|
||||
descrambler_section_callback_t callback,
|
||||
service_t *service )
|
||||
{
|
||||
int res;
|
||||
|
||||
pthread_mutex_lock(&mux->mm_descrambler_lock);
|
||||
res = descrambler_open_pid_(mux, opaque, pid, callback);
|
||||
res = descrambler_open_pid_(mux, opaque, pid, callback, service);
|
||||
pthread_mutex_unlock(&mux->mm_descrambler_lock);
|
||||
return res;
|
||||
}
|
||||
|
@ -391,7 +434,7 @@ descrambler_cat_data( mpegts_mux_t *mux, const uint8_t *data, int len )
|
|||
}
|
||||
}
|
||||
if (emm)
|
||||
descrambler_open_pid_(mux, opaque, pid, callback);
|
||||
descrambler_open_pid_(mux, opaque, pid, callback, NULL);
|
||||
pthread_mutex_unlock(&mux->mm_descrambler_lock);
|
||||
next:
|
||||
data += dlen;
|
||||
|
@ -456,7 +499,7 @@ descrambler_open_emm( mpegts_mux_t *mux, void *opaque, int caid,
|
|||
tvhtrace("descrambler",
|
||||
"attach emm caid %04X (%i) pid %04X (%i) - direct",
|
||||
caid, caid, pid, pid);
|
||||
descrambler_open_pid_(mux, opaque, pid, callback);
|
||||
descrambler_open_pid_(mux, opaque, pid, callback, NULL);
|
||||
}
|
||||
pthread_mutex_unlock(&mux->mm_descrambler_lock);
|
||||
return 1;
|
||||
|
|
|
@ -194,6 +194,8 @@ struct mpegts_table
|
|||
mpegts_psi_section_t mt_sect;
|
||||
|
||||
struct mpegts_table_mux_cb *mt_mux_cb;
|
||||
|
||||
mpegts_service_t *mt_service;
|
||||
|
||||
void (*mt_destroy) (mpegts_table_t *mt); // Allow customisable destroy hook
|
||||
// useful for dynamic allocation of
|
||||
|
|
|
@ -400,7 +400,9 @@ typedef struct service {
|
|||
*/
|
||||
|
||||
struct th_descrambler_list s_descramblers;
|
||||
int s_scrambled_seen;
|
||||
uint16_t s_scrambled_seen;
|
||||
uint16_t s_descramble_key;
|
||||
sbuf_t *s_descramble_buf;
|
||||
|
||||
/**
|
||||
* List of all and filtered components.
|
||||
|
|
Loading…
Add table
Reference in a new issue