summaryrefslogtreecommitdiff
path: root/gst
diff options
context:
space:
mode:
authorMathieu Duponchelle <mathieu@centricular.com>2021-03-11 18:21:11 +0100
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>2021-03-18 13:57:27 +0000
commitb7e9e606a97a3e174fc5c791e515fa63df563ff9 (patch)
tree5a21cf3d854f65d9207d81abb46ed3d3b2c57b8b /gst
parent3201575d2a522018f14040dc787009945e468814 (diff)
downloadgstreamer-plugins-bad-b7e9e606a97a3e174fc5c791e515fa63df563ff9.tar.gz
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: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/2073>
Diffstat (limited to 'gst')
-rw-r--r--gst/mpegtsmux/tsmux/tsmux.c43
1 files changed, 43 insertions, 0 deletions
diff --git a/gst/mpegtsmux/tsmux/tsmux.c b/gst/mpegtsmux/tsmux/tsmux.c
index 5a1310609..186b660d5 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;
}
/*