Browse code

avfilter/avf_showspectrum: do not let multiple threads to write to same part of memory

Paul B Mahol authored on 2016/08/16 22:52:30
Showing 1 changed files
... ...
@@ -77,6 +77,7 @@ typedef struct {
77 77
     float gain;
78 78
     int hop_size;
79 79
     float *combine_buffer;      ///< color combining buffer (3 * h items)
80
+    float **color_buffer;       ///< color buffer (3 * h * ch items)
80 81
     AVAudioFifo *fifo;
81 82
     int64_t pts;
82 83
     int single_pic;
... ...
@@ -230,12 +231,17 @@ static av_cold void uninit(AVFilterContext *ctx)
230 230
         for (i = 0; i < s->nb_display_channels; i++)
231 231
             av_fft_end(s->fft[i]);
232 232
     }
233
+    av_freep(&s->fft);
233 234
     if (s->fft_data) {
234 235
         for (i = 0; i < s->nb_display_channels; i++)
235 236
             av_freep(&s->fft_data[i]);
236 237
     }
237
-    av_freep(&s->fft);
238 238
     av_freep(&s->fft_data);
239
+    if (s->color_buffer) {
240
+        for (i = 0; i < s->nb_display_channels; i++)
241
+            av_freep(&s->color_buffer[i]);
242
+    }
243
+    av_freep(&s->color_buffer);
239 244
     av_freep(&s->window_func_lut);
240 245
     if (s->magnitudes) {
241 246
         for (i = 0; i < s->nb_display_channels; i++)
... ...
@@ -366,6 +372,16 @@ static int config_output(AVFilterLink *outlink)
366 366
                 return AVERROR(ENOMEM);
367 367
         }
368 368
 
369
+        av_freep(&s->color_buffer);
370
+        s->color_buffer = av_calloc(s->nb_display_channels, sizeof(*s->color_buffer));
371
+        if (!s->color_buffer)
372
+            return AVERROR(ENOMEM);
373
+        for (i = 0; i < s->nb_display_channels; i++) {
374
+            s->color_buffer[i] = av_malloc_array(s->orientation == VERTICAL ? s->h * 3 : s->w * 3, sizeof(**s->color_buffer));
375
+            if (!s->color_buffer[i])
376
+                return AVERROR(ENOMEM);
377
+        }
378
+
369 379
         s->fft_data = av_calloc(s->nb_display_channels, sizeof(*s->fft_data));
370 380
         if (!s->fft_data)
371 381
             return AVERROR(ENOMEM);
... ...
@@ -613,13 +629,13 @@ static void pick_color(ShowSpectrumContext *s,
613 613
               + color_table[cm][i].v * lerpfrac;
614 614
         }
615 615
 
616
-        out[0] += y * yf;
617
-        out[1] += u * uf;
618
-        out[2] += v * vf;
616
+        out[0] = y * yf;
617
+        out[1] = u * uf;
618
+        out[2] = v * vf;
619 619
     } else {
620
-        out[0] += a * yf;
621
-        out[1] += a * uf;
622
-        out[2] += a * vf;
620
+        out[0] = a * yf;
621
+        out[1] = a * uf;
622
+        out[2] = a * vf;
623 623
     }
624 624
 }
625 625
 
... ...
@@ -650,7 +666,7 @@ static int plot_channel(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
650 650
     /* draw the channel */
651 651
     for (y = 0; y < h; y++) {
652 652
         int row = (s->mode == COMBINED) ? y : ch * h + y;
653
-        float *out = &s->combine_buffer[3 * row];
653
+        float *out = &s->color_buffer[ch][3 * row];
654 654
         float a;
655 655
 
656 656
         switch (s->data) {
... ...
@@ -702,14 +718,21 @@ static int plot_spectrum_column(AVFilterLink *inlink, AVFrame *insamples)
702 702
     AVFilterLink *outlink = ctx->outputs[0];
703 703
     ShowSpectrumContext *s = ctx->priv;
704 704
     AVFrame *outpicref = s->outpicref;
705
-    int ret, plane, x, y;
705
+    int ret, plane, x, y, z = s->orientation == VERTICAL ? s->h : s->w;
706 706
 
707 707
     /* fill a new spectrum column */
708 708
     /* initialize buffer for combining to black */
709
-    clear_combine_buffer(s, s->orientation == VERTICAL ? s->h : s->w);
709
+    clear_combine_buffer(s, z);
710 710
 
711 711
     ctx->internal->execute(ctx, plot_channel, NULL, NULL, s->nb_display_channels);
712 712
 
713
+    for (y = 0; y < z * 3; y++) {
714
+        s->combine_buffer[y] += s->color_buffer[0][y];
715
+        for (x = 1; x < s->nb_display_channels; x++) {
716
+            s->combine_buffer[y] += s->color_buffer[x][y];
717
+        }
718
+    }
719
+
713 720
     av_frame_make_writable(s->outpicref);
714 721
     /* copy to output */
715 722
     if (s->orientation == VERTICAL) {