Commit 1eff7868 authored by Wim Taymans's avatar Wim Taymans
Browse files

gst/avi/gstavidemux.*: Precalc most of the duration query for each stream.

Original commit message from CVS:
* gst/avi/gstavidemux.c: (gst_avi_demux_reset),
(gst_avi_demux_index_entry_for_time),
(gst_avi_demux_handle_src_query), (gst_avi_demux_handle_src_event),
(gst_avi_demux_stream_init), (gst_avi_demux_parse_stream),
(gst_avi_demux_stream_index), (gst_avi_demux_peek_tag),
(gst_avi_demux_next_data_buffer),
(gst_avi_demux_calculate_durations_from_index),
(gst_avi_demux_stream_header), (gst_avi_demux_do_seek),
(gst_avi_demux_handle_seek), (gst_avi_demux_aggregated_flow),
(gst_avi_demux_process_next_entry), (gst_avi_demux_loop),
(gst_avi_demux_sink_activate_pull), (gst_avi_demux_change_state):
* gst/avi/gstavidemux.h:
Precalc most of the duration query for each stream.
Make seeking more correct.
Use GstSegment to track position and duration.
Code cleanups and leak fixes.
Calculate correct total duration based on index length.
parent 66bbbfb7
2006-08-22 Wim Taymans <wim@fluendo.com>
* gst/avi/gstavidemux.c: (gst_avi_demux_reset),
(gst_avi_demux_index_entry_for_time),
(gst_avi_demux_handle_src_query), (gst_avi_demux_handle_src_event),
(gst_avi_demux_stream_init), (gst_avi_demux_parse_stream),
(gst_avi_demux_stream_index), (gst_avi_demux_peek_tag),
(gst_avi_demux_next_data_buffer),
(gst_avi_demux_calculate_durations_from_index),
(gst_avi_demux_stream_header), (gst_avi_demux_do_seek),
(gst_avi_demux_handle_seek), (gst_avi_demux_aggregated_flow),
(gst_avi_demux_process_next_entry), (gst_avi_demux_loop),
(gst_avi_demux_sink_activate_pull), (gst_avi_demux_change_state):
* gst/avi/gstavidemux.h:
Precalc most of the duration query for each stream.
Make seeking more correct.
Use GstSegment to track position and duration.
Code cleanups and leak fixes.
Calculate correct total duration based on index length.
2006-08-22 Jan Schmidt <thaytan@mad.scientist.com>
* gst/id3demux/id3v2frames.c: (parse_text_identification_frame),
......
......@@ -83,7 +83,9 @@ static gboolean gst_avi_demux_handle_src_query (GstPad * pad, GstQuery * query);
static gboolean gst_avi_demux_src_convert (GstPad * pad, GstFormat src_format,
gint64 src_value, GstFormat * dest_format, gint64 * dest_value);
static gboolean gst_avi_demux_handle_seek (GstAviDemux * avi, gboolean update);
static gboolean gst_avi_demux_do_seek (GstAviDemux * avi, GstSegment * segment);
static gboolean gst_avi_demux_handle_seek (GstAviDemux * avi, GstPad * pad,
GstEvent * event);
static void gst_avi_demux_loop (GstPad * pad);
static gboolean gst_avi_demux_sink_activate (GstPad * sinkpad);
static gboolean gst_avi_demux_sink_activate_pull (GstPad * sinkpad,
......@@ -226,8 +228,6 @@ gst_avi_demux_reset (GstAviDemux * avi)
avi->globaltags = NULL;
avi->got_tags = FALSE;
gst_segment_init (&avi->segment, GST_FORMAT_TIME);
}
static gst_avi_index_entry *
......@@ -257,6 +257,7 @@ gst_avi_demux_index_entry_for_time (GstAviDemux * avi,
GST_LOG_OBJECT (avi, "stream_nr:%d , time:%" GST_TIME_FORMAT " flags:%d",
stream_nr, GST_TIME_ARGS (time), flags);
i = -1;
do {
entry = gst_avi_demux_index_next (avi, stream_nr, i + 1);
......@@ -269,6 +270,7 @@ gst_avi_demux_index_entry_for_time (GstAviDemux * avi,
"looking at entry %d / ts:%" GST_TIME_FORMAT " / dur:%" GST_TIME_FORMAT
" flags:%d", i, GST_TIME_ARGS (entry->ts), GST_TIME_ARGS (entry->dur),
entry->flags);
if (entry->ts <= time && (entry->flags & flags) == flags)
last_entry = entry;
} while (entry->ts < time);
......@@ -429,6 +431,7 @@ gst_avi_demux_handle_src_query (GstPad * pad, GstQuery * query)
pos = gst_util_uint64_scale_int (xlen, stream->current_frame,
stream->total_frames);
} else {
/* we don't know */
res = FALSE;
}
} else {
......@@ -451,20 +454,7 @@ gst_avi_demux_handle_src_query (GstPad * pad, GstQuery * query)
res = FALSE;
break;
}
/* use duration from the index if we have an
* index instead of trusting the stream header */
if (GST_CLOCK_TIME_IS_VALID (stream->idx_duration)) {
gst_query_set_duration (query, GST_FORMAT_TIME, stream->idx_duration);
} else {
gint64 len;
len =
gst_util_uint64_scale ((guint64) stream->strh->length *
stream->strh->scale, GST_SECOND, stream->strh->rate);
gst_query_set_duration (query, GST_FORMAT_TIME, len);
}
gst_query_set_duration (query, GST_FORMAT_TIME, stream->idx_duration);
break;
}
default:
......@@ -493,104 +483,26 @@ gst_avi_demux_handle_src_event (GstPad * pad, GstEvent * event)
{
gboolean res = TRUE;
GstAviDemux *avi = GST_AVI_DEMUX (GST_PAD_PARENT (pad));
avi_stream_context *stream;
GST_CAT_DEBUG_OBJECT (GST_CAT_EVENT, avi,
"have event type %s: %p on src pad", GST_EVENT_TYPE_NAME (event), event);
if (!avi->index_entries) {
GST_CAT_DEBUG_OBJECT (GST_CAT_EVENT, avi, "no index entries, returning");
return FALSE;
}
stream = gst_pad_get_element_private (pad);
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_SEEK:
{
/* FIXME, this seeking code is not correct, look at wavparse for
* a better example */
GstFormat format;
GstSeekFlags flags;
gdouble rate;
gint64 start, stop;
gint64 tstart, tstop;
gint64 duration;
GstFormat tformat = GST_FORMAT_TIME;
GstSeekType start_type, stop_type;
gboolean update_start = TRUE;
gboolean update_stop = TRUE;
gst_event_parse_seek (event, &rate, &format, &flags, &start_type, &start,
&stop_type, &stop);
GST_DEBUG_OBJECT (avi,
"seek format %d, flags:%d, %08x, start:%lld, stop:%lld", format,
flags, stream->strh->type, start, stop);
if (format != GST_FORMAT_TIME) {
res &=
gst_avi_demux_src_convert (pad, format, start, &tformat, &tstart);
res &= gst_avi_demux_src_convert (pad, format, stop, &tformat, &tstop);
if (!res)
goto done;
} else {
tstart = start;
tstop = stop;
}
if (!gst_pad_query_duration (stream->pad, &tformat, &duration)) {
res = FALSE;
goto done;
}
switch (start_type) {
case GST_SEEK_TYPE_CUR:
tstart = avi->segment.start + tstart;
break;
case GST_SEEK_TYPE_END:
tstart = duration + tstart;
break;
case GST_SEEK_TYPE_NONE:
tstart = avi->segment.start;
update_start = FALSE;
break;
case GST_SEEK_TYPE_SET:
break;
}
tstart = CLAMP (tstart, 0, duration);
switch (stop_type) {
case GST_SEEK_TYPE_CUR:
tstop = avi->segment.stop + tstop;
break;
case GST_SEEK_TYPE_END:
tstop = duration + tstop;
break;
case GST_SEEK_TYPE_NONE:
tstop = avi->segment.stop;
update_stop = FALSE;
break;
case GST_SEEK_TYPE_SET:
break;
}
tstop = CLAMP (tstop, 0, duration);
/* now store the values */
avi->segment.rate = rate;
avi->segment.flags = flags;
avi->segment.start = tstart;
avi->segment.stop = tstop;
gst_avi_demux_handle_seek (avi, update_start || update_stop);
/* handle seeking */
res = gst_avi_demux_handle_seek (avi, pad, event);
break;
case GST_EVENT_QOS:
/* FIXME, we can do something clever here like skip to the next keyframe
* based on the QoS values. */
res = FALSE;
break;
}
default:
/* most other events are not very usefull */
res = FALSE;
break;
}
done:
gst_event_unref (event);
GST_DEBUG_OBJECT (avi, "returning %d", res);
......@@ -603,7 +515,7 @@ done:
* @buf: input data to be used for parsing.
*
* "Open" a RIFF/AVI file. The buffer should be at least 12
* bytes long. Discards buffer after use.
* bytes long. Takes ownership of @buf.
*
* Returns: TRUE if the file is a RIFF/AVI file, FALSE otherwise.
* Throws an error, caller should error out (fatal).
......@@ -638,10 +550,10 @@ gst_avi_demux_stream_init (GstAviDemux * avi)
GstFlowReturn res;
GstBuffer *buf = NULL;
if ((res = gst_pad_pull_range (avi->sinkpad,
avi->offset, 12, &buf)) != GST_FLOW_OK)
res = gst_pad_pull_range (avi->sinkpad, avi->offset, 12, &buf);
if (res != GST_FLOW_OK)
return res;
else if (!gst_avi_demux_parse_file_header (GST_ELEMENT (avi), buf))
else if (!gst_avi_demux_parse_file_header (GST_ELEMENT_CAST (avi), buf))
goto wrong_header;
avi->offset += 12;
......@@ -652,7 +564,6 @@ gst_avi_demux_stream_init (GstAviDemux * avi)
wrong_header:
{
GST_DEBUG_OBJECT (avi, "error parsing file header");
gst_buffer_unref (buf);
return GST_FLOW_ERROR;
}
}
......@@ -1001,7 +912,6 @@ gst_avi_demux_read_subindexes (GstAviDemux * avi,
* Errors are not fatal. It does indicate the stream
* was skipped.
*/
static gboolean
gst_avi_demux_parse_stream (GstElement * element, GstBuffer * buf)
{
......@@ -1020,11 +930,11 @@ gst_avi_demux_parse_stream (GstElement * element, GstBuffer * buf)
GST_DEBUG_OBJECT (element, "Parsing stream");
/* read strh */
if (!buf || !gst_riff_parse_chunk (element, buf, &offset, &tag, &sub) ||
if (!gst_riff_parse_chunk (element, buf, &offset, &tag, &sub) ||
tag != GST_RIFF_TAG_strh) {
GST_ERROR_OBJECT (element,
"Failed to find strh chunk (tag: %" GST_FOURCC_FORMAT ")",
buf ? GST_BUFFER_SIZE (buf) : 0, GST_FOURCC_ARGS (tag));
GST_BUFFER_SIZE (buf), GST_FOURCC_ARGS (tag));
goto fail;
} else if (!gst_riff_parse_strh (element, sub, &stream->strh))
goto fail;
......@@ -1034,8 +944,7 @@ gst_avi_demux_parse_stream (GstElement * element, GstBuffer * buf)
tag != GST_RIFF_TAG_strf) {
GST_ERROR_OBJECT (element,
"Failed to find strh chunk (size: %d, tag: %"
GST_FOURCC_FORMAT ")", buf ? GST_BUFFER_SIZE (buf) : 0,
GST_FOURCC_ARGS (tag));
GST_FOURCC_FORMAT ")", GST_BUFFER_SIZE (buf), GST_FOURCC_ARGS (tag));
goto fail;
} else {
gboolean res = FALSE;
......@@ -1081,9 +990,9 @@ gst_avi_demux_parse_stream (GstElement * element, GstBuffer * buf)
case GST_RIFF_TAG_strn:
g_free (stream->name);
if (sub != NULL) {
stream->name = g_new (gchar, GST_BUFFER_SIZE (sub) + 1);
memcpy (stream->name, GST_BUFFER_DATA (sub), GST_BUFFER_SIZE (sub));
stream->name[GST_BUFFER_SIZE (sub)] = '\0';
stream->name =
g_strndup ((gchar *) GST_BUFFER_DATA (sub),
(gsize) GST_BUFFER_SIZE (sub));
gst_buffer_unref (sub);
sub = NULL;
} else {
......@@ -1233,7 +1142,6 @@ fail:
gst_buffer_unref (stream->extradata);
memset (stream, 0, sizeof (avi_stream_context));
avi->num_streams++;
return FALSE;
}
}
......@@ -1246,7 +1154,6 @@ fail:
* Read an openDML-2.0 extension header. Fills in the frame number
* in the avi demuxer object when reading succeeds.
*/
static void
gst_avi_demux_parse_odml (GstElement * element, GstBuffer * buf)
{
......@@ -1441,9 +1348,8 @@ gst_avi_demux_stream_index (GstAviDemux * avi,
/* get position */
if (gst_pad_pull_range (avi->sinkpad, offset, 8, &buf) != GST_FLOW_OK)
return;
else if (!buf || GST_BUFFER_SIZE (buf) < 8) {
if (buf)
gst_buffer_unref (buf);
else if (GST_BUFFER_SIZE (buf) < 8) {
gst_buffer_unref (buf);
return;
}
offset += 8 + GST_READ_UINT32_LE (GST_BUFFER_DATA (buf) + 4);
......@@ -1641,10 +1547,15 @@ gst_avi_demux_peek_tag (GstAviDemux * avi, guint64 offset, guint32 * tag,
GstFlowReturn res = GST_FLOW_OK;
GstBuffer *buf = NULL;
if ((res = gst_pad_pull_range (avi->sinkpad, offset, 8, &buf)) != GST_FLOW_OK)
res = gst_pad_pull_range (avi->sinkpad, offset, 8, &buf);
if (res != GST_FLOW_OK)
goto beach;
if (GST_BUFFER_SIZE (buf) != 8)
if (GST_BUFFER_SIZE (buf) != 8) {
gst_buffer_unref (buf);
return GST_FLOW_ERROR;
}
*tag = GST_READ_UINT32_LE (GST_BUFFER_DATA (buf));
*size = GST_READ_UINT32_LE (GST_BUFFER_DATA (buf) + 4);
gst_buffer_unref (buf);
......@@ -1663,7 +1574,6 @@ beach:
* Returns the offset and size of the next buffer
* Position is the position of the buffer (after tag and size)
*/
static GstFlowReturn
gst_avi_demux_next_data_buffer (GstAviDemux * avi, guint64 * offset,
guint32 * tag, guint * size)
......@@ -1673,7 +1583,8 @@ gst_avi_demux_next_data_buffer (GstAviDemux * avi, guint64 * offset,
GstFlowReturn res = GST_FLOW_OK;
while (1) {
if ((res = gst_avi_demux_peek_tag (avi, off, tag, &siz)) != GST_FLOW_OK)
res = gst_avi_demux_peek_tag (avi, off, tag, &siz);
if (res != GST_FLOW_OK)
break;
if (*tag == GST_RIFF_TAG_LIST)
off += 12;
......@@ -1693,7 +1604,6 @@ gst_avi_demux_next_data_buffer (GstAviDemux * avi, guint64 * offset,
*
* pull-range based
*/
static gboolean
gst_avi_demux_stream_scan (GstAviDemux * avi,
GList ** index, GList ** alloc_list)
......@@ -1883,7 +1793,6 @@ gst_avi_demux_stream_scan (GstAviDemux * avi,
* smaller pieces. In the second case, we re-order chunk reading
* order. The end result should be a smoother playing AVI.
*/
static gint
sort (gst_avi_index_entry * a, gst_avi_index_entry * b)
{
......@@ -2056,23 +1965,50 @@ static void
gst_avi_demux_calculate_durations_from_index (GstAviDemux * avi)
{
gst_avi_index_entry *entry;
GstClockTime end_time;
gint stream, i;
GstClockTime total;
total = GST_CLOCK_TIME_NONE;
/* we assume all streams start at a timestamp of 0 for now */
/* all streams start at a timestamp 0 */
for (stream = 0; stream < avi->num_streams; stream++) {
end_time = GST_CLOCK_TIME_NONE;
GstClockTime duration = GST_CLOCK_TIME_NONE;
GstClockTime hduration;
gst_riff_strh *strh = avi->stream[stream].strh;
/* get header duration */
hduration = gst_util_uint64_scale ((guint64) strh->length *
strh->scale, GST_SECOND, strh->rate);
GST_INFO ("Stream %d duration according to header: %" GST_TIME_FORMAT,
stream, GST_TIME_ARGS (hduration));
i = 0;
/* run over index to get last duration */
while ((entry = gst_avi_demux_index_next (avi, stream, i))) {
end_time = entry->ts + entry->dur;
duration = entry->ts + entry->dur;
i++;
}
if (GST_CLOCK_TIME_IS_VALID (end_time)) {
if (GST_CLOCK_TIME_IS_VALID (duration)) {
/* index gave valid duration, use that */
GST_INFO ("Stream %d duration according to index: %" GST_TIME_FORMAT,
stream, GST_TIME_ARGS (end_time));
avi->stream[stream].idx_duration = end_time;
stream, GST_TIME_ARGS (duration));
} else {
/* fall back to header info to calculate a duration */
duration = hduration;
}
/* set duration for the stream */
avi->stream[stream].idx_duration = duration;
/* find total duration */
if (total == GST_CLOCK_TIME_NONE || duration > total)
total = duration;
}
/* and set the total duration in the segment. */
GST_INFO ("Setting total duration to: %" GST_TIME_FORMAT,
GST_TIME_ARGS (total));
gst_segment_set_duration (&avi->segment, GST_FORMAT_TIME, total);
}
static gboolean
......@@ -2095,7 +2031,6 @@ gst_avi_demux_push_event (GstAviDemux * avi, GstEvent * event)
/*
* Read full AVI headers.
*/
static GstFlowReturn
gst_avi_demux_stream_header (GstAviDemux * avi)
{
......@@ -2104,6 +2039,7 @@ gst_avi_demux_stream_header (GstAviDemux * avi)
guint32 tag;
GList *index = NULL, *alloc = NULL;
guint offset = 4;
gint64 stop;
/* the header consists of a 'hdrl' LIST tag */
if ((res = gst_riff_read_chunk (GST_ELEMENT (avi), avi->sinkpad,
......@@ -2203,8 +2139,10 @@ gst_avi_demux_stream_header (GstAviDemux * avi)
if ((res = gst_pad_pull_range (avi->sinkpad, avi->offset,
12, &buf)) != GST_FLOW_OK)
return res;
else if (!buf || GST_BUFFER_SIZE (buf) < 12)
else if (GST_BUFFER_SIZE (buf) < 12) {
gst_buffer_unref (buf);
return GST_FLOW_ERROR;
}
tag = GST_READ_UINT32_LE (GST_BUFFER_DATA (buf));
size = GST_READ_UINT32_LE (GST_BUFFER_DATA (buf) + 4);
......@@ -2260,22 +2198,22 @@ done:
gst_avi_demux_massage_index (avi, index, alloc);
gst_avi_demux_calculate_durations_from_index (avi);
/* send initial discont */
avi->segment.start = 0;
avi->segment.stop =
gst_util_uint64_scale_int ((gint64) avi->stream[0].strh->scale *
avi->stream[0].strh->length, GST_SECOND, avi->stream[0].strh->rate);
/* create initial NEWSEGMENT event */
if ((stop = avi->segment.stop) == GST_CLOCK_TIME_NONE)
stop = avi->segment.duration;
GST_DEBUG_OBJECT (avi, "segment stop %" G_GINT64_FORMAT, avi->segment.stop);
GST_DEBUG_OBJECT (avi, "segment stop %" G_GINT64_FORMAT, stop);
if (avi->seek_event)
gst_event_unref (avi->seek_event);
avi->seek_event = gst_event_new_new_segment
(FALSE, avi->segment.rate, GST_FORMAT_TIME,
avi->segment.start, avi->segment.stop, avi->segment.start);
avi->segment.start, stop, avi->segment.start);
/* at this point we know all the streams and we can signal the no more
* pads signal */
GST_DEBUG_OBJECT (avi, "signaling no more pads");
gst_element_no_more_pads (GST_ELEMENT (avi));
gst_element_no_more_pads (GST_ELEMENT_CAST (avi));
return GST_FLOW_OK;
......@@ -2301,10 +2239,8 @@ no_avih:
GST_ELEMENT_ERROR (avi, STREAM, DEMUX, (NULL),
("Invalid AVI header (no avih at start): %"
GST_FOURCC_FORMAT, GST_FOURCC_ARGS (tag)));
if (sub) {
if (sub)
gst_buffer_unref (sub);
sub = NULL;
}
gst_buffer_unref (buf);
return GST_FLOW_ERROR;
}
......@@ -2312,10 +2248,8 @@ invalid_avih:
{
GST_ELEMENT_ERROR (avi, STREAM, DEMUX, (NULL),
("Invalid AVI header (cannot parse avih at start)"));
if (sub) {
if (sub)
gst_buffer_unref (sub);
sub = NULL;
}
gst_buffer_unref (buf);
return GST_FLOW_ERROR;
}
......@@ -2336,86 +2270,190 @@ no_index:
}
}
/*
* Handle seek.
/* Do the actual seeking.
*/
static gboolean
gst_avi_demux_handle_seek (GstAviDemux * avi, gboolean update)
gst_avi_demux_do_seek (GstAviDemux * avi, GstSegment * segment)
{
GstClockTime start_time;
gboolean flush, keyframe;
GstClockTime seek_time;
gboolean keyframe;
gst_avi_index_entry *entry;
guint i;
seek_time = segment->last_stop;
keyframe = !!(segment->flags & GST_SEEK_FLAG_KEY_UNIT);
/* FIXME: if we seek in an openDML file, we will have multiple
* primary levels. Seeking in between those will cause havoc. */
flush = avi->segment.flags & GST_SEEK_FLAG_FLUSH;
keyframe = avi->segment.flags & GST_SEEK_FLAG_KEY_UNIT;
/* get the entry for the requested position, which is always in last_stop.
* we search the index intry for stream 0, since all entries are sorted by
* time and stream we automagically are positioned for the other streams as
* well. FIXME, this code assumes the main stream with keyframes is stream 0,
* which is mostly correct... */
entry = gst_avi_demux_index_entry_for_time (avi, 0, seek_time,
(guint32) GST_RIFF_IF_KEYFRAME);
if (entry) {
GST_DEBUG_OBJECT (avi,
"Got keyframe entry %d [stream:%d / ts:%" GST_TIME_FORMAT
" / duration:%" GST_TIME_FORMAT "]", entry->index_nr,
entry->stream_nr, GST_TIME_ARGS (entry->ts),
GST_TIME_ARGS (entry->dur));
avi->current_entry = entry->index_nr;
} else {
GST_WARNING_OBJECT (avi,
"Couldn't find AviIndexEntry for time:%" GST_TIME_FORMAT,
GST_TIME_ARGS (seek_time));
if (avi->current_entry >= avi->index_size && avi->index_size > 0)
avi->current_entry = avi->index_size - 1;
}
GST_DEBUG_OBJECT (avi, "seek: %" GST_TIME_FORMAT
" keyframe seeking:%d", GST_TIME_ARGS (seek_time), keyframe);
if (keyframe) {
/* when seeking to a keyframe, we update the result seek time
* to the time of the keyframe. */
seek_time = avi->index_entries[avi->current_entry].ts;
}
segment->last_stop = seek_time;
return TRUE;
}
static gboolean
gst_avi_demux_handle_seek (GstAviDemux * avi, GstPad * pad, GstEvent * event)
{
gboolean res;
gdouble rate;
GstFormat format;
GstSeekFlags flags;
GstSeekType cur_type = GST_SEEK_TYPE_NONE, stop_type;
gint64 cur, stop;
gboolean flush;
gboolean update;
GstSegment seeksegment = { 0, };
if (event) {
GST_DEBUG_OBJECT (avi, "doing seek with event");
gst_event_parse_seek (event, &rate, &format, &flags,
&cur_type, &cur, &stop_type, &stop);
/* we have to have a format as the segment format. Try to convert
* if not. */
if (format != GST_FORMAT_TIME) {
GstFormat fmt;
fmt = GST_FORMAT_TIME;
res = TRUE;
if (cur_type != GST_SEEK_TYPE_NONE)
res = gst_pad_query_convert (pad, format, cur, &fmt, &cur);
if (res && stop_type != GST_SEEK_TYPE_NONE)
res = gst_pad_query_convert (pad, format, stop, &fmt, &stop);
if (!res)
goto no_format;
format = fmt;
}
} else {
GST_DEBUG_OBJECT (avi, "doing seek without event");
flags = 0;
}
/* save flush flag */
flush = flags & GST_SEEK_FLAG_FLUSH;
if (flush) {
/* for a flushing seek, we send a flush_start on all pads. This will
* eventually stop streaming with a WRONG_STATE. We can thus eventually
* take the STREAM_LOCK. */
GST_DEBUG_OBJECT (avi, "sending flush start");
gst_avi_demux_push_event (avi, gst_event_new_flush_start ());
gst_pad_push_event (avi->sinkpad, gst_event_new_flush_start ());
} else
} else {
/* a non-flushing seek, we PAUSE the task so that we can take the
* STREAM_LOCK */
GST_DEBUG_OBJECT (avi, "non flushing seek, pausing task");
gst_pad_pause_task (avi->sinkpad);
}
/* wait for streaming to stop */
GST_PAD_STREAM_LOCK (avi->sinkpad);
/* fill current_entry according to flags and update */
if (update) {
entry = gst_avi_demux_index_entry_for_time (avi, 0, avi->segment.start,
(guint32) GST_RIFF_IF_KEYFRAME);
if (entry) {
GST_DEBUG_OBJECT (avi,
"Got keyframe entry %d [stream:%d / ts:%" GST_TIME_FORMAT
" / duration:%" GST_TIME_FORMAT "]", entry->index_nr,
entry->stream_nr, GST_TIME_ARGS (entry->ts),