From 5eb32551863523b8fd5c60078cf84ef6901841ec Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 9 Jun 2014 15:26:55 +0200 Subject: [PATCH] descrambler: use buffer to make streaming of scrambled streams faster --- src/descrambler.h | 3 +- src/descrambler/capmt.c | 43 ++++++++++++------------- src/descrambler/cwc.c | 2 +- src/descrambler/descrambler.c | 59 ++++++++++++++++++++++++++++++----- src/input/mpegts.h | 2 ++ src/service.h | 4 ++- 6 files changed, 79 insertions(+), 34 deletions(-) diff --git a/src/descrambler.h b/src/descrambler.h index ccc855e8..587b1853 100755 --- a/src/descrambler.h +++ b/src/descrambler.h @@ -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 ); diff --git a/src/descrambler/capmt.c b/src/descrambler/capmt.c index c028f43c..34437ea3 100644 --- a/src/descrambler/capmt.c +++ b/src/descrambler/capmt.c @@ -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) { diff --git a/src/descrambler/cwc.c b/src/descrambler/cwc.c index 892ca820..9506c877 100755 --- a/src/descrambler/cwc.c +++ b/src/descrambler/cwc.c @@ -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); diff --git a/src/descrambler/descrambler.c b/src/descrambler/descrambler.c index 6ebf975e..08da260e 100755 --- a/src/descrambler/descrambler.c +++ b/src/descrambler/descrambler.c @@ -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; diff --git a/src/input/mpegts.h b/src/input/mpegts.h index ac0d107e..35d00ec2 100644 --- a/src/input/mpegts.h +++ b/src/input/mpegts.h @@ -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 diff --git a/src/service.h b/src/service.h index 10fb445a..1a322b3e 100644 --- a/src/service.h +++ b/src/service.h @@ -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.