Merge commit 'd06e4d8aab9c679b6aea2591d2a9b382df9e5f74'
authorClément Bœsch <clement@stupeflix.com>
Wed, 29 Jun 2016 12:55:02 +0000 (14:55 +0200)
committerClément Bœsch <clement@stupeflix.com>
Wed, 29 Jun 2016 12:55:02 +0000 (14:55 +0200)
* commit 'd06e4d8aab9c679b6aea2591d2a9b382df9e5f74':
  h264: start splitting decode_slice_header()

Merged-by: Clément Bœsch <clement@stupeflix.com>
1  2 
libavcodec/h264_slice.c

@@@ -1003,85 -899,30 +1003,77 @@@ static int h264_slice_header_init(H264C
      h->context_initialized = 1;
  
      return 0;
 +fail:
 +    ff_h264_free_tables(h);
 +    h->context_initialized = 0;
 +    return ret;
 +}
 +
 +static enum AVPixelFormat non_j_pixfmt(enum AVPixelFormat a)
 +{
 +    switch (a) {
 +    case AV_PIX_FMT_YUVJ420P: return AV_PIX_FMT_YUV420P;
 +    case AV_PIX_FMT_YUVJ422P: return AV_PIX_FMT_YUV422P;
 +    case AV_PIX_FMT_YUVJ444P: return AV_PIX_FMT_YUV444P;
 +    default:
 +        return a;
 +    }
  }
  
- /**
-  * 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)
+ static int h264_slice_header_parse(H264Context *h, H264SliceContext *sl)
  {
      const SPS *sps;
      const PPS *pps;
      unsigned int first_mb_in_slice;
      unsigned int pps_id;
      int ret;
-     unsigned int slice_type, tmp, i, j;
+     unsigned int slice_type, tmp, i;
      int last_pic_structure, last_pic_droppable;
 +    int must_reinit;
      int needs_reinit = 0;
      int field_pic_flag, bottom_field_flag;
 +    int first_slice = sl == h->slice_ctx && !h->current_slice;
      int frame_num, droppable, picture_structure;
 -    int mb_aff_frame = 0;
 +    int mb_aff_frame, last_mb_aff_frame;
  
 -    first_mb_in_slice = get_ue_golomb(&sl->gb);
 +    if (first_slice)
 +        av_assert0(!h->setup_finished);
 +
 +    first_mb_in_slice = get_ue_golomb_long(&sl->gb);
  
      if (first_mb_in_slice == 0) { // FIXME better field boundary detection
 -        if (h->current_slice && h->cur_pic_ptr && FIELD_PICTURE(h)) {
 -            ff_h264_field_end(h, sl, 1);
 +        if (h->current_slice) {
 +            if (h->setup_finished) {
 +                av_log(h->avctx, AV_LOG_ERROR, "Too many fields\n");
 +                return AVERROR_INVALIDDATA;
 +            }
 +            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  == 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;
          }
  
 -        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,
          }
      }
  
+     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)
+ {
+     int i, j, ret = 0;
+     ret = h264_slice_header_parse(h, sl);
+     if (ret < 0)
+         return ret;
      if (h->avctx->skip_loop_filter >= AVDISCARD_ALL ||
          (h->avctx->skip_loop_filter >= AVDISCARD_NONKEY &&
 +         h->nal_unit_type != NAL_IDR_SLICE) ||
 +        (h->avctx->skip_loop_filter >= AVDISCARD_NONINTRA &&
           sl->slice_type_nos != AV_PICTURE_TYPE_I) ||
          (h->avctx->skip_loop_filter >= AVDISCARD_BIDIR  &&
           sl->slice_type_nos == AV_PICTURE_TYPE_B) ||
      sl->qp_thresh = 15 -
                     FFMIN(sl->slice_alpha_c0_offset, sl->slice_beta_offset) -
                     FFMAX3(0,
-                           pps->chroma_qp_index_offset[0],
-                           pps->chroma_qp_index_offset[1]) +
-                    6 * (sps->bit_depth_luma - 8);
+                           h->ps.pps->chroma_qp_index_offset[0],
+                           h->ps.pps->chroma_qp_index_offset[1]) +
+                    6 * (h->ps.sps->bit_depth_luma - 8);
  
      sl->slice_num       = ++h->current_slice;
 -    if (sl->slice_num >= MAX_SLICES) {
 -        av_log(h->avctx, AV_LOG_ERROR,
 -               "Too many slices, increase MAX_SLICES and recompile\n");
 +
 +    if (sl->slice_num)
 +        h->slice_row[(sl->slice_num-1)&(MAX_SLICES-1)]= sl->resync_mb_y;
 +    if (   h->slice_row[sl->slice_num&(MAX_SLICES-1)] + 3 >= sl->resync_mb_y
 +        && h->slice_row[sl->slice_num&(MAX_SLICES-1)] <= sl->resync_mb_y
 +        && sl->slice_num >= MAX_SLICES) {
 +        //in case of ASO this check needs to be updated depending on how we decide to assign slice numbers in this case
 +        av_log(h->avctx, AV_LOG_WARNING, "Possibly too many slices (%d >= %d), increase MAX_SLICES and recompile if there are artifacts\n", sl->slice_num, MAX_SLICES);
      }
  
      for (j = 0; j < 2; j++) {