From fae29cb3c21ffe480f110c2f9448a60c871e39fd Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Fri, 19 Mar 2021 02:51:20 +1100 Subject: [PATCH] qtmux: Protect against writing absurd sample durations If the input DTS goes backward or is missing, the calculated sample duration goes negative and wraps around to a very big number. In that case, just write a sample with a duration of 0 and hope the problem is transient. Part-of: --- gst/isomp4/gstqtmux.c | 23 +++++++++++++++++------ gst/isomp4/gstqtmux.h | 4 ++++ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/gst/isomp4/gstqtmux.c b/gst/isomp4/gstqtmux.c index 821e7f1710..a4d949c0c3 100644 --- a/gst/isomp4/gstqtmux.c +++ b/gst/isomp4/gstqtmux.c @@ -658,6 +658,7 @@ gst_qt_mux_pad_reset (GstQTMuxPad * qtpad) qtpad->sparse = FALSE; qtpad->first_cc_sample_size = 0; qtpad->flow_status = GST_FLOW_OK; + qtpad->warned_empty_duration = FALSE; gst_buffer_replace (&qtpad->last_buf, NULL); @@ -5150,18 +5151,28 @@ gst_qt_mux_add_buffer (GstQTMux * qtmux, GstQTMuxPad * pad, GstBuffer * buf) /* duration actually means time delta between samples, so we calculate * the duration based on the difference in DTS or PTS, falling back * to DURATION if the other two don't exist, such as with the last - * sample before EOS. Or use 0 if nothing else is available */ + * sample before EOS. Or use 0 if nothing else is available, + * making sure that duration doesn't go negative and wraparound. */ if (GST_BUFFER_DURATION_IS_VALID (last_buf)) duration = GST_BUFFER_DURATION (last_buf); else duration = 0; if (!pad->sparse) { if (buf && GST_BUFFER_DTS_IS_VALID (buf) - && GST_BUFFER_DTS_IS_VALID (last_buf)) - duration = GST_BUFFER_DTS (buf) - GST_BUFFER_DTS (last_buf); - else if (buf && GST_BUFFER_PTS_IS_VALID (buf) - && GST_BUFFER_PTS_IS_VALID (last_buf)) - duration = GST_BUFFER_PTS (buf) - GST_BUFFER_PTS (last_buf); + && GST_BUFFER_DTS_IS_VALID (last_buf)) { + if (GST_BUFFER_DTS (buf) >= GST_BUFFER_DTS (last_buf)) + duration = GST_BUFFER_DTS (buf) - GST_BUFFER_DTS (last_buf); + } else if (buf && GST_BUFFER_PTS_IS_VALID (buf) + && GST_BUFFER_PTS_IS_VALID (last_buf)) { + if (GST_BUFFER_PTS (buf) >= GST_BUFFER_PTS (last_buf)) + duration = GST_BUFFER_PTS (buf) - GST_BUFFER_PTS (last_buf); + } + if (duration == 0 && !pad->warned_empty_duration) { + GST_WARNING_OBJECT (qtmux, + "Sample with zero duration on pad %" GST_PTR_FORMAT + " due to missing or backward timestamps on the input stream", pad); + pad->warned_empty_duration = TRUE; + } } if (qtmux->current_pad != pad || qtmux->current_chunk_offset == -1) { diff --git a/gst/isomp4/gstqtmux.h b/gst/isomp4/gstqtmux.h index f4038852a9..0e6e7f6793 100644 --- a/gst/isomp4/gstqtmux.h +++ b/gst/isomp4/gstqtmux.h @@ -128,6 +128,10 @@ struct _GstQTMuxPad GstClockTime last_dts; guint64 sample_offset; + /* TRUE if we saw backward/missing DTS on this + * pad (and warned about it */ + gboolean warned_empty_duration; + /* This is compensate for CTTS */ GstClockTime dts_adjustment;