Merge commit '54974c62982ae827becdbdb9b620b7ba75d079a0'
authorMichael Niedermayer <michaelni@gmx.at>
Sat, 16 Feb 2013 17:46:28 +0000 (18:46 +0100)
committerMichael Niedermayer <michaelni@gmx.at>
Sat, 16 Feb 2013 17:54:56 +0000 (18:54 +0100)
* commit '54974c62982ae827becdbdb9b620b7ba75d079a0':
  error_resilience: decouple ER from MpegEncContext

Conflicts:
libavcodec/error_resilience.c
libavcodec/h263dec.c
libavcodec/h264.c
libavcodec/mpegvideo.c
libavcodec/vc1dec.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>
15 files changed:
1  2 
libavcodec/error_resilience.c
libavcodec/error_resilience.h
libavcodec/h261dec.c
libavcodec/h263dec.c
libavcodec/h264.c
libavcodec/intrax8.c
libavcodec/mpeg12.c
libavcodec/mpeg4videodec.c
libavcodec/mpegvideo.c
libavcodec/mpegvideo.h
libavcodec/mpegvideo_enc.c
libavcodec/mss2.c
libavcodec/rv10.c
libavcodec/rv34.c
libavcodec/vc1dec.c

   * @param stride the number of MVs to get to the next row
   * @param mv_step the number of MVs per row or column in a macroblock
   */
- static void set_mv_strides(MpegEncContext *s, int *mv_step, int *stride)
+ static void set_mv_strides(ERContext *s, int *mv_step, int *stride)
  {
-     if (s->codec_id == AV_CODEC_ID_H264) {
-         H264Context *h = (void*)s;
+     if (s->avctx->codec_id == AV_CODEC_ID_H264) {
 -        assert(s->quarter_sample);
 +        av_assert0(s->quarter_sample);
          *mv_step = 4;
-         *stride  = h->b_stride;
+         *stride  = s->mb_width * 4;
      } else {
          *mv_step = 2;
          *stride  = s->b8_stride;
@@@ -184,70 -134,6 +134,70 @@@ static void guess_dc(ERContext *s, int1
                       int h, int stride, int is_luma)
  {
      int b_x, b_y;
-             int intra_j = IS_INTRA(s->current_picture.f.mb_type[mb_index_j]);
 +    int16_t  (*col )[4] = av_malloc(stride*h*sizeof( int16_t)*4);
 +    uint32_t (*dist)[4] = av_malloc(stride*h*sizeof(uint32_t)*4);
 +
 +    if(!col || !dist) {
 +        av_log(s->avctx, AV_LOG_ERROR, "guess_dc() is out of memory\n");
 +        goto fail;
 +    }
 +
 +    for(b_y=0; b_y<h; b_y++){
 +        int color= 1024;
 +        int distance= -1;
 +        for(b_x=0; b_x<w; b_x++){
 +            int mb_index_j= (b_x>>is_luma) + (b_y>>is_luma)*s->mb_stride;
 +            int error_j= s->error_status_table[mb_index_j];
-             int intra_j = IS_INTRA(s->current_picture.f.mb_type[mb_index_j]);
++            int intra_j = IS_INTRA(s->cur_pic->f.mb_type[mb_index_j]);
 +            if(intra_j==0 || !(error_j&ER_DC_ERROR)){
 +                color= dc[b_x + b_y*stride];
 +                distance= b_x;
 +            }
 +            col [b_x + b_y*stride][1]= color;
 +            dist[b_x + b_y*stride][1]= distance >= 0 ? b_x-distance : 9999;
 +        }
 +        color= 1024;
 +        distance= -1;
 +        for(b_x=w-1; b_x>=0; b_x--){
 +            int mb_index_j= (b_x>>is_luma) + (b_y>>is_luma)*s->mb_stride;
 +            int error_j= s->error_status_table[mb_index_j];
-             int intra_j = IS_INTRA(s->current_picture.f.mb_type[mb_index_j]);
++            int intra_j = IS_INTRA(s->cur_pic->f.mb_type[mb_index_j]);
 +            if(intra_j==0 || !(error_j&ER_DC_ERROR)){
 +                color= dc[b_x + b_y*stride];
 +                distance= b_x;
 +            }
 +            col [b_x + b_y*stride][0]= color;
 +            dist[b_x + b_y*stride][0]= distance >= 0 ? distance-b_x : 9999;
 +        }
 +    }
 +    for(b_x=0; b_x<w; b_x++){
 +        int color= 1024;
 +        int distance= -1;
 +        for(b_y=0; b_y<h; b_y++){
 +            int mb_index_j= (b_x>>is_luma) + (b_y>>is_luma)*s->mb_stride;
 +            int error_j= s->error_status_table[mb_index_j];
-             int intra_j = IS_INTRA(s->current_picture.f.mb_type[mb_index_j]);
++            int intra_j = IS_INTRA(s->cur_pic->f.mb_type[mb_index_j]);
 +            if(intra_j==0 || !(error_j&ER_DC_ERROR)){
 +                color= dc[b_x + b_y*stride];
 +                distance= b_y;
 +            }
 +            col [b_x + b_y*stride][3]= color;
 +            dist[b_x + b_y*stride][3]= distance >= 0 ? b_y-distance : 9999;
 +        }
 +        color= 1024;
 +        distance= -1;
 +        for(b_y=h-1; b_y>=0; b_y--){
 +            int mb_index_j= (b_x>>is_luma) + (b_y>>is_luma)*s->mb_stride;
 +            int error_j= s->error_status_table[mb_index_j];
++            int intra_j = IS_INTRA(s->cur_pic->f.mb_type[mb_index_j]);
 +            if(intra_j==0 || !(error_j&ER_DC_ERROR)){
 +                color= dc[b_x + b_y*stride];
 +                distance= b_y;
 +            }
 +            col [b_x + b_y*stride][2]= color;
 +            dist[b_x + b_y*stride][2]= distance >= 0 ? distance-b_y : 9999;
 +        }
 +    }
  
      for (b_y = 0; b_y < h; b_y++) {
          for (b_x = 0; b_x < w; b_x++) {
@@@ -445,14 -378,6 +395,14 @@@ static void guess_mv(ERContext *s
          fixed[mb_xy] = f;
          if (f == MV_FROZEN)
              num_avail++;
-         else if(s->last_picture.f.data[0] && s->last_picture.f.motion_val[0]){
++        else if(s->last_pic->f.data[0] && s->last_pic->f.motion_val[0]){
 +            const int mb_y= mb_xy / s->mb_stride;
 +            const int mb_x= mb_xy % s->mb_stride;
 +            const int mot_index= (mb_x + mb_y*mot_stride) * mot_step;
-             s->current_picture.f.motion_val[0][mot_index][0]= s->last_picture.f.motion_val[0][mot_index][0];
-             s->current_picture.f.motion_val[0][mot_index][1]= s->last_picture.f.motion_val[0][mot_index][1];
-             s->current_picture.f.ref_index[0][4*mb_xy]      = s->last_picture.f.ref_index[0][4*mb_xy];
++            s->cur_pic->f.motion_val[0][mot_index][0]= s->last_pic->f.motion_val[0][mot_index][0];
++            s->cur_pic->f.motion_val[0][mot_index][1]= s->last_pic->f.motion_val[0][mot_index][1];
++            s->cur_pic->f.ref_index[0][4*mb_xy]      = s->last_pic->f.ref_index[0][4*mb_xy];
 +        }
      }
  
      if ((!(s->avctx->error_concealment&FF_EC_GUESS_MVS)) ||
  
                      if (fixed[mb_xy] == MV_FROZEN)
                          continue;
-                     av_assert1(!IS_INTRA(s->current_picture.f.mb_type[mb_xy]));
-                     av_assert1(s->last_picture_ptr && s->last_picture_ptr->f.data[0]);
 -                    assert(!IS_INTRA(s->cur_pic->f.mb_type[mb_xy]));
 -                    assert(s->last_pic && s->last_pic->f.data[0]);
++                    av_assert1(!IS_INTRA(s->cur_pic->f.mb_type[mb_xy]));
++                    av_assert1(s->last_pic && s->last_pic->f.data[0]);
  
                      j = 0;
                      if (mb_x > 0             && fixed[mb_xy - 1]         == MV_FROZEN)
@@@ -799,14 -707,15 +732,16 @@@ static int is_intra_more_likely(ERConte
                  if (s->avctx->codec_id == AV_CODEC_ID_H264) {
                      // FIXME
                  } else {
-                     ff_thread_await_progress(&s->last_picture_ptr->f,
-                                              mb_y, 0);
+                     ff_thread_await_progress(&s->last_pic->f, mb_y, 0);
                  }
-                 is_intra_likely += s->dsp.sad[0](NULL, last_mb_ptr, mb_ptr                    , s->linesize, 16);
+                 is_intra_likely += s->dsp->sad[0](NULL, last_mb_ptr, mb_ptr,
+                                                  linesize[0], 16);
 +                // FIXME need await_progress() here
-                 is_intra_likely -= s->dsp.sad[0](NULL, last_mb_ptr, last_mb_ptr+s->linesize*16, s->linesize, 16);
+                 is_intra_likely -= s->dsp->sad[0](NULL, last_mb_ptr,
+                                                  last_mb_ptr + linesize[0] * 16,
+                                                  linesize[0], 16);
              } else {
-                 if (IS_INTRA(s->current_picture.f.mb_type[mb_xy]))
+                 if (IS_INTRA(s->cur_pic->f.mb_type[mb_xy]))
                     is_intra_likely++;
                  else
                     is_intra_likely--;
@@@ -914,23 -823,16 +850,17 @@@ void ff_er_frame_end(ERContext *s
  
      /* We do not support ER of field pictures yet,
       * though it should not crash if enabled. */
-     if (!s->err_recognition || s->error_count == 0 || s->avctx->lowres ||
+     if (!s->avctx->err_recognition || s->error_count == 0              ||
++        s->avctx->lowres                                               ||
          s->avctx->hwaccel                                              ||
          s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU          ||
-         s->picture_structure != PICT_FRAME                             ||
+         !s->cur_pic || s->cur_pic->field_picture                               ||
          s->error_count == 3 * s->mb_width *
                            (s->avctx->skip_top + s->avctx->skip_bottom)) {
          return;
--    };
-     if (   s->picture_structure == PICT_FRAME
-         && s->current_picture.f.linesize[0] != s->current_picture_ptr->f.linesize[0]) {
-         av_log(s->avctx, AV_LOG_ERROR, "Error concealment not possible, frame not fully initialized\n");
-         return;
 +    }
  
-     if (s->current_picture.f.motion_val[0] == NULL) {
+     if (s->cur_pic->f.motion_val[0] == NULL) {
          av_log(s->avctx, AV_LOG_ERROR, "Warning MVs not available\n");
  
          for (i = 0; i < 2; i++) {
                  end_ok = 0;
          }
      }
 -
 +#endif
      /* handle missing slices */
-     if (s->err_recognition & AV_EF_EXPLODE) {
+     if (s->avctx->err_recognition & AV_EF_EXPLODE) {
          int end_ok = 1;
  
          // FIXME + 100 hack
          if (error & ER_MV_ERROR)
              mv_error++;
      }
 -    av_log(s->avctx, AV_LOG_INFO, "concealing %d DC, %d AC, %d MV errors\n",
 -           dc_error, ac_error, mv_error);
 +    av_log(s->avctx, AV_LOG_INFO, "concealing %d DC, %d AC, %d MV errors in %c frame\n",
-            dc_error, ac_error, mv_error, av_get_picture_type_char(s->pict_type));
++           dc_error, ac_error, mv_error, av_get_picture_type_char(s->cur_pic->f.pict_type));
  
      is_intra_likely = is_intra_more_likely(s);
  
                      int time_pp = s->pp_time;
                      int time_pb = s->pb_time;
  
-                     ff_thread_await_progress(&s->next_picture_ptr->f, mb_y, 0);
-                     s->mv[0][0][0] = s->next_picture.f.motion_val[0][xy][0] *  time_pb            / time_pp;
-                     s->mv[0][0][1] = s->next_picture.f.motion_val[0][xy][1] *  time_pb            / time_pp;
-                     s->mv[1][0][0] = s->next_picture.f.motion_val[0][xy][0] * (time_pb - time_pp) / time_pp;
-                     s->mv[1][0][1] = s->next_picture.f.motion_val[0][xy][1] * (time_pb - time_pp) / time_pp;
 +                    av_assert0(s->avctx->codec_id != AV_CODEC_ID_H264);
+                     ff_thread_await_progress(&s->next_pic->f, mb_y, 0);
+                     s->mv[0][0][0] = s->next_pic->f.motion_val[0][xy][0] *  time_pb            / time_pp;
+                     s->mv[0][0][1] = s->next_pic->f.motion_val[0][xy][1] *  time_pb            / time_pp;
+                     s->mv[1][0][0] = s->next_pic->f.motion_val[0][xy][0] * (time_pb - time_pp) / time_pp;
+                     s->mv[1][0][1] = s->next_pic->f.motion_val[0][xy][1] * (time_pb - time_pp) / time_pp;
                  } else {
                      s->mv[0][0][0] = 0;
                      s->mv[0][0][1] = 0;
index 0000000,949c58f..b2318b7
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,74 +1,74 @@@
 - * This file is part of Libav.
+ /*
+  *
 - * Libav is free software; you can redistribute it and/or
++ * This file is part of FFmpeg.
+  *
 - * Libav is distributed in the hope that it will be useful,
++ * 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.
+  *
 - * License along with Libav; if not, write to the Free Software
++ * 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 FFmpeg; if not, write to the Free Software
+  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+  */
+ #ifndef AVCODEC_ERROR_RESILIENCE_H
+ #define AVCODEC_ERROR_RESILIENCE_H
+ ///< current MB is the first after a resync marker
+ #define VP_START               1
+ #define ER_AC_ERROR            2
+ #define ER_DC_ERROR            4
+ #define ER_MV_ERROR            8
+ #define ER_AC_END              16
+ #define ER_DC_END              32
+ #define ER_MV_END              64
+ #define ER_MB_ERROR (ER_AC_ERROR|ER_DC_ERROR|ER_MV_ERROR)
+ #define ER_MB_END   (ER_AC_END|ER_DC_END|ER_MV_END)
+ typedef struct ERContext {
+     AVCodecContext *avctx;
+     DSPContext *dsp;
+     int *mb_index2xy;
+     int mb_num;
+     int mb_width, mb_height;
+     int mb_stride;
+     int b8_stride;
+     int error_count, error_occurred;
+     uint8_t *error_status_table;
+     uint8_t *er_temp_buffer;
+     int16_t *dc_val[3];
+     uint8_t *mbskip_table;
+     uint8_t *mbintra_table;
+     int mv[2][4][2];
+     struct Picture *cur_pic;
+     struct Picture *last_pic;
+     struct Picture *next_pic;
+     uint16_t pp_time;
+     uint16_t pb_time;
+     int quarter_sample;
+     int partitioned_frame;
+     int ref_count;
+     void (*decode_mb)(void *opaque, int ref, int mv_dir, int mv_type,
+                       int (*mv)[2][4][2],
+                       int mb_x, int mb_y, int mb_intra, int mb_skipped);
+     void *opaque;
+ } ERContext;
+ void ff_er_frame_start(ERContext *s);
+ void ff_er_frame_end(ERContext *s);
+ void ff_er_add_slice(ERContext *s, int startx, int starty, int endx, int endy,
+                      int status);
+ #endif /* AVCODEC_ERROR_RESILIENCE_H */
Simple merge
@@@ -248,13 -242,13 +248,13 @@@ static int decode_slice(MpegEncContext 
                      return 0;
                  }else if(ret==SLICE_NOEND){
                      av_log(s->avctx, AV_LOG_ERROR, "Slice mismatch at MB: %d\n", xy);
-                     ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x+1, s->mb_y, ER_MB_END&part_mask);
+                     ff_er_add_slice(&s->er, s->resync_mb_x, s->resync_mb_y, s->mb_x+1, s->mb_y, ER_MB_END&part_mask);
 -                    return -1;
 +                    return AVERROR_INVALIDDATA;
                  }
                  av_log(s->avctx, AV_LOG_ERROR, "Error at MB: %d\n", xy);
-                 ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, ER_MB_ERROR&part_mask);
+                 ff_er_add_slice(&s->er, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, ER_MB_ERROR&part_mask);
  
 -                return -1;
 +                return AVERROR_INVALIDDATA;
              }
  
              ff_MPV_decode_mb(s, s->block);
              get_bits_left(&s->gb),
              show_bits(&s->gb, 24), s->padding_bug_score);
  
-     ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, ER_MB_END&part_mask);
+     ff_er_add_slice(&s->er, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, ER_MB_END&part_mask);
  
 -    return -1;
 +    return AVERROR_INVALIDDATA;
  }
  
  int ff_h263_decode_frame(AVCodecContext *avctx,
@@@ -662,11 -634,11 +662,11 @@@ retry
      }
  
      if (avctx->hwaccel) {
 -        if (avctx->hwaccel->start_frame(avctx, s->gb.buffer, s->gb.buffer_end - s->gb.buffer) < 0)
 -            return -1;
 +        if ((ret = avctx->hwaccel->start_frame(avctx, s->gb.buffer, s->gb.buffer_end - s->gb.buffer)) < 0)
 +            return ret;
      }
  
-     ff_er_frame_start(s);
+     ff_mpeg_er_frame_start(s);
  
      //the second part of the wmv2 header contains the MB skip bits which are stored in current_picture->mb_type
      //which is not available before ff_MPV_frame_start()
  
      if (s->msmpeg4_version && s->msmpeg4_version<4 && s->pict_type==AV_PICTURE_TYPE_I)
          if(!CONFIG_MSMPEG4_DECODER || ff_msmpeg4_decode_ext_header(s, buf_size) < 0){
-             s->error_status_table[s->mb_num-1]= ER_MB_ERROR;
+             s->er.error_status_table[s->mb_num - 1] = ER_MB_ERROR;
          }
  
 -    assert(s->bitstream_buffer_size==0);
 +    av_assert1(s->bitstream_buffer_size==0);
  frame_end:
 -    /* divx 5.01+ bistream reorder stuff */
 +    /* divx 5.01+ bitstream reorder stuff */
      if(s->codec_id==AV_CODEC_ID_MPEG4 && s->divx_packed){
 -        int current_pos= get_bits_count(&s->gb)>>3;
 +        int current_pos= s->gb.buffer == s->bitstream_buffer ? 0 : (get_bits_count(&s->gb)>>3);
          int startcode_found=0;
  
 -        if(buf_size - current_pos > 5){
 +        if(buf_size - current_pos > 7){
              int i;
 -            for(i=current_pos; i<buf_size-3; i++){
 +            for(i=current_pos; i<buf_size-4; i++){
                  if(buf[i]==0 && buf[i+1]==0 && buf[i+2]==1 && buf[i+3]==0xB6){
 -                    startcode_found=1;
 +                    startcode_found=!(buf[i+4]&0x40);
                      break;
                  }
              }
      }
  
  intrax8_decoded:
-     ff_er_frame_end(s);
+     ff_er_frame_end(&s->er);
  
      if (avctx->hwaccel) {
 -        if (avctx->hwaccel->end_frame(avctx) < 0)
 -            return -1;
 +        if ((ret = avctx->hwaccel->end_frame(avctx)) < 0)
 +            return ret;
      }
  
      ff_MPV_frame_end(s);
@@@ -85,12 -78,33 +85,48 @@@ static const enum AVPixelFormat hwaccel
      AV_PIX_FMT_NONE
  };
  
 -    assert(ref >= 0);
 +int avpriv_h264_has_num_reorder_frames(AVCodecContext *avctx)
 +{
 +    H264Context *h = avctx->priv_data;
 +    return h ? h->sps.num_reorder_frames : 0;
 +}
 +
+ static void h264_er_decode_mb(void *opaque, int ref, int mv_dir, int mv_type,
+                               int (*mv)[2][4][2],
+                               int mb_x, int mb_y, int mb_intra, int mb_skipped)
+ {
+     H264Context    *h = opaque;
+     MpegEncContext *s = &h->s;
+     s->mb_x  = mb_x;
+     s->mb_y  = mb_y;
+     h->mb_xy = s->mb_x + s->mb_y * s->mb_stride;
+     memset(h->non_zero_count_cache, 0, sizeof(h->non_zero_count_cache));
 -                   pack16to32(s->mv[0][0][0], s->mv[0][0][1]), 4);
 -    assert(!FRAME_MBAFF);
++    av_assert1(ref >= 0);
+     /* FIXME: It is possible albeit uncommon that slice references
+      * differ between slices. We take the easy approach and ignore
+      * it for now. If this turns out to have any relevance in
+      * practice then correct remapping should be added. */
+     if (ref >= h->ref_count[0])
+         ref = 0;
++    if (!h->ref_list[0][ref].f.data[0]) {
++        av_log(s->avctx, AV_LOG_DEBUG, "Reference not available for error concealing\n");
++        ref = 0;
++    }
++    if ((h->ref_list[0][ref].f.reference&3) != 3) {
++        av_log(s->avctx, AV_LOG_DEBUG, "Reference invalid\n");
++        return;
++    }
+     fill_rectangle(&s->current_picture.f.ref_index[0][4 * h->mb_xy],
+                    2, 2, 2, ref, 1);
+     fill_rectangle(&h->ref_cache[0][scan8[0]], 4, 4, 8, ref, 1);
+     fill_rectangle(h->mv_cache[0][scan8[0]], 4, 4, 8,
++                   pack16to32((*mv)[0][0][0], (*mv)[0][0][1]), 4);
++    h->mb_mbaff =
++    h->mb_field_decoding_flag = 0;
+     ff_h264_hl_decode_mb(h);
+ }
  /**
   * Check if the top & left blocks are available if needed and
   * change the dc mode so it only uses the available blocks.
@@@ -1353,9 -1329,7 +1392,10 @@@ int ff_h264_frame_start(H264Context *h
  
      if (ff_MPV_frame_start(s, s->avctx) < 0)
          return -1;
-     ff_er_frame_start(s);
 +    if(!h->sync)
 +        avpriv_color_frame(&h->s.current_picture_ptr->f, c);
++
+     ff_mpeg_er_frame_start(s);
      /*
       * ff_MPV_frame_start uses pict_type to derive key_frame.
       * This is incorrect for H.264; IDR markings must be used.
@@@ -2377,8 -2369,8 +2417,8 @@@ static int field_end(H264Context *h, in
       * past end by one (callers fault) and resync_mb_y != 0
       * causes problems for the first MB line, too.
       */
 -    if (!FIELD_PICTURE)
 +    if (!FIELD_PICTURE && h->current_slice && !h->sps.new)
-         ff_er_frame_end(s);
+         ff_er_frame_end(&s->er);
  
      ff_MPV_frame_end(s);
  
@@@ -3861,16 -3804,15 +3912,16 @@@ static int decode_slice(struct AVCodecC
                      tprintf(s->avctx, "slice end %d %d\n",
                              get_bits_count(&s->gb), s->gb.size_in_bits);
  
 -                    if (get_bits_left(&s->gb) == 0) {
 +                    if (   get_bits_left(&s->gb) == 0
 +                        || get_bits_left(&s->gb) > 0 && !(s->avctx->err_recognition & AV_EF_AGGRESSIVE)) {
-                         ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y,
+                         er_add_slice(h, s->resync_mb_x, s->resync_mb_y,
                                          s->mb_x - 1, s->mb_y,
                                          ER_MB_END);
  
                          return 0;
                      } else {
-                         ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y,
+                         er_add_slice(h, s->resync_mb_x, s->resync_mb_y,
 -                                        s->mb_x - 1, s->mb_y,
 +                                        s->mb_x, s->mb_y,
                                          ER_MB_END);
  
                          return -1;
@@@ -3923,8 -3864,7 +3974,8 @@@ static int execute_decode_slices(H264Co
          for (i = 1; i < context_count; i++) {
              hx                    = h->thread_context[i];
              hx->s.err_recognition = avctx->err_recognition;
-             hx->s.error_count     = 0;
+             hx->s.er.error_count  = 0;
 +            hx->x264_build        = h->x264_build;
          }
  
          avctx->execute(avctx, decode_slice, h->thread_context,
Simple merge
@@@ -2273,13 -2210,12 +2273,13 @@@ static int decode_chunks(AVCodecContex
  
                      avctx->execute(avctx, slice_decode_thread,  &s2->thread_context[0], NULL, s->slice_count, sizeof(void*));
                      for (i = 0; i < s->slice_count; i++)
-                         s2->error_count += s2->thread_context[i]->error_count;
+                         s2->er.error_count += s2->thread_context[i]->er.error_count;
                  }
  
 -                if (CONFIG_MPEG_VDPAU_DECODER && avctx->codec->capabilities & CODEC_CAP_HWACCEL_VDPAU)
 +                if (CONFIG_VDPAU && uses_vdpau(avctx))
                      ff_vdpau_mpeg_picture_complete(s2, buf, buf_size, s->slice_count);
  
 +
                  if (slice_end(avctx, picture)) {
                      if (s2->last_picture_ptr || s2->low_delay) //FIXME merge with the stuff in mpeg_decode_slice
                          *got_output = 1;
Simple merge
@@@ -145,9 -147,36 +145,36 @@@ const enum AVPixelFormat ff_hwaccel_pix
      AV_PIX_FMT_NONE
  };
  
 -const uint8_t *avpriv_mpv_find_start_code(const uint8_t *restrict p,
+ static void mpeg_er_decode_mb(void *opaque, int ref, int mv_dir, int mv_type,
+                               int (*mv)[2][4][2],
+                               int mb_x, int mb_y, int mb_intra, int mb_skipped)
+ {
+     MpegEncContext *s = opaque;
+     s->mv_dir     = mv_dir;
+     s->mv_type    = mv_type;
+     s->mb_intra   = mb_intra;
+     s->mb_skipped = mb_skipped;
+     s->mb_x       = mb_x;
+     s->mb_y       = mb_y;
+     memcpy(s->mv, mv, sizeof(*mv));
+     ff_init_block_index(s);
+     ff_update_block_index(s);
+     s->dsp.clear_blocks(s->block[0]);
+     s->dest[0] = s->current_picture.f.data[0] + (s->mb_y *  16                       * s->linesize)   + s->mb_x *  16;
+     s->dest[1] = s->current_picture.f.data[1] + (s->mb_y * (16 >> s->chroma_y_shift) * s->uvlinesize) + s->mb_x * (16 >> s->chroma_x_shift);
+     s->dest[2] = s->current_picture.f.data[2] + (s->mb_y * (16 >> s->chroma_y_shift) * s->uvlinesize) + s->mb_x * (16 >> s->chroma_x_shift);
+     assert(ref == 0);
+     ff_MPV_decode_mb(s, s->block);
+ }
 +const uint8_t *avpriv_mpv_find_start_code(const uint8_t *av_restrict p,
                                            const uint8_t *end,
 -                                          uint32_t * restrict state)
 +                                          uint32_t *av_restrict state)
  {
      int i;
  
@@@ -854,7 -922,17 +914,7 @@@ static int init_context_frame(MpegEncCo
      FF_ALLOCZ_OR_GOTO(s->avctx, s->mbskip_table, mb_array_size + 2, fail);
      // Note the + 1 is for  a quicker mpeg4 slice_end detection
  
-     return 0;
 -    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);
 -    }
 -
+     return init_er(s);
  fail:
      return AVERROR(ENOMEM);
  }
@@@ -1023,11 -1113,10 +1083,11 @@@ static int free_context_frame(MpegEncCo
  
      av_freep(&s->mbskip_table);
  
-     av_freep(&s->error_status_table);
-     av_freep(&s->er_temp_buffer);
+     av_freep(&s->er.error_status_table);
+     av_freep(&s->er.er_temp_buffer);
      av_freep(&s->mb_index2xy);
      av_freep(&s->lambda_table);
 +
      av_freep(&s->cplx_tab);
      av_freep(&s->bits_tab);
  
@@@ -1595,7 -1648,7 +1655,7 @@@ void ff_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 || !(s->avctx->codec->capabilities&CODEC_CAP_DRAW_HORIZ_BAND)) &&
 -   } else if ((s->er.error_count || s->encoding) &&
++   } else if ((s->er.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 &&
@@@ -30,8 -30,8 +30,9 @@@
  
  #include "avcodec.h"
  #include "dsputil.h"
+ #include "error_resilience.h"
  #include "get_bits.h"
 +#include "h264chroma.h"
  #include "put_bits.h"
  #include "ratecontrol.h"
  #include "parser.h"
@@@ -801,12 -774,9 +788,10 @@@ int ff_mpeg_update_thread_context(AVCod
  const uint8_t *avpriv_mpv_find_start_code(const uint8_t *p, const uint8_t *end, uint32_t *state);
  void ff_set_qscale(MpegEncContext * s, int qscale);
  
- void ff_er_frame_start(MpegEncContext *s);
- void ff_er_frame_end(MpegEncContext *s);
- void ff_er_add_slice(MpegEncContext *s, int startx, int starty, int endx, int endy, int status);
+ void ff_mpeg_er_frame_start(MpegEncContext *s);
  
  int ff_dct_common_init(MpegEncContext *s);
 +int ff_dct_encode_init(MpegEncContext *s);
  void ff_convert_matrix(DSPContext *dsp, int (*qmat)[64], uint16_t (*qmat16)[2][64],
                         const uint16_t *quant_matrix, int bias, int qmin, int qmax, int intra);
  int ff_dct_quantize_c(MpegEncContext *s, int16_t *block, int n, int qscale, int *overflow);
Simple merge
Simple merge
Simple merge
@@@ -1649,9 -1644,9 +1649,9 @@@ int ff_rv34_decode_frame(AVCodecContex
      /* first slice */
      if (si.start == 0) {
          if (s->mb_num_left > 0) {
 -            av_log(avctx, AV_LOG_ERROR, "New frame but still %d MB left.",
 +            av_log(avctx, AV_LOG_ERROR, "New frame but still %d MB left.\n",
                     s->mb_num_left);
-             ff_er_frame_end(s);
+             ff_er_frame_end(&s->er);
              ff_MPV_frame_end(s);
          }
  
@@@ -5603,47 -5551,14 +5603,47 @@@ static int vc1_decode_frame(AVCodecCont
          &&s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU)
          ff_vdpau_vc1_decode_picture(s, buf_start, (buf + buf_size) - buf_start);
      else if (avctx->hwaccel) {
 -        if (avctx->hwaccel->start_frame(avctx, buf, buf_size) < 0)
 -            goto err;
 -        if (avctx->hwaccel->decode_slice(avctx, buf_start, (buf + buf_size) - buf_start) < 0)
 -            goto err;
 -        if (avctx->hwaccel->end_frame(avctx) < 0)
 -            goto err;
 +        if (v->field_mode && buf_start_second_field) {
 +            // decode first field
 +            s->picture_structure = PICT_BOTTOM_FIELD - v->tff;
 +            if (avctx->hwaccel->start_frame(avctx, buf_start, buf_start_second_field - buf_start) < 0)
 +                goto err;
 +            if (avctx->hwaccel->decode_slice(avctx, buf_start, buf_start_second_field - buf_start) < 0)
 +                goto err;
 +            if (avctx->hwaccel->end_frame(avctx) < 0)
 +                goto err;
 +
 +            // decode second field
 +            s->gb = slices[n_slices1 + 1].gb;
 +            s->picture_structure = PICT_TOP_FIELD + v->tff;
 +            v->second_field = 1;
 +            v->pic_header_flag = 0;
 +            if (ff_vc1_parse_frame_header_adv(v, &s->gb) < 0) {
 +                av_log(avctx, AV_LOG_ERROR, "parsing header for second field failed");
 +                goto err;
 +            }
 +            v->s.current_picture_ptr->f.pict_type = v->s.pict_type;
 +
 +            if (avctx->hwaccel->start_frame(avctx, buf_start_second_field, (buf + buf_size) - buf_start_second_field) < 0)
 +                goto err;
 +            if (avctx->hwaccel->decode_slice(avctx, buf_start_second_field, (buf + buf_size) - buf_start_second_field) < 0)
 +                goto err;
 +            if (avctx->hwaccel->end_frame(avctx) < 0)
 +                goto err;
 +        } else {
 +            s->picture_structure = PICT_FRAME;
 +            if (avctx->hwaccel->start_frame(avctx, buf_start, (buf + buf_size) - buf_start) < 0)
 +                goto err;
 +            if (avctx->hwaccel->decode_slice(avctx, buf_start, (buf + buf_size) - buf_start) < 0)
 +                goto err;
 +            if (avctx->hwaccel->end_frame(avctx) < 0)
 +                goto err;
 +        }
      } else {
-         ff_er_frame_start(s);
 +        if (v->fcm == ILACE_FRAME && s->pict_type == AV_PICTURE_TYPE_B)
 +            goto err; // This codepath is still incomplete thus it is disabled
 +
+         ff_mpeg_er_frame_start(s);
  
          v->bits = buf_size * 8;
          v->end_mb_x = s->mb_width;
                  get_bits_count(&s->gb), s->gb.size_in_bits);
  //  if (get_bits_count(&s->gb) > buf_size * 8)
  //      return -1;
-         if(s->error_occurred && s->pict_type == AV_PICTURE_TYPE_B)
 -        ff_er_frame_end(&s->er);
++        if(s->er.error_occurred && s->pict_type == AV_PICTURE_TYPE_B)
 +            goto err;
 +        if(!v->field_mode)
-             ff_er_frame_end(s);
++            ff_er_frame_end(&s->er);
      }
  
      ff_MPV_frame_end(s);