From 3ec623c22f87b42c4f5a68851e4f27a5751d7dd8 Mon Sep 17 00:00:00 2001 From: Kostya Shishkov Date: Mon, 13 Feb 2012 19:27:48 +0100 Subject: [PATCH] prores: fix multithreaded decoding case when slice quantisers are not the same Since quantisation matrices are stored in context, decoding slices with different quantisers in parallel leads to unpredictable content of aforementioned matrices and wrong output picture thereof. --- libavcodec/proresdec.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/libavcodec/proresdec.c b/libavcodec/proresdec.c index 7617cb3c98..ba78b62894 100644 --- a/libavcodec/proresdec.c +++ b/libavcodec/proresdec.c @@ -42,7 +42,10 @@ typedef struct { int slice_num; int x_pos, y_pos; int slice_width; + int prev_slice_sf; ///< scalefactor of the previous decoded slice DECLARE_ALIGNED(16, DCTELEM, blocks)[8 * 4 * 64]; + DECLARE_ALIGNED(16, int16_t, qmat_luma_scaled)[64]; + DECLARE_ALIGNED(16, int16_t, qmat_chroma_scaled)[64]; } ProresThreadData; typedef struct { @@ -56,9 +59,6 @@ typedef struct { uint8_t qmat_luma[64]; ///< dequantization matrix for luma uint8_t qmat_chroma[64]; ///< dequantization matrix for chroma int qmat_changed; ///< 1 - global quantization matrices changed - int prev_slice_sf; ///< scalefactor of the previous decoded slice - DECLARE_ALIGNED(16, int16_t, qmat_luma_scaled)[64]; - DECLARE_ALIGNED(16, int16_t, qmat_chroma_scaled)[64]; int total_slices; ///< total number of slices in a picture ProresThreadData *slice_data; int pic_num; @@ -116,7 +116,6 @@ static av_cold int decode_init(AVCodecContext *avctx) ctx->scantable_type = -1; // set scantable type to uninitialized memset(ctx->qmat_luma, 4, 64); memset(ctx->qmat_chroma, 4, 64); - ctx->prev_slice_sf = 0; return 0; } @@ -294,9 +293,11 @@ static int decode_picture_header(ProresContext *ctx, const uint8_t *buf, for (i = 0; i < num_slices; i++) { ctx->slice_data[i].index = data_ptr; + ctx->slice_data[i].prev_slice_sf = 0; data_ptr += AV_RB16(index_ptr + i * 2); } ctx->slice_data[i].index = data_ptr; + ctx->slice_data[i].prev_slice_sf = 0; if (data_ptr > buf + data_size) { av_log(avctx, AV_LOG_ERROR, "out of slice data\n"); @@ -561,11 +562,11 @@ static int decode_slice(AVCodecContext *avctx, void *tdata) /* scale quantization matrixes according with slice's scale factor */ /* TODO: this can be SIMD-optimized a lot */ - if (ctx->qmat_changed || sf != ctx->prev_slice_sf) { - ctx->prev_slice_sf = sf; + if (ctx->qmat_changed || sf != td->prev_slice_sf) { + td->prev_slice_sf = sf; for (i = 0; i < 64; i++) { - ctx->qmat_luma_scaled[ctx->dsp.idct_permutation[i]] = ctx->qmat_luma[i] * sf; - ctx->qmat_chroma_scaled[ctx->dsp.idct_permutation[i]] = ctx->qmat_chroma[i] * sf; + td->qmat_luma_scaled[ctx->dsp.idct_permutation[i]] = ctx->qmat_luma[i] * sf; + td->qmat_chroma_scaled[ctx->dsp.idct_permutation[i]] = ctx->qmat_chroma[i] * sf; } } @@ -574,7 +575,7 @@ static int decode_slice(AVCodecContext *avctx, void *tdata) (uint16_t*) (y_data + (mb_y_pos << 4) * y_linesize + (mb_x_pos << 5)), y_linesize, mbs_per_slice, 4, slice_width_factor + 2, - ctx->qmat_luma_scaled); + td->qmat_luma_scaled); /* decode U chroma plane */ decode_slice_plane(ctx, td, buf + hdr_size + y_data_size, u_data_size, @@ -582,7 +583,7 @@ static int decode_slice(AVCodecContext *avctx, void *tdata) (mb_x_pos << ctx->mb_chroma_factor)), u_linesize, mbs_per_slice, ctx->num_chroma_blocks, slice_width_factor + ctx->chroma_factor - 1, - ctx->qmat_chroma_scaled); + td->qmat_chroma_scaled); /* decode V chroma plane */ decode_slice_plane(ctx, td, buf + hdr_size + y_data_size + u_data_size, @@ -591,7 +592,7 @@ static int decode_slice(AVCodecContext *avctx, void *tdata) (mb_x_pos << ctx->mb_chroma_factor)), v_linesize, mbs_per_slice, ctx->num_chroma_blocks, slice_width_factor + ctx->chroma_factor - 1, - ctx->qmat_chroma_scaled); + td->qmat_chroma_scaled); return 0; }