mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-30 13:41:48 +00:00
dashdemux: Fix snap SIDX seeking and report if we're going outside the index
Instead of just going to the first or last fragment, report if we're going outside the index. This should never happen unless there's a bug or the stream is broken. Allow some possibility for inaccuracies here though.
This commit is contained in:
parent
b1434d1f1c
commit
ffa63c5933
1 changed files with 59 additions and 54 deletions
|
@ -1247,7 +1247,7 @@ gst_dash_demux_index_entry_search (GstSidxBoxEntry * entry, GstClockTime * ts,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static GstFlowReturn
|
||||||
gst_dash_demux_stream_sidx_seek (GstDashDemuxStream * dashstream,
|
gst_dash_demux_stream_sidx_seek (GstDashDemuxStream * dashstream,
|
||||||
gboolean forward, GstSeekFlags flags, GstClockTime ts,
|
gboolean forward, GstSeekFlags flags, GstClockTime ts,
|
||||||
GstClockTime * final_ts)
|
GstClockTime * final_ts)
|
||||||
|
@ -1255,56 +1255,64 @@ gst_dash_demux_stream_sidx_seek (GstDashDemuxStream * dashstream,
|
||||||
GstSidxBox *sidx = SIDX (dashstream);
|
GstSidxBox *sidx = SIDX (dashstream);
|
||||||
GstSidxBoxEntry *entry;
|
GstSidxBoxEntry *entry;
|
||||||
gint idx = sidx->entries_count;
|
gint idx = sidx->entries_count;
|
||||||
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
|
|
||||||
/* check whether ts is already past the last element or not */
|
if (sidx->entries_count == 0)
|
||||||
if (sidx->entries[idx - 1].pts + sidx->entries[idx - 1].duration >= ts) {
|
return GST_FLOW_EOS;
|
||||||
GstSearchMode mode = GST_SEARCH_MODE_BEFORE;
|
|
||||||
|
|
||||||
if ((flags & GST_SEEK_FLAG_SNAP_NEAREST) == GST_SEEK_FLAG_SNAP_NEAREST) {
|
|
||||||
mode = GST_SEARCH_MODE_BEFORE;
|
|
||||||
} else if ((forward && (flags & GST_SEEK_FLAG_SNAP_AFTER)) ||
|
|
||||||
(!forward && (flags & GST_SEEK_FLAG_SNAP_BEFORE))) {
|
|
||||||
mode = GST_SEARCH_MODE_AFTER;
|
|
||||||
} else {
|
|
||||||
mode = GST_SEARCH_MODE_BEFORE;
|
|
||||||
}
|
|
||||||
|
|
||||||
entry =
|
entry =
|
||||||
gst_util_array_binary_search (sidx->entries, sidx->entries_count,
|
gst_util_array_binary_search (sidx->entries, sidx->entries_count,
|
||||||
sizeof (GstSidxBoxEntry),
|
sizeof (GstSidxBoxEntry),
|
||||||
(GCompareDataFunc) gst_dash_demux_index_entry_search, mode, &ts, NULL);
|
(GCompareDataFunc) gst_dash_demux_index_entry_search,
|
||||||
|
GST_SEARCH_MODE_EXACT, &ts, NULL);
|
||||||
|
|
||||||
if (entry) {
|
/* No exact match found, nothing in our index
|
||||||
idx = entry - sidx->entries;
|
* This is usually a bug or broken stream, as the seeking code already
|
||||||
} else if (mode == GST_SEARCH_MODE_BEFORE) {
|
* makes sure that we're in the correct period and segment, and only need
|
||||||
/* target ts is smaller than pts of the first entry */
|
* to find the correct place inside the segment. Allow for some rounding
|
||||||
idx = 0;
|
* errors and inaccuracies here though */
|
||||||
} else {
|
if (!entry) {
|
||||||
/* target ts is larger than pts + duration of the last entry
|
GstSidxBoxEntry *last_entry = &sidx->entries[sidx->entries_count - 1];
|
||||||
* idx = sidx->entries_count */
|
|
||||||
|
GST_WARNING_OBJECT (dashstream->parent.pad, "Couldn't find SIDX entry");
|
||||||
|
|
||||||
|
if (ts < sidx->entries[0].pts
|
||||||
|
&& ts + 250 * GST_MSECOND >= sidx->entries[0].pts)
|
||||||
|
entry = &sidx->entries[0];
|
||||||
|
else if (ts >= last_entry->pts + last_entry->duration &&
|
||||||
|
ts < last_entry->pts + last_entry->duration + 250 * GST_MSECOND)
|
||||||
|
entry = last_entry;
|
||||||
}
|
}
|
||||||
|
if (!entry)
|
||||||
|
return GST_FLOW_EOS;
|
||||||
|
|
||||||
|
idx = entry - sidx->entries;
|
||||||
|
|
||||||
/* FIXME in reverse mode, if we are exactly at a fragment start it makes more
|
/* FIXME in reverse mode, if we are exactly at a fragment start it makes more
|
||||||
* sense to start from the end of the previous fragment */
|
* sense to start from the end of the previous fragment */
|
||||||
/* FIXME we should have a GST_SEARCH_MODE_NEAREST */
|
|
||||||
if ((flags & GST_SEEK_FLAG_SNAP_NEAREST) == GST_SEEK_FLAG_SNAP_NEAREST &&
|
/* Now entry->pts <= ts < entry->pts + entry->duration, need to adjust for
|
||||||
idx + 1 < sidx->entries_count) {
|
* snapping */
|
||||||
if (ABS (sidx->entries[idx + 1].pts - ts) <
|
if ((flags & GST_SEEK_FLAG_SNAP_NEAREST) == GST_SEEK_FLAG_SNAP_NEAREST) {
|
||||||
|
if (idx + 1 < sidx->entries_count
|
||||||
|
&& ABS (sidx->entries[idx + 1].pts - ts) <
|
||||||
ABS (sidx->entries[idx].pts - ts))
|
ABS (sidx->entries[idx].pts - ts))
|
||||||
idx += 1;
|
idx += 1;
|
||||||
|
} else if ((forward && (flags & GST_SEEK_FLAG_SNAP_AFTER)) || (!forward
|
||||||
|
&& (flags & GST_SEEK_FLAG_SNAP_BEFORE))) {
|
||||||
|
if (idx + 1 < sidx->entries_count && entry->pts < ts)
|
||||||
|
idx += 1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
g_assert (sidx->entry_index < sidx->entries_count);
|
||||||
|
|
||||||
sidx->entry_index = idx;
|
sidx->entry_index = idx;
|
||||||
if (idx == sidx->entries_count)
|
|
||||||
dashstream->sidx_position =
|
|
||||||
sidx->entries[idx - 1].pts + sidx->entries[idx - 1].duration;
|
|
||||||
else
|
|
||||||
dashstream->sidx_position = sidx->entries[idx].pts;
|
dashstream->sidx_position = sidx->entries[idx].pts;
|
||||||
|
|
||||||
if (final_ts) {
|
if (final_ts)
|
||||||
*final_ts = dashstream->sidx_position;
|
*final_ts = dashstream->sidx_position;
|
||||||
}
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
|
@ -1343,13 +1351,13 @@ gst_dash_demux_stream_seek (GstAdaptiveDemuxStream * stream, gboolean forward,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dashstream->sidx_parser.status == GST_ISOFF_SIDX_PARSER_FINISHED) {
|
if (dashstream->sidx_parser.status == GST_ISOFF_SIDX_PARSER_FINISHED) {
|
||||||
gst_dash_demux_stream_sidx_seek (dashstream, forward, flags, ts,
|
if (gst_dash_demux_stream_sidx_seek (dashstream, forward, flags, ts,
|
||||||
final_ts);
|
final_ts) != GST_FLOW_OK) {
|
||||||
if (SIDX (dashstream)->entry_index >= SIDX (dashstream)->entries_count) {
|
|
||||||
GST_ERROR_OBJECT (stream->pad, "Couldn't find position in sidx");
|
GST_ERROR_OBJECT (stream->pad, "Couldn't find position in sidx");
|
||||||
dashstream->sidx_position = GST_CLOCK_TIME_NONE;
|
dashstream->sidx_position = GST_CLOCK_TIME_NONE;
|
||||||
gst_isoff_sidx_parser_clear (&dashstream->sidx_parser);
|
gst_isoff_sidx_parser_clear (&dashstream->sidx_parser);
|
||||||
}
|
}
|
||||||
|
dashstream->pending_seek_ts = GST_CLOCK_TIME_NONE;
|
||||||
} else {
|
} else {
|
||||||
/* no index yet, seek when we have it */
|
/* no index yet, seek when we have it */
|
||||||
/* FIXME - the final_ts won't be correct here */
|
/* FIXME - the final_ts won't be correct here */
|
||||||
|
@ -2282,10 +2290,9 @@ gst_dash_demux_parse_isobmff (GstAdaptiveDemux * demux,
|
||||||
|
|
||||||
if (GST_CLOCK_TIME_IS_VALID (dash_stream->pending_seek_ts)) {
|
if (GST_CLOCK_TIME_IS_VALID (dash_stream->pending_seek_ts)) {
|
||||||
/* FIXME, preserve seek flags */
|
/* FIXME, preserve seek flags */
|
||||||
gst_dash_demux_stream_sidx_seek (dash_stream,
|
if (gst_dash_demux_stream_sidx_seek (dash_stream,
|
||||||
demux->segment.rate >= 0, 0, dash_stream->pending_seek_ts, NULL);
|
demux->segment.rate >= 0, 0, dash_stream->pending_seek_ts,
|
||||||
if (SIDX (dash_stream)->entry_index >=
|
NULL) != GST_FLOW_OK) {
|
||||||
SIDX (dash_stream)->entries_count) {
|
|
||||||
GST_ERROR_OBJECT (stream->pad, "Couldn't find position in sidx");
|
GST_ERROR_OBJECT (stream->pad, "Couldn't find position in sidx");
|
||||||
dash_stream->sidx_position = GST_CLOCK_TIME_NONE;
|
dash_stream->sidx_position = GST_CLOCK_TIME_NONE;
|
||||||
gst_isoff_sidx_parser_clear (&dash_stream->sidx_parser);
|
gst_isoff_sidx_parser_clear (&dash_stream->sidx_parser);
|
||||||
|
@ -2764,16 +2771,14 @@ gst_dash_demux_data_received (GstAdaptiveDemux * demux,
|
||||||
if (dash_stream->sidx_parser.status == GST_ISOFF_SIDX_PARSER_FINISHED) {
|
if (dash_stream->sidx_parser.status == GST_ISOFF_SIDX_PARSER_FINISHED) {
|
||||||
if (GST_CLOCK_TIME_IS_VALID (dash_stream->pending_seek_ts)) {
|
if (GST_CLOCK_TIME_IS_VALID (dash_stream->pending_seek_ts)) {
|
||||||
/* FIXME, preserve seek flags */
|
/* FIXME, preserve seek flags */
|
||||||
gst_dash_demux_stream_sidx_seek (dash_stream,
|
if (gst_dash_demux_stream_sidx_seek (dash_stream,
|
||||||
demux->segment.rate >= 0, 0, dash_stream->pending_seek_ts,
|
demux->segment.rate >= 0, 0, dash_stream->pending_seek_ts,
|
||||||
NULL);
|
NULL) != GST_FLOW_OK) {
|
||||||
dash_stream->pending_seek_ts = GST_CLOCK_TIME_NONE;
|
|
||||||
if (SIDX (dash_stream)->entry_index >=
|
|
||||||
SIDX (dash_stream)->entries_count) {
|
|
||||||
GST_ERROR_OBJECT (stream->pad, "Couldn't find position in sidx");
|
GST_ERROR_OBJECT (stream->pad, "Couldn't find position in sidx");
|
||||||
dash_stream->sidx_position = GST_CLOCK_TIME_NONE;
|
dash_stream->sidx_position = GST_CLOCK_TIME_NONE;
|
||||||
gst_isoff_sidx_parser_clear (&dash_stream->sidx_parser);
|
gst_isoff_sidx_parser_clear (&dash_stream->sidx_parser);
|
||||||
}
|
}
|
||||||
|
dash_stream->pending_seek_ts = GST_CLOCK_TIME_NONE;
|
||||||
} else {
|
} else {
|
||||||
gint idx = 0;
|
gint idx = 0;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue