diff mpegvideo.c @ 903:22ee74da2cd3 libavcodec

cleanup adding AVVideoFrame moving quality, pict_type, key_frame, qscale_table, ... to AVVideoFrame removing obsolete variables in AVCodecContext skiping of MBs in b frames correctly initalizing AVCodecContext picture buffer cleanup
author michaelni
date Wed, 04 Dec 2002 10:04:03 +0000
parents 9d9a415e3dd9
children 8ae1e4c24e91
line wrap: on
line diff
--- a/mpegvideo.c	Tue Dec 03 19:40:35 2002 +0000
+++ b/mpegvideo.c	Wed Dec 04 10:04:03 2002 +0000
@@ -46,7 +46,6 @@
 static void emulated_edge_mc(MpegEncContext *s, UINT8 *src, int linesize, int block_w, int block_h, 
                                     int src_x, int src_y, int w, int h);
 
-#define EDGE_WIDTH 16
 
 /* enable all paranoid tests for rounding, overflows, etc... */
 //#define PARANOID
@@ -268,10 +267,47 @@
     return 0;
 }
 
+/**
+ * allocates various arrays for a Picture structure, except the pixels themself.
+ * The pixels are allocated/set in te get_buffer()
+ */
+static int alloc_picture(MpegEncContext *s, Picture *pic){
+    if (s->encoding) {        
+        CHECKED_ALLOCZ(pic->mb_var   , s->mb_num * sizeof(INT16))
+        CHECKED_ALLOCZ(pic->mc_mb_var, s->mb_num * sizeof(INT16))
+        CHECKED_ALLOCZ(pic->mb_mean  , s->mb_num * sizeof(INT8))
+    }
+
+    CHECKED_ALLOCZ(pic->mbskip_table , s->mb_num * sizeof(UINT8)+1) //the +1 is for the slice end check
+    CHECKED_ALLOCZ(pic->qscale_table , s->mb_num * sizeof(UINT8))
+    pic->qstride= s->mb_width;
+    
+    return 0;
+fail: //for the CHECKED_ALLOCZ macro
+    return -1;
+}
+
+static void free_picture(MpegEncContext *s, Picture *pic){
+    int i;
+    
+    av_freep(&pic->mb_var);
+    av_freep(&pic->mc_mb_var);
+    av_freep(&pic->mb_mean);
+    av_freep(&pic->mbskip_table);
+    av_freep(&pic->qscale_table);
+    
+    if(s->avctx->get_buffer == avcodec_default_get_buffer){
+        for(i=0; i<4; i++){
+            av_freep(&pic->base[i]);
+            pic->data[i]= NULL;
+        }
+        av_freep(&pic->opaque);
+    }
+}
+
 /* init common structure for both encoder and decoder */
 int MPV_common_init(MpegEncContext *s)
 {
-    UINT8 *pict;
     int y_size, c_size, yc_size, i;
 
     dsputil_init(&s->dsp, s->avctx->dsp_mask);
@@ -279,7 +315,7 @@
 
     s->flags= s->avctx->flags;
 
-    s->mb_width = (s->width + 15) / 16;
+    s->mb_width  = (s->width  + 15) / 16;
     s->mb_height = (s->height + 15) / 16;
 
     /* set default edge pos, will be overriden in decode_header if needed */
@@ -298,51 +334,12 @@
                      + (toupper((s->avctx->fourcc>>16)&0xFF)<<16) 
                      + (toupper((s->avctx->fourcc>>24)&0xFF)<<24);
 
-    if(!(s->flags&CODEC_FLAG_DR1)){
-      s->linesize   = s->mb_width * 16 + 2 * EDGE_WIDTH;
-      s->uvlinesize = s->mb_width * 8  +     EDGE_WIDTH;
-
-      for(i=0;i<3;i++) {
-	int w, h, shift, pict_start;
-	unsigned size;
-
-        w = s->linesize;
-        h = s->mb_height * 16 + 2 * EDGE_WIDTH;
-        shift = (i == 0) ? 0 : 1;
-        size = (s->linesize>>shift) * (h >> shift);
-        pict_start = (s->linesize>>shift) * (EDGE_WIDTH >> shift) + (EDGE_WIDTH >> shift);
-
-        CHECKED_ALLOCZ(pict, size)
-        s->last_picture_base[i] = pict;
-        s->last_picture[i] = pict + pict_start;
-        if(i>0) memset(s->last_picture_base[i], 128, size);
-    
-        CHECKED_ALLOCZ(pict, size)
-        s->next_picture_base[i] = pict;
-        s->next_picture[i] = pict + pict_start;
-        if(i>0) memset(s->next_picture_base[i], 128, size);
-        
-        if (s->has_b_frames || s->codec_id==CODEC_ID_MPEG4) {
-        /* Note the MPEG4 stuff is here cuz of buggy encoders which dont set the low_delay flag but 
-           do low-delay encoding, so we cant allways distinguish b-frame containing streams from low_delay streams */
-            CHECKED_ALLOCZ(pict, size)
-            s->aux_picture_base[i] = pict;
-            s->aux_picture[i] = pict + pict_start;
-            if(i>0) memset(s->aux_picture_base[i], 128, size);
-        }
-      }
-      s->ip_buffer_count= 2;
-    }
-    
     CHECKED_ALLOCZ(s->edge_emu_buffer, (s->width+64)*2*17*2); //(width + edge + align)*interlaced*MBsize*tolerance
-    
+
+    s->avctx->coded_picture= (AVVideoFrame*)&s->current_picture;
+
     if (s->encoding) {
-        int j;
         int mv_table_size= (s->mb_width+2)*(s->mb_height+2);
-        
-        CHECKED_ALLOCZ(s->mb_var   , s->mb_num * sizeof(INT16))
-        CHECKED_ALLOCZ(s->mc_mb_var, s->mb_num * sizeof(INT16))
-        CHECKED_ALLOCZ(s->mb_mean  , s->mb_num * sizeof(INT8))
 
         /* Allocate MV tables */
         CHECKED_ALLOCZ(s->p_mv_table            , mv_table_size * 2 * sizeof(INT16))
@@ -354,28 +351,12 @@
         CHECKED_ALLOCZ(s->b_direct_back_mv_table, mv_table_size * 2 * sizeof(INT16))
         CHECKED_ALLOCZ(s->b_direct_mv_table     , mv_table_size * 2 * sizeof(INT16))
 
-        CHECKED_ALLOCZ(s->me_scratchpad,  s->linesize*16*3*sizeof(uint8_t))
+        //FIXME should be linesize instead of s->width*2 but that isnt known before get_buffer()
+        CHECKED_ALLOCZ(s->me_scratchpad,  s->width*2*16*3*sizeof(uint8_t)) 
         
         CHECKED_ALLOCZ(s->me_map      , ME_MAP_SIZE*sizeof(uint32_t))
         CHECKED_ALLOCZ(s->me_score_map, ME_MAP_SIZE*sizeof(uint16_t))
 
-        if(s->max_b_frames){
-            for(j=0; j<REORDER_BUFFER_SIZE; j++){
-                int i;
-                for(i=0;i<3;i++) {
-                    int w, h, shift, size;
-
-                    w = s->linesize;
-                    h = s->mb_height * 16;
-                    shift = (i == 0) ? 0 : 1;
-                    size = (w >> shift) * (h >> shift);
-
-                    CHECKED_ALLOCZ(pict, size);
-                    s->picture_buffer[j][i] = pict;
-                }
-            }
-        }
-
         if(s->codec_id==CODEC_ID_MPEG4){
             CHECKED_ALLOCZ(s->tex_pb_buffer, PB_BUFFER_SIZE);
             CHECKED_ALLOCZ(   s->pb2_buffer, PB_BUFFER_SIZE);
@@ -434,12 +415,6 @@
             s->dc_val[0][i] = 1024;
     }
 
-    CHECKED_ALLOCZ(s->next_qscale_table  , s->mb_num * sizeof(UINT8))
-    CHECKED_ALLOCZ(s->last_qscale_table  , s->mb_num * sizeof(UINT8))
-    CHECKED_ALLOCZ(s->aux_qscale_table   , s->mb_num * sizeof(UINT8))
-    s->qscale_table= s->next_qscale_table;
-    s->avctx->qstride= s->mb_width;
-    
     /* which mb is a intra block */
     CHECKED_ALLOCZ(s->mbintra_table, s->mb_num);
     memset(s->mbintra_table, 1, s->mb_num);
@@ -470,10 +445,13 @@
 {
     int i;
 
+    for(i=0; i<MAX_PICTURE_COUNT; i++){
+        if(s->picture[i].data[0]){
+            s->avctx->release_buffer(s->avctx, (AVVideoFrame*)&s->picture[i]);
+        }
+    }
+    
     av_freep(&s->mb_type);
-    av_freep(&s->mb_var);
-    av_freep(&s->mc_mb_var);
-    av_freep(&s->mb_mean);
     av_freep(&s->p_mv_table);
     av_freep(&s->b_forw_mv_table);
     av_freep(&s->b_back_mv_table);
@@ -489,9 +467,6 @@
     av_freep(&s->mbintra_table);
     av_freep(&s->cbp_table);
     av_freep(&s->pred_dir_table);
-    av_freep(&s->next_qscale_table);
-    av_freep(&s->last_qscale_table);
-    av_freep(&s->aux_qscale_table);
     av_freep(&s->me_scratchpad);
     av_freep(&s->me_map);
     av_freep(&s->me_score_map);
@@ -507,24 +482,9 @@
     av_freep(&s->avctx->stats_out);
     av_freep(&s->ac_stats);
     av_freep(&s->error_status_table);
-    
-    for(i=0;i<3;i++) {
-        int j;
-        if(!(s->flags&CODEC_FLAG_DR1)){
-            av_freep(&s->last_picture_base[i]);
-            av_freep(&s->next_picture_base[i]);
-            av_freep(&s->aux_picture_base[i]);
-        }
-        s->last_picture_base[i]=
-        s->next_picture_base[i]=
-        s->aux_picture_base [i] = NULL;
-        s->last_picture[i]=
-        s->next_picture[i]=
-        s->aux_picture [i] = NULL;
-
-        for(j=0; j<REORDER_BUFFER_SIZE; j++){
-            av_freep(&s->picture_buffer[j][i]);
-        }
+
+    for(i=0; i<MAX_PICTURE_COUNT; i++){
+        free_picture(s, &s->picture[i]);
     }
     s->context_initialized = 0;
 }
@@ -813,70 +773,70 @@
 /* generic function for encode/decode called before a frame is coded/decoded */
 int MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx)
 {
-    int i;
-    UINT8 *tmp;
+    int i, r;
+    AVVideoFrame *pic;
 
     s->mb_skiped = 0;
-    avctx->mbskip_table= s->mbskip_table;
+    
+    /* mark&release old frames */
+    if (s->pict_type != B_TYPE && s->last_picture.data[0]) {
+        Picture *pic= NULL;
+        for(i=0; i<MAX_PICTURE_COUNT; i++){
+            if(s->picture[i].data[0] == s->last_picture.data[0]){
+//                s->picture[i].reference=0;
+                avctx->release_buffer(avctx, (AVVideoFrame*)&s->picture[i]);
+                break;
+            }    
+        }
+        assert(i<MAX_PICTURE_COUNT);
+
+        /* release forgotten pictures */
+        /* if(mpeg124/h263) */
+        if(!s->encoding){
+            for(i=0; i<MAX_PICTURE_COUNT; i++){
+                if(s->picture[i].data[0] && s->picture[i].data[0] != s->next_picture.data[0] && s->picture[i].reference){
+                    fprintf(stderr, "releasing zombie picture\n");
+                    avctx->release_buffer(avctx, (AVVideoFrame*)&s->picture[i]);                
+                }
+            }
+        }
+    }
+
+    if(!s->encoding){        
+        /* find unused Picture */
+        for(i=0; i<MAX_PICTURE_COUNT; i++){
+            if(s->picture[i].data[0]==NULL) break;
+        }
+        assert(i<MAX_PICTURE_COUNT);
+    
+        pic= (AVVideoFrame*)&s->picture[i];
+        pic->reference= s->pict_type != B_TYPE;
+        pic->coded_picture_number= s->current_picture.coded_picture_number+1;
+        
+        r= avctx->get_buffer(avctx, pic);
+    
+        if(r<0 || (s->linesize && (s->linesize != pic->linesize[0] || s->uvlinesize != pic->linesize[1]))){
+            fprintf(stderr, "get_buffer() failed (stride changed), bye bye\n");
+            return -1;
+        }
+
+        s->linesize  = pic->linesize[0];
+        s->uvlinesize= pic->linesize[1];
+    
+        if(pic->qscale_table==NULL)
+            alloc_picture(s, (Picture*)pic);
+
+        s->current_picture= s->picture[i];
+    }
 
     s->hurry_up= s->avctx->hurry_up;
     s->error_resilience= avctx->error_resilience;
 
-    if(avctx->flags&CODEC_FLAG_DR1){
-        if(avctx->get_buffer_callback(avctx, s->width, s->height, s->pict_type) < 0){
-            fprintf(stderr, "get_buffer() failed\n");
-            return -1;
-        }
-
-        s->linesize  = avctx->dr_stride;
-        s->uvlinesize= avctx->dr_uvstride;
-        s->ip_buffer_count= avctx->dr_ip_buffer_count;
+    if (s->pict_type != B_TYPE) {
+        s->last_picture= s->next_picture;
+        s->next_picture= s->current_picture;
     }
-    avctx->dr_ip_buffer_count= s->ip_buffer_count;
-    
-    if (s->pict_type == B_TYPE) {
-        for(i=0;i<3;i++) {
-            if(avctx->flags&CODEC_FLAG_DR1)
-                s->aux_picture[i]= avctx->dr_buffer[i];
-            
-            //FIXME the following should never be needed, the decoder should drop b frames if no reference is available
-            if(s->next_picture[i]==NULL)
-                s->next_picture[i]= s->aux_picture[i];
-            if(s->last_picture[i]==NULL)
-                s->last_picture[i]= s->next_picture[i];
-
-            s->current_picture[i] = s->aux_picture[i];
-        }
-        s->avctx->display_qscale_table=
-        s->avctx->current_qscale_table= 
-        s->qscale_table= s->aux_qscale_table;
-    } else {
-        for(i=0;i<3;i++) {
-            /* swap next and last */
-            if(avctx->flags&CODEC_FLAG_DR1)
-                tmp= avctx->dr_buffer[i];
-            else
-                tmp = s->last_picture[i];
-
-            s->last_picture[i] = s->next_picture[i];
-            s->next_picture[i] = tmp;
-            s->current_picture[i] = tmp;
-
-            if(s->last_picture[i]==NULL)
-                s->last_picture[i]= s->next_picture[i];
-
-            s->last_dr_opaque= s->next_dr_opaque;
-            s->next_dr_opaque= avctx->dr_opaque_frame;
-
-            if(s->has_b_frames && s->last_dr_opaque && s->codec_id!=CODEC_ID_SVQ1)
-                avctx->dr_opaque_frame= s->last_dr_opaque;
-            else
-                avctx->dr_opaque_frame= s->next_dr_opaque;
-        }
-        s->avctx->current_qscale_table= s->qscale_table      = s->last_qscale_table;
-        s->avctx->display_qscale_table= s->last_qscale_table = s->next_qscale_table;
-        s->next_qscale_table= s->qscale_table;
-    }
+   
     /* set dequantizer, we cant do it during init as it might change for mpeg4
        and we cant do it in the header decode as init isnt called for mpeg4 there yet */
     if(s->out_format == FMT_H263){
@@ -893,14 +853,15 @@
 /* generic function for encode/decode called after a frame has been coded/decoded */
 void MPV_frame_end(MpegEncContext *s)
 {
-    s->avctx->key_frame   = (s->pict_type == I_TYPE);
-    s->avctx->pict_type   = s->pict_type;
+    int i;
 
     /* draw edge for correct motion prediction if outside */
-    if (s->pict_type != B_TYPE && !s->intra_only && !(s->flags&CODEC_FLAG_EMU_EDGE)) {
-        draw_edges(s->current_picture[0], s->linesize  , s->h_edge_pos   , s->v_edge_pos   , EDGE_WIDTH  );
-        draw_edges(s->current_picture[1], s->uvlinesize, s->h_edge_pos>>1, s->v_edge_pos>>1, EDGE_WIDTH/2);
-        draw_edges(s->current_picture[2], s->uvlinesize, s->h_edge_pos>>1, s->v_edge_pos>>1, EDGE_WIDTH/2);
+    if(s->codec_id!=CODEC_ID_SVQ1){
+        if (s->pict_type != B_TYPE && !s->intra_only && !(s->flags&CODEC_FLAG_EMU_EDGE)) {
+            draw_edges(s->current_picture.data[0], s->linesize  , s->h_edge_pos   , s->v_edge_pos   , EDGE_WIDTH  );
+            draw_edges(s->current_picture.data[1], s->uvlinesize, s->h_edge_pos>>1, s->v_edge_pos>>1, EDGE_WIDTH/2);
+            draw_edges(s->current_picture.data[2], s->uvlinesize, s->h_edge_pos>>1, s->v_edge_pos>>1, EDGE_WIDTH/2);
+        }
     }
     emms_c();
     
@@ -910,84 +871,154 @@
         s->num_available_buffers++;
         if(s->num_available_buffers>2) s->num_available_buffers= 2;
     }
-}
-
-/* reorder input for encoding */
-void reorder_input(MpegEncContext *s, AVPicture *pict)
-{
-    int i, j, index;
-            
-    if(s->max_b_frames > FF_MAX_B_FRAMES) s->max_b_frames= FF_MAX_B_FRAMES;
-
-//        delay= s->max_b_frames+1; (or 0 if no b frames cuz decoder diff)
-
-    for(j=0; j<REORDER_BUFFER_SIZE-1; j++){
-        s->coded_order[j]= s->coded_order[j+1];
+    
+    s->current_picture.quality= s->qscale; //FIXME get average of qscale_table
+    s->current_picture.pict_type= s->pict_type;
+    s->current_picture.key_frame= s->pict_type == I_TYPE;
+    
+    /* copy back current_picture variables */
+    for(i=0; i<MAX_PICTURE_COUNT; i++){
+        if(s->picture[i].data[0] == s->current_picture.data[0]){
+            s->picture[i]= s->current_picture;
+            break;
+        }    
+    }
+    assert(i<MAX_PICTURE_COUNT);
+
+    /* release non refernce frames */
+    for(i=0; i<MAX_PICTURE_COUNT; i++){
+        if(s->picture[i].data[0] && !s->picture[i].reference)
+            s->avctx->release_buffer(s->avctx, (AVVideoFrame*)&s->picture[i]);
     }
-    s->coded_order[j].picture[0]= s->coded_order[j].picture[1]= s->coded_order[j].picture[2]= NULL; //catch uninitalized buffers
-    s->coded_order[j].pict_type=0;
-
-    switch(s->input_pict_type){
-    default: 
-    case I_TYPE:
-    case S_TYPE:
-    case P_TYPE:
-        index= s->max_b_frames - s->b_frames_since_non_b;
-        s->b_frames_since_non_b=0;
-        break;            
-    case B_TYPE:
-        index= s->max_b_frames + 1;
-        s->b_frames_since_non_b++;
-        break;          
+}
+
+static int load_input_picture(MpegEncContext *s, AVVideoFrame *pic_arg){
+    AVVideoFrame *pic;
+    int i,r;
+    const int encoding_delay= s->max_b_frames;
+
+    /* find unused Picture */
+    for(i=0; i<MAX_PICTURE_COUNT; i++){
+        if(s->picture[i].data[0]==NULL) break;
+    }
+    assert(i<MAX_PICTURE_COUNT);
+        
+    pic= (AVVideoFrame*)&s->picture[i];
+    pic->reference= 1;
+    
+//    assert(avctx->get_buffer == default_get_buffer || avctx->get_buffer==NULL);
+    r= s->avctx->get_buffer(s->avctx, pic);
+
+    if(r<0 || (s->linesize && (s->linesize != pic->linesize[0] || s->uvlinesize != pic->linesize[1]))){
+        fprintf(stderr, "get_buffer() failed (stride changed), bye bye\n");
+        return -1;
     }
-//printf("index:%d type:%d strides: %d %d\n", index, s->input_pict_type, pict->linesize[0], s->linesize);
-    if(   (index==0 || (s->flags&CODEC_FLAG_INPUT_PRESERVED))
-       && pict->linesize[0] == s->linesize
-       && pict->linesize[1] == s->uvlinesize
-       && pict->linesize[2] == s->uvlinesize){
-//printf("ptr\n");
-        for(i=0; i<3; i++){
-            s->coded_order[index].picture[i]= pict->data[i];
-        }
+    
+    assert(s->linesize==0   || s->linesize  ==pic->linesize[0]);
+    assert(s->uvlinesize==0 || s->uvlinesize==pic->linesize[1]);
+    assert(pic->linesize[1] == pic->linesize[2]);
+    s->linesize  = pic->linesize[0];
+    s->uvlinesize= pic->linesize[1];
+    
+    if(pic->qscale_table==NULL)
+        alloc_picture(s, (Picture*)pic);
+
+//    assert(s->input_picture[0]==NULL || s->input_picture[0]->data[0]==NULL);
+    
+    if(s->input_picture[encoding_delay])
+        pic->display_picture_number= s->input_picture[encoding_delay]->display_picture_number + 1;
+//printf("dpn2:%d\n", pic->display_picture_number);
+
+    /* shift buffer entries */
+    for(i=1; i<MAX_PICTURE_COUNT /*s->encoding_delay+1*/; i++)
+        s->input_picture[i-1]= s->input_picture[i];
+        
+    s->input_picture[encoding_delay]= (Picture*)pic;
+    pic->pict_type= pic_arg->pict_type;
+    pic->quality= pic_arg->quality;
+    
+    if(   pic->data[0] == pic_arg->data[0] 
+       && pic->data[1] == pic_arg->data[1]
+       && pic->data[2] == pic_arg->data[2]){
+       // empty
     }else{
-//printf("copy\n");
+        int h_chroma_shift, v_chroma_shift;
+        
+        avcodec_get_chroma_sub_sample(s->avctx->pix_fmt, &h_chroma_shift, &v_chroma_shift);
+        
         for(i=0; i<3; i++){
-            uint8_t *src = pict->data[i];
-            uint8_t *dest;
-            int src_wrap = pict->linesize[i];
-            int dest_wrap = s->linesize;
-            int w = s->width;
-            int h = s->height;
-
-            if(index==0) dest= s->last_picture[i]+16; //is current_picture indeed but the switch hapens after reordering
-            else         dest= s->picture_buffer[s->picture_buffer_index][i];
-
-            if (i >= 1) {
-                dest_wrap >>= 1;
-                w >>= 1;
-                h >>= 1;
-            }
-
-            s->coded_order[index].picture[i]= dest;
-            for(j=0;j<h;j++) {
-                memcpy(dest, src, w);
-                dest += dest_wrap;
-                src += src_wrap;
+            int src_stride= pic_arg->linesize[i];
+            int dst_stride= i ? s->uvlinesize : s->linesize;
+            int h_shift= i ? h_chroma_shift : 0;
+            int v_shift= i ? v_chroma_shift : 0;
+            int w= s->width >>h_shift;
+            int h= s->height>>v_shift;
+            uint8_t *src= pic_arg->data[i];
+            uint8_t *dst= pic->data[i] + 16;
+            
+            if(src_stride==dst_stride)
+                memcpy(dst, src, src_stride*h);
+            else{
+                while(h--){
+                    memcpy(dst, src, w);
+                    dst += dst_stride;
+                    src += src_stride;
+                }
             }
         }
-        if(index!=0){
-            s->picture_buffer_index++;
-            if(s->picture_buffer_index >= REORDER_BUFFER_SIZE) s->picture_buffer_index=0;
+    }
+
+    return 0;
+}
+
+static void select_input_picture(MpegEncContext *s){
+    int i;
+    const int encoding_delay= s->max_b_frames;
+    int coded_pic_num=0;    
+
+    if(s->reordered_input_picture[0])
+        coded_pic_num= s->reordered_input_picture[0]->coded_picture_number + 1;
+//printf("cpn:%d\n", coded_pic_num);
+    for(i=1; i<MAX_PICTURE_COUNT; i++)
+        s->reordered_input_picture[i-1]= s->reordered_input_picture[i];
+    s->reordered_input_picture[MAX_PICTURE_COUNT-1]= NULL;
+
+    /* set next picture types & ordering */
+    if(s->reordered_input_picture[0]==NULL && s->input_picture[0]){
+        if(/*s->picture_in_gop_number >= s->gop_size ||*/ s->next_picture.data[0]==NULL || s->intra_only){
+            s->reordered_input_picture[0]= s->input_picture[0];
+            s->reordered_input_picture[0]->pict_type= I_TYPE;
+            s->reordered_input_picture[0]->coded_picture_number= coded_pic_num;
+        }else{
+            s->reordered_input_picture[0]= s->input_picture[s->max_b_frames];
+            if(s->picture_in_gop_number + s->max_b_frames >= s->gop_size)
+                s->reordered_input_picture[0]->pict_type= I_TYPE;
+            else
+                s->reordered_input_picture[0]->pict_type= P_TYPE;
+            s->reordered_input_picture[0]->coded_picture_number= coded_pic_num;
+            for(i=0; i<s->max_b_frames; i++){
+                coded_pic_num++;
+                s->reordered_input_picture[i+1]= s->input_picture[i];
+                s->reordered_input_picture[i+1]->pict_type= B_TYPE;
+                s->reordered_input_picture[i+1]->coded_picture_number= coded_pic_num;
+            }
         }
     }
-    s->coded_order[index].pict_type = s->input_pict_type;
-    s->coded_order[index].qscale    = s->input_qscale;
-    s->coded_order[index].force_type= s->force_input_type;
-    s->coded_order[index].picture_in_gop_number= s->input_picture_in_gop_number;
-    s->coded_order[index].picture_number= s->input_picture_number;
-
-    for(i=0; i<3; i++){
-        s->new_picture[i]= s->coded_order[0].picture[i];
+    
+    if(s->reordered_input_picture[0]){
+        if(s->reordered_input_picture[0]->pict_type==B_TYPE){
+            s->reordered_input_picture[0]->reference=0;
+        }
+        s->current_picture= *s->reordered_input_picture[0];
+        s->new_picture= s->current_picture;
+        s->new_picture.data[0]+=16;
+        s->new_picture.data[1]+=16;
+        s->new_picture.data[2]+=16;
+    
+        s->picture_number= s->new_picture.display_picture_number;
+//printf("dpn:%d\n", s->picture_number);
+    }else{
+       memset(&s->new_picture, 0, sizeof(Picture));
     }
 }
 
@@ -995,52 +1026,26 @@
                        unsigned char *buf, int buf_size, void *data)
 {
     MpegEncContext *s = avctx->priv_data;
-    AVPicture *pict = data;
-
-    s->input_qscale = avctx->quality;
+    AVVideoFrame *pic_arg = data;
 
     init_put_bits(&s->pb, buf, buf_size, NULL, NULL);
 
-    if(avctx->force_type){
-        s->input_pict_type=
-        s->force_input_type= avctx->force_type;
-    }else if(s->flags&CODEC_FLAG_PASS2){
-        s->input_pict_type=
-        s->force_input_type= s->rc_context.entry[s->input_picture_number].new_pict_type;
-    }else{
-        s->force_input_type=0;
-        if (!s->intra_only) {
-            /* first picture of GOP is intra */
-            if (s->input_picture_in_gop_number % s->gop_size==0){
-                s->input_pict_type = I_TYPE;
-            }else if(s->max_b_frames==0){
-                s->input_pict_type = P_TYPE;
-            }else{
-                if(s->b_frames_since_non_b < s->max_b_frames) //FIXME more IQ
-                    s->input_pict_type = B_TYPE;
-                else
-                    s->input_pict_type = P_TYPE;
-            }
-        } else {
-            s->input_pict_type = I_TYPE;
-        }
-    }
-
-    if(s->input_pict_type==I_TYPE)
-        s->input_picture_in_gop_number=0;
+    s->picture_in_gop_number++;
+
+    load_input_picture(s, pic_arg);
     
-    reorder_input(s, pict);
+    select_input_picture(s);
     
     /* output? */
-    if(s->coded_order[0].picture[0]){
-
-        s->pict_type= s->coded_order[0].pict_type;
-        if (s->fixed_qscale) /* the ratecontrol needs the last qscale so we dont touch it for CBR */
-            s->qscale= s->coded_order[0].qscale;
-        s->force_type= s->coded_order[0].force_type;
-        s->picture_in_gop_number= s->coded_order[0].picture_in_gop_number;
-        s->picture_number= s->coded_order[0].picture_number;
-
+    if(s->new_picture.data[0]){
+
+        s->pict_type= s->new_picture.pict_type;
+        if (s->fixed_qscale){ /* the ratecontrol needs the last qscale so we dont touch it for CBR */
+            s->qscale= (int)(s->new_picture.quality+0.5);
+            assert(s->qscale);
+        }
+//emms_c();
+//printf("qs:%f %f %d\n", s->new_picture.quality, s->current_picture.quality, s->qscale);
         MPV_frame_start(s, avctx);
 
         encode_picture(s, s->picture_number);
@@ -1059,17 +1064,12 @@
 
         if (s->out_format == FMT_MJPEG)
             mjpeg_picture_trailer(s);
-
-        if(!s->fixed_qscale)
-            avctx->quality = s->qscale;
         
         if(s->flags&CODEC_FLAG_PASS1)
             ff_write_pass1_stats(s);
-    
     }
 
     s->input_picture_number++;
-    s->input_picture_in_gop_number++;
 
     flush_put_bits(&s->pb);
     s->frame_bits  = (pbBufPtr(&s->pb) - s->pb.buf) * 8;
@@ -1088,14 +1088,16 @@
     fprintf(f, "%7d, %7d, %2.4f\n", pbBufPtr(&s->pb) - s->pb.buf, s->qscale, avctx->psnr_y);
 }
 #endif
-
+#if 0
     if (avctx->get_psnr) {
         /* At this point pict->data should have the original frame   */
         /* an s->current_picture should have the coded/decoded frame */
-        get_psnr(pict->data, s->current_picture,
+        get_psnr(pict->data, s->current_picture.data,
                  pict->linesize, s->linesize, avctx);
 //        printf("%f\n", avctx->psnr_y);
     }
+#endif
+
     return pbBufPtr(&s->pb) - s->pb.buf;
 }
 
@@ -1757,7 +1759,7 @@
     mb_x = s->mb_x;
     mb_y = s->mb_y;
 
-    s->qscale_table[mb_xy]= s->qscale;
+    s->current_picture.qscale_table[mb_xy]= s->qscale;
 
     /* update DC predictors for P macroblocks */
     if (!s->mb_intra) {
@@ -1823,33 +1825,47 @@
         op_pixels_func (*op_pix)[4];
         qpel_mc_func (*op_qpix)[16];
 
-        /* avoid copy if macroblock skipped in last frame too 
-           dont touch it for B-frames as they need the skip info from the next p-frame */
+        /* avoid copy if macroblock skipped in last frame too */
         if (s->pict_type != B_TYPE) {
+            s->current_picture.mbskip_table[mb_xy]= s->mb_skiped;
+        }
+
+        /* skip only during decoding as we might trash the buffers during encoding a bit */
+        if(!s->encoding){
             UINT8 *mbskip_ptr = &s->mbskip_table[mb_xy];
+            const int age= s->current_picture.age;
+
+            assert(age);
+
             if (s->mb_skiped) {
-                s->mb_skiped = 0;
-
+                s->mb_skiped= 0;
+                assert(s->pict_type!=I_TYPE);
+ 
                 (*mbskip_ptr) ++; /* indicate that this time we skiped it */
                 if(*mbskip_ptr >99) *mbskip_ptr= 99;
 
-                /* if previous was skipped too, then nothing to do ! 
-                   skip only during decoding as we might trash the buffers during encoding a bit */
-                if (*mbskip_ptr >= s->ip_buffer_count  && !s->encoding) 
-                    return;
+                /* if previous was skipped too, then nothing to do !  */
+                if (*mbskip_ptr >= age){
+//if(s->pict_type!=B_TYPE && s->mb_x==0) printf("\n");
+//if(s->pict_type!=B_TYPE) printf("%d%d ", *mbskip_ptr, age);
+                    if(s->pict_type!=B_TYPE) return;
+                    if(s->avctx->draw_horiz_band==NULL && *mbskip_ptr > age) return; 
+                    /* we dont draw complete frames here so we cant skip */
+                }
             } else {
                 *mbskip_ptr = 0; /* not skipped */
             }
-        }
+        }else
+            s->mb_skiped= 0;
 
         if(s->pict_type==B_TYPE && s->avctx->draw_horiz_band){
-            dest_y = s->current_picture [0] + mb_x * 16;
-            dest_cb = s->current_picture[1] + mb_x * 8;
-            dest_cr = s->current_picture[2] + mb_x * 8;
+            dest_y  = s->current_picture.data[0] + mb_x * 16;
+            dest_cb = s->current_picture.data[1] + mb_x * 8;
+            dest_cr = s->current_picture.data[2] + mb_x * 8;
         }else{
-            dest_y = s->current_picture [0] + (mb_y * 16* s->linesize  ) + mb_x * 16;
-            dest_cb = s->current_picture[1] + (mb_y * 8 * s->uvlinesize) + mb_x * 8;
-            dest_cr = s->current_picture[2] + (mb_y * 8 * s->uvlinesize) + mb_x * 8;
+            dest_y  = s->current_picture.data[0] + (mb_y * 16* s->linesize  ) + mb_x * 16;
+            dest_cb = s->current_picture.data[1] + (mb_y * 8 * s->uvlinesize) + mb_x * 8;
+            dest_cr = s->current_picture.data[2] + (mb_y * 8 * s->uvlinesize) + mb_x * 8;
         }
 
         if (s->interlaced_dct) {
@@ -1873,12 +1889,12 @@
                 }
 
                 if (s->mv_dir & MV_DIR_FORWARD) {
-                    MPV_motion(s, dest_y, dest_cb, dest_cr, 0, s->last_picture, op_pix, op_qpix);
+                    MPV_motion(s, dest_y, dest_cb, dest_cr, 0, s->last_picture.data, op_pix, op_qpix);
 		    op_pix = s->dsp.avg_pixels_tab;
                     op_qpix= s->dsp.avg_qpel_pixels_tab;
                 }
                 if (s->mv_dir & MV_DIR_BACKWARD) {
-                    MPV_motion(s, dest_y, dest_cb, dest_cr, 1, s->next_picture, op_pix, op_qpix);
+                    MPV_motion(s, dest_y, dest_cb, dest_cr, 1, s->next_picture.data, op_pix, op_qpix);
                 }
             }
 
@@ -2154,13 +2170,13 @@
             offset = y * s->linesize;
 
         if(s->pict_type==B_TYPE || (!s->has_b_frames)){
-            src_ptr[0] = s->current_picture[0] + offset;
-            src_ptr[1] = s->current_picture[1] + (offset >> 2);
-            src_ptr[2] = s->current_picture[2] + (offset >> 2);
+            src_ptr[0] = s->current_picture.data[0] + offset;
+            src_ptr[1] = s->current_picture.data[1] + (offset >> 2);
+            src_ptr[2] = s->current_picture.data[2] + (offset >> 2);
         } else {
-            src_ptr[0] = s->last_picture[0] + offset;
-            src_ptr[1] = s->last_picture[1] + (offset >> 2);
-            src_ptr[2] = s->last_picture[2] + (offset >> 2);
+            src_ptr[0] = s->last_picture.data[0] + offset;
+            src_ptr[1] = s->last_picture.data[1] + (offset >> 2);
+            src_ptr[2] = s->last_picture.data[2] + (offset >> 2);
         }
         emms_c();
 
@@ -2180,7 +2196,7 @@
     for(i=0; i<6; i++) skip_dct[i]=0;
     
     if(s->adaptive_quant){
-        s->dquant= s->qscale_table[mb_x + mb_y*s->mb_width] - s->qscale;
+        s->dquant= s->current_picture.qscale_table[mb_x + mb_y*s->mb_width] - s->qscale;
 
         if(s->out_format==FMT_H263){
             if     (s->dquant> 2) s->dquant= 2;
@@ -2206,7 +2222,7 @@
         int emu=0;
 
         wrap_y = s->linesize;
-        ptr = s->new_picture[0] + (mb_y * 16 * wrap_y) + mb_x * 16;
+        ptr = s->new_picture.data[0] + (mb_y * 16 * wrap_y) + mb_x * 16;
 
         if(mb_x*16+16 > s->width || mb_y*16+16 > s->height){
             emulated_edge_mc(s, ptr, wrap_y, 16, 16, mb_x*16, mb_y*16, s->width, s->height);
@@ -2239,14 +2255,14 @@
             skip_dct[5]= 1;
         }else{
             int wrap_c = s->uvlinesize;
-            ptr = s->new_picture[1] + (mb_y * 8 * wrap_c) + mb_x * 8;
+            ptr = s->new_picture.data[1] + (mb_y * 8 * wrap_c) + mb_x * 8;
             if(emu){
                 emulated_edge_mc(s, ptr, wrap_c, 8, 8, mb_x*8, mb_y*8, s->width>>1, s->height>>1);
                 ptr= s->edge_emu_buffer;
             }
 	    s->dsp.get_pixels(s->block[4], ptr, wrap_c);
 
-            ptr = s->new_picture[2] + (mb_y * 8 * wrap_c) + mb_x * 8;
+            ptr = s->new_picture.data[2] + (mb_y * 8 * wrap_c) + mb_x * 8;
             if(emu){
                 emulated_edge_mc(s, ptr, wrap_c, 8, 8, mb_x*8, mb_y*8, s->width>>1, s->height>>1);
                 ptr= s->edge_emu_buffer;
@@ -2261,14 +2277,14 @@
         int wrap_y, wrap_c;
         int emu=0;
 
-        dest_y  = s->current_picture[0] + (mb_y * 16 * s->linesize       ) + mb_x * 16;
-        dest_cb = s->current_picture[1] + (mb_y * 8  * (s->uvlinesize)) + mb_x * 8;
-        dest_cr = s->current_picture[2] + (mb_y * 8  * (s->uvlinesize)) + mb_x * 8;
+        dest_y  = s->current_picture.data[0] + (mb_y * 16 * s->linesize    ) + mb_x * 16;
+        dest_cb = s->current_picture.data[1] + (mb_y * 8  * (s->uvlinesize)) + mb_x * 8;
+        dest_cr = s->current_picture.data[2] + (mb_y * 8  * (s->uvlinesize)) + mb_x * 8;
         wrap_y = s->linesize;
         wrap_c = s->uvlinesize;
-        ptr_y  = s->new_picture[0] + (mb_y * 16 * wrap_y) + mb_x * 16;
-        ptr_cb = s->new_picture[1] + (mb_y * 8 * wrap_c) + mb_x * 8;
-        ptr_cr = s->new_picture[2] + (mb_y * 8 * wrap_c) + mb_x * 8;
+        ptr_y  = s->new_picture.data[0] + (mb_y * 16 * wrap_y) + mb_x * 16;
+        ptr_cb = s->new_picture.data[1] + (mb_y * 8 * wrap_c) + mb_x * 8;
+        ptr_cr = s->new_picture.data[2] + (mb_y * 8 * wrap_c) + mb_x * 8;
 
         if ((!s->no_rounding) || s->pict_type==B_TYPE){
 	    op_pix = s->dsp.put_pixels_tab;
@@ -2279,12 +2295,12 @@
         }
 
         if (s->mv_dir & MV_DIR_FORWARD) {
-            MPV_motion(s, dest_y, dest_cb, dest_cr, 0, s->last_picture, op_pix, op_qpix);
+            MPV_motion(s, dest_y, dest_cb, dest_cr, 0, s->last_picture.data, op_pix, op_qpix);
             op_pix = s->dsp.avg_pixels_tab;
             op_qpix= s->dsp.avg_qpel_pixels_tab;
         }
         if (s->mv_dir & MV_DIR_BACKWARD) {
-            MPV_motion(s, dest_y, dest_cb, dest_cr, 1, s->next_picture, op_pix, op_qpix);
+            MPV_motion(s, dest_y, dest_cb, dest_cr, 1, s->next_picture.data, op_pix, op_qpix);
         }
 
         if(mb_x*16+16 > s->width || mb_y*16+16 > s->height){
@@ -2330,9 +2346,8 @@
             }
             s->dsp.diff_pixels(s->block[5], ptr_cr, dest_cr, wrap_c);
         }
-
         /* pre quantization */         
-        if(s->mc_mb_var[s->mb_width*mb_y+ mb_x]<2*s->qscale*s->qscale){
+        if(s->current_picture.mc_mb_var[s->mb_width*mb_y+ mb_x]<2*s->qscale*s->qscale){
             //FIXME optimize
 	    if(s->dsp.pix_abs8x8(ptr_y               , dest_y               , wrap_y) < 20*s->qscale) skip_dct[0]= 1;
             if(s->dsp.pix_abs8x8(ptr_y            + 8, dest_y            + 8, wrap_y) < 20*s->qscale) skip_dct[1]= 1;
@@ -2557,8 +2572,8 @@
     s->block_wrap[5]= s->mb_width + 2;
     
     /* Reset the average MB variance */
-    s->mb_var_sum = 0;
-    s->mc_mb_var_sum = 0;
+    s->current_picture.mb_var_sum = 0;
+    s->current_picture.mc_mb_var_sum = 0;
 
     /* we need to initialize some time vars before we can encode b-frames */
     if (s->h263_pred && !s->h263_msmpeg4)
@@ -2604,15 +2619,15 @@
                 for(mb_x=0; mb_x < s->mb_width; mb_x++) {
                     int xx = mb_x * 16;
                     int yy = mb_y * 16;
-                    uint8_t *pix = s->new_picture[0] + (yy * s->linesize) + xx;
+                    uint8_t *pix = s->new_picture.data[0] + (yy * s->linesize) + xx;
                     int varc;
 		    int sum = s->dsp.pix_sum(pix, s->linesize);
     
 		    varc = (s->dsp.pix_norm1(pix, s->linesize) - (((unsigned)(sum*sum))>>8) + 500 + 128)>>8;
 
-                    s->mb_var [s->mb_width * mb_y + mb_x] = varc;
-                    s->mb_mean[s->mb_width * mb_y + mb_x] = (sum+128)>>8;
-                    s->mb_var_sum    += varc;
+                    s->current_picture.mb_var [s->mb_width * mb_y + mb_x] = varc;
+                    s->current_picture.mb_mean[s->mb_width * mb_y + mb_x] = (sum+128)>>8;
+                    s->current_picture.mb_var_sum    += varc;
                 }
             }
         }
@@ -2622,13 +2637,9 @@
     if(s->scene_change_score > 0 && s->pict_type == P_TYPE){
         s->pict_type= I_TYPE;
         memset(s->mb_type   , MB_TYPE_INTRA, sizeof(UINT8)*s->mb_width*s->mb_height);
-        if(s->max_b_frames==0){
-            s->input_pict_type= I_TYPE;
-            s->input_picture_in_gop_number=0;
-        }
-//printf("Scene change detected, encoding as I Frame %d %d\n", s->mb_var_sum, s->mc_mb_var_sum);
+//printf("Scene change detected, encoding as I Frame %d %d\n", s->current_picture.mb_var_sum, s->current_picture.mc_mb_var_sum);
     }
-    
+
     if(s->pict_type==P_TYPE || s->pict_type==S_TYPE) 
         s->f_code= ff_get_best_fcode(s, s->p_mv_table, MB_TYPE_INTER);
         ff_fix_long_p_mvs(s);
@@ -2643,7 +2654,7 @@
     }
     
     if (s->fixed_qscale) 
-        s->frame_qscale = s->avctx->quality;
+        s->frame_qscale = s->current_picture.quality;
     else
         s->frame_qscale = ff_rate_estimate_qscale(s);
 
@@ -2658,7 +2669,7 @@
             break;
         }
 
-        s->qscale= s->qscale_table[0];
+        s->qscale= s->current_picture.qscale_table[0];
     }else
         s->qscale= (int)(s->frame_qscale + 0.5);
         
@@ -2673,6 +2684,13 @@
         convert_matrix(s, s->q_intra_matrix, s->q_intra_matrix16, 
                        s->q_intra_matrix16_bias, s->intra_matrix, s->intra_quant_bias, 8, 8);
     }
+    
+    //FIXME var duplication
+    s->current_picture.key_frame= s->pict_type == I_TYPE;
+    s->current_picture.pict_type= s->pict_type;
+
+    if(s->current_picture.key_frame)
+        s->picture_in_gop_number=0;
 
     s->last_bits= get_bit_count(&s->pb);
     switch(s->out_format) {