]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/mpegvideo.c
Merge remote-tracking branch 'qatar/master'
[ffmpeg] / libavcodec / mpegvideo.c
index a2aa257f89369592779968af337e7dca528ffef0..90eb737ec7ac6d93f7dc8dc737e88d548f6380b6 100644 (file)
@@ -5,20 +5,20 @@
  *
  * 4MV & hq & B-frame encoding stuff by Michael Niedermayer <michaelni@gmx.at>
  *
- * This file is part of Libav.
+ * This file is part of FFmpeg.
  *
- * Libav is free software; you can redistribute it and/or
+ * FFmpeg is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  *
- * Libav is distributed in the hope that it will be useful,
+ * FFmpeg is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with Libav; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
@@ -568,6 +568,7 @@ int ff_mpeg_update_thread_context(AVCodecContext *dst,
     // Error/bug resilience
     s->next_p_frame_damaged = s1->next_p_frame_damaged;
     s->workaround_bugs      = s1->workaround_bugs;
+    s->padding_bug_score    = s1->padding_bug_score;
 
     // MPEG4 timing info
     memcpy(&s->time_increment_bits, &s1->time_increment_bits,
@@ -696,110 +697,83 @@ av_cold int MPV_common_init(MpegEncContext *s)
     s->flags  = s->avctx->flags;
     s->flags2 = s->avctx->flags2;
 
-    if (s->width && s->height) {
-        s->mb_width   = (s->width + 15) / 16;
-        s->mb_stride  = s->mb_width + 1;
-        s->b8_stride  = s->mb_width * 2 + 1;
-        s->b4_stride  = s->mb_width * 4 + 1;
-        mb_array_size = s->mb_height * s->mb_stride;
-        mv_table_size = (s->mb_height + 2) * s->mb_stride + 1;
+    s->mb_width   = (s->width + 15) / 16;
+    s->mb_stride  = s->mb_width + 1;
+    s->b8_stride  = s->mb_width * 2 + 1;
+    s->b4_stride  = s->mb_width * 4 + 1;
+    mb_array_size = s->mb_height * s->mb_stride;
+    mv_table_size = (s->mb_height + 2) * s->mb_stride + 1;
 
-        /* set chroma shifts */
-        avcodec_get_chroma_sub_sample(s->avctx->pix_fmt,&(s->chroma_x_shift),
-                                      &(s->chroma_y_shift) );
+    /* set chroma shifts */
+    avcodec_get_chroma_sub_sample(s->avctx->pix_fmt,&(s->chroma_x_shift),
+                                                    &(s->chroma_y_shift) );
 
-        /* set default edge pos, will be overriden
-         * in decode_header if needed */
-        s->h_edge_pos = s->mb_width * 16;
-        s->v_edge_pos = s->mb_height * 16;
+    /* set default edge pos, will be overriden in decode_header if needed */
+    s->h_edge_pos = s->mb_width * 16;
+    s->v_edge_pos = s->mb_height * 16;
 
-        s->mb_num     = s->mb_width * s->mb_height;
+    s->mb_num = s->mb_width * s->mb_height;
 
-        s->block_wrap[0] =
-        s->block_wrap[1] =
-        s->block_wrap[2] =
-        s->block_wrap[3] = s->b8_stride;
-        s->block_wrap[4] =
-        s->block_wrap[5] = s->mb_stride;
+    s->block_wrap[0] =
+    s->block_wrap[1] =
+    s->block_wrap[2] =
+    s->block_wrap[3] = s->b8_stride;
+    s->block_wrap[4] =
+    s->block_wrap[5] = s->mb_stride;
 
-        y_size  = s->b8_stride * (2 * s->mb_height + 1);
-        c_size  = s->mb_stride * (s->mb_height + 1);
-        yc_size = y_size + 2   * c_size;
+    y_size = s->b8_stride * (2 * s->mb_height + 1);
+    c_size = s->mb_stride * (s->mb_height + 1);
+    yc_size = y_size + 2 * c_size;
 
-        /* convert fourcc to upper case */
-        s->codec_tag          = avpriv_toupper4(s->avctx->codec_tag);
+    /* convert fourcc to upper case */
+    s->codec_tag        = avpriv_toupper4(s->avctx->codec_tag);
+    s->stream_codec_tag = avpriv_toupper4(s->avctx->stream_codec_tag);
 
-        s->stream_codec_tag   = avpriv_toupper4(s->avctx->stream_codec_tag);
+    s->avctx->coded_frame = (AVFrame*)&s->current_picture;
 
-        s->avctx->coded_frame = (AVFrame *)&s->current_picture;
+    FF_ALLOCZ_OR_GOTO(s->avctx, s->mb_index2xy, (s->mb_num + 1) * sizeof(int), fail); // error ressilience code looks cleaner with this
+    for (y = 0; y < s->mb_height; y++)
+        for (x = 0; x < s->mb_width; x++)
+            s->mb_index2xy[x + y * s->mb_width] = x + y * s->mb_stride;
 
-        FF_ALLOCZ_OR_GOTO(s->avctx, s->mb_index2xy, (s->mb_num + 1) * sizeof(int),
-                          fail); // error ressilience code looks cleaner with this
-        for (y = 0; y < s->mb_height; y++)
-            for (x = 0; x < s->mb_width; x++)
-                s->mb_index2xy[x + y * s->mb_width] = x + y * s->mb_stride;
+    s->mb_index2xy[s->mb_height * s->mb_width] = (s->mb_height - 1) * s->mb_stride + s->mb_width; // FIXME really needed?
 
-        s->mb_index2xy[s->mb_height * s->mb_width] =
-                       (s->mb_height - 1) * s->mb_stride + s->mb_width; // FIXME really needed?
+    if (s->encoding) {
+        /* Allocate MV tables */
+        FF_ALLOCZ_OR_GOTO(s->avctx, s->p_mv_table_base            , mv_table_size * 2 * sizeof(int16_t), fail)
+        FF_ALLOCZ_OR_GOTO(s->avctx, s->b_forw_mv_table_base       , mv_table_size * 2 * sizeof(int16_t), fail)
+        FF_ALLOCZ_OR_GOTO(s->avctx, s->b_back_mv_table_base       , mv_table_size * 2 * sizeof(int16_t), fail)
+        FF_ALLOCZ_OR_GOTO(s->avctx, s->b_bidir_forw_mv_table_base , mv_table_size * 2 * sizeof(int16_t), fail)
+        FF_ALLOCZ_OR_GOTO(s->avctx, s->b_bidir_back_mv_table_base , mv_table_size * 2 * sizeof(int16_t), fail)
+        FF_ALLOCZ_OR_GOTO(s->avctx, s->b_direct_mv_table_base     , mv_table_size * 2 * sizeof(int16_t), fail)
+        s->p_mv_table           = s->p_mv_table_base            + s->mb_stride + 1;
+        s->b_forw_mv_table      = s->b_forw_mv_table_base       + s->mb_stride + 1;
+        s->b_back_mv_table      = s->b_back_mv_table_base       + s->mb_stride + 1;
+        s->b_bidir_forw_mv_table= s->b_bidir_forw_mv_table_base + s->mb_stride + 1;
+        s->b_bidir_back_mv_table= s->b_bidir_back_mv_table_base + s->mb_stride + 1;
+        s->b_direct_mv_table    = s->b_direct_mv_table_base     + s->mb_stride + 1;
 
-        if (s->encoding) {
-            /* Allocate MV tables */
-            FF_ALLOCZ_OR_GOTO(s->avctx, s->p_mv_table_base,
-                              mv_table_size * 2 * sizeof(int16_t), fail);
-            FF_ALLOCZ_OR_GOTO(s->avctx, s->b_forw_mv_table_base,
-                              mv_table_size * 2 * sizeof(int16_t), fail);
-            FF_ALLOCZ_OR_GOTO(s->avctx, s->b_back_mv_table_base,
-                              mv_table_size * 2 * sizeof(int16_t), fail);
-            FF_ALLOCZ_OR_GOTO(s->avctx, s->b_bidir_forw_mv_table_base,
-                              mv_table_size * 2 * sizeof(int16_t), fail);
-            FF_ALLOCZ_OR_GOTO(s->avctx, s->b_bidir_back_mv_table_base,
-                              mv_table_size * 2 * sizeof(int16_t), fail);
-            FF_ALLOCZ_OR_GOTO(s->avctx, s->b_direct_mv_table_base,
-                              mv_table_size * 2 * sizeof(int16_t), fail);
-            s->p_mv_table            = s->p_mv_table_base +
-                                       s->mb_stride + 1;
-            s->b_forw_mv_table       = s->b_forw_mv_table_base +
-                                       s->mb_stride + 1;
-            s->b_back_mv_table       = s->b_back_mv_table_base +
-                                       s->mb_stride + 1;
-            s->b_bidir_forw_mv_table = s->b_bidir_forw_mv_table_base +
-                                       s->mb_stride + 1;
-            s->b_bidir_back_mv_table = s->b_bidir_back_mv_table_base +
-                                       s->mb_stride + 1;
-            s->b_direct_mv_table     = s->b_direct_mv_table_base +
-                                       s->mb_stride + 1;
-
-            if (s->msmpeg4_version) {
-                FF_ALLOCZ_OR_GOTO(s->avctx, s->ac_stats,
-                                  2 * 2 * (MAX_LEVEL + 1) *
-                                  (MAX_RUN + 1) * 2 * sizeof(int), fail);
-            }
-            FF_ALLOCZ_OR_GOTO(s->avctx, s->avctx->stats_out, 256, fail);
-
-            /* Allocate MB type table */
-            FF_ALLOCZ_OR_GOTO(s->avctx, s->mb_type, mb_array_size *
-                              sizeof(uint16_t), fail); // needed for encoding
-
-            FF_ALLOCZ_OR_GOTO(s->avctx, s->lambda_table, mb_array_size *
-                              sizeof(int), fail);
-
-            FF_ALLOCZ_OR_GOTO(s->avctx, s->q_intra_matrix,
-                              64 * 32   * sizeof(int), fail);
-            FF_ALLOCZ_OR_GOTO(s->avctx, s->q_inter_matrix,
-                              64 * 32   * sizeof(int), fail);
-            FF_ALLOCZ_OR_GOTO(s->avctx, s->q_intra_matrix16,
-                              64 * 32 * 2 * sizeof(uint16_t), fail);
-            FF_ALLOCZ_OR_GOTO(s->avctx, s->q_inter_matrix16,
-                              64 * 32 * 2 * sizeof(uint16_t), fail);
-            FF_ALLOCZ_OR_GOTO(s->avctx, s->input_picture,
-                              MAX_PICTURE_COUNT * sizeof(Picture *), fail);
-            FF_ALLOCZ_OR_GOTO(s->avctx, s->reordered_input_picture,
-                              MAX_PICTURE_COUNT * sizeof(Picture *), fail);
-
-            if (s->avctx->noise_reduction) {
-                FF_ALLOCZ_OR_GOTO(s->avctx, s->dct_offset,
-                                  2 * 64 * sizeof(uint16_t), fail);
-            }
+        if(s->msmpeg4_version){
+            FF_ALLOCZ_OR_GOTO(s->avctx, s->ac_stats, 2*2*(MAX_LEVEL+1)*(MAX_RUN+1)*2*sizeof(int), fail);
+        }
+        FF_ALLOCZ_OR_GOTO(s->avctx, s->avctx->stats_out, 256, fail);
+
+        /* Allocate MB type table */
+        FF_ALLOCZ_OR_GOTO(s->avctx, s->mb_type  , mb_array_size * sizeof(uint16_t), fail) //needed for encoding
+
+        FF_ALLOCZ_OR_GOTO(s->avctx, s->lambda_table, mb_array_size * sizeof(int), fail)
+
+        FF_ALLOCZ_OR_GOTO(s->avctx, s->q_intra_matrix         , 64*32   * sizeof(int), fail)
+        FF_ALLOCZ_OR_GOTO(s->avctx, s->q_chroma_intra_matrix  , 64*32   * sizeof(int), fail)
+        FF_ALLOCZ_OR_GOTO(s->avctx, s->q_inter_matrix         , 64*32   * sizeof(int), fail)
+        FF_ALLOCZ_OR_GOTO(s->avctx, s->q_intra_matrix16       , 64*32*2 * sizeof(uint16_t), fail)
+        FF_ALLOCZ_OR_GOTO(s->avctx, s->q_chroma_intra_matrix16, 64*32*2 * sizeof(uint16_t), fail)
+        FF_ALLOCZ_OR_GOTO(s->avctx, s->q_inter_matrix16       , 64*32*2 * sizeof(uint16_t), fail)
+        FF_ALLOCZ_OR_GOTO(s->avctx, s->input_picture, MAX_PICTURE_COUNT * sizeof(Picture*), fail)
+        FF_ALLOCZ_OR_GOTO(s->avctx, s->reordered_input_picture, MAX_PICTURE_COUNT * sizeof(Picture*), fail)
+
+        if(s->avctx->noise_reduction){
+            FF_ALLOCZ_OR_GOTO(s->avctx, s->dct_offset, 2 * 64 * sizeof(uint16_t), fail)
         }
     }
 
@@ -810,36 +784,22 @@ av_cold int MPV_common_init(MpegEncContext *s)
         avcodec_get_frame_defaults((AVFrame *) &s->picture[i]);
     }
 
-    if (s->width && s->height) {
-        FF_ALLOCZ_OR_GOTO(s->avctx, s->error_status_table,
-                          mb_array_size * sizeof(uint8_t), fail);
+    FF_ALLOCZ_OR_GOTO(s->avctx, s->error_status_table, mb_array_size*sizeof(uint8_t), fail)
 
-        if (s->codec_id == CODEC_ID_MPEG4 ||
-            (s->flags & CODEC_FLAG_INTERLACED_ME)) {
+        if(s->codec_id==CODEC_ID_MPEG4 || (s->flags & CODEC_FLAG_INTERLACED_ME)){
             /* interlaced direct mode decoding tables */
             for (i = 0; i < 2; i++) {
                 int j, k;
                 for (j = 0; j < 2; j++) {
                     for (k = 0; k < 2; k++) {
-                        FF_ALLOCZ_OR_GOTO(s->avctx,
-                                          s->b_field_mv_table_base[i][j][k],
-                                          mv_table_size * 2 * sizeof(int16_t),
-                                          fail);
-                        s->b_field_mv_table[i][j][k] = s->b_field_mv_table_base[i][j][k] +
-                                                       s->mb_stride + 1;
+                        FF_ALLOCZ_OR_GOTO(s->avctx, s->b_field_mv_table_base[i][j][k],  mv_table_size * 2 * sizeof(int16_t), fail)
+                        s->b_field_mv_table[i][j][k] = s->b_field_mv_table_base[i][j][k] + s->mb_stride + 1;
                     }
-                    FF_ALLOCZ_OR_GOTO(s->avctx, s->b_field_select_table [i][j],
-                                      mb_array_size * 2 * sizeof(uint8_t),
-                                      fail);
-                    FF_ALLOCZ_OR_GOTO(s->avctx, s->p_field_mv_table_base[i][j],
-                                      mv_table_size * 2 * sizeof(int16_t),
-                                      fail);
-                    s->p_field_mv_table[i][j] = s->p_field_mv_table_base[i][j]
-                                                + s->mb_stride + 1;
+                    FF_ALLOCZ_OR_GOTO(s->avctx, s->b_field_select_table [i][j], mb_array_size * 2 * sizeof(uint8_t), fail)
+                    FF_ALLOCZ_OR_GOTO(s->avctx, s->p_field_mv_table_base[i][j], mv_table_size * 2 * sizeof(int16_t), fail)
+                    s->p_field_mv_table[i][j] = s->p_field_mv_table_base[i][j] + s->mb_stride + 1;
                 }
-                FF_ALLOCZ_OR_GOTO(s->avctx, s->p_field_select_table[i],
-                                  mb_array_size * 2 * sizeof(uint8_t),
-                                  fail);
+                FF_ALLOCZ_OR_GOTO(s->avctx, s->p_field_select_table[i], mb_array_size * 2 * sizeof(uint8_t), fail)
             }
         }
         if (s->out_format == FMT_H263) {
@@ -848,17 +808,14 @@ av_cold int MPV_common_init(MpegEncContext *s)
             s->coded_block = s->coded_block_base + s->b8_stride + 1;
 
             /* cbp, ac_pred, pred_dir */
-            FF_ALLOCZ_OR_GOTO(s->avctx, s->cbp_table,
-                              mb_array_size * sizeof(uint8_t), fail);
-            FF_ALLOCZ_OR_GOTO(s->avctx, s->pred_dir_table,
-                              mb_array_size * sizeof(uint8_t), fail);
+            FF_ALLOCZ_OR_GOTO(s->avctx, s->cbp_table     , mb_array_size * sizeof(uint8_t), fail);
+            FF_ALLOCZ_OR_GOTO(s->avctx, s->pred_dir_table, mb_array_size * sizeof(uint8_t), fail);
         }
 
         if (s->h263_pred || s->h263_plus || !s->encoding) {
             /* dc values */
             // MN: we need these for  error resilience of intra-frames
-            FF_ALLOCZ_OR_GOTO(s->avctx, s->dc_val_base,
-                              yc_size * sizeof(int16_t), fail);
+            FF_ALLOCZ_OR_GOTO(s->avctx, s->dc_val_base, yc_size * sizeof(int16_t), fail);
             s->dc_val[0] = s->dc_val_base + s->b8_stride + 1;
             s->dc_val[1] = s->dc_val_base + y_size + s->mb_stride + 1;
             s->dc_val[2] = s->dc_val[1] + c_size;
@@ -875,21 +832,11 @@ av_cold int MPV_common_init(MpegEncContext *s)
         // Note the + 1 is for  a quicker mpeg4 slice_end detection
 
         s->parse_context.state = -1;
-        if ((s->avctx->debug & (FF_DEBUG_VIS_QP | FF_DEBUG_VIS_MB_TYPE)) ||
-            s->avctx->debug_mv) {
-            s->visualization_buffer[0] = av_malloc((s->mb_width * 16 +
-                        2 * EDGE_WIDTH) * s->mb_height * 16 + 2 * EDGE_WIDTH);
-            s->visualization_buffer[1] = av_malloc((s->mb_width * 16 +
-                        2 * EDGE_WIDTH) * s->mb_height * 16 + 2 * EDGE_WIDTH);
-            s->visualization_buffer[2] = av_malloc((s->mb_width * 16 +
-                        2 * EDGE_WIDTH) * s->mb_height * 16 + 2 * EDGE_WIDTH);
-        }
-    }
 
-    s->context_initialized = 1;
-    s->thread_context[0]   = s;
+        s->context_initialized = 1;
+        s->thread_context[0]   = s;
 
-    if (s->width && s->height) {
+//     if (s->width && s->height) {
         if (nb_slices > 1) {
             for (i = 1; i < nb_slices; i++) {
                 s->thread_context[i] = av_malloc(sizeof(MpegEncContext));
@@ -911,7 +858,7 @@ av_cold int MPV_common_init(MpegEncContext *s)
             s->end_mb_y   = s->mb_height;
         }
         s->slice_context_count = nb_slices;
-    }
+//     }
 
     return 0;
  fail:
@@ -978,6 +925,10 @@ void MPV_common_end(MpegEncContext *s)
     av_freep(&s->error_status_table);
     av_freep(&s->mb_index2xy);
     av_freep(&s->lambda_table);
+    if(s->q_chroma_intra_matrix   != s->q_intra_matrix  ) av_freep(&s->q_chroma_intra_matrix);
+    if(s->q_chroma_intra_matrix16 != s->q_intra_matrix16) av_freep(&s->q_chroma_intra_matrix16);
+    s->q_chroma_intra_matrix=   NULL;
+    s->q_chroma_intra_matrix16= NULL;
     av_freep(&s->q_intra_matrix);
     av_freep(&s->q_inter_matrix);
     av_freep(&s->q_intra_matrix16);
@@ -1132,7 +1083,21 @@ int ff_find_unused_picture(MpegEncContext *s, int shared)
         }
     }
 
-    return AVERROR_INVALIDDATA;
+    av_log(s->avctx, AV_LOG_FATAL,
+           "Internal error, picture buffer overflow\n");
+    /* We could return -1, but the codec would crash trying to draw into a
+     * non-existing frame anyway. This is safer than waiting for a random crash.
+     * Also the return of this is never useful, an encoder must only allocate
+     * as much as allowed in the specification. This has no relationship to how
+     * much libavcodec could allocate (and MAX_PICTURE_COUNT is always large
+     * enough for such valid streams).
+     * Plus, a decoder has to check stream validity and remove frames if too
+     * many reference frames are around. Waiting for "OOM" is not correct at
+     * all. Similarly, missing reference frames have to be replaced by
+     * interpolated/MC frames, anything else is a bug in the codec ...
+     */
+    abort();
+    return -1;
 }
 
 static void update_noise_reduction(MpegEncContext *s)
@@ -1204,6 +1169,8 @@ int MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx)
             pic = s->current_picture_ptr;
         } else {
             i   = ff_find_unused_picture(s, 0);
+            if (i < 0)
+                return i;
             pic = &s->picture[i];
         }
 
@@ -1267,9 +1234,18 @@ int MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx)
 
             /* Allocate a dummy frame */
             i = ff_find_unused_picture(s, 0);
-            s->last_picture_ptr = &s->picture[i];
+            if (i < 0)
+                return i;
+            s->last_picture_ptr= &s->picture[i];
+            s->last_picture_ptr->f.key_frame = 0;
             if (ff_alloc_picture(s, s->last_picture_ptr, 0) < 0)
                 return -1;
+
+            if(s->codec_id == CODEC_ID_FLV1 || s->codec_id == CODEC_ID_H263){
+                for(i=0; i<avctx->height; i++)
+                    memset(s->last_picture_ptr->f.data[0] + s->last_picture_ptr->f.linesize[0]*i, 16, avctx->width);
+            }
+
             ff_thread_report_progress((AVFrame *) s->last_picture_ptr,
                                       INT_MAX, 0);
             ff_thread_report_progress((AVFrame *) s->last_picture_ptr,
@@ -1280,7 +1256,10 @@ int MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx)
             s->pict_type == AV_PICTURE_TYPE_B) {
             /* Allocate a dummy frame */
             i = ff_find_unused_picture(s, 0);
-            s->next_picture_ptr = &s->picture[i];
+            if (i < 0)
+                return i;
+            s->next_picture_ptr= &s->picture[i];
+            s->next_picture_ptr->f.key_frame = 0;
             if (ff_alloc_picture(s, s->next_picture_ptr, 0) < 0)
                 return -1;
             ff_thread_report_progress((AVFrame *) s->next_picture_ptr,
@@ -1347,7 +1326,7 @@ void MPV_frame_end(MpegEncContext *s)
     // just to make sure that all data is rendered.
     if (CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration) {
         ff_xvmc_field_end(s);
-   } else if ((s->error_count || s->encoding) &&
+   } else if((s->error_count || s->encoding || !(s->avctx->codec->capabilities&CODEC_CAP_DRAW_HORIZ_BAND)) &&
               !s->avctx->hwaccel &&
               !(s->avctx->codec->capabilities & CODEC_CAP_HWACCEL_VDPAU) &&
               s->unrestricted_mv &&
@@ -1438,7 +1417,7 @@ static void draw_line(uint8_t *buf, int sx, int sy, int ex, int ey,
         buf += sx + sy * stride;
         ex  -= sx;
         f    = ((ey - sy) << 16) / ex;
-        for (x = 0; x = ex; x++) {
+        for(x= 0; x <= ex; x++){
             y  = (x * f) >> 16;
             fr = (x * f) & 0xFFFF;
             buf[y * stride + x]       += (color * (0x10000 - fr)) >> 16;
@@ -1452,12 +1431,12 @@ static void draw_line(uint8_t *buf, int sx, int sy, int ex, int ey,
         buf += sx + sy * stride;
         ey  -= sy;
         if (ey)
-            f  = ((ex - sx) << 16) / ey;
+            f = ((ex - sx) << 16) / ey;
         else
             f = 0;
-        for (y = 0; y = ey; y++) {
-            x  = (y * f) >> 16;
-            fr = (y * f) & 0xFFFF;
+        for(y= 0; y <= ey; y++){
+            x  = (y*f) >> 16;
+            fr = (y*f) & 0xFFFF;
             buf[y * stride + x]     += (color * (0x10000 - fr)) >> 16;
             buf[y * stride + x + 1] += (color *            fr ) >> 16;
         }
@@ -1510,27 +1489,8 @@ void ff_print_debug_info(MpegEncContext *s, AVFrame *pict)
     if (s->avctx->debug & (FF_DEBUG_SKIP | FF_DEBUG_QP | FF_DEBUG_MB_TYPE)) {
         int x,y;
 
-        av_log(s->avctx,AV_LOG_DEBUG,"New frame, type: ");
-        switch (pict->pict_type) {
-        case AV_PICTURE_TYPE_I:
-            av_log(s->avctx,AV_LOG_DEBUG,"I\n");
-            break;
-        case AV_PICTURE_TYPE_P:
-            av_log(s->avctx,AV_LOG_DEBUG,"P\n");
-            break;
-        case AV_PICTURE_TYPE_B:
-            av_log(s->avctx,AV_LOG_DEBUG,"B\n");
-            break;
-        case AV_PICTURE_TYPE_S:
-            av_log(s->avctx,AV_LOG_DEBUG,"S\n");
-            break;
-        case AV_PICTURE_TYPE_SI:
-            av_log(s->avctx,AV_LOG_DEBUG,"SI\n");
-            break;
-        case AV_PICTURE_TYPE_SP:
-            av_log(s->avctx,AV_LOG_DEBUG,"SP\n");
-            break;
-        }
+        av_log(s->avctx, AV_LOG_DEBUG, "New frame, type: %c\n",
+               av_get_picture_type_char(pict->pict_type));
         for (y = 0; y < s->mb_height; y++) {
             for (x = 0; x < s->mb_width; x++) {
                 if (s->avctx->debug & FF_DEBUG_SKIP) {
@@ -1614,12 +1574,14 @@ void ff_print_debug_info(MpegEncContext *s, AVFrame *pict)
         avcodec_get_chroma_sub_sample(s->avctx->pix_fmt,
                                       &h_chroma_shift, &v_chroma_shift);
         for (i = 0; i < 3; i++) {
-            memcpy(s->visualization_buffer[i], pict->data[i],
-                   (i == 0) ? pict->linesize[i] * height:
-                              pict->linesize[i] * height >> v_chroma_shift);
+            size_t size= (i == 0) ? pict->linesize[i] * height:
+                         pict->linesize[i] * height >> v_chroma_shift;
+            s->visualization_buffer[i]= av_realloc(s->visualization_buffer[i], size);
+            memcpy(s->visualization_buffer[i], pict->data[i], size);
             pict->data[i] = s->visualization_buffer[i];
         }
         pict->type   = FF_BUFFER_TYPE_COPY;
+        pict->opaque= NULL;
         ptr          = pict->data[0];
         block_height = 16 >> v_chroma_shift;
 
@@ -1697,11 +1659,11 @@ void ff_print_debug_info(MpegEncContext *s, AVFrame *pict)
                                            height, s->linesize, 100);
                             }
                         } else {
-                              int sx = mb_x * 16 + 8;
-                              int sy = mb_y * 16 + 8;
-                              int xy = (mb_x + mb_y * mv_stride) << mv_sample_log2;
-                              int mx = pict->motion_val[direction][xy][0] >> shift + sx;
-                              int my = pict->motion_val[direction][xy][1] >> shift + sy;
+                              int sx= mb_x * 16 + 8;
+                              int sy= mb_y * 16 + 8;
+                              int xy= (mb_x + mb_y * mv_stride) << mv_sample_log2;
+                              int mx= (pict->motion_val[direction][xy][0]>>shift) + sx;
+                              int my= (pict->motion_val[direction][xy][1]>>shift) + sy;
                               draw_arrow(ptr, sx, sy, mx, my, width, height, s->linesize, 100);
                         }
                     }
@@ -1870,7 +1832,7 @@ static av_always_inline void mpeg_motion_lowres(MpegEncContext *s,
     int mx, my, src_x, src_y, uvsrc_x, uvsrc_y, uvlinesize, linesize, sx, sy,
         uvsx, uvsy;
     const int lowres     = s->avctx->lowres;
-    const int op_index   = FFMIN(lowres, 2);
+    const int op_index   = FFMIN(lowres-1+s->chroma_x_shift, 2);
     const int block_s    = 8>>lowres;
     const int s_mask     = (2 << lowres) - 1;
     const int h_edge_pos = s->h_edge_pos >> lowres;
@@ -1884,8 +1846,8 @@ static av_always_inline void mpeg_motion_lowres(MpegEncContext *s,
         motion_y /= 2;
     }
 
-    if (field_based) {
-        motion_y += (bottom_field - field_select) * (1 << lowres - 1);
+    if(field_based){
+        motion_y += (bottom_field - field_select)*((1 << lowres)-1);
     }
 
     sx = motion_x & s_mask;
@@ -1907,12 +1869,29 @@ static av_always_inline void mpeg_motion_lowres(MpegEncContext *s,
         uvsrc_x = s->mb_x * block_s + (mx >> lowres);
         uvsrc_y =    mb_y * block_s + (my >> lowres);
     } else {
-        mx      = motion_x / 2;
-        my      = motion_y / 2;
-        uvsx    = mx & s_mask;
-        uvsy    = my & s_mask;
-        uvsrc_x = s->mb_x * block_s                 + (mx >> lowres + 1);
-        uvsrc_y =   (mb_y * block_s >> field_based) + (my >> lowres + 1);
+        if(s->chroma_y_shift){
+            mx      = motion_x / 2;
+            my      = motion_y / 2;
+            uvsx    = mx & s_mask;
+            uvsy    = my & s_mask;
+            uvsrc_x = s->mb_x * block_s                 + (mx >> lowres + 1);
+            uvsrc_y =   (mb_y * block_s >> field_based) + (my >> lowres + 1);
+        } else {
+            if(s->chroma_x_shift){
+            //Chroma422
+                mx = motion_x / 2;
+                uvsx = mx & s_mask;
+                uvsy = motion_y & s_mask;
+                uvsrc_y = src_y;
+                uvsrc_x = s->mb_x*block_s               + (mx >> (lowres+1));
+            } else {
+            //Chroma444
+                uvsx = motion_x & s_mask;
+                uvsy = motion_y & s_mask;
+                uvsrc_x = src_x;
+                uvsrc_y = src_y;
+            }
+        }
     }
 
     ptr_y  = ref_picture[0] + src_y   * linesize   + src_x;
@@ -1961,10 +1940,10 @@ static av_always_inline void mpeg_motion_lowres(MpegEncContext *s,
     if (!CONFIG_GRAY || !(s->flags & CODEC_FLAG_GRAY)) {
         uvsx = (uvsx << 2) >> lowres;
         uvsy = (uvsy << 2) >> lowres;
-        pix_op[op_index](dest_cb, ptr_cb, uvlinesize, h >> s->chroma_y_shift,
-                         uvsx, uvsy);
-        pix_op[op_index](dest_cr, ptr_cr, uvlinesize, h >> s->chroma_y_shift,
-                         uvsx, uvsy);
+        if (h >> s->chroma_y_shift) {
+            pix_op[op_index](dest_cb, ptr_cb, uvlinesize, h >> s->chroma_y_shift, uvsx, uvsy);
+            pix_op[op_index](dest_cr, ptr_cr, uvlinesize, h >> s->chroma_y_shift, uvsx, uvsy);
+        }
     }
     // FIXME h261 lowres loop filter
 }
@@ -2435,17 +2414,17 @@ void MPV_decode_mb_internal(MpegEncContext *s, DCTELEM block[12][64],
                     }else{
                         //chroma422
                         dct_linesize = uvlinesize << s->interlaced_dct;
-                        dct_offset =(s->interlaced_dct)? uvlinesize : uvlinesize*8;
+                        dct_offset =(s->interlaced_dct)? uvlinesize : uvlinesize*block_size;
 
                         add_dct(s, block[4], 4, dest_cb, dct_linesize);
                         add_dct(s, block[5], 5, dest_cr, dct_linesize);
                         add_dct(s, block[6], 6, dest_cb+dct_offset, dct_linesize);
                         add_dct(s, block[7], 7, dest_cr+dct_offset, dct_linesize);
                         if(!s->chroma_x_shift){//Chroma444
-                            add_dct(s, block[8], 8, dest_cb+8, dct_linesize);
-                            add_dct(s, block[9], 9, dest_cr+8, dct_linesize);
-                            add_dct(s, block[10], 10, dest_cb+8+dct_offset, dct_linesize);
-                            add_dct(s, block[11], 11, dest_cr+8+dct_offset, dct_linesize);
+                            add_dct(s, block[8], 8, dest_cb+block_size, dct_linesize);
+                            add_dct(s, block[9], 9, dest_cr+block_size, dct_linesize);
+                            add_dct(s, block[10], 10, dest_cb+block_size+dct_offset, dct_linesize);
+                            add_dct(s, block[11], 11, dest_cr+block_size+dct_offset, dct_linesize);
                         }
                     }
                 }//fi gray
@@ -2487,17 +2466,17 @@ void MPV_decode_mb_internal(MpegEncContext *s, DCTELEM block[12][64],
                     }else{
 
                         dct_linesize = uvlinesize << s->interlaced_dct;
-                        dct_offset =(s->interlaced_dct)? uvlinesize : uvlinesize*8;
+                        dct_offset =(s->interlaced_dct)? uvlinesize : uvlinesize*block_size;
 
                         s->dsp.idct_put(dest_cb,              dct_linesize, block[4]);
                         s->dsp.idct_put(dest_cr,              dct_linesize, block[5]);
                         s->dsp.idct_put(dest_cb + dct_offset, dct_linesize, block[6]);
                         s->dsp.idct_put(dest_cr + dct_offset, dct_linesize, block[7]);
                         if(!s->chroma_x_shift){//Chroma444
-                            s->dsp.idct_put(dest_cb + 8,              dct_linesize, block[8]);
-                            s->dsp.idct_put(dest_cr + 8,              dct_linesize, block[9]);
-                            s->dsp.idct_put(dest_cb + 8 + dct_offset, dct_linesize, block[10]);
-                            s->dsp.idct_put(dest_cr + 8 + dct_offset, dct_linesize, block[11]);
+                            s->dsp.idct_put(dest_cb + block_size,              dct_linesize, block[8]);
+                            s->dsp.idct_put(dest_cr + block_size,              dct_linesize, block[9]);
+                            s->dsp.idct_put(dest_cb + block_size + dct_offset, dct_linesize, block[10]);
+                            s->dsp.idct_put(dest_cr + block_size + dct_offset, dct_linesize, block[11]);
                         }
                     }
                 }//gray
@@ -2640,6 +2619,7 @@ void ff_mpeg_flush(AVCodecContext *avctx){
     s->current_picture_ptr = s->last_picture_ptr = s->next_picture_ptr = NULL;
 
     s->mb_x= s->mb_y= 0;
+    s->closed_gop= 0;
 
     s->parse_context.state= -1;
     s->parse_context.frame_start_found= 0;