dashdemux: fix seeking on multiple streams

Each stream has its own durations and timestamps, the fragment number
is different for each stream when seeking, so the seek has to be done
for all streams, rather than on a single stream and propagated to
others
This commit is contained in:
Thiago Santos 2013-01-28 19:43:46 -03:00
parent 7330225ac8
commit 80c6973319
3 changed files with 46 additions and 50 deletions

View file

@ -531,10 +531,9 @@ gst_dash_demux_src_event (GstPad * pad, GstEvent * event)
GList *list;
GstClockTime current_pos, target_pos;
guint current_sequence, current_period;
GstActiveStream *stream;
GstActiveStream *active_stream;
GstMediaSegment *chunk;
GstStreamPeriod *period;
guint nb_active_stream;
GSList *iter;
GST_WARNING_OBJECT (demux, "Received seek event");
@ -555,6 +554,26 @@ gst_dash_demux_src_event (GstPad * pad, GstEvent * event)
GST_TIME_FORMAT, rate, start_type, GST_TIME_ARGS (start),
GST_TIME_ARGS (stop));
if (flags & GST_SEEK_FLAG_FLUSH) {
GST_DEBUG_OBJECT (demux, "sending flush start");
for (iter = demux->streams; iter; iter = g_slist_next (iter)) {
GstDashDemuxStream *stream;
stream = iter->data;
gst_pad_push_event (stream->pad, gst_event_new_flush_start ());
}
}
/* Stop the demux */
demux->cancelled = TRUE;
gst_dash_demux_stop (demux);
/* Wait for streaming to finish */
g_static_rec_mutex_lock (&demux->stream_lock);
/* Clear the buffering queue */
/* FIXME: allow seeking in the buffering queue */
gst_dash_demux_clear_queues (demux);
//GST_MPD_CLIENT_LOCK (demux->client);
/* select the requested Period in the Media Presentation */
@ -582,57 +601,35 @@ gst_dash_demux_src_event (GstPad * pad, GstEvent * event)
return FALSE;
}
stream = gst_mpdparser_get_active_stream_by_index (demux->client, 0);
current_pos = 0;
current_sequence = 0;
for (list = g_list_first (stream->segments); list;
list = g_list_next (list)) {
chunk = list->data;
current_pos = chunk->start_time;
//current_sequence = chunk->number;
GST_WARNING_OBJECT (demux, "%llu <= %llu (%llu)", current_pos,
target_pos, chunk->duration);
if (current_pos <= target_pos
&& target_pos < current_pos + chunk->duration) {
break;
}
current_sequence++;
}
//GST_MPD_CLIENT_UNLOCK (demux->client);
if (list == NULL) {
GST_WARNING_OBJECT (demux, "Could not find seeked fragment");
return FALSE;
}
/* We can actually perform the seek */
nb_active_stream = gst_mpdparser_get_nb_active_stream (demux->client);
if (flags & GST_SEEK_FLAG_FLUSH) {
GST_DEBUG_OBJECT (demux, "sending flush start");
for (iter = demux->streams; iter; iter = g_slist_next (iter)) {
GstDashDemuxStream *stream;
stream = iter->data;
gst_pad_push_event (stream->pad, gst_event_new_flush_start ());
}
}
/* Stop the demux */
demux->cancelled = TRUE;
gst_dash_demux_stop (demux);
/* Wait for streaming to finish */
g_static_rec_mutex_lock (&demux->stream_lock);
/* Clear the buffering queue */
/* FIXME: allow seeking in the buffering queue */
gst_dash_demux_clear_queues (demux);
//GST_MPD_CLIENT_LOCK (demux->client);
GST_DEBUG_OBJECT (demux, "Seeking to sequence %d", current_sequence);
/* Update the current sequence on all streams */
gst_mpd_client_set_segment_index_for_all_streams (demux->client,
current_sequence);
for (iter = demux->streams; iter; iter = g_slist_next (iter)) {
GstDashDemuxStream *stream = iter->data;
active_stream =
gst_mpdparser_get_active_stream_by_index (demux->client,
stream->index);
current_pos = 0;
current_sequence = 0;
for (list = g_list_first (active_stream->segments); list;
list = g_list_next (list)) {
chunk = list->data;
current_pos = chunk->start_time;
//current_sequence = chunk->number;
GST_WARNING_OBJECT (demux, "%llu <= %llu (%llu)", current_pos,
target_pos, chunk->duration);
if (current_pos <= target_pos
&& target_pos < current_pos + chunk->duration) {
break;
}
current_sequence++;
}
gst_mpd_client_set_segment_index (active_stream, current_sequence);
}
/* Calculate offset in the next fragment */
demux->position = gst_mpd_client_get_current_position (demux->client);
demux->position_shift = start - demux->position;

View file

@ -127,8 +127,6 @@ static gboolean gst_mpd_client_add_media_segment (GstActiveStream * stream,
GstClockTime start_time, GstClockTime duration);
static const gchar *gst_mpdparser_mimetype_to_caps (const gchar * mimeType);
static GstClockTime gst_mpd_client_get_segment_duration (GstMpdClient * client);
static void gst_mpd_client_set_segment_index (GstActiveStream * stream,
guint segment_idx);
/* Adaptation Set */
static GstAdaptationSetNode
@ -3338,7 +3336,7 @@ gst_mpd_client_set_segment_index_for_all_streams (GstMpdClient * client,
}
}
static void
void
gst_mpd_client_set_segment_index (GstActiveStream * stream, guint segment_idx)
{
g_return_if_fail (stream != NULL);

View file

@ -496,6 +496,7 @@ guint gst_mpdparser_get_nb_adaptationSet (GstMpdClient *client);
/* Segment */
void gst_mpd_client_set_segment_index_for_all_streams (GstMpdClient * client, guint segment_idx);
guint gst_mpd_client_get_segment_index (GstActiveStream * stream);
void gst_mpd_client_set_segment_index (GstActiveStream * stream, guint segment_idx);
/* Get audio/video stream parameters (mimeType, width, height, rate, number of channels) */
const gchar *gst_mpd_client_get_stream_mimeType (GstActiveStream * stream);