]> git.sesse.net Git - ffmpeg/commitdiff
prores: fix multithreaded decoding case when slice quantisers are not the same
authorKostya Shishkov <kostya.shishkov@gmail.com>
Mon, 13 Feb 2012 18:27:48 +0000 (19:27 +0100)
committerKostya Shishkov <kostya.shishkov@gmail.com>
Wed, 15 Feb 2012 06:14:35 +0000 (07:14 +0100)
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

index 7617cb3c98ffaac1060bc236a926c24b2f6d7432..ba78b628948e06e358fe5f9944cc8563c156f118 100644 (file)
@@ -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;
 }