]> git.sesse.net Git - ffmpeg/commitdiff
Merge commit '38efff92f1ef81f3de20ff0460ec7b70c253d714'
authorClément Bœsch <u@pkh.me>
Tue, 17 Jan 2017 14:26:38 +0000 (15:26 +0100)
committerClément Bœsch <u@pkh.me>
Tue, 24 Jan 2017 15:13:03 +0000 (16:13 +0100)
* commit '38efff92f1ef81f3de20ff0460ec7b70c253d714':
  FATE: add a test for H.264 with two fields per packet
  h264: fix decoding multiple fields per packet with slice threads

This merge includes two commits because the FATE test was useful in
order to make proper testing.

The merge gets rid of the now unused:
- SLICE_SINGLETHREAD and SLICE_SKIPED macros
- max_contexts
- "again" label in decode_nal_units()

This commit also includes the fix from d3e4d406b.

Thanks to wm4 and Michael Niedermayer for their testing.

Merged-by: Clément Bœsch <u@pkh.me>
Merged-by: Matthieu Bouron <matthieu.bouron@gmail.com>
1  2 
libavcodec/h264_slice.c
libavcodec/h264dec.c
libavcodec/h264dec.h
tests/fate/h264.mak
tests/ref/fate/h264-twofields-packet

index ad7a75fa2ee34cac16750e99e9d87a7fba16820a,8d79740a7f5cf62f16ecebd3e3df96f77be5537f..6b555ab4c5dfc235dbaaf906bed3daaa034bfed9
@@@ -1849,120 -1699,33 +1849,13 @@@ static int h264_slice_header_parse(cons
      return 0;
  }
  
- /**
-  * Decode a slice header.
-  * This will (re)initialize the decoder and call h264_frame_start() as needed.
-  *
-  * @param h h264context
-  *
-  * @return 0 if okay, <0 if an error occurred
-  */
- int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl,
-                                 const H2645NAL *nal)
+ /* do all the per-slice initialization needed before we can start decoding the
+  * actual MBs */
+ static int h264_slice_init(H264Context *h, H264SliceContext *sl,
+                            const H2645NAL *nal)
  {
      int i, j, ret = 0;
-     int first_slice = sl == h->slice_ctx && !h->current_slice;
-     ret = h264_slice_header_parse(h, sl, nal);
-     if (ret < 0)
-         return ret;
-     // discard redundant pictures
-     if (sl->redundant_pic_count > 0)
-         return 0;
-     if (sl->first_mb_addr == 0 || !h->current_slice) {
-         if (h->setup_finished) {
-             av_log(h->avctx, AV_LOG_ERROR, "Too many fields\n");
-             return AVERROR_INVALIDDATA;
-         }
-     }
-     if (sl->first_mb_addr == 0) { // FIXME better field boundary detection
-         if (h->current_slice) {
-             if (h->max_contexts > 1) {
-                 if (!h->single_decode_warning) {
-                     av_log(h->avctx, AV_LOG_WARNING, "Cannot decode multiple access units as slice threads\n");
-                     h->single_decode_warning = 1;
-                 }
-                 h->max_contexts = 1;
-                 return SLICE_SINGLETHREAD;
-             }
-             if (h->cur_pic_ptr && FIELD_PICTURE(h) && h->first_field) {
-                 ret = ff_h264_field_end(h, h->slice_ctx, 1);
-                 if (ret < 0)
-                     return ret;
-             } else if (h->cur_pic_ptr && !FIELD_PICTURE(h) && !h->first_field && h->nal_unit_type  == H264_NAL_IDR_SLICE) {
-                 av_log(h, AV_LOG_WARNING, "Broken frame packetizing\n");
-                 ret = ff_h264_field_end(h, h->slice_ctx, 1);
-                 ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, 0);
-                 ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, 1);
-                 h->cur_pic_ptr = NULL;
-                 if (ret < 0)
-                     return ret;
-             } else
-                 return AVERROR_INVALIDDATA;
-         }
-         if (!h->first_field) {
-             if (h->cur_pic_ptr && !h->droppable) {
-                 ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX,
-                                           h->picture_structure == PICT_BOTTOM_FIELD);
-             }
-             h->cur_pic_ptr = NULL;
-         }
-     }
-     if (!h->current_slice)
-         av_assert0(sl == h->slice_ctx);
-     if (h->current_slice == 0 && !h->first_field) {
-         if (
-             (h->avctx->skip_frame >= AVDISCARD_NONREF && !h->nal_ref_idc) ||
-             (h->avctx->skip_frame >= AVDISCARD_BIDIR  && sl->slice_type_nos == AV_PICTURE_TYPE_B) ||
-             (h->avctx->skip_frame >= AVDISCARD_NONINTRA && sl->slice_type_nos != AV_PICTURE_TYPE_I) ||
-             (h->avctx->skip_frame >= AVDISCARD_NONKEY && h->nal_unit_type != H264_NAL_IDR_SLICE && h->sei.recovery_point.recovery_frame_cnt < 0) ||
-             h->avctx->skip_frame >= AVDISCARD_ALL) {
-             return SLICE_SKIPED;
-         }
-     }
-     if (!first_slice) {
-         const PPS *pps = (const PPS*)h->ps.pps_list[sl->pps_id]->data;
-         if (h->ps.pps->sps_id != pps->sps_id ||
-             h->ps.pps->transform_8x8_mode != pps->transform_8x8_mode /*||
-             (h->setup_finished && h->ps.pps != pps)*/) {
-             av_log(h->avctx, AV_LOG_ERROR, "PPS changed between slices\n");
-             return AVERROR_INVALIDDATA;
-         }
-         if (h->ps.sps != (const SPS*)h->ps.sps_list[h->ps.pps->sps_id]->data) {
-             av_log(h->avctx, AV_LOG_ERROR,
-                "SPS changed in the middle of the frame\n");
-             return AVERROR_INVALIDDATA;
-         }
-     }
-     if (h->current_slice == 0) {
-         ret = h264_field_start(h, sl, nal, first_slice);
-         if (ret < 0)
-             return ret;
-     } else {
-         if (h->picture_structure != sl->picture_structure ||
-             h->droppable         != (nal->ref_idc == 0)) {
-             av_log(h->avctx, AV_LOG_ERROR,
-                    "Changing field mode (%d -> %d) between slices is not allowed\n",
-                    h->picture_structure, sl->picture_structure);
-             return AVERROR_INVALIDDATA;
-         } else if (!h->cur_pic_ptr) {
-             av_log(h->avctx, AV_LOG_ERROR,
-                    "unset cur_pic_ptr on slice %d\n",
-                    h->current_slice + 1);
-             return AVERROR_INVALIDDATA;
-         }
-     }
  
 -    if (h->current_slice > 0) {
 -        if (h->ps.pps != (const PPS*)h->ps.pps_list[sl->pps_id]->data) {
 -            av_log(h->avctx, AV_LOG_ERROR, "PPS changed between slices\n");
 -            return AVERROR_INVALIDDATA;
 -        }
 -
 -        if (h->picture_structure != sl->picture_structure ||
 -            h->droppable         != (nal->ref_idc == 0)) {
 -            av_log(h->avctx, AV_LOG_ERROR,
 -                   "Changing field mode (%d -> %d) between slices is not allowed\n",
 -                   h->picture_structure, sl->picture_structure);
 -            return AVERROR_INVALIDDATA;
 -        } else if (!h->cur_pic_ptr) {
 -            av_log(h->avctx, AV_LOG_ERROR,
 -                   "unset cur_pic_ptr on slice %d\n",
 -                   h->current_slice + 1);
 -            return AVERROR_INVALIDDATA;
 -        }
 -    }
 -
      if (h->picture_idr && nal->type != H264_NAL_IDR_SLICE) {
          av_log(h->avctx, AV_LOG_ERROR, "Invalid mix of IDR and non-IDR slices\n");
          return AVERROR_INVALIDDATA;
      return 0;
  }
  
 -    ret = h264_slice_header_parse(sl, nal, &h->ps, h->avctx);
+ int ff_h264_queue_decode_slice(H264Context *h, const H2645NAL *nal)
+ {
+     H264SliceContext *sl = h->slice_ctx + h->nb_slice_ctx_queued;
++    int first_slice = sl == h->slice_ctx && !h->current_slice;
+     int ret;
+     sl->gb = nal->gb;
 -    if (!h->setup_finished) {
 -        if (sl->first_mb_addr == 0) { // FIXME better field boundary detection
++    ret = h264_slice_header_parse(h, sl, nal);
+     if (ret < 0)
+         return ret;
+     // discard redundant pictures
+     if (sl->redundant_pic_count > 0)
+         return 0;
 -            if (h->current_slice && h->cur_pic_ptr && FIELD_PICTURE(h)) {
 -                ff_h264_field_end(h, sl, 1);
 -            }
 -
 -            h->current_slice = 0;
 -            if (!h->first_field) {
 -                if (h->cur_pic_ptr && !h->droppable) {
 -                    ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX,
 -                                              h->picture_structure == PICT_BOTTOM_FIELD);
 -                }
++    if (sl->first_mb_addr == 0 || !h->current_slice) {
++        if (h->setup_finished) {
++            av_log(h->avctx, AV_LOG_ERROR, "Too many fields\n");
++            return AVERROR_INVALIDDATA;
++        }
++    }
++
++    if (sl->first_mb_addr == 0) { // FIXME better field boundary detection
++        if (h->current_slice) {
+             // this slice starts a new field
+             // first decode any pending queued slices
+             if (h->nb_slice_ctx_queued) {
+                 H264SliceContext tmp_ctx;
+                 ret = ff_h264_execute_decode_slices(h);
+                 if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE))
+                     return ret;
+                 memcpy(&tmp_ctx, h->slice_ctx, sizeof(tmp_ctx));
+                 memcpy(h->slice_ctx, sl, sizeof(tmp_ctx));
+                 memcpy(sl, &tmp_ctx, sizeof(tmp_ctx));
+                 sl = h->slice_ctx;
+             }
 -        if (h->current_slice == 0) {
 -            ret = h264_field_start(h, sl, nal);
 -            if (ret < 0)
 -                return ret;
++            if (h->cur_pic_ptr && FIELD_PICTURE(h) && h->first_field) {
++                ret = ff_h264_field_end(h, h->slice_ctx, 1);
++                if (ret < 0)
++                    return ret;
++            } else if (h->cur_pic_ptr && !FIELD_PICTURE(h) && !h->first_field && h->nal_unit_type  == H264_NAL_IDR_SLICE) {
++                av_log(h, AV_LOG_WARNING, "Broken frame packetizing\n");
++                ret = ff_h264_field_end(h, h->slice_ctx, 1);
++                ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, 0);
++                ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, 1);
+                 h->cur_pic_ptr = NULL;
++                if (ret < 0)
++                    return ret;
++            } else
++                return AVERROR_INVALIDDATA;
++        }
++
++        if (!h->first_field) {
++            if (h->cur_pic_ptr && !h->droppable) {
++                ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX,
++                                          h->picture_structure == PICT_BOTTOM_FIELD);
+             }
++            h->cur_pic_ptr = NULL;
+         }
++    }
 -    if ((h->avctx->skip_frame < AVDISCARD_NONREF || nal->ref_idc) &&
 -        (h->avctx->skip_frame < AVDISCARD_BIDIR  ||
 -         sl->slice_type_nos != AV_PICTURE_TYPE_B) &&
 -        (h->avctx->skip_frame < AVDISCARD_NONKEY ||
 -         h->cur_pic_ptr->f->key_frame) &&
 -        h->avctx->skip_frame < AVDISCARD_ALL) {
 -        h->nb_slice_ctx_queued++;
 -    }
++    if (!h->current_slice)
++        av_assert0(sl == h->slice_ctx);
++
++    if (h->current_slice == 0 && !h->first_field) {
++        if (
++            (h->avctx->skip_frame >= AVDISCARD_NONREF && !h->nal_ref_idc) ||
++            (h->avctx->skip_frame >= AVDISCARD_BIDIR  && sl->slice_type_nos == AV_PICTURE_TYPE_B) ||
++            (h->avctx->skip_frame >= AVDISCARD_NONINTRA && sl->slice_type_nos != AV_PICTURE_TYPE_I) ||
++            (h->avctx->skip_frame >= AVDISCARD_NONKEY && h->nal_unit_type != H264_NAL_IDR_SLICE && h->sei.recovery_point.recovery_frame_cnt < 0) ||
++            h->avctx->skip_frame >= AVDISCARD_ALL) {
++            return 0;
++        }
++    }
++
++    if (!first_slice) {
++        const PPS *pps = (const PPS*)h->ps.pps_list[sl->pps_id]->data;
++
++        if (h->ps.pps->sps_id != pps->sps_id ||
++            h->ps.pps->transform_8x8_mode != pps->transform_8x8_mode /*||
++            (h->setup_finished && h->ps.pps != pps)*/) {
++            av_log(h->avctx, AV_LOG_ERROR, "PPS changed between slices\n");
++            return AVERROR_INVALIDDATA;
++        }
++        if (h->ps.sps != (const SPS*)h->ps.sps_list[h->ps.pps->sps_id]->data) {
++            av_log(h->avctx, AV_LOG_ERROR,
++               "SPS changed in the middle of the frame\n");
++            return AVERROR_INVALIDDATA;
++        }
++    }
++
++    if (h->current_slice == 0) {
++        ret = h264_field_start(h, sl, nal, first_slice);
++        if (ret < 0)
++            return ret;
++    } else {
++        if (h->picture_structure != sl->picture_structure ||
++            h->droppable         != (nal->ref_idc == 0)) {
++            av_log(h->avctx, AV_LOG_ERROR,
++                   "Changing field mode (%d -> %d) between slices is not allowed\n",
++                   h->picture_structure, sl->picture_structure);
++            return AVERROR_INVALIDDATA;
++        } else if (!h->cur_pic_ptr) {
++            av_log(h->avctx, AV_LOG_ERROR,
++                   "unset cur_pic_ptr on slice %d\n",
++                   h->current_slice + 1);
++            return AVERROR_INVALIDDATA;
+         }
+     }
+     ret = h264_slice_init(h, sl, nal);
+     if (ret < 0)
+         return ret;
++    h->nb_slice_ctx_queued++;
+     return 0;
+ }
  int ff_h264_get_slice_type(const H264SliceContext *sl)
  {
      switch (sl->slice_type) {
@@@ -2684,29 -2489,22 +2699,32 @@@ int ff_h264_execute_decode_slices(H264C
  {
      AVCodecContext *const avctx = h->avctx;
      H264SliceContext *sl;
+     int context_count = h->nb_slice_ctx_queued;
+     int ret = 0;
      int i, j;
  
-     av_assert0(context_count && h->slice_ctx[context_count - 1].mb_y < h->mb_height);
 -    if (h->avctx->hwaccel || context_count < 1)
 +    h->slice_ctx[0].next_slice_idx = INT_MAX;
 +
-     if (h->avctx->hwaccel
++    if (h->avctx->hwaccel || context_count < 1
 +#if FF_API_CAP_VDPAU
 +        || h->avctx->codec->capabilities & AV_CODEC_CAP_HWACCEL_VDPAU
 +#endif
 +        )
          return 0;
++
++    av_assert0(context_count && h->slice_ctx[context_count - 1].mb_y < h->mb_height);
++
      if (context_count == 1) {
-         int ret;
  
          h->slice_ctx[0].next_slice_idx = h->mb_width * h->mb_height;
          h->postpone_filter = 0;
  
          ret = decode_slice(avctx, &h->slice_ctx[0]);
          h->mb_y = h->slice_ctx[0].mb_y;
-         return ret;
+         if (ret < 0)
+             goto finish;
      } else {
 +        av_assert0(context_count > 0);
          for (i = 0; i < context_count; i++) {
              int next_slice_idx = h->mb_width * h->mb_height;
              int slice_idx;
index 41e6ce458cec05aff7e1843f5706f51186c27a79,1086eab8d3fc0a99b2bdee9a1463bdc091c386cf..31db1db076f66eb6192068c9a73949a6faa2ea2d
@@@ -602,15 -508,9 +602,13 @@@ static void debug_green_metadata(const 
  static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size)
  {
      AVCodecContext *const avctx = h->avctx;
-     unsigned context_count = 0;
      int nals_needed = 0; ///< number of NALs that need decoding before the next frame thread starts
 +    int idr_cleared=0;
      int i, ret = 0;
  
-     h->max_contexts = h->nb_slice_ctx;
 +    h->has_slice = 0;
 +    h->nal_unit_type= 0;
 +
      if (!(avctx->flags2 & AV_CODEC_FLAG2_CHUNKS)) {
          h->current_slice = 0;
          if (!h->first_field)
          err = 0;
          switch (nal->type) {
          case H264_NAL_IDR_SLICE:
 -            idr(h); // FIXME ensure we don't lose some frames if there is reordering
 +            if ((nal->data[1] & 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(!idr_cleared) {
 +                if (h->current_slice && (avctx->active_thread_type & FF_THREAD_SLICE)) {
 +                    av_log(h, AV_LOG_ERROR, "invalid mixed IDR / non IDR frames cannot be decoded in slice multithreading mode\n");
 +                    ret = AVERROR_INVALIDDATA;
 +                    goto end;
 +                }
 +                idr(h); // FIXME ensure we don't lose some frames if there is reordering
 +            }
 +            idr_cleared = 1;
 +            h->has_recovery_point = 1;
          case H264_NAL_SLICE:
-             sl->gb = nal->gb;
 +            h->has_slice = 1;
 +
-             if ((err = ff_h264_decode_slice_header(h, sl, nal)))
-                 break;
-             if (sl->redundant_pic_count > 0)
+             if ((err = ff_h264_queue_decode_slice(h, nal)))
                  break;
  
 -            if (avctx->active_thread_type & FF_THREAD_FRAME && !h->avctx->hwaccel &&
 -                i >= nals_needed) {
 -                ff_thread_finish_setup(avctx);
 -                h->setup_finished = 1;
 +            if (h->current_slice == 1) {
 +                if (avctx->active_thread_type & FF_THREAD_FRAME && !h->avctx->hwaccel &&
 +                    i >= nals_needed && !h->setup_finished && h->cur_pic_ptr) {
 +                    ff_thread_finish_setup(avctx);
 +                    h->setup_finished = 1;
 +                }
 +
 +                if (h->avctx->hwaccel &&
 +                    (ret = h->avctx->hwaccel->start_frame(h->avctx, buf, buf_size)) < 0)
 +                    goto end;
 +#if FF_API_CAP_VDPAU
 +                if (CONFIG_H264_VDPAU_DECODER &&
 +                    h->avctx->codec->capabilities & AV_CODEC_CAP_HWACCEL_VDPAU)
 +                    ff_vdpau_h264_picture_start(h);
 +#endif
              }
  
-             if (avctx->hwaccel) {
-                 ret = avctx->hwaccel->decode_slice(avctx,
-                                                    nal->raw_data,
-                                                    nal->raw_size);
-                 if (ret < 0)
-                     goto end;
+             max_slice_ctx = avctx->hwaccel ? 1 : h->nb_slice_ctx;
+             if (h->nb_slice_ctx_queued == max_slice_ctx) {
 -                if (avctx->hwaccel)
++                if (h->avctx->hwaccel) {
+                     ret = avctx->hwaccel->decode_slice(avctx, nal->raw_data, nal->raw_size);
 -                else
++                    h->nb_slice_ctx_queued = 0;
++                } else
 +#if FF_API_CAP_VDPAU
-             } else if (CONFIG_H264_VDPAU_DECODER &&
++            if (CONFIG_H264_VDPAU_DECODER &&
 +                       h->avctx->codec->capabilities & AV_CODEC_CAP_HWACCEL_VDPAU) {
 +                ff_vdpau_add_data_chunk(h->cur_pic_ptr->f->data[0],
 +                                        start_code,
 +                                        sizeof(start_code));
 +                ff_vdpau_add_data_chunk(h->cur_pic_ptr->f->data[0],
 +                                        nal->raw_data,
 +                                        nal->raw_size);
- #endif
++                ret = 0;
 +            } else
-                 context_count++;
++#endif
+                     ret = ff_h264_execute_decode_slices(h);
+                 if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE))
+                     goto end;
+             }
              break;
          case H264_NAL_DPA:
          case H264_NAL_DPB:
@@@ -1013,39 -665,53 +989,40 @@@ static int h264_decode_frame(AVCodecCon
  
      h->flags = avctx->flags;
      h->setup_finished = 0;
+     h->nb_slice_ctx_queued = 0;
  
 -    /* end of stream, output what is still in the buffers */
 -out:
 -    if (buf_size == 0) {
 -        H264Picture *out;
 -        int i, out_idx;
 -
 -        h->cur_pic_ptr = NULL;
 -
 -        // FIXME factorize this with the output code below
 -        out     = h->delayed_pic[0];
 -        out_idx = 0;
 -        for (i = 1;
 -             h->delayed_pic[i] &&
 -             !h->delayed_pic[i]->f->key_frame &&
 -             !h->delayed_pic[i]->mmco_reset;
 -             i++)
 -            if (h->delayed_pic[i]->poc < out->poc) {
 -                out     = h->delayed_pic[i];
 -                out_idx = i;
 -            }
 -
 -        for (i = out_idx; h->delayed_pic[i]; i++)
 -            h->delayed_pic[i] = h->delayed_pic[i + 1];
 +    if (h->backup_width != -1) {
 +        avctx->width    = h->backup_width;
 +        h->backup_width = -1;
 +    }
 +    if (h->backup_height != -1) {
 +        avctx->height    = h->backup_height;
 +        h->backup_height = -1;
 +    }
 +    if (h->backup_pix_fmt != AV_PIX_FMT_NONE) {
 +        avctx->pix_fmt    = h->backup_pix_fmt;
 +        h->backup_pix_fmt = AV_PIX_FMT_NONE;
 +    }
  
 -        if (out) {
 -            ret = output_frame(h, pict, out->f);
 -            if (ret < 0)
 -                return ret;
 -            *got_frame = 1;
 -        }
 +    ff_h264_unref_picture(h, &h->last_pic_for_ec);
  
 -        return buf_index;
 +    /* end of stream, output what is still in the buffers */
 +    if (buf_size == 0)
 +        return send_next_delayed_frame(h, pict, got_frame, 0);
 +
 +    if (h->is_avc && av_packet_get_side_data(avpkt, AV_PKT_DATA_NEW_EXTRADATA, NULL)) {
 +        int side_size;
 +        uint8_t *side = av_packet_get_side_data(avpkt, AV_PKT_DATA_NEW_EXTRADATA, &side_size);
 +        if (is_extra(side, side_size))
 +            ff_h264_decode_extradata(side, side_size,
 +                                     &h->ps, &h->is_avc, &h->nal_length_size,
 +                                     avctx->err_recognition, avctx);
      }
 -
 -    new_extradata_size = 0;
 -    new_extradata = av_packet_get_side_data(avpkt, AV_PKT_DATA_NEW_EXTRADATA,
 -                                            &new_extradata_size);
 -    if (new_extradata_size > 0 && new_extradata) {
 -        ret = ff_h264_decode_extradata(new_extradata, new_extradata_size,
 -                                       &h->ps, &h->is_avc, &h->nal_length_size,
 -                                       avctx->err_recognition, avctx);
 -        if (ret < 0)
 -            return ret;
 +    if(h->is_avc && buf_size >= 9 && buf[0]==1 && buf[2]==0 && (buf[4]&0xFC)==0xFC && (buf[5]&0x1F) && buf[8]==0x67){
 +        if (is_extra(buf, buf_size))
 +            return ff_h264_decode_extradata(buf, buf_size,
 +                                            &h->ps, &h->is_avc, &h->nal_length_size,
 +                                            avctx->err_recognition, avctx);
      }
  
      buf_index = decode_nal_units(h, buf, buf_size);
index fa5c98ee9006764955f17824559d63dbac283af2,f934fc40b84a78cdf4eb402d581021adfa7d3dd8..5f868b76cb6356282dd9729c34aa856b3cd9bc31
@@@ -846,12 -794,14 +833,16 @@@ int ff_h264_slice_context_init(H264Cont
  
  void ff_h264_draw_horiz_band(const H264Context *h, H264SliceContext *sl, int y, int height);
  
- #define SLICE_SINGLETHREAD 1
- #define SLICE_SKIPED 2
- int ff_h264_execute_decode_slices(H264Context *h, unsigned context_count);
 +int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl,
 +                                const H2645NAL *nal);
+ /**
+  * Submit a slice for decoding.
+  *
+  * Parse the slice header, starting a new field/frame if necessary. If any
+  * slices are queued for the previous field, they are decoded.
+  */
+ int ff_h264_queue_decode_slice(H264Context *h, const H2645NAL *nal);
+ int ff_h264_execute_decode_slices(H264Context *h);
  int ff_h264_update_thread_context(AVCodecContext *dst,
                                    const AVCodecContext *src);
  
index 1f6e5f39474ec1563c1f40ad2fb3ac8605082b19,ff1dd15109231e287475997dd12e3e05723fa65f..52b6a987854dafe2e7b93cb1c7c52103d7ef2151
@@@ -215,23 -198,17 +215,26 @@@ FATE_H264-$(call DEMDEC,  MOV, H264) +
  # this sample has invalid extradata that is not escaped
  FATE_H264-$(call DEMDEC,  MOV, H264) += fate-h264-unescaped-extradata
  
 -FATE_H264-$(call ALLYES, MOV_DEMUXER H264_MP4TOANNEXB_BSF) += fate-h264-bsf-mp4toannexb
+ # this sample contains field-coded frames, with both fields in a single packet
+ FATE_H264-$(call DEMDEC,  MOV, H264) += fate-h264-twofields-packet
 +FATE_H264-$(call ALLYES, MOV_DEMUXER H264_MP4TOANNEXB_BSF H264_MUXER) += fate-h264-bsf-mp4toannexb
  FATE_H264-$(call DEMDEC, MATROSKA, H264) += fate-h264-direct-bff
 +FATE_H264-$(call DEMDEC, FLV, H264) += fate-h264-brokensps-2580
 +FATE_H264-$(call DEMDEC, MXF, H264) += fate-h264-xavc-4389
 +FATE_H264-$(call DEMDEC, MOV, H264) += fate-h264-attachment-631
 +FATE_H264-$(call DEMDEC, MPEGTS, H264) += fate-h264-skip-nokey fate-h264-skip-nointra
 +FATE_H264_FFPROBE-$(call DEMDEC, MATROSKA, H264) += fate-h264-dts_5frames
  
  FATE_SAMPLES_AVCONV += $(FATE_H264-yes)
 -fate-h264: $(FATE_H264-yes)
 +FATE_SAMPLES_FFPROBE += $(FATE_H264_FFPROBE-yes)
 +fate-h264: $(FATE_H264-yes) $(FATE_H264_FFPROBE-yes)
 +
 +fate-h264-conformance-aud_mw_e:                   CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/AUD_MW_E.264
 +
 +#force framerate so that the option is tested, theres no other case that tests it, its not needed at all otherwise here
 +fate-h264-conformance-ba1_ft_c:                   CMD = framecrc -framerate 19 -i $(TARGET_SAMPLES)/h264-conformance/BA1_FT_C.264
  
 -fate-h264-conformance-aud_mw_e:                   CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/AUD_MW_E.264
 -fate-h264-conformance-ba1_ft_c:                   CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/BA1_FT_C.264
  fate-h264-conformance-ba1_sony_d:                 CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/BA1_Sony_D.jsv
  fate-h264-conformance-ba2_sony_f:                 CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/BA2_Sony_F.jsv
  fate-h264-conformance-ba3_sva_c:                  CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/BA3_SVA_C.264
@@@ -431,10 -390,7 +434,11 @@@ fate-h264-intra-refresh-recovery
  fate-h264-invalid-ref-mod:                        CMD = framecrc -i $(TARGET_SAMPLES)/h264/h264refframeregression.mp4 -an -frames 10 -pix_fmt yuv420p10le
  fate-h264-lossless:                               CMD = framecrc -i $(TARGET_SAMPLES)/h264/lossless.h264
  fate-h264-mixed-nal-coding:                       CMD = framecrc -i $(TARGET_SAMPLES)/h264/mixed-nal-coding.mp4
+ fate-h264-twofields-packet:                       CMD = framecrc -i $(TARGET_SAMPLES)/h264/twofields_packet.mp4 -an -frames 30
  fate-h264-unescaped-extradata:                    CMD = framecrc -i $(TARGET_SAMPLES)/h264/unescaped_extradata.mp4 -an -frames 10
 +fate-h264-3386:                                   CMD = framecrc -i $(TARGET_SAMPLES)/h264/bbc2.sample.h264
 +fate-h264-missing-frame:                          CMD = framecrc -i $(TARGET_SAMPLES)/h264/nondeterministic_cut.h264
  
  fate-h264-reinit-%:                               CMD = framecrc -i $(TARGET_SAMPLES)/h264/$(@:fate-h264-%=%).h264 -vf format=yuv444p10le,scale=w=352:h=288
 +
 +fate-h264-dts_5frames:                            CMD = probeframes $(TARGET_SAMPLES)/h264/dts_5frames.mkv
index 0000000000000000000000000000000000000000,fc2b9f93188cf37bc4df377be8872751d1d0f946..4cff0a15bddf133d309740b21b3f3ef45bd6888c
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,31 +1,35 @@@
 -#tb 0: 1/90000
 -0,          0,          0,        0,  3110400, 0x48e39acd
 -0,       3003,       3003,        0,  3110400, 0x40d65f69
 -0,       6006,       6006,        0,  3110400, 0xdcbc50bf
 -0,       9009,       9009,        0,  3110400, 0x73a2276a
 -0,      12012,      12012,        0,  3110400, 0x84a2b3c6
 -0,      15015,      15015,        0,  3110400, 0x7cf3b570
 -0,      18018,      18018,        0,  3110400, 0xa2d1e03a
 -0,      21021,      21021,        0,  3110400, 0x03220fb1
 -0,      24024,      24024,        0,  3110400, 0x89cd526a
 -0,      27027,      27027,        0,  3110400, 0xbb4b7531
 -0,      30030,      30030,        0,  3110400, 0x0a69f053
 -0,      33033,      33033,        0,  3110400, 0x0187994b
 -0,      36036,      36036,        0,  3110400, 0x26ed49fa
 -0,      39039,      39039,        0,  3110400, 0xbe8966d4
 -0,      42042,      42042,        0,  3110400, 0x248d203c
 -0,      45045,      45045,        0,  3110400, 0x3139c754
 -0,      48048,      48048,        0,  3110400, 0xf22380c4
 -0,      51051,      51051,        0,  3110400, 0x3e00dcc1
 -0,      54054,      54054,        0,  3110400, 0x8cbe2483
 -0,      57057,      57057,        0,  3110400, 0x6951cd63
 -0,      60060,      60060,        0,  3110400, 0x36aca4c5
 -0,      63063,      63063,        0,  3110400, 0x4d4f6fbe
 -0,      66066,      66066,        0,  3110400, 0x997247aa
 -0,      69069,      69069,        0,  3110400, 0x0fd40e06
 -0,      72072,      72072,        0,  3110400, 0xa10d2d67
 -0,      75075,      75075,        0,  3110400, 0x87c481da
 -0,      78078,      78078,        0,  3110400, 0xe3dca3cd
 -0,      81081,      81081,        0,  3110400, 0x5f77b078
 -0,      84084,      84084,        0,  3110400, 0xf1ddd098
 -0,      87087,      87087,        0,  3110400, 0xedcd1754
++#tb 0: 1001/30000
++#media_type 0: video
++#codec_id 0: rawvideo
++#dimensions 0: 1920x1080
++#sar 0: 1/1
++0,          0,          0,        1,  3110400, 0x40d65f69
++0,          1,          1,        1,  3110400, 0xdcbc50bf
++0,          2,          2,        1,  3110400, 0x73a2276a
++0,          3,          3,        1,  3110400, 0x84a2b3c6
++0,          4,          4,        1,  3110400, 0x7cf3b570
++0,          5,          5,        1,  3110400, 0xa2d1e03a
++0,          6,          6,        1,  3110400, 0x03220fb1
++0,          7,          7,        1,  3110400, 0x89cd526a
++0,          8,          8,        1,  3110400, 0xbb4b7531
++0,          9,          9,        1,  3110400, 0x0a69f053
++0,         10,         10,        1,  3110400, 0x0187994b
++0,         11,         11,        1,  3110400, 0x26ed49fa
++0,         12,         12,        1,  3110400, 0xbe8966d4
++0,         13,         13,        1,  3110400, 0x248d203c
++0,         14,         14,        1,  3110400, 0x3139c754
++0,         15,         15,        1,  3110400, 0xf22380c4
++0,         16,         16,        1,  3110400, 0x3e00dcc1
++0,         17,         17,        1,  3110400, 0x8cbe2483
++0,         18,         18,        1,  3110400, 0x6951cd63
++0,         19,         19,        1,  3110400, 0x36aca4c5
++0,         20,         20,        1,  3110400, 0x4d4f6fbe
++0,         21,         21,        1,  3110400, 0x997247aa
++0,         22,         22,        1,  3110400, 0x0fd40e06
++0,         23,         23,        1,  3110400, 0xa10d2d67
++0,         24,         24,        1,  3110400, 0x87c481da
++0,         25,         25,        1,  3110400, 0xe3dca3cd
++0,         26,         26,        1,  3110400, 0x5f77b078
++0,         27,         27,        1,  3110400, 0xf1ddd098
++0,         28,         28,        1,  3110400, 0xedcd1754
++0,         29,         29,        1,  3110400, 0x14ac7153