[FFmpeg-devel] [PATCH 1/5] mxfdec: Parse IndexTableSegments and convert them into AVIndexEntry arrays

Tomas Härdin tomas.hardin at codemill.se
Fri Nov 18 15:19:58 CET 2011


On Mon, 2011-11-14 at 16:03 +0100, Michael Niedermayer wrote:
> qsort() is O(n log(n)) for reverse order
> qsort() breaks down to O(n^2) when elements are ordered

Ah, I had it that it was the other way around. Anyway, not many entries.
We can bother if someone finds a sample with tens of thousands of
segments.

> [...]
> > > > +        st->index_entries_allocated_size += duration * sizeof(*st->index_entries);
> > > > +        if (st->index_entries_allocated_size / sizeof(*st->index_entries) < st->nb_index_entries + duration) {
> > > > +            av_log(mxf->fc, AV_LOG_ERROR, "index_entries_allocated_size overflow; "
> > > > +                                          "segment duration %i unreasonably large?\n", duration);
> > > > +            return AVERROR_INVALIDDATA;
> > > > +        }
> > > > +        if (!(st->index_entries = av_realloc(st->index_entries, st->index_entries_allocated_size))) {
> > > > +            av_free(sorted_segments);
> > > > +            return AVERROR(ENOMEM);
> > > > +        }
> > > > +        for (k = 0; k < duration; k++) {
> > > > +            AVIndexEntry *e = &st->index_entries[st->nb_index_entries];
> > > > +            if (k < tableseg->nb_index_entries) {
> > > > +                e->pos = tableseg->stream_offset_entries[k];
> > > > +                if (n_delta < tableseg->nb_delta_entries) {
> > > > +                    if (n_delta < tableseg->nb_delta_entries - 1) {
> > > > +                        e->size =
> > > > +                            tableseg->slice_offset_entries[k][tableseg->slice[n_delta+1]-1] +
> > > > +                            tableseg->element_delta[n_delta+1] -
> > > > +                            tableseg->element_delta[n_delta];
> > > > +                        if (tableseg->slice[n_delta] > 0)
> > > > +                            e->size -= tableseg->slice_offset_entries[k][tableseg->slice[n_delta]-1];
> > > > +                    } else if (k < duration - 1) {
> > > > +                        e->size = tableseg->stream_offset_entries[k+1] -
> > > > +                            tableseg->stream_offset_entries[k] -
> > > > +                            tableseg->slice_offset_entries[k][tableseg->slice[tableseg->nb_delta_entries-1]-1] -
> > > > +                            tableseg->element_delta[tableseg->nb_delta_entries-1];
> > > > +                    } else
> > > > +                        e->size = 0;
> > > > +                    if (tableseg->slice[n_delta] > 0)
> > > > +                        e->pos += tableseg->slice_offset_entries[k][tableseg->slice[n_delta]-1];
> > > > +                    e->pos += tableseg->element_delta[n_delta];
> > > > +                }
> > > > +                e->flags = !(tableseg->flag_entries[k] & 0x30) ? AVINDEX_KEYFRAME : 0;
> > > > +            } else {
> > > > +                e->pos = (int64_t)k * tableseg->edit_unit_byte_count + accumulated_offset;
> > > > +                if (n_delta < tableseg->nb_delta_entries - 1)
> > > > +                    e->size = tableseg->element_delta[n_delta+1] - tableseg->element_delta[n_delta];
> > > > +                else {
> > > > +                    /* use smaller size for last sample if we should */
> > > > +                    if (last_sample_size && k == duration - 1)
> > > > +                        e->size = last_sample_size;
> > > > +                    else
> > > > +                        e->size = tableseg->edit_unit_byte_count;
> > > > +                    if (tableseg->nb_delta_entries)
> > > > +                        e->size -= tableseg->element_delta[tableseg->nb_delta_entries-1];
> > > > +                }
> > > > +                if (n_delta < tableseg->nb_delta_entries)
> > > > +                    e->pos += tableseg->element_delta[n_delta];
> > > > +                e->flags = AVINDEX_KEYFRAME;
> > > > +            }
> > > > +            if (k > 0 && e->pos < mxf->first_essence_length && accumulated_offset == 0)
> > > > +                e->pos += mxf->first_essence_kl_length;
> > > > +            e->timestamp = sample_duration * st->nb_index_entries++;
> > > > +            av_dlog(mxf->fc, "Stream %d IndexEntry %d n_Delta %d Offset %"PRIx64" Timestamp %"PRId64"\n",
> > > > +                    st->index, st->nb_index_entries, n_delta, e->pos, e->timestamp);
> > > > +            e->pos += mxf->essence_offset;
> > > > +            e->min_distance = 0;
> > > > +        }
> > > > +        accumulated_offset += segment_size;
> > > > +    }
> > > 
> > > why does this not use av_add_index_entry() ?
> > 
> > To avoid needless allocations. IIRC Baptiste suggested that I keep this
> > approach. I see that av_add_index_entry() makes use of
> > index_entries_allocated_size, meaning simply keeping the realloc part
> > should be enough. It could perhaps be broken out into a function like
> > ff_alloc_extra_index_entries() in a separate patch though.
> 
> av_realloc() is slow, av_fast_realloc() is faster (by reallocating in
> larger steps and not reducing size)
> av_add_index_entry() uses the fast variant.
> 
> the problem av_add_index_entry() has currently is when adding
> millions of entries in non sequential order.
> 
> also duration * sizeof(*st->index_entries) needs to be checked for
> integer overflow unless something implicitly prevents it from becoming
> too large as otherwise the array may be quite a bit smaller than the
> data written into it.
> av_add_index_entry() already does that check

Fair enough. I switched to using av_add_index_entry(), simplifying the
code quite a bit.
Reworking the patch revealed that one possible branch left size unset
(above "flags = !(tableseg->flag_entries[k] & 0x30) ? AVINDEX_KEYFRAME :
0;"). I'm setting size to zero there for now, just like a few lines
further up. Not sure if it makes sense though.

Updated patch attached.

/Tomas
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-mxfdec-Parse-IndexTableSegments-and-convert-them-int.patch
Type: text/x-patch
Size: 14987 bytes
Desc: not available
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20111118/217ccab8/attachment.bin>


More information about the ffmpeg-devel mailing list