]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
tsfix: apply local reference for teletext if the MPEG-TS encoder is crazy
authorJaroslav Kysela <perex@perex.cz>
Thu, 23 Oct 2014 19:55:08 +0000 (21:55 +0200)
committerJaroslav Kysela <perex@perex.cz>
Thu, 23 Oct 2014 19:55:08 +0000 (21:55 +0200)
src/plumbing/tsfix.c

index b1b1afde63199529e4b3eabdd705290efedd2a24..5aa10c965c0b809cd1331e1a11d0edf758f73923 100644 (file)
 #include "streaming.h"
 #include "tsfix.h"
 
-LIST_HEAD(tfstream_list, tfstream);
+#define PTS_MASK 0x1ffffffffLL
 
 #define tsfixprintf(fmt...) // printf(fmt)
 
+LIST_HEAD(tfstream_list, tfstream);
+
 /**
  *
  */
@@ -36,6 +38,7 @@ typedef struct tfstream {
   streaming_component_type_t tfs_type;
 
   int tfs_bad_dts;
+  int64_t tfs_local_ref;
   int64_t tfs_last_dts_norm;
   int64_t tfs_dts_epoch;
 
@@ -63,6 +66,28 @@ typedef struct tsfix {
 } tsfix_t;
 
 
+/**
+ * Compute the timestamp deltas
+ */
+static int64_t
+tsfix_ts_diff(int64_t ts1, int64_t ts2)
+{
+  int64_t r;
+  ts1 &= PTS_MASK;
+  ts2 &= PTS_MASK;
+
+  r = abs(ts1 - ts2);
+  if (r > (PTS_MASK / 4)) {
+    /* try to wrap the lowest value */
+    if (ts1 < ts2)
+      ts1 += PTS_MASK + 1;
+    else
+      ts2 += PTS_MASK + 1;
+    return abs(ts1 - ts2);
+  }
+  return r;
+}
+
 /**
  *
  */
@@ -98,6 +123,7 @@ tsfix_add_stream(tsfix_t *tf, int index, streaming_component_type_t type)
 
   tfs->tfs_type = type;
   tfs->tfs_index = index;
+  tfs->tfs_local_ref = PTS_UNSET;
   tfs->tfs_last_dts_norm = PTS_UNSET;
   tfs->tfs_last_dts_in = PTS_UNSET;
   tfs->tfs_dts_epoch = 0;
@@ -142,15 +168,13 @@ tsfix_stop(tsfix_t *tf)
 }
 
 
-#define PTS_MASK 0x1ffffffffLL
-
 /**
  *
  */
 static void
 normalize_ts(tsfix_t *tf, tfstream_t *tfs, th_pkt_t *pkt)
 {
-  int64_t dts, d;
+  int64_t ref, dts, d;
 
   if(tf->tf_tsref == PTS_UNSET) {
     pkt_ref_dec(pkt);
@@ -161,7 +185,8 @@ normalize_ts(tsfix_t *tf, tfstream_t *tfs, th_pkt_t *pkt)
   pkt->pkt_pts &= PTS_MASK;
 
   /* Subtract the transport wide start offset */
-  dts = pkt->pkt_dts - tf->tf_tsref;
+  ref = tfs->tfs_local_ref != PTS_UNSET ? tfs->tfs_local_ref : tf->tf_tsref;
+  dts = pkt->pkt_dts - ref;
 
   if(tfs->tfs_last_dts_norm == PTS_UNSET) {
     if(dts < 0) {
@@ -322,6 +347,19 @@ tsfix_input_packet(tsfix_t *tf, streaming_message_t *sm)
       (SCT_ISVIDEO(tfs->tfs_type) && pkt->pkt_frametype == PKT_I_FRAME))) {
       tf->tf_tsref = pkt->pkt_dts & PTS_MASK;
       tsfixprintf("reference clock set to %"PRId64"\n", tf->tf_tsref);
+  } else {
+    /* For teletext, the encoders might use completely different timestamps */
+    /* If the difference is greater than 2 seconds, use the actual dts value */
+    if (tfs->tfs_type == SCT_TELETEXT && tfs->tfs_local_ref == PTS_UNSET &&
+        tf->tf_tsref != PTS_UNSET) {
+      int64_t diff = tsfix_ts_diff(tf->tf_tsref, pkt->pkt_dts);
+      if (diff > 2 * 90000) {
+        tvhwarn("parser", "The timediff for TELETEXT is big (%"PRId64"), using current dts", diff);
+        tfs->tfs_local_ref = pkt->pkt_dts;
+      } else {
+        tfs->tfs_local_ref = tf->tf_tsref;
+      }
+    }
   }
 
   int pdur = pkt->pkt_duration >> pkt->pkt_field;