[FFmpeg-cvslog] prores: fix multithreaded decoding case when slice quantisers are not the same

Kostya Shishkov git at videolan.org
Thu Feb 16 01:46:55 CET 2012


ffmpeg | branch: master | Kostya Shishkov <kostya.shishkov at gmail.com> | Mon Feb 13 19:27:48 2012 +0100| [3ec623c22f87b42c4f5a68851e4f27a5751d7dd8] | committer: Kostya Shishkov

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.

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=3ec623c22f87b42c4f5a68851e4f27a5751d7dd8
---

 libavcodec/proresdec.c |   23 ++++++++++++-----------
 1 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/libavcodec/proresdec.c b/libavcodec/proresdec.c
index 7617cb3..ba78b62 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;
 }



More information about the ffmpeg-cvslog mailing list