mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-25 17:50:36 +00:00
avidemux: fix offset handling in push mode seeking
Push mode seeking uses same index data as pull mode, and stores offset to data in chunk, whereas push mode operates in chunks, and as such needs offset consistently corresponding to chunk headers. Also fix determining best matching stream for incoming newsegment event, as well as setting some stream state accordingly.
This commit is contained in:
parent
1dfcc3227c
commit
d90aed1857
1 changed files with 39 additions and 19 deletions
|
@ -693,11 +693,14 @@ gst_avi_demux_seek_streams_index (GstAviDemux * avi, guint64 offset,
|
||||||
for (i = 0; i < avi->num_streams; i++) {
|
for (i = 0; i < avi->num_streams; i++) {
|
||||||
stream = &avi->stream[i];
|
stream = &avi->stream[i];
|
||||||
|
|
||||||
|
/* compensate for chunk header */
|
||||||
|
offset += 8;
|
||||||
entry =
|
entry =
|
||||||
gst_util_array_binary_search (stream->index, stream->idx_n,
|
gst_util_array_binary_search (stream->index, stream->idx_n,
|
||||||
sizeof (GstAviIndexEntry),
|
sizeof (GstAviIndexEntry),
|
||||||
(GCompareDataFunc) gst_avi_demux_index_entry_offset_search,
|
(GCompareDataFunc) gst_avi_demux_index_entry_offset_search,
|
||||||
before ? GST_SEARCH_MODE_BEFORE : GST_SEARCH_MODE_AFTER, &offset, NULL);
|
before ? GST_SEARCH_MODE_BEFORE : GST_SEARCH_MODE_AFTER, &offset, NULL);
|
||||||
|
offset -= 8;
|
||||||
|
|
||||||
if (entry)
|
if (entry)
|
||||||
index = entry - stream->index;
|
index = entry - stream->index;
|
||||||
|
@ -720,13 +723,11 @@ gst_avi_demux_seek_streams_index (GstAviDemux * avi, guint64 offset,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
val = stream->index[index].offset;
|
val = stream->index[index].offset - 8;
|
||||||
GST_DEBUG_OBJECT (avi, "stream %d, next entry at %" G_GUINT64_FORMAT, i,
|
GST_DEBUG_OBJECT (avi, "stream %d, next entry at %" G_GUINT64_FORMAT, i,
|
||||||
val);
|
val);
|
||||||
|
|
||||||
gst_avi_demux_get_buffer_info (avi, stream, index, (GstClockTime *) & val,
|
stream->current_total = stream->index[index].total;
|
||||||
NULL, NULL, NULL);
|
|
||||||
stream->current_total = val;
|
|
||||||
stream->current_entry = index;
|
stream->current_entry = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -777,9 +778,11 @@ gst_avi_demux_handle_sink_event (GstPad * pad, GstEvent * event)
|
||||||
|
|
||||||
if (avi->have_index) {
|
if (avi->have_index) {
|
||||||
GstAviIndexEntry *entry;
|
GstAviIndexEntry *entry;
|
||||||
guint i = 0, index;
|
guint i = 0, index = 0, k = 0;
|
||||||
GstAviStream *stream;
|
GstAviStream *stream;
|
||||||
|
|
||||||
|
/* compensate chunk header, stored index offset points after header */
|
||||||
|
start += 8;
|
||||||
/* find which stream we're on */
|
/* find which stream we're on */
|
||||||
do {
|
do {
|
||||||
stream = &avi->stream[i];
|
stream = &avi->stream[i];
|
||||||
|
@ -788,17 +791,30 @@ gst_avi_demux_handle_sink_event (GstPad * pad, GstEvent * event)
|
||||||
entry = gst_util_array_binary_search (stream->index,
|
entry = gst_util_array_binary_search (stream->index,
|
||||||
stream->idx_n, sizeof (GstAviIndexEntry),
|
stream->idx_n, sizeof (GstAviIndexEntry),
|
||||||
(GCompareDataFunc) gst_avi_demux_index_entry_offset_search,
|
(GCompareDataFunc) gst_avi_demux_index_entry_offset_search,
|
||||||
GST_SEARCH_MODE_BEFORE, &start, NULL);
|
GST_SEARCH_MODE_AFTER, &start, NULL);
|
||||||
|
|
||||||
if (entry == NULL) {
|
if (entry == NULL)
|
||||||
index = 0;
|
continue;
|
||||||
} else {
|
|
||||||
index = entry - stream->index;
|
index = entry - stream->index;
|
||||||
}
|
|
||||||
|
|
||||||
|
/* we are on the stream with a chunk start offset closest to start */
|
||||||
|
if (!offset || stream->index[index].offset < offset) {
|
||||||
|
offset = stream->index[index].offset;
|
||||||
|
k = i;
|
||||||
|
}
|
||||||
|
/* exact match needs no further searching */
|
||||||
if (stream->index[index].offset == start)
|
if (stream->index[index].offset == start)
|
||||||
break;
|
break;
|
||||||
} while (++i < avi->num_streams);
|
} while (++i < avi->num_streams);
|
||||||
|
start -= 8;
|
||||||
|
offset -= 8;
|
||||||
|
stream = &avi->stream[k];
|
||||||
|
|
||||||
|
/* so we have no idea what is to come, or where we are */
|
||||||
|
if (!offset) {
|
||||||
|
GST_WARNING_OBJECT (avi, "insufficient index data, forcing EOS");
|
||||||
|
goto eos;
|
||||||
|
}
|
||||||
|
|
||||||
/* get the ts corresponding to start offset bytes for the stream */
|
/* get the ts corresponding to start offset bytes for the stream */
|
||||||
gst_avi_demux_get_buffer_info (avi, stream, index,
|
gst_avi_demux_get_buffer_info (avi, stream, index,
|
||||||
|
@ -818,13 +834,12 @@ gst_avi_demux_handle_sink_event (GstPad * pad, GstEvent * event)
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_index_entry_assoc_map (entry, GST_FORMAT_TIME, &time);
|
gst_index_entry_assoc_map (entry, GST_FORMAT_TIME, &time);
|
||||||
gst_index_entry_assoc_map (entry, GST_FORMAT_BYTES, &start);
|
gst_index_entry_assoc_map (entry, GST_FORMAT_BYTES, &offset);
|
||||||
} else {
|
} else {
|
||||||
GST_WARNING_OBJECT (avi, "no index data, forcing EOS");
|
GST_WARNING_OBJECT (avi, "no index data, forcing EOS");
|
||||||
goto eos;
|
goto eos;
|
||||||
}
|
}
|
||||||
|
|
||||||
offset = start;
|
|
||||||
stop = GST_CLOCK_TIME_NONE;
|
stop = GST_CLOCK_TIME_NONE;
|
||||||
|
|
||||||
/* set up segment and send downstream */
|
/* set up segment and send downstream */
|
||||||
|
@ -841,15 +856,15 @@ gst_avi_demux_handle_sink_event (GstPad * pad, GstEvent * event)
|
||||||
GST_DEBUG_OBJECT (avi, "next chunk expected at %" G_GINT64_FORMAT, start);
|
GST_DEBUG_OBJECT (avi, "next chunk expected at %" G_GINT64_FORMAT, start);
|
||||||
|
|
||||||
/* adjust state for streaming thread accordingly */
|
/* adjust state for streaming thread accordingly */
|
||||||
avi->offset = offset;
|
|
||||||
if (avi->have_index)
|
if (avi->have_index)
|
||||||
gst_avi_demux_seek_streams_index (avi, offset, FALSE);
|
gst_avi_demux_seek_streams_index (avi, offset, FALSE);
|
||||||
else
|
else
|
||||||
gst_avi_demux_seek_streams (avi, offset, FALSE);
|
gst_avi_demux_seek_streams (avi, offset, FALSE);
|
||||||
|
|
||||||
/* set up streaming thread */
|
/* set up streaming thread */
|
||||||
avi->offset = offset;
|
g_assert (offset >= start);
|
||||||
avi->todrop = start - offset;
|
avi->offset = start;
|
||||||
|
avi->todrop = offset - start;
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
gst_event_unref (event);
|
gst_event_unref (event);
|
||||||
|
@ -4190,7 +4205,8 @@ avi_demux_handle_seek_push (GstAviDemux * avi, GstPad * pad, GstEvent * event)
|
||||||
/* re-use cur to be the timestamp of the seek as it _will_ be */
|
/* re-use cur to be the timestamp of the seek as it _will_ be */
|
||||||
cur = stream->current_timestamp;
|
cur = stream->current_timestamp;
|
||||||
|
|
||||||
min_offset = avi->seek_kf_offset = stream->index[index].offset;
|
min_offset = stream->index[index].offset;
|
||||||
|
avi->seek_kf_offset = min_offset - 8;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (avi,
|
GST_DEBUG_OBJECT (avi,
|
||||||
"Seek to: ts %" GST_TIME_FORMAT " (on str %u, idx %u, offset %"
|
"Seek to: ts %" GST_TIME_FORMAT " (on str %u, idx %u, offset %"
|
||||||
|
@ -4241,8 +4257,12 @@ avi_demux_handle_seek_push (GstAviDemux * avi, GstPad * pad, GstEvent * event)
|
||||||
GST_TIME_ARGS (stream->current_ts_end), stream->current_offset,
|
GST_TIME_ARGS (stream->current_ts_end), stream->current_offset,
|
||||||
stream->current_offset_end);
|
stream->current_offset_end);
|
||||||
|
|
||||||
if (!perform_seek_to_offset (avi,
|
/* index data refers to data, not chunk header (for pull mode convenience) */
|
||||||
min_offset - (avi->stream[0].indexes ? 8 : 0))) {
|
min_offset -= 8;
|
||||||
|
GST_DEBUG_OBJECT (avi, "seeking to chunk at offset %" G_GUINT64_FORMAT,
|
||||||
|
min_offset);
|
||||||
|
|
||||||
|
if (!perform_seek_to_offset (avi, min_offset)) {
|
||||||
GST_DEBUG_OBJECT (avi, "seek event failed!");
|
GST_DEBUG_OBJECT (avi, "seek event failed!");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue