dashdemux: track segments in the demuxer

Use a GstSegment to track the current segment information in the
demuxer.
This commit is contained in:
Thiago Santos 2013-02-01 00:37:33 -03:00
parent 39924c60a1
commit dbd6bde9d1
2 changed files with 107 additions and 96 deletions

View file

@ -361,6 +361,8 @@ gst_dash_demux_init (GstDashDemux * demux, GstDashDemuxClass * klass)
GST_DEBUG_FUNCPTR (gst_dash_demux_sink_event)); GST_DEBUG_FUNCPTR (gst_dash_demux_sink_event));
gst_element_add_pad (GST_ELEMENT (demux), demux->sinkpad); gst_element_add_pad (GST_ELEMENT (demux), demux->sinkpad);
gst_segment_init (&demux->segment, GST_FORMAT_TIME);
/* Downloader */ /* Downloader */
demux->downloader = gst_uri_downloader_new (); demux->downloader = gst_uri_downloader_new ();
@ -546,6 +548,7 @@ gst_dash_demux_src_event (GstPad * pad, GstEvent * event)
GstMediaSegment *chunk; GstMediaSegment *chunk;
GstStreamPeriod *period; GstStreamPeriod *period;
GSList *iter; GSList *iter;
gboolean update;
GST_WARNING_OBJECT (demux, "Received seek event"); GST_WARNING_OBJECT (demux, "Received seek event");
@ -565,108 +568,114 @@ gst_dash_demux_src_event (GstPad * pad, GstEvent * event)
GST_TIME_FORMAT, rate, start_type, GST_TIME_ARGS (start), GST_TIME_FORMAT, rate, start_type, GST_TIME_ARGS (start),
GST_TIME_ARGS (stop)); GST_TIME_ARGS (stop));
if (flags & GST_SEEK_FLAG_FLUSH) { gst_segment_set_seek (&demux->segment, rate, format, flags, start_type,
GST_DEBUG_OBJECT (demux, "sending flush start"); start, stop_type, stop, &update);
for (iter = demux->streams; iter; iter = g_slist_next (iter)) {
GstDashDemuxStream *stream; if (update) {
stream = iter->data;
gst_pad_push_event (stream->pad, gst_event_new_flush_start ()); 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 */ /* Stop the demux */
demux->cancelled = TRUE; demux->cancelled = TRUE;
gst_dash_demux_stop (demux); gst_dash_demux_stop (demux);
/* Wait for streaming to finish */ /* Wait for streaming to finish */
g_static_rec_mutex_lock (&demux->stream_lock); g_static_rec_mutex_lock (&demux->stream_lock);
/* Clear the buffering queue */ /* Clear the buffering queue */
/* FIXME: allow seeking in the buffering queue */ /* FIXME: allow seeking in the buffering queue */
gst_dash_demux_clear_queues (demux); gst_dash_demux_clear_queues (demux);
//GST_MPD_CLIENT_LOCK (demux->client); //GST_MPD_CLIENT_LOCK (demux->client);
/* select the requested Period in the Media Presentation */ /* select the requested Period in the Media Presentation */
target_pos = (GstClockTime) start; target_pos = (GstClockTime) demux->segment.start;
current_period = 0; current_period = 0;
for (list = g_list_first (demux->client->periods); list; for (list = g_list_first (demux->client->periods); list;
list = g_list_next (list)) {
period = list->data;
current_pos = period->start;
current_period = period->number;
if (current_pos <= target_pos
&& target_pos < current_pos + period->duration) {
break;
}
}
if (list == NULL) {
GST_WARNING_OBJECT (demux, "Could not find seeked Period");
return FALSE;
}
if (current_period != gst_mpd_client_get_period_index (demux->client)) {
GST_DEBUG_OBJECT (demux, "Seeking to Period %d", current_period);
/* setup video, audio and subtitle streams, starting from the new Period */
if (!gst_mpd_client_set_period_index (demux->client, current_period) ||
!gst_dash_demux_setup_all_streams (demux))
return FALSE;
}
if (list == NULL) {
GST_WARNING_OBJECT (demux, "Could not find seeked fragment");
return FALSE;
}
/* Update the current sequence on all streams */
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)) { list = g_list_next (list)) {
chunk = list->data; period = list->data;
current_pos = chunk->start_time; current_pos = period->start;
//current_sequence = chunk->number; current_period = period->number;
GST_WARNING_OBJECT (demux, "%llu <= %llu (%llu)", current_pos,
target_pos, chunk->duration);
if (current_pos <= target_pos if (current_pos <= target_pos
&& target_pos < current_pos + chunk->duration) { && target_pos < current_pos + period->duration) {
break; break;
} }
current_sequence++;
} }
gst_mpd_client_set_segment_index (active_stream, current_sequence); if (list == NULL) {
} GST_WARNING_OBJECT (demux, "Could not find seeked Period");
/* Calculate offset in the next fragment */ return FALSE;
demux->position = gst_mpd_client_get_current_position (demux->client); }
demux->position_shift = start - demux->position; if (current_period != gst_mpd_client_get_period_index (demux->client)) {
demux->need_segment = TRUE; GST_DEBUG_OBJECT (demux, "Seeking to Period %d", current_period);
//GST_MPD_CLIENT_UNLOCK (demux->client); /* setup video, audio and subtitle streams, starting from the new Period */
if (!gst_mpd_client_set_period_index (demux->client, current_period)
|| !gst_dash_demux_setup_all_streams (demux))
return FALSE;
}
if (flags & GST_SEEK_FLAG_FLUSH) { if (list == NULL) {
GST_DEBUG_OBJECT (demux, "Sending flush stop on all pad"); GST_WARNING_OBJECT (demux, "Could not find seeked fragment");
return FALSE;
}
/* Update the current sequence on all streams */
for (iter = demux->streams; iter; iter = g_slist_next (iter)) { for (iter = demux->streams; iter; iter = g_slist_next (iter)) {
GstDashDemuxStream *stream; GstDashDemuxStream *stream = iter->data;
stream = iter->data; active_stream =
gst_pad_push_event (stream->pad, gst_event_new_flush_stop ()); 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 = demux->segment.start - demux->position;
//GST_MPD_CLIENT_UNLOCK (demux->client);
/* Restart the demux */ if (flags & GST_SEEK_FLAG_FLUSH) {
demux->cancelled = FALSE; GST_DEBUG_OBJECT (demux, "Sending flush stop on all pad");
demux->end_of_manifest = FALSE; for (iter = demux->streams; iter; iter = g_slist_next (iter)) {
for (iter = demux->streams; iter; iter = g_slist_next (iter)) { GstDashDemuxStream *stream;
GstDashDemuxStream *stream = iter->data;
gst_data_queue_set_flushing (stream->queue, FALSE); stream = iter->data;
gst_pad_push_event (stream->pad, gst_event_new_flush_stop ());
}
}
/* Restart the demux */
demux->cancelled = FALSE;
demux->end_of_manifest = FALSE;
for (iter = demux->streams; iter; iter = g_slist_next (iter)) {
GstDashDemuxStream *stream = iter->data;
stream->need_segment = TRUE;
gst_data_queue_set_flushing (stream->queue, FALSE);
}
gst_dash_demux_resume_download_task (demux);
gst_dash_demux_resume_stream_task (demux);
g_static_rec_mutex_unlock (&demux->stream_lock);
} }
gst_dash_demux_resume_download_task (demux);
gst_dash_demux_resume_stream_task (demux);
g_static_rec_mutex_unlock (&demux->stream_lock);
return TRUE; return TRUE;
} }
@ -986,6 +995,7 @@ switch_pads (GstDashDemux * demux)
gst_structure_get (structure, "caps", GST_TYPE_CAPS, &caps, NULL); gst_structure_get (structure, "caps", GST_TYPE_CAPS, &caps, NULL);
g_assert (caps != NULL); g_assert (caps != NULL);
stream->need_segment = TRUE;
stream->pad = gst_pad_new_from_static_template (&srctemplate, NULL); stream->pad = gst_pad_new_from_static_template (&srctemplate, NULL);
gst_pad_set_event_function (stream->pad, gst_pad_set_event_function (stream->pad,
GST_DEBUG_FUNCPTR (gst_dash_demux_src_event)); GST_DEBUG_FUNCPTR (gst_dash_demux_src_event));
@ -1092,7 +1102,6 @@ gst_dash_demux_stream_loop (GstDashDemux * demux)
if (pad_switch) { if (pad_switch) {
switch_pads (demux); switch_pads (demux);
demux->need_segment = TRUE;
goto end; goto end;
} }
@ -1107,20 +1116,17 @@ gst_dash_demux_stream_loop (GstDashDemux * demux)
active_stream = active_stream =
gst_mpdparser_get_active_stream_by_index (demux->client, gst_mpdparser_get_active_stream_by_index (demux->client,
selected_stream->index); selected_stream->index);
if (demux->need_segment) { if (selected_stream->need_segment) {
GstClockTime start =
GST_BUFFER_TIMESTAMP (buffer) + demux->position_shift;
/* And send a newsegment */ /* And send a newsegment */
GST_DEBUG_OBJECT (demux, "Sending new-segment. segment start:%"
GST_TIME_FORMAT, GST_TIME_ARGS (start));
for (iter = demux->streams, i = 0; iter; for (iter = demux->streams, i = 0; iter;
i++, iter = g_slist_next (iter)) { i++, iter = g_slist_next (iter)) {
GstDashDemuxStream *stream = iter->data; GstDashDemuxStream *stream = iter->data;
gst_pad_push_event (stream->pad, gst_pad_push_event (stream->pad,
gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, gst_event_new_new_segment (TRUE, demux->segment.rate,
start, GST_CLOCK_TIME_NONE, start)); GST_FORMAT_TIME, demux->segment.start, demux->segment.stop,
0));
} }
demux->need_segment = FALSE; selected_stream->need_segment = FALSE;
demux->position_shift = 0; demux->position_shift = 0;
} }
@ -1130,6 +1136,8 @@ gst_dash_demux_stream_loop (GstDashDemux * demux)
selected_stream->index, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)), selected_stream->index, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
GST_TIME_ARGS (GST_BUFFER_DURATION (buffer))); GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)));
ret = gst_pad_push (selected_stream->pad, gst_buffer_ref (buffer)); ret = gst_pad_push (selected_stream->pad, gst_buffer_ref (buffer));
gst_segment_set_last_stop (&demux->segment, GST_FORMAT_TIME,
GST_BUFFER_TIMESTAMP (buffer));
item->destroy (item); item->destroy (item);
if ((ret != GST_FLOW_OK) && (active_stream if ((ret != GST_FLOW_OK) && (active_stream
&& active_stream->mimeType == GST_STREAM_VIDEO)) && active_stream->mimeType == GST_STREAM_VIDEO))
@ -1227,10 +1235,10 @@ gst_dash_demux_reset (GstDashDemux * demux, gboolean dispose)
demux->client = gst_mpd_client_new (); demux->client = gst_mpd_client_new ();
} }
gst_segment_init (&demux->segment, GST_FORMAT_TIME);
demux->last_manifest_update = GST_CLOCK_TIME_NONE; demux->last_manifest_update = GST_CLOCK_TIME_NONE;
demux->position = 0; demux->position = 0;
demux->position_shift = 0; demux->position_shift = 0;
demux->need_segment = TRUE;
} }
static GstClockTime static GstClockTime

View file

@ -81,6 +81,8 @@ struct _GstDashDemuxStream
gboolean need_header; gboolean need_header;
gboolean need_segment;
GstDataQueue *queue; GstDataQueue *queue;
}; };
@ -96,6 +98,8 @@ struct _GstDashDemux
GSList *streams; GSList *streams;
GstSegment segment;
GstBuffer *manifest; GstBuffer *manifest;
GstUriDownloader *downloader; GstUriDownloader *downloader;
GstMpdClient *client; /* MPD client */ GstMpdClient *client; /* MPD client */
@ -125,7 +129,6 @@ struct _GstDashDemux
GstClockTime position; GstClockTime position;
GstClockTime position_shift; GstClockTime position_shift;
GstClockTime last_position_shift; GstClockTime last_position_shift;
gboolean need_segment;
/* Download rate */ /* Download rate */
guint64 dnl_rate; guint64 dnl_rate;
}; };