]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
Fix dvr input if sync is lost, also minor efficiency improvement.
authorAdam Sutton <dev@adamsutton.me.uk>
Fri, 31 Aug 2012 22:12:07 +0000 (23:12 +0100)
committerAdam Sutton <dev@adamsutton.me.uk>
Sun, 2 Sep 2012 19:25:06 +0000 (20:25 +0100)
src/dvb/dvb_adapter.c
src/tsdemux.c
src/tsdemux.h

index 9e714e93acf49a3bd6744125b8bdc6a4989444ac..5557a4fe1310afe5ab68742c5cbe50ca0b8d2b4e 100644 (file)
@@ -701,7 +701,7 @@ static void *
 dvb_adapter_input_dvr(void *aux)
 {
   th_dvb_adapter_t *tda = aux;
-  int fd, i, r, efd, nfds;
+  int fd, i, r, c, efd, nfds;
   uint8_t tsb[188 * 10];
   service_t *t;
   struct epoll_event ev;
@@ -720,34 +720,68 @@ dvb_adapter_input_dvr(void *aux)
   ev.data.fd = tda->tda_dvr_pipe[0];
   epoll_ctl(efd, EPOLL_CTL_ADD, tda->tda_dvr_pipe[0], &ev);
 
-  while(1){
+  r = i = 0;
+  while(1) {
 
     /* Wait for input */
     nfds = epoll_wait(efd, &ev, 1, -1);
     if (nfds < 1) continue;
     if (ev.data.fd != fd) break;
 
-    r = read(fd, tsb, sizeof(tsb));
+    c = read(fd, tsb+r, sizeof(tsb)-r);
+    if (c < 0) {
+      if (errno == EAGAIN || errno == EINTR)
+        continue;
+      else
+        break;
+    }
+    r += c;
+
+    /* not enough data */
+    if (r < 188) continue;
 
     pthread_mutex_lock(&tda->tda_delivery_mutex);
-    
-    for(i = 0; i < r; i += 188) {
-      LIST_FOREACH(t, &tda->tda_transports, s_active_link)
-        if(t->s_dvb_mux_instance == tda->tda_mux_current)
-          ts_recv_packet1(t, tsb + i, NULL);
-    }
 
+    /* debug */
     if(tda->tda_dump_fd != -1) {
       if(write(tda->tda_dump_fd, tsb, r) != r) {
         tvhlog(LOG_ERR, "dvb",
-              "\"%s\" unable to write to mux dump file -- %s",
-              tda->tda_identifier, strerror(errno));
-             close(tda->tda_dump_fd);
-             tda->tda_dump_fd = -1;
+               "\"%s\" unable to write to mux dump file -- %s",
+               tda->tda_identifier, strerror(errno));
+        close(tda->tda_dump_fd);
+        tda->tda_dump_fd = -1;
+      }
+    }
+
+    /* find mux */
+    LIST_FOREACH(t, &tda->tda_transports, s_active_link)
+      if(t->s_dvb_mux_instance == tda->tda_mux_current)
+        break;
+
+    /* Process */
+    while (r >= 188) {
+  
+      /* sync */
+      if (tsb[i] == 0x47) {
+        if(t) ts_recv_packet1(t, tsb + i, NULL);
+        i += 188;
+        r -= 188;
+
+      /* no sync */
+      } else {
+        tvhlog(LOG_DEBUG, "dvb", "\"%s\" ts sync lost", tda->tda_identifier);
+        if (ts_resync(tsb, &r, &i)) break;
+        tvhlog(LOG_DEBUG, "dvb", "\"%s\" ts sync found", tda->tda_identifier);
       }
     }
 
     pthread_mutex_unlock(&tda->tda_delivery_mutex);
+
+    /* reset buffer */
+    if (r && r < i) {
+      memcpy(tsb, tsb+i, r);
+      i = 0;
+    }
   }
 
   close(efd);
index afd0eded763e7c903c8d83350275dac9a219de54..89e016a5d369a79ff4af06ac2e2fb487abb5e949 100644 (file)
@@ -286,3 +286,18 @@ ts_remux(service_t *t, const uint8_t *src)
   sm.sm_data = tsb;
   streaming_pad_deliver(&t->s_streaming_pad, &sm);
 }
+
+/*
+ * Attempt to re-sync a ts stream (3 valid sync's in a row)
+ */
+int
+ts_resync ( const uint8_t *tsb, int *len, int *idx )
+{
+  int err = 1;
+  while (err && (*len > 376)) {
+    (*idx)++; (*len)--;
+    err = (tsb[*idx] != 0x47) || (tsb[*idx+188] != 0x47) || 
+          (tsb[*idx+376] != 0x47);
+  }
+  return err;
+}
index 77f1b4ddb5c549d181fa3f6121e6924a359dedcd..61e088fe4ab2c30a5ab6cd1da8cfa80dc88da903 100644 (file)
@@ -19,6 +19,8 @@
 #ifndef TSDEMUX_H
 #define TSDEMUX_H
 
+int ts_resync ( const uint8_t *tsb, int *len, int *idx );
+
 void ts_recv_packet1(struct service *t, const uint8_t *tsb, int64_t *pcrp);
 
 void ts_recv_packet2(struct service *t, const uint8_t *tsb);