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 (st->codec->codec_id != AV_CODEC_ID_PROBE ||
                !st->probe_packets ||
                s->internal->raw_packet_buffer_remaining_size < pkt->size) {
                AVProbeData *pd;
                if (st->probe_packets)
                    if ((err = probe_codec(s, st, NULL)) < 0)
                        return err;
                pd = &st->probe_data;
                av_freep(&pd->buf);
                pd->buf_size = 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) {
            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;
            }
            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;
        }

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

        switch (st->codec->codec_type) {
        case AVMEDIA_TYPE_VIDEO:
            if (s->video_codec_id)
                st->codec->codec_id = s->video_codec_id;
            break;
        case AVMEDIA_TYPE_AUDIO:
            if (s->audio_codec_id)
                st->codec->codec_id = s->audio_codec_id;
            break;
        case AVMEDIA_TYPE_SUBTITLE:
            if (s->subtitle_codec_id)
                st->codec->codec_id = s->subtitle_codec_id;
            break;
        }

        if (!pktl && (st->codec->codec_id != AV_CODEC_ID_PROBE ||
                      !st->probe_packets))
            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;
    }
}