aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2015-05-06 11:12:55 +0200
committerAnton Khirnov <anton@khirnov.net>2015-06-27 16:43:22 +0200
commite49e0f58e273237f83b4486f3536931ed1943d18 (patch)
tree06c31e9c072fdb1646e30f5c6c136a814586088b
parentb56b12cd12f32bf11efff05632600a7619584b98 (diff)
downloadffmpeg-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.h2
-rw-r--r--libavcodec/h264_slice.c46
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,