]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
descrambler: add DS_FATAL state, handle better TSS_NO_DESCRAMBLER flag
authorJaroslav Kysela <perex@perex.cz>
Tue, 21 Nov 2017 07:40:18 +0000 (08:40 +0100)
committerJaroslav Kysela <perex@perex.cz>
Tue, 21 Nov 2017 07:40:18 +0000 (08:40 +0100)
src/descrambler.h
src/descrambler/capmt.c
src/descrambler/descrambler.c
src/descrambler/dvbcam.c
src/service.c
src/subscriptions.c

index 42528cb83384b0993a568f4855836a8945bc97ea..b2d06fffa7a01e917a92f4a781715a1897267443 100644 (file)
@@ -46,6 +46,7 @@ typedef enum {
     DS_READY,
     DS_RESOLVED,
     DS_FORBIDDEN,
+    DS_FATAL,
     DS_IDLE
 } th_descrambler_keystate_t;
 
@@ -92,6 +93,7 @@ typedef struct th_descrambler_runtime {
   int      dr_ca_count;
   int      dr_ca_resolved;
   int      dr_ca_failed;
+  int      dr_ca_fatal;
   uint32_t dr_external:1;
   uint32_t dr_skip:1;
   uint32_t dr_quick_ecm:1;
index 22af8bca35ba23296849bcb82bd3d8a3533e5120..f7d93b4d712bf8053d27c9f80409f4a2ffec9860 100644 (file)
@@ -193,6 +193,10 @@ typedef struct capmt_service {
   /* Elementary stream types */
   uint8_t ct_types[MAX_PIDS];
   uint8_t ct_type_sok[MAX_PIDS];
+
+  /* OK flag - seems that descrambling is going on */
+  uint8_t ct_ok_flag;
+  mtimer_t ct_ok_timer;
 } capmt_service_t;
 
 /**
@@ -840,6 +844,8 @@ capmt_service_destroy(th_descrambler_t *td)
            "%s: Removing CAPMT Server from service \"%s\" on adapter %d",
            capmt_name(capmt), s->s_dvb_svcname, ct->ct_adapter);
 
+  mtimer_disarm(&ct->ct_ok_timer);
+
   pthread_mutex_lock(&capmt->capmt_mutex);
 
   /* send stop to client */
@@ -942,10 +948,10 @@ capmt_set_filter(capmt_t *capmt, int adapter, sbuf_t *sb, int offset)
       if (cce->cce_ecmpid == pid) {
         flags = CAPMT_MSG_FAST;
         t = cce->cce_service;
-        break;
+        goto service_found;
       }
-    if (t) break;
   }
+service_found:
   if (t) {
     dmx_filter_t *pf = (dmx_filter_t *)sbuf_peek(sb, offset + 4);
     /* OK, probably ECM, but sometimes, it's shared */
@@ -958,9 +964,13 @@ capmt_set_filter(capmt_t *capmt, int adapter, sbuf_t *sb, int offset)
     if (i < DMX_FILTER_SIZE ||
         pf->mode[0] ||
         (pf->filter[0] & 0xf0) != 0x80 ||
-        (pf->mask[0] & 0xf0) != 0xf0)
+        (pf->mask[0] & 0xf0) != 0xf0) {
       t = NULL;
+      flags = 0;
+    }
   }
+  if (t)
+    ct->ct_ok_flag = 1;
 
   cf->adapter = adapter;
   filter = &cf->dmx[filter_index];
@@ -1121,6 +1131,7 @@ capmt_process_key(capmt_t *capmt, uint8_t adapter, ca_info_t *cai,
         if (pid == 0) break;
         if (pid == pids[i]) {
           if (multipid) {
+            ct->ct_ok_flag = 1;
             descrambler_keys((th_descrambler_t *)ct, type, pid, even, odd);
             continue;
           } else if (ct->ct_type_sok[j])
@@ -1131,6 +1142,7 @@ capmt_process_key(capmt_t *capmt, uint8_t adapter, ca_info_t *cai,
     continue;
 
 found:
+    ct->ct_ok_flag = 1;
     descrambler_keys((th_descrambler_t *)ct, type, pid, even, odd);
   }
   pthread_mutex_unlock(&capmt->capmt_mutex);
@@ -2127,6 +2139,15 @@ capmt_caid_change(th_descrambler_t *td)
     capmt_notify_server(capmt, ct, 1);
 }
 
+static void
+capmt_ok_timer_cb(void *aux)
+{
+  capmt_service_t *ct = aux;
+
+  if (!ct->ct_ok_flag)
+    descrambler_change_keystate((th_descrambler_t *)ct, DS_FATAL, 1);
+}
+
 static void
 capmt_send_request(capmt_service_t *ct, int lm)
 {
@@ -2290,6 +2311,8 @@ capmt_send_request(capmt_service_t *ct, int lm)
              capmt_name(capmt), t->s_dvb_svcname);
 
   capmt_queue_msg(capmt, adapter_num, sid, buf, pos, 0);
+
+  mtimer_arm_rel(&ct->ct_ok_timer, capmt_ok_timer_cb, ct, sec2mono(3)/2);
 }
 
 static void
index 3bf729809b21e671812da83dd2890d7858bdb369..ffa509be12e4d07ccc45a3c564e614e5a7b998b6 100644 (file)
@@ -542,6 +542,7 @@ static struct strtab keystatetab[] = {
   { "READY",      DS_READY },
   { "RESOLVED",   DS_RESOLVED },
   { "FORBIDDEN",  DS_FORBIDDEN },
+  { "FATAL",      DS_FATAL },
   { "IDLE",       DS_IDLE },
 };
 
@@ -556,7 +557,7 @@ descrambler_change_keystate( th_descrambler_t *td, th_descrambler_keystate_t key
 {
   service_t *t = td->td_service;
   th_descrambler_runtime_t *dr;
-  int count = 0, failed = 0, resolved = 0;
+  int count = 0, fatal = 0, failed = 0, resolved = 0;
 
   if (td->td_keystate == keystate)
     return;
@@ -576,6 +577,7 @@ descrambler_change_keystate( th_descrambler_t *td, th_descrambler_keystate_t key
   LIST_FOREACH(td, &t->s_descramblers, td_service_link) {
     count++;
     switch (td->td_keystate) {
+    case DS_FATAL:     fatal++;    break;
     case DS_FORBIDDEN: failed++;   break;
     case DS_RESOLVED : resolved++; break;
     default: break;
@@ -584,8 +586,9 @@ descrambler_change_keystate( th_descrambler_t *td, th_descrambler_keystate_t key
   dr->dr_ca_count = count;
   dr->dr_ca_resolved = resolved;
   dr->dr_ca_failed = failed;
-  tvhtrace(LS_DESCRAMBLER, "service \"%s\": %d descramblers (%d ok %d failed)",
-                           t->s_nicename, count, resolved, failed);
+  dr->dr_ca_fatal = fatal;
+  tvhtrace(LS_DESCRAMBLER, "service \"%s\": %d descramblers (%d ok %d failed %d fatal)",
+                           t->s_nicename, count, resolved, failed, fatal);
   if (lock)
     pthread_mutex_unlock(&t->s_stream_mutex);
 }
@@ -1186,8 +1189,12 @@ queue:
     descrambler_flush_table_data(t);
 end:
   debug2("%p: end, %s", dr, keystr(tsb));
-  if (dr->dr_ca_count > 0 && dr->dr_ca_count == dr->dr_ca_failed)
-    return -1;
+  if (dr->dr_ca_count > 0) {
+    if (dr->dr_ca_count == dr->dr_ca_fatal)
+      return 0;
+    if (dr->dr_ca_count == dr->dr_ca_failed)
+      return -1;
+  }
   return dr->dr_ca_count;
 }
 
index 4569d9437a6600d8d4571da23edba7f72a8b8c0a..08cfd155ee721410a71b73e0e06039861808a53e 100644 (file)
@@ -535,6 +535,7 @@ dvbcam_cat_update(caclient_t *cac, mpegts_mux_t *mux, const uint8_t *data, int l
   mpegts_apids_t pids;
   const uint8_t *data1;
   int len1;
+  uint8_t dtag;
   uint8_t dlen;
   uint16_t caid;
   uint16_t pid;
index 99a87705ae6233ad810d5ebe295b9fdc07b1aff9..f0a30a3201b73fc463efff4e9a66730390c1ae9d 100644 (file)
@@ -1840,15 +1840,15 @@ service_tss2text(int flags)
 int
 tss2errcode(int tss)
 {
+  if(tss & TSS_NO_DESCRAMBLER)
+    return SM_CODE_NO_DESCRAMBLER;
+
   if(tss & TSS_NO_ACCESS)
     return SM_CODE_NO_ACCESS;
 
   if(tss & TSS_TUNING)
     return SM_CODE_TUNING_FAILED;
 
-  if(tss & TSS_NO_DESCRAMBLER)
-    return SM_CODE_NO_DESCRAMBLER;
-
   if(tss & (TSS_GRACEPERIOD|TSS_TIMEOUT))
     return SM_CODE_NO_INPUT;
 
index 22ffd8893f3cd15f215a78748a4c9a8eca4355f1..e55f0e0e31f22a86488ae39540729dc430f4898d 100644 (file)
@@ -613,7 +613,7 @@ subscription_input(void *opaque, streaming_message_t *sm)
   }
 
   if (sm->sm_type == SMT_SERVICE_STATUS &&
-      (sm->sm_code & (TSS_TUNING|TSS_TIMEOUT|TSS_CA_CHECK))) {
+      (sm->sm_code & (TSS_TUNING|TSS_TIMEOUT|TSS_NO_DESCRAMBLER|TSS_CA_CHECK))) {
     error = tss2errcode(sm->sm_code);
     if (error != SM_CODE_OK)
       if (error != SM_CODE_NO_ACCESS ||