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: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/merge_requests/914>
This commit is contained in:
Jan Schmidt 2021-03-19 02:51:20 +11:00
parent 590fbb4ddd
commit fae29cb3c2
2 changed files with 21 additions and 6 deletions

View file

@ -658,6 +658,7 @@ gst_qt_mux_pad_reset (GstQTMuxPad * qtpad)
qtpad->sparse = FALSE; qtpad->sparse = FALSE;
qtpad->first_cc_sample_size = 0; qtpad->first_cc_sample_size = 0;
qtpad->flow_status = GST_FLOW_OK; qtpad->flow_status = GST_FLOW_OK;
qtpad->warned_empty_duration = FALSE;
gst_buffer_replace (&qtpad->last_buf, NULL); 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 /* duration actually means time delta between samples, so we calculate
* the duration based on the difference in DTS or PTS, falling back * 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 * 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)) if (GST_BUFFER_DURATION_IS_VALID (last_buf))
duration = GST_BUFFER_DURATION (last_buf); duration = GST_BUFFER_DURATION (last_buf);
else else
duration = 0; duration = 0;
if (!pad->sparse) { if (!pad->sparse) {
if (buf && GST_BUFFER_DTS_IS_VALID (buf) if (buf && GST_BUFFER_DTS_IS_VALID (buf)
&& GST_BUFFER_DTS_IS_VALID (last_buf)) && GST_BUFFER_DTS_IS_VALID (last_buf)) {
duration = GST_BUFFER_DTS (buf) - GST_BUFFER_DTS (last_buf); if (GST_BUFFER_DTS (buf) >= GST_BUFFER_DTS (last_buf))
else if (buf && GST_BUFFER_PTS_IS_VALID (buf) duration = GST_BUFFER_DTS (buf) - GST_BUFFER_DTS (last_buf);
&& GST_BUFFER_PTS_IS_VALID (last_buf)) } else if (buf && GST_BUFFER_PTS_IS_VALID (buf)
duration = GST_BUFFER_PTS (buf) - GST_BUFFER_PTS (last_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) { if (qtmux->current_pad != pad || qtmux->current_chunk_offset == -1) {

View file

@ -128,6 +128,10 @@ struct _GstQTMuxPad
GstClockTime last_dts; GstClockTime last_dts;
guint64 sample_offset; 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 */ /* This is compensate for CTTS */
GstClockTime dts_adjustment; GstClockTime dts_adjustment;