]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/mpegvideo.c
nicer looking arrows for the motion vector vissualization
[ffmpeg] / libavcodec / mpegvideo.c
index 38d68689c18c3b3b4b3083ff5397d55003187705..25a1996b68de32287742ba357ba1ed7d82813ab0 100644 (file)
@@ -267,8 +267,6 @@ int DCT_common_init(MpegEncContext *s)
     ff_init_scantable(s->dsp.idct_permutation, &s->intra_h_scantable, ff_alternate_horizontal_scan);
     ff_init_scantable(s->dsp.idct_permutation, &s->intra_v_scantable, ff_alternate_vertical_scan);
 
-    s->picture_structure= PICT_FRAME;
-    
     return 0;
 }
 
@@ -342,15 +340,15 @@ static int alloc_picture(MpegEncContext *s, Picture *pic, int shared){
         pic->mb_type= pic->mb_type_base + s->mb_stride+1;
         if(s->out_format == FMT_H264){
             for(i=0; i<2; i++){
-                CHECKED_ALLOCZ(pic->motion_val_base[i], 2 * (b4_array_size+1)  * sizeof(int16_t))
-                pic->motion_val[i]= pic->motion_val_base[i]+1;
+                CHECKED_ALLOCZ(pic->motion_val_base[i], 2 * (b4_array_size+2)  * sizeof(int16_t))
+                pic->motion_val[i]= pic->motion_val_base[i]+2;
                 CHECKED_ALLOCZ(pic->ref_index[i] , b8_array_size * sizeof(uint8_t))
             }
             pic->motion_subsample_log2= 2;
         }else if(s->out_format == FMT_H263 || s->encoding || (s->avctx->debug&FF_DEBUG_MV) || (s->avctx->debug_mv)){
             for(i=0; i<2; i++){
-                CHECKED_ALLOCZ(pic->motion_val_base[i], 2 * (b8_array_size+1) * sizeof(int16_t)*2) //FIXME
-                pic->motion_val[i]= pic->motion_val_base[i]+1;
+                CHECKED_ALLOCZ(pic->motion_val_base[i], 2 * (b8_array_size+2) * sizeof(int16_t)*2) //FIXME
+                pic->motion_val[i]= pic->motion_val_base[i]+2;
             }
             pic->motion_subsample_log2= 3;
         }
@@ -424,7 +422,7 @@ static int init_duplicate_context(MpegEncContext *s, MpegEncContext *base){
             CHECKED_ALLOCZ(s->dct_error_sum, 2 * 64 * sizeof(int))
         }
     }   
-    CHECKED_ALLOCZ(s->blocks, 64*6*2 * sizeof(DCTELEM))
+    CHECKED_ALLOCZ(s->blocks, 64*12*2 * sizeof(DCTELEM))
     s->block= s->blocks[0];
 
     for(i=0;i<12;i++){
@@ -504,7 +502,68 @@ static void update_duplicate_context_after_me(MpegEncContext *dst, MpegEncContex
 #undef COPY
 }
 
-/* init common structure for both encoder and decoder */
+/**
+ * sets the given MpegEncContext to common defaults (same for encoding and decoding).
+ * the changed fields will not depend upon the prior state of the MpegEncContext.
+ */
+static void MPV_common_defaults(MpegEncContext *s){
+    s->y_dc_scale_table=
+    s->c_dc_scale_table= ff_mpeg1_dc_scale_table;
+    s->chroma_qscale_table= ff_default_chroma_qscale_table;
+    s->progressive_frame= 1;
+    s->progressive_sequence= 1;
+    s->picture_structure= PICT_FRAME;
+
+    s->coded_picture_number = 0;
+    s->picture_number = 0;
+    s->input_picture_number = 0;
+
+    s->picture_in_gop_number = 0;
+
+    s->f_code = 1;
+    s->b_code = 1;
+}
+
+/**
+ * sets the given MpegEncContext to defaults for decoding.
+ * the changed fields will not depend upon the prior state of the MpegEncContext.
+ */
+void MPV_decode_defaults(MpegEncContext *s){
+    MPV_common_defaults(s);
+}
+
+/**
+ * sets the given MpegEncContext to defaults for encoding.
+ * the changed fields will not depend upon the prior state of the MpegEncContext.
+ */
+
+#ifdef CONFIG_ENCODERS
+void MPV_encode_defaults(MpegEncContext *s){
+    static int done=0;
+    
+    MPV_common_defaults(s);
+    
+    if(!done){
+        int i;
+        done=1;
+
+        default_mv_penalty= av_mallocz( sizeof(uint8_t)*(MAX_FCODE+1)*(2*MAX_MV+1) );
+        memset(default_mv_penalty, 0, sizeof(uint8_t)*(MAX_FCODE+1)*(2*MAX_MV+1));
+        memset(default_fcode_tab , 0, sizeof(uint8_t)*(2*MAX_MV+1));
+
+        for(i=-16; i<16; i++){
+            default_fcode_tab[i + MAX_MV]= 1;
+        }
+    }
+    s->me.mv_penalty= default_mv_penalty;
+    s->fcode_tab= default_fcode_tab;
+}
+#endif //CONFIG_ENCODERS
+
+/** 
+ * init common structure for both encoder and decoder.
+ * this assumes that some variables like width/height are already set
+ */
 int MPV_common_init(MpegEncContext *s)
 {
     int y_size, c_size, yc_size, i, mb_array_size, mv_table_size, x, y;
@@ -535,19 +594,11 @@ int MPV_common_init(MpegEncContext *s)
     s->block_wrap[3]= s->mb_width*2 + 2;
     s->block_wrap[4]=
     s->block_wrap[5]= s->mb_width + 2;
-
-    s->y_dc_scale_table=
-    s->c_dc_scale_table= ff_mpeg1_dc_scale_table;
-    s->chroma_qscale_table= ff_default_chroma_qscale_table;
-    if (!s->encoding)
-        s->progressive_sequence= 1;
-    s->progressive_frame= 1;
-    s->coded_picture_number = 0;
-
     y_size = (2 * s->mb_width + 2) * (2 * s->mb_height + 2);
     c_size = (s->mb_width + 2) * (s->mb_height + 2);
     yc_size = y_size + 2 * c_size;
-
+    
     /* convert fourcc to upper case */
     s->avctx->codec_tag=   toupper( s->avctx->codec_tag     &0xFF)          
                         + (toupper((s->avctx->codec_tag>>8 )&0xFF)<<8 )
@@ -656,9 +707,6 @@ int MPV_common_init(MpegEncContext *s)
     CHECKED_ALLOCZ(s->mbintra_table, mb_array_size);
     memset(s->mbintra_table, 1, mb_array_size);
     
-    /* default structure is frame */
-    s->picture_structure = PICT_FRAME;
-    
     /* init macroblock skip table */
     CHECKED_ALLOCZ(s->mbskip_table, mb_array_size+2);
     //Note the +1 is for a quicker mpeg4 slice_end detection
@@ -767,9 +815,9 @@ void MPV_common_end(MpegEncContext *s)
     s->last_picture_ptr=
     s->next_picture_ptr=
     s->current_picture_ptr= NULL;
+
     for(i=0; i<3; i++)
-        if (s->visualization_buffer[i])
-            av_free(s->visualization_buffer[i]);
+        av_freep(&s->visualization_buffer[i]);
 }
 
 #ifdef CONFIG_ENCODERS
@@ -780,6 +828,8 @@ int MPV_encode_init(AVCodecContext *avctx)
     MpegEncContext *s = avctx->priv_data;
     int i, dummy;
     int chroma_h_shift, chroma_v_shift;
+    
+    MPV_encode_defaults(s);
 
     avctx->pix_fmt = PIX_FMT_YUV420P; // FIXME
 
@@ -835,8 +885,15 @@ int MPV_encode_init(AVCodecContext *avctx)
 
     if(avctx->rc_min_rate && avctx->rc_max_rate != avctx->rc_min_rate){
         av_log(avctx, AV_LOG_INFO, "Warning min_rate > 0 but min_rate != max_rate isnt recommanded!\n");
-    }    
+    }
+    
+    if(   s->avctx->rc_max_rate && s->avctx->rc_min_rate == s->avctx->rc_max_rate 
+       && (s->codec_id == CODEC_ID_MPEG1VIDEO || s->codec_id == CODEC_ID_MPEG2VIDEO)
+       && 90000LL * (avctx->rc_buffer_size-1) > s->avctx->rc_max_rate*0xFFFFLL){
         
+        av_log(avctx, AV_LOG_INFO, "Warning vbv_delay will be set to 0xFFFF (=VBR) as the specified vbv buffer is too large for the given bitrate!\n");
+    }
+       
     if((s->flags & CODEC_FLAG_4MV) && s->codec_id != CODEC_ID_MPEG4 
        && s->codec_id != CODEC_ID_H263 && s->codec_id != CODEC_ID_H263P && s->codec_id != CODEC_ID_FLV1){
         av_log(avctx, AV_LOG_ERROR, "4MV not supported by codec\n");
@@ -1063,28 +1120,6 @@ int MPV_encode_init(AVCodecContext *avctx)
         return -1;
     }
 
-    { /* set up some save defaults, some codecs might override them later */
-        static int done=0;
-        if(!done){
-            int i;
-            done=1;
-
-            default_mv_penalty= av_mallocz( sizeof(uint8_t)*(MAX_FCODE+1)*(2*MAX_MV+1) );
-            memset(default_mv_penalty, 0, sizeof(uint8_t)*(MAX_FCODE+1)*(2*MAX_MV+1));
-            memset(default_fcode_tab , 0, sizeof(uint8_t)*(2*MAX_MV+1));
-
-            for(i=-16; i<16; i++){
-                default_fcode_tab[i + MAX_MV]= 1;
-            }
-        }
-    }
-    s->me.mv_penalty= default_mv_penalty;
-    s->fcode_tab= default_fcode_tab;
-    /* dont use mv_penalty table for crap MV as it would be confused */
-    //FIXME remove after fixing / removing old ME
-    if (s->me_method < ME_EPZS) s->me.mv_penalty = default_mv_penalty;
-
     s->encoding = 1;
 
     /* init */
@@ -1112,7 +1147,7 @@ int MPV_encode_init(AVCodecContext *avctx)
         ff_mpeg1_encode_init(s);
 #endif
 
-    /* init default q matrix */
+    /* init q matrix */
     for(i=0;i<64;i++) {
         int j= s->dsp.idct_permutation[i];
 #ifdef CONFIG_RISKY
@@ -1145,14 +1180,7 @@ int MPV_encode_init(AVCodecContext *avctx)
 
     if(ff_rate_control_init(s) < 0)
         return -1;
-
-    s->picture_number = 0;
-    s->input_picture_number = 0;
-    s->picture_in_gop_number = 0;
-    /* motion detector init */
-    s->f_code = 1;
-    s->b_code = 1;
-
+    
     return 0;
 }
 
@@ -1458,7 +1486,7 @@ void MPV_frame_end(MpegEncContext *s)
  * @param color color of the arrow
  */
 static void draw_line(uint8_t *buf, int sx, int sy, int ex, int ey, int w, int h, int stride, int color){
-    int t, x, y, f;
+    int t, x, y, fr, f;
     
     sx= clip(sx, 0, w-1);
     sy= clip(sy, 0, h-1);
@@ -1476,8 +1504,10 @@ static void draw_line(uint8_t *buf, int sx, int sy, int ex, int ey, int w, int h
         ex-= sx;
         f= ((ey-sy)<<16)/ex;
         for(x= 0; x <= ex; x++){
-            y= ((x*f) + (1<<15))>>16;
-            buf[y*stride + x]+= color;
+            y = (x*f)>>16;
+            fr= (x*f)&0xFFFF;
+            buf[ y   *stride + x]+= (color*(0x10000-fr))>>16;
+            buf[(y+1)*stride + x]+= (color*         fr )>>16;
         }
     }else{
         if(sy > ey){
@@ -1489,8 +1519,10 @@ static void draw_line(uint8_t *buf, int sx, int sy, int ex, int ey, int w, int h
         if(ey) f= ((ex-sx)<<16)/ey;
         else   f= 0;
         for(y= 0; y <= ey; y++){
-            x= ((y*f) + (1<<15))>>16;
-            buf[y*stride + x]+= color;
+            x = (y*f)>>16;
+            fr= (y*f)&0xFFFF;
+            buf[y*stride + x  ]+= (color*(0x10000-fr))>>16;;
+            buf[y*stride + x+1]+= (color*         fr )>>16;;
         }
     }
 }
@@ -2094,7 +2126,8 @@ int MPV_encode_picture(AVCodecContext *avctx,
         }
 
         /* update mpeg1/2 vbv_delay for CBR */    
-        if(s->avctx->rc_max_rate && s->avctx->rc_min_rate == s->avctx->rc_max_rate){
+        if(s->avctx->rc_max_rate && s->avctx->rc_min_rate == s->avctx->rc_max_rate && s->out_format == FMT_MPEG1
+           && 90000LL * (avctx->rc_buffer_size-1) <= s->avctx->rc_max_rate*0xFFFFLL){
             int vbv_delay;
 
             assert(s->repeat_first_field==0);
@@ -2381,15 +2414,8 @@ static inline void mpeg_motion(MpegEncContext *s,
                                uint8_t **ref_picture, op_pixels_func (*pix_op)[4],
                                int motion_x, int motion_y, int h)
 {
-    uint8_t *ptr;
-    int dxy, offset, mx, my, src_x, src_y, height, v_edge_pos, uvlinesize;
-    int emu=0;
-    
-    if(bottom_field){ //FIXME use this for field pix too instead of the obnoxious hack which changes picture.data
-        dest_y += s->linesize;
-        dest_cb+= s->uvlinesize;
-        dest_cr+= s->uvlinesize;
-    }
+    uint8_t *ptr_y, *ptr_cb, *ptr_cr;
+    int dxy, uvdxy, mx, my, src_x, src_y, uvsrc_x, uvsrc_y, v_edge_pos, uvlinesize, linesize;
     
 #if 0    
 if(s->quarter_sample)
@@ -2399,65 +2425,72 @@ if(s->quarter_sample)
 }
 #endif
 
-    height = s->height >> field_based;
     v_edge_pos = s->v_edge_pos >> field_based;
+    linesize   = s->current_picture.linesize[0] << field_based;
     uvlinesize = s->current_picture.linesize[1] << field_based;
 
-    emu= hpel_motion(s, 
-                dest_y, ref_picture[0], field_based, field_select,
-                s->mb_x * 16, s->mb_y * (16 >> field_based),
-                s->width, height, s->current_picture.linesize[0] << field_based,
-                s->h_edge_pos, v_edge_pos,
-                16, h, pix_op[0],
-                motion_x, motion_y);
-
-
-    if(s->flags&CODEC_FLAG_GRAY) return;
+    dxy = ((motion_y & 1) << 1) | (motion_x & 1);
+    src_x = s->mb_x* 16               + (motion_x >> 1);
+    src_y = s->mb_y*(16>>field_based) + (motion_y >> 1);
 
     if (s->out_format == FMT_H263) {
-        dxy = 0;
-        if ((motion_x & 3) != 0)
-            dxy |= 1;
-        if ((motion_y & 3) != 0)
-            dxy |= 2;
-        mx = motion_x >> 2;
-        my = motion_y >> 2;
+        if((s->workaround_bugs & FF_BUG_HPEL_CHROMA) && field_based){
+            mx = (motion_x>>1)|(motion_x&1);
+            my = motion_y >>1;
+            uvdxy = ((my & 1) << 1) | (mx & 1);
+            uvsrc_x = s->mb_x* 8               + (mx >> 1);
+            uvsrc_y = s->mb_y*(8>>field_based) + (my >> 1);
+        }else{
+            uvdxy = dxy | (motion_y & 2) | ((motion_x & 2) >> 1);
+            uvsrc_x = src_x>>1;
+            uvsrc_y = src_y>>1;
+        }
     } else {
         mx = motion_x / 2;
         my = motion_y / 2;
-        dxy = ((my & 1) << 1) | (mx & 1);
-        mx >>= 1;
-        my >>= 1;
+        uvdxy = ((my & 1) << 1) | (mx & 1);
+        uvsrc_x = s->mb_x* 8               + (mx >> 1);
+        uvsrc_y = s->mb_y*(8>>field_based) + (my >> 1);
     }
-    
-    src_x = s->mb_x * 8 + mx;
-    src_y = s->mb_y * (8 >> field_based) + my;
-    src_x = clip(src_x, -8, s->width >> 1);
-    if (src_x == (s->width >> 1))
-        dxy &= ~1;
-    src_y = clip(src_y, -8, height >> 1);
-    if (src_y == (height >> 1))
-        dxy &= ~2;
-    offset = (src_y * uvlinesize) + src_x;
-    ptr = ref_picture[1] + offset;
-    if(emu){
-        ff_emulated_edge_mc(s->edge_emu_buffer, ptr, s->uvlinesize, 9, 9+field_based, 
-                         src_x, src_y<<field_based, s->h_edge_pos>>1, s->v_edge_pos>>1);
-        ptr= s->edge_emu_buffer;
+
+    ptr_y  = ref_picture[0] + src_y * linesize + src_x;
+    ptr_cb = ref_picture[1] + uvsrc_y * uvlinesize + uvsrc_x;
+    ptr_cr = ref_picture[2] + uvsrc_y * uvlinesize + uvsrc_x;
+
+    if(   (unsigned)src_x > s->h_edge_pos - (motion_x&1) - 16
+       || (unsigned)src_y >    v_edge_pos - (motion_y&1) - h){
+            ff_emulated_edge_mc(s->edge_emu_buffer, ptr_y, s->linesize, 17, 17+field_based,
+                             src_x, src_y<<field_based, s->h_edge_pos, s->v_edge_pos);
+            ptr_y = s->edge_emu_buffer;
+            if(!(s->flags&CODEC_FLAG_GRAY)){
+                uint8_t *uvbuf= s->edge_emu_buffer+18*s->linesize;
+                ff_emulated_edge_mc(uvbuf  , ptr_cb, s->uvlinesize, 9, 9+field_based, 
+                                 uvsrc_x, uvsrc_y<<field_based, s->h_edge_pos>>1, s->v_edge_pos>>1);
+                ff_emulated_edge_mc(uvbuf+16, ptr_cr, s->uvlinesize, 9, 9+field_based, 
+                                 uvsrc_x, uvsrc_y<<field_based, s->h_edge_pos>>1, s->v_edge_pos>>1);
+                ptr_cb= uvbuf;
+                ptr_cr= uvbuf+16;
+            }
     }
-    if(field_select)
-        ptr+= s->uvlinesize;
-    pix_op[1][dxy](dest_cb, ptr, uvlinesize, h >> 1);
 
-    ptr = ref_picture[2] + offset;
-    if(emu){
-        ff_emulated_edge_mc(s->edge_emu_buffer, ptr, s->uvlinesize, 9, 9+field_based, 
-                         src_x, src_y<<field_based, s->h_edge_pos>>1, s->v_edge_pos>>1);
-        ptr= s->edge_emu_buffer;
+    if(bottom_field){ //FIXME use this for field pix too instead of the obnoxious hack which changes picture.data
+        dest_y += s->linesize;
+        dest_cb+= s->uvlinesize;
+        dest_cr+= s->uvlinesize;
+    }
+
+    if(field_select){
+        ptr_y += s->linesize;
+        ptr_cb+= s->uvlinesize;
+        ptr_cr+= s->uvlinesize;
+    }
+
+    pix_op[0][dxy](dest_y, ptr_y, linesize, h);
+    
+    if(!(s->flags&CODEC_FLAG_GRAY)){
+        pix_op[1][uvdxy](dest_cb, ptr_cb, uvlinesize, h >> 1);
+        pix_op[1][uvdxy](dest_cr, ptr_cr, uvlinesize, h >> 1);
     }
-    if(field_select)
-        ptr+= s->uvlinesize;
-    pix_op[1][dxy](dest_cr, ptr, uvlinesize, h >> 1);
 }
 //FIXME move to dsputil, avg variant, 16x16 version
 static inline void put_obmc(uint8_t *dst, uint8_t *src[5], int stride){
@@ -2548,54 +2581,17 @@ static inline void qpel_motion(MpegEncContext *s,
                                qpel_mc_func (*qpix_op)[16],
                                int motion_x, int motion_y, int h)
 {
-    uint8_t *ptr;
-    int dxy, offset, mx, my, src_x, src_y, height, v_edge_pos, linesize, uvlinesize;
-    int emu=0;
-
-    if(bottom_field){
-        dest_y += s->linesize;
-        dest_cb+= s->uvlinesize;
-        dest_cr+= s->uvlinesize;
-    }
+    uint8_t *ptr_y, *ptr_cb, *ptr_cr;
+    int dxy, uvdxy, mx, my, src_x, src_y, uvsrc_x, uvsrc_y, v_edge_pos, linesize, uvlinesize;
 
     dxy = ((motion_y & 3) << 2) | (motion_x & 3);
-    src_x = s->mb_x * 16 + (motion_x >> 2);
+    src_x = s->mb_x *  16                 + (motion_x >> 2);
     src_y = s->mb_y * (16 >> field_based) + (motion_y >> 2);
 
-    height = s->height >> field_based;
     v_edge_pos = s->v_edge_pos >> field_based;
-    src_x = clip(src_x, -16, s->width);
-    if (src_x == s->width)
-        dxy &= ~3;
-    src_y = clip(src_y, -16, height);
-    if (src_y == height)
-        dxy &= ~12;
     linesize = s->linesize << field_based;
     uvlinesize = s->uvlinesize << field_based;
-    ptr = ref_picture[0] + (src_y * linesize) + src_x;
     
-    if(s->flags&CODEC_FLAG_EMU_EDGE){
-        if(   (unsigned)src_x > s->h_edge_pos - (motion_x&3) - 16 
-           || (unsigned)src_y >    v_edge_pos - (motion_y&3) - h  ){
-            ff_emulated_edge_mc(s->edge_emu_buffer, ptr, s->linesize, 17, 17+field_based, 
-                             src_x, src_y<<field_based, s->h_edge_pos, s->v_edge_pos);
-            ptr= s->edge_emu_buffer;
-            emu=1;
-        }
-    }
-    if(!field_based)
-        qpix_op[0][dxy](dest_y, ptr, linesize);
-    else{
-        if(field_select)
-            ptr += s->linesize;
-        //damn interlaced mode
-        //FIXME boundary mirroring is not exactly correct here
-        qpix_op[1][dxy](dest_y  , ptr  , linesize);
-        qpix_op[1][dxy](dest_y+8, ptr+8, linesize);
-    }
-
-    if(s->flags&CODEC_FLAG_GRAY) return;
-
     if(field_based){
         mx= motion_x/2;
         my= motion_y>>1;
@@ -2613,39 +2609,56 @@ static inline void qpel_motion(MpegEncContext *s,
     mx= (mx>>1)|(mx&1);
     my= (my>>1)|(my&1);
 
-    dxy= (mx&1) | ((my&1)<<1);
+    uvdxy= (mx&1) | ((my&1)<<1);
     mx>>=1;
     my>>=1;
 
-    src_x = s->mb_x * 8 + mx;
-    src_y = s->mb_y * (8 >> field_based) + my;
-    src_x = clip(src_x, -8, s->width >> 1);
-    if (src_x == (s->width >> 1))
-        dxy &= ~1;
-    src_y = clip(src_y, -8, height >> 1);
-    if (src_y == (height >> 1))
-        dxy &= ~2;
+    uvsrc_x = s->mb_x *  8                 + mx;
+    uvsrc_y = s->mb_y * (8 >> field_based) + my;
 
-    offset = (src_y * uvlinesize) + src_x;
-    ptr = ref_picture[1] + offset;
-    if(emu){
-        ff_emulated_edge_mc(s->edge_emu_buffer, ptr, s->uvlinesize, 9, 9 + field_based, 
-                         src_x, src_y<<field_based, s->h_edge_pos>>1, s->v_edge_pos>>1);
-        ptr= s->edge_emu_buffer;
+    ptr_y  = ref_picture[0] +   src_y *   linesize +   src_x;
+    ptr_cb = ref_picture[1] + uvsrc_y * uvlinesize + uvsrc_x;
+    ptr_cr = ref_picture[2] + uvsrc_y * uvlinesize + uvsrc_x;
+
+    if(   (unsigned)src_x > s->h_edge_pos - (motion_x&3) - 16 
+       || (unsigned)src_y >    v_edge_pos - (motion_y&3) - h  ){
+        ff_emulated_edge_mc(s->edge_emu_buffer, ptr_y, s->linesize, 17, 17+field_based, 
+                         src_x, src_y<<field_based, s->h_edge_pos, s->v_edge_pos);
+        ptr_y= s->edge_emu_buffer;
+        if(!(s->flags&CODEC_FLAG_GRAY)){
+            uint8_t *uvbuf= s->edge_emu_buffer + 18*s->linesize;
+            ff_emulated_edge_mc(uvbuf, ptr_cb, s->uvlinesize, 9, 9 + field_based, 
+                             uvsrc_x, uvsrc_y<<field_based, s->h_edge_pos>>1, s->v_edge_pos>>1);
+            ff_emulated_edge_mc(uvbuf + 16, ptr_cr, s->uvlinesize, 9, 9 + field_based, 
+                             uvsrc_x, uvsrc_y<<field_based, s->h_edge_pos>>1, s->v_edge_pos>>1);
+            ptr_cb= uvbuf;
+            ptr_cr= uvbuf + 16;
+        }
     }
-    if(field_select)
-        ptr += s->uvlinesize;
-    pix_op[1][dxy](dest_cb, ptr, uvlinesize, h >> 1);
-    
-    ptr = ref_picture[2] + offset;
-    if(emu){
-        ff_emulated_edge_mc(s->edge_emu_buffer, ptr, s->uvlinesize, 9, 9 + field_based, 
-                         src_x, src_y<<field_based, s->h_edge_pos>>1, s->v_edge_pos>>1);
-        ptr= s->edge_emu_buffer;
+
+    if(!field_based)
+        qpix_op[0][dxy](dest_y, ptr_y, linesize);
+    else{
+        if(bottom_field){
+            dest_y += s->linesize;
+            dest_cb+= s->uvlinesize;
+            dest_cr+= s->uvlinesize;
+        }
+
+        if(field_select){
+            ptr_y  += s->linesize;
+            ptr_cb += s->uvlinesize;
+            ptr_cr += s->uvlinesize;
+        }
+        //damn interlaced mode
+        //FIXME boundary mirroring is not exactly correct here
+        qpix_op[1][dxy](dest_y  , ptr_y  , linesize);
+        qpix_op[1][dxy](dest_y+8, ptr_y+8, linesize);
+    }
+    if(!(s->flags&CODEC_FLAG_GRAY)){
+        pix_op[1][uvdxy](dest_cr, ptr_cr, uvlinesize, h >> 1);
+        pix_op[1][uvdxy](dest_cb, ptr_cb, uvlinesize, h >> 1);
     }
-    if(field_select)
-        ptr += s->uvlinesize;
-    pix_op[1][dxy](dest_cr, ptr, uvlinesize, h >> 1);
 }
 
 inline int ff_h263_round_chroma(int x){
@@ -2875,16 +2888,12 @@ static inline void MPV_motion(MpegEncContext *s,
     case MV_TYPE_FIELD:
         if (s->picture_structure == PICT_FRAME) {
             if(s->quarter_sample){
-                /* top field */
-                qpel_motion(s, dest_y, dest_cb, dest_cr,
-                            1, 0, s->field_select[dir][0],
-                            ref_picture, pix_op, qpix_op,
-                            s->mv[dir][0][0], s->mv[dir][0][1], 8);
-                /* bottom field */
-                qpel_motion(s, dest_y, dest_cb, dest_cr,
-                            1, 1, s->field_select[dir][1],
-                            ref_picture, pix_op, qpix_op,
-                            s->mv[dir][1][0], s->mv[dir][1][1], 8);
+                for(i=0; i<2; i++){
+                    qpel_motion(s, dest_y, dest_cb, dest_cr,
+                                1, i, s->field_select[dir][i],
+                                ref_picture, pix_op, qpix_op,
+                                s->mv[dir][i][0], s->mv[dir][i][1], 8);
+                }
             }else{
                 /* top field */       
                 mpeg_motion(s, dest_y, dest_cb, dest_cr,
@@ -2908,83 +2917,53 @@ static inline void MPV_motion(MpegEncContext *s,
                         s->mv[dir][0][0], s->mv[dir][0][1], 16);
         }
         break;
-    case MV_TYPE_16X8:{
-         uint8_t ** ref2picture;
+    case MV_TYPE_16X8:
+        for(i=0; i<2; i++){
+            uint8_t ** ref2picture;
 
-            if(s->picture_structure == s->field_select[dir][0] + 1 || s->pict_type == B_TYPE || s->first_field){
+            if(s->picture_structure == s->field_select[dir][i] + 1 || s->pict_type == B_TYPE || s->first_field){
                 ref2picture= ref_picture;
             }else{
                 ref2picture= s->current_picture_ptr->data;
             } 
 
             mpeg_motion(s, dest_y, dest_cb, dest_cr, 
-                        0, 0, s->field_select[dir][0],
+                        0, 0, s->field_select[dir][i],
                         ref2picture, pix_op,
-                        s->mv[dir][0][0], s->mv[dir][0][1], 8);
-
-
-            if(s->picture_structure == s->field_select[dir][1] + 1 || s->pict_type == B_TYPE || s->first_field){
-                ref2picture= ref_picture;
-            }else{
-                ref2picture= s->current_picture_ptr->data;
-            } 
-            // I know it is ugly but this is the only way to fool emu_edge without rewrite mpeg_motion
-            mpeg_motion(s, dest_y+16*s->linesize, dest_cb+8*s->uvlinesize, dest_cr+8*s->uvlinesize,
-                        0, 0, s->field_select[dir][1],
-                        ref2picture, pix_op,
-                        s->mv[dir][1][0], s->mv[dir][1][1]+16, 8);
-        }
-        
+                        s->mv[dir][i][0], s->mv[dir][i][1] + 16*i, 8);
+                
+            dest_y += 16*s->linesize;
+            dest_cb+=  8*s->uvlinesize;
+            dest_cr+=  8*s->uvlinesize;
+        }        
         break;
     case MV_TYPE_DMV:
-        pix_op = s->dsp.put_pixels_tab;
-
         if(s->picture_structure == PICT_FRAME){
-            //put top field from top field
-            mpeg_motion(s, dest_y, dest_cb, dest_cr,
-                        1, 0, 0,
-                        ref_picture, pix_op,
-                        s->mv[dir][0][0], s->mv[dir][0][1], 8);
-            //put bottom field from bottom field
-            mpeg_motion(s, dest_y, dest_cb, dest_cr,
-                        1, 1, 1,
-                        ref_picture, pix_op,
-                        s->mv[dir][0][0], s->mv[dir][0][1], 8);
-
-            pix_op = s->dsp.avg_pixels_tab; 
-        
-            //avg top field from bottom field
-            mpeg_motion(s, dest_y, dest_cb, dest_cr,
-                        1, 0, 1,
-                        ref_picture, pix_op,
-                        s->mv[dir][2][0], s->mv[dir][2][1], 8);
-            //avg bottom field from top field
-            mpeg_motion(s, dest_y, dest_cb, dest_cr,
-                        1, 1, 0,
-                        ref_picture, pix_op,
-                        s->mv[dir][3][0], s->mv[dir][3][1], 8);
-
+            for(i=0; i<2; i++){
+                int j;
+                for(j=0; j<2; j++){
+                    mpeg_motion(s, dest_y, dest_cb, dest_cr,
+                                1, j, j^i,
+                                ref_picture, pix_op,
+                                s->mv[dir][2*i + j][0], s->mv[dir][2*i + j][1], 8);
+                }
+                pix_op = s->dsp.avg_pixels_tab; 
+            }
         }else{
-            //put field from the same parity
-            //same parity is never in the same frame
-            mpeg_motion(s, dest_y, dest_cb, dest_cr, 
-                        0, 0, s->picture_structure == PICT_BOTTOM_FIELD,
-                        ref_picture, pix_op,
-                        s->mv[dir][0][0],s->mv[dir][0][1],16);
+            for(i=0; i<2; i++){
+                mpeg_motion(s, dest_y, dest_cb, dest_cr, 
+                            0, 0, s->picture_structure != i+1,
+                            ref_picture, pix_op,
+                            s->mv[dir][2*i][0],s->mv[dir][2*i][1],16);
 
-            // after put we make avg of the same block
-            pix_op=s->dsp.avg_pixels_tab; 
+                // after put we make avg of the same block
+                pix_op=s->dsp.avg_pixels_tab; 
 
-            //opposite parity is always in the same frame if this is second field
-            if(!s->first_field){
-                ref_picture = s->current_picture_ptr->data;    
+                //opposite parity is always in the same frame if this is second field
+                if(!s->first_field){
+                    ref_picture = s->current_picture_ptr->data;    
+                }
             }
-
-            //avg field from the opposite parity
-            mpeg_motion(s, dest_y, dest_cb, dest_cr,
-                        0, 0, s->picture_structure != PICT_BOTTOM_FIELD,
-                        ref_picture, pix_op,
-                        s->mv[dir][2][0],s->mv[dir][2][1],16);
         }
     break;
     default: assert(0);
@@ -3423,7 +3402,6 @@ static void encode_mb(MpegEncContext *s, int motion_x, int motion_y)
     int dct_offset   = s->linesize*8; //default for progressive frames
     uint8_t *ptr_y, *ptr_cb, *ptr_cr;
     int wrap_y, wrap_c;
-    int emu=0;
     
     for(i=0; i<6; i++) skip_dct[i]=0;
     
@@ -3466,10 +3444,10 @@ static void encode_mb(MpegEncContext *s, int motion_x, int motion_y)
     if(mb_x*16+16 > s->width || mb_y*16+16 > s->height){
         ff_emulated_edge_mc(s->edge_emu_buffer            , ptr_y , wrap_y,16,16,mb_x*16,mb_y*16, s->width   , s->height);
         ptr_y= s->edge_emu_buffer;
-        ff_emulated_edge_mc(s->edge_emu_buffer+16*wrap_y  , ptr_cb, wrap_c, 8, 8, mb_x*8, mb_y*8, s->width>>1, s->height>>1);
-        ptr_cb= s->edge_emu_buffer+16*wrap_y;
-        ff_emulated_edge_mc(s->edge_emu_buffer+16*wrap_y+8, ptr_cr, wrap_c, 8, 8, mb_x*8, mb_y*8, s->width>>1, s->height>>1);
-        ptr_cr= s->edge_emu_buffer+16*wrap_y+8;
+        ff_emulated_edge_mc(s->edge_emu_buffer+18*wrap_y  , ptr_cb, wrap_c, 8, 8, mb_x*8, mb_y*8, s->width>>1, s->height>>1);
+        ptr_cb= s->edge_emu_buffer+18*wrap_y;
+        ff_emulated_edge_mc(s->edge_emu_buffer+18*wrap_y+9, ptr_cr, wrap_c, 8, 8, mb_x*8, mb_y*8, s->width>>1, s->height>>1);
+        ptr_cr= s->edge_emu_buffer+18*wrap_y+9;
     }
 
     if (s->mb_intra) {
@@ -3750,6 +3728,7 @@ void ff_mpeg_flush(AVCodecContext *avctx){
     s->parse_context.overread_index= 0;
     s->parse_context.index= 0;
     s->parse_context.last_index= 0;
+    s->bitstream_buffer_size=0;
 }
 
 #ifdef CONFIG_ENCODERS
@@ -4620,7 +4599,6 @@ static void merge_context_after_encode(MpegEncContext *dst, MpegEncContext *src)
 
 static void encode_picture(MpegEncContext *s, int picture_number)
 {
-    int mb_x, mb_y;
     int i, j;
     int bits;
 
@@ -5181,7 +5159,6 @@ static int dct_quantize_refine(MpegEncContext *s, //FIXME breaks denoise?
     int prev_run=0;
     int prev_level=0;
     int qmul, qadd, start_i, last_non_zero, i, dc;
-    const int esc_length= s->ac_esc_length;
     uint8_t * length;
     uint8_t * last_length;
     int lambda;
@@ -5289,7 +5266,6 @@ STOP_TIMER("init rem[]")
 #endif
     for(;;){
         int best_score=s->dsp.try_8x8basis(rem, weight, basis[0], 0);
-        int nochange_score= best_score;
         int best_coeff=0;
         int best_change=0;
         int run2, best_unquant_change, analyze_gradient;