qtmux: Handle DTS with negative running time

As QT works with duration, simply bring back first DTS to 0 and shift
forward the PTS of the same amount.

https://bugzilla.gnome.org/show_bug.cgi?id=740575
This commit is contained in:
Nicolas Dufresne 2015-04-03 20:34:42 -04:00
parent 2274ca7d07
commit 12181efddc
2 changed files with 56 additions and 7 deletions

View file

@ -493,6 +493,7 @@ gst_qt_mux_pad_reset (GstQTPad * qtpad)
qtpad->sample_size = 0;
qtpad->sync = FALSE;
qtpad->last_dts = 0;
qtpad->dts_adjustment = GST_CLOCK_TIME_NONE;
qtpad->first_ts = GST_CLOCK_TIME_NONE;
qtpad->prepare_buf_func = NULL;
qtpad->create_empty_buffer = NULL;
@ -2996,9 +2997,6 @@ gst_qt_mux_add_buffer (GstQTMux * qtmux, GstQTPad * pad, GstBuffer * buf)
GST_BUFFER_DTS (buf)) {
GST_BUFFER_DTS (buf) = GST_BUFFER_DTS (last_buf) + last_buf_duration;
}
if (GST_BUFFER_PTS_IS_VALID (buf))
GST_BUFFER_DTS (buf) = MIN (GST_BUFFER_DTS (buf), GST_BUFFER_PTS (buf));
}
if (last_buf && !buf && !GST_BUFFER_DURATION_IS_VALID (last_buf)) {
@ -3248,6 +3246,57 @@ not_negotiated:
}
}
/*
* DTS running time can be negative. There is no way to represent that in
* MP4 however, thus we need to offset DTS so that it starts from 0.
*/
static void
gst_qt_pad_adjust_buffer_dts (GstQTMux * qtmux, GstQTPad * pad,
GstCollectData * cdata, GstBuffer ** buf)
{
GstClockTime pts;
gint64 dts;
pts = GST_BUFFER_PTS (*buf);
dts = GST_COLLECT_PADS_DTS (cdata);
GST_LOG_OBJECT (qtmux, "selected pad %s with PTS %" GST_TIME_FORMAT
" and DTS %" GST_STIME_FORMAT, GST_PAD_NAME (cdata->pad),
GST_TIME_ARGS (pts), GST_STIME_ARGS (dts));
if (!GST_CLOCK_TIME_IS_VALID (pad->dts_adjustment)) {
if (GST_CLOCK_STIME_IS_VALID (dts) && dts < 0)
pad->dts_adjustment = -dts;
else
pad->dts_adjustment = 0;
}
if (pad->dts_adjustment > 0) {
*buf = gst_buffer_make_writable (*buf);
dts += pad->dts_adjustment;
if (GST_CLOCK_TIME_IS_VALID (pts))
pts += pad->dts_adjustment;
if (GST_CLOCK_STIME_IS_VALID (dts) && dts < 0) {
GST_WARNING_OBJECT (pad, "Decreasing DTS.");
dts = 0;
}
if (pts < dts) {
GST_WARNING_OBJECT (pad, "DTS is bigger then PTS");
pts = dts;
}
GST_BUFFER_PTS (*buf) = pts;
GST_BUFFER_DTS (*buf) = dts;
GST_LOG_OBJECT (qtmux, "time adjusted to PTS %" GST_TIME_FORMAT
" and DTS %" GST_TIME_FORMAT, GST_TIME_ARGS (pts), GST_TIME_ARGS (dts));
}
}
static GstFlowReturn
gst_qt_mux_handle_buffer (GstCollectPads * pads, GstCollectData * cdata,
GstBuffer * buf, gpointer user_data)
@ -3255,7 +3304,6 @@ gst_qt_mux_handle_buffer (GstCollectPads * pads, GstCollectData * cdata,
GstFlowReturn ret = GST_FLOW_OK;
GstQTMux *qtmux = GST_QT_MUX_CAST (user_data);
GstQTPad *best_pad = NULL;
GstClockTime best_time = GST_CLOCK_TIME_NONE;
if (G_UNLIKELY (qtmux->state == GST_QT_MUX_STATE_STARTED)) {
if ((ret = gst_qt_mux_start_file (qtmux)) != GST_FLOW_OK)
@ -3272,9 +3320,7 @@ gst_qt_mux_handle_buffer (GstCollectPads * pads, GstCollectData * cdata,
/* clipping already converted to running time */
if (best_pad != NULL) {
g_assert (buf);
best_time = GST_BUFFER_PTS (buf);
GST_LOG_OBJECT (qtmux, "selected pad %s with time %" GST_TIME_FORMAT,
GST_PAD_NAME (best_pad->collect.pad), GST_TIME_ARGS (best_time));
gst_qt_pad_adjust_buffer_dts (qtmux, best_pad, cdata, &buf);
ret = gst_qt_mux_add_buffer (qtmux, best_pad, buf);
} else {
qtmux->state = GST_QT_MUX_STATE_EOS;

View file

@ -109,6 +109,9 @@ struct _GstQTPad
/* dts of last_buf */
GstClockTime last_dts;
/* This is compensate for CTTS */
GstClockTime dts_adjustment;
/* store the first timestamp for comparing with other streams and
* know if there are late streams */
GstClockTime first_ts;