mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-05 06:58:56 +00:00
dashdemux: track segments in the demuxer
Use a GstSegment to track the current segment information in the demuxer.
This commit is contained in:
parent
39924c60a1
commit
dbd6bde9d1
2 changed files with 107 additions and 96 deletions
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue