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))
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_ */
recover_pts(tsfix_t *tf, tfstream_t *tfs, th_pkt_t *pkt)
{
th_pktref_t *srch;
+ int total;
pktref_enqueue(&tf->tf_ptsq, 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;