Commit e49e0f58 authored by Anton Khirnov's avatar Anton Khirnov

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: 's avatarKieran Kunhya <kierank@obe.tv>
parent b56b12cd
...@@ -374,6 +374,8 @@ typedef struct H264SliceContext { ...@@ -374,6 +374,8 @@ typedef struct H264SliceContext {
int mb_xy; int mb_xy;
int resync_mb_x; int resync_mb_x;
int resync_mb_y; int resync_mb_y;
// index of the first MB of the next slice
int next_slice_idx;
int mb_skip_run; int mb_skip_run;
int is_complex; int is_complex;
......
...@@ -2080,8 +2080,15 @@ static int decode_slice(struct AVCodecContext *avctx, void *arg) ...@@ -2080,8 +2080,15 @@ static int decode_slice(struct AVCodecContext *avctx, void *arg)
for (;;) { for (;;) {
// START_TIMER // START_TIMER
int ret = ff_h264_decode_mb_cabac(h, sl); int ret, eos;
int 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") // STOP_TIMER("decode_mb_cabac")
if (ret >= 0) if (ret >= 0)
...@@ -2141,7 +2148,15 @@ static int decode_slice(struct AVCodecContext *avctx, void *arg) ...@@ -2141,7 +2148,15 @@ static int decode_slice(struct AVCodecContext *avctx, void *arg)
} }
} else { } else {
for (;;) { 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) if (ret >= 0)
ff_h264_hl_decode_mb(h, sl); ff_h264_hl_decode_mb(h, sl);
...@@ -2224,18 +2239,37 @@ int ff_h264_execute_decode_slices(H264Context *h, unsigned context_count) ...@@ -2224,18 +2239,37 @@ int ff_h264_execute_decode_slices(H264Context *h, unsigned context_count)
{ {
AVCodecContext *const avctx = h->avctx; AVCodecContext *const avctx = h->avctx;
H264SliceContext *sl; H264SliceContext *sl;
int i; int i, j;
if (h->avctx->hwaccel) if (h->avctx->hwaccel)
return 0; return 0;
if (context_count == 1) { 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; h->mb_y = h->slice_ctx[0].mb_y;
return ret; return ret;
} else { } 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 = &h->slice_ctx[i];
sl->er.error_count = 0; 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, avctx->execute(avctx, decode_slice, h->slice_ctx,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment