mssdemux: implement snap seeking

Implement snap seek flags handling in stream_seek to allow the
parent class to handle it for us

https://bugzilla.gnome.org/show_bug.cgi?id=759158
This commit is contained in:
Thiago Santos 2016-02-02 16:54:10 -03:00
parent c01d266238
commit ac2734f5cb
3 changed files with 58 additions and 39 deletions

View file

@ -310,7 +310,8 @@ gst_mss_demux_stream_seek (GstAdaptiveDemuxStream * stream, gboolean forward,
{
GstMssDemuxStream *mssstream = (GstMssDemuxStream *) stream;
gst_mss_stream_seek (mssstream->manifest_stream, flags, ts, final_ts);
gst_mss_stream_seek (mssstream->manifest_stream, forward, flags, ts,
final_ts);
return GST_FLOW_OK;
}

View file

@ -1089,26 +1089,32 @@ gst_mss_stream_type_name (GstMssStreamType streamtype)
/**
* Seeks all streams to the fragment that contains the set time
*
* @forward: if this is forward playback
* @time: time in nanoseconds
*/
void
gst_mss_manifest_seek (GstMssManifest * manifest, guint64 time)
gst_mss_manifest_seek (GstMssManifest * manifest, gboolean forward,
guint64 time)
{
GSList *iter;
for (iter = manifest->streams; iter; iter = g_slist_next (iter)) {
gst_mss_stream_seek (iter->data, 0, time, NULL);
gst_mss_stream_seek (iter->data, forward, 0, time, NULL);
}
}
#define SNAP_AFTER(forward,flags) \
((forward && (flags & GST_SEEK_FLAG_SNAP_AFTER)) || \
(!forward && (flags & GST_SEEK_FLAG_SNAP_BEFORE)))
/**
* Seeks this stream to the fragment that contains the sample at time
*
* @time: time in nanoseconds
*/
void
gst_mss_stream_seek (GstMssStream * stream, GstSeekFlags flags, guint64 time,
guint64 * final_time)
gst_mss_stream_seek (GstMssStream * stream, gboolean forward,
GstSeekFlags flags, guint64 time, guint64 * final_time)
{
GList *iter;
guint64 timescale;
@ -1118,48 +1124,58 @@ gst_mss_stream_seek (GstMssStream * stream, GstSeekFlags flags, guint64 time,
time = gst_util_uint64_scale_round (time, timescale, GST_SECOND);
GST_DEBUG ("Stream %s seeking to %" G_GUINT64_FORMAT, stream->url, time);
for (iter = stream->fragments; iter; iter = g_list_next (iter)) {
GList *next = g_list_next (iter);
if (next) {
fragment = next->data;
fragment = iter->data;
if (fragment->time + fragment->repetitions * fragment->duration > time) {
stream->current_fragment = iter;
stream->fragment_repetition_index =
(time - fragment->time) / fragment->duration;
if (((time - fragment->time) % fragment->duration) == 0) {
if (fragment->time > time) {
stream->current_fragment = iter;
break;
}
} else {
fragment = iter->data;
if (fragment->time + fragment->repetitions * fragment->duration > time) {
stream->current_fragment = iter;
} else {
stream->current_fragment = NULL; /* EOS */
/* for reverse playback, start from the previous fragment when we are
* exactly at a limit */
if (!forward)
stream->fragment_repetition_index--;
} else if (SNAP_AFTER (forward, flags))
stream->fragment_repetition_index++;
if (stream->fragment_repetition_index == fragment->repetitions) {
/* move to the next one */
stream->fragment_repetition_index = 0;
stream->current_fragment = g_list_next (iter);
fragment =
stream->current_fragment ? stream->current_fragment->data : NULL;
} else if (stream->fragment_repetition_index == -1) {
if (g_list_previous (iter)) {
stream->current_fragment = g_list_previous (iter);
fragment =
stream->current_fragment ? stream->current_fragment->data : NULL;
stream->fragment_repetition_index = fragment->repetitions - 1;
} else {
stream->fragment_repetition_index = 0;
}
}
break;
}
}
/* position inside the repetitions */
if (stream->current_fragment) {
fragment = stream->current_fragment->data;
stream->fragment_repetition_index =
(time - fragment->time) / fragment->duration;
}
GST_DEBUG ("Stream %s seeked to fragment time %" G_GUINT64_FORMAT
" repetition %u", stream->url, fragment->time,
" repetition %u", stream->url,
fragment ? fragment->time : GST_CLOCK_TIME_NONE,
stream->fragment_repetition_index);
if (final_time) {
if (fragment)
*final_time =
fragment->time +
stream->fragment_repetition_index * fragment->duration;
else {
/* always stops on the last one */
GstMssStreamFragment *last_fragment = iter->data;
*final_time =
last_fragment->time +
last_fragment->repetitions * last_fragment->duration;
if (fragment) {
*final_time = gst_util_uint64_scale_round (fragment->time +
stream->fragment_repetition_index * fragment->duration,
GST_SECOND, timescale);
} else {
GstMssStreamFragment *last_fragment = g_list_last (iter)->data;
*final_time = gst_util_uint64_scale_round (last_fragment->time +
last_fragment->repetitions * last_fragment->duration,
GST_SECOND, timescale);
}
}
}
@ -1214,7 +1230,9 @@ gst_mss_stream_reload_fragments (GstMssStream * stream, xmlNodePtr streamIndex)
g_list_free_full (stream->fragments, g_free);
stream->fragments = g_list_reverse (builder.fragments);
stream->current_fragment = stream->fragments;
gst_mss_stream_seek (stream, 0, current_gst_time, NULL);
/* TODO Verify how repositioning here works for reverse
* playback - it might start from the wrong fragment */
gst_mss_stream_seek (stream, TRUE, 0, current_gst_time, NULL);
}
}

View file

@ -44,7 +44,7 @@ GSList * gst_mss_manifest_get_streams (GstMssManifest * manifest);
guint64 gst_mss_manifest_get_timescale (GstMssManifest * manifest);
guint64 gst_mss_manifest_get_duration (GstMssManifest * manifest);
GstClockTime gst_mss_manifest_get_gst_duration (GstMssManifest * manifest);
void gst_mss_manifest_seek (GstMssManifest * manifest, guint64 time);
void gst_mss_manifest_seek (GstMssManifest * manifest, gboolean forward, guint64 time);
gboolean gst_mss_manifest_change_bitrate (GstMssManifest *manifest, guint64 bitrate);
guint64 gst_mss_manifest_get_current_bitrate (GstMssManifest * manifest);
gboolean gst_mss_manifest_is_live (GstMssManifest * manifest);
@ -67,7 +67,7 @@ GstClockTime gst_mss_stream_get_fragment_gst_duration (GstMssStream * stream);
gboolean gst_mss_stream_has_next_fragment (GstMssStream * stream);
GstFlowReturn gst_mss_stream_advance_fragment (GstMssStream * stream);
GstFlowReturn gst_mss_stream_regress_fragment (GstMssStream * stream);
void gst_mss_stream_seek (GstMssStream * stream, GstSeekFlags flags, guint64 time, guint64 * final_time);
void gst_mss_stream_seek (GstMssStream * stream, gboolean forward, GstSeekFlags flags, guint64 time, guint64 * final_time);
const gchar * gst_mss_stream_get_lang (GstMssStream * stream);
const gchar * gst_mss_stream_type_name (GstMssStreamType streamtype);