static int avi_sync(AVFormatContext *s, int exit_early)

{

    AVIContext *avi = s->priv_data;

    AVIOContext *pb = s->pb;

    int n;

    unsigned int d[8];

    unsigned int size;

    int64_t i, sync;



start_sync:

    memset(d, -1, sizeof(d));

    for (i = sync = avio_tell(pb); !avio_feof(pb); i++) {

        int j;



        for (j = 0; j < 7; j++)

            d[j] = d[j + 1];

        d[7] = avio_r8(pb);



        size = d[4] + (d[5] << 8) + (d[6] << 16) + (d[7] << 24);



        n = get_stream_idx(d + 2);

        ff_tlog(s, "%X %X %X %X %X %X %X %X %"PRId64" %u %d\n",

                d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], i, size, n);

        if (i*(avi->io_fsize>0) + (uint64_t)size > avi->fsize || d[0] > 127)

            continue;



        // parse ix##

        if ((d[0] == 'i' && d[1] == 'x' && n < s->nb_streams) ||

            // parse JUNK

            (d[0] == 'J' && d[1] == 'U' && d[2] == 'N' && d[3] == 'K') ||

            (d[0] == 'i' && d[1] == 'd' && d[2] == 'x' && d[3] == '1') ||

            (d[0] == 'i' && d[1] == 'n' && d[2] == 'd' && d[3] == 'x')) {

            avio_skip(pb, size);

            goto start_sync;

        }



        // parse stray LIST

        if (d[0] == 'L' && d[1] == 'I' && d[2] == 'S' && d[3] == 'T') {

            avio_skip(pb, 4);

            goto start_sync;

        }



        n = get_stream_idx(d);



        if (!((i - avi->last_pkt_pos) & 1) &&

            get_stream_idx(d + 1) < s->nb_streams)

            continue;



        // detect ##ix chunk and skip

        if (d[2] == 'i' && d[3] == 'x' && n < s->nb_streams) {

            avio_skip(pb, size);

            goto start_sync;

        }



        if (avi->dv_demux && n != 0)

            continue;



        // parse ##dc/##wb

        if (n < s->nb_streams) {

            AVStream *st;

            AVIStream *ast;

            st  = s->streams[n];

            ast = st->priv_data;



            if (!ast) {

                av_log(s, AV_LOG_WARNING, "Skipping foreign stream %d packet\n", n);

                continue;

            }



            if (s->nb_streams >= 2) {

                AVStream *st1   = s->streams[1];

                AVIStream *ast1 = st1->priv_data;

                // workaround for broken small-file-bug402.avi

                if (   d[2] == 'w' && d[3] == 'b'

                   && n == 0

                   && st ->codecpar->codec_type == AVMEDIA_TYPE_VIDEO

                   && st1->codecpar->codec_type == AVMEDIA_TYPE_AUDIO

                   && ast->prefix == 'd'*256+'c'

                   && (d[2]*256+d[3] == ast1->prefix || !ast1->prefix_count)

                  ) {

                    n   = 1;

                    st  = st1;

                    ast = ast1;

                    av_log(s, AV_LOG_WARNING,

                           "Invalid stream + prefix combination, assuming audio.\n");

                }

            }



            if (!avi->dv_demux &&

                ((st->discard >= AVDISCARD_DEFAULT && size == 0) /* ||

                 // FIXME: needs a little reordering

                 (st->discard >= AVDISCARD_NONKEY &&

                 !(pkt->flags & AV_PKT_FLAG_KEY)) */

                || st->discard >= AVDISCARD_ALL)) {

                if (!exit_early) {

                    ast->frame_offset += get_duration(ast, size);

                    avio_skip(pb, size);

                    goto start_sync;

                }

            }



            if (d[2] == 'p' && d[3] == 'c' && size <= 4 * 256 + 4) {

                int k    = avio_r8(pb);

                int last = (k + avio_r8(pb) - 1) & 0xFF;



                avio_rl16(pb); // flags



                // b + (g << 8) + (r << 16);

                for (; k <= last; k++)

                    ast->pal[k] = 0xFFU<<24 | avio_rb32(pb)>>8;



                ast->has_pal = 1;

                goto start_sync;

            } else if (((ast->prefix_count < 5 || sync + 9 > i) &&

                        d[2] < 128 && d[3] < 128) ||

                       d[2] * 256 + d[3] == ast->prefix /* ||

                       (d[2] == 'd' && d[3] == 'c') ||

                       (d[2] == 'w' && d[3] == 'b') */) {

                if (exit_early)

                    return 0;

                if (d[2] * 256 + d[3] == ast->prefix)

                    ast->prefix_count++;

                else {

                    ast->prefix       = d[2] * 256 + d[3];

                    ast->prefix_count = 0;

                }



                avi->stream_index = n;

                ast->packet_size  = size + 8;

                ast->remaining    = size;



                if (size) {

                    uint64_t pos = avio_tell(pb) - 8;

                    if (!st->index_entries || !st->nb_index_entries ||

                        st->index_entries[st->nb_index_entries - 1].pos < pos) {

                        av_add_index_entry(st, pos, ast->frame_offset, size,

                                           0, AVINDEX_KEYFRAME);

                    }

                }

                return 0;

            }

        }

    }



    if (pb->error)

        return pb->error;

    return AVERROR_EOF;

}
