From: Jaroslav Kysela Date: Thu, 11 Aug 2016 13:40:28 +0000 (+0200) Subject: tsfix: try to fix MPEG2VIDEO pts recovery for broken stream X-Git-Tag: v4.2.1~393 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=219678c2c3f14ab343a093eb27d21dd290a65585;p=thirdparty%2Ftvheadend.git tsfix: try to fix MPEG2VIDEO pts recovery for broken stream --- diff --git a/src/packet.h b/src/packet.h index 00e12da00..9253201e2 100644 --- a/src/packet.h +++ b/src/packet.h @@ -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_ */ diff --git a/src/plumbing/tsfix.c b/src/plumbing/tsfix.c index c413987f8..7c0f19d85 100644 --- a/src/plumbing/tsfix.c +++ b/src/plumbing/tsfix.c @@ -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;