From 5e47f8fec4496b783ecd0f87589839ba18849ce0 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Fri, 28 Apr 2017 21:08:49 +0200 Subject: [PATCH] mkv muxer: reoder DVBSUB packets (to be more in sync with current PTS) --- src/muxer/muxer_mkv.c | 35 +++++++++++++++++++++++++++++++++-- src/packet.c | 16 ++++++++++++++++ src/packet.h | 7 +++++++ src/parsers/parsers.c | 2 +- src/plumbing/tsfix.c | 12 ++++++++++++ src/profile.c | 4 +++- 6 files changed, 72 insertions(+), 4 deletions(-) diff --git a/src/muxer/muxer_mkv.c b/src/muxer/muxer_mkv.c index 016a90be6..948750df0 100644 --- a/src/muxer/muxer_mkv.c +++ b/src/muxer/muxer_mkv.c @@ -131,13 +131,24 @@ typedef struct mk_muxer { char *title; int webm; + + struct th_pktref_queue holdq; } mk_muxer_t; /* --- */ static int mk_mux_insert_chapter(mk_muxer_t *mk); -/** +/* + * + */ +static int mk_pktref_cmp(const void *_a, const void *_b) +{ + const th_pktref_t *a = _a, *b = _b; + return a->pr_pkt->pkt_pts - b->pr_pkt->pkt_pts; +} + +/* * */ static htsbuf_queue_t * @@ -1094,7 +1105,7 @@ mk_mux_write_pkt(mk_muxer_t *mk, th_pkt_t *pkt) { int i, mark; mk_track_t *t = NULL; - th_pkt_t *opkt; + th_pkt_t *opkt, *tpkt; for (i = 0; i < mk->ntracks; i++) { t = &mk->tracks[i]; @@ -1107,8 +1118,24 @@ mk_mux_write_pkt(mk_muxer_t *mk, th_pkt_t *pkt) return mk->error; } + if (pkt->pkt_type == SCT_DVBSUB && pts_diff(pkt->pkt_pcr, pkt->pkt_pts) > 90000) { + tvhtrace(LS_MKV, "insert pkt to holdq: pts %ld, pcr %ld, diff %ld\n", pkt->pkt_pcr, pkt->pkt_pts, pts_diff(pkt->pkt_pcr, pkt->pkt_pts)); + pktref_enqueue_sorted(&mk->holdq, pkt, mk_pktref_cmp); + return mk->error; + } + mark = 0; if(SCT_ISAUDIO(pkt->pkt_type)) { + while ((opkt = pktref_first(&mk->holdq)) != NULL) { + if (pts_diff(opkt->pkt_pts, pkt->pkt_pts) > 90000) + break; + opkt = pktref_get_first(&mk->holdq); + tvhtrace(LS_MKV, "hold push, pts %ld\n", opkt->pkt_pts); + tpkt = pkt_copy_shallow(opkt); + pkt_ref_dec(opkt); + tpkt->pkt_pcr = tpkt->pkt_pts; + mk_mux_write_pkt(mk, tpkt); + } if(pkt->a.pkt_channels != t->channels && pkt->a.pkt_channels) { mark = 1; @@ -1432,6 +1459,8 @@ mkv_muxer_close(muxer_t *m) return -1; } + pktref_clear_queue(&mk->holdq); + return 0; } @@ -1481,5 +1510,7 @@ mkv_muxer_create(const muxer_config_t *m_cfg) mk->webm = m_cfg->m_type == MC_WEBM; mk->fd = -1; + TAILQ_INIT(&mk->holdq); + return (muxer_t*)mk; } diff --git a/src/packet.c b/src/packet.c index 6c723134d..bb23ef1e4 100644 --- a/src/packet.c +++ b/src/packet.c @@ -216,6 +216,22 @@ pktref_enqueue(struct th_pktref_queue *q, th_pkt_t *pkt) } +/** + * Reference count is transfered to queue + */ +void +pktref_enqueue_sorted(struct th_pktref_queue *q, th_pkt_t *pkt, + int (*cmp)(const void *, const void *)) +{ + th_pktref_t *pr = malloc(sizeof(th_pktref_t)); + if (pr) { + pr->pr_pkt = pkt; + TAILQ_INSERT_SORTED(q, pr, pr_link, cmp); + memoryinfo_alloc(&pktref_memoryinfo, sizeof(*pr)); + } +} + + /** * */ diff --git a/src/packet.h b/src/packet.h index 6d418fbfb..c3e6e5716 100644 --- a/src/packet.h +++ b/src/packet.h @@ -111,8 +111,15 @@ void pktref_clear_queue(struct th_pktref_queue *q); // Reference count is transfered to queue void pktref_enqueue(struct th_pktref_queue *q, th_pkt_t *pkt); +// Reference count is transfered to queue +void pktref_enqueue_sorted(struct th_pktref_queue *q, th_pkt_t *pkt, + int (*cmp)(const void *, const void *)); + void pktref_remove(struct th_pktref_queue *q, th_pktref_t *pr); +static inline th_pkt_t *pktref_first(struct th_pktref_queue *q) + { return (th_pkt_t *)TAILQ_FIRST(q); } + th_pkt_t *pktref_get_first(struct th_pktref_queue *q); void pktref_insert_head(struct th_pktref_queue *q, th_pkt_t *pkt); diff --git a/src/parsers/parsers.c b/src/parsers/parsers.c index 23465b4ba..08b02dd81 100644 --- a/src/parsers/parsers.c +++ b/src/parsers/parsers.c @@ -1832,7 +1832,7 @@ parser_deliver(service_t *t, elementary_stream_t *st, th_pkt_t *pkt) assert(pkt->pkt_type == st->es_type); - diff = st->es_type == SCT_DVBSUB ? 4*90000 : 2*90000; + diff = st->es_type == SCT_DVBSUB ? 4*90000 : 3*90000; if (pts_diff(pkt->pkt_pcr, pkt->pkt_pts) > diff) { if (tvhlog_limit(&st->es_pcr_log, 2)) diff --git a/src/plumbing/tsfix.c b/src/plumbing/tsfix.c index 866cbd7fd..3c9f19f87 100644 --- a/src/plumbing/tsfix.c +++ b/src/plumbing/tsfix.c @@ -282,9 +282,21 @@ normalize_ts(tsfix_t *tf, tfstream_t *tfs, th_pkt_t *pkt, int backlog) d = ((pkt->pkt_pts & PTS_MASK) - pkt->pkt_dts) & PTS_MASK; pkt->pkt_pts = dts + d; } + if(pkt->pkt_pcr != PTS_UNSET) { + /* Compute delta between PCR and DTS (and watch out for 33 bit wrap) */ + d = ((pkt->pkt_pcr & PTS_MASK) - pkt->pkt_dts) & PTS_MASK; + if (d > PTS_MASK / 2) + d = -(PTS_MASK - d); + pkt->pkt_pcr = dts + d; + } pkt->pkt_dts = dts; + if (pkt->pkt_pts < 0 || pkt->pkt_dts < 0 || pkt->pkt_pcr < 0) { + tsfix_packet_drop(tfs, pkt, "negative2/error"); + return; + } + deliver: if (tvhtrace_enabled()) { char _odts[22], _opts[22]; diff --git a/src/profile.c b/src/profile.c index 0dd96ac5d..018a1a10e 100644 --- a/src/profile.c +++ b/src/profile.c @@ -716,11 +716,13 @@ profile_sharer_deliver(profile_chain_t *prch, streaming_message_t *sm) * time correction here */ if (pkt->pkt_pts >= prch->prch_ts_delta && - pkt->pkt_dts >= prch->prch_ts_delta) { + pkt->pkt_dts >= prch->prch_ts_delta && + pkt->pkt_pcr >= prch->prch_ts_delta) { th_pkt_t *n = pkt_copy_shallow(pkt); pkt_ref_dec(pkt); n->pkt_pts -= prch->prch_ts_delta; n->pkt_dts -= prch->prch_ts_delta; + n->pkt_pcr -= prch->prch_ts_delta; sm->sm_data = n; } else { streaming_msg_free(sm); -- 2.47.2