Merge commit '51d8725a6e4c7f989d6f0f38b59cb54a2d72846c'
authorMichael Niedermayer <michaelni@gmx.at>
Sat, 21 Mar 2015 20:33:27 +0000 (21:33 +0100)
committerMichael Niedermayer <michaelni@gmx.at>
Sat, 21 Mar 2015 20:33:27 +0000 (21:33 +0100)
* commit '51d8725a6e4c7f989d6f0f38b59cb54a2d72846c':
  h264: use the main H264Context as the parent for all slice contexts

Conflicts:
libavcodec/h264.c
libavcodec/h264.h
libavcodec/h264_slice.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>
1  2 
libavcodec/h264.c
libavcodec/h264.h
libavcodec/h264_slice.c

@@@ -1506,8 -1481,8 +1504,8 @@@ static int decode_nal_units(H264Contex
  
              if (h->avctx->debug & FF_DEBUG_STARTCODE)
                  av_log(h->avctx, AV_LOG_DEBUG,
 -                       "NAL %d at %d/%d length %d\n",
 -                       h->nal_unit_type, buf_index, buf_size, dst_length);
 +                       "NAL %d/%d at %d/%d length %d\n",
-                        hx->nal_unit_type, hx->nal_ref_idc, buf_index, buf_size, dst_length);
++                       h->nal_unit_type, h->nal_ref_idc, buf_index, buf_size, dst_length);
  
              if (h->is_avc && (nalsize != consumed) && nalsize)
                  av_log(h->avctx, AV_LOG_DEBUG,
                  continue;
  
  again:
 -            /* Ignore every NAL unit type except PPS and SPS during extradata
 +            if (   (!(avctx->active_thread_type & FF_THREAD_FRAME) || nals_needed >= nal_index)
 +                && !h->current_slice)
 +                h->au_pps_id = -1;
 +            /* Ignore per frame NAL unit type during extradata
               * parsing. Decoding slices is not possible in codec init
               * with frame-mt */
 -            if (parse_extradata && HAVE_THREADS &&
 -                (h->avctx->active_thread_type & FF_THREAD_FRAME) &&
 -                (h->nal_unit_type != NAL_PPS &&
 -                 h->nal_unit_type != NAL_SPS)) {
 -                if (h->nal_unit_type < NAL_AUD ||
 -                    h->nal_unit_type > NAL_AUXILIARY_SLICE)
 -                    av_log(avctx, AV_LOG_INFO,
 -                           "Ignoring NAL unit %d during extradata parsing\n",
 +            if (parse_extradata) {
-                 switch (hx->nal_unit_type) {
++                switch (h->nal_unit_type) {
 +                case NAL_IDR_SLICE:
 +                case NAL_SLICE:
 +                case NAL_DPA:
 +                case NAL_DPB:
 +                case NAL_DPC:
 +                    av_log(h->avctx, AV_LOG_WARNING,
 +                           "Ignoring NAL %d in global header/extradata\n",
-                            hx->nal_unit_type);
+                            h->nal_unit_type);
 -                h->nal_unit_type = NAL_FF_IGNORE;
 +                    // fall through to next case
 +                case NAL_AUXILIARY_SLICE:
-                     hx->nal_unit_type = NAL_FF_IGNORE;
++                    h->nal_unit_type = NAL_FF_IGNORE;
 +                }
              }
 +
              err = 0;
-             switch (hx->nal_unit_type) {
 +
+             switch (h->nal_unit_type) {
              case NAL_IDR_SLICE:
 +                if ((ptr[0] & 0xFC) == 0x98) {
 +                    av_log(h->avctx, AV_LOG_ERROR, "Invalid inter IDR frame\n");
 +                    h->next_outputed_poc = INT_MIN;
 +                    ret = -1;
 +                    goto end;
 +                }
                  if (h->nal_unit_type != NAL_IDR_SLICE) {
                      av_log(h->avctx, AV_LOG_ERROR,
                             "Invalid mix of idr and non-idr slices\n");
              case NAL_SLICE:
                  init_get_bits(&sl->gb, ptr, bit_length);
  
-                 if ((err = ff_h264_decode_slice_header(hx, sl, h)))
+                 if ((err = ff_h264_decode_slice_header(h, sl)))
                      break;
  
 -                if (h->sei_recovery_frame_cnt >= 0 && h->recovery_frame < 0) {
 -                    h->recovery_frame = (h->frame_num + h->sei_recovery_frame_cnt) &
 -                                        ((1 << h->sps.log2_max_frame_num) - 1);
 +                if (h->sei_recovery_frame_cnt >= 0) {
 +                    if (h->frame_num != h->sei_recovery_frame_cnt || sl->slice_type_nos != AV_PICTURE_TYPE_I)
 +                        h->valid_recovery_point = 1;
 +
 +                    if (   h->recovery_frame < 0
 +                        || ((h->recovery_frame - h->frame_num) & ((1 << h->sps.log2_max_frame_num)-1)) > h->sei_recovery_frame_cnt) {
 +                        h->recovery_frame = (h->frame_num + h->sei_recovery_frame_cnt) &
 +                                            ((1 << h->sps.log2_max_frame_num) - 1);
 +
 +                        if (!h->valid_recovery_point)
 +                            h->recovery_frame = h->frame_num;
 +                    }
                  }
  
                  h->cur_pic_ptr->f.key_frame |=
-                     (hx->nal_unit_type == NAL_IDR_SLICE);
 -                    (h->nal_unit_type == NAL_IDR_SLICE) ||
 -                    (h->sei_recovery_frame_cnt >= 0);
++                    (h->nal_unit_type == NAL_IDR_SLICE);
  
-                 if (hx->nal_unit_type == NAL_IDR_SLICE ||
+                 if (h->nal_unit_type == NAL_IDR_SLICE ||
                      h->recovery_frame == h->frame_num) {
                      h->recovery_frame         = -1;
                      h->cur_pic_ptr->recovered = 1;
                  }
                  // If we have an IDR, all frames after it in decoded order are
                  // "recovered".
-                 if (hx->nal_unit_type == NAL_IDR_SLICE)
+                 if (h->nal_unit_type == NAL_IDR_SLICE)
                      h->frame_recovered |= FRAME_RECOVERED_IDR;
 +                h->frame_recovered |= 3*!!(avctx->flags2 & CODEC_FLAG2_SHOW_ALL);
 +                h->frame_recovered |= 3*!!(avctx->flags & CODEC_FLAG_OUTPUT_CORRUPT);
 +#if 1
 +                h->cur_pic_ptr->recovered |= h->frame_recovered;
 +#else
                  h->cur_pic_ptr->recovered |= !!(h->frame_recovered & FRAME_RECOVERED_IDR);
 +#endif
  
                  if (h->current_slice == 1) {
                      if (!(avctx->flags2 & CODEC_FLAG2_CHUNKS))
                  context_count = 0;
              }
  
 -            if (err < 0) {
 -                av_log(h->avctx, AV_LOG_ERROR, "decode_slice_header error\n");
 +            if (err < 0 || err == SLICE_SKIPED) {
 +                if (err < 0)
 +                    av_log(h->avctx, AV_LOG_ERROR, "decode_slice_header error\n");
                  sl->ref_count[0] = sl->ref_count[1] = sl->list_count = 0;
 -            } else if (err == 1) {
 +            } else if (err == SLICE_SINGLETHREAD) {
-                 /* Slice could not be decoded in parallel mode, copy down
-                  * NAL unit stuff to context 0 and restart. Note that
-                  * rbsp_buffer is not transferred, but since we no longer
+                 /* Slice could not be decoded in parallel mode, restart. Note
+                  * that rbsp_buffer is not transferred, but since we no longer
                   * run in parallel mode this should not be an issue. */
-                 h->nal_unit_type = hx->nal_unit_type;
-                 h->nal_ref_idc   = hx->nal_ref_idc;
-                 hx               = h;
                  sl               = &h->slice_ctx[0];
                  goto again;
              }
@@@ -1171,10 -1070,7 +1171,10 @@@ int ff_init_poc(H264Context *h, int pic
  int ff_pred_weight_table(H264Context *h, H264SliceContext *sl);
  int ff_set_ref_count(H264Context *h, H264SliceContext *sl);
  
- int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl, H264Context *h0);
+ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl);
 +#define SLICE_SINGLETHREAD 1
 +#define SLICE_SKIPED 2
 +
  int ff_h264_execute_decode_slices(H264Context *h, unsigned context_count);
  int ff_h264_update_thread_context(AVCodecContext *dst,
                                    const AVCodecContext *src);
@@@ -977,35 -904,7 +977,7 @@@ static void init_scan_tables(H264Contex
      }
  }
  
- /**
-  * Replicate H264 "master" context to thread contexts.
-  */
- static int clone_slice(H264Context *dst, H264Context *src)
- {
-     memcpy(dst->block_offset, src->block_offset, sizeof(dst->block_offset));
-     dst->cur_pic_ptr = src->cur_pic_ptr;
-     dst->cur_pic     = src->cur_pic;
-     dst->linesize    = src->linesize;
-     dst->uvlinesize  = src->uvlinesize;
-     dst->first_field = src->first_field;
-     dst->prev_poc_msb          = src->prev_poc_msb;
-     dst->prev_poc_lsb          = src->prev_poc_lsb;
-     dst->prev_frame_num_offset = src->prev_frame_num_offset;
-     dst->prev_frame_num        = src->prev_frame_num;
-     dst->short_ref_count       = src->short_ref_count;
-     memcpy(dst->short_ref,        src->short_ref,        sizeof(dst->short_ref));
-     memcpy(dst->long_ref,         src->long_ref,         sizeof(dst->long_ref));
-     memcpy(dst->default_ref_list, src->default_ref_list, sizeof(dst->default_ref_list));
-     memcpy(dst->dequant4_coeff,   src->dequant4_coeff,   sizeof(src->dequant4_coeff));
-     memcpy(dst->dequant8_coeff,   src->dequant8_coeff,   sizeof(src->dequant8_coeff));
-     return 0;
- }
 -static enum AVPixelFormat get_pixel_format(H264Context *h)
 +static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback)
  {
  #define HWACCEL_MAX (CONFIG_H264_DXVA2_HWACCEL + \
                       CONFIG_H264_VAAPI_HWACCEL + \
@@@ -1286,21 -1135,18 +1256,21 @@@ int ff_h264_decode_slice_header(H264Con
      unsigned int pps_id;
      int ret;
      unsigned int slice_type, tmp, i, j;
 -    int default_ref_list_done = 0;
      int last_pic_structure, last_pic_droppable;
 +    int must_reinit;
      int needs_reinit = 0;
      int field_pic_flag, bottom_field_flag;
-     int first_slice = h == h0 && !h0->current_slice;
++    int first_slice = sl == h->slice_ctx && !h->current_slice;
 +    int frame_num, picture_structure, droppable;
 +    PPS *pps;
  
      h->qpel_put = h->h264qpel.put_h264_qpel_pixels_tab;
      h->qpel_avg = h->h264qpel.avg_h264_qpel_pixels_tab;
  
 -    first_mb_in_slice = get_ue_golomb(&sl->gb);
 +    first_mb_in_slice = get_ue_golomb_long(&sl->gb);
  
      if (first_mb_in_slice == 0) { // FIXME better field boundary detection
-         if (h0->current_slice && h->cur_pic_ptr && FIELD_PICTURE(h)) {
+         if (h->current_slice && h->cur_pic_ptr && FIELD_PICTURE(h)) {
              ff_h264_field_end(h, sl, 1);
          }
  
          sl->slice_type_fixed = 0;
  
      slice_type = golomb_to_pict_type[slice_type];
 -    if (slice_type == AV_PICTURE_TYPE_I ||
 -        (h->current_slice != 0 && slice_type == h->last_slice_type)) {
 -        default_ref_list_done = 1;
 -    }
++
      sl->slice_type     = slice_type;
      sl->slice_type_nos = slice_type & 3;
  
                 pps_id);
          return AVERROR_INVALIDDATA;
      }
-     if (h0->au_pps_id >= 0 && pps_id != h0->au_pps_id) {
 -    h->pps = *h->pps_buffers[pps_id];
++    if (h->au_pps_id >= 0 && pps_id != h->au_pps_id) {
 +        av_log(h->avctx, AV_LOG_ERROR,
 +               "PPS change from %d to %d forbidden\n",
-                h0->au_pps_id, pps_id);
++               h->au_pps_id, pps_id);
 +        return AVERROR_INVALIDDATA;
 +    }
  
-     pps = h0->pps_buffers[pps_id];
 -    if (!h->sps_buffers[h->pps.sps_id]) {
++    pps = h->pps_buffers[pps_id];
 +
-     if (!h0->sps_buffers[pps->sps_id]) {
++    if (!h->sps_buffers[pps->sps_id]) {
          av_log(h->avctx, AV_LOG_ERROR,
                 "non-existing SPS %u referenced\n",
                 h->pps.sps_id);
          return AVERROR_INVALIDDATA;
      }
-         h->pps = *h0->pps_buffers[pps_id];
 +    if (first_slice)
++        h->pps = *h->pps_buffers[pps_id];
  
 -    if (h->pps.sps_id != h->sps.sps_id ||
 -        h->sps_buffers[h->pps.sps_id]->new) {
 -        h->sps_buffers[h->pps.sps_id]->new = 0;
 +    if (pps->sps_id != h->sps.sps_id ||
 +        pps->sps_id != h->current_sps_id ||
-         h0->sps_buffers[pps->sps_id]->new) {
++        h->sps_buffers[pps->sps_id]->new) {
 +
 +        if (!first_slice) {
 +            av_log(h->avctx, AV_LOG_ERROR,
 +               "SPS changed in the middle of the frame\n");
 +            return AVERROR_INVALIDDATA;
 +        }
  
-         h->sps = *h0->sps_buffers[h->pps.sps_id];
+         h->sps = *h->sps_buffers[h->pps.sps_id];
  
 +        if (h->mb_width  != h->sps.mb_width ||
 +            h->mb_height != h->sps.mb_height * (2 - h->sps.frame_mbs_only_flag) ||
 +            h->avctx->bits_per_raw_sample != h->sps.bit_depth_luma ||
 +            h->cur_chroma_format_idc != h->sps.chroma_format_idc
 +        )
 +            needs_reinit = 1;
 +
          if (h->bit_depth_luma    != h->sps.bit_depth_luma ||
              h->chroma_format_idc != h->sps.chroma_format_idc) {
              h->bit_depth_luma    = h->sps.bit_depth_luma;
      h->avctx->level   = h->sps.level_idc;
      h->avctx->refs    = h->sps.ref_frame_count;
  
 -    if (h->mb_width  != h->sps.mb_width ||
 -        h->mb_height != h->sps.mb_height * (2 - h->sps.frame_mbs_only_flag))
 -        needs_reinit = 1;
 +    must_reinit = (h->context_initialized &&
 +                    (   16*h->sps.mb_width != h->avctx->coded_width
 +                     || 16*h->sps.mb_height * (2 - h->sps.frame_mbs_only_flag) != h->avctx->coded_height
 +                     || h->avctx->bits_per_raw_sample != h->sps.bit_depth_luma
 +                     || h->cur_chroma_format_idc != h->sps.chroma_format_idc
 +                     || h->mb_width  != h->sps.mb_width
 +                     || h->mb_height != h->sps.mb_height * (2 - h->sps.frame_mbs_only_flag)
 +                    ));
-     if (non_j_pixfmt(h0->avctx->pix_fmt) != non_j_pixfmt(get_pixel_format(h0, 0)))
++    if (non_j_pixfmt(h->avctx->pix_fmt) != non_j_pixfmt(get_pixel_format(h, 0)))
 +        must_reinit = 1;
 +
 +    if (first_slice && av_cmp_q(h->sps.sar, h->avctx->sample_aspect_ratio))
 +        must_reinit = 1;
  
      h->mb_width  = h->sps.mb_width;
      h->mb_height = h->sps.mb_height * (2 - h->sps.frame_mbs_only_flag);
          }
      }
  
 -    if (h->context_initialized && needs_reinit) {
 +    if (h->context_initialized &&
 +        (must_reinit || needs_reinit)) {
-         if (h != h0) {
+         if (sl != h->slice_ctx) {
              av_log(h->avctx, AV_LOG_ERROR,
                     "changing width %d -> %d / height %d -> %d on "
                     "slice %d\n",
          }
      }
  
 -    if (sl == h->slice_ctx && h->dequant_coeff_pps != pps_id) {
 +    if (first_slice && h->dequant_coeff_pps != pps_id) {
          h->dequant_coeff_pps = pps_id;
 -        h264_init_dequant_tables(h);
 +        ff_h264_init_dequant_tables(h);
      }
  
 -    h->frame_num = get_bits(&sl->gb, h->sps.log2_max_frame_num);
 +    frame_num = get_bits(&sl->gb, h->sps.log2_max_frame_num);
 +    if (!first_slice) {
-         if (h0->frame_num != frame_num) {
++        if (h->frame_num != frame_num) {
 +            av_log(h->avctx, AV_LOG_ERROR, "Frame num change from %d to %d\n",
-                    h0->frame_num, frame_num);
++                   h->frame_num, frame_num);
 +            return AVERROR_INVALIDDATA;
 +        }
 +    }
  
      sl->mb_mbaff       = 0;
      h->mb_aff_frame    = 0;
-     last_pic_structure = h0->picture_structure;
-     last_pic_droppable = h0->droppable;
+     last_pic_structure = h->picture_structure;
+     last_pic_droppable = h->droppable;
 -    h->droppable       = h->nal_ref_idc == 0;
 +    droppable          = h->nal_ref_idc == 0;
      if (h->sps.frame_mbs_only_flag) {
 -        h->picture_structure = PICT_FRAME;
 +        picture_structure = PICT_FRAME;
      } else {
 +        if (!h->sps.direct_8x8_inference_flag && slice_type == AV_PICTURE_TYPE_B) {
 +            av_log(h->avctx, AV_LOG_ERROR, "This stream was generated by a broken encoder, invalid 8x8 inference\n");
 +            return -1;
 +        }
          field_pic_flag = get_bits1(&sl->gb);
 +
          if (field_pic_flag) {
              bottom_field_flag = get_bits1(&sl->gb);
 -            h->picture_structure = PICT_TOP_FIELD + bottom_field_flag;
 +            picture_structure = PICT_TOP_FIELD + bottom_field_flag;
          } else {
 -            h->picture_structure = PICT_FRAME;
 +            picture_structure = PICT_FRAME;
              h->mb_aff_frame      = h->sps.mb_aff;
          }
      }
-     if (h0->current_slice) {
 -    sl->mb_field_decoding_flag = h->picture_structure != PICT_FRAME;
 -
 -    if (h->current_slice != 0) {
 -        if (last_pic_structure != h->picture_structure ||
 -            last_pic_droppable != h->droppable) {
++    if (h->current_slice) {
 +        if (last_pic_structure != picture_structure ||
 +            last_pic_droppable != droppable) {
              av_log(h->avctx, AV_LOG_ERROR,
                     "Changing field mode (%d -> %d) between slices is not allowed\n",
                     last_pic_structure, h->picture_structure);
 -            h->picture_structure = last_pic_structure;
 -            h->droppable         = last_pic_droppable;
              return AVERROR_INVALIDDATA;
-         } else if (!h0->cur_pic_ptr) {
+         } else if (!h->cur_pic_ptr) {
              av_log(h->avctx, AV_LOG_ERROR,
                     "unset cur_pic_ptr on slice %d\n",
-                    h0->current_slice + 1);
+                    h->current_slice + 1);
              return AVERROR_INVALIDDATA;
          }
 -    } else {
 +    }
 +
 +    h->picture_structure = picture_structure;
 +    h->droppable         = droppable;
 +    h->frame_num         = frame_num;
 +    sl->mb_field_decoding_flag = picture_structure != PICT_FRAME;
 +
-     if (h0->current_slice == 0) {
++    if (h->current_slice == 0) {
          /* Shorten frame num gaps so we don't have to allocate reference
           * frames just to throw them away */
          if (h->frame_num != h->prev_frame_num) {
           * Here, we're using that to see if we should mark previously
           * decode frames as "finished".
           * We have to do that before the "dummy" in-between frame allocation,
 -         * since that can modify s->current_picture_ptr. */
 +         * since that can modify h->cur_pic_ptr. */
-         if (h0->first_field) {
-             assert(h0->cur_pic_ptr);
-             assert(h0->cur_pic_ptr->f.buf[0]);
-             assert(h0->cur_pic_ptr->reference != DELAYED_PIC_REF);
+         if (h->first_field) {
+             assert(h->cur_pic_ptr);
+             assert(h->cur_pic_ptr->f.buf[0]);
+             assert(h->cur_pic_ptr->reference != DELAYED_PIC_REF);
  
-             if (h0->cur_pic_ptr->tf.owner == h0->avctx) {
-                 ff_thread_report_progress(&h0->cur_pic_ptr->tf, INT_MAX,
 +            /* Mark old field/frame as completed */
++            if (h->cur_pic_ptr->tf.owner == h->avctx) {
++                ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX,
 +                                          last_pic_structure == PICT_BOTTOM_FIELD);
 +            }
 +
              /* figure out if we have a complementary field pair */
              if (!FIELD_PICTURE(h) || h->picture_structure == last_pic_structure) {
                  /* Previous field is unmatched. Don't display it, but let it
                   * remain for reference if marked as such. */
 -                if (!last_pic_droppable && last_pic_structure != PICT_FRAME) {
 +                if (last_pic_structure != PICT_FRAME) {
-                     ff_thread_report_progress(&h0->cur_pic_ptr->tf, INT_MAX,
+                     ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX,
                                                last_pic_structure == PICT_TOP_FIELD);
                  }
              } else {
                       * different frame_nums. Consider this field first in
                       * pair. Throw away previous field except for reference
                       * purposes. */
 -                    if (!last_pic_droppable && last_pic_structure != PICT_FRAME) {
 +                    if (last_pic_structure != PICT_FRAME) {
-                         ff_thread_report_progress(&h0->cur_pic_ptr->tf, INT_MAX,
+                         ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX,
                                                    last_pic_structure == PICT_TOP_FIELD);
                      }
                  } else {
              }
          }
  
-         while (h->frame_num != h->prev_frame_num && !h0->first_field &&
 -        while (h->frame_num != h->prev_frame_num &&
++        while (h->frame_num != h->prev_frame_num && !h->first_field &&
                 h->frame_num != (h->prev_frame_num + 1) % (1 << h->sps.log2_max_frame_num)) {
              H264Picture *prev = h->short_ref_count ? h->short_ref[0] : NULL;
              av_log(h->avctx, AV_LOG_DEBUG, "Frame num gap %d %d\n",
                     h->frame_num, h->prev_frame_num);
 +            if (!h->sps.gaps_in_frame_num_allowed_flag)
 +                for(i=0; i<FF_ARRAY_ELEMS(h->last_pocs); i++)
 +                    h->last_pocs[i] = INT_MIN;
              ret = h264_frame_start(h);
              if (ret < 0) {
-                 h0->first_field = 0;
+                 h->first_field = 0;
                  return ret;
              }
  
              if (!FIELD_PICTURE(h) || h->picture_structure == last_pic_structure) {
                  /* Previous field is unmatched. Don't display it, but let it
                   * remain for reference if marked as such. */
-                 h0->missing_fields ++;
-                 h0->cur_pic_ptr = NULL;
-                 h0->first_field = FIELD_PICTURE(h);
++                h->missing_fields ++;
+                 h->cur_pic_ptr = NULL;
+                 h->first_field = FIELD_PICTURE(h);
              } else {
-                 h0->missing_fields = 0;
-                 if (h0->cur_pic_ptr->frame_num != h->frame_num) {
-                     ff_thread_report_progress(&h0->cur_pic_ptr->tf, INT_MAX,
-                                               h0->picture_structure==PICT_BOTTOM_FIELD);
++                h->missing_fields = 0;
+                 if (h->cur_pic_ptr->frame_num != h->frame_num) {
++                    ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX,
++                                              h->picture_structure==PICT_BOTTOM_FIELD);
                      /* This and the previous field had different frame_nums.
                       * Consider this field first in pair. Throw away previous
                       * one except for reference purposes. */
          } else {
              release_unused_pictures(h, 0);
          }
-         h0->last_slice_type = -1;
 +        /* Some macroblocks can be accessed before they're available in case
 +        * of lost slices, MBAFF or threading. */
 +        if (FIELD_PICTURE(h)) {
 +            for(i = (h->picture_structure == PICT_BOTTOM_FIELD); i<h->mb_height; i++)
 +                memset(h->slice_table + i*h->mb_stride, -1, (h->mb_stride - (i+1==h->mb_height)) * sizeof(*h->slice_table));
 +        } else {
 +            memset(h->slice_table, -1,
 +                (h->mb_height * h->mb_stride - 1) * sizeof(*h->slice_table));
 +        }
++        h->last_slice_type = -1;
      }
-     if (h != h0 && (ret = clone_slice(h, h0)) < 0)
-         return ret;
  
 +
      h->cur_pic_ptr->frame_num = h->frame_num; // FIXME frame_num cleanup
  
 -    assert(h->mb_num == h->mb_width * h->mb_height);
 +    av_assert1(h->mb_num == h->mb_width * h->mb_height);
      if (first_mb_in_slice << FIELD_OR_MBAFF_PICTURE(h) >= h->mb_num ||
          first_mb_in_slice >= h->mb_num) {
          av_log(h->avctx, AV_LOG_ERROR, "first_mb_in_slice overflow\n");
      ret = ff_set_ref_count(h, sl);
      if (ret < 0)
          return ret;
 -    else if (ret == 1)
 -        default_ref_list_done = 0;
  
 -    if (!default_ref_list_done)
 +    if (slice_type != AV_PICTURE_TYPE_I &&
-         (h0->current_slice == 0 ||
-          slice_type != h0->last_slice_type ||
-          memcmp(h0->last_ref_count, sl->ref_count, sizeof(sl->ref_count)))) {
++        (h->current_slice == 0 ||
++         slice_type != h->last_slice_type ||
++         memcmp(h->last_ref_count, sl->ref_count, sizeof(sl->ref_count)))) {
 +
          ff_h264_fill_default_ref_list(h, sl);
 +    }
  
      if (sl->slice_type_nos != AV_PICTURE_TYPE_I) {
         ret = ff_h264_decode_ref_pic_list_reordering(h, sl);
               * Do not bother to deblock across slices. */
              sl->deblocking_filter = 2;
          } else {
-             h0->max_contexts = 1;
-             if (!h0->single_decode_warning) {
+             h->max_contexts = 1;
+             if (!h->single_decode_warning) {
                  av_log(h->avctx, AV_LOG_INFO,
 -                       "Cannot parallelize deblocking type 1, decoding such frames in sequential order\n");
 +                       "Cannot parallelize slice decoding with deblocking filter type 1, decoding such frames in sequential order\n"
 +                       "To parallelize slice decoding you need video encoded with disable_deblocking_filter_idc set to 2 (deblock only edges that do not cross slices).\n"
 +                       "Setting the flags2 libavcodec option to +fast (-flags2 +fast) will disable deblocking across slices and enable parallel slice decoding "
 +                       "but will generate non-standard-compliant output.\n");
-                 h0->single_decode_warning = 1;
+                 h->single_decode_warning = 1;
              }
-             if (h != h0) {
+             if (sl != h->slice_ctx) {
                  av_log(h->avctx, AV_LOG_ERROR,
                         "Deblocking switched inside frame.\n");
 -                return 1;
 +                return SLICE_SINGLETHREAD;
              }
          }
      }
                            h->pps.chroma_qp_index_offset[1]) +
                     6 * (h->sps.bit_depth_luma - 8);
  
-     h0->last_slice_type = slice_type;
-     memcpy(h0->last_ref_count, sl->ref_count, sizeof(h0->last_ref_count));
-     sl->slice_num       = ++h0->current_slice;
+     h->last_slice_type = slice_type;
++    memcpy(h->last_ref_count, sl->ref_count, sizeof(h->last_ref_count));
+     sl->slice_num       = ++h->current_slice;
 -    if (sl->slice_num >= MAX_SLICES) {
 -        av_log(h->avctx, AV_LOG_ERROR,
 -               "Too many slices, increase MAX_SLICES and recompile\n");
 +
 +    if (sl->slice_num)
-         h0->slice_row[(sl->slice_num-1)&(MAX_SLICES-1)]= sl->resync_mb_y;
-     if (   h0->slice_row[sl->slice_num&(MAX_SLICES-1)] + 3 >= sl->resync_mb_y
-         && h0->slice_row[sl->slice_num&(MAX_SLICES-1)] <= sl->resync_mb_y
++        h->slice_row[(sl->slice_num-1)&(MAX_SLICES-1)]= sl->resync_mb_y;
++    if (   h->slice_row[sl->slice_num&(MAX_SLICES-1)] + 3 >= sl->resync_mb_y
++        && h->slice_row[sl->slice_num&(MAX_SLICES-1)] <= sl->resync_mb_y
 +        && sl->slice_num >= MAX_SLICES) {
 +        //in case of ASO this check needs to be updated depending on how we decide to assign slice numbers in this case
 +        av_log(h->avctx, AV_LOG_WARNING, "Possibly too many slices (%d >= %d), increase MAX_SLICES and recompile if there are artifacts\n", sl->slice_num, MAX_SLICES);
      }
  
      for (j = 0; j < 2; j++) {
                               (sl->ref_list[j][i].reference & 3);
      }
  
-     h0->au_pps_id = pps_id;
++    h->au_pps_id = pps_id;
 +    h->sps.new =
-     h0->sps_buffers[h->pps.sps_id]->new = 0;
++    h->sps_buffers[h->pps.sps_id]->new = 0;
 +    h->current_sps_id = h->pps.sps_id;
 +
      if (h->avctx->debug & FF_DEBUG_PICT_INFO) {
          av_log(h->avctx, AV_LOG_DEBUG,
                 "slice:%d %s mb:%d %c%s%s pps:%u frame:%d poc:%d/%d ref:%d/%d qp:%d loop:%d:%d:%d weight:%d%s %s\n",
@@@ -2388,7 -2134,7 +2357,7 @@@ static void er_add_slice(H264SliceConte
  static int decode_slice(struct AVCodecContext *avctx, void *arg)
  {
      H264SliceContext *sl = arg;
--    const H264Context *h = sl->h264;
++    const H264Context *h = avctx->priv_data;
      int lf_x_start = sl->mb_x;
      int ret;
  
@@@ -2587,29 -2314,19 +2555,24 @@@ int ff_h264_execute_decode_slices(H264C
          h->mb_y = h->slice_ctx[0].mb_y;
          return ret;
      } else {
 +        av_assert0(context_count > 0);
          for (i = 1; i < context_count; i++) {
-             hx                 = h->thread_context[i];
              sl                 = &h->slice_ctx[i];
 -            sl->er.error_count = 0;
 +            if (CONFIG_ERROR_RESILIENCE) {
 +                sl->er.error_count = 0;
 +            }
-             hx->x264_build     = h->x264_build;
          }
  
          avctx->execute(avctx, decode_slice, h->slice_ctx,
                         NULL, context_count, sizeof(h->slice_ctx[0]));
  
          /* pull back stuff from slices to master context */
-         hx                   = h->thread_context[context_count - 1];
          sl                   = &h->slice_ctx[context_count - 1];
          h->mb_y              = sl->mb_y;
-         h->droppable         = hx->droppable;
-         h->picture_structure = hx->picture_structure;
 -        for (i = 1; i < context_count; i++)
 -            h->slice_ctx[0].er.error_count += h->slice_ctx[i].er.error_count;
 +        if (CONFIG_ERROR_RESILIENCE) {
 +            for (i = 1; i < context_count; i++)
 +                h->slice_ctx[0].er.error_count += h->slice_ctx[i].er.error_count;
 +        }
      }
  
      return 0;