]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
reorder the ts demuxer code slightly to prepare for PCR extraction
authorAndreas Öman <andreas@lonelycoder.com>
Sun, 10 Feb 2008 07:55:41 +0000 (07:55 +0000)
committerAndreas Öman <andreas@lonelycoder.com>
Sun, 10 Feb 2008 07:55:41 +0000 (07:55 +0000)
cwc.c
dvb_dvr.c
iptv_input.c
tsdemux.c
tsdemux.h

diff --git a/cwc.c b/cwc.c
index f537f5375bc6d82c5374bc296f87b0c8300fc460..8a30ace2602148496a2a0ce442c915f2049c84e8 100644 (file)
--- a/cwc.c
+++ b/cwc.c
@@ -716,7 +716,7 @@ cwc_descramble(th_descrambler_t *td, th_transport_t *t, struct th_stream *st,
     if(r == 0)
       break;
     for(i = 0; i < r; i++) {
-      ts_recv_packet(t, (t0[1] & 0x1f) << 8 | t0[2], t0, 0);
+      ts_recv_packet2(t, t0);
       t0 += 188;
     }
   }
index 2d4f3936aed14bd201a6446ce50f43f9bedf62d4..f36aceeb02a5d588bbd4016f05ccdc3af4118632 100644 (file)
--- a/dvb_dvr.c
+++ b/dvb_dvr.c
@@ -68,13 +68,11 @@ dvb_dvr_init(th_dvb_adapter_t *tda)
 static void
 dvb_dvr_process_packets(th_dvb_adapter_t *tda, uint8_t *tsb, int r)
 {
-  int pid;
   th_transport_t *t;
 
   while(r >= 188) {
-    pid = (tsb[1] & 0x1f) << 8 | tsb[2];
     LIST_FOREACH(t, &tda->tda_transports, tht_adapter_link)
-      ts_recv_packet(t, pid, tsb, 1);
+      ts_recv_packet1(t, tsb);
     r -= 188;
     tsb += 188;
   }
index c0711f1b07dbd284e24e0575868fa8a4c42589ac..eadf37412a8a76edd03b29a972075dd598c6e499 100644 (file)
@@ -55,14 +55,13 @@ iptv_fd_callback(int events, void *opaque, int fd)
 {
   th_transport_t *t = opaque;
   uint8_t buf[2000];
-  int r, pid;
+  int r;
   uint8_t *tsb = buf;
 
   r = read(fd, buf, sizeof(buf));
 
   while(r >= 188) {
-    pid = (tsb[1] & 0x1f) << 8 | tsb[2];
-    ts_recv_packet(t, pid, tsb, 1);
+    ts_recv_packet1(t, tsb);
     r -= 188;
     tsb += 188;
   }
index 5a4f04fc15dedd1023362ffe8784eefcb1138648..1ed4405800a159534039abaa7125bdcd861dd849 100644 (file)
--- a/tsdemux.c
+++ b/tsdemux.c
@@ -70,42 +70,22 @@ got_section(th_transport_t *t, th_stream_t *st)
 
 
 
-/*
- * Process transport stream packets
+/**
+ * Continue processing of transport stream packets
  */
-void
-ts_recv_packet(th_transport_t *t, int pid, uint8_t *tsb, int dodescramble)
+static void
+ts_recv_packet0(th_transport_t *t, th_stream_t *st, uint8_t *tsb)
 {
-  th_stream_t *st = NULL;
   th_subscription_t *s;
-  int cc, err = 0, afc, afl = 0;
-  int len, pusi;
-  th_descrambler_t *td;
-
-  LIST_FOREACH(st, &t->tht_streams, st_link) 
-    if(st->st_pid == pid)
-      break;
-
-  if(st == NULL)
-    return;
-
-  if(((tsb[3] >> 6) & 3) && dodescramble)
-    LIST_FOREACH(td, &t->tht_descramblers, td_transport_link)
-      if(td->td_descramble(td, t, st, tsb))
-       return;
-    
-  avgstat_add(&t->tht_rate, 188, dispatch_clock);
-  if((tsb[3] >> 6) & 3)
-    return; /* channel is encrypted */
-
+  int off, len, pusi, cc, err = 0;
 
   LIST_FOREACH(s, &t->tht_subscriptions, ths_transport_link)
     if(s->ths_raw_input != NULL)
       s->ths_raw_input(s, tsb, 188, st, s->ths_opaque);
 
-  afc = (tsb[3] >> 4) & 3;
+  /* Check CC */
 
-  if(afc & 1) {
+  if(tsb[3] & 0x10) {
     cc = tsb[3] & 0xf;
     if(st->st_cc_valid && cc != st->st_cc) {
       /* Incorrect CC */
@@ -117,38 +97,33 @@ ts_recv_packet(th_transport_t *t, int pid, uint8_t *tsb, int dodescramble)
     st->st_cc = (cc + 1) & 0xf;
   }
 
-
-  if(afc & 2)
-    afl = tsb[4] + 1;
-  
+  off = tsb[3] & 0x20 ? tsb[4] + 5 : 4;
   pusi = tsb[1] & 0x40;
 
-  afl += 4;
-
   switch(st->st_type) {
 
   case HTSTV_TABLE:
     if(st->st_section == NULL)
       st->st_section = calloc(1, sizeof(struct psi_section));
 
-    if(err || afl >= 188) {
+    if(err || off >= 188) {
       st->st_section->ps_offset = -1; /* hold parser until next pusi */
       break;
     }
 
     if(pusi) {
-      len = tsb[afl++];
+      len = tsb[off++];
       if(len > 0) {
-       if(len > 188 - afl)
+       if(len > 188 - off)
          break;
-       if(!psi_section_reassemble(st->st_section, tsb + afl, len, 0,
+       if(!psi_section_reassemble(st->st_section, tsb + off, len, 0,
                                   st->st_section_docrc))
          got_section(t, st);
-       afl += len;
+       off += len;
       }
     }
     
-    if(!psi_section_reassemble(st->st_section, tsb + afl, 188 - afl, pusi,
+    if(!psi_section_reassemble(st->st_section, tsb + off, 188 - off, pusi,
                               st->st_section_docrc))
       got_section(t, st);
     break;
@@ -158,10 +133,110 @@ ts_recv_packet(th_transport_t *t, int pid, uint8_t *tsb, int dodescramble)
     break;
 
   default:
-    if(afl > 188)
+    if(off > 188)
       break;
 
-    parse_raw_mpeg(t, st, tsb + afl, 188 - afl, pusi, err);
+    parse_raw_mpeg(t, st, tsb + off, 188 - off, pusi, err);
     break;
   }
 }
+
+
+/**
+ * Process transport stream packets, extract PCR and optionally descramble
+ */
+static void
+ts_extract_pcr(th_transport_t *t, th_stream_t *st, uint8_t *tsb)
+{
+  int64_t real = getclock_hires();
+  int64_t pcr;
+
+  pcr  = tsb[6] << 25;
+  pcr |= tsb[7] << 17;
+  pcr |= tsb[8] << 9;
+  pcr |= tsb[9] << 1;
+  pcr |= (tsb[10] >> 7) & 0x01;
+
+  pcr = av_rescale_q(pcr, st->st_tb, AV_TIME_BASE_Q);
+
+
+  {
+    static int64_t pcr0;
+    static int64_t real0, dv;
+
+    int64_t pcr_d, real_d, dx;
+
+    pcr_d = pcr - pcr0;
+    real_d = real - real0;
+
+    dx = pcr_d - real_d;
+
+    if(real0 && dx > -1000000LL && dx < 1000000LL)
+      dv += dx;
+#if 0
+    printf("B: realtime = %-12lld pcr = %-12lld delta = %lld\n",
+          real_d, pcr_d, dv / 1000);
+#endif
+    pcr0 = pcr;
+    real0 = real;
+  }
+}
+
+/**
+ * Process transport stream packets, extract PCR and optionally descramble
+ */
+void
+ts_recv_packet1(th_transport_t *t, uint8_t *tsb)
+{
+  th_stream_t *st;
+  int pid;
+  th_descrambler_t *td;
+
+  pid = (tsb[1] & 0x1f) << 8 | tsb[2];
+
+  LIST_FOREACH(st, &t->tht_streams, st_link) 
+    if(st->st_pid == pid)
+      break;
+
+  if(st == NULL)
+    return;
+
+  avgstat_add(&t->tht_rate, 188, dispatch_clock);
+
+  /* Extract PCR */
+  if(tsb[3] & 0x20 && tsb[4] > 0 && tsb[5] & 0x10)
+    ts_extract_pcr(t, st, tsb);
+
+
+  if(tsb[3] & 0xc0) {
+    /* scrambled stream */
+    LIST_FOREACH(td, &t->tht_descramblers, td_transport_link)
+      if(td->td_descramble(td, t, st, tsb))
+       break;
+    
+    return;
+  }
+
+  ts_recv_packet0(t, st, tsb);
+}
+
+
+/*
+ * Process transport stream packets, simple version
+ */
+void
+ts_recv_packet2(th_transport_t *t, uint8_t *tsb)
+{
+  th_stream_t *st;
+  int pid;
+
+  pid = (tsb[1] & 0x1f) << 8 | tsb[2];
+  LIST_FOREACH(st, &t->tht_streams, st_link) 
+    if(st->st_pid == pid)
+      break;
+
+  if(st == NULL)
+    return;
+
+  ts_recv_packet0(t, st, tsb);
+}
index acce432089b57987bcc05ed2267838c29e1c9bc6..108dfcd5642522b63fb0eb9a96dbb3b35c9f4d44 100644 (file)
--- a/tsdemux.h
+++ b/tsdemux.h
@@ -19,6 +19,8 @@
 #ifndef TSDEMUX_H
 #define TSDEMUX_H
 
-void ts_recv_packet(th_transport_t *t, int pid, uint8_t *tsb, int doplugin);
+void ts_recv_packet1(th_transport_t *t, uint8_t *tsb);
+
+void ts_recv_packet2(th_transport_t *t, uint8_t *tsb);
 
 #endif /* TSDEMUX_H */