tsfix: apply local reference for teletext if the MPEG-TS encoder is crazy

This commit is contained in:
Jaroslav Kysela 2014-10-23 21:55:08 +02:00
parent c297aa739a
commit 9c6b8c2975

View file

@ -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;