diff options
author | Anton Khirnov <anton@khirnov.net> | 2015-05-06 11:12:55 +0200 |
---|---|---|
committer | Anton Khirnov <anton@khirnov.net> | 2015-06-27 16:43:22 +0200 |
commit | e49e0f58e273237f83b4486f3536931ed1943d18 (patch) | |
tree | 06c31e9c072fdb1646e30f5c6c136a814586088b | |
parent | b56b12cd12f32bf11efff05632600a7619584b98 (diff) | |
download | ffmpeg-e49e0f58e273237f83b4486f3536931ed1943d18.tar.gz |
h264: make sure the slices do not overlap during slice threading
Based on a patch by Michael Niedermayer <michaelni@gmx.at>.
CC: libav-stable@libav.org
Found-by: Kieran Kunhya <kierank@obe.tv>
-rw-r--r-- | libavcodec/h264.h | 2 | ||||
-rw-r--r-- | libavcodec/h264_slice.c | 46 |
2 files changed, 42 insertions, 6 deletions
diff --git a/libavcodec/h264.h b/libavcodec/h264.h index 12172ac7bc..624a761ded 100644 --- a/libavcodec/h264.h +++ b/libavcodec/h264.h @@ -374,6 +374,8 @@ typedef struct H264SliceContext { int mb_xy; int resync_mb_x; int resync_mb_y; + // index of the first MB of the next slice + int next_slice_idx; int mb_skip_run; int is_complex; diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index 4e8ee4f7a4..93f0704d47 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -2080,8 +2080,15 @@ static int decode_slice(struct AVCodecContext *avctx, void *arg) for (;;) { // START_TIMER - int ret = ff_h264_decode_mb_cabac(h, sl); - int eos; + int ret, eos; + + 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); + return AVERROR_INVALIDDATA; + } + + ret = ff_h264_decode_mb_cabac(h, sl); // STOP_TIMER("decode_mb_cabac") if (ret >= 0) @@ -2141,7 +2148,15 @@ static int decode_slice(struct AVCodecContext *avctx, void *arg) } } else { for (;;) { - int ret = ff_h264_decode_mb_cavlc(h, sl); + int ret; + + 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); + return AVERROR_INVALIDDATA; + } + + ret = ff_h264_decode_mb_cavlc(h, sl); if (ret >= 0) ff_h264_hl_decode_mb(h, sl); @@ -2224,18 +2239,37 @@ int ff_h264_execute_decode_slices(H264Context *h, unsigned context_count) { AVCodecContext *const avctx = h->avctx; H264SliceContext *sl; - int i; + int i, j; if (h->avctx->hwaccel) 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 { - for (i = 1; i < context_count; i++) { + for (i = 0; i < context_count; i++) { + int next_slice_idx = h->mb_width * h->mb_height; + int slice_idx; + sl = &h->slice_ctx[i]; 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 slice_idx2 = sl2->mb_y * h->mb_width + sl2->mb_x; + + if (i == j || slice_idx2 < slice_idx) + continue; + next_slice_idx = FFMIN(next_slice_idx, slice_idx2); + } + sl->next_slice_idx = next_slice_idx; } avctx->execute(avctx, decode_slice, h->slice_ctx, |