]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/h264_slice.c
avcodec/h264_slice: Use w/h from the AVFrame instead of mb_w/h
[ffmpeg] / libavcodec / h264_slice.c
index 0c0812f472ad69ee467e8d0d16c552ee19de49f2..35ef7bf8d3efccde80091dd32200a763a5c56892 100644 (file)
@@ -383,7 +383,7 @@ void ff_h264_init_dequant_tables(H264Context *h)
     }
 }
 
-#define IN_RANGE(a, b, size) (((a) >= (b)) && ((a) < ((b) + (size))))
+#define IN_RANGE(a, b, size) (((void*)(a) >= (void*)(b)) && ((void*)(a) < (void*)((b) + (size))))
 
 #define REBASE_PICTURE(pic, new_ctx, old_ctx)             \
     (((pic) && (pic) >= (old_ctx)->DPB &&                       \
@@ -397,10 +397,9 @@ static void copy_picture_range(H264Picture **to, H264Picture **from, int count,
     int i;
 
     for (i = 0; i < count; i++) {
-        av_assert1((IN_RANGE(from[i], old_base, 1) ||
-                IN_RANGE(from[i], old_base->DPB,
-                         H264_MAX_PICTURE_COUNT) ||
-                !from[i]));
+        av_assert1(!from[i] ||
+                   IN_RANGE(from[i], old_base, 1) ||
+                   IN_RANGE(from[i], old_base->DPB, H264_MAX_PICTURE_COUNT));
         to[i] = REBASE_PICTURE(from[i], new_base, old_base);
     }
 }
@@ -1151,10 +1150,13 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
     int needs_reinit = 0;
     int field_pic_flag, bottom_field_flag;
     int first_slice = sl == h->slice_ctx && !h->current_slice;
-    int frame_num, picture_structure, droppable;
+    int frame_num, droppable, picture_structure;
     int mb_aff_frame, last_mb_aff_frame;
     PPS *pps;
 
+    if (first_slice)
+        av_assert0(!h->setup_finished);
+
     h->qpel_put = h->h264qpel.put_h264_qpel_pixels_tab;
     h->qpel_avg = h->h264qpel.avg_h264_qpel_pixels_tab;
 
@@ -1162,6 +1164,7 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
 
     if (first_mb_in_slice == 0) { // FIXME better field boundary detection
         if (h->current_slice) {
+            av_assert0(!h->setup_finished);
             if (h->cur_pic_ptr && FIELD_PICTURE(h) && h->first_field) {
                 ff_h264_field_end(h, h->slice_ctx, 1);
                 h->current_slice = 0;
@@ -1219,7 +1222,8 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
      }
 
     // to make a few old functions happy, it's wrong though
-    h->pict_type = sl->slice_type;
+    if (!h->setup_finished)
+        h->pict_type = sl->slice_type;
 
     pps_id = get_ue_golomb(&sl->gb);
     if (pps_id >= MAX_PPS_COUNT) {
@@ -1247,8 +1251,13 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
                h->pps.sps_id);
         return AVERROR_INVALIDDATA;
     }
-    if (first_slice)
+
+    if (first_slice) {
         h->pps = *h->pps_buffers[pps_id];
+    } else if (h->setup_finished && h->dequant_coeff_pps != pps_id) {
+        av_log(h->avctx, AV_LOG_ERROR, "PPS changed between slices\n");
+        return AVERROR_INVALIDDATA;
+    }
 
     if (pps->sps_id != h->sps.sps_id ||
         pps->sps_id != h->current_sps_id ||
@@ -1288,10 +1297,6 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
 
     }
 
-    h->avctx->profile = ff_h264_get_profile(&h->sps);
-    h->avctx->level   = h->sps.level_idc;
-    h->avctx->refs    = h->sps.ref_frame_count;
-
     must_reinit = (h->context_initialized &&
                     (   16*h->sps.mb_width != h->avctx->coded_width
                      || 16*h->sps.mb_height * (2 - h->sps.frame_mbs_only_flag) != h->avctx->coded_height
@@ -1307,31 +1312,37 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
     if (first_slice && av_cmp_q(h->sps.sar, h->avctx->sample_aspect_ratio))
         must_reinit = 1;
 
-    h->mb_width  = h->sps.mb_width;
-    h->mb_height = h->sps.mb_height * (2 - h->sps.frame_mbs_only_flag);
-    h->mb_num    = h->mb_width * h->mb_height;
-    h->mb_stride = h->mb_width + 1;
+    if (!h->setup_finished) {
+        h->avctx->profile = ff_h264_get_profile(&h->sps);
+        h->avctx->level   = h->sps.level_idc;
+        h->avctx->refs    = h->sps.ref_frame_count;
 
-    h->b_stride = h->mb_width * 4;
+        h->mb_width  = h->sps.mb_width;
+        h->mb_height = h->sps.mb_height * (2 - h->sps.frame_mbs_only_flag);
+        h->mb_num    = h->mb_width * h->mb_height;
+        h->mb_stride = h->mb_width + 1;
 
-    h->chroma_y_shift = h->sps.chroma_format_idc <= 1; // 400 uses yuv420p
+        h->b_stride = h->mb_width * 4;
 
-    h->width  = 16 * h->mb_width;
-    h->height = 16 * h->mb_height;
+        h->chroma_y_shift = h->sps.chroma_format_idc <= 1; // 400 uses yuv420p
 
-    ret = init_dimensions(h);
-    if (ret < 0)
-        return ret;
+        h->width  = 16 * h->mb_width;
+        h->height = 16 * h->mb_height;
+
+        ret = init_dimensions(h);
+        if (ret < 0)
+            return ret;
 
-    if (h->sps.video_signal_type_present_flag) {
-        h->avctx->color_range = h->sps.full_range>0 ? AVCOL_RANGE_JPEG
-                                                    : AVCOL_RANGE_MPEG;
-        if (h->sps.colour_description_present_flag) {
-            if (h->avctx->colorspace != h->sps.colorspace)
-                needs_reinit = 1;
-            h->avctx->color_primaries = h->sps.color_primaries;
-            h->avctx->color_trc       = h->sps.color_trc;
-            h->avctx->colorspace      = h->sps.colorspace;
+        if (h->sps.video_signal_type_present_flag) {
+            h->avctx->color_range = h->sps.full_range>0 ? AVCOL_RANGE_JPEG
+                                                        : AVCOL_RANGE_MPEG;
+            if (h->sps.colour_description_present_flag) {
+                if (h->avctx->colorspace != h->sps.colorspace)
+                    needs_reinit = 1;
+                h->avctx->color_primaries = h->sps.color_primaries;
+                h->avctx->color_trc       = h->sps.color_trc;
+                h->avctx->colorspace      = h->sps.colorspace;
+            }
         }
     }
 
@@ -1397,12 +1408,16 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
         }
     }
 
+    if (!h->setup_finished)
+        h->frame_num = frame_num;
+
     sl->mb_mbaff       = 0;
     mb_aff_frame       = 0;
     last_mb_aff_frame  = h->mb_aff_frame;
     last_pic_structure = h->picture_structure;
     last_pic_droppable = h->droppable;
-    droppable          = h->nal_ref_idc == 0;
+
+    droppable = h->nal_ref_idc == 0;
     if (h->sps.frame_mbs_only_flag) {
         picture_structure = PICT_FRAME;
     } else {
@@ -1420,6 +1435,7 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
             mb_aff_frame      = h->sps.mb_aff;
         }
     }
+
     if (h->current_slice) {
         if (last_pic_structure != picture_structure ||
             last_pic_droppable != droppable ||
@@ -1437,9 +1453,11 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
     }
 
     h->picture_structure = picture_structure;
-    h->droppable         = droppable;
-    h->frame_num         = frame_num;
-    h->mb_aff_frame      = mb_aff_frame;
+    if (!h->setup_finished) {
+        h->droppable         = droppable;
+        h->picture_structure = picture_structure;
+        h->mb_aff_frame      = mb_aff_frame;
+    }
     sl->mb_field_decoding_flag = picture_structure != PICT_FRAME;
 
     if (h->current_slice == 0) {
@@ -1552,14 +1570,17 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
              * vectors.  Given we are concealing a lost frame, this probably
              * is not noticeable by comparison, but it should be fixed. */
             if (h->short_ref_count) {
-                if (prev) {
+                if (prev &&
+                    h->short_ref[0]->f->width == prev->f->width &&
+                    h->short_ref[0]->f->height == prev->f->height &&
+                    h->short_ref[0]->f->format == prev->f->format) {
                     av_image_copy(h->short_ref[0]->f->data,
                                   h->short_ref[0]->f->linesize,
                                   (const uint8_t **)prev->f->data,
                                   prev->f->linesize,
-                                  h->avctx->pix_fmt,
-                                  h->mb_width  * 16,
-                                  h->mb_height * 16);
+                                  prev->f->format,
+                                  prev->f->width,
+                                  prev->f->height);
                     h->short_ref[0]->poc = prev->poc + 2;
                 }
                 h->short_ref[0]->frame_num = h->prev_frame_num;
@@ -1621,8 +1642,8 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
         h->last_slice_type = -1;
     }
 
-
-    h->cur_pic_ptr->frame_num = h->frame_num; // FIXME frame_num cleanup
+    if (!h->setup_finished)
+        h->cur_pic_ptr->frame_num = h->frame_num; // FIXME frame_num cleanup
 
     av_assert1(h->mb_num == h->mb_width * h->mb_height);
     if (first_mb_in_slice << FIELD_OR_MBAFF_PICTURE(h) >= h->mb_num ||
@@ -1649,20 +1670,34 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
         get_ue_golomb(&sl->gb); /* idr_pic_id */
 
     if (h->sps.poc_type == 0) {
-        h->poc_lsb = get_bits(&sl->gb, h->sps.log2_max_poc_lsb);
+        int poc_lsb = get_bits(&sl->gb, h->sps.log2_max_poc_lsb);
+
+        if (!h->setup_finished)
+            h->poc_lsb = poc_lsb;
 
-        if (h->pps.pic_order_present == 1 && h->picture_structure == PICT_FRAME)
-            h->delta_poc_bottom = get_se_golomb(&sl->gb);
+        if (h->pps.pic_order_present == 1 && h->picture_structure == PICT_FRAME) {
+            int delta_poc_bottom = get_se_golomb(&sl->gb);
+            if (!h->setup_finished)
+                h->delta_poc_bottom = delta_poc_bottom;
+        }
     }
 
     if (h->sps.poc_type == 1 && !h->sps.delta_pic_order_always_zero_flag) {
-        h->delta_poc[0] = get_se_golomb(&sl->gb);
+        int delta_poc = get_se_golomb(&sl->gb);
+
+        if (!h->setup_finished)
+            h->delta_poc[0] = delta_poc;
+
+        if (h->pps.pic_order_present == 1 && h->picture_structure == PICT_FRAME) {
+            delta_poc = get_se_golomb(&sl->gb);
 
-        if (h->pps.pic_order_present == 1 && h->picture_structure == PICT_FRAME)
-            h->delta_poc[1] = get_se_golomb(&sl->gb);
+            if (!h->setup_finished)
+                h->delta_poc[1] = delta_poc;
+        }
     }
 
-    ff_init_poc(h, h->cur_pic_ptr->field_poc, &h->cur_pic_ptr->poc);
+    if (!h->setup_finished)
+        ff_init_poc(h, h->cur_pic_ptr->field_poc, &h->cur_pic_ptr->poc);
 
     if (h->pps.redundant_pic_cnt_present)
         sl->redundant_pic_count = get_ue_golomb(&sl->gb);
@@ -2318,10 +2353,9 @@ static int decode_slice(struct AVCodecContext *avctx, void *arg)
         for (;;) {
             // START_TIMER
             int ret, eos;
-
-            if (sl->mb_x + sl->mb_y * h->mb_width >= sl->mb_index_end) {
-                av_log(h->avctx, AV_LOG_ERROR, "Slice overlaps next at %d\n",
-                       sl->mb_index_end);
+            if (sl->mb_x + sl->mb_y * h->mb_width >= sl->next_slice_idx) {
+                av_log(h->avctx, AV_LOG_ERROR, "Slice overlaps with next at %d\n",
+                       sl->next_slice_idx);
                 er_add_slice(sl, sl->resync_mb_x, sl->resync_mb_y, sl->mb_x,
                              sl->mb_y, ER_MB_ERROR);
                 return AVERROR_INVALIDDATA;
@@ -2391,9 +2425,9 @@ static int decode_slice(struct AVCodecContext *avctx, void *arg)
         for (;;) {
             int ret;
 
-            if (sl->mb_x + sl->mb_y * h->mb_width >= sl->mb_index_end) {
-                av_log(h->avctx, AV_LOG_ERROR, "Slice overlaps next at %d\n",
-                       sl->mb_index_end);
+            if (sl->mb_x + sl->mb_y * h->mb_width >= sl->next_slice_idx) {
+                av_log(h->avctx, AV_LOG_ERROR, "Slice overlaps with next at %d\n",
+                       sl->next_slice_idx);
                 er_add_slice(sl, sl->resync_mb_x, sl->resync_mb_y, sl->mb_x,
                              sl->mb_y, ER_MB_ERROR);
                 return AVERROR_INVALIDDATA;
@@ -2483,38 +2517,45 @@ int ff_h264_execute_decode_slices(H264Context *h, unsigned context_count)
 {
     AVCodecContext *const avctx = h->avctx;
     H264SliceContext *sl;
-    int i;
+    int i, j;
 
     av_assert0(context_count && h->slice_ctx[context_count - 1].mb_y < h->mb_height);
 
-    h->slice_ctx[0].mb_index_end = INT_MAX;
+    h->slice_ctx[0].next_slice_idx = INT_MAX;
 
     if (h->avctx->hwaccel ||
         h->avctx->codec->capabilities & CODEC_CAP_HWACCEL_VDPAU)
         return 0;
     if (context_count == 1) {
-        int ret = decode_slice(avctx, &h->slice_ctx[0]);
+        int ret;
+
+        h->slice_ctx[0].next_slice_idx = h->mb_width * h->mb_height;
+
+        ret = decode_slice(avctx, &h->slice_ctx[0]);
         h->mb_y = h->slice_ctx[0].mb_y;
         return ret;
     } else {
-        int j, mb_index;
         av_assert0(context_count > 0);
         for (i = 0; i < context_count; i++) {
-            int mb_index_end = h->mb_width * h->mb_height;
+            int next_slice_idx = h->mb_width * h->mb_height;
+            int slice_idx;
+
             sl                 = &h->slice_ctx[i];
-            mb_index = sl->resync_mb_x + sl->resync_mb_y * h->mb_width;
             if (CONFIG_ERROR_RESILIENCE) {
                 sl->er.error_count = 0;
             }
+
+            /* make sure none of those slices overlap */
+            slice_idx = sl->mb_y * h->mb_width + sl->mb_x;
             for (j = 0; j < context_count; j++) {
                 H264SliceContext *sl2 = &h->slice_ctx[j];
-                int mb_index2 = sl2->resync_mb_x + sl2->resync_mb_y * h->mb_width;
+                int        slice_idx2 = sl2->mb_y * h->mb_width + sl2->mb_x;
 
-                if (i==j || mb_index > mb_index2)
+                if (i == j || slice_idx2 < slice_idx)
                     continue;
-                mb_index_end = FFMIN(mb_index_end, mb_index2);
+                next_slice_idx = FFMIN(next_slice_idx, slice_idx2);
             }
-            sl->mb_index_end = mb_index_end;
+            sl->next_slice_idx = next_slice_idx;
         }
 
         avctx->execute(avctx, decode_slice, h->slice_ctx,