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; 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; 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 * Seeks all streams to the fragment that contains the set time
* *
* @forward: if this is forward playback
* @time: time in nanoseconds * @time: time in nanoseconds
*/ */
void void
gst_mss_manifest_seek (GstMssManifest * manifest, guint64 time) gst_mss_manifest_seek (GstMssManifest * manifest, gboolean forward,
guint64 time)
{ {
GSList *iter; GSList *iter;
for (iter = manifest->streams; iter; iter = g_slist_next (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 * Seeks this stream to the fragment that contains the sample at time
* *
* @time: time in nanoseconds * @time: time in nanoseconds
*/ */
void void
gst_mss_stream_seek (GstMssStream * stream, GstSeekFlags flags, guint64 time, gst_mss_stream_seek (GstMssStream * stream, gboolean forward,
guint64 * final_time) GstSeekFlags flags, guint64 time, guint64 * final_time)
{ {
GList *iter; GList *iter;
guint64 timescale; 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); time = gst_util_uint64_scale_round (time, timescale, GST_SECOND);
GST_DEBUG ("Stream %s seeking to %" G_GUINT64_FORMAT, stream->url, time); GST_DEBUG ("Stream %s seeking to %" G_GUINT64_FORMAT, stream->url, time);
for (iter = stream->fragments; iter; iter = g_list_next (iter)) { for (iter = stream->fragments; iter; iter = g_list_next (iter)) {
GList *next = g_list_next (iter); fragment = iter->data;
if (next) { if (fragment->time + fragment->repetitions * fragment->duration > time) {
fragment = next->data; stream->current_fragment = iter;
stream->fragment_repetition_index =
(time - fragment->time) / fragment->duration;
if (((time - fragment->time) % fragment->duration) == 0) {
if (fragment->time > time) { /* for reverse playback, start from the previous fragment when we are
stream->current_fragment = iter; * exactly at a limit */
break; if (!forward)
} stream->fragment_repetition_index--;
} else { } else if (SNAP_AFTER (forward, flags))
fragment = iter->data; stream->fragment_repetition_index++;
if (fragment->time + fragment->repetitions * fragment->duration > time) {
stream->current_fragment = iter; if (stream->fragment_repetition_index == fragment->repetitions) {
} else { /* move to the next one */
stream->current_fragment = NULL; /* EOS */ 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; 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 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); stream->fragment_repetition_index);
if (final_time) { if (final_time) {
if (fragment) if (fragment) {
*final_time = *final_time = gst_util_uint64_scale_round (fragment->time +
fragment->time + stream->fragment_repetition_index * fragment->duration,
stream->fragment_repetition_index * fragment->duration; GST_SECOND, timescale);
else { } else {
/* always stops on the last one */ GstMssStreamFragment *last_fragment = g_list_last (iter)->data;
GstMssStreamFragment *last_fragment = iter->data; *final_time = gst_util_uint64_scale_round (last_fragment->time +
*final_time = last_fragment->repetitions * last_fragment->duration,
last_fragment->time + GST_SECOND, timescale);
last_fragment->repetitions * last_fragment->duration;
} }
} }
} }
@ -1214,7 +1230,9 @@ gst_mss_stream_reload_fragments (GstMssStream * stream, xmlNodePtr streamIndex)
g_list_free_full (stream->fragments, g_free); g_list_free_full (stream->fragments, g_free);
stream->fragments = g_list_reverse (builder.fragments); stream->fragments = g_list_reverse (builder.fragments);
stream->current_fragment = stream->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_timescale (GstMssManifest * manifest);
guint64 gst_mss_manifest_get_duration (GstMssManifest * manifest); guint64 gst_mss_manifest_get_duration (GstMssManifest * manifest);
GstClockTime gst_mss_manifest_get_gst_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); gboolean gst_mss_manifest_change_bitrate (GstMssManifest *manifest, guint64 bitrate);
guint64 gst_mss_manifest_get_current_bitrate (GstMssManifest * manifest); guint64 gst_mss_manifest_get_current_bitrate (GstMssManifest * manifest);
gboolean gst_mss_manifest_is_live (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); gboolean gst_mss_stream_has_next_fragment (GstMssStream * stream);
GstFlowReturn gst_mss_stream_advance_fragment (GstMssStream * stream); GstFlowReturn gst_mss_stream_advance_fragment (GstMssStream * stream);
GstFlowReturn gst_mss_stream_regress_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_get_lang (GstMssStream * stream);
const gchar * gst_mss_stream_type_name (GstMssStreamType streamtype); const gchar * gst_mss_stream_type_name (GstMssStreamType streamtype);