summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gst/avi/gstavidemux.c976
-rw-r--r--gst/avi/gstavidemux.h40
2 files changed, 628 insertions, 388 deletions
diff --git a/gst/avi/gstavidemux.c b/gst/avi/gstavidemux.c
index a1cc0a052..68050f7f8 100644
--- a/gst/avi/gstavidemux.c
+++ b/gst/avi/gstavidemux.c
@@ -254,7 +254,6 @@ gst_avi_demux_reset (GstAviDemux * avi)
- g_free (avi->index_entries);
- avi->index_entries = NULL;
- avi->index_size = 0;
+ //g_free (avi->index_entries);
+ //avi->index_entries = NULL;
+ //avi->index_size = 0;
avi->index_offset = 0;
- avi->current_entry = 0;
g_free (avi->avih);
@@ -279,118 +278,2 @@ gst_avi_demux_reset (GstAviDemux * avi)
-/* Index helper */
-static gst_avi_index_entry *
-gst_avi_demux_index_last (GstAviDemux * avi, gint stream_nr)
-{
- gint i;
- gst_avi_index_entry *result = NULL;
-
- for (i = avi->index_size - 1; i >= 0; i--) {
- if (avi->index_entries[i].stream_nr == stream_nr) {
- result = &avi->index_entries[i];
- break;
- }
- }
- return result;
-}
-
-static gst_avi_index_entry *
-gst_avi_demux_index_next (GstAviDemux * avi, gint stream_nr, gint last,
- guchar flags)
-{
- gint i;
- gst_avi_index_entry *result = NULL, *entry;
-
- for (i = last + 1; i < avi->index_size; i++) {
- entry = &avi->index_entries[i];
-
- if (entry->stream_nr != stream_nr)
- continue;
-
- if ((entry->flags & flags) == flags) {
- result = entry;
- break;
- }
- }
- return result;
-}
-
-static gst_avi_index_entry *
-gst_avi_demux_index_prev (GstAviDemux * avi, gint stream_nr, gint last,
- guchar flags)
-{
- gint i;
- gst_avi_index_entry *result = NULL, *entry;
-
- for (i = last - 1; i >= 0; i--) {
- entry = &avi->index_entries[i];
-
- if (entry->stream_nr != stream_nr)
- continue;
-
- if ((entry->flags & flags) == flags) {
- result = entry;
- break;
- }
- }
- return result;
-}
-
-static gint
-gst_avi_demux_index_entry_search (gst_avi_index_entry * entry, guint64 * time)
-{
- if (entry->ts < *time)
- return -1;
- else if (entry->ts > *time)
- return 1;
- return 0;
-}
-
-/*
- * gst_avi_index_entry:
- * @avi: Avi object
- * @stream_nr: stream number
- * @time: seek time position
- *
- * Finds the index entry which time is less or equal than the requested time.
- *
- * Returns: the found index entry or %NULL
- */
-static gst_avi_index_entry *
-gst_avi_demux_index_entry_for_time (GstAviDemux * avi,
- gint stream_nr, guint64 time)
-{
- gst_avi_index_entry *entry = NULL;
- guint n;
-
- GST_LOG_OBJECT (avi, "stream_nr:%d , time:%" GST_TIME_FORMAT,
- stream_nr, GST_TIME_ARGS (time));
-
- entry = gst_util_array_binary_search (avi->index_entries,
- avi->index_size,
- sizeof (gst_avi_index_entry),
- (GCompareDataFunc) gst_avi_demux_index_entry_search,
- GST_SEARCH_MODE_BEFORE, &time, NULL);
-
- n = entry - avi->index_entries;
- if (entry == NULL) {
- entry = &avi->index_entries[0];
- n = 0;
- while (entry->stream_nr != stream_nr && n < avi->index_size - 1) {
- n++;
- entry = &avi->index_entries[n];
- }
- } else if (entry->stream_nr != stream_nr) {
- while (entry->stream_nr != stream_nr && n > 0) {
- n--;
- entry = &avi->index_entries[n];
- }
- }
-
- GST_LOG_OBJECT (avi,
- "best at entry %u / ts:%" GST_TIME_FORMAT " / dur:%" GST_TIME_FORMAT
- " flags:%02x", n, GST_TIME_ARGS (entry->ts), GST_TIME_ARGS (entry->dur),
- entry->flags);
-
- return entry;
-}
@@ -402,3 +285,3 @@ gst_avi_demux_get_src_formats (GstPad * pad)
{
- avi_stream_context *stream = gst_pad_get_element_private (pad);
+ GstAviStream *stream = gst_pad_get_element_private (pad);
@@ -423,3 +306,3 @@ gst_avi_demux_get_src_formats (GstPad * pad)
static inline GstClockTime
-avi_stream_convert_bytes_to_time_unchecked (avi_stream_context * stream,
+avi_stream_convert_bytes_to_time_unchecked (GstAviStream * stream,
guint64 bytes)
@@ -429,5 +312,12 @@ avi_stream_convert_bytes_to_time_unchecked (avi_stream_context * stream,
+static inline guint64
+avi_stream_convert_time_to_bytes_unchecked (GstAviStream * stream,
+ GstClockTime time)
+{
+ return gst_util_uint64_scale (time, stream->strf.auds->av_bps, GST_SECOND);
+}
+
/* assumes stream->strh->rate != 0 */
static inline GstClockTime
-avi_stream_convert_frames_to_time_unchecked (avi_stream_context * stream,
+avi_stream_convert_frames_to_time_unchecked (GstAviStream * stream,
guint64 frames)
@@ -438,2 +328,10 @@ avi_stream_convert_frames_to_time_unchecked (avi_stream_context * stream,
+static inline guint64
+avi_stream_convert_time_to_frames_unchecked (GstAviStream * stream,
+ GstClockTime time)
+{
+ return gst_util_uint64_scale (time, stream->strh->rate,
+ stream->strh->scale * GST_SECOND);
+}
+
static gboolean
@@ -443,3 +341,3 @@ gst_avi_demux_src_convert (GstPad * pad,
{
- avi_stream_context *stream = gst_pad_get_element_private (pad);
+ GstAviStream *stream = gst_pad_get_element_private (pad);
gboolean res = TRUE;
@@ -474,18 +372,6 @@ gst_avi_demux_src_convert (GstPad * pad,
case GST_FORMAT_DEFAULT:
- {
- gdouble error;
-
- *dest_value = gst_util_uint64_scale (src_value, stream->strh->rate,
+ *dest_value =
+ gst_util_uint64_scale_round (src_value, stream->strh->rate,
stream->strh->scale * GST_SECOND);
-
- /* Attempt to round to nearest integer: if the difference is more
- * than 0.5 (less than -0.5), it means that gst_util_uint64_scale()
- * just truncated an integer, while it had to be rounded
- */
- error = *dest_value * GST_SECOND -
- src_value * stream->strh->rate / stream->strh->scale;
- if (error <= -0.5)
- *dest_value += 1;
break;
- }
default:
@@ -551,3 +437,3 @@ gst_avi_demux_handle_src_query (GstPad * pad, GstQuery * query)
- avi_stream_context *stream = gst_pad_get_element_private (pad);
+ GstAviStream *stream = gst_pad_get_element_private (pad);
@@ -577,3 +463,3 @@ gst_avi_demux_handle_src_query (GstPad * pad, GstQuery * query)
stream->current_byte, GST_TIME_ARGS (pos));
- } else if (stream->total_frames != 0 && stream->total_bytes != 0) {
+ } else if (stream->idx_n != 0 && stream->total_bytes != 0) {
/* calculate timestamps based on percentage of length */
@@ -584,3 +470,3 @@ gst_avi_demux_handle_src_query (GstPad * pad, GstQuery * query)
pos = gst_util_uint64_scale (xlen, stream->current_frame,
- stream->total_frames);
+ stream->idx_n);
GST_DEBUG_OBJECT (avi, "VBR perc convert frame %u, time %"
@@ -633,6 +519,6 @@ gst_avi_demux_handle_src_query (GstPad * pad, GstQuery * query)
GST_DEBUG_OBJECT (query, "total frames is %" G_GUINT32_FORMAT,
- stream->total_frames);
+ stream->idx_n);
- if (stream->total_frames >= 0)
- gst_query_set_duration (query, fmt, stream->total_frames);
+ if (stream->idx_n >= 0)
+ gst_query_set_duration (query, fmt, stream->idx_n);
else if (gst_pad_query_convert (pad, GST_FORMAT_TIME,
@@ -657,10 +543,2 @@ gst_avi_demux_handle_src_query (GstPad * pad, GstQuery * query)
seekable = FALSE;
- } else {
- if (avi->index_entries == NULL) {
- seekable = FALSE;
- /* FIXME: when building index_entried, count keyframes
- if (!(avi->key_frame_ct > 1))
- seekable = FALSE;
- */
- }
}
@@ -794,5 +672,4 @@ gst_avi_demux_peek_chunk_info (GstAviDemux * avi, guint32 * tag, guint32 * size)
- if (gst_adapter_available (avi->adapter) < 8) {
+ if (gst_adapter_available (avi->adapter) < 8)
return FALSE;
- }
@@ -821,5 +698,4 @@ gst_avi_demux_peek_chunk (GstAviDemux * avi, guint32 * tag, guint32 * size)
- if (!gst_avi_demux_peek_chunk_info (avi, tag, size)) {
- return FALSE;
- }
+ if (!gst_avi_demux_peek_chunk_info (avi, tag, size))
+ goto peek_failed;
@@ -829,9 +705,5 @@ gst_avi_demux_peek_chunk (GstAviDemux * avi, guint32 * tag, guint32 * size)
* wants to handle 0 size chunk */
- if (!(*size) || (*size) >= (1 << 30)) {
- GST_INFO ("Invalid/unexpected chunk size %d for tag %" GST_FOURCC_FORMAT,
- *size, GST_FOURCC_ARGS (*tag));
- /* chain should give up */
- avi->abort_buffering = TRUE;
- return FALSE;
- }
+ if (!(*size) || (*size) >= (1 << 30))
+ goto strange_size;
+
peek_size = (*size + 1) & ~1;
@@ -839,8 +711,30 @@ gst_avi_demux_peek_chunk (GstAviDemux * avi, guint32 * tag, guint32 * size)
- GST_DEBUG ("Need to peek chunk of %d bytes to read chunk %" GST_FOURCC_FORMAT
+ GST_DEBUG_OBJECT (avi,
+ "Need to peek chunk of %d bytes to read chunk %" GST_FOURCC_FORMAT
", %d bytes available", *size, GST_FOURCC_ARGS (*tag), available);
- if (available >= (8 + peek_size)) {
- return TRUE;
- } else {
+ if (available < (8 + peek_size))
+ goto need_more;
+
+ return TRUE;
+
+ /* ERRORS */
+peek_failed:
+ {
+ GST_INFO_OBJECT (avi, "Failed to peek");
+ return FALSE;
+ }
+strange_size:
+ {
+ GST_INFO_OBJECT (avi,
+ "Invalid/unexpected chunk size %d for tag %" GST_FOURCC_FORMAT, *size,
+ GST_FOURCC_ARGS (*tag));
+ /* chain should give up */
+ avi->abort_buffering = TRUE;
+ return FALSE;
+ }
+need_more:
+ {
+ GST_INFO_OBJECT (avi, "need more %d < %" G_GUINT32_FORMAT,
+ available, 8 + peek_size);
return FALSE;
@@ -1095,2 +989,3 @@ too_small:
+#if 0
/*
@@ -1115,3 +1010,3 @@ static gboolean
gst_avi_demux_parse_subindex (GstAviDemux * avi,
- GstBuffer * buf, avi_stream_context * stream, GList ** _entries_list)
+ GstBuffer * buf, GstAviStream * stream, GList ** _entries_list)
{
@@ -1204,3 +1099,3 @@ gst_avi_demux_parse_subindex (GstAviDemux * avi,
next_ts = avi_stream_convert_frames_to_time_unchecked (stream,
- stream->total_frames + 1);
+ stream->idx_n + 1);
}
@@ -1216,6 +1111,6 @@ gst_avi_demux_parse_subindex (GstAviDemux * avi,
entry->bytes_before = stream->total_bytes;
- entry->frames_before = stream->total_frames;
+ entry->frames_before = stream->idx_n;
stream->total_bytes += entry->size;
- stream->total_frames++;
+ stream->idx_n++;
if (stream->strh->type == GST_RIFF_FCC_auds) {
@@ -1274,2 +1169,3 @@ out_of_mem:
}
+#endif
@@ -1292,3 +1188,3 @@ gst_avi_demux_read_subindexes_push (GstAviDemux * avi,
for (n = 0; n < avi->num_streams; n++) {
- avi_stream_context *stream = &avi->stream[n];
+ GstAviStream *stream = &avi->stream[n];
@@ -1328,2 +1224,3 @@ gst_avi_demux_read_subindexes_push (GstAviDemux * avi,
+#if 0
/*
@@ -1344,3 +1241,3 @@ gst_avi_demux_read_subindexes_pull (GstAviDemux * avi,
for (n = 0; n < avi->num_streams; n++) {
- avi_stream_context *stream = &avi->stream[n];
+ GstAviStream *stream = &avi->stream[n];
@@ -1378,2 +1275,3 @@ gst_avi_demux_read_subindexes_pull (GstAviDemux * avi,
}
+#endif
@@ -1516,3 +1414,3 @@ gst_avi_demux_parse_stream (GstAviDemux * avi, GstBuffer * buf)
{
- avi_stream_context *stream;
+ GstAviStream *stream;
GstElementClass *klass;
@@ -1854,3 +1752,3 @@ gst_avi_demux_parse_stream (GstAviDemux * avi, GstBuffer * buf)
stream->total_bytes = 0;
- stream->total_frames = 0;
+ stream->idx_n = 0;
stream->total_blocks = 0;
@@ -1901,3 +1799,3 @@ fail:
gst_buffer_unref (stream->extradata);
- memset (stream, 0, sizeof (avi_stream_context));
+ memset (stream, 0, sizeof (GstAviStream));
avi->num_streams++;
@@ -1968,19 +1866,164 @@ gst_avi_demux_parse_odml (GstAviDemux * avi, GstBuffer * buf)
+/* Index helper */
+static guint
+gst_avi_demux_index_last (GstAviDemux * avi, GstAviStream * stream)
+{
+ return stream->idx_n - 1;
+}
+
+/* find a previous entry in the index with the given flags */
+static guint
+gst_avi_demux_index_prev (GstAviDemux * avi, GstAviStream * stream,
+ guint last, guint32 flags)
+{
+ GstAviIndexEntry *entry;
+ guint i;
+
+ for (i = last; i > 0; i--) {
+ entry = &stream->index[i - 1];
+ if ((entry->flags & flags) == flags) {
+ return i;
+ }
+ }
+ return 0;
+}
+
+static guint
+gst_avi_demux_index_next (GstAviDemux * avi, GstAviStream * stream,
+ guint last, guint32 flags)
+{
+ GstAviIndexEntry *entry;
+ gint i;
+
+ for (i = last + 1; i < stream->idx_n; i++) {
+ entry = &stream->index[i];
+ if ((entry->flags & flags) == flags) {
+ return i;
+ }
+ }
+ return stream->idx_n - 1;
+}
+
+static guint
+gst_avi_demux_index_entry_search (GstAviIndexEntry * entry, guint64 * total)
+{
+ if (entry->total < *total)
+ return -1;
+ else if (entry->total > *total)
+ return 1;
+ return 0;
+}
+
/*
- * Sort helper for index entries that sorts by index time.
- * If times are equal we sort by stream number.
+ * gst_avi_index_entry:
+ * @avi: Avi object
+ * @stream: the stream
+ * @time: seek time position
+ *
+ * Finds the index entry which time is less or equal than the requested time.
+ *
+ * Returns: the found position in the index.
*/
-static gint
-sort (gst_avi_index_entry * a, gst_avi_index_entry * b)
+static guint
+gst_avi_demux_index_for_time (GstAviDemux * avi,
+ GstAviStream * stream, guint64 time)
{
- if (a->ts > b->ts)
- return 1;
- else if (a->ts < b->ts)
- return -1;
- else
- return a->stream_nr - b->stream_nr;
+ guint index = -1;
+ guint64 total;
+
+ GST_LOG_OBJECT (avi, "search time:%" GST_TIME_FORMAT, GST_TIME_ARGS (time));
+
+ /* easy (and common) cases */
+ if (time == 0 || stream->idx_n == 0)
+ return 0;
+ if (time >= stream->idx_duration)
+ return stream->idx_n - 1;
+
+ /* figure out where we need to go. For that we convert the time to an
+ * index entry or we convert it to a total and then do a binary search. */
+ if (stream->is_vbr) {
+ /* VBR stream next timestamp */
+ if (stream->strh->type == GST_RIFF_FCC_auds) {
+ total = avi_stream_convert_time_to_frames_unchecked (stream, time);
+ } else {
+ index = avi_stream_convert_time_to_frames_unchecked (stream, time);
+ }
+ } else {
+ /* constant rate stream */
+ total = avi_stream_convert_time_to_bytes_unchecked (stream, time);
+ }
+
+ if (index == -1) {
+ GstAviIndexEntry *entry;
+
+ /* no index, find index with binary search on total */
+ GST_LOG_OBJECT (avi, "binary search for entry with total %"
+ G_GUINT64_FORMAT, total);
+
+ entry = gst_util_array_binary_search (stream->index,
+ stream->idx_n, sizeof (GstAviIndexEntry),
+ (GCompareDataFunc) gst_avi_demux_index_entry_search,
+ GST_SEARCH_MODE_BEFORE, &total, NULL);
+
+ if (entry == NULL) {
+ GST_LOG_OBJECT (avi, "not found, assume index 0");
+ index = 0;
+ } else {
+ index = entry - stream->index;
+ GST_LOG_OBJECT (avi, "found at %u", index);
+ }
+ }
+
+ return index;
+}
+
+static void
+gst_avi_demux_get_entry_info (GstAviDemux * avi, GstAviStream * stream,
+ guint entry_n, GstClockTime * timestamp, GstClockTime * duration,
+ guint64 * offset, guint64 * size, gboolean * keyframe)
+{
+ GstAviIndexEntry *entry;
+ GstClockTime next_ts = 0, ts = 0;
+
+ entry = &stream->index[entry_n];
+
+ if (stream->is_vbr) {
+ /* VBR stream next timestamp */
+ if (stream->strh->type == GST_RIFF_FCC_auds) {
+ if (timestamp || duration)
+ ts = avi_stream_convert_frames_to_time_unchecked (stream, entry->total);
+ if (duration)
+ next_ts = avi_stream_convert_frames_to_time_unchecked (stream,
+ entry->total + entry->size);
+ } else {
+ if (timestamp || duration)
+ ts = avi_stream_convert_frames_to_time_unchecked (stream, entry_n);
+ if (duration)
+ next_ts = avi_stream_convert_frames_to_time_unchecked (stream,
+ entry_n + 1);
+ }
+ } else {
+ /* constant rate stream */
+ if (timestamp || duration)
+ ts = avi_stream_convert_bytes_to_time_unchecked (stream, entry->total);
+ if (duration)
+ next_ts = avi_stream_convert_bytes_to_time_unchecked (stream,
+ entry->total + entry->size);
+ }
+ if (timestamp)
+ *timestamp = ts;
+ if (duration)
+ *duration = next_ts - ts;
+
+ if (offset)
+ *offset = entry->offset;
+ if (size)
+ *size = entry->size;
+ if (keyframe)
+ *keyframe = (entry->flags & GST_AVI_INDEX_ENTRY_FLAG_KEYFRAME) != 0;
}
+
/*
- * gst_avi_demux_parse_index2:
+ * gst_avi_demux_parse_index:
* @avi: calling element (used for debugging/errors).
@@ -1992,3 +2035,3 @@ sort (gst_avi_index_entry * a, gst_avi_index_entry * b)
static void
-gst_avi_demux_parse_index2 (GstAviDemux * avi, GstBuffer * buf)
+gst_avi_demux_parse_index (GstAviDemux * avi, GstBuffer * buf)
{
@@ -2000,3 +2043,3 @@ gst_avi_demux_parse_index2 (GstAviDemux * avi, GstBuffer * buf)
GstClockTime stamp;
- avi_stream_context *stream;
+ GstAviStream *stream;
#ifndef GST_DISABLE_GST_DEBUG
@@ -2066,4 +2109,16 @@ gst_avi_demux_parse_index2 (GstAviDemux * avi, GstBuffer * buf)
+ /* update stats */
+ entry.total = stream->total_bytes;
+ stream->total_bytes += entry.size;
+ if (stream->strh->type == GST_RIFF_FCC_auds) {
+ if (stream->strf.auds->blockalign > 0)
+ stream->total_blocks +=
+ (entry.size + stream->strf.auds->blockalign -
+ 1) / stream->strf.auds->blockalign;
+ else
+ stream->total_blocks++;
+ }
+
/* add to the index */
- if (stream->idx_n >= stream->idx_max) {
+ if (G_UNLIKELY (stream->idx_n >= stream->idx_max)) {
/* we need to make some more room */
@@ -2084,10 +2139,3 @@ gst_avi_demux_parse_index2 (GstAviDemux * avi, GstBuffer * buf)
}
- if (stream->idx_n == 0) {
- /* first entry, set total bytes to 0 */
- entry.total = 0;
- } else {
- /* calculate bytes based on previous entry */
- entry.total = stream->index[stream->idx_n - 1].total +
- stream->index[stream->idx_n - 1].size;
- }
+
/* and copy */
@@ -2114,7 +2162,7 @@ gst_avi_demux_parse_index2 (GstAviDemux * avi, GstBuffer * buf)
- if (!(stream = &avi->stream[i]))
+ if (G_UNLIKELY (!(stream = &avi->stream[i])))
continue;
- if (!stream->strh)
+ if (G_UNLIKELY (!stream->strh))
continue;
- if (!stream->index || stream->idx_n == 0)
+ if (G_UNLIKELY (!stream->index || stream->idx_n == 0))
continue;
@@ -2179,2 +2227,3 @@ out_of_mem:
+#if 0
/*
@@ -2225,3 +2274,3 @@ gst_avi_demux_parse_index (GstAviDemux * avi,
gst_riff_index_entry entry, *_entry;
- avi_stream_context *stream;
+ GstAviStream *stream;
guint stream_nr;
@@ -2292,3 +2341,3 @@ gst_avi_demux_parse_index (GstAviDemux * avi,
next_ts = avi_stream_convert_frames_to_time_unchecked (stream,
- stream->total_frames + 1);
+ stream->idx_n + 1);
}
@@ -2304,6 +2353,6 @@ gst_avi_demux_parse_index (GstAviDemux * avi,
target->bytes_before = stream->total_bytes;
- target->frames_before = stream->total_frames;
+ target->frames_before = stream->idx_n;
stream->total_bytes += target->size;
- stream->total_frames++;
+ stream->idx_n++;
if (stream->strh->type == GST_RIFF_FCC_auds) {
@@ -2322,3 +2371,3 @@ gst_avi_demux_parse_index (GstAviDemux * avi,
GST_TIME_FORMAT,
- target->index_nr, stream->total_frames - 1, target->flags,
+ target->index_nr, stream->idx_n - 1, target->flags,
target->stream_nr, target->size, target->offset,
@@ -2359,2 +2408,3 @@ out_of_mem:
}
+#endif
@@ -2363,4 +2413,2 @@ out_of_mem:
* @avi: avi demuxer object.
- * @index: list of index entries, returned by this function.
- * @alloc_list: list of allocated data, returned by this function.
*
@@ -2369,4 +2417,3 @@ out_of_mem:
static void
-gst_avi_demux_stream_index (GstAviDemux * avi,
- GList ** index, GList ** alloc_list)
+gst_avi_demux_stream_index (GstAviDemux * avi)
{
@@ -2380,5 +2427,2 @@ gst_avi_demux_stream_index (GstAviDemux * avi,
- *alloc_list = NULL;
- *index = NULL;
-
/* get chunk information */
@@ -2425,6 +2469,4 @@ gst_avi_demux_stream_index (GstAviDemux * avi,
- gst_avi_demux_parse_index2 (avi, buf);
- gst_avi_demux_parse_index (avi, buf, index);
- if (*index)
- *alloc_list = g_list_append (*alloc_list, (*index)->data);
+ gst_avi_demux_parse_index (avi, buf);
+ gst_buffer_unref (buf);
@@ -2434,3 +2476,3 @@ gst_avi_demux_stream_index (GstAviDemux * avi,
gint i;
- avi_stream_context *stream;
+ GstAviStream *stream;
@@ -2439,3 +2481,3 @@ gst_avi_demux_stream_index (GstAviDemux * avi,
GST_DEBUG_OBJECT (avi, "stream %u: %u frames, %" G_GINT64_FORMAT " bytes",
- i, stream->total_frames, stream->total_bytes);
+ i, stream->idx_n, stream->total_bytes);
}
@@ -2615,2 +2657,3 @@ done:
+#if 0
/*
@@ -2660,3 +2703,5 @@ wrong_size:
}
+#endif
+#if 0
/*
@@ -2690,3 +2735,5 @@ gst_avi_demux_next_data_buffer (GstAviDemux * avi, guint64 * offset,
}
+#endif
+#if 0
/*
@@ -2709,3 +2756,3 @@ gst_avi_demux_stream_scan (GstAviDemux * avi,
gst_avi_index_entry *entry, *entries = NULL;
- avi_stream_context *stream;
+ GstAviStream *stream;
GstFormat format;
@@ -2790,5 +2837,5 @@ gst_avi_demux_stream_scan (GstAviDemux * avi,
entry->ts = avi_stream_convert_frames_to_time_unchecked (stream,
- stream->total_frames);
+ stream->idx_n);
entry->dur = avi_stream_convert_frames_to_time_unchecked (stream,
- stream->total_frames + 1);
+ stream->idx_n + 1);
} else {
@@ -2805,4 +2852,4 @@ gst_avi_demux_stream_scan (GstAviDemux * avi,
stream->total_bytes += entry->size;
- entry->frames_before = stream->total_frames;
- stream->total_frames++;
+ entry->frames_before = stream->idx_n;
+ stream->idx_n++;
stream->idx_duration = entry->ts + entry->dur;
@@ -2851,5 +2898,5 @@ gst_avi_demux_stream_scan (GstAviDemux * avi,
entry->ts = avi_stream_convert_frames_to_time_unchecked (stream,
- stream->total_frames);
+ stream->idx_n);
entry->dur = avi_stream_convert_frames_to_time_unchecked (stream,
- stream->total_frames + 1);
+ stream->idx_n + 1);
} else {
@@ -2866,4 +2913,4 @@ gst_avi_demux_stream_scan (GstAviDemux * avi,
stream->total_bytes += entry->size;
- entry->frames_before = stream->total_frames;
- stream->total_frames++;
+ entry->frames_before = stream->idx_n;
+ stream->idx_n++;
@@ -2894,3 +2941,5 @@ gst_avi_demux_stream_scan (GstAviDemux * avi,
}
+#endif
+#if 0
/*
@@ -2911,3 +2960,3 @@ gst_avi_demux_massage_index (GstAviDemux * avi,
gst_avi_index_entry *entry;
- avi_stream_context *stream;
+ GstAviStream *stream;
guint i;
@@ -2937,3 +2986,3 @@ gst_avi_demux_massage_index (GstAviDemux * avi,
/* only chop streams that have exactly *one* chunk */
- if (avi->stream[i].total_frames != 1)
+ if (avi->stream[i].idx_n != 1)
continue;
@@ -3085,3 +3134,3 @@ gst_avi_demux_massage_index (GstAviDemux * avi,
GST_LOG_OBJECT (avi, "Stream %d, %d frames, %8" G_GUINT64_FORMAT " bytes",
- i, avi->stream[i].total_frames, avi->stream[i].total_bytes);
+ i, avi->stream[i].idx_n, avi->stream[i].total_bytes);
}
@@ -3106,2 +3155,3 @@ out_of_mem:
}
+#endif
@@ -3118,3 +3168,3 @@ gst_avi_demux_calculate_durations_from_index (GstAviDemux * avi)
GstClockTime duration, hduration;
- avi_stream_context *streamc = &avi->stream[stream];
+ GstAviStream *streamc = &avi->stream[stream];
gst_riff_strh *strh = streamc->strh;
@@ -3150,3 +3200,3 @@ gst_avi_demux_calculate_durations_from_index (GstAviDemux * avi)
for (stream = 0; stream < avi->num_streams; stream++) {
- avi_stream_context *streamc = &avi->stream[stream];
+ GstAviStream *streamc = &avi->stream[stream];
@@ -3182,3 +3232,3 @@ gst_avi_demux_push_event (GstAviDemux * avi, GstEvent * event)
for (i = 0; i < avi->num_streams; i++) {
- avi_stream_context *stream = &avi->stream[i];
+ GstAviStream *stream = &avi->stream[i];
@@ -3483,3 +3533,5 @@ gst_avi_demux_stream_header_pull (GstAviDemux * avi)
guint32 tag;
+#if 0
GList *index = NULL, *alloc = NULL;
+#endif
guint offset = 4;
@@ -3686,2 +3738,3 @@ skipping_done:
+#if 0
/* create or read stream index (for seeking) */
@@ -3692,5 +3745,7 @@ skipping_done:
if (!index) {
+#endif
if (avi->avih->flags & GST_RIFF_AVIH_HASINDEX) {
- gst_avi_demux_stream_index (avi, &index, &alloc);
+ gst_avi_demux_stream_index (avi);
}
+#if 0
/* some indexes are incomplete, continue streaming from there */
@@ -3703,5 +3758,3 @@ skipping_done:
goto no_index;
-
- if (!gst_avi_demux_massage_index (avi, index, alloc))
- goto no_index;
+#endif
@@ -3715,2 +3768,5 @@ skipping_done:
+ /* do initial seek to the configured segment values */
+ gst_avi_demux_do_seek (avi, &avi->segment);
+
if (avi->seek_event)
@@ -3771,2 +3827,3 @@ no_streams:
}
+#if 0
no_index:
@@ -3782,2 +3839,3 @@ no_index:
}
+#endif
pull_range_failed:
@@ -3790,2 +3848,36 @@ pull_range_failed:
+/* move a stream to an offset */
+static void
+gst_avi_demux_move_stream (GstAviDemux * avi, GstAviStream * stream,
+ GstSegment * segment, guint index)
+{
+ GST_DEBUG_OBJECT (avi, "Move stream %d to %u", stream->num, index);
+
+ if (segment->rate < 0.0) {
+ guint next_key;
+ /* Because we don't know the frame order we need to push from the prev keyframe
+ * to the next keyframe. If there is a smart decoder downstream he will notice
+ * that there are too many encoded frames send and return UNEXPECTED when there
+ * are enough decoded frames to fill the segment. */
+ next_key = gst_avi_demux_index_next (avi, stream, index,
+ GST_AVI_INDEX_ENTRY_FLAG_KEYFRAME);
+
+ stream->start_entry = 0;
+ stream->step_entry = index;
+ stream->current_entry = index;
+ stream->stop_entry = next_key;
+
+ GST_DEBUG_OBJECT (avi, "reverse seek: start %u, step %u, stop %u",
+ stream->start_entry, stream->step_entry, stream->stop_entry);
+ } else {
+ stream->start_entry = index;
+ stream->step_entry = index;
+ stream->stop_entry = gst_avi_demux_index_last (avi, stream);
+ }
+ if (stream->current_entry != index) {
+ stream->current_entry = index;
+ stream->discont = TRUE;
+ }
+}
+
/*
@@ -3798,4 +3890,6 @@ gst_avi_demux_do_seek (GstAviDemux * avi, GstSegment * segment)
gboolean keyframe;
- gst_avi_index_entry *entry, *kentry;
- gint old_entry;
+ guint i, index;
+ GstAviStream *stream;
+ GstClockTime timestamp, duration;
+ gboolean kentry;
@@ -3804,63 +3898,33 @@ gst_avi_demux_do_seek (GstAviDemux * avi, GstSegment * segment)
- /* FIXME: if we seek in an openDML file, we will have multiple
- * primary levels. Seeking in between those will cause havoc. */
+ /* FIXME, this code assumes the main stream with keyframes is stream 0,
+ * which is mostly correct... */
+ stream = &avi->stream[0];
- /* save old position so we can see if we must mark a discont. */
- old_entry = avi->current_entry;
+ /* get the entry index for the requested position */
+ index = gst_avi_demux_index_for_time (avi, stream, seek_time);
- /* get the entry for the requested position, which is always in last_stop.
- * we search the index entry 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... */
- if (!(entry = gst_avi_demux_index_entry_for_time (avi, 0, seek_time)))
- goto no_entry;
+ /* take a look at the entry info */
+ gst_avi_demux_get_entry_info (avi, stream, index,
+ NULL, NULL, NULL, NULL, &kentry);
- GST_DEBUG_OBJECT (avi,
- "Got requested 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));
+ GST_DEBUG_OBJECT (avi, "Got entry %u", index);
/* check if we are already on a keyframe */
- if (!(entry->flags & GST_AVI_INDEX_ENTRY_FLAG_KEYFRAME)) {
+ if (!kentry) {
+ GST_DEBUG_OBJECT (avi, "not keyframe, searching back");
/* now go to the previous keyframe, this is where we should start
* decoding from. */
- if (!(kentry = gst_avi_demux_index_prev (avi, 0, entry->index_nr,
- GST_AVI_INDEX_ENTRY_FLAG_KEYFRAME))) {
- goto no_entry;
- }
- } else {
- /* we were on a keyframe */
- kentry = entry;
- }
-
- GST_DEBUG_OBJECT (avi,
- "Got keyframe entry %d [stream:%d / ts:%" GST_TIME_FORMAT
- " / duration:%" GST_TIME_FORMAT "]", kentry->index_nr,
- entry->stream_nr, GST_TIME_ARGS (kentry->ts),
- GST_TIME_ARGS (kentry->dur));
-
- /* we must start decoding at the keyframe */
- avi->current_entry = kentry->index_nr;
-
- if (segment->rate < 0.0) {
- gst_avi_index_entry *next_keyframe;
-
- /* Because we don't know the frame order we need to push from the prev keyframe
- * to the next keyframe. If there is a smart decoder downstream he will notice
- * that there are too many encoded frames send and return UNEXPECTED when there
- * are enough decoded frames to fill the segment.
- */
- next_keyframe =
- gst_avi_demux_index_next (avi, 0, kentry->index_nr,
+ index = gst_avi_demux_index_prev (avi, stream, index,
GST_AVI_INDEX_ENTRY_FLAG_KEYFRAME);
- if (!next_keyframe)
- next_keyframe = gst_avi_demux_index_last (avi, 0);
+ GST_DEBUG_OBJECT (avi, "previous keyframe at %u", index);
+ }
- avi->reverse_start_index = kentry->index_nr;
- avi->reverse_stop_index = next_keyframe->index_nr;
+ /* take a look at the final entry */
+ gst_avi_demux_get_entry_info (avi, stream, index,
+ &timestamp, &duration, NULL, NULL, NULL);
- GST_DEBUG_OBJECT (avi, "reverse seek: start idx (%d) and stop idx (%d)",
- avi->reverse_start_index, avi->reverse_stop_index);
- }
+ GST_DEBUG_OBJECT (avi,
+ "Got keyframe entry %d [ts:%" GST_TIME_FORMAT
+ " / duration:%" GST_TIME_FORMAT "]", index,
+ GST_TIME_ARGS (timestamp), GST_TIME_ARGS (duration));
@@ -3869,13 +3933,26 @@ gst_avi_demux_do_seek (GstAviDemux * avi, GstSegment * segment)
* to the time of the keyframe. */
- seek_time = avi->index_entries[avi->current_entry].ts;
+ seek_time = timestamp;
}
-next:
- /* if we changed position, mark a DISCONT on all streams */
- if (avi->current_entry != old_entry) {
- gint i;
+ /* move the main stream */
+ gst_avi_demux_move_stream (avi, stream, segment, index);
- for (i = 0; i < avi->num_streams; i++) {
- avi->stream[i].discont = TRUE;
+ /* now set DISCONT and align the other streams */
+ for (i = 0; i < avi->num_streams; i++) {
+ GstAviStream *ostream;
+
+ ostream = &avi->stream[i];
+ if (ostream == stream)
+ continue;
+
+ /* get the entry index for the requested position */
+ index = gst_avi_demux_index_for_time (avi, ostream, seek_time);
+
+ gst_avi_demux_get_entry_info (avi, ostream, index,
+ NULL, NULL, NULL, NULL, &kentry);
+ if (!kentry) {
+ index = gst_avi_demux_index_prev (avi, ostream, index,
+ GST_AVI_INDEX_ENTRY_FLAG_KEYFRAME);
}
+ gst_avi_demux_move_stream (avi, ostream, segment, index);
}
@@ -3890,14 +3967,2 @@ next:
return TRUE;
-
-no_entry:
- {
- /* we could not find an entry for the given time */
- 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;
-
- goto next;
- }
}
@@ -3982,3 +4047,2 @@ gst_avi_demux_handle_seek (GstAviDemux * avi, GstPad * pad, GstEvent * event)
}
-
/* do the seek, seeksegment.last_stop contains the new position, this
@@ -4079,3 +4143,3 @@ swap_line (guint8 * d1, guint8 * d2, guint8 * tmp, gint bytes)
static GstBuffer *
-gst_avi_demux_invert (avi_stream_context * stream, GstBuffer * buf)
+gst_avi_demux_invert (GstAviStream * stream, GstBuffer * buf)
{
@@ -4130,3 +4194,3 @@ gst_avi_demux_invert (avi_stream_context * stream, GstBuffer * buf)
static GstFlowReturn
-gst_avi_demux_combine_flows (GstAviDemux * avi, avi_stream_context * stream,
+gst_avi_demux_combine_flows (GstAviDemux * avi, GstAviStream * stream,
GstFlowReturn ret)
@@ -4144,3 +4208,3 @@ gst_avi_demux_combine_flows (GstAviDemux * avi, avi_stream_context * stream,
for (i = 0; i < avi->num_streams; i++) {
- avi_stream_context *ostream = &avi->stream[i];
+ GstAviStream *ostream = &avi->stream[i];
@@ -4159,34 +4223,3 @@ done:
-/*
- * prepare the avi element for a reverse jump to a prev keyframe
- * this function will return the start entry. if the function returns
- * NULL there was no prev keyframe.
- */
-static gst_avi_index_entry *
-gst_avi_demux_step_reverse (GstAviDemux * avi)
-{
- gst_avi_index_entry *entry;
- gint i;
-
- avi->reverse_stop_index = avi->reverse_start_index;
- entry =
- gst_avi_demux_index_prev (avi, 0, avi->reverse_stop_index,
- GST_AVI_INDEX_ENTRY_FLAG_KEYFRAME);
- if (!entry) {
- GST_DEBUG_OBJECT (avi, "no valid index entry found index %d",
- avi->reverse_stop_index);
- return NULL;
- }
- avi->current_entry = avi->reverse_start_index = entry->index_nr;
- GST_DEBUG_OBJECT (avi,
- "reverse playback jump: start idx (%d) and stop idx (%d)",
- avi->reverse_start_index, avi->reverse_stop_index);
- gst_segment_set_last_stop (&avi->segment, GST_FORMAT_TIME, entry->ts);
- for (i = 0; i < avi->num_streams; i++) {
- avi->stream[i].last_flow = GST_FLOW_OK;
- avi->stream[i].discont = TRUE;
- }
- return entry;
-}
-
+#if 0
/*
@@ -4199,3 +4232,3 @@ gst_avi_demux_process_next_entry (GstAviDemux * avi)
gboolean processed = FALSE;
- avi_stream_context *stream;
+ GstAviStream *stream;
gst_avi_index_entry *entry;
@@ -4400,2 +4433,234 @@ short_buffer:
}
+#endif
+
+/* move @stream to the next position in its index */
+static GstFlowReturn
+gst_avi_demux_advance (GstAviDemux * avi, GstAviStream * stream,
+ GstFlowReturn ret)
+{
+ guint i;
+
+ /* move to the next entry */
+ stream->current_entry++;
+ stream->current_frame++;
+
+ /* see if we reached the end */
+ if (stream->current_entry >= stream->stop_entry) {
+ if (avi->segment.rate < 0.0) {
+ if (stream->step_entry == stream->start_entry) {
+ /* we stepped all the way to the start, eos */
+ GST_DEBUG_OBJECT (avi, "reverse reached start %u", stream->start_entry);
+ goto eos;
+ }
+ /* backwards, stop becomes step, find a new step */
+ stream->stop_entry = stream->step_entry;
+ stream->step_entry = gst_avi_demux_index_prev (avi, stream,
+ stream->stop_entry, GST_AVI_INDEX_ENTRY_FLAG_KEYFRAME);
+ stream->current_entry = stream->step_entry;
+
+ GST_DEBUG_OBJECT (avi,
+ "reverse playback jump: start %u, step %u, stop %u",
+ stream->start_entry, stream->step_entry, stream->stop_entry);
+
+ /* mark DISCONT */
+ for (i = 0; i < avi->num_streams; i++) {
+ avi->stream[i].last_flow = GST_FLOW_OK;
+ avi->stream[i].discont = TRUE;
+ }
+ } else {
+ /* EOS */
+ GST_DEBUG_OBJECT (avi, "forward reached stop %u", stream->stop_entry);
+ goto eos;
+ }
+ }
+ return ret;
+
+ /* ERROR */
+eos:
+ {
+ GST_DEBUG_OBJECT (avi, "we are EOS");
+ /* setting current_time to -1 marks EOS */
+ stream->current_time = -1;
+ return GST_FLOW_UNEXPECTED;
+ }
+}
+
+static GstFlowReturn
+gst_avi_demux_loop_data (GstAviDemux * avi)
+{
+ GstFlowReturn ret = GST_FLOW_OK;
+ guint64 min_time;
+ guint stream_num, i;
+ GstAviStream *stream;
+ gboolean processed = FALSE;
+ GstBuffer *buf;
+ guint64 offset, size;
+ GstClockTime timestamp, duration;
+ gboolean keyframe;
+
+ do {
+ /* first find the stream with the lowest current position, this is the one
+ * we should push from next */
+ min_time = G_MAXUINT64;
+ stream_num = -1;
+ for (i = 0; i < avi->num_streams; i++) {
+ guint64 position;
+
+ stream = &avi->stream[i];
+ position = stream->current_time;
+
+ /* position of -1 is EOS */
+ if (position != -1 && position < min_time) {
+ min_time = position;
+ stream_num = i;
+ }
+ }
+
+ /* all are EOS */
+ if (G_UNLIKELY (stream_num == -1)) {
+ GST_DEBUG_OBJECT (avi, "all streams are EOS");
+ goto eos;
+ }
+
+ /* we have the stream now */
+ stream = &avi->stream[stream_num];
+
+ /* skip streams without pads */
+ if (!stream->pad) {
+ GST_DEBUG_OBJECT (avi, "skipping entry from stream %d without pad",
+ stream_num);
+ goto next;
+ }
+
+ /* get the timing info for the entry */
+ gst_avi_demux_get_entry_info (avi, stream, stream->current_entry,
+ &timestamp, &duration, &offset, &size, &keyframe);
+
+ /* skip empty entries */
+ if (size == 0) {
+ GST_DEBUG_OBJECT (avi, "Skipping entry %d (%d, %p)",
+ stream->current_entry, size, stream->pad);
+ goto next;
+ }
+
+ if (avi->segment.rate > 0.0) {
+ /* only check this for fowards playback for now */
+ if (keyframe && GST_CLOCK_TIME_IS_VALID (timestamp)
+ && GST_CLOCK_TIME_IS_VALID (avi->segment.stop)
+ && (timestamp > avi->segment.stop)) {
+ goto eos_stop;
+ }
+ }
+
+ /* correct for index offset */
+ offset += avi->index_offset;
+
+ GST_LOG ("reading buffer (size=%d) from stream %d at current pos %"
+ G_GUINT64_FORMAT " (%llx)", size, stream_num, offset, offset);
+
+ /* pull in the data */
+ ret = gst_pad_pull_range (avi->sinkpad, offset, size, &buf);
+ if (ret != GST_FLOW_OK)
+ goto pull_failed;
+
+ /* check for short buffers, this is EOS as well */
+ if (GST_BUFFER_SIZE (buf) < size)
+ goto short_buffer;
+
+ /* invert the picture if needed */
+ buf = gst_avi_demux_invert (stream, buf);
+
+ /* mark non-keyframes */
+ if (!keyframe)
+ GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
+
+ GST_BUFFER_TIMESTAMP (buf) = timestamp;
+ GST_BUFFER_DURATION (buf) = duration;
+ GST_BUFFER_OFFSET (buf) = GST_BUFFER_OFFSET_NONE;
+ GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_OFFSET_NONE;
+
+ gst_buffer_set_caps (buf, GST_PAD_CAPS (stream->pad));
+
+ GST_DEBUG_OBJECT (avi, "Pushing buffer of size %d, offset %"
+ G_GUINT64_FORMAT " and time %"
+ GST_TIME_FORMAT " on pad %s",
+ GST_BUFFER_SIZE (buf), GST_BUFFER_OFFSET (buf),
+ GST_TIME_ARGS (timestamp), GST_PAD_NAME (stream->pad));
+
+ /* update current position in the segment */
+ gst_segment_set_last_stop (&avi->segment, GST_FORMAT_TIME, timestamp);
+
+ /* mark discont when pending */
+ if (stream->discont) {
+ GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
+ stream->discont = FALSE;
+ }
+
+ ret = gst_pad_push (stream->pad, buf);
+
+ /* mark as processed, we increment the frame and byte counters then
+ * leave the while loop and return the GstFlowReturn */
+ processed = TRUE;
+ GST_DEBUG_OBJECT (avi, "Processed buffer %d: %s", stream->current_entry,
+ gst_flow_get_name (ret));
+
+ if (avi->segment.rate < 0) {
+ if (timestamp > avi->segment.stop && ret == GST_FLOW_UNEXPECTED) {
+ /* In reverse playback we can get a GST_FLOW_UNEXPECTED when
+ * we are at the end of the segment, so we just need to jump
+ * back to the previous section. */
+ GST_DEBUG_OBJECT (avi, "downstream has reached end of segment");
+ ret = GST_FLOW_OK;
+ }
+ }
+ next:
+ ret = gst_avi_demux_advance (avi, stream, ret);
+
+ /* combine flows */
+ ret = gst_avi_demux_combine_flows (avi, stream, ret);
+ } while (!processed);
+
+beach:
+ return ret;
+
+ /* special cases */
+eos:
+ {
+ GST_DEBUG_OBJECT (avi, "No samples left for any streams - EOS");
+ ret = GST_FLOW_UNEXPECTED;
+ goto beach;
+ }
+eos_stop:
+ {
+ GST_LOG_OBJECT (avi, "Found keyframe after segment,"
+ " setting EOS (%" GST_TIME_FORMAT " > %" GST_TIME_FORMAT ")",
+ GST_TIME_ARGS (timestamp), GST_TIME_ARGS (avi->segment.stop));
+ ret = GST_FLOW_UNEXPECTED;
+ goto beach;
+ }
+pull_failed:
+ {
+ GST_DEBUG_OBJECT (avi, "pull range failed: pos=%" G_GUINT64_FORMAT
+ " size=%d", offset, size);
+ goto beach;
+ }
+short_buffer:
+ {
+ GST_WARNING_OBJECT (avi, "Short read at offset %" G_GUINT64_FORMAT
+ ", only got %d/%d bytes (truncated file?)", offset,
+ GST_BUFFER_SIZE (buf), size);
+ gst_buffer_unref (buf);
+ ret = GST_FLOW_UNEXPECTED;
+ goto beach;
+ }
+#if 0
+eos_stream:
+ {
+ GST_DEBUG_OBJECT (avi, "No samples left for stream");
+ /* EOS will be raised if all are EOS */
+ ret = GST_FLOW_OK;
+ goto beach;
+ }
+#endif
+}
@@ -4414,7 +4679,2 @@ gst_avi_demux_stream_data (GstAviDemux * avi)
- /* if we have a avi->index_entries[], we don't want to read
- * the stream linearly, but seek to the next ts/index_entry. */
- if (G_LIKELY (avi->index_entries != NULL))
- return gst_avi_demux_process_next_entry (avi);
-
if (G_UNLIKELY (avi->have_eos)) {
@@ -4425,7 +4685,2 @@ gst_avi_demux_stream_data (GstAviDemux * avi)
- /*
- if (!gst_avi_demux_sync (avi, &tag, FALSE))
- return FALSE;
- */
-
/* Iterate until need more data, so adapter won't grow too much */
@@ -4501,3 +4756,3 @@ gst_avi_demux_stream_data (GstAviDemux * avi)
} else {
- avi_stream_context *stream;
+ GstAviStream *stream;
GstClockTime next_ts = 0;
@@ -4521,3 +4776,2 @@ gst_avi_demux_stream_data (GstAviDemux * avi)
-
/* parsing of corresponding header may have failed */
@@ -4659,3 +4913,3 @@ gst_avi_demux_loop (GstPad * pad)
/* process each index entry in turn */
- res = gst_avi_demux_stream_data (avi);
+ res = gst_avi_demux_loop_data (avi);
diff --git a/gst/avi/gstavidemux.h b/gst/avi/gstavidemux.h
index d713fa099..918939296 100644
--- a/gst/avi/gstavidemux.h
+++ b/gst/avi/gstavidemux.h
@@ -51,15 +51,2 @@ G_BEGIN_DECLS
-/* 48 bytes */
-typedef struct {
- guint index_nr; /* = (entry-index_entries)/sizeof(gst_avi_index_entry); */
- guchar stream_nr;
- guchar flags;
- guint64 ts;
- guint64 dur; /* =entry[1].ts-entry->ts */
- guint64 offset;
- guint64 bytes_before; /* calculated */
- guint32 frames_before; /* calculated */
- guint32 size; /* could be read from the chunk (if we don't split) */
-} gst_avi_index_entry;
-
/* new index entries 24 bytes */
@@ -90,5 +77,12 @@ typedef struct {
+ /* the start/step/stop entries */
+ guint start_entry;
+ guint step_entry;
+ guint stop_entry;
/* current position (byte, frame, time) and other status vars */
+ guint current_entry;
guint current_frame;
guint64 current_byte;
+ guint64 current_time;
+
GstFlowReturn last_flow;
@@ -98,3 +92,2 @@ typedef struct {
guint64 total_bytes;
- guint32 total_frames;
guint32 total_blocks;
@@ -121,3 +114,3 @@ typedef struct {
GstTagList *taglist;
-} avi_stream_context;
+} GstAviStream;
@@ -150,11 +143,7 @@ typedef struct _GstAviDemux {
- /* index */
- gst_avi_index_entry *index_entries;
- guint index_size;
+ /* index offset in the file */
guint64 index_offset;
- guint current_entry;
- guint reverse_start_index;
- guint reverse_stop_index;
/* streams */
+ GstAviStream stream[GST_AVI_DEMUX_MAX_STREAMS];
guint num_streams;
@@ -164,7 +153,5 @@ typedef struct _GstAviDemux {
- avi_stream_context stream[GST_AVI_DEMUX_MAX_STREAMS];
-
/* for streaming mode */
- gboolean streaming;
- gboolean have_eos;
+ gboolean streaming;
+ gboolean have_eos;
GstAdapter *adapter;
@@ -181,4 +168,3 @@ typedef struct _GstAviDemux {
GstTagList *globaltags;
- gboolean got_tags;
-
+ gboolean got_tags;
} GstAviDemux;