static int nut_write_packet(AVFormatContext *s, int stream_index, 

			    const uint8_t *buf, int size, int64_t pts)

{

    NUTContext *nut = s->priv_data;

    StreamContext *stream= &nut->stream[stream_index];

    ByteIOContext *bc = &s->pb;

    int key_frame = 0, full_pts=0;

    AVCodecContext *enc;

    int64_t lsb_pts, delta_pts;

    int frame_type, best_length, frame_code, flags, i, size_mul, size_lsb;

    const int64_t frame_start= url_ftell(bc);



    if (stream_index > s->nb_streams)

	return 1;

        

    pts= (av_rescale(pts, stream->rate_num, stream->rate_den) + AV_TIME_BASE/2) / AV_TIME_BASE;



    enc = &s->streams[stream_index]->codec;

    key_frame = enc->coded_frame->key_frame;

    delta_pts= pts - stream->last_pts;

    

    frame_type=0;

    if(frame_start + size + 20 - FFMAX(nut->last_frame_start[1], nut->last_frame_start[2]) > MAX_TYPE1_DISTANCE)

        frame_type=1;

    if(key_frame){

        if(frame_type==1 && frame_start + size - nut->last_frame_start[2] > MAX_TYPE2_DISTANCE)

            frame_type=2;

        if(!stream->last_key_frame)

            frame_type=2;

    }



    if(frame_type>0){

        update_packetheader(nut, bc, 0);

        reset(s);

        full_pts=1;

    }

    //FIXME ensure that the timestamp can be represented by either delta or lsb or full_pts=1



    lsb_pts = pts & ((1 << stream->msb_timestamp_shift)-1);



    best_length=INT_MAX;

    frame_code= -1;

    for(i=0; i<256; i++){

        int stream_id_plus1= nut->frame_code[i].stream_id_plus1;

        int fc_key_frame= stream->last_key_frame;

        int length=0;

        size_mul= nut->frame_code[i].size_mul;

        size_lsb= nut->frame_code[i].size_lsb;

        flags= nut->frame_code[i].flags;



        if(stream_id_plus1 == 0) length+= get_length(stream_index);

        else if(stream_id_plus1 - 1 != stream_index)

            continue;

        if(flags & FLAG_PRED_KEY_FRAME){

            if(flags & FLAG_KEY_FRAME)

                fc_key_frame= !fc_key_frame;

        }else{

            fc_key_frame= !!(flags & FLAG_KEY_FRAME);

        }

        assert(key_frame==0 || key_frame==1);

        if(fc_key_frame != key_frame)

            continue;



        if((!!(flags & FLAG_FRAME_TYPE)) != (frame_type > 0))

            continue;

        

        if(size_mul <= size_lsb){

            int p= stream->lru_size[size_lsb - size_mul];

            if(p != size)

                continue;

        }else{

            if(size % size_mul != size_lsb)

                continue;

            if(flags & FLAG_DATA_SIZE)

                length += get_length(size / size_mul);

            else if(size/size_mul)

                continue;

        }



        if(full_pts != ((flags & FLAG_PTS) && (flags & FLAG_FULL_PTS)))

            continue;

            

        if(flags&FLAG_PTS){

            if(flags&FLAG_FULL_PTS){

                length += get_length(pts);

            }else{

                length += get_length(lsb_pts);

            }

        }else{

            int delta= stream->lru_pts_delta[(flags & 12)>>2];

            if(delta != pts - stream->last_pts)

                continue;

            assert(frame_type == 0);

        }



        if(length < best_length){

            best_length= length;

            frame_code=i;

        }

//    av_log(s, AV_LOG_DEBUG, "%d %d %d %d %d %d %d %d %d %d\n", key_frame, frame_type, full_pts, size, stream_index, flags, size_mul, size_lsb, stream_id_plus1, length);

    }



    assert(frame_code != -1);

    flags= nut->frame_code[frame_code].flags;

    size_mul= nut->frame_code[frame_code].size_mul;

    size_lsb= nut->frame_code[frame_code].size_lsb;

#if 0

    best_length /= 7;

    best_length ++; //frame_code

    if(frame_type>0){

        best_length += 4; //packet header

        if(frame_type>1)

            best_length += 8; // startcode

    }

    av_log(s, AV_LOG_DEBUG, "kf:%d ft:%d pt:%d fc:%2X len:%2d size:%d stream:%d flag:%d mul:%d lsb:%d s+1:%d pts_delta:%d\n", key_frame, frame_type, full_pts ? 2 : ((flags & FLAG_PTS) ? 1 : 0), frame_code, best_length, size, stream_index, flags, size_mul, size_lsb, nut->frame_code[frame_code].stream_id_plus1,(int)(pts - stream->last_pts));

#endif



    if (frame_type==2)

	put_be64(bc, KEYFRAME_STARTCODE);

    put_byte(bc, frame_code);



    if(frame_type>0)

        put_packetheader(nut, bc, FFMAX(size+20, MAX_TYPE1_DISTANCE));

    if(nut->frame_code[frame_code].stream_id_plus1 == 0)

        put_v(bc, stream_index);

    if (flags & FLAG_PTS){

        if (flags & FLAG_FULL_PTS)

            put_v(bc, pts);

        else

            put_v(bc, lsb_pts);

    }

    if(flags & FLAG_DATA_SIZE)

        put_v(bc, size / size_mul);

    if(size > MAX_TYPE1_DISTANCE){

        assert(frame_type > 0);

        update_packetheader(nut, bc, size);

    }

    

    put_buffer(bc, buf, size);



    update(nut, stream_index, frame_start, frame_type, frame_code, key_frame, size, pts);

    

    return 0;

}

static int nut_write_packet(AVFormatContext *s, int stream_index, 

			    const uint8_t *buf, int size, int64_t pts)

{

    NUTContext *nut = s->priv_data;

    StreamContext *stream= &nut->stream[stream_index];

    ByteIOContext *bc = &s->pb;

    int key_frame = 0, full_pts=0;

    AVCodecContext *enc;

    int64_t lsb_pts, delta_pts;

    int frame_type, best_length, frame_code, flags, i, size_mul, size_lsb;

    const int64_t frame_start= url_ftell(bc);



    if (stream_index > s->nb_streams)

	return 1;

        

    pts= (av_rescale(pts, stream->rate_num, stream->rate_den) + AV_TIME_BASE/2) / AV_TIME_BASE;



    enc = &s->streams[stream_index]->codec;

    key_frame = enc->coded_frame->key_frame;

    delta_pts= pts - stream->last_pts;

    

    frame_type=0;

    if(frame_start + size + 20 - FFMAX(nut->last_frame_start[1], nut->last_frame_start[2]) > MAX_TYPE1_DISTANCE)

        frame_type=1;

    if(key_frame){

        if(frame_type==1 && frame_start + size - nut->last_frame_start[2] > MAX_TYPE2_DISTANCE)

            frame_type=2;

        if(!stream->last_key_frame)

            frame_type=2;

    }



    if(frame_type>0){

        update_packetheader(nut, bc, 0);

        reset(s);

        full_pts=1;

    }

    



    lsb_pts = pts & ((1 << stream->msb_timestamp_shift)-1);



    best_length=INT_MAX;

    frame_code= -1;

    for(i=0; i<256; i++){

        int stream_id_plus1= nut->frame_code[i].stream_id_plus1;

        int fc_key_frame= stream->last_key_frame;

        int length=0;

        size_mul= nut->frame_code[i].size_mul;

        size_lsb= nut->frame_code[i].size_lsb;

        flags= nut->frame_code[i].flags;



        if(stream_id_plus1 == 0) length+= get_length(stream_index);

        else if(stream_id_plus1 - 1 != stream_index)

            continue;

        if(flags & FLAG_PRED_KEY_FRAME){

            if(flags & FLAG_KEY_FRAME)

                fc_key_frame= !fc_key_frame;

        }else{

            fc_key_frame= !!(flags & FLAG_KEY_FRAME);

        }

        assert(key_frame==0 || key_frame==1);

        if(fc_key_frame != key_frame)

            continue;



        if((!!(flags & FLAG_FRAME_TYPE)) != (frame_type > 0))

            continue;

        

        if(size_mul <= size_lsb){

            int p= stream->lru_size[size_lsb - size_mul];

            if(p != size)

                continue;

        }else{

            if(size % size_mul != size_lsb)

                continue;

            if(flags & FLAG_DATA_SIZE)

                length += get_length(size / size_mul);

            else if(size/size_mul)

                continue;

        }



        if(full_pts != ((flags & FLAG_PTS) && (flags & FLAG_FULL_PTS)))

            continue;

            

        if(flags&FLAG_PTS){

            if(flags&FLAG_FULL_PTS){

                length += get_length(pts);

            }else{

                length += get_length(lsb_pts);

            }

        }else{

            int delta= stream->lru_pts_delta[(flags & 12)>>2];

            if(delta != pts - stream->last_pts)

                continue;

            assert(frame_type == 0);

        }



        if(length < best_length){

            best_length= length;

            frame_code=i;

        }



    }



    assert(frame_code != -1);

    flags= nut->frame_code[frame_code].flags;

    size_mul= nut->frame_code[frame_code].size_mul;

    size_lsb= nut->frame_code[frame_code].size_lsb;

#if 0

    best_length /= 7;

    best_length ++; 

    if(frame_type>0){

        best_length += 4; 

        if(frame_type>1)

            best_length += 8; 

    }

    av_log(s, AV_LOG_DEBUG, "kf:%d ft:%d pt:%d fc:%2X len:%2d size:%d stream:%d flag:%d mul:%d lsb:%d s+1:%d pts_delta:%d\n", key_frame, frame_type, full_pts ? 2 : ((flags & FLAG_PTS) ? 1 : 0), frame_code, best_length, size, stream_index, flags, size_mul, size_lsb, nut->frame_code[frame_code].stream_id_plus1,(int)(pts - stream->last_pts));

#endif



    if (frame_type==2)

	put_be64(bc, KEYFRAME_STARTCODE);

    put_byte(bc, frame_code);



    if(frame_type>0)

        put_packetheader(nut, bc, FFMAX(size+20, MAX_TYPE1_DISTANCE));

    if(nut->frame_code[frame_code].stream_id_plus1 == 0)

        put_v(bc, stream_index);

    if (flags & FLAG_PTS){

        if (flags & FLAG_FULL_PTS)

            put_v(bc, pts);

        else

            put_v(bc, lsb_pts);

    }

    if(flags & FLAG_DATA_SIZE)

        put_v(bc, size / size_mul);

    if(size > MAX_TYPE1_DISTANCE){

        assert(frame_type > 0);

        update_packetheader(nut, bc, size);

    }

    

    put_buffer(bc, buf, size);



    update(nut, stream_index, frame_start, frame_type, frame_code, key_frame, size, pts);

    

    return 0;

}

static int FUNC_0(AVFormatContext *VAR_0, int VAR_1, 

			    const uint8_t *VAR_2, int VAR_3, int64_t VAR_4)

{

    NUTContext *nut = VAR_0->priv_data;

    StreamContext *stream= &nut->stream[VAR_1];

    ByteIOContext *bc = &VAR_0->pb;

    int VAR_5 = 0, VAR_6=0;

    AVCodecContext *enc;

    int64_t lsb_pts, delta_pts;

    int VAR_7, VAR_8, VAR_9, VAR_10, VAR_11, VAR_12, VAR_13;

    const int64_t VAR_14= url_ftell(bc);



    if (VAR_1 > VAR_0->nb_streams)

	return 1;

        

    VAR_4= (av_rescale(VAR_4, stream->rate_num, stream->rate_den) + AV_TIME_BASE/2) / AV_TIME_BASE;



    enc = &VAR_0->streams[VAR_1]->codec;

    VAR_5 = enc->coded_frame->VAR_5;

    delta_pts= VAR_4 - stream->last_pts;

    

    VAR_7=0;

    if(VAR_14 + VAR_3 + 20 - FFMAX(nut->last_frame_start[1], nut->last_frame_start[2]) > MAX_TYPE1_DISTANCE)

        VAR_7=1;

    if(VAR_5){

        if(VAR_7==1 && VAR_14 + VAR_3 - nut->last_frame_start[2] > MAX_TYPE2_DISTANCE)

            VAR_7=2;

        if(!stream->last_key_frame)

            VAR_7=2;

    }



    if(VAR_7>0){

        update_packetheader(nut, bc, 0);

        reset(VAR_0);

        VAR_6=1;

    }

    



    lsb_pts = VAR_4 & ((1 << stream->msb_timestamp_shift)-1);



    VAR_8=INT_MAX;

    VAR_9= -1;

    for(VAR_11=0; VAR_11<256; VAR_11++){

        int VAR_15= nut->VAR_9[VAR_11].VAR_15;

        int VAR_16= stream->last_key_frame;

        int VAR_17=0;

        VAR_12= nut->VAR_9[VAR_11].VAR_12;

        VAR_13= nut->VAR_9[VAR_11].VAR_13;

        VAR_10= nut->VAR_9[VAR_11].VAR_10;



        if(VAR_15 == 0) VAR_17+= get_length(VAR_1);

        else if(VAR_15 - 1 != VAR_1)

            continue;

        if(VAR_10 & FLAG_PRED_KEY_FRAME){

            if(VAR_10 & FLAG_KEY_FRAME)

                VAR_16= !VAR_16;

        }else{

            VAR_16= !!(VAR_10 & FLAG_KEY_FRAME);

        }

        assert(VAR_5==0 || VAR_5==1);

        if(VAR_16 != VAR_5)

            continue;



        if((!!(VAR_10 & FLAG_FRAME_TYPE)) != (VAR_7 > 0))

            continue;

        

        if(VAR_12 <= VAR_13){

            int VAR_18= stream->lru_size[VAR_13 - VAR_12];

            if(VAR_18 != VAR_3)

                continue;

        }else{

            if(VAR_3 % VAR_12 != VAR_13)

                continue;

            if(VAR_10 & FLAG_DATA_SIZE)

                VAR_17 += get_length(VAR_3 / VAR_12);

            else if(VAR_3/VAR_12)

                continue;

        }



        if(VAR_6 != ((VAR_10 & FLAG_PTS) && (VAR_10 & FLAG_FULL_PTS)))

            continue;

            

        if(VAR_10&FLAG_PTS){

            if(VAR_10&FLAG_FULL_PTS){

                VAR_17 += get_length(VAR_4);

            }else{

                VAR_17 += get_length(lsb_pts);

            }

        }else{

            int VAR_19= stream->lru_pts_delta[(VAR_10 & 12)>>2];

            if(VAR_19 != VAR_4 - stream->last_pts)

                continue;

            assert(VAR_7 == 0);

        }



        if(VAR_17 < VAR_8){

            VAR_8= VAR_17;

            VAR_9=VAR_11;

        }



    }



    assert(VAR_9 != -1);

    VAR_10= nut->VAR_9[VAR_9].VAR_10;

    VAR_12= nut->VAR_9[VAR_9].VAR_12;

    VAR_13= nut->VAR_9[VAR_9].VAR_13;

#if 0

    VAR_8 /= 7;

    VAR_8 ++; 

    if(VAR_7>0){

        VAR_8 += 4; 

        if(VAR_7>1)

            VAR_8 += 8; 

    }

    av_log(VAR_0, AV_LOG_DEBUG, "kf:%d ft:%d pt:%d fc:%2X len:%2d VAR_3:%d stream:%d flag:%d mul:%d lsb:%d VAR_0+1:%d pts_delta:%d\n", VAR_5, VAR_7, VAR_6 ? 2 : ((VAR_10 & FLAG_PTS) ? 1 : 0), VAR_9, VAR_8, VAR_3, VAR_1, VAR_10, VAR_12, VAR_13, nut->VAR_9[VAR_9].VAR_15,(int)(VAR_4 - stream->last_pts));

#endif



    if (VAR_7==2)

	put_be64(bc, KEYFRAME_STARTCODE);

    put_byte(bc, VAR_9);



    if(VAR_7>0)

        put_packetheader(nut, bc, FFMAX(VAR_3+20, MAX_TYPE1_DISTANCE));

    if(nut->VAR_9[VAR_9].VAR_15 == 0)

        put_v(bc, VAR_1);

    if (VAR_10 & FLAG_PTS){

        if (VAR_10 & FLAG_FULL_PTS)

            put_v(bc, VAR_4);

        else

            put_v(bc, lsb_pts);

    }

    if(VAR_10 & FLAG_DATA_SIZE)

        put_v(bc, VAR_3 / VAR_12);

    if(VAR_3 > MAX_TYPE1_DISTANCE){

        assert(VAR_7 > 0);

        update_packetheader(nut, bc, VAR_3);

    }

    

    put_buffer(bc, VAR_2, VAR_3);



    update(nut, VAR_1, VAR_14, VAR_7, VAR_9, VAR_5, VAR_3, VAR_4);

    

    return 0;

}

static int FUNC_0(AVFormatContext *VAR_0, int VAR_1,
const uint8_t *VAR_2, int VAR_3, int64_t VAR_4)
{ NUTContext *nut = VAR_0->priv_data; StreamContext *stream= &nut->stream[VAR_1]; ByteIOContext *bc = &VAR_0->pb; int VAR_5 = 0, VAR_6=0; AVCodecContext *enc; int64_t lsb_pts, delta_pts; int VAR_7, VAR_8, VAR_9, VAR_10, VAR_11, VAR_12, VAR_13; const int64_t VAR_14= url_ftell(bc); if (VAR_1 > VAR_0->nb_streams)
return 1; VAR_4= (av_rescale(VAR_4, stream->rate_num, stream->rate_den) + AV_TIME_BASE/2) / AV_TIME_BASE; enc = &VAR_0->streams[VAR_1]->codec; VAR_5 = enc->coded_frame->VAR_5; delta_pts= VAR_4 - stream->last_pts; VAR_7=0; if(VAR_14 + VAR_3 + 20 - FFMAX(nut->last_frame_start[1], nut->last_frame_start[2]) > MAX_TYPE1_DISTANCE)
VAR_7=1; if(VAR_5){ if(VAR_7==1 && VAR_14 + VAR_3 - nut->last_frame_start[2] > MAX_TYPE2_DISTANCE)
VAR_7=2; if(!stream->last_key_frame)
VAR_7=2; } if(VAR_7>0){ update_packetheader(nut, bc, 0); reset(VAR_0); VAR_6=1; } lsb_pts = VAR_4 & ((1 << stream->msb_timestamp_shift)-1); VAR_8=INT_MAX; VAR_9= -1; for(VAR_11=0; VAR_11<256; VAR_11++){ int VAR_15= nut->VAR_9[VAR_11].VAR_15; int VAR_16= stream->last_key_frame; int VAR_17=0; VAR_12= nut->VAR_9[VAR_11].VAR_12; VAR_13= nut->VAR_9[VAR_11].VAR_13; VAR_10= nut->VAR_9[VAR_11].VAR_10; if(VAR_15 == 0) VAR_17+= get_length(VAR_1); else if(VAR_15 - 1 != VAR_1)
continue; if(VAR_10 & FLAG_PRED_KEY_FRAME){ if(VAR_10 & FLAG_KEY_FRAME)
VAR_16= !VAR_16; }else{ VAR_16= !!(VAR_10 & FLAG_KEY_FRAME); } assert(VAR_5==0 || VAR_5==1); if(VAR_16 != VAR_5)
continue; if((!!(VAR_10 & FLAG_FRAME_TYPE)) != (VAR_7 > 0))
continue; if(VAR_12 <= VAR_13){ int VAR_18= stream->lru_size[VAR_13 - VAR_12]; if(VAR_18 != VAR_3)
continue; }else{ if(VAR_3 % VAR_12 != VAR_13)
continue; if(VAR_10 & FLAG_DATA_SIZE)
VAR_17 += get_length(VAR_3 / VAR_12); else if(VAR_3/VAR_12)
continue; } if(VAR_6 != ((VAR_10 & FLAG_PTS) && (VAR_10 & FLAG_FULL_PTS)))
continue; if(VAR_10&FLAG_PTS){ if(VAR_10&FLAG_FULL_PTS){ VAR_17 += get_length(VAR_4); }else{ VAR_17 += get_length(lsb_pts); } }else{ int VAR_19= stream->lru_pts_delta[(VAR_10 & 12)>>2]; if(VAR_19 != VAR_4 - stream->last_pts)
continue; assert(VAR_7 == 0); } if(VAR_17 < VAR_8){ VAR_8= VAR_17; VAR_9=VAR_11; } } assert(VAR_9 != -1); VAR_10= nut->VAR_9[VAR_9].VAR_10; VAR_12= nut->VAR_9[VAR_9].VAR_12; VAR_13= nut->VAR_9[VAR_9].VAR_13; #if 0
VAR_8 /= 7; VAR_8 ++; if(VAR_7>0){ VAR_8 += 4; if(VAR_7>1)
VAR_8 += 8; } av_log(VAR_0, AV_LOG_DEBUG, "kf:%d ft:%d pt:%d fc:%2X len:%2d VAR_3:%d stream:%d flag:%d mul:%d lsb:%d VAR_0+1:%d pts_delta:%d\n", VAR_5, VAR_7, VAR_6 ? 2 : ((VAR_10 & FLAG_PTS) ? 1 : 0), VAR_9, VAR_8, VAR_3, VAR_1, VAR_10, VAR_12, VAR_13, nut->VAR_9[VAR_9].VAR_15,(int)(VAR_4 - stream->last_pts)); #endif
if (VAR_7==2)
put_be64(bc, KEYFRAME_STARTCODE); put_byte(bc, VAR_9); if(VAR_7>0)
put_packetheader(nut, bc, FFMAX(VAR_3+20, MAX_TYPE1_DISTANCE)); if(nut->VAR_9[VAR_9].VAR_15 == 0)
put_v(bc, VAR_1); if (VAR_10 & FLAG_PTS){ if (VAR_10 & FLAG_FULL_PTS)
put_v(bc, VAR_4); else
put_v(bc, lsb_pts); } if(VAR_10 & FLAG_DATA_SIZE)
put_v(bc, VAR_3 / VAR_12); if(VAR_3 > MAX_TYPE1_DISTANCE){ assert(VAR_7 > 0); update_packetheader(nut, bc, VAR_3); } put_buffer(bc, VAR_2, VAR_3); update(nut, VAR_1, VAR_14, VAR_7, VAR_9, VAR_5, VAR_3, VAR_4); return 0; }