]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
mkv muxer: reoder DVBSUB packets (to be more in sync with current PTS)
authorJaroslav Kysela <perex@perex.cz>
Fri, 28 Apr 2017 19:08:49 +0000 (21:08 +0200)
committerJaroslav Kysela <perex@perex.cz>
Fri, 28 Apr 2017 19:08:49 +0000 (21:08 +0200)
src/muxer/muxer_mkv.c
src/packet.c
src/packet.h
src/parsers/parsers.c
src/plumbing/tsfix.c
src/profile.c

index 016a90be60210096c772e67efc7696871805965e..948750df04b8736418890d8ac706ae4af5b0c5cc 100644 (file)
@@ -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;
 }
index 6c723134da240895d31414daa2caa854c383d16e..bb23ef1e4f5548bf7e80beb7e6b999822782dc18 100644 (file)
@@ -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));
+  }
+}
+
+
 /**
  *
  */
index 6d418fbfbbc1b9656cabe27b91aa10e667e009c8..c3e6e5716b9a0a4917a0af3faaa78ba2e4f5283e 100644 (file)
@@ -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);
index 23465b4baadf840cf990bf46f02495818cf49540..08b02dd81d4681b724961f9a11cfb303847abf88 100644 (file)
@@ -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))
index 866cbd7fd6624beddce766eebefe3e476cb0d7d9..3c9f19f8787f2d7d300992896b1779d42e13a45b 100644 (file)
@@ -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];
index 0dd96ac5d3e03862fc9456f4a828bb6bb45d06f1..018a1a10e45428050bd5cf1a46b81045b129a317 100644 (file)
@@ -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);