static int rtmp_packet_read_one_chunk(URLContext *h, RTMPPacket *p,

                                      int chunk_size, RTMPPacket **prev_pkt_ptr,

                                      int *nb_prev_pkt, uint8_t hdr)

{



    uint8_t buf[16];

    int channel_id, timestamp, size;

    uint32_t ts_field; // non-extended timestamp or delta field

    uint32_t extra = 0;

    enum RTMPPacketType type;

    int written = 0;

    int ret, toread;

    RTMPPacket *prev_pkt;



    written++;

    channel_id = hdr & 0x3F;



    if (channel_id < 2) { //special case for channel number >= 64

        buf[1] = 0;

        if (ffurl_read_complete(h, buf, channel_id + 1) != channel_id + 1)

            return AVERROR(EIO);

        written += channel_id + 1;

        channel_id = AV_RL16(buf) + 64;

    }

    if ((ret = ff_rtmp_check_alloc_array(prev_pkt_ptr, nb_prev_pkt,

                                         channel_id)) < 0)

        return ret;

    prev_pkt = *prev_pkt_ptr;

    size  = prev_pkt[channel_id].size;

    type  = prev_pkt[channel_id].type;

    extra = prev_pkt[channel_id].extra;



    hdr >>= 6; // header size indicator

    if (hdr == RTMP_PS_ONEBYTE) {

        ts_field = prev_pkt[channel_id].ts_field;

    } else {

        if (ffurl_read_complete(h, buf, 3) != 3)

            return AVERROR(EIO);

        written += 3;

        ts_field = AV_RB24(buf);

        if (hdr != RTMP_PS_FOURBYTES) {

            if (ffurl_read_complete(h, buf, 3) != 3)

                return AVERROR(EIO);

            written += 3;

            size = AV_RB24(buf);

            if (ffurl_read_complete(h, buf, 1) != 1)

                return AVERROR(EIO);

            written++;

            type = buf[0];

            if (hdr == RTMP_PS_TWELVEBYTES) {

                if (ffurl_read_complete(h, buf, 4) != 4)

                    return AVERROR(EIO);

                written += 4;

                extra = AV_RL32(buf);

            }

        }

    }

    if (ts_field == 0xFFFFFF) {

        if (ffurl_read_complete(h, buf, 4) != 4)

            return AVERROR(EIO);

        timestamp = AV_RB32(buf);

    } else {

        timestamp = ts_field;

    }

    if (hdr != RTMP_PS_TWELVEBYTES)

        timestamp += prev_pkt[channel_id].timestamp;



    if (!prev_pkt[channel_id].read) {

        if ((ret = ff_rtmp_packet_create(p, channel_id, type, timestamp,

                                         size)) < 0)

            return ret;

        p->read = written;

        p->offset = 0;

        prev_pkt[channel_id].ts_field   = ts_field;

        prev_pkt[channel_id].timestamp  = timestamp;

    } else {

        // previous packet in this channel hasn't completed reading

        RTMPPacket *prev = &prev_pkt[channel_id];

        p->data          = prev->data;

        p->size          = prev->size;

        p->channel_id    = prev->channel_id;

        p->type          = prev->type;

        p->ts_field      = prev->ts_field;

        p->extra         = prev->extra;

        p->offset        = prev->offset;

        p->read          = prev->read + written;

        p->timestamp     = prev->timestamp;

        prev->data       = NULL;

    }

    p->extra = extra;

    // save history

    prev_pkt[channel_id].channel_id = channel_id;

    prev_pkt[channel_id].type       = type;

    prev_pkt[channel_id].size       = size;

    prev_pkt[channel_id].extra      = extra;

    size = size - p->offset;



    toread = FFMIN(size, chunk_size);

    if (ffurl_read_complete(h, p->data + p->offset, toread) != toread) {

        ff_rtmp_packet_destroy(p);

        return AVERROR(EIO);

    }

    size      -= toread;

    p->read   += toread;

    p->offset += toread;



    if (size > 0) {

       RTMPPacket *prev = &prev_pkt[channel_id];

       prev->data = p->data;

       prev->read = p->read;

       prev->offset = p->offset;


       return AVERROR(EAGAIN);

    }



    prev_pkt[channel_id].read = 0; // read complete; reset if needed

    return p->read;

}