diff options
author | Wim Taymans <wim.taymans@collabora.co.uk> | 2009-09-23 12:56:07 +0200 |
---|---|---|
committer | Wim Taymans <wim@metal.(none)> | 2009-09-28 22:17:00 +0200 |
commit | 7b9b8343ba03ef4ad19268b443c80d7538f6083c (patch) | |
tree | 54133c4bf93dff128ff4dd65b259abfe3b4cac38 | |
parent | ceb7d66e2582090317aa0cf33007885985ad12cb (diff) |
avi: add support for ODML indexes again
-rw-r--r-- | gst/avi/gstavidemux.c | 403 |
1 files changed, 165 insertions, 238 deletions
diff --git a/gst/avi/gstavidemux.c b/gst/avi/gstavidemux.c index 43a8a16cb..0765bd856 100644 --- a/gst/avi/gstavidemux.c +++ b/gst/avi/gstavidemux.c @@ -997,3 +997,113 @@ too_small: -#if 0 +/* add an entry to the index of a stream. @num should be an estimate of the + * total amount of index entries for all streams and is used to dynamically + * allocate memory for the index entries. */ +static inline gboolean +gst_avi_demux_add_index (GstAviDemux * avi, GstAviStream * stream, + guint num, GstAviIndexEntry * entry) +{ + /* ensure index memory */ + if (G_UNLIKELY (stream->idx_n >= stream->idx_max)) { + /* we need to make some more room */ + if (stream->idx_max == 0) { + /* initial size guess, assume each stream has an equal amount of entries, + * overshoot with at least 8K */ + stream->idx_max = + (num / avi->num_streams) + (8192 / sizeof (GstAviIndexEntry)); + } else { + stream->idx_max += 8192 / sizeof (GstAviIndexEntry); + GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "expanded index to %u", + stream->idx_max); + } + stream->index = g_try_renew (GstAviIndexEntry, stream->index, + stream->idx_max); + if (G_UNLIKELY (!stream->index)) + return FALSE; + } + + /* update stream stats and total size */ + entry->total = stream->total_bytes; + stream->total_bytes += entry->size; + if (stream->strh->type == GST_RIFF_FCC_auds) { + gint blockalign = stream->strf.auds->blockalign; + if (blockalign > 0) + stream->total_blocks += DIV_ROUND_UP (entry->size, blockalign); + else + stream->total_blocks++; + } + if (ENTRY_IS_KEYFRAME (entry)) + stream->n_keyframes++; + + /* and add */ + GST_LOG_OBJECT (avi, + "Adding stream %u, index entry %d, kf %d, size %u " + ", offset %" G_GUINT64_FORMAT ", total %" G_GUINT64_FORMAT, stream->num, + stream->idx_n, ENTRY_IS_KEYFRAME (entry), entry->size, entry->offset, + entry->total); + stream->index[stream->idx_n++] = *entry; + + return TRUE; +} + +/* collect and debug stats about the indexes for all streams. + * This method is also responsible for filling in the stream duration + * as measured by the amount of index entries. */ +static void +gst_avi_demux_do_index_stats (GstAviDemux * avi) +{ + guint i; +#ifndef GST_DISABLE_GST_DEBUG + guint total_idx = 0, total_max = 0; +#endif + + /* get stream stats now */ + for (i = 0; i < avi->num_streams; i++) { + GstAviIndexEntry *entry; + GstAviStream *stream; + guint64 total; + + if (G_UNLIKELY (!(stream = &avi->stream[i]))) + continue; + if (G_UNLIKELY (!stream->strh)) + continue; + if (G_UNLIKELY (!stream->index || stream->idx_n == 0)) + continue; + + entry = &stream->index[stream->idx_n - 1]; + total = entry->total + entry->size; + + /* calculate duration */ + if (stream->is_vbr) { + /* VBR stream next timestamp */ + if (stream->strh->type == GST_RIFF_FCC_auds) { + stream->idx_duration = + avi_stream_convert_frames_to_time_unchecked (stream, total); + } else { + stream->idx_duration = + avi_stream_convert_frames_to_time_unchecked (stream, stream->idx_n); + } + } else { + /* constant rate stream */ + stream->idx_duration = avi_stream_convert_bytes_to_time_unchecked (stream, + total); + } +#ifndef GST_DISABLE_GST_DEBUG + total_idx += stream->idx_n; + total_max += stream->idx_max; +#endif + GST_INFO_OBJECT (avi, "Stream %d, dur %" GST_TIME_FORMAT ", %6u entries, " + "%5u keyframes, entry size = %2u, total size = %10u, allocated %10u", + i, GST_TIME_ARGS (stream->idx_duration), stream->idx_n, + stream->n_keyframes, (guint) sizeof (GstAviIndexEntry), + (guint) (stream->idx_n * sizeof (GstAviIndexEntry)), + (guint) (stream->idx_max * sizeof (GstAviIndexEntry))); + } +#ifndef GST_DISABLE_GST_DEBUG + total_idx *= sizeof (GstAviIndexEntry); + total_max *= sizeof (GstAviIndexEntry); +#endif + GST_INFO_OBJECT (avi, "%u bytes for index vs %u ideally, %u wasted", + total_max, total_idx, total_max - total_idx); +} + /* @@ -1010,3 +1120,2 @@ too_small: * Reads superindex (openDML-2 spec stuff) from the provided data. - * The buffer will be discarded after use. * The buffer should contain a GST_RIFF_TAG_ix?? chunk. @@ -1017,6 +1126,6 @@ too_small: static gboolean -gst_avi_demux_parse_subindex (GstAviDemux * avi, - GstBuffer * buf, GstAviStream * stream, GList ** _entries_list) +gst_avi_demux_parse_subindex (GstAviDemux * avi, GstAviStream * stream, + GstBuffer * buf) { - guint8 *data = GST_BUFFER_DATA (buf); + guint8 *data; guint16 bpe; @@ -1024,13 +1133,8 @@ gst_avi_demux_parse_subindex (GstAviDemux * avi, guint64 baseoff; - gst_avi_index_entry *entries, *entry; - GList *entries_list = NULL; guint size; -#ifndef GST_DISABLE_GST_DEBUG - gulong _nr_keyframes = 0; -#endif - - *_entries_list = NULL; + if (!buf) + return TRUE; - size = buf ? GST_BUFFER_SIZE (buf) : 0; + size = GST_BUFFER_SIZE (buf); @@ -1040,2 +1144,4 @@ gst_avi_demux_parse_subindex (GstAviDemux * avi, + data = GST_BUFFER_DATA (buf); + /* We don't support index-data yet */ @@ -1061,6 +1167,3 @@ gst_avi_demux_parse_subindex (GstAviDemux * avi, if (num == 0) - return TRUE; - - if (!(entries = g_try_new (gst_avi_index_entry, num))) - goto out_of_mem; + goto empty_index; @@ -1069,5 +1172,3 @@ gst_avi_demux_parse_subindex (GstAviDemux * avi, for (i = 0; i < num; i++) { - gint64 next_ts; - - entry = &entries[i]; + GstAviIndexEntry entry; @@ -1076,75 +1177,22 @@ gst_avi_demux_parse_subindex (GstAviDemux * avi, - /* fill in */ - entry->offset = baseoff + GST_READ_UINT32_LE (&data[24 + bpe * i]); - entry->size = GST_READ_UINT32_LE (&data[24 + bpe * i + 4]); - entry->flags = - (entry->size & 0x80000000) ? 0 : GST_AVI_INDEX_ENTRY_FLAG_KEYFRAME; - entry->size &= ~0x80000000; - entry->index_nr = i; - entry->stream_nr = stream->num; - + /* fill in offset and size. offset contains the keyframe flag in the + * upper bit*/ + entry.offset = baseoff + GST_READ_UINT32_LE (&data[24 + bpe * i]); + entry.size = GST_READ_UINT32_LE (&data[24 + bpe * i + 4]); + /* handle flags */ if (stream->strh->type == GST_RIFF_FCC_auds) { /* all audio frames are keyframes */ - entry->flags |= GST_AVI_INDEX_ENTRY_FLAG_KEYFRAME; - } -#ifndef GST_DISABLE_GST_DEBUG - if (entry->flags & GST_AVI_INDEX_ENTRY_FLAG_KEYFRAME) - _nr_keyframes++; -#endif - - /* stream duration unknown, now we can calculate it */ - if (stream->idx_duration == -1) - stream->idx_duration = 0; - - /* timestamps */ - entry->ts = stream->idx_duration; - if (stream->is_vbr) { - /* VBR stream next timestamp */ - if (stream->strh->type == GST_RIFF_FCC_auds) { - next_ts = avi_stream_convert_frames_to_time_unchecked (stream, - stream->total_blocks + 1); - } else { - next_ts = avi_stream_convert_frames_to_time_unchecked (stream, - stream->idx_n + 1); - } + ENTRY_SET_KEYFRAME (&entry); } else { - /* CBR get next timestamp */ - next_ts = avi_stream_convert_bytes_to_time_unchecked (stream, - stream->total_bytes + entry->size); - } - /* duration is next - current */ - entry->dur = next_ts - entry->ts; - - /* stream position */ - entry->bytes_before = stream->total_bytes; - entry->frames_before = stream->idx_n; - - stream->total_bytes += entry->size; - stream->idx_n++; - 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++; + /* else read flags */ + entry.flags = (entry.size & 0x80000000) ? 0 : GST_AVI_KEYFRAME; } - stream->idx_duration = next_ts; + entry.size &= ~0x80000000; - entries_list = g_list_prepend (entries_list, entry); + /* and add */ + if (G_UNLIKELY (!gst_avi_demux_add_index (avi, stream, num, &entry))) + goto out_of_mem; } - - GST_INFO_OBJECT (avi, "Parsed index, %6u/%6u entries, %5lu keyframes, " - "entry size = %2u, total size = %10d", i, num, _nr_keyframes, - (gint) sizeof (gst_avi_index_entry), - (gint) (i * sizeof (gst_avi_index_entry))); - gst_buffer_unref (buf); - if (i > 0) { - *_entries_list = g_list_reverse (entries_list); - } else { - g_free (entries); - } - return TRUE; @@ -1156,4 +1204,3 @@ too_small: "Not enough data to parse subindex (%d available, 24 needed)", size); - if (buf) - gst_buffer_unref (buf); + gst_buffer_unref (buf); return TRUE; /* continue */ @@ -1167,2 +1214,8 @@ not_implemented: } +empty_index: + { + GST_DEBUG_OBJECT (avi, "the index is empty"); + gst_buffer_unref (buf); + return TRUE; + } out_of_mem: @@ -1171,4 +1224,4 @@ out_of_mem: ("Cannot allocate memory for %u*%u=%u bytes", - (guint) sizeof (gst_avi_index_entry), num, - (guint) sizeof (gst_avi_index_entry) * num)); + (guint) sizeof (GstAviIndexEntry), num, + (guint) sizeof (GstAviIndexEntry) * num)); gst_buffer_unref (buf); @@ -1177,3 +1230,2 @@ out_of_mem: } -#endif @@ -1184,6 +1236,4 @@ out_of_mem: static void -gst_avi_demux_read_subindexes_push (GstAviDemux * avi, - GList ** index, GList ** alloc_list) +gst_avi_demux_read_subindexes_push (GstAviDemux * avi) { - GList *list = NULL; guint32 tag = 0, size; @@ -1192,4 +1242,3 @@ gst_avi_demux_read_subindexes_push (GstAviDemux * avi, - GST_DEBUG_OBJECT (avi, "gst_avi_demux_read_subindexes_push for %d streams", - avi->num_streams); + GST_DEBUG_OBJECT (avi, "read subindexes for %d streams", avi->num_streams); @@ -1216,9 +1265,4 @@ gst_avi_demux_read_subindexes_push (GstAviDemux * avi, - if (!gst_avi_demux_parse_subindex (avi, buf, stream, &list)) + if (!gst_avi_demux_parse_subindex (avi, stream, buf)) continue; - if (list) { - GST_DEBUG_OBJECT (avi, " adding %d entries", g_list_length (list)); - *alloc_list = g_list_append (*alloc_list, list->data); - *index = g_list_concat (*index, list); - } } @@ -1228,3 +1272,6 @@ gst_avi_demux_read_subindexes_push (GstAviDemux * avi, } - GST_DEBUG_OBJECT (avi, "index %s", ((*index) ? "!= 0" : "== 0")); + /* get stream stats now */ + gst_avi_demux_do_index_stats (avi); + + avi->have_index = TRUE; } @@ -1232,3 +1279,2 @@ gst_avi_demux_read_subindexes_push (GstAviDemux * avi, -#if 0 /* @@ -1237,6 +1283,4 @@ gst_avi_demux_read_subindexes_push (GstAviDemux * avi, static void -gst_avi_demux_read_subindexes_pull (GstAviDemux * avi, - GList ** index, GList ** alloc_list) +gst_avi_demux_read_subindexes_pull (GstAviDemux * avi) { - GList *list = NULL; guint32 tag; @@ -1245,4 +1289,3 @@ gst_avi_demux_read_subindexes_pull (GstAviDemux * avi, - GST_DEBUG_OBJECT (avi, "gst_avi_demux_read_subindexes_pull for %d streams", - avi->num_streams); + GST_DEBUG_OBJECT (avi, "read subindexes for %d streams", avi->num_streams); @@ -1252,3 +1295,3 @@ gst_avi_demux_read_subindexes_pull (GstAviDemux * avi, for (i = 0; stream->indexes[i] != GST_BUFFER_OFFSET_NONE; i++) { - if (gst_riff_read_chunk (GST_ELEMENT (avi), avi->sinkpad, + if (gst_riff_read_chunk (GST_ELEMENT_CAST (avi), avi->sinkpad, &stream->indexes[i], &tag, &buf) != GST_FLOW_OK) @@ -1267,11 +1310,4 @@ gst_avi_demux_read_subindexes_pull (GstAviDemux * avi, - if (!gst_avi_demux_parse_subindex (avi, buf, stream, &list)) + if (!gst_avi_demux_parse_subindex (avi, stream, buf)) continue; - if (list) { - GST_DEBUG_OBJECT (avi, " adding %5d entries, total %2d %5d", - g_list_length (list), g_list_length (*alloc_list), - g_list_length (*index)); - *alloc_list = g_list_append (*alloc_list, list->data); - *index = g_list_concat (*index, list); - } } @@ -1281,5 +1317,7 @@ gst_avi_demux_read_subindexes_pull (GstAviDemux * avi, } - GST_DEBUG_OBJECT (avi, "index %s", ((*index) ? "!= 0" : "== 0")); + /* get stream stats now */ + gst_avi_demux_do_index_stats (avi); + + avi->have_index = TRUE; } -#endif @@ -2048,113 +2086,2 @@ gst_avi_demux_get_buffer_info (GstAviDemux * avi, GstAviStream * stream, -/* collect and debug stats about the indexes for all streams. - * This method is also responsible for filling in the stream duration - * as measured by the amount of index entries. */ -static void -gst_avi_demux_do_index_stats (GstAviDemux * avi) -{ - guint i; -#ifndef GST_DISABLE_GST_DEBUG - guint total_idx = 0, total_max = 0; -#endif - - /* get stream stats now */ - for (i = 0; i < avi->num_streams; i++) { - GstAviIndexEntry *entry; - GstAviStream *stream; - guint64 total; - - if (G_UNLIKELY (!(stream = &avi->stream[i]))) - continue; - if (G_UNLIKELY (!stream->strh)) - continue; - if (G_UNLIKELY (!stream->index || stream->idx_n == 0)) - continue; - - entry = &stream->index[stream->idx_n - 1]; - total = entry->total + entry->size; - - /* calculate duration */ - if (stream->is_vbr) { - /* VBR stream next timestamp */ - if (stream->strh->type == GST_RIFF_FCC_auds) { - stream->idx_duration = - avi_stream_convert_frames_to_time_unchecked (stream, total); - } else { - stream->idx_duration = - avi_stream_convert_frames_to_time_unchecked (stream, stream->idx_n); - } - } else { - /* constant rate stream */ - stream->idx_duration = avi_stream_convert_bytes_to_time_unchecked (stream, - total); - } -#ifndef GST_DISABLE_GST_DEBUG - total_idx += stream->idx_n; - total_max += stream->idx_max; -#endif - GST_INFO_OBJECT (avi, "Stream %d, dur %" GST_TIME_FORMAT ", %6u entries, " - "%5u keyframes, entry size = %2u, total size = %10u, allocated %10u", - i, GST_TIME_ARGS (stream->idx_duration), stream->idx_n, - stream->n_keyframes, (guint) sizeof (GstAviIndexEntry), - (guint) (stream->idx_n * sizeof (GstAviIndexEntry)), - (guint) (stream->idx_max * sizeof (GstAviIndexEntry))); - } -#ifndef GST_DISABLE_GST_DEBUG - total_idx *= sizeof (GstAviIndexEntry); - total_max *= sizeof (GstAviIndexEntry); -#endif - GST_INFO_OBJECT (avi, "%u bytes for index vs %u ideally, %u wasted", - total_max, total_idx, total_max - total_idx); -} - -/* add an entry to the index of a stream. @num should be an estimate of the - * total amount of index entries for all streams and is used to dynamically - * allocate memory for the index entries. */ -static inline gboolean -gst_avi_demux_add_index (GstAviDemux * avi, GstAviStream * stream, - guint num, GstAviIndexEntry * entry) -{ - /* ensure index memory */ - if (G_UNLIKELY (stream->idx_n >= stream->idx_max)) { - /* we need to make some more room */ - if (stream->idx_max == 0) { - /* initial size guess, assume each stream has an equal amount of entries, - * overshoot with at least 8K */ - stream->idx_max = - (num / avi->num_streams) + (8192 / sizeof (GstAviIndexEntry)); - } else { - stream->idx_max += 8192 / sizeof (GstAviIndexEntry); - GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "expanded index to %u", - stream->idx_max); - } - stream->index = g_try_renew (GstAviIndexEntry, stream->index, - stream->idx_max); - if (G_UNLIKELY (!stream->index)) - return FALSE; - } - - /* update stream stats and total size */ - entry->total = stream->total_bytes; - stream->total_bytes += entry->size; - if (stream->strh->type == GST_RIFF_FCC_auds) { - gint blockalign = stream->strf.auds->blockalign; - if (blockalign > 0) - stream->total_blocks += DIV_ROUND_UP (entry->size, blockalign); - else - stream->total_blocks++; - } - if (ENTRY_IS_KEYFRAME (entry)) - stream->n_keyframes++; - - /* and add */ - GST_LOG_OBJECT (avi, - "Adding stream %u, index entry %d, kf %d, size %u " - ", offset %" G_GUINT64_FORMAT ", total %" G_GUINT64_FORMAT, stream->num, - stream->idx_n, ENTRY_IS_KEYFRAME (entry), entry->size, entry->offset, - entry->total); - stream->index[stream->idx_n++] = *entry; - - return TRUE; -} - static inline GstAviStream * @@ -2201,3 +2128,3 @@ gst_avi_demux_parse_index (GstAviDemux * avi, GstBuffer * buf) if (!buf) - goto empty_list; + return FALSE; @@ -2267,2 +2194,4 @@ gst_avi_demux_parse_index (GstAviDemux * avi, GstBuffer * buf) } + gst_buffer_unref (buf); + /* get stream stats now */ @@ -2283,2 +2212,3 @@ empty_list: GST_DEBUG_OBJECT (avi, "empty index"); + gst_buffer_unref (buf); return FALSE; @@ -2291,2 +2221,3 @@ out_of_mem: (guint) sizeof (GstAviIndexEntry) * num)); + gst_buffer_unref (buf); return FALSE; @@ -2355,3 +2286,2 @@ gst_avi_demux_stream_index (GstAviDemux * avi) gst_avi_demux_parse_index (avi, buf); - gst_buffer_unref (buf); @@ -2494,3 +2424,3 @@ gst_avi_demux_stream_scan (GstAviDemux * avi) GstFormat format; - guint64 pos; + guint64 pos = 0; guint64 length; @@ -2503,4 +2433,3 @@ gst_avi_demux_stream_scan (GstAviDemux * avi) */ - GST_DEBUG_OBJECT (avi, - "Creating index starting at offset %" G_GUINT64_FORMAT, pos); + GST_DEBUG_OBJECT (avi, "Creating index"); @@ -3118,3 +3047,2 @@ skipping_done: -#if 0 /* create or read stream index (for seeking) */ @@ -3122,5 +3050,4 @@ skipping_done: /* we read a super index already (gst_avi_demux_parse_superindex() ) */ - gst_avi_demux_read_subindexes_pull (avi, &index, &alloc); + gst_avi_demux_read_subindexes_pull (avi); } -#endif if (!avi->have_index) { |