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;
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; 
    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) { 
        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; 
    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 {
        
        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;
    
    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; 
    return p->read;
static int FUNC_0(URLContext *VAR_0, RTMPPacket *VAR_1,
                                      int VAR_2, RTMPPacket **VAR_3,
                                      int *VAR_4, uint8_t VAR_5)
{
    uint8_t buf[16];
    int VAR_6, VAR_7, VAR_8;
    uint32_t ts_field; 
    uint32_t extra = 0;
    enum RTMPPacketType VAR_9;
    int VAR_10 = 0;
    int VAR_11, VAR_12;
    RTMPPacket *prev_pkt;
    VAR_10++;
    VAR_6 = VAR_5 & 0x3F;
    if (VAR_6 < 2) { 
        buf[1] = 0;
        if (ffurl_read_complete(VAR_0, buf, VAR_6 + 1) != VAR_6 + 1)
            return AVERROR(EIO);
        VAR_10 += VAR_6 + 1;
        VAR_6 = AV_RL16(buf) + 64;
    if ((VAR_11 = ff_rtmp_check_alloc_array(VAR_3, VAR_4,
                                         VAR_6)) < 0)
        return VAR_11;
    prev_pkt = *VAR_3;
    VAR_8  = prev_pkt[VAR_6].VAR_8;
    VAR_9  = prev_pkt[VAR_6].VAR_9;
    extra = prev_pkt[VAR_6].extra;
    VAR_5 >>= 6; 
    if (VAR_5 == RTMP_PS_ONEBYTE) {
        ts_field = prev_pkt[VAR_6].ts_field;
    } else {
        if (ffurl_read_complete(VAR_0, buf, 3) != 3)
            return AVERROR(EIO);
        VAR_10 += 3;
        ts_field = AV_RB24(buf);
        if (VAR_5 != RTMP_PS_FOURBYTES) {
            if (ffurl_read_complete(VAR_0, buf, 3) != 3)
                return AVERROR(EIO);
            VAR_10 += 3;
            VAR_8 = AV_RB24(buf);
            if (ffurl_read_complete(VAR_0, buf, 1) != 1)
                return AVERROR(EIO);
            VAR_10++;
            VAR_9 = buf[0];
            if (VAR_5 == RTMP_PS_TWELVEBYTES) {
                if (ffurl_read_complete(VAR_0, buf, 4) != 4)
                    return AVERROR(EIO);
                VAR_10 += 4;
                extra = AV_RL32(buf);
    if (ts_field == 0xFFFFFF) {
        if (ffurl_read_complete(VAR_0, buf, 4) != 4)
            return AVERROR(EIO);
        VAR_7 = AV_RB32(buf);
    } else {
        VAR_7 = ts_field;
    if (VAR_5 != RTMP_PS_TWELVEBYTES)
        VAR_7 += prev_pkt[VAR_6].VAR_7;
    if (!prev_pkt[VAR_6].read) {
        if ((VAR_11 = ff_rtmp_packet_create(VAR_1, VAR_6, VAR_9, VAR_7,
                                         VAR_8)) < 0)
            return VAR_11;
        VAR_1->read = VAR_10;
        VAR_1->offset = 0;
        prev_pkt[VAR_6].ts_field   = ts_field;
        prev_pkt[VAR_6].VAR_7  = VAR_7;
    } else {
        
        RTMPPacket *prev = &prev_pkt[VAR_6];
        VAR_1->data          = prev->data;
        VAR_1->VAR_8          = prev->VAR_8;
        VAR_1->VAR_6    = prev->VAR_6;
        VAR_1->VAR_9          = prev->VAR_9;
        VAR_1->ts_field      = prev->ts_field;
        VAR_1->extra         = prev->extra;
        VAR_1->offset        = prev->offset;
        VAR_1->read          = prev->read + VAR_10;
        VAR_1->VAR_7     = prev->VAR_7;
        prev->data       = NULL;
    VAR_1->extra = extra;
    
    prev_pkt[VAR_6].VAR_6 = VAR_6;
    prev_pkt[VAR_6].VAR_9       = VAR_9;
    prev_pkt[VAR_6].VAR_8       = VAR_8;
    prev_pkt[VAR_6].extra      = extra;
    VAR_8 = VAR_8 - VAR_1->offset;
    VAR_12 = FFMIN(VAR_8, VAR_2);
    if (ffurl_read_complete(VAR_0, VAR_1->data + VAR_1->offset, VAR_12) != VAR_12) {
        ff_rtmp_packet_destroy(VAR_1);
        return AVERROR(EIO);
    VAR_8      -= VAR_12;
    VAR_1->read   += VAR_12;
    VAR_1->offset += VAR_12;
    if (VAR_8 > 0) {
       RTMPPacket *prev = &prev_pkt[VAR_6];
       prev->data = VAR_1->data;
       prev->read = VAR_1->read;
       prev->offset = VAR_1->offset;
       return AVERROR(EAGAIN);
    prev_pkt[VAR_6].read = 0; 
    return VAR_1->read;
static int FUNC_0(URLContext *VAR_0, RTMPPacket *VAR_1,
int VAR_2, RTMPPacket **VAR_3,
int *VAR_4, uint8_t VAR_5)
{ uint8_t buf[16]; int VAR_6, VAR_7, VAR_8; uint32_t ts_field; uint32_t extra = 0; enum RTMPPacketType VAR_9; int VAR_10 = 0; int VAR_11, VAR_12; RTMPPacket *prev_pkt; VAR_10++; VAR_6 = VAR_5 & 0x3F; if (VAR_6 < 2) { buf[1] = 0; if (ffurl_read_complete(VAR_0, buf, VAR_6 + 1) != VAR_6 + 1)
return AVERROR(EIO); VAR_10 += VAR_6 + 1; VAR_6 = AV_RL16(buf) + 64; if ((VAR_11 = ff_rtmp_check_alloc_array(VAR_3, VAR_4,
VAR_6)) < 0)
return VAR_11; prev_pkt = *VAR_3; VAR_8  = prev_pkt[VAR_6].VAR_8; VAR_9  = prev_pkt[VAR_6].VAR_9; extra = prev_pkt[VAR_6].extra; VAR_5 >>= 6; if (VAR_5 == RTMP_PS_ONEBYTE) { ts_field = prev_pkt[VAR_6].ts_field; } else { if (ffurl_read_complete(VAR_0, buf, 3) != 3)
return AVERROR(EIO); VAR_10 += 3; ts_field = AV_RB24(buf); if (VAR_5 != RTMP_PS_FOURBYTES) { if (ffurl_read_complete(VAR_0, buf, 3) != 3)
return AVERROR(EIO); VAR_10 += 3; VAR_8 = AV_RB24(buf); if (ffurl_read_complete(VAR_0, buf, 1) != 1)
return AVERROR(EIO); VAR_10++; VAR_9 = buf[0]; if (VAR_5 == RTMP_PS_TWELVEBYTES) { if (ffurl_read_complete(VAR_0, buf, 4) != 4)
return AVERROR(EIO); VAR_10 += 4; extra = AV_RL32(buf); if (ts_field == 0xFFFFFF) { if (ffurl_read_complete(VAR_0, buf, 4) != 4)
return AVERROR(EIO); VAR_7 = AV_RB32(buf); } else { VAR_7 = ts_field; if (VAR_5 != RTMP_PS_TWELVEBYTES)
VAR_7 += prev_pkt[VAR_6].VAR_7; if (!prev_pkt[VAR_6].read) { if ((VAR_11 = ff_rtmp_packet_create(VAR_1, VAR_6, VAR_9, VAR_7,
VAR_8)) < 0)
return VAR_11; VAR_1->read = VAR_10; VAR_1->offset = 0; prev_pkt[VAR_6].ts_field   = ts_field; prev_pkt[VAR_6].VAR_7  = VAR_7; } else { RTMPPacket *prev = &prev_pkt[VAR_6]; VAR_1->data          = prev->data; VAR_1->VAR_8          = prev->VAR_8; VAR_1->VAR_6    = prev->VAR_6; VAR_1->VAR_9          = prev->VAR_9; VAR_1->ts_field      = prev->ts_field; VAR_1->extra         = prev->extra; VAR_1->offset        = prev->offset; VAR_1->read          = prev->read + VAR_10; VAR_1->VAR_7     = prev->VAR_7; prev->data       = NULL; VAR_1->extra = extra; prev_pkt[VAR_6].VAR_6 = VAR_6; prev_pkt[VAR_6].VAR_9       = VAR_9; prev_pkt[VAR_6].VAR_8       = VAR_8; prev_pkt[VAR_6].extra      = extra; VAR_8 = VAR_8 - VAR_1->offset; VAR_12 = FFMIN(VAR_8, VAR_2); if (ffurl_read_complete(VAR_0, VAR_1->data + VAR_1->offset, VAR_12) != VAR_12) { ff_rtmp_packet_destroy(VAR_1); return AVERROR(EIO); VAR_8      -= VAR_12; VAR_1->read   += VAR_12; VAR_1->offset += VAR_12; if (VAR_8 > 0) { RTMPPacket *prev = &prev_pkt[VAR_6]; prev->data = VAR_1->data; prev->read = VAR_1->read; prev->offset = VAR_1->offset; return AVERROR(EAGAIN); prev_pkt[VAR_6].read = 0; return VAR_1->read;