[FFmpeg-cvslog] Merge commit '38efff92f1ef81f3de20ff0460ec7b70c253d714'

Clément Bœsch git at videolan.org
Tue Jan 24 17:18:12 EET 2017


ffmpeg | branch: master | Clément Bœsch <u at pkh.me> | Tue Jan 17 15:26:38 2017 +0100| [744801989099df26e90b00062c645969c5347533] | committer: Clément Bœsch

Merge commit '38efff92f1ef81f3de20ff0460ec7b70c253d714'

* 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 at pkh.me>
Merged-by: Matthieu Bouron <matthieu.bouron at gmail.com>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=744801989099df26e90b00062c645969c5347533
---

 libavcodec/h264_slice.c              | 260 +++++++++++++++++++----------------
 libavcodec/h264dec.c                 |  67 +++------
 libavcodec/h264dec.h                 |  27 ++--
 tests/fate/h264.mak                  |   4 +
 tests/ref/fate/h264-twofields-packet |  35 +++++
 5 files changed, 210 insertions(+), 183 deletions(-)

diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c
index ad7a75f..6b555ab 100644
--- a/libavcodec/h264_slice.c
+++ b/libavcodec/h264_slice.c
@@ -1849,119 +1849,12 @@ static int h264_slice_header_parse(const H264Context *h, H264SliceContext *sl,
     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->picture_idr && nal->type != H264_NAL_IDR_SLICE) {
         av_log(h->avctx, AV_LOG_ERROR, "Invalid mix of IDR and non-IDR slices\n");
@@ -2009,7 +1902,7 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl,
          nal->ref_idc == 0))
         sl->deblocking_filter = 0;
 
-    if (sl->deblocking_filter == 1 && h->max_contexts > 1) {
+    if (sl->deblocking_filter == 1 && h->nb_slice_ctx > 1) {
         if (h->avctx->flags2 & AV_CODEC_FLAG2_FAST) {
             /* Cheat slightly for speed:
              * Do not bother to deblock across slices. */
@@ -2093,6 +1986,129 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl,
     return 0;
 }
 
+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;
+
+    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) {
+            // 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->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 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) {
@@ -2678,33 +2694,35 @@ finish:
  * Call decode_slice() for each context.
  *
  * @param h h264 master context
- * @param context_count number of contexts to execute
  */
-int ff_h264_execute_decode_slices(H264Context *h, unsigned context_count)
+int ff_h264_execute_decode_slices(H264Context *h)
 {
     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);
-
     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++) {
@@ -2759,5 +2777,7 @@ int ff_h264_execute_decode_slices(H264Context *h, unsigned context_count)
         }
     }
 
-    return 0;
+finish:
+    h->nb_slice_ctx_queued = 0;
+    return ret;
 }
diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c
index 41e6ce4..31db1db 100644
--- a/libavcodec/h264dec.c
+++ b/libavcodec/h264dec.c
@@ -602,7 +602,6 @@ static void debug_green_metadata(const H264SEIGreenMetaData *gm, void *logctx)
 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;
@@ -610,7 +609,6 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size)
     h->has_slice = 0;
     h->nal_unit_type= 0;
 
-    h->max_contexts = h->nb_slice_ctx;
     if (!(avctx->flags2 & AV_CODEC_FLAG2_CHUNKS)) {
         h->current_slice = 0;
         if (!h->first_field)
@@ -640,14 +638,12 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size)
 
     for (i = 0; i < h->pkt.nb_nals; i++) {
         H2645NAL *nal = &h->pkt.nals[i];
-        H264SliceContext *sl = &h->slice_ctx[context_count];
-        int err;
+        int max_slice_ctx, err;
 
         if (avctx->skip_frame >= AVDISCARD_NONREF &&
             nal->ref_idc == 0 && nal->type != H264_NAL_SEI)
             continue;
 
-again:
         // FIXME these should stop being context-global variables
         h->nal_ref_idc   = nal->ref_idc;
         h->nal_unit_type = nal->type;
@@ -672,13 +668,9 @@ again:
             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 (h->current_slice == 1) {
@@ -698,14 +690,14 @@ again:
 #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 (h->avctx->hwaccel) {
+                    ret = avctx->hwaccel->decode_slice(avctx, nal->raw_data, nal->raw_size);
+                    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,
@@ -713,9 +705,13 @@ again:
                 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:
@@ -765,34 +761,14 @@ FF_ENABLE_DEPRECATION_WARNINGS
                    nal->type, nal->size_bits);
         }
 
-        if (context_count == h->max_contexts) {
-            ret = ff_h264_execute_decode_slices(h, context_count);
-            if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE))
-                goto end;
-            context_count = 0;
-        }
-
-        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 == SLICE_SINGLETHREAD) {
-            if (context_count > 0) {
-                ret = ff_h264_execute_decode_slices(h, context_count);
-                if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE))
-                    goto end;
-                context_count = 0;
-            }
-            /* Slice could not be decoded in parallel mode, restart. */
-            sl               = &h->slice_ctx[0];
-            goto again;
+        if (err < 0) {
+            av_log(h->avctx, AV_LOG_ERROR, "decode_slice_header error\n");
         }
     }
-    if (context_count) {
-        ret = ff_h264_execute_decode_slices(h, context_count);
-        if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE))
-            goto end;
-    }
+
+    ret = ff_h264_execute_decode_slices(h);
+    if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE))
+        goto end;
 
     ret = 0;
 end:
@@ -1013,6 +989,7 @@ static int h264_decode_frame(AVCodecContext *avctx, void *data,
 
     h->flags = avctx->flags;
     h->setup_finished = 0;
+    h->nb_slice_ctx_queued = 0;
 
     if (h->backup_width != -1) {
         avctx->width    = h->backup_width;
diff --git a/libavcodec/h264dec.h b/libavcodec/h264dec.h
index fa5c98e..5f868b7 100644
--- a/libavcodec/h264dec.h
+++ b/libavcodec/h264dec.h
@@ -353,6 +353,7 @@ typedef struct H264Context {
 
     H264SliceContext *slice_ctx;
     int            nb_slice_ctx;
+    int            nb_slice_ctx_queued;
 
     H2645Packet pkt;
 
@@ -491,20 +492,6 @@ typedef struct H264Context {
      */
     int current_slice;
 
-    /**
-     * Max number of threads / contexts.
-     * This is equal to AVCodecContext.thread_count unless
-     * multithreaded decoding is impossible, in which case it is
-     * reduced to 1.
-     */
-    int max_contexts;
-
-    /**
-     *  1 if the single thread fallback warning has already been
-     *  displayed, 0 otherwise.
-     */
-    int single_decode_warning;
-
     /** @} */
 
     /**
@@ -848,10 +835,14 @@ void ff_h264_draw_horiz_band(const H264Context *h, H264SliceContext *sl, int y,
 
 int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl,
                                 const H2645NAL *nal);
-#define SLICE_SINGLETHREAD 1
-#define SLICE_SKIPED 2
-
-int ff_h264_execute_decode_slices(H264Context *h, unsigned context_count);
+/**
+ * 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);
 
diff --git a/tests/fate/h264.mak b/tests/fate/h264.mak
index 1f6e5f3..52b6a98 100644
--- a/tests/fate/h264.mak
+++ b/tests/fate/h264.mak
@@ -215,6 +215,9 @@ FATE_H264-$(call DEMDEC,  MOV, H264) += fate-h264-mixed-nal-coding
 # this sample has invalid extradata that is not escaped
 FATE_H264-$(call DEMDEC,  MOV, H264) += fate-h264-unescaped-extradata
 
+# 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
@@ -431,6 +434,7 @@ fate-h264-intra-refresh-recovery:                 CMD = framecrc -i $(TARGET_SAM
 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
diff --git a/tests/ref/fate/h264-twofields-packet b/tests/ref/fate/h264-twofields-packet
new file mode 100644
index 0000000..4cff0a1
--- /dev/null
+++ b/tests/ref/fate/h264-twofields-packet
@@ -0,0 +1,35 @@
+#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


======================================================================

diff --cc libavcodec/h264_slice.c
index ad7a75f,8d79740..6b555ab
--- a/libavcodec/h264_slice.c
+++ b/libavcodec/h264_slice.c
@@@ -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;
@@@ -2093,6 -1849,75 +1986,129 @@@
      return 0;
  }
  
+ 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;
+ 
 -    ret = h264_slice_header_parse(sl, nal, &h->ps, h->avctx);
++    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->setup_finished) {
 -        if (sl->first_mb_addr == 0) { // FIXME better field boundary detection
++    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 && 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 (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 == 0) {
 -            ret = h264_field_start(h, sl, nal);
 -            if (ret < 0)
 -                return ret;
++    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;
+ 
 -    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++;
 -    }
++    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;
diff --cc libavcodec/h264dec.c
index 41e6ce4,1086eab..31db1db
--- a/libavcodec/h264dec.c
+++ b/libavcodec/h264dec.c
@@@ -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->has_slice = 0;
 +    h->nal_unit_type= 0;
 +
-     h->max_contexts = h->nb_slice_ctx;
      if (!(avctx->flags2 & AV_CODEC_FLAG2_CHUNKS)) {
          h->current_slice = 0;
          if (!h->first_field)
@@@ -655,67 -544,26 +651,67 @@@
          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);
diff --cc libavcodec/h264dec.h
index fa5c98e,f934fc4..5f868b7
--- a/libavcodec/h264dec.h
+++ b/libavcodec/h264dec.h
@@@ -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);
  
 +int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl,
 +                                const H2645NAL *nal);
- #define SLICE_SINGLETHREAD 1
- #define SLICE_SKIPED 2
- 
- int ff_h264_execute_decode_slices(H264Context *h, unsigned context_count);
+ /**
+  * 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);
  
diff --cc tests/fate/h264.mak
index 1f6e5f3,ff1dd15..52b6a98
--- a/tests/fate/h264.mak
+++ b/tests/fate/h264.mak
@@@ -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
  
+ # 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) += fate-h264-bsf-mp4toannexb
 +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
diff --cc tests/ref/fate/h264-twofields-packet
index 0000000,fc2b9f9..4cff0a1
mode 000000,100644..100644
--- a/tests/ref/fate/h264-twofields-packet
+++ b/tests/ref/fate/h264-twofields-packet
@@@ -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



More information about the ffmpeg-cvslog mailing list