[FFmpeg-devel] [PATCH 2/2] avcodec/h264: Move error resilience from slice to main context

Michael Niedermayer michael at niedermayer.cc
Sun Nov 12 00:16:56 EET 2017


This should fix some issues with slice threads and ER, it may or may not
fix all
---
 libavcodec/h264_slice.c | 26 ++++++++++----------------
 libavcodec/h264dec.c    | 31 +++++++++++++------------------
 libavcodec/h264dec.h    |  2 +-
 3 files changed, 24 insertions(+), 35 deletions(-)

diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c
index da76b9293f..919e66a906 100644
--- a/libavcodec/h264_slice.c
+++ b/libavcodec/h264_slice.c
@@ -25,6 +25,7 @@
  * @author Michael Niedermayer <michaelni at gmx.at>
  */
 
+#include "libavutil/atomic.h"
 #include "libavutil/avassert.h"
 #include "libavutil/display.h"
 #include "libavutil/imgutils.h"
@@ -503,7 +504,7 @@ static int h264_frame_start(H264Context *h)
     h->cur_pic_ptr = pic;
     ff_h264_unref_picture(h, &h->cur_pic);
     if (CONFIG_ERROR_RESILIENCE) {
-        ff_h264_set_erpic(&h->slice_ctx[0].er.cur_pic, NULL);
+        ff_h264_set_erpic(&h->er.cur_pic, NULL);
     }
 
     if ((ret = ff_h264_ref_picture(h, &h->cur_pic, h->cur_pic_ptr)) < 0)
@@ -515,9 +516,9 @@ static int h264_frame_start(H264Context *h)
     }
 
     if (CONFIG_ERROR_RESILIENCE && h->enable_er) {
-        ff_er_frame_start(&h->slice_ctx[0].er);
-        ff_h264_set_erpic(&h->slice_ctx[0].er.last_pic, NULL);
-        ff_h264_set_erpic(&h->slice_ctx[0].er.next_pic, NULL);
+        ff_er_frame_start(&h->er);
+        ff_h264_set_erpic(&h->er.last_pic, NULL);
+        ff_h264_set_erpic(&h->er.next_pic, NULL);
     }
 
     for (i = 0; i < 16; i++) {
@@ -2480,7 +2481,7 @@ static void decode_finish_row(const H264Context *h, H264SliceContext *sl)
 
     ff_h264_draw_horiz_band(h, sl, top, height);
 
-    if (h->droppable || sl->h264->slice_ctx[0].er.error_occurred)
+    if (h->droppable || sl->h264->er.error_occurred)
         return;
 
     ff_thread_report_progress(&h->cur_pic_ptr->tf, top + height - 1,
@@ -2495,7 +2496,7 @@ static void er_add_slice(H264SliceContext *sl,
         return;
 
     if (CONFIG_ERROR_RESILIENCE) {
-        ERContext *er = &sl->h264->slice_ctx[0].er;
+        ERContext *er = &sl->h264->er;
 
         ff_er_add_slice(er, startx, starty, endx, endy, status);
     }
@@ -2526,13 +2527,13 @@ static int decode_slice(struct AVCodecContext *avctx, void *arg)
     sl->is_complex = FRAME_MBAFF(h) || h->picture_structure != PICT_FRAME ||
                      (CONFIG_GRAY && (h->flags & AV_CODEC_FLAG_GRAY));
 
-    if (!(h->avctx->active_thread_type & FF_THREAD_SLICE) && h->picture_structure == PICT_FRAME && h->slice_ctx[0].er.error_status_table) {
+    if (!(h->avctx->active_thread_type & FF_THREAD_SLICE) && h->picture_structure == PICT_FRAME && h->er.error_status_table) {
         const int start_i  = av_clip(sl->resync_mb_x + sl->resync_mb_y * h->mb_width, 0, h->mb_num - 1);
         if (start_i) {
-            int prev_status = h->slice_ctx[0].er.error_status_table[h->slice_ctx[0].er.mb_index2xy[start_i - 1]];
+            int prev_status = h->er.error_status_table[h->er.mb_index2xy[start_i - 1]];
             prev_status &= ~ VP_START;
             if (prev_status != (ER_MV_END | ER_DC_END | ER_AC_END))
-                h->slice_ctx[0].er.error_occurred = 1;
+                avpriv_atomic_int_set(&h->er.error_occurred, 1);
         }
     }
 
@@ -2746,9 +2747,6 @@ int ff_h264_execute_decode_slices(H264Context *h)
             int slice_idx;
 
             sl                 = &h->slice_ctx[i];
-            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;
@@ -2769,10 +2767,6 @@ int ff_h264_execute_decode_slices(H264Context *h)
         /* pull back stuff from slices to master context */
         sl                   = &h->slice_ctx[context_count - 1];
         h->mb_y              = sl->mb_y;
-        if (CONFIG_ERROR_RESILIENCE) {
-            for (i = 1; i < context_count; i++)
-                h->slice_ctx[0].er.error_count += h->slice_ctx[i].er.error_count;
-        }
 
         if (h->postpone_filter) {
             h->postpone_filter = 0;
diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c
index aed23c4fba..abf05158f9 100644
--- a/libavcodec/h264dec.c
+++ b/libavcodec/h264dec.c
@@ -157,13 +157,14 @@ void ff_h264_free_tables(H264Context *h)
     av_buffer_pool_uninit(&h->motion_val_pool);
     av_buffer_pool_uninit(&h->ref_index_pool);
 
+    av_freep(&h->er.mb_index2xy);
+    av_freep(&h->er.error_status_table);
+    av_freep(&h->er.er_temp_buffer);
+
     for (i = 0; i < h->nb_slice_ctx; i++) {
         H264SliceContext *sl = &h->slice_ctx[i];
 
         av_freep(&sl->dc_val_base);
-        av_freep(&sl->er.mb_index2xy);
-        av_freep(&sl->er.error_status_table);
-        av_freep(&sl->er.er_temp_buffer);
 
         av_freep(&sl->bipred_scratchpad);
         av_freep(&sl->edge_emu_buffer);
@@ -237,7 +238,6 @@ fail:
  */
 int ff_h264_slice_context_init(H264Context *h, H264SliceContext *sl)
 {
-    ERContext *er = &sl->er;
     int mb_array_size = h->mb_height * h->mb_stride;
     int y_size  = (2 * h->mb_width + 1) * (2 * h->mb_height + 1);
     int c_size  = h->mb_stride * (h->mb_height + 1);
@@ -251,10 +251,8 @@ int ff_h264_slice_context_init(H264Context *h, H264SliceContext *sl)
     sl->ref_cache[1][scan8[7]  + 1] =
     sl->ref_cache[1][scan8[13] + 1] = PART_NOT_AVAILABLE;
 
-    if (sl != h->slice_ctx) {
-        memset(er, 0, sizeof(*er));
-    } else
-    if (CONFIG_ERROR_RESILIENCE) {
+    if (CONFIG_ERROR_RESILIENCE && sl == h->slice_ctx) {
+        ERContext *er = &h->er;
 
         /* init ER */
         er->avctx          = h->avctx;
@@ -432,9 +430,6 @@ static av_cold int h264_decode_init(AVCodecContext *avctx)
 
     ff_h264_flush_change(h);
 
-    if (h->enable_er < 0 && (avctx->active_thread_type & FF_THREAD_SLICE))
-        h->enable_er = 0;
-
     if (h->enable_er && (avctx->active_thread_type & FF_THREAD_SLICE)) {
         av_log(avctx, AV_LOG_WARNING,
                "Error resilience with slice threads is enabled. It is unsafe and unsupported and may crash. "
@@ -773,25 +768,25 @@ end:
         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);
+        ff_h264_set_erpic(&h->er.cur_pic, h->cur_pic_ptr);
 
         if (use_last_pic) {
-            ff_h264_set_erpic(&sl->er.last_pic, &h->last_pic_for_ec);
+            ff_h264_set_erpic(&h->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);
+            ff_h264_set_erpic(&h->er.last_pic, sl->ref_list[0][0].parent);
         } else
-            ff_h264_set_erpic(&sl->er.last_pic, NULL);
+            ff_h264_set_erpic(&h->er.last_pic, NULL);
 
         if (sl->ref_count[1])
-            ff_h264_set_erpic(&sl->er.next_pic, sl->ref_list[1][0].parent);
+            ff_h264_set_erpic(&h->er.next_pic, sl->ref_list[1][0].parent);
 
-        sl->er.ref_count = sl->ref_count[0];
+        h->er.ref_count = sl->ref_count[0];
 
-        ff_er_frame_end(&sl->er);
+        ff_er_frame_end(&h->er);
         if (use_last_pic)
             memset(&sl->ref_list[0][0], 0, sizeof(sl->ref_list[0][0]));
     }
diff --git a/libavcodec/h264dec.h b/libavcodec/h264dec.h
index b87b947f95..81c4f2ebc0 100644
--- a/libavcodec/h264dec.h
+++ b/libavcodec/h264dec.h
@@ -177,7 +177,6 @@ typedef struct H264Ref {
 typedef struct H264SliceContext {
     struct H264Context *h264;
     GetBitContext gb;
-    ERContext er;
 
     int slice_num;
     int slice_type;
@@ -341,6 +340,7 @@ typedef struct H264Context {
     H264DSPContext h264dsp;
     H264ChromaContext h264chroma;
     H264QpelContext h264qpel;
+    ERContext er;
 
     H264Picture DPB[H264_MAX_PICTURE_COUNT];
     H264Picture *cur_pic_ptr;
-- 
2.15.0



More information about the ffmpeg-devel mailing list