From 9c6b8c2975f079a6ad3b174a613fbc2d034a08a9 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Thu, 23 Oct 2014 21:55:08 +0200 Subject: [PATCH] tsfix: apply local reference for teletext if the MPEG-TS encoder is crazy --- src/plumbing/tsfix.c | 48 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 5 deletions(-) diff --git a/src/plumbing/tsfix.c b/src/plumbing/tsfix.c index b1b1afde..5aa10c96 100644 --- a/src/plumbing/tsfix.c +++ b/src/plumbing/tsfix.c @@ -20,10 +20,12 @@ #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;