int ff_read_packet(AVFormatContext *s, AVPacket *pkt)

{

    int ret, i, err;

    AVStream *st;



    for (;;) {

        AVPacketList *pktl = s->internal->raw_packet_buffer;



        if (pktl) {

            *pkt = pktl->pkt;

            st   = s->streams[pkt->stream_index];

            if (s->internal->raw_packet_buffer_remaining_size <= 0)

                if ((err = probe_codec(s, st, NULL)) < 0)

                    return err;

            if (st->request_probe <= 0) {

                s->internal->raw_packet_buffer                 = pktl->next;

                s->internal->raw_packet_buffer_remaining_size += pkt->size;

                av_free(pktl);

                return 0;

            }

        }



        pkt->data = NULL;

        pkt->size = 0;

        av_init_packet(pkt);

        ret = s->iformat->read_packet(s, pkt);

        if (ret < 0) {

            /* Some demuxers return FFERROR_REDO when they consume

               data and discard it (ignored streams, junk, extradata).

               We must re-call the demuxer to get the real packet. */

            if (ret == FFERROR_REDO)

                continue;

            if (!pktl || ret == AVERROR(EAGAIN))

                return ret;

            for (i = 0; i < s->nb_streams; i++) {

                st = s->streams[i];

                if (st->probe_packets)

                    if ((err = probe_codec(s, st, NULL)) < 0)

                        return err;

                av_assert0(st->request_probe <= 0);

            }

            continue;

        }



        if (!pkt->buf) {

            AVPacket tmp = { 0 };

            ret = av_packet_ref(&tmp, pkt);

            if (ret < 0)

                return ret;

            *pkt = tmp;

        }



        if ((s->flags & AVFMT_FLAG_DISCARD_CORRUPT) &&

            (pkt->flags & AV_PKT_FLAG_CORRUPT)) {

            av_log(s, AV_LOG_WARNING,

                   "Dropped corrupted packet (stream = %d)\n",

                   pkt->stream_index);

            av_packet_unref(pkt);

            continue;

        }



        if (pkt->stream_index >= (unsigned)s->nb_streams) {

            av_log(s, AV_LOG_ERROR, "Invalid stream index %d\n", pkt->stream_index);

            continue;

        }



        st = s->streams[pkt->stream_index];



        if (update_wrap_reference(s, st, pkt->stream_index, pkt) && st->pts_wrap_behavior == AV_PTS_WRAP_SUB_OFFSET) {

            // correct first time stamps to negative values

            if (!is_relative(st->first_dts))

                st->first_dts = wrap_timestamp(st, st->first_dts);

            if (!is_relative(st->start_time))

                st->start_time = wrap_timestamp(st, st->start_time);

            if (!is_relative(st->cur_dts))

                st->cur_dts = wrap_timestamp(st, st->cur_dts);

        }



        pkt->dts = wrap_timestamp(st, pkt->dts);

        pkt->pts = wrap_timestamp(st, pkt->pts);



        force_codec_ids(s, st);



        /* TODO: audio: time filter; video: frame reordering (pts != dts) */

        if (s->use_wallclock_as_timestamps)

            pkt->dts = pkt->pts = av_rescale_q(av_gettime(), AV_TIME_BASE_Q, st->time_base);



        if (!pktl && st->request_probe <= 0)

            return ret;



        err = add_to_pktbuf(&s->internal->raw_packet_buffer, pkt,

                            &s->internal->raw_packet_buffer_end, 0);

        if (err)

            return err;

        s->internal->raw_packet_buffer_remaining_size -= pkt->size;



        if ((err = probe_codec(s, st, pkt)) < 0)

            return err;

    }

}
