[FFmpeg-soc] [soc]: r5826 - in seek2010: . seek2010.patch

Michael Chinen mchinen at gmail.com
Wed Jun 16 22:50:06 CEST 2010


On Wed, Jun 16, 2010 at 10:07 PM, Michael Niedermayer <michaelni at gmx.at> wrote:
> On Wed, Jun 09, 2010 at 03:42:09PM +0200, mchinen wrote:
>> Author: mchinen
>> Date: Wed Jun  9 15:42:08 2010
>> New Revision: 5826
>>
>> Log:
>> creating seek2010 dir for my soc proj and adding current patch
> [...]
>
>> +Index: libavformat/avformat.h
>> +===================================================================
>> +--- libavformat/avformat.h   (revision 23548)
>> ++++ libavformat/avformat.h   (working copy)
>> +@@ -390,6 +390,21 @@
>> +     int min_distance;         /**< Minimum distance between this and the previous keyframe, used to avoid unneeded searching. */
>> + } AVIndexEntry;
>> +
>> ++#define AV_SEEKTABLE_BUILDING   0x0001
>> ++#define AV_SEEKTABLE_CBR        0x0002
>> ++#define AV_SEEKTABLE_FINISHED   0x0004
>> ++#define AV_SEEKTABLE_COPIED     0x0008
>
> missing documentation
>
>
> [...]
>
>> +@@ -531,6 +546,9 @@
>> +      * Number of frames that have been demuxed during av_find_stream_info()
>> +      */
>> +     int codec_info_nb_frames;
>> ++
>> ++    /* new av_seek_frame() support */
>> ++    AVSeekTable seek_table;
>> + } AVStream;
>
> we alraedy have a table for seeking, that is AVStream.index_entries
> why do you add a second table?
This one is a complete index table that will be saved/loaded/built on
a different thread during decoding.  I made a new one mostly to make
sure I didn't cause regression bugs.  Also currently lots of demuxers
change the state of that index table during normal read/parse.  Once
the complete table is built, the idea is to stop using the old
index_entries one and use the complete table for seeking.  Is this
okay?

>
>
> [...]
>> +Index: libavformat/utils.c
>> +===================================================================
>> +--- libavformat/utils.c      (revision 23548)
>> ++++ libavformat/utils.c      (working copy)
>> +@@ -1001,7 +1001,38 @@
>> +         pkt->convergence_duration = pc->convergence_duration;
>> + }
>> +
>> ++static int av_add_table_entry(AVStream *st,
>> ++                            int64_t pos, int64_t timestamp, int size, int distance, int flags)
>> ++{
>> ++    AVIndexEntry *entries, *ie;
>> ++    int index;
>> +
>> ++    if((unsigned)st->nb_index_entries + 1 >= UINT_MAX / sizeof(AVIndexEntry))
>> ++        return -1;
>> ++
>> ++    entries = av_fast_realloc(st->seek_table.index_entries,
>> ++                              &st->seek_table.index_entries_allocated_size,
>> ++                              (st->seek_table.nb_index_entries + 1) *
>> ++                              sizeof(AVIndexEntry));
>> ++    if(!entries)
>> ++        return -1;
>> ++
>> ++    st->seek_table.index_entries= entries;
>> ++
>> ++    /* we assume the indecies are placed in order */
>> ++    ie = &st->seek_table.index_entries[st->seek_table.nb_index_entries++];
>> ++    assert(index==0 || ie[-1].timestamp < timestamp);
>> ++
>> ++    ie->pos = pos;
>> ++    ie->timestamp = timestamp;
>> ++    ie->min_distance= distance;
>> ++    ie->size= size;
>> ++    ie->flags = flags;
>> ++
>> ++    return st->seek_table.nb_index_entries;
>> ++}
>> ++
>> ++
>> + static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt)
>> + {
>> +     AVStream *st;
>> +@@ -1359,6 +1390,7 @@
>> +     int a, b, m;
>> +     int64_t timestamp;
>> +
>> ++
>> +     a = - 1;
>> +     b = nb_entries;
>> +
>> +@@ -1675,6 +1707,11 @@
>> +         timestamp = av_rescale(timestamp, st->time_base.den, AV_TIME_BASE * (int64_t)st->time_base.num);
>> +     }
>> +
>> ++    /* if we've built a seek table, use it. */
>> ++    st = s->streams[stream_index];
>> ++    if (st->seek_table.flags & AV_SEEKTABLE_FINISHED)
>> ++        return av_seek_frame_table(s, stream_index, timestamp, flags);
>> ++
>> +     /* first, we try the format specific seek */
>> +     if (s->iformat->read_seek)
>> +         ret = s->iformat->read_seek(s, stream_index, timestamp, flags);
>> +@@ -1712,9 +1749,367 @@
>> +     // try some generic seek like av_seek_frame_generic() but with new ts semantics
>> + }
>> +
>> ++
>> + /*******************************************************/
>> ++int av_table_search_timestamp(AVStream *st, int64_t wanted_timestamp,
>> ++                              int flags)
>> ++{
>> ++    AVIndexEntry *entries= st->seek_table.index_entries;
>> ++    int nb_entries= st->seek_table.nb_index_entries;
>> ++    int a, b, m;
>> ++    int64_t timestamp;
>> +
>> ++    a = - 1;
>> ++    b = nb_entries;
>> ++
>> ++    //optimize appending index entries at the end
>> ++    if(b && entries[b-1].timestamp < wanted_timestamp)
>> ++        a= b-1;
>> ++
>> ++    while (b - a > 1) {
>> ++    //TODO: since we have a lot of contiguous entries in the table, we can use something more
>> ++    //like dictionary search, which will speed things up quite a bit.
>> ++        m = (a + b) >> 1;
>> ++        timestamp = entries[m].timestamp;
>> ++        if(timestamp >= wanted_timestamp)
>> ++            b = m;
>> ++        if(timestamp <= wanted_timestamp)
>> ++            a = m;
>> ++    }
>> ++    m= (flags & AVSEEK_FLAG_BACKWARD) ? a : b;
>> ++
>> ++    if(!(flags & AVSEEK_FLAG_ANY)){
>> ++        while(m>=0 && m<nb_entries && !(entries[m].flags & AVINDEX_KEYFRAME)){
>> ++            m += (flags & AVSEEK_FLAG_BACKWARD) ? -1 : 1;
>> ++        }
>> ++    }
>> ++
>> ++    if(m == nb_entries)
>> ++        return -1;
>> ++    return  m;
>> ++}
>> ++
> [...]
>> ++static int av_fill_table_internal(AVFormatContext *s, AVPacket *pkt, ByteIOContext *pb)
>
> lots of code duplication
yes, these are working stubs based on the calls to modify the old
index_entries, but I will optimize them to be a special case for
complete index table.
Michael


More information about the FFmpeg-soc mailing list