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>
This commit is contained in:
parent
b56b12cd12
commit
e49e0f58e2
@ -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)
|
|||||||
|
|
||||||
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)
|
|||||||
}
|
}
|
||||||
} 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)
|
|||||||
{
|
{
|
||||||
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,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user