From b7e9e606a97a3e174fc5c791e515fa63df563ff9 Mon Sep 17 00:00:00 2001 From: Mathieu Duponchelle Date: Thu, 11 Mar 2021 18:21:11 +0100 Subject: [PATCH] tsmux: finalize PCR timing for complete accuracy In order to always insert a PCR packet right on time, we need to check whether one is needed when outputting any packet, not only a packet for the PCR stream. Most of the PCR packets will remain data-carrying packets, but as a last resort we may insert stuffing packets on the PCR stream. Part-of: --- gst/mpegtsmux/tsmux/tsmux.c | 43 +++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/gst/mpegtsmux/tsmux/tsmux.c b/gst/mpegtsmux/tsmux/tsmux.c index 5a13106091..186b660d56 100644 --- a/gst/mpegtsmux/tsmux/tsmux.c +++ b/gst/mpegtsmux/tsmux/tsmux.c @@ -117,6 +117,14 @@ static gboolean tsmux_write_pat (TsMux * mux); static gboolean tsmux_write_pmt (TsMux * mux, TsMuxProgram * program); static gboolean tsmux_write_scte_null (TsMux * mux, TsMuxProgram * program); +static gint64 get_next_pcr (TsMux * mux, gint64 cur_ts); +static gint64 get_current_pcr (TsMux * mux, gint64 cur_ts); +static gint64 write_new_pcr (TsMux * mux, TsMuxStream * stream, gint64 cur_pcr, + gint64 next_pcr); +static gboolean tsmux_write_ts_header (TsMux * mux, guint8 * buf, + TsMuxPacketInfo * pi, guint * payload_len_out, guint * payload_offset_out, + guint stream_avail); + static void tsmux_section_free (TsMuxSection * section) { @@ -808,9 +816,44 @@ tsmux_packet_out (TsMux * mux, GstBuffer * buf, gint64 pcr) GST_BUFFER_PTS (buf) = gst_util_uint64_scale (mux->n_bytes * 8, GST_SECOND, mux->bitrate); + if (mux->bitrate && mux->first_pcr_ts != G_MININT64) { + GList *cur; + + for (cur = mux->programs; cur; cur = cur->next) { + TsMuxProgram *program = (TsMuxProgram *) cur->data; + TsMuxStream *stream = program->pcr_stream; + gint64 cur_pcr = get_current_pcr (mux, 0); + gint64 next_pcr = get_next_pcr (mux, 0); + + gint64 new_pcr = write_new_pcr (mux, stream, cur_pcr, next_pcr); + + if (new_pcr != -1) { + GstBuffer *buf = NULL; + GstMapInfo map; + guint payload_len, payload_offs; + + if (!tsmux_get_buffer (mux, &buf)) { + goto error; + } + + gst_buffer_map (buf, &map, GST_MAP_READ); + tsmux_write_ts_header (mux, map.data, &stream->pi, &payload_len, + &payload_offs, 0); + gst_buffer_unmap (buf, &map); + + stream->pi.flags &= TSMUX_PACKET_FLAG_PES_FULL_HEADER; + if (!tsmux_packet_out (mux, buf, new_pcr)) + goto error; + } + } + } + mux->n_bytes += gst_buffer_get_size (buf); return mux->write_func (buf, mux->write_func_data, pcr); + +error: + return FALSE; } /*