dashdemux: Improve live stream manifest update repositioning

When updating the manifest the timestamps on it might have changed a little
due to rounding and timescale conversions. If the change makes the timestamp
of the current segment to go up it makes dashdemux reposition to the previous
one causing one extra unnecessary download.

So when repositioning add an extra 10 microseconds to cover for that rounding
issues and increase the chance of falling in the same segment.

Additionally, also improve the time used when the client is already after the
last segment. Instead of using the last segment starting timestamp use the
final timestamp to make it reposition to the next one and not to the one that
has already been downloaded.
This commit is contained in:
Thiago Santos 2015-05-11 14:19:20 -03:00
parent 7de9fbc122
commit 23ad922b64
3 changed files with 20 additions and 8 deletions

View file

@ -1196,14 +1196,24 @@ gst_dash_demux_update_manifest_data (GstAdaptiveDemux * demux,
} }
if (gst_mpd_client_get_next_fragment_timestamp (dashdemux->client, if (gst_mpd_client_get_next_fragment_timestamp (dashdemux->client,
demux_stream->index, &ts)
|| gst_mpd_client_get_last_fragment_timestamp_end (dashdemux->client,
demux_stream->index, &ts)) { demux_stream->index, &ts)) {
/* Due to rounding when doing the timescale conversions it might happen
* that the ts falls back to a previous segment, leading the same data
* to be downloaded twice. We try to work around this by always adding
* 10 microseconds to get back to the correct segment. The errors are
* usually on the order of nanoseconds so it should be enough.
*/
GST_DEBUG_OBJECT (GST_ADAPTIVE_DEMUX_STREAM_PAD (demux_stream),
"Current position: %" GST_TIME_FORMAT ", updating to %"
GST_TIME_FORMAT, GST_TIME_ARGS (ts),
GST_TIME_ARGS (ts + (10 * GST_USECOND)));
ts += 10 * GST_USECOND;
gst_mpd_client_stream_seek (new_client, new_stream, ts); gst_mpd_client_stream_seek (new_client, new_stream, ts);
} else
if (gst_mpd_client_get_last_fragment_timestamp (dashdemux->client,
demux_stream->index, &ts)) {
/* try to set to the old timestamp + 1 */
gst_mpd_client_stream_seek (new_client, new_stream, ts + 1);
} }
demux_stream->active_stream = new_stream; demux_stream->active_stream = new_stream;
} }

View file

@ -3548,7 +3548,7 @@ gst_mpd_client_get_availability_start_time (GstMpdClient * client)
} }
gboolean gboolean
gst_mpd_client_get_last_fragment_timestamp (GstMpdClient * client, gst_mpd_client_get_last_fragment_timestamp_end (GstMpdClient * client,
guint stream_idx, GstClockTime * ts) guint stream_idx, GstClockTime * ts)
{ {
GstActiveStream *stream; GstActiveStream *stream;
@ -3562,7 +3562,9 @@ gst_mpd_client_get_last_fragment_timestamp (GstMpdClient * client,
segment_idx = gst_mpd_client_get_segments_counts (stream) - 1; segment_idx = gst_mpd_client_get_segments_counts (stream) - 1;
currentChunk = g_ptr_array_index (stream->segments, segment_idx); currentChunk = g_ptr_array_index (stream->segments, segment_idx);
*ts = currentChunk->start + (currentChunk->duration * currentChunk->repeat); *ts =
currentChunk->start + (currentChunk->duration * (1 +
currentChunk->repeat));
return TRUE; return TRUE;
} }

View file

@ -496,7 +496,7 @@ gboolean gst_mpd_client_setup_representation (GstMpdClient *client, GstActiveStr
GList * gst_mpd_client_get_adaptation_sets (GstMpdClient * client); GList * gst_mpd_client_get_adaptation_sets (GstMpdClient * client);
GstClockTime gst_mpd_client_get_next_fragment_duration (GstMpdClient * client, GstActiveStream * stream); GstClockTime gst_mpd_client_get_next_fragment_duration (GstMpdClient * client, GstActiveStream * stream);
GstClockTime gst_mpd_client_get_media_presentation_duration (GstMpdClient *client); GstClockTime gst_mpd_client_get_media_presentation_duration (GstMpdClient *client);
gboolean gst_mpd_client_get_last_fragment_timestamp (GstMpdClient * client, guint stream_idx, GstClockTime * ts); gboolean gst_mpd_client_get_last_fragment_timestamp_end (GstMpdClient * client, guint stream_idx, GstClockTime * ts);
gboolean gst_mpd_client_get_next_fragment_timestamp (GstMpdClient * client, guint stream_idx, GstClockTime * ts); gboolean gst_mpd_client_get_next_fragment_timestamp (GstMpdClient * client, guint stream_idx, GstClockTime * ts);
gboolean gst_mpd_client_get_next_fragment (GstMpdClient *client, guint indexStream, GstMediaFragmentInfo * fragment); gboolean gst_mpd_client_get_next_fragment (GstMpdClient *client, guint indexStream, GstMediaFragmentInfo * fragment);
gboolean gst_mpd_client_get_next_header (GstMpdClient *client, gchar **uri, guint stream_idx, gint64 * range_start, gint64 * range_end); gboolean gst_mpd_client_get_next_header (GstMpdClient *client, gchar **uri, guint stream_idx, gint64 * range_start, gint64 * range_end);