Merge commit 'e26c64148be8a20ace7512d96503172fb5e9753b'
authorTimothy Gu <timothygu99@gmail.com>
Thu, 4 Aug 2016 02:46:06 +0000 (19:46 -0700)
committerTimothy Gu <timothygu99@gmail.com>
Thu, 4 Aug 2016 02:50:06 +0000 (19:50 -0700)
* commit 'e26c64148be8a20ace7512d96503172fb5e9753b':
  h264: discard slices of redundant pictures right after parsing the slice header

Conflicts:
libavcodec/h264_slice.c
libavcodec/h264dec.c

TODO: fix indentation

Merged-by: Timothy Gu <timothygu99@gmail.com>
1  2 
libavcodec/h264_slice.c
libavcodec/h264dec.c

@@@ -1738,62 -1565,30 +1738,66 @@@ int ff_h264_decode_slice_header(H264Con
      if (ret < 0)
          return ret;
  
 -    if (!h->setup_finished) {
 -        if (sl->first_mb_addr == 0) { // FIXME better field boundary detection
 -            if (h->current_slice && h->cur_pic_ptr && FIELD_PICTURE(h)) {
 -                ff_h264_field_end(h, sl, 1);
 -            }
+     // 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;
 +        }
 +    }
  
 -            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) { // 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);
 +                h->current_slice = 0;
 +                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);
 +                h->current_slice = 0;
 +                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 SLICE_SKIPED;
          }
      }
  
@@@ -799,25 -701,18 +799,28 @@@ again
              if ((err = ff_h264_decode_slice_header(h, sl, nal)))
                  break;
  
 -            if (h->sei.recovery_point.recovery_frame_cnt >= 0 && h->recovery_frame < 0) {
 -                h->recovery_frame = (h->poc.frame_num + h->sei.recovery_point.recovery_frame_cnt) &
 -                                    ((1 << h->ps.sps->log2_max_frame_num) - 1);
+             if (sl->redundant_pic_count > 0)
+                 break;
 +            if (h->sei.recovery_point.recovery_frame_cnt >= 0) {
 +                const int sei_recovery_frame_cnt = h->sei.recovery_point.recovery_frame_cnt;
 +
 +                if (h->poc.frame_num != 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->poc.frame_num, h->ps.sps->log2_max_frame_num) > sei_recovery_frame_cnt) {
 +                    h->recovery_frame = av_mod_uintp2(h->poc.frame_num + sei_recovery_frame_cnt, h->ps.sps->log2_max_frame_num);
 +
 +                    if (!h->valid_recovery_point)
 +                        h->recovery_frame = h->poc.frame_num;
 +                }
              }
  
 -            h->cur_pic_ptr->f->key_frame |=
 -                (nal->type == H264_NAL_IDR_SLICE) || (h->sei.recovery_point.recovery_frame_cnt >= 0);
 +            h->cur_pic_ptr->f->key_frame |= (nal->type == H264_NAL_IDR_SLICE);
  
 -            if (nal->type == H264_NAL_IDR_SLICE || h->recovery_frame == h->poc.frame_num) {
 +            if (nal->type == H264_NAL_IDR_SLICE ||
 +                (h->recovery_frame == h->poc.frame_num && nal->ref_idc)) {
                  h->recovery_frame         = -1;
                  h->cur_pic_ptr->recovered = 1;
              }
              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 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 (sl->redundant_pic_count == 0) {
 -            if ((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 (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],
 +                                            nal->raw_data,
 +                                            nal->raw_size);
 +#endif
                  } else
                      context_count++;
--            }
              break;
          case H264_NAL_DPA:
          case H264_NAL_DPB: