]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
tsfix: try to fix MPEG2VIDEO pts recovery for broken stream
authorJaroslav Kysela <perex@perex.cz>
Thu, 11 Aug 2016 13:40:28 +0000 (15:40 +0200)
committerJaroslav Kysela <perex@perex.cz>
Thu, 11 Aug 2016 13:40:28 +0000 (15:40 +0200)
src/packet.h
src/plumbing/tsfix.c

index 00e12da00f888f03322ae442171c530dc7b6c964..9253201e2305b86e7a8a7320d95bf2a573ea9bfb 100644 (file)
@@ -140,6 +140,8 @@ static inline uint8_t *pktbuf_ptr(pktbuf_t *pb) { return pb->pb_data; }
 
 static inline int64_t pts_diff(int64_t a, int64_t b)
 {
+  if (a == PTS_UNSET || b == PTS_UNSET)
+    return PTS_UNSET;
   a &= PTS_MASK;
   b &= PTS_MASK;
   if (b < (PTS_MASK / 4) && a > (PTS_MASK / 2))
@@ -150,4 +152,15 @@ static inline int64_t pts_diff(int64_t a, int64_t b)
     return PTS_UNSET;
 }
 
+static inline int pts_is_greater_or_equal(int64_t base, int64_t value)
+{
+  if (base == PTS_UNSET || value == PTS_UNSET)
+    return -1;
+  if (value >= base)
+    return 1;
+  if (value < (PTS_MASK / 4) && base > (PTS_MASK / 2))
+    return value + PTS_MASK + 1 >= base;
+  return 0;
+}
+
 #endif /* PACKET_H_ */
index c413987f8ef5c767837cc9329b39bedfd4676e38..7c0f19d85989e466e34a1bf476cf0d634d41e4b1 100644 (file)
@@ -333,6 +333,7 @@ static void
 recover_pts(tsfix_t *tf, tfstream_t *tfs, th_pkt_t *pkt)
 {
   th_pktref_t *srch;
+  int total;
 
   pktref_enqueue(&tf->tf_ptsq, pkt);
 
@@ -357,19 +358,33 @@ recover_pts(tsfix_t *tf, tfstream_t *tfs, th_pkt_t *pkt)
       case PKT_P_FRAME:
        /* Presentation occures at DTS of next I or P frame,
           try to find it */
-       PKTREF_FOREACH(srch, &tf->tf_ptsq)
-         if (tfs_find(tf, srch->pr_pkt) == tfs &&
-             srch->pr_pkt->pkt_frametype <= PKT_P_FRAME) {
+        total = 0;
+       PKTREF_FOREACH(srch, &tf->tf_ptsq) {
+         if (pkt->pkt_componentindex != tfs->tfs_index)
+           continue;
+          total++;
+         if (srch->pr_pkt->pkt_frametype <= PKT_P_FRAME &&
+             pts_is_greater_or_equal(pkt->pkt_dts, srch->pr_pkt->pkt_dts) > 0 &&
+             pts_diff(pkt->pkt_dts, srch->pr_pkt->pkt_dts) < 10 * 90000) {
            pkt->pkt_pts = srch->pr_pkt->pkt_dts;
-           tvhtrace("tsfix", "%-12s PTS *-frame set to %"PRId64,
+           tvhtrace("tsfix", "%-12s PTS *-frame set to %"PRId64", DTS %"PRId64,
                        streaming_component_type2txt(tfs->tfs_type),
-                       pkt->pkt_pts);
+                       pkt->pkt_pts, pkt->pkt_dts);
            break;
          }
+         
+        }
        if (srch == NULL) {
-         /* return packet back to tf_ptsq */
-         pktref_insert_head(&tf->tf_ptsq, pkt);
-         return; /* not arrived yet, wait */
+         if (total < 50) {
+            /* return packet back to tf_ptsq */
+           pktref_insert_head(&tf->tf_ptsq, pkt);
+           return; /* not arrived yet, wait */
+          } else {
+           tvhtrace("tsfix", "%-12s packet drop PTS %"PRId64", DTS %"PRId64,
+                       streaming_component_type2txt(tfs->tfs_type),
+                       pkt->pkt_pts, pkt->pkt_dts);
+            pkt_ref_dec(pkt);
+          }
         }
       }
       break;