]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
descrambler: reset ecm states for all readers when key is late
authorJaroslav Kysela <perex@perex.cz>
Sun, 1 Feb 2015 10:52:37 +0000 (11:52 +0100)
committerJaroslav Kysela <perex@perex.cz>
Sun, 1 Feb 2015 11:03:19 +0000 (12:03 +0100)
src/descrambler/descrambler.c

index e65848acd33a205496ae714e765d0cb2ffb4e55b..6a2395ae2c211fea4439f687356067e8378b7cda 100755 (executable)
@@ -347,6 +347,22 @@ key_late( th_descrambler_runtime_t *dr, uint8_t ki )
   return dr->dr_ecm_key_time + 2 < dr->dr_key_start;
 }
 
+static int
+ecm_reset( service_t *t, th_descrambler_runtime_t *dr )
+{
+  th_descrambler_t *td;
+  int ret = 0;
+
+  /* reset the reader ECM state */
+  LIST_FOREACH(td, &t->s_descramblers, td_service_link) {
+    if (!td->td_ecm_reset(td)) {
+      dr->dr_key_valid = 0;
+      ret = 1;
+    }
+  }
+  return ret;
+}
+
 int
 descrambler_descramble ( service_t *t,
                          elementary_stream_t *st,
@@ -354,7 +370,7 @@ descrambler_descramble ( service_t *t,
 {
   th_descrambler_t *td;
   th_descrambler_runtime_t *dr = t->s_descramble;
-  int count, failed, off, size, flush_data = 0;
+  int count, failed, resolved, off, size, flush_data = 0;
   uint8_t *tsb2, ki;
 
   lock_assert(&t->s_stream_mutex);
@@ -362,18 +378,21 @@ descrambler_descramble ( service_t *t,
   if (dr == NULL)
     return -1;
 
-  count = failed = 0;
+  count = failed = resolved = 0;
   LIST_FOREACH(td, &t->s_descramblers, td_service_link) {
     count++;
-    if (td->td_keystate == DS_FORBIDDEN) {
-      failed++;
-      continue;
+    switch (td->td_keystate) {
+    case DS_FORBIDDEN: failed++;   break;
+    case DS_RESOLVED : resolved++; break;
+    default: break;
     }
-    if (td->td_keystate != DS_RESOLVED)
-      continue;
+  }
+
+  if (resolved) {
 
+    /* update the keys */
     if (dr->dr_key_changed) {
-      dr->dr_csa.csa_flush(&dr->dr_csa, (mpegts_service_t *)td->td_service);
+      dr->dr_csa.csa_flush(&dr->dr_csa, (mpegts_service_t *)t);
       if (dr->dr_key_changed & 1)
         tvhcsa_set_key_even(&dr->dr_csa, dr->dr_key_even);
       if (dr->dr_key_changed & 2)
@@ -381,6 +400,7 @@ descrambler_descramble ( service_t *t,
       dr->dr_key_changed = 0;
     }
 
+    /* process the queued TS packets */
     if (dr->dr_buf.sb_ptr > 0) {
       for (off = 0, size = dr->dr_buf.sb_ptr; off < size; off += 188) {
         tsb2 = dr->dr_buf.sb_data + off;
@@ -388,7 +408,8 @@ descrambler_descramble ( service_t *t,
         if ((ki & 0x80) != 0x00) {
           if (key_valid(dr, ki) == 0) {
             sbuf_cut(&dr->dr_buf, off);
-            goto next2;
+            flush_data = 1;
+            goto next;
           }
           if (dr->dr_key_index != (ki & 0x40) &&
               dr->dr_key_start + 2 < dispatch_clock) {
@@ -397,23 +418,22 @@ descrambler_descramble ( service_t *t,
                                     ((mpegts_service_t *)t)->s_dvb_svcname);
             if (key_late(dr, ki)) {
               sbuf_cut(&dr->dr_buf, off);
-              if (!td->td_ecm_reset(td)) {
-                dr->dr_key_valid = 0;
+              if (ecm_reset(t, dr)) {
+                flush_data = 1;
                 goto next;
               }
             }
             key_update(dr, ki);
           }
         }
-        dr->dr_csa.csa_descramble(&dr->dr_csa,
-                                  (mpegts_service_t *)td->td_service,
-                                  tsb2);
+        dr->dr_csa.csa_descramble(&dr->dr_csa, (mpegts_service_t *)t, tsb2);
       }
       if (off > 0)
         service_reset_streaming_status_flags(t, TSS_NO_ACCESS);
       sbuf_free(&dr->dr_buf);
     }
 
+    /* check for key change */
     ki = tsb[3];
     if ((ki & 0x80) != 0x00) {
       if (key_valid(dr, ki) == 0) {
@@ -422,7 +442,7 @@ descrambler_descramble ( service_t *t,
                    ((mpegts_service_t *)t)->s_dvb_svcname,
                    (ki & 0x40) ? "odd stream key is not valid" :
                                  "even stream key is not valid");
-        continue;
+        goto next;
       }
       if (dr->dr_key_index != (ki & 0x40) &&
           dr->dr_key_start + 2 < dispatch_clock) {
@@ -433,24 +453,19 @@ descrambler_descramble ( service_t *t,
           tvhtrace("descrambler", "ECM late (%ld seconds) for service \"%s\"",
                                   dispatch_clock - dr->dr_ecm_key_time,
                                   ((mpegts_service_t *)t)->s_dvb_svcname);
-          if (!td->td_ecm_reset(td)) {
-            dr->dr_key_valid = 0;
+          if (ecm_reset(t, dr)) {
+            flush_data = 1;
             goto next;
           }
         }
         key_update(dr, ki);
       }
     }
-    dr->dr_csa.csa_descramble(&dr->dr_csa,
-                              (mpegts_service_t *)td->td_service,
-                              tsb);
+    dr->dr_csa.csa_descramble(&dr->dr_csa, (mpegts_service_t *)t, tsb);
     service_reset_streaming_status_flags(t, TSS_NO_ACCESS);
     return 1;
-next:
-    flush_data = 1;
-next2:
-    continue;
   }
+next:
   if (dr->dr_ecm_start) { /* ECM sent */
     ki = tsb[3];
     if ((ki & 0x80) != 0x00) {