Commit 1457786d authored by Paul B Mahol's avatar Paul B Mahol

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

parent ea58dd2b
...@@ -77,6 +77,7 @@ typedef struct { ...@@ -77,6 +77,7 @@ typedef struct {
float gain; float gain;
int hop_size; int hop_size;
float *combine_buffer; ///< color combining buffer (3 * h items) float *combine_buffer; ///< color combining buffer (3 * h items)
float **color_buffer; ///< color buffer (3 * h * ch items)
AVAudioFifo *fifo; AVAudioFifo *fifo;
int64_t pts; int64_t pts;
int single_pic; int single_pic;
...@@ -230,12 +231,17 @@ static av_cold void uninit(AVFilterContext *ctx) ...@@ -230,12 +231,17 @@ static av_cold void uninit(AVFilterContext *ctx)
for (i = 0; i < s->nb_display_channels; i++) for (i = 0; i < s->nb_display_channels; i++)
av_fft_end(s->fft[i]); av_fft_end(s->fft[i]);
} }
av_freep(&s->fft);
if (s->fft_data) { if (s->fft_data) {
for (i = 0; i < s->nb_display_channels; i++) for (i = 0; i < s->nb_display_channels; i++)
av_freep(&s->fft_data[i]); av_freep(&s->fft_data[i]);
} }
av_freep(&s->fft);
av_freep(&s->fft_data); av_freep(&s->fft_data);
if (s->color_buffer) {
for (i = 0; i < s->nb_display_channels; i++)
av_freep(&s->color_buffer[i]);
}
av_freep(&s->color_buffer);
av_freep(&s->window_func_lut); av_freep(&s->window_func_lut);
if (s->magnitudes) { if (s->magnitudes) {
for (i = 0; i < s->nb_display_channels; i++) for (i = 0; i < s->nb_display_channels; i++)
...@@ -366,6 +372,16 @@ static int config_output(AVFilterLink *outlink) ...@@ -366,6 +372,16 @@ static int config_output(AVFilterLink *outlink)
return AVERROR(ENOMEM); return AVERROR(ENOMEM);
} }
av_freep(&s->color_buffer);
s->color_buffer = av_calloc(s->nb_display_channels, sizeof(*s->color_buffer));
if (!s->color_buffer)
return AVERROR(ENOMEM);
for (i = 0; i < s->nb_display_channels; i++) {
s->color_buffer[i] = av_malloc_array(s->orientation == VERTICAL ? s->h * 3 : s->w * 3, sizeof(**s->color_buffer));
if (!s->color_buffer[i])
return AVERROR(ENOMEM);
}
s->fft_data = av_calloc(s->nb_display_channels, sizeof(*s->fft_data)); s->fft_data = av_calloc(s->nb_display_channels, sizeof(*s->fft_data));
if (!s->fft_data) if (!s->fft_data)
return AVERROR(ENOMEM); return AVERROR(ENOMEM);
...@@ -613,13 +629,13 @@ static void pick_color(ShowSpectrumContext *s, ...@@ -613,13 +629,13 @@ static void pick_color(ShowSpectrumContext *s,
+ color_table[cm][i].v * lerpfrac; + color_table[cm][i].v * lerpfrac;
} }
out[0] += y * yf; out[0] = y * yf;
out[1] += u * uf; out[1] = u * uf;
out[2] += v * vf; out[2] = v * vf;
} else { } else {
out[0] += a * yf; out[0] = a * yf;
out[1] += a * uf; out[1] = a * uf;
out[2] += a * vf; out[2] = a * vf;
} }
} }
...@@ -650,7 +666,7 @@ static int plot_channel(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) ...@@ -650,7 +666,7 @@ static int plot_channel(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
/* draw the channel */ /* draw the channel */
for (y = 0; y < h; y++) { for (y = 0; y < h; y++) {
int row = (s->mode == COMBINED) ? y : ch * h + y; int row = (s->mode == COMBINED) ? y : ch * h + y;
float *out = &s->combine_buffer[3 * row]; float *out = &s->color_buffer[ch][3 * row];
float a; float a;
switch (s->data) { switch (s->data) {
...@@ -702,14 +718,21 @@ static int plot_spectrum_column(AVFilterLink *inlink, AVFrame *insamples) ...@@ -702,14 +718,21 @@ static int plot_spectrum_column(AVFilterLink *inlink, AVFrame *insamples)
AVFilterLink *outlink = ctx->outputs[0]; AVFilterLink *outlink = ctx->outputs[0];
ShowSpectrumContext *s = ctx->priv; ShowSpectrumContext *s = ctx->priv;
AVFrame *outpicref = s->outpicref; AVFrame *outpicref = s->outpicref;
int ret, plane, x, y; int ret, plane, x, y, z = s->orientation == VERTICAL ? s->h : s->w;
/* fill a new spectrum column */ /* fill a new spectrum column */
/* initialize buffer for combining to black */ /* initialize buffer for combining to black */
clear_combine_buffer(s, s->orientation == VERTICAL ? s->h : s->w); clear_combine_buffer(s, z);
ctx->internal->execute(ctx, plot_channel, NULL, NULL, s->nb_display_channels); ctx->internal->execute(ctx, plot_channel, NULL, NULL, s->nb_display_channels);
for (y = 0; y < z * 3; y++) {
s->combine_buffer[y] += s->color_buffer[0][y];
for (x = 1; x < s->nb_display_channels; x++) {
s->combine_buffer[y] += s->color_buffer[x][y];
}
}
av_frame_make_writable(s->outpicref); av_frame_make_writable(s->outpicref);
/* copy to output */ /* copy to output */
if (s->orientation == VERTICAL) { if (s->orientation == VERTICAL) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment