static int asf_read_frame_header(AVFormatContext *s, AVIOContext *pb)
{
    ASFContext *asf = s->priv_data;
    ASFStream *asfst;
    int rsize       = 1;
    int num         = avio_r8(pb);
    int i;
    int64_t ts0, ts1 av_unused;

    asf->packet_segments--;
    asf->packet_key_frame = num >> 7;
    asf->stream_index     = asf->asfid2avid[num & 0x7f];
    asfst                 = &asf->streams[num & 0x7f];
    // sequence should be ignored!
    DO_2BITS(asf->packet_property >> 4, asf->packet_seq, 0);
    DO_2BITS(asf->packet_property >> 2, asf->packet_frag_offset, 0);
    DO_2BITS(asf->packet_property, asf->packet_replic_size, 0);
    av_log(asf, AV_LOG_TRACE, "key:%d stream:%d seq:%d offset:%d replic_size:%d num:%X packet_property %X\n",
            asf->packet_key_frame, asf->stream_index, asf->packet_seq,
            asf->packet_frag_offset, asf->packet_replic_size, num, asf->packet_property);
    if (rsize+(int64_t)asf->packet_replic_size > asf->packet_size_left) {
        av_log(s, AV_LOG_ERROR, "packet_replic_size %d is invalid\n", asf->packet_replic_size);
        return AVERROR_INVALIDDATA;
    }
    if (asf->packet_replic_size >= 8) {
        int64_t end = avio_tell(pb) + asf->packet_replic_size;
        AVRational aspect;
        asfst->packet_obj_size = avio_rl32(pb);
        if (asfst->packet_obj_size >= (1 << 24) || asfst->packet_obj_size < 0) {
            av_log(s, AV_LOG_ERROR, "packet_obj_size %d invalid\n", asfst->packet_obj_size);
            asfst->packet_obj_size = 0;
            return AVERROR_INVALIDDATA;
        }
        asf->packet_frag_timestamp = avio_rl32(pb); // timestamp

        for (i = 0; i < asfst->payload_ext_ct; i++) {
            ASFPayload *p = &asfst->payload[i];
            int size = p->size;
            int64_t payend;
            if (size == 0xFFFF)
                size = avio_rl16(pb);
            payend = avio_tell(pb) + size;
            if (payend > end) {
                av_log(s, AV_LOG_ERROR, "too long payload\n");
                break;
            }
            switch (p->type) {
            case 0x50:
//              duration = avio_rl16(pb);
                break;
            case 0x54:
                aspect.num = avio_r8(pb);
                aspect.den = avio_r8(pb);
                if (aspect.num > 0 && aspect.den > 0 && asf->stream_index >= 0) {
                    s->streams[asf->stream_index]->sample_aspect_ratio = aspect;
                }
                break;
            case 0x2A:
                avio_skip(pb, 8);
                ts0 = avio_rl64(pb);
                ts1 = avio_rl64(pb);
                if (ts0!= -1) asf->packet_frag_timestamp = ts0/10000;
                else          asf->packet_frag_timestamp = AV_NOPTS_VALUE;
                asf->ts_is_pts = 1;
                break;
            case 0x5B:
            case 0xB7:
            case 0xCC:
            case 0xC0:
            case 0xA0:
                //unknown
                break;
            }
            avio_seek(pb, payend, SEEK_SET);
        }

        avio_seek(pb, end, SEEK_SET);
        rsize += asf->packet_replic_size; // FIXME - check validity
    } else if (asf->packet_replic_size == 1) {
        // multipacket - frag_offset is beginning timestamp
        asf->packet_time_start     = asf->packet_frag_offset;
        asf->packet_frag_offset    = 0;
        asf->packet_frag_timestamp = asf->packet_timestamp;

        asf->packet_time_delta = avio_r8(pb);
        rsize++;
    } else if (asf->packet_replic_size != 0) {
        av_log(s, AV_LOG_ERROR, "unexpected packet_replic_size of %d\n",
               asf->packet_replic_size);
        return AVERROR_INVALIDDATA;
    }
    if (asf->packet_flags & 0x01) {
        DO_2BITS(asf->packet_segsizetype >> 6, asf->packet_frag_size, 0); // 0 is illegal
        if (rsize > asf->packet_size_left) {
            av_log(s, AV_LOG_ERROR, "packet_replic_size is invalid\n");
            return AVERROR_INVALIDDATA;
        } else if (asf->packet_frag_size > asf->packet_size_left - rsize) {
            if (asf->packet_frag_size > asf->packet_size_left - rsize + asf->packet_padsize) {
                av_log(s, AV_LOG_ERROR, "packet_frag_size is invalid (%d>%d-%d+%d)\n",
                       asf->packet_frag_size, asf->packet_size_left, rsize, asf->packet_padsize);
                return AVERROR_INVALIDDATA;
            } else {
                int diff = asf->packet_frag_size - (asf->packet_size_left - rsize);
                asf->packet_size_left += diff;
                asf->packet_padsize   -= diff;
            }
        }
    } else {
        asf->packet_frag_size = asf->packet_size_left - rsize;
    }
    if (asf->packet_replic_size == 1) {
        asf->packet_multi_size = asf->packet_frag_size;
        if (asf->packet_multi_size > asf->packet_size_left)
            return AVERROR_INVALIDDATA;
    }
    asf->packet_size_left -= rsize;

    return 0;
}