mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-24 02:31:03 +00:00
dashdemux: Properly keep track of current offset
GstAdapter does not guarantee to pass through all the offsets, we have to keep track of it ourselves. https://bugzilla.gnome.org/show_bug.cgi?id=764684
This commit is contained in:
parent
8344854c4c
commit
9374643089
2 changed files with 80 additions and 19 deletions
|
@ -254,6 +254,9 @@ static void gst_dash_demux_advance_period (GstAdaptiveDemux * demux);
|
||||||
static gboolean gst_dash_demux_has_next_period (GstAdaptiveDemux * demux);
|
static gboolean gst_dash_demux_has_next_period (GstAdaptiveDemux * demux);
|
||||||
static GstFlowReturn gst_dash_demux_data_received (GstAdaptiveDemux * demux,
|
static GstFlowReturn gst_dash_demux_data_received (GstAdaptiveDemux * demux,
|
||||||
GstAdaptiveDemuxStream * stream, GstBuffer * buffer);
|
GstAdaptiveDemuxStream * stream, GstBuffer * buffer);
|
||||||
|
static gboolean
|
||||||
|
gst_dash_demux_stream_fragment_start (GstAdaptiveDemux * demux,
|
||||||
|
GstAdaptiveDemuxStream * stream);
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_dash_demux_stream_fragment_finished (GstAdaptiveDemux * demux,
|
gst_dash_demux_stream_fragment_finished (GstAdaptiveDemux * demux,
|
||||||
GstAdaptiveDemuxStream * stream);
|
GstAdaptiveDemuxStream * stream);
|
||||||
|
@ -454,6 +457,7 @@ gst_dash_demux_class_init (GstDashDemuxClass * klass)
|
||||||
gstadaptivedemux_class->get_period_start_time =
|
gstadaptivedemux_class->get_period_start_time =
|
||||||
gst_dash_demux_get_period_start_time;
|
gst_dash_demux_get_period_start_time;
|
||||||
|
|
||||||
|
gstadaptivedemux_class->start_fragment = gst_dash_demux_stream_fragment_start;
|
||||||
gstadaptivedemux_class->finish_fragment =
|
gstadaptivedemux_class->finish_fragment =
|
||||||
gst_dash_demux_stream_fragment_finished;
|
gst_dash_demux_stream_fragment_finished;
|
||||||
gstadaptivedemux_class->data_received = gst_dash_demux_data_received;
|
gstadaptivedemux_class->data_received = gst_dash_demux_data_received;
|
||||||
|
@ -1225,6 +1229,16 @@ gst_dash_demux_stream_has_next_fragment (GstAdaptiveDemuxStream * stream)
|
||||||
dashstream->active_stream, stream->demux->segment.rate > 0.0);
|
dashstream->active_stream, stream->demux->segment.rate > 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_dash_demux_clear_pending_stream_data (GstDashDemux * dashdemux,
|
||||||
|
GstDashDemuxStream * dashstream)
|
||||||
|
{
|
||||||
|
gst_isoff_sidx_parser_clear (&dashstream->sidx_parser);
|
||||||
|
gst_isoff_sidx_parser_init (&dashstream->sidx_parser);
|
||||||
|
if (dashstream->sidx_adapter)
|
||||||
|
gst_adapter_clear (dashstream->sidx_adapter);
|
||||||
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_dash_demux_stream_advance_fragment (GstAdaptiveDemuxStream * stream)
|
gst_dash_demux_stream_advance_fragment (GstAdaptiveDemuxStream * stream)
|
||||||
{
|
{
|
||||||
|
@ -1238,6 +1252,8 @@ gst_dash_demux_stream_advance_fragment (GstAdaptiveDemuxStream * stream)
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gst_dash_demux_clear_pending_stream_data (dashdemux, dashstream);
|
||||||
|
|
||||||
return gst_mpd_client_advance_segment (dashdemux->client,
|
return gst_mpd_client_advance_segment (dashdemux->client,
|
||||||
dashstream->active_stream, stream->demux->segment.rate > 0.0);
|
dashstream->active_stream, stream->demux->segment.rate > 0.0);
|
||||||
}
|
}
|
||||||
|
@ -1293,17 +1309,13 @@ gst_dash_demux_stream_select_bitrate (GstAdaptiveDemuxStream * stream,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gst_mpd_client_has_isoff_ondemand_profile (demux->client)) {
|
if (ret) {
|
||||||
|
gst_dash_demux_clear_pending_stream_data (demux, dashstream);
|
||||||
|
|
||||||
/* store our current position to change to the same one in a different
|
if (gst_mpd_client_has_isoff_ondemand_profile (demux->client)) {
|
||||||
* representation if needed */
|
/* store our current position to change to the same one in a different
|
||||||
dashstream->sidx_index = SIDX (dashstream)->entry_index;
|
* representation if needed */
|
||||||
if (ret) {
|
dashstream->sidx_index = SIDX (dashstream)->entry_index;
|
||||||
/* TODO cache indexes to avoid re-downloading and parsing */
|
|
||||||
/* if we switched, we need a new index */
|
|
||||||
gst_isoff_sidx_parser_clear (&dashstream->sidx_parser);
|
|
||||||
gst_isoff_sidx_parser_init (&dashstream->sidx_parser);
|
|
||||||
gst_adapter_clear (dashstream->sidx_adapter);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1389,10 +1401,7 @@ gst_dash_demux_seek (GstAdaptiveDemux * demux, GstEvent * seek)
|
||||||
GstDashDemuxStream *dashstream = iter->data;
|
GstDashDemuxStream *dashstream = iter->data;
|
||||||
|
|
||||||
if (flags & GST_SEEK_FLAG_FLUSH) {
|
if (flags & GST_SEEK_FLAG_FLUSH) {
|
||||||
gst_isoff_sidx_parser_clear (&dashstream->sidx_parser);
|
gst_dash_demux_clear_pending_stream_data (dashdemux, dashstream);
|
||||||
gst_isoff_sidx_parser_init (&dashstream->sidx_parser);
|
|
||||||
if (dashstream->sidx_adapter)
|
|
||||||
gst_adapter_clear (dashstream->sidx_adapter);
|
|
||||||
}
|
}
|
||||||
gst_dash_demux_stream_seek (iter->data, rate >= 0, 0, target_pos, NULL);
|
gst_dash_demux_stream_seek (iter->data, rate >= 0, 0, target_pos, NULL);
|
||||||
}
|
}
|
||||||
|
@ -1612,6 +1621,18 @@ _gst_buffer_split (GstBuffer * buffer, gint offset, gsize size)
|
||||||
return newbuf;
|
return newbuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_dash_demux_stream_fragment_start (GstAdaptiveDemux * demux,
|
||||||
|
GstAdaptiveDemuxStream * stream)
|
||||||
|
{
|
||||||
|
GstDashDemuxStream *dashstream = (GstDashDemuxStream *) stream;
|
||||||
|
|
||||||
|
dashstream->sidx_index_header_or_data = 0;
|
||||||
|
dashstream->sidx_current_offset = -1;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_dash_demux_stream_fragment_finished (GstAdaptiveDemux * demux,
|
gst_dash_demux_stream_fragment_finished (GstAdaptiveDemux * demux,
|
||||||
GstAdaptiveDemuxStream * stream)
|
GstAdaptiveDemuxStream * stream)
|
||||||
|
@ -1641,10 +1662,32 @@ gst_dash_demux_data_received (GstAdaptiveDemux * demux,
|
||||||
GstDashDemuxStream *dash_stream = (GstDashDemuxStream *) stream;
|
GstDashDemuxStream *dash_stream = (GstDashDemuxStream *) stream;
|
||||||
GstDashDemux *dashdemux = GST_DASH_DEMUX_CAST (demux);
|
GstDashDemux *dashdemux = GST_DASH_DEMUX_CAST (demux);
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
|
guint index_header_or_data;
|
||||||
|
|
||||||
if (!gst_mpd_client_has_isoff_ondemand_profile (dashdemux->client))
|
if (!gst_mpd_client_has_isoff_ondemand_profile (dashdemux->client))
|
||||||
return gst_adaptive_demux_stream_push_buffer (stream, buffer);
|
return gst_adaptive_demux_stream_push_buffer (stream, buffer);
|
||||||
|
|
||||||
|
if (stream->downloading_index)
|
||||||
|
index_header_or_data = 1;
|
||||||
|
else if (stream->downloading_header)
|
||||||
|
index_header_or_data = 2;
|
||||||
|
else
|
||||||
|
index_header_or_data = 3;
|
||||||
|
|
||||||
|
if (dash_stream->sidx_index_header_or_data != index_header_or_data) {
|
||||||
|
/* Clear pending data */
|
||||||
|
if (gst_adapter_available (dash_stream->sidx_adapter) != 0)
|
||||||
|
GST_ERROR_OBJECT (stream->pad,
|
||||||
|
"Had pending SIDX data after switch between index/header/data");
|
||||||
|
gst_adapter_clear (dash_stream->sidx_adapter);
|
||||||
|
dash_stream->sidx_index_header_or_data = index_header_or_data;
|
||||||
|
dash_stream->sidx_current_offset = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dash_stream->sidx_current_offset == -1)
|
||||||
|
dash_stream->sidx_current_offset =
|
||||||
|
GST_BUFFER_OFFSET_IS_VALID (buffer) ? GST_BUFFER_OFFSET (buffer) : 0;
|
||||||
|
|
||||||
gst_adapter_push (dash_stream->sidx_adapter, buffer);
|
gst_adapter_push (dash_stream->sidx_adapter, buffer);
|
||||||
buffer = NULL;
|
buffer = NULL;
|
||||||
|
|
||||||
|
@ -1687,12 +1730,17 @@ gst_dash_demux_data_received (GstAdaptiveDemux * demux,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
GST_BUFFER_OFFSET (buffer) = dash_stream->sidx_current_offset;
|
||||||
|
GST_BUFFER_OFFSET_END (buffer) =
|
||||||
|
GST_BUFFER_OFFSET (buffer) + gst_buffer_get_size (buffer);
|
||||||
|
dash_stream->sidx_current_offset = GST_BUFFER_OFFSET_END (buffer);
|
||||||
ret = gst_adaptive_demux_stream_push_buffer (stream, buffer);
|
ret = gst_adaptive_demux_stream_push_buffer (stream, buffer);
|
||||||
} else if (dash_stream->sidx_parser.status == GST_ISOFF_SIDX_PARSER_FINISHED) {
|
} else if (dash_stream->sidx_parser.status == GST_ISOFF_SIDX_PARSER_FINISHED) {
|
||||||
gsize available;
|
gsize available;
|
||||||
|
|
||||||
while (ret == GST_FLOW_OK
|
while (ret == GST_FLOW_OK
|
||||||
&& ((available = gst_adapter_available (dash_stream->sidx_adapter)) > 0)) {
|
&& ((available =
|
||||||
|
gst_adapter_available (dash_stream->sidx_adapter)) > 0)) {
|
||||||
gboolean advance = FALSE;
|
gboolean advance = FALSE;
|
||||||
|
|
||||||
if (available < dash_stream->sidx_current_remaining) {
|
if (available < dash_stream->sidx_current_remaining) {
|
||||||
|
@ -1705,6 +1753,10 @@ gst_dash_demux_data_received (GstAdaptiveDemux * demux,
|
||||||
dash_stream->sidx_current_remaining = 0;
|
dash_stream->sidx_current_remaining = 0;
|
||||||
advance = TRUE;
|
advance = TRUE;
|
||||||
}
|
}
|
||||||
|
GST_BUFFER_OFFSET (buffer) = dash_stream->sidx_current_offset;
|
||||||
|
GST_BUFFER_OFFSET_END (buffer) =
|
||||||
|
GST_BUFFER_OFFSET (buffer) + gst_buffer_get_size (buffer);
|
||||||
|
dash_stream->sidx_current_offset = GST_BUFFER_OFFSET_END (buffer);
|
||||||
ret = gst_adaptive_demux_stream_push_buffer (stream, buffer);
|
ret = gst_adaptive_demux_stream_push_buffer (stream, buffer);
|
||||||
if (advance) {
|
if (advance) {
|
||||||
GstFlowReturn new_ret;
|
GstFlowReturn new_ret;
|
||||||
|
@ -1719,10 +1771,15 @@ gst_dash_demux_data_received (GstAdaptiveDemux * demux,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* this should be the main header, just push it all */
|
/* this should be the main header, just push it all */
|
||||||
ret =
|
buffer = gst_adapter_take_buffer (dash_stream->sidx_adapter,
|
||||||
gst_adaptive_demux_stream_push_buffer (stream,
|
gst_adapter_available (dash_stream->sidx_adapter));
|
||||||
gst_adapter_take_buffer (dash_stream->sidx_adapter,
|
|
||||||
gst_adapter_available (dash_stream->sidx_adapter)));
|
GST_BUFFER_OFFSET (buffer) = dash_stream->sidx_current_offset;
|
||||||
|
GST_BUFFER_OFFSET_END (buffer) =
|
||||||
|
GST_BUFFER_OFFSET (buffer) + gst_buffer_get_size (buffer);
|
||||||
|
dash_stream->sidx_current_offset = GST_BUFFER_OFFSET_END (buffer);
|
||||||
|
|
||||||
|
ret = gst_adaptive_demux_stream_push_buffer (stream, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -73,6 +73,10 @@ struct _GstDashDemuxStream
|
||||||
gint sidx_index;
|
gint sidx_index;
|
||||||
gint64 sidx_base_offset;
|
gint64 sidx_base_offset;
|
||||||
GstClockTime pending_seek_ts;
|
GstClockTime pending_seek_ts;
|
||||||
|
/* sidx offset tracking */
|
||||||
|
guint64 sidx_current_offset;
|
||||||
|
/* index = 1, header = 2, data = 3 */
|
||||||
|
guint sidx_index_header_or_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue