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:
Mark Nauwelaerts 2010-03-09 18:05:29 +01:00
parent 1dfcc3227c
commit d90aed1857

View file

@ -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;
} }