OSDN Git Service

Merge commit 'ca2f19b9cc37be509d85f05c8f902860475905f8'
authorHendrik Leppkes <h.leppkes@gmail.com>
Sat, 7 May 2016 08:31:13 +0000 (10:31 +0200)
committerDerek Buitenhuis <derek.buitenhuis@gmail.com>
Sat, 7 May 2016 20:13:44 +0000 (21:13 +0100)
* commit 'ca2f19b9cc37be509d85f05c8f902860475905f8':
  h264: switch to h2645_parse for NAL parsing

Merged-by: Hendrik Leppkes <h.leppkes@gmail.com>
1  2 
libavcodec/Makefile
libavcodec/h264.c
libavcodec/h264.h

@@@ -308,10 -251,11 +308,12 @@@ OBJS-$(CONFIG_H263_ENCODER)            
  OBJS-$(CONFIG_H264_DECODER)            += h264.o h264_cabac.o h264_cavlc.o \
                                            h264_direct.o h264_loopfilter.o  \
                                            h264_mb.o h264_picture.o h264_ps.o \
-                                           h264_refs.o h264_sei.o h264_slice.o h264data.o h264_parse.o
+                                           h264_refs.o h264_sei.o \
+                                           h264_slice.o h264data.o h264_parse.o \
+                                           h2645_parse.o
 +OBJS-$(CONFIG_H264_MEDIACODEC_DECODER) += mediacodecdec_h264.o
  OBJS-$(CONFIG_H264_MMAL_DECODER)       += mmaldec.o
 -OBJS-$(CONFIG_H264_NVENC_ENCODER)      += nvenc_h264.o
 +OBJS-$(CONFIG_H264_VDA_DECODER)        += vda_h264_dec.o
  OBJS-$(CONFIG_H264_QSV_DECODER)        += qsvdec_h2645.o
  OBJS-$(CONFIG_H264_QSV_ENCODER)        += qsvenc_h264.o
  OBJS-$(CONFIG_HAP_DECODER)             += hapdec.o hap.o
@@@ -1179,65 -1125,14 +1161,19 @@@ int ff_set_ref_count(H264Context *h, H2
      return 0;
  }
  
- static int get_bit_length(H264Context *h, const uint8_t *buf,
-                           const uint8_t *ptr, int dst_length,
-                           int i, int next_avc)
- {
-     if ((h->workaround_bugs & FF_BUG_AUTODETECT) && i + 3 < next_avc &&
-         buf[i]     == 0x00 && buf[i + 1] == 0x00 &&
-         buf[i + 2] == 0x01 && buf[i + 3] == 0xE0)
-         h->workaround_bugs |= FF_BUG_TRUNCATED;
-     if (!(h->workaround_bugs & FF_BUG_TRUNCATED))
-         while (dst_length > 0 && ptr[dst_length - 1] == 0)
-             dst_length--;
-     if (!dst_length)
-         return 0;
-     return 8 * dst_length - decode_rbsp_trailing(h, ptr + dst_length - 1);
- }
- static int get_last_needed_nal(H264Context *h, const uint8_t *buf, int buf_size)
++#if FF_API_CAP_VDPAU
 +static const uint8_t start_code[] = { 0x00, 0x00, 0x01 };
++#endif
 +
+ static int get_last_needed_nal(H264Context *h)
  {
-     int next_avc    = h->is_avc ? 0 : buf_size;
-     int nal_index   = 0;
-     int buf_index   = 0;
      int nals_needed = 0;
 +    int first_slice = 0;
+     int i;
  
-     while(1) {
+     for (i = 0; i < h->pkt.nb_nals; i++) {
+         H2645NAL *nal = &h->pkt.nals[i];
          GetBitContext gb;
-         int nalsize = 0;
-         int dst_length, bit_length, consumed;
-         const uint8_t *ptr;
-         if (buf_index >= next_avc) {
-             nalsize = get_avc_nalsize(h, buf, buf_size, &buf_index);
-             if (nalsize < 0)
-                 break;
-             next_avc = buf_index + nalsize;
-         } else {
-             buf_index = find_start_code(buf, buf_size, buf_index, next_avc);
-             if (buf_index >= buf_size)
-                 break;
-             if (buf_index >= next_avc)
-                 continue;
-         }
-         ptr = ff_h264_decode_nal(h, &h->slice_ctx[0], buf + buf_index, &dst_length, &consumed,
-                                  next_avc - buf_index);
-         if (!ptr || dst_length < 0)
-             return AVERROR_INVALIDDATA;
-         buf_index += consumed;
-         bit_length = get_bit_length(h, buf, ptr, dst_length,
-                                     buf_index, next_avc);
-         nal_index++;
  
          /* packets can sometimes contain multiple PPS/SPS,
           * e.g. two PAFF field pictures in one packet, or a demuxer
          case NAL_DPA:
          case NAL_IDR_SLICE:
          case NAL_SLICE:
-             init_get_bits(&gb, ptr, bit_length);
 -            init_get_bits(&gb, nal->data + 1, (nal->size - 1) * 8);
 -            if (!get_ue_golomb(&gb))
++            init_get_bits8(&gb, nal->data + 1, (nal->size - 1));
 +            if (!get_ue_golomb_long(&gb) ||  // first_mb_in_slice
 +                !first_slice ||
-                 first_slice != h->nal_unit_type)
-                 nals_needed = nal_index;
++                first_slice != nal->type)
+                 nals_needed = i;
 +            if (!first_slice)
-                 first_slice = h->nal_unit_type;
++                first_slice = nal->type;
          }
      }
  
@@@ -1268,19 -1159,10 +1204,15 @@@ static int decode_nal_units(H264Contex
                              int parse_extradata)
  {
      AVCodecContext *const avctx = h->avctx;
-     H264SliceContext *sl;
-     int buf_index;
-     unsigned context_count;
-     int next_avc;
+     unsigned context_count = 0;
      int nals_needed = 0; ///< number of NALs that need decoding before the next frame thread starts
-     int nal_index;
 +    int idr_cleared=0;
-     int ret = 0;
+     int i, ret = 0;
  
 +    h->nal_unit_type= 0;
 +
 +    if(!h->slice_context_count)
 +         h->slice_context_count= 1;
      h->max_contexts = h->slice_context_count;
      if (!(avctx->flags2 & AV_CODEC_FLAG2_CHUNKS)) {
          h->current_slice = 0;
          ff_h264_reset_sei(h);
      }
  
-     if (avctx->active_thread_type & FF_THREAD_FRAME)
-         nals_needed = get_last_needed_nal(h, buf, buf_size);
-     {
-         buf_index     = 0;
-         context_count = 0;
-         next_avc      = h->is_avc ? 0 : buf_size;
-         nal_index     = 0;
-         for (;;) {
-             int consumed;
-             int dst_length;
-             int bit_length;
-             const uint8_t *ptr;
-             int nalsize = 0;
-             int err;
-             if (buf_index >= next_avc) {
-                 nalsize = get_avc_nalsize(h, buf, buf_size, &buf_index);
-                 if (nalsize < 0)
-                     break;
-                 next_avc = buf_index + nalsize;
-             } else {
-                 buf_index = find_start_code(buf, buf_size, buf_index, next_avc);
-                 if (buf_index >= buf_size)
-                     break;
-                 if (buf_index >= next_avc)
-                     continue;
-             }
-             sl = &h->slice_ctx[context_count];
-             ptr = ff_h264_decode_nal(h, sl, buf + buf_index, &dst_length,
-                                      &consumed, next_avc - buf_index);
-             if (!ptr || dst_length < 0) {
-                 ret = -1;
-                 goto end;
-             }
-             bit_length = get_bit_length(h, buf, ptr, dst_length,
-                                         buf_index + consumed, next_avc);
-             if (h->avctx->debug & FF_DEBUG_STARTCODE)
-                 av_log(h->avctx, AV_LOG_DEBUG,
-                        "NAL %d/%d at %d/%d length %d\n",
-                        h->nal_unit_type, h->nal_ref_idc, buf_index, buf_size, dst_length);
 +    if (h->nal_length_size == 4) {
 +        if (buf_size > 8 && AV_RB32(buf) == 1 && AV_RB32(buf+5) > (unsigned)buf_size) {
 +            h->is_avc = 0;
 +        }else if(buf_size > 3 && AV_RB32(buf) > 1 && AV_RB32(buf) <= (unsigned)buf_size)
 +            h->is_avc = 1;
 +    }
 +
+     ret = ff_h2645_packet_split(&h->pkt, buf, buf_size, avctx, h->is_avc,
+                                 h->nal_length_size, avctx->codec_id);
+     if (ret < 0) {
+         av_log(avctx, AV_LOG_ERROR,
+                "Error splitting the input into NAL units.\n");
+         return ret;
+     }
  
-             if (h->is_avc && (nalsize != consumed) && nalsize)
-                 av_log(h->avctx, AV_LOG_DEBUG,
-                        "AVC: Consumed only %d bytes instead of %d\n",
-                        consumed, nalsize);
+     if (avctx->active_thread_type & FF_THREAD_FRAME)
+         nals_needed = get_last_needed_nal(h);
  
-             buf_index += consumed;
-             nal_index++;
+     for (i = 0; i < h->pkt.nb_nals; i++) {
+         H2645NAL *nal = &h->pkt.nals[i];
+         H264SliceContext *sl = &h->slice_ctx[context_count];
+         int err;
  
-             if (avctx->skip_frame >= AVDISCARD_NONREF &&
-                 h->nal_ref_idc == 0 &&
-                 h->nal_unit_type != NAL_SEI)
-                 continue;
+         if (avctx->skip_frame >= AVDISCARD_NONREF &&
+             nal->ref_idc == 0 && nal->type != NAL_SEI)
+             continue;
  
  again:
-             /* Ignore per frame NAL unit type during extradata
-              * parsing. Decoding slices is not possible in codec init
-              * with frame-mt */
-             if (parse_extradata) {
-                 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",
-                            h->nal_unit_type);
-                     // fall through to next case
-                 case NAL_AUXILIARY_SLICE:
-                     h->nal_unit_type = NAL_FF_IGNORE;
-                 }
 -        /* Ignore every NAL unit type except PPS and SPS during extradata
++        /* 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) &&
 -            (nal->type != NAL_PPS && nal->type != NAL_SPS)) {
 -            if (nal->type < NAL_AUD || nal->type > NAL_AUXILIARY_SLICE)
 -                av_log(avctx, AV_LOG_INFO,
 -                       "Ignoring NAL unit %d during extradata parsing\n",
++        if (parse_extradata) {
++            switch (nal->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",
+                        nal->type);
 -            nal->type = NAL_FF_IGNORE;
++                // fall through to next case
++            case NAL_AUXILIARY_SLICE:
++                nal->type = NAL_FF_IGNORE;
 +            }
+         }
  
-             err = 0;
+         // FIXME these should stop being context-global variables
+         h->nal_ref_idc   = nal->ref_idc;
+         h->nal_unit_type = nal->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");
-                     ret = -1;
+         err = 0;
+         switch (nal->type) {
+         case NAL_IDR_SLICE:
++            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 (nal->type != NAL_IDR_SLICE) {
+                 av_log(h->avctx, AV_LOG_ERROR,
+                        "Invalid mix of idr and non-idr slices\n");
+                 ret = -1;
+                 goto end;
+             }
 -            idr(h); // FIXME ensure we don't lose some frames if there is reordering
++            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;
 +                }
-                 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 NAL_SLICE:
-                 init_get_bits(&sl->gb, ptr, bit_length);
-                 if (   nals_needed >= nal_index
-                     || (!(avctx->active_thread_type & FF_THREAD_FRAME) && !context_count))
-                     h->au_pps_id = -1;
++                idr(h); // FIXME ensure we don't lose some frames if there is reordering
++            }
++            idr_cleared = 1;
++            h->has_recovery_point = 1;
+         case NAL_SLICE:
+             sl->gb = nal->gb;
++            if (   nals_needed >= i
++                || (!(avctx->active_thread_type & FF_THREAD_FRAME) && !context_count))
++                h->au_pps_id = -1;
  
-                 if ((err = ff_h264_decode_slice_header(h, sl)))
-                     break;
+             if ((err = ff_h264_decode_slice_header(h, sl)))
+                 break;
  
-                 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->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
-                         || av_mod_uintp2(h->recovery_frame - h->frame_num, h->sps.log2_max_frame_num) > h->sei_recovery_frame_cnt) {
-                         h->recovery_frame = av_mod_uintp2(h->frame_num + h->sei_recovery_frame_cnt, h->sps.log2_max_frame_num);
++                if (   h->recovery_frame < 0
++                    || av_mod_uintp2(h->recovery_frame - h->frame_num, h->sps.log2_max_frame_num) > h->sei_recovery_frame_cnt) {
++                    h->recovery_frame = av_mod_uintp2(h->frame_num + h->sei_recovery_frame_cnt, h->sps.log2_max_frame_num);
 +
-                         if (!h->valid_recovery_point)
-                             h->recovery_frame = h->frame_num;
-                     }
++                    if (!h->valid_recovery_point)
++                        h->recovery_frame = h->frame_num;
 +                }
+             }
  
-                 h->cur_pic_ptr->f->key_frame |=
-                     (h->nal_unit_type == NAL_IDR_SLICE);
 -            h->cur_pic_ptr->f->key_frame |=
 -                (nal->type == NAL_IDR_SLICE) || (h->sei_recovery_frame_cnt >= 0);
++            h->cur_pic_ptr->f->key_frame |= (nal->type == NAL_IDR_SLICE);
  
-                 if (h->nal_unit_type == NAL_IDR_SLICE ||
-                     (h->recovery_frame == h->frame_num && h->nal_ref_idc)) {
-                     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 (h->nal_unit_type == NAL_IDR_SLICE)
-                     h->frame_recovered |= FRAME_RECOVERED_IDR;
 -            if (nal->type == NAL_IDR_SLICE || h->recovery_frame == h->frame_num) {
++            if (nal->type == NAL_IDR_SLICE ||
++                (h->recovery_frame == h->frame_num && nal->ref_idc)) {
+                 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 (nal->type == NAL_IDR_SLICE)
+                 h->frame_recovered |= FRAME_RECOVERED_IDR;
 +#if 1
-                 h->cur_pic_ptr->recovered |= h->frame_recovered;
++            h->cur_pic_ptr->recovered |= h->frame_recovered;
 +#else
-                 h->cur_pic_ptr->recovered |= !!(h->frame_recovered & FRAME_RECOVERED_IDR);
+             h->cur_pic_ptr->recovered |= !!(h->frame_recovered & FRAME_RECOVERED_IDR);
 +#endif
  
-                 if (h->current_slice == 1) {
-                     if (!(avctx->flags2 & AV_CODEC_FLAG2_CHUNKS))
-                         decode_postinit(h, nal_index >= nals_needed);
+             if (h->current_slice == 1) {
+                 if (!(avctx->flags2 & AV_CODEC_FLAG2_CHUNKS))
+                     decode_postinit(h, i >= nals_needed);
  
-                     if (h->avctx->hwaccel &&
-                         (ret = h->avctx->hwaccel->start_frame(h->avctx, buf, buf_size)) < 0)
-                         goto end;
+                 if (h->avctx->hwaccel &&
 -                    (ret = h->avctx->hwaccel->start_frame(h->avctx, NULL, 0)) < 0)
 -                    return ret;
++                    (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);
++                if (CONFIG_H264_VDPAU_DECODER &&
++                    h->avctx->codec->capabilities & AV_CODEC_CAP_HWACCEL_VDPAU)
++                    ff_vdpau_h264_picture_start(h);
 +#endif
-                 }
+             }
  
-                 if (sl->redundant_pic_count == 0) {
-                     if (avctx->hwaccel) {
-                         ret = avctx->hwaccel->decode_slice(avctx,
-                                                            &buf[buf_index - consumed],
-                                                            consumed);
-                         if (ret < 0)
-                             goto end;
 -            if (sl->redundant_pic_count == 0 &&
 -                (avctx->skip_frame < AVDISCARD_NONREF || nal->ref_idc) &&
 -                (avctx->skip_frame < AVDISCARD_BIDIR  ||
 -                 sl->slice_type_nos != AV_PICTURE_TYPE_B) &&
 -                (avctx->skip_frame < AVDISCARD_NONKEY ||
 -                 h->cur_pic_ptr->f->key_frame) &&
 -                avctx->skip_frame < AVDISCARD_ALL) {
++            if (sl->redundant_pic_count == 0) {
+                 if (avctx->hwaccel) {
 -                    ret = avctx->hwaccel->decode_slice(avctx, nal->raw_data, nal->raw_size);
++                    ret = avctx->hwaccel->decode_slice(avctx,
++                                                       nal->raw_data,
++                                                       nal->raw_size);
+                     if (ret < 0)
 -                        return ret;
++                        goto end;
 +#if FF_API_CAP_VDPAU
-                     } else 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],
-                                                 &buf[buf_index - consumed],
-                                                 consumed);
++                } else 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
-                     } else
-                         context_count++;
-                 }
-                 break;
-             case NAL_DPA:
-             case NAL_DPB:
-             case NAL_DPC:
-                 avpriv_request_sample(avctx, "data partitioning");
+                 } else
+                     context_count++;
+             }
+             break;
+         case NAL_DPA:
+         case NAL_DPB:
+         case NAL_DPC:
+             avpriv_request_sample(avctx, "data partitioning");
 -            ret = AVERROR(ENOSYS);
 -            goto end;
+             break;
+         case NAL_SEI:
+             h->gb = nal->gb;
+             ret = ff_h264_decode_sei(h);
+             if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE))
+                 goto end;
+             break;
+         case NAL_SPS:
+             h->gb = nal->gb;
 -            ret = ff_h264_decode_seq_parameter_set(h);
 -            if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE))
 -                goto end;
++            if (ff_h264_decode_seq_parameter_set(h, 0) >= 0)
 +                break;
-             case NAL_SEI:
-                 init_get_bits(&h->gb, ptr, bit_length);
-                 ret = ff_h264_decode_sei(h);
-                 if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE))
-                     goto end;
++            av_log(h->avctx, AV_LOG_DEBUG,
++                   "SPS decoding failure, trying again with the complete NAL\n");
++            init_get_bits8(&h->gb, nal->raw_data + 1, nal->raw_size - 1);
++            if (ff_h264_decode_seq_parameter_set(h, 0) >= 0)
 +                break;
-             case NAL_SPS:
-                 init_get_bits(&h->gb, ptr, bit_length);
-                 if (ff_h264_decode_seq_parameter_set(h, 0) >= 0)
-                     break;
-                 if (h->is_avc ? nalsize : 1) {
-                     av_log(h->avctx, AV_LOG_DEBUG,
-                            "SPS decoding failure, trying again with the complete NAL\n");
-                     if (h->is_avc)
-                         av_assert0(next_avc - buf_index + consumed == nalsize);
-                     if ((next_avc - buf_index + consumed - 1) >= INT_MAX/8)
-                         break;
-                     init_get_bits(&h->gb, &buf[buf_index + 1 - consumed],
-                                   8*(next_avc - buf_index + consumed - 1));
-                     if (ff_h264_decode_seq_parameter_set(h, 0) >= 0)
-                         break;
-                 }
-                 init_get_bits(&h->gb, ptr, bit_length);
-                 ff_h264_decode_seq_parameter_set(h, 1);
++            h->gb = nal->gb;
++            ff_h264_decode_seq_parameter_set(h, 1);
 +
-                 break;
-             case NAL_PPS:
-                 init_get_bits(&h->gb, ptr, bit_length);
-                 ret = ff_h264_decode_picture_parameter_set(h, bit_length);
-                 if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE))
-                     goto end;
-                 break;
-             case NAL_AUD:
-             case NAL_END_SEQUENCE:
-             case NAL_END_STREAM:
-             case NAL_FILLER_DATA:
-             case NAL_SPS_EXT:
-             case NAL_AUXILIARY_SLICE:
-                 break;
-             case NAL_FF_IGNORE:
-                 break;
-             default:
-                 av_log(avctx, AV_LOG_DEBUG, "Unknown NAL code: %d (%d bits)\n",
-                        h->nal_unit_type, bit_length);
-             }
+             break;
+         case NAL_PPS:
+             h->gb = nal->gb;
+             ret = ff_h264_decode_picture_parameter_set(h, nal->size_bits);
+             if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE))
+                 goto end;
+             break;
+         case NAL_AUD:
+         case NAL_END_SEQUENCE:
+         case NAL_END_STREAM:
+         case NAL_FILLER_DATA:
+         case NAL_SPS_EXT:
+         case NAL_AUXILIARY_SLICE:
+             break;
+         case NAL_FF_IGNORE:
+             break;
+         default:
+             av_log(avctx, AV_LOG_DEBUG, "Unknown NAL code: %d (%d bits)\n",
+                    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 (context_count == h->max_contexts) {
-                 ret = ff_h264_execute_decode_slices(h, context_count);
 -        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) {
++            if (context_count > 1) {
++                ret = ff_h264_execute_decode_slices(h, context_count - 1);
 +                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 > 1) {
-                     ret = ff_h264_execute_decode_slices(h, context_count - 1);
-                     if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE))
-                         goto end;
-                     context_count = 0;
-                 }
-                 /* 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. */
-                 sl               = &h->slice_ctx[0];
-                 goto again;
-             }
+             /* 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. */
+             sl               = &h->slice_ctx[0];
+             goto again;
          }
      }
      if (context_count) {
  
      ret = 0;
  end:
-     sl = h->slice_ctx;
 +
 +#if CONFIG_ERROR_RESILIENCE
 +    /*
 +     * FIXME: Error handling code does not seem to support interlaced
 +     * when slices span multiple rows
 +     * The ff_er_add_slice calls don't work right for bottom
 +     * fields; they cause massive erroneous error concealing
 +     * Error marking covers both fields (top and bottom).
 +     * This causes a mismatched s->error_count
 +     * and a bad error table. Further, the error count goes to
 +     * INT_MAX when called for bottom field, because mb_y is
 +     * past end by one (callers fault) and resync_mb_y != 0
 +     * causes problems for the first MB line, too.
 +     */
 +    if (!FIELD_PICTURE(h) && h->current_slice && !h->sps.new && h->enable_er) {
++        H264SliceContext *sl = h->slice_ctx;
 +        int use_last_pic = h->last_pic_for_ec.f->buf[0] && !sl->ref_count[0];
 +
 +        ff_h264_set_erpic(&sl->er.cur_pic, h->cur_pic_ptr);
 +
 +        if (use_last_pic) {
 +            ff_h264_set_erpic(&sl->er.last_pic, &h->last_pic_for_ec);
 +            sl->ref_list[0][0].parent = &h->last_pic_for_ec;
 +            memcpy(sl->ref_list[0][0].data, h->last_pic_for_ec.f->data, sizeof(sl->ref_list[0][0].data));
 +            memcpy(sl->ref_list[0][0].linesize, h->last_pic_for_ec.f->linesize, sizeof(sl->ref_list[0][0].linesize));
 +            sl->ref_list[0][0].reference = h->last_pic_for_ec.reference;
 +        } else if (sl->ref_count[0]) {
 +            ff_h264_set_erpic(&sl->er.last_pic, sl->ref_list[0][0].parent);
 +        } else
 +            ff_h264_set_erpic(&sl->er.last_pic, NULL);
 +
 +        if (sl->ref_count[1])
 +            ff_h264_set_erpic(&sl->er.next_pic, sl->ref_list[1][0].parent);
 +
 +        sl->er.ref_count = sl->ref_count[0];
 +
 +        ff_er_frame_end(&sl->er);
 +        if (use_last_pic)
 +            memset(&sl->ref_list[0][0], 0, sizeof(sl->ref_list[0][0]));
 +    }
 +#endif /* CONFIG_ERROR_RESILIENCE */
      /* clean up */
      if (h->cur_pic_ptr && !h->droppable) {
          ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX,
Simple merge