[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:
Adam Sutton 2012-11-28 11:19:44 +00:00
parent 7c1819ba92
commit 592a38f9f2
5 changed files with 210 additions and 26 deletions

View file

@ -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
View file

@ -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
# ###########################################################################

View file

@ -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
View file

@ -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;

View file

@ -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);