]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
[PR-54] updated code from the PR to be optional.
authorAdam Sutton <dev@adamsutton.me.uk>
Wed, 28 Nov 2012 11:19:44 +0000 (11:19 +0000)
committerAdam Sutton <dev@adamsutton.me.uk>
Wed, 28 Nov 2012 11:32:15 +0000 (11:32 +0000)
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.

Makefile
configure
src/capmt.c
src/cwc.c
src/main.c

index 3da265560c0f9e6120f18da16f83fbbc8555e87f..8c6b29364cefe58f9180d3f10c9f4a936ec4a949 100644 (file)
--- a/Makefile
+++ b/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
index cd493750ee8174599d72e7fad726183a5a1d9cd6..8e02c1b438dc4311c8e1ccc03dbc231f20899fa6 100755 (executable)
--- a/configure
+++ b/configure
@@ -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
 # ###########################################################################
index 0f779ed0e8b525894c0a148ad0f69e1125b59180..f10778b35268085ff7818bfac16d3ac8e521feb0 100644 (file)
 #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;
 
index 242478ca8460a990dbe28c212fb5d374645cc2f6..b90cc8fe4663c4378edfae8e3a0ed4356809e150 100644 (file)
--- a/src/cwc.c
+++ b/src/cwc.c
 #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;
index 7ee0e70fa623efbfdd8b01b62e50e2664c4d5ab3..acc757d8bb65053e7117c89fc2a2451c88628e7b 100644 (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);