[PR-54] updated code from the PR to be optional.
I have decided to include this as there is some suggestion the performance will be better on ARM (non-x86) processors where we currently have no optimised code.
This commit is contained in:
parent
7c1819ba92
commit
592a38f9f2
5 changed files with 210 additions and 26 deletions
16
Makefile
16
Makefile
|
@ -166,20 +166,22 @@ SRCS-${CONFIG_V4L} += \
|
|||
src/v4l.c \
|
||||
src/webui/extjs_v4l.c \
|
||||
|
||||
# CWC
|
||||
SRCS-${CONFIG_CWC} += src/cwc.c \
|
||||
src/capmt.c \
|
||||
src/ffdecsa/ffdecsa_interface.c \
|
||||
src/ffdecsa/ffdecsa_int.c
|
||||
|
||||
# Avahi
|
||||
SRCS-$(CONFIG_AVAHI) += src/avahi.c
|
||||
|
||||
# Optimised code
|
||||
# CWC
|
||||
SRCS-${CONFIG_CWC} += src/cwc.c \
|
||||
src/capmt.c
|
||||
|
||||
# FFdecsa
|
||||
ifneq ($(CONFIG_DVBCSA),yes)
|
||||
SRCS-${CONFIG_CWC} += src/ffdecsa/ffdecsa_interface.c \
|
||||
src/ffdecsa/ffdecsa_int.c
|
||||
SRCS-${CONFIG_MMX} += src/ffdecsa/ffdecsa_mmx.c
|
||||
SRCS-${CONFIG_SSE2} += src/ffdecsa/ffdecsa_sse2.c
|
||||
${BUILDDIR}/src/ffdecsa/ffdecsa_mmx.o : CFLAGS += -mmmx
|
||||
${BUILDDIR}/src/ffdecsa/ffdecsa_sse2.o : CFLAGS += -msse2
|
||||
endif
|
||||
|
||||
# File bundles
|
||||
SRCS-${CONFIG_BUNDLE} += bundle.c
|
||||
|
|
12
configure
vendored
12
configure
vendored
|
@ -23,6 +23,7 @@ OPTIONS=(
|
|||
"avahi:auto"
|
||||
"zlib:auto"
|
||||
"bundle:no"
|
||||
"dvbcsa:no"
|
||||
)
|
||||
|
||||
#
|
||||
|
@ -116,6 +117,17 @@ if enabled linuxdvb && enabled dvbscan; then
|
|||
fi
|
||||
fi
|
||||
|
||||
#
|
||||
# libdvbcsa
|
||||
#
|
||||
if enabled cwc && enabled dvbcsa; then
|
||||
(check_cc_header "dvbcsa/dvbcsa" dvbcsa_h &&\
|
||||
check_cc_lib dvbcsa dvbcsa_l) ||\
|
||||
die "Failed to find dvbcsa support (use --disable-dvbcsa)"
|
||||
LDFLAGS="$LDFLAGS -ldvbcsa"
|
||||
fi
|
||||
|
||||
|
||||
# ###########################################################################
|
||||
# Write config
|
||||
# ###########################################################################
|
||||
|
|
81
src/capmt.c
81
src/capmt.c
|
@ -42,12 +42,17 @@
|
|||
#include "tcp.h"
|
||||
#include "psi.h"
|
||||
#include "tsdemux.h"
|
||||
#include <dvbcsa/dvbcsa.h>
|
||||
#include "capmt.h"
|
||||
#include "notify.h"
|
||||
#include "subscriptions.h"
|
||||
#include "dtable.h"
|
||||
|
||||
#if ENABLE_DVBCSA
|
||||
#include <dvbcsa/dvbcsa.h>
|
||||
#else
|
||||
#include "ffdecsa/FFdecsa.h"
|
||||
#endif
|
||||
|
||||
// ca_pmt_list_management values:
|
||||
#define CAPMT_LIST_MORE 0x00 // append a 'MORE' CAPMT object the list and start receiving the next object
|
||||
#define CAPMT_LIST_FIRST 0x01 // clear the list when a 'FIRST' CAPMT object is received, and start receiving the next object
|
||||
|
@ -156,17 +161,23 @@ typedef struct capmt_service {
|
|||
} ct_keystate;
|
||||
|
||||
/* buffers for keystructs */
|
||||
#if ENABLE_DVBCSA
|
||||
struct dvbcsa_bs_key_s *ct_key_even;
|
||||
struct dvbcsa_bs_key_s *ct_key_odd;
|
||||
#else
|
||||
void *ct_keys;
|
||||
#endif
|
||||
|
||||
/* CSA */
|
||||
int ct_cluster_size;
|
||||
uint8_t *ct_tsbcluster;
|
||||
int ct_fill;
|
||||
#if ENABLE_DVBCSA
|
||||
struct dvbcsa_bs_batch_s *ct_tsbbatch_even;
|
||||
struct dvbcsa_bs_batch_s *ct_tsbbatch_odd;
|
||||
int ct_fill;
|
||||
int ct_fill_even;
|
||||
int ct_fill_odd;
|
||||
#endif
|
||||
|
||||
/* current sequence number */
|
||||
uint16_t ct_seq;
|
||||
|
@ -364,10 +375,14 @@ capmt_service_destroy(th_descrambler_t *td)
|
|||
|
||||
LIST_REMOVE(ct, ct_link);
|
||||
|
||||
#if ENABLE_DVBCSA
|
||||
dvbcsa_bs_key_free(ct->ct_key_odd);
|
||||
dvbcsa_bs_key_free(ct->ct_key_even);
|
||||
free(ct->ct_tsbbatch_odd);
|
||||
free(ct->ct_tsbbatch_even);
|
||||
#else
|
||||
free_key_struct(ct->ct_keys);
|
||||
#endif
|
||||
free(ct->ct_tsbcluster);
|
||||
free(ct);
|
||||
}
|
||||
|
@ -506,9 +521,17 @@ handle_ca0(capmt_t* capmt) {
|
|||
continue;
|
||||
|
||||
if (memcmp(even, invalid, 8))
|
||||
#if ENABLE_DVBCSA
|
||||
dvbcsa_bs_key_set(even, ct->ct_key_even);
|
||||
#else
|
||||
set_even_control_word(ct->ct_keys, even);
|
||||
#endif
|
||||
if (memcmp(odd, invalid, 8))
|
||||
#if ENABLE_DVBCSA
|
||||
dvbcsa_bs_key_set(odd, ct->ct_key_odd);
|
||||
#else
|
||||
set_odd_control_word(ct->ct_keys, odd);
|
||||
#endif
|
||||
|
||||
if(ct->ct_keystate != CT_RESOLVED)
|
||||
tvhlog(LOG_INFO, "capmt", "Obtained key for service \"%s\"",t->s_svcname);
|
||||
|
@ -842,6 +865,7 @@ capmt_table_input(struct th_descrambler *td, struct service *t,
|
|||
/**
|
||||
*
|
||||
*/
|
||||
#if ENABLE_DVBCSA
|
||||
static int
|
||||
capmt_descramble(th_descrambler_t *td, service_t *t, struct elementary_stream *st,
|
||||
const uint8_t *tsb)
|
||||
|
@ -926,6 +950,47 @@ capmt_descramble(th_descrambler_t *td, service_t *t, struct elementary_stream *s
|
|||
ct->ct_fill = 0;
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int
|
||||
capmt_descramble(th_descrambler_t *td, service_t *t, struct elementary_stream *st,
|
||||
const uint8_t *tsb)
|
||||
{
|
||||
capmt_service_t *ct = (capmt_service_t *)td;
|
||||
int r, i;
|
||||
unsigned char *vec[3];
|
||||
uint8_t *t0;
|
||||
|
||||
if(ct->ct_keystate == CT_FORBIDDEN)
|
||||
return 1;
|
||||
|
||||
if(ct->ct_keystate != CT_RESOLVED)
|
||||
return -1;
|
||||
|
||||
memcpy(ct->ct_tsbcluster + ct->ct_fill * 188, tsb, 188);
|
||||
ct->ct_fill++;
|
||||
|
||||
if(ct->ct_fill != ct->ct_cluster_size)
|
||||
return 0;
|
||||
|
||||
ct->ct_fill = 0;
|
||||
|
||||
vec[0] = ct->ct_tsbcluster;
|
||||
vec[1] = ct->ct_tsbcluster + ct->ct_cluster_size * 188;
|
||||
vec[2] = NULL;
|
||||
|
||||
while(1) {
|
||||
t0 = vec[0];
|
||||
r = decrypt_packets(ct->ct_keys, vec);
|
||||
if(r == 0)
|
||||
break;
|
||||
for(i = 0; i < r; i++) {
|
||||
ts_recv_packet2(t, t0);
|
||||
t0 += 188;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Check if our CAID's matches, and if so, link
|
||||
|
@ -952,13 +1017,19 @@ capmt_service_start(service_t *t)
|
|||
|
||||
/* create new capmt service */
|
||||
ct = calloc(1, sizeof(capmt_service_t));
|
||||
#if ENABLE_DVBCSA
|
||||
ct->ct_cluster_size = dvbcsa_bs_batch_size();
|
||||
#else
|
||||
ct->ct_cluster_size = get_suggested_cluster_size();
|
||||
#endif
|
||||
ct->ct_tsbcluster = malloc(ct->ct_cluster_size * 188);
|
||||
ct->ct_seq = capmt->capmt_seq++;
|
||||
#if ENABLE_DVBCSA
|
||||
ct->ct_tsbbatch_even = malloc((ct->ct_cluster_size + 1) *
|
||||
sizeof(struct dvbcsa_bs_batch_s));
|
||||
ct->ct_tsbbatch_odd = malloc((ct->ct_cluster_size + 1) *
|
||||
sizeof(struct dvbcsa_bs_batch_s));
|
||||
ct->ct_seq = capmt->capmt_seq++;
|
||||
#endif
|
||||
|
||||
TAILQ_FOREACH(st, &t->s_components, es_link) {
|
||||
caid_t *c;
|
||||
|
@ -981,8 +1052,12 @@ capmt_service_start(service_t *t)
|
|||
}
|
||||
}
|
||||
|
||||
#if ENABLE_DVBCSA
|
||||
ct->ct_key_even = dvbcsa_bs_key_alloc();
|
||||
ct->ct_key_odd = dvbcsa_bs_key_alloc();
|
||||
#else
|
||||
ct->ct_keys = get_key_struct();
|
||||
#endif
|
||||
ct->ct_capmt = capmt;
|
||||
ct->ct_service = t;
|
||||
|
||||
|
|
123
src/cwc.c
123
src/cwc.c
|
@ -27,18 +27,24 @@
|
|||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <ctype.h>
|
||||
#include <openssl/des.h>
|
||||
|
||||
#include "tvheadend.h"
|
||||
#include "tcp.h"
|
||||
#include "psi.h"
|
||||
#include "tsdemux.h"
|
||||
#include <dvbcsa/dvbcsa.h>
|
||||
#include "cwc.h"
|
||||
#include "notify.h"
|
||||
#include "atomic.h"
|
||||
#include "dtable.h"
|
||||
#include "subscriptions.h"
|
||||
#include "service.h"
|
||||
#include <openssl/des.h>
|
||||
|
||||
#if ENABLE_DVBCSA
|
||||
#include <dvbcsa/dvbcsa.h>
|
||||
#else
|
||||
#include "ffdecsa/FFdecsa.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -155,9 +161,12 @@ typedef struct cwc_service {
|
|||
CS_IDLE
|
||||
} cs_keystate;
|
||||
|
||||
#if ENABLE_DVBCSA
|
||||
struct dvbcsa_bs_key_s *cs_key_even;
|
||||
struct dvbcsa_bs_key_s *cs_key_odd;
|
||||
|
||||
#else
|
||||
void *cs_keys;
|
||||
#endif
|
||||
|
||||
uint8_t cs_cw[16];
|
||||
int cs_pending_cw_update;
|
||||
|
@ -167,11 +176,13 @@ typedef struct cwc_service {
|
|||
*/
|
||||
int cs_cluster_size;
|
||||
uint8_t *cs_tsbcluster;
|
||||
int cs_fill;
|
||||
#if ENABLE_DVBCSA
|
||||
struct dvbcsa_bs_batch_s *cs_tsbbatch_even;
|
||||
struct dvbcsa_bs_batch_s *cs_tsbbatch_odd;
|
||||
int cs_fill;
|
||||
int cs_fill_even;
|
||||
int cs_fill_odd;
|
||||
#endif
|
||||
|
||||
LIST_HEAD(, ecm_pid) cs_pids;
|
||||
|
||||
|
@ -1889,13 +1900,21 @@ update_keys(cwc_service_t *ct)
|
|||
ct->cs_pending_cw_update = 0;
|
||||
for(i = 0; i < 8; i++)
|
||||
if(ct->cs_cw[i]) {
|
||||
#if ENABLE_DVBCSA
|
||||
dvbcsa_bs_key_set(ct->cs_cw, ct->cs_key_even);
|
||||
#else
|
||||
set_even_control_word(ct->cs_keys, ct->cs_cw);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
for(i = 0; i < 8; i++)
|
||||
if(ct->cs_cw[8 + i]) {
|
||||
#if ENABLE_DVBCSA
|
||||
dvbcsa_bs_key_set(ct->cs_cw + 8, ct->cs_key_odd);
|
||||
#else
|
||||
set_odd_control_word(ct->cs_keys, ct->cs_cw + 8);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1904,6 +1923,7 @@ update_keys(cwc_service_t *ct)
|
|||
/**
|
||||
*
|
||||
*/
|
||||
#if ENABLE_DVBCSA
|
||||
static int
|
||||
cwc_descramble(th_descrambler_t *td, service_t *t, struct elementary_stream *st,
|
||||
const uint8_t *tsb)
|
||||
|
@ -1997,6 +2017,66 @@ cwc_descramble(th_descrambler_t *td, service_t *t, struct elementary_stream *st,
|
|||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int
|
||||
cwc_descramble(th_descrambler_t *td, service_t *t, struct elementary_stream *st,
|
||||
const uint8_t *tsb)
|
||||
{
|
||||
cwc_service_t *ct = (cwc_service_t *)td;
|
||||
int r;
|
||||
unsigned char *vec[3];
|
||||
|
||||
if(ct->cs_keystate == CS_FORBIDDEN)
|
||||
return 1;
|
||||
|
||||
if(ct->cs_keystate != CS_RESOLVED)
|
||||
return -1;
|
||||
|
||||
if(ct->cs_fill == 0 && ct->cs_pending_cw_update)
|
||||
update_keys(ct);
|
||||
|
||||
memcpy(ct->cs_tsbcluster + ct->cs_fill * 188, tsb, 188);
|
||||
ct->cs_fill++;
|
||||
|
||||
if(ct->cs_fill != ct->cs_cluster_size)
|
||||
return 0;
|
||||
|
||||
while(1) {
|
||||
|
||||
vec[0] = ct->cs_tsbcluster;
|
||||
vec[1] = ct->cs_tsbcluster + ct->cs_fill * 188;
|
||||
vec[2] = NULL;
|
||||
|
||||
r = decrypt_packets(ct->cs_keys, vec);
|
||||
if(r > 0) {
|
||||
int i;
|
||||
const uint8_t *t0 = ct->cs_tsbcluster;
|
||||
|
||||
for(i = 0; i < r; i++) {
|
||||
ts_recv_packet2(t, t0);
|
||||
t0 += 188;
|
||||
}
|
||||
|
||||
r = ct->cs_fill - r;
|
||||
assert(r >= 0);
|
||||
|
||||
if(r > 0)
|
||||
memmove(ct->cs_tsbcluster, t0, r * 188);
|
||||
ct->cs_fill = r;
|
||||
|
||||
if(ct->cs_pending_cw_update && r > 0)
|
||||
continue;
|
||||
} else {
|
||||
ct->cs_fill = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(ct->cs_pending_cw_update)
|
||||
update_keys(ct);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* cwc_mutex is held
|
||||
|
@ -2020,10 +2100,14 @@ cwc_service_destroy(th_descrambler_t *td)
|
|||
|
||||
LIST_REMOVE(ct, cs_link);
|
||||
|
||||
#if ENABLE_DVBCSA
|
||||
dvbcsa_bs_key_free(ct->cs_key_odd);
|
||||
dvbcsa_bs_key_free(ct->cs_key_even);
|
||||
free(ct->cs_tsbbatch_odd);
|
||||
free(ct->cs_tsbbatch_even);
|
||||
#else
|
||||
free_key_struct(ct->cs_keys);
|
||||
#endif
|
||||
free(ct->cs_tsbcluster);
|
||||
free(ct);
|
||||
}
|
||||
|
@ -2067,19 +2151,26 @@ cwc_service_start(service_t *t)
|
|||
if(cwc_find_stream_by_caid(t, cwc->cwc_caid) == NULL)
|
||||
continue;
|
||||
|
||||
ct = calloc(1, sizeof(cwc_service_t));
|
||||
ct->cs_cluster_size = dvbcsa_bs_batch_size();
|
||||
ct->cs_tsbcluster = malloc(ct->cs_cluster_size * 188);
|
||||
ct = calloc(1, sizeof(cwc_service_t));
|
||||
#if ENABLE_DVBCSA
|
||||
ct->cs_cluster_size = dvbcsa_bs_batch_size();
|
||||
#else
|
||||
ct->cs_cluster_size = get_suggested_cluster_size();
|
||||
#endif
|
||||
ct->cs_tsbcluster = malloc(ct->cs_cluster_size * 188);
|
||||
#if ENABLE_DVBCSA
|
||||
ct->cs_tsbbatch_even = malloc((ct->cs_cluster_size + 1) *
|
||||
sizeof(struct dvbcsa_bs_batch_s));
|
||||
ct->cs_tsbbatch_odd = malloc((ct->cs_cluster_size + 1) *
|
||||
sizeof(struct dvbcsa_bs_batch_s));
|
||||
|
||||
ct->cs_key_even = dvbcsa_bs_key_alloc();
|
||||
ct->cs_key_odd = dvbcsa_bs_key_alloc();
|
||||
ct->cs_cwc = cwc;
|
||||
ct->cs_service = t;
|
||||
ct->cs_okchannel = -3;
|
||||
sizeof(struct dvbcsa_bs_batch_s));
|
||||
ct->cs_tsbbatch_odd = malloc((ct->cs_cluster_size + 1) *
|
||||
sizeof(struct dvbcsa_bs_batch_s));
|
||||
ct->cs_key_even = dvbcsa_bs_key_alloc();
|
||||
ct->cs_key_odd = dvbcsa_bs_key_alloc();
|
||||
#else
|
||||
ct->cs_keys = get_key_struct();
|
||||
#endif
|
||||
ct->cs_cwc = cwc;
|
||||
ct->cs_service = t;
|
||||
ct->cs_okchannel = -1;
|
||||
|
||||
td = &ct->cs_head;
|
||||
td->td_stop = cwc_service_destroy;
|
||||
|
|
|
@ -468,6 +468,10 @@ main(int argc, char **argv)
|
|||
|
||||
htsp_init();
|
||||
|
||||
#if (!ENABLE_DVBCSA)
|
||||
ffdecsa_init();
|
||||
#endif
|
||||
|
||||
if(rawts_input != NULL)
|
||||
rawts_init(rawts_input);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue