[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