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 *
{
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];
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;
return -1;
}
+ pktref_clear_queue(&mk->holdq);
+
return 0;
}
mk->webm = m_cfg->m_type == MC_WEBM;
mk->fd = -1;
+ TAILQ_INIT(&mk->holdq);
+
return (muxer_t*)mk;
}
}
+/**
+ * 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));
+ }
+}
+
+
/**
*
*/
// 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);
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))
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];
* 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);