avfilter/avf_showfreqs: add option to draw subset of channels
This commit is contained in:
		
							parent
							
								
									fd834924d7
								
							
						
					
					
						commit
						0b6e801d4a
					
				@ -28432,6 +28432,9 @@ It accepts the following values:
 | 
			
		||||
@item delay
 | 
			
		||||
@end table
 | 
			
		||||
Default is @code{magnitude}.
 | 
			
		||||
 | 
			
		||||
@item channels
 | 
			
		||||
Set channels to use when processing audio. By default all are processed.
 | 
			
		||||
@end table
 | 
			
		||||
 | 
			
		||||
@section showspatial
 | 
			
		||||
 | 
			
		||||
@ -51,6 +51,9 @@ typedef struct ShowFreqsContext {
 | 
			
		||||
    int ascale, fscale;
 | 
			
		||||
    int avg;
 | 
			
		||||
    int win_func;
 | 
			
		||||
    char *ch_layout_str;
 | 
			
		||||
    uint8_t *bypass;
 | 
			
		||||
    AVChannelLayout ch_layout;
 | 
			
		||||
    AVTXContext *fft;
 | 
			
		||||
    av_tx_fn tx_fn;
 | 
			
		||||
    AVComplexFloat **fft_input;
 | 
			
		||||
@ -62,6 +65,7 @@ typedef struct ShowFreqsContext {
 | 
			
		||||
    float minamp;
 | 
			
		||||
    int hop_size;
 | 
			
		||||
    int nb_channels;
 | 
			
		||||
    int nb_draw_channels;
 | 
			
		||||
    int nb_freq;
 | 
			
		||||
    int win_size;
 | 
			
		||||
    float scale;
 | 
			
		||||
@ -100,6 +104,7 @@ static const AVOption showfreqs_options[] = {
 | 
			
		||||
        { "magnitude", "show magnitude",  0, AV_OPT_TYPE_CONST, {.i64=MAGNITUDE}, 0, 0, FLAGS, "data" },
 | 
			
		||||
        { "phase",     "show phase",      0, AV_OPT_TYPE_CONST, {.i64=PHASE},     0, 0, FLAGS, "data" },
 | 
			
		||||
        { "delay",     "show group delay",0, AV_OPT_TYPE_CONST, {.i64=DELAY},     0, 0, FLAGS, "data" },
 | 
			
		||||
    { "channels", "set channels to draw", OFFSET(ch_layout_str), AV_OPT_TYPE_STRING, {.str="all"}, 0, 0, FLAGS },
 | 
			
		||||
    { NULL }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -162,11 +167,15 @@ static int config_output(AVFilterLink *outlink)
 | 
			
		||||
        av_freep(&s->fft_data[i]);
 | 
			
		||||
        av_freep(&s->avg_data[i]);
 | 
			
		||||
    }
 | 
			
		||||
    av_freep(&s->bypass);
 | 
			
		||||
    av_freep(&s->fft_input);
 | 
			
		||||
    av_freep(&s->fft_data);
 | 
			
		||||
    av_freep(&s->avg_data);
 | 
			
		||||
    s->nb_channels = inlink->ch_layout.nb_channels;
 | 
			
		||||
 | 
			
		||||
    s->bypass = av_calloc(s->nb_channels, sizeof(*s->bypass));
 | 
			
		||||
    if (!s->bypass)
 | 
			
		||||
        return AVERROR(ENOMEM);
 | 
			
		||||
    s->fft_input = av_calloc(s->nb_channels, sizeof(*s->fft_input));
 | 
			
		||||
    if (!s->fft_input)
 | 
			
		||||
        return AVERROR(ENOMEM);
 | 
			
		||||
@ -212,6 +221,26 @@ static int config_output(AVFilterLink *outlink)
 | 
			
		||||
    outlink->w = s->w;
 | 
			
		||||
    outlink->h = s->h;
 | 
			
		||||
 | 
			
		||||
    ret = av_channel_layout_copy(&s->ch_layout, &inlink->ch_layout);
 | 
			
		||||
    if (ret < 0)
 | 
			
		||||
        return ret;
 | 
			
		||||
    s->nb_draw_channels = s->nb_channels;
 | 
			
		||||
 | 
			
		||||
    if (strcmp(s->ch_layout_str, "all")) {
 | 
			
		||||
        int nb_draw_channels = 0;
 | 
			
		||||
        av_channel_layout_from_string(&s->ch_layout,
 | 
			
		||||
                                      s->ch_layout_str);
 | 
			
		||||
 | 
			
		||||
        for (int ch = 0; ch < s->nb_channels; ch++) {
 | 
			
		||||
            const enum AVChannel channel = av_channel_layout_channel_from_index(&inlink->ch_layout, ch);
 | 
			
		||||
 | 
			
		||||
            s->bypass[ch] = av_channel_layout_index_from_channel(&s->ch_layout, channel) < 0;
 | 
			
		||||
            nb_draw_channels += s->bypass[ch] == 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        s->nb_draw_channels = nb_draw_channels;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -288,8 +317,8 @@ static inline void plot_freq(ShowFreqsContext *s, int ch,
 | 
			
		||||
        y = a * outlink->h - 1;
 | 
			
		||||
        break;
 | 
			
		||||
    case SEPARATE:
 | 
			
		||||
        end = (outlink->h / s->nb_channels) * (ch + 1);
 | 
			
		||||
        y = (outlink->h / s->nb_channels) * ch + a * (outlink->h / s->nb_channels) - 1;
 | 
			
		||||
        end = (outlink->h / s->nb_draw_channels) * (ch + 1);
 | 
			
		||||
        y = (outlink->h / s->nb_draw_channels) * ch + a * (outlink->h / s->nb_draw_channels) - 1;
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        av_assert0(0);
 | 
			
		||||
@ -361,6 +390,9 @@ static int plot_freqs(AVFilterLink *inlink, int64_t pts)
 | 
			
		||||
    for (ch = 0; ch < s->nb_channels; ch++) {
 | 
			
		||||
        const float *p = (float *)in->extended_data[ch];
 | 
			
		||||
 | 
			
		||||
        if (s->bypass[ch])
 | 
			
		||||
            continue;
 | 
			
		||||
 | 
			
		||||
        for (n = 0; n < win_size; n++) {
 | 
			
		||||
            s->fft_input[ch][n].re = p[n] * s->window_func_lut[n];
 | 
			
		||||
            s->fft_input[ch][n].im = 0;
 | 
			
		||||
@ -369,6 +401,9 @@ static int plot_freqs(AVFilterLink *inlink, int64_t pts)
 | 
			
		||||
 | 
			
		||||
    /* run FFT on each samples set */
 | 
			
		||||
    for (ch = 0; ch < s->nb_channels; ch++) {
 | 
			
		||||
        if (s->bypass[ch])
 | 
			
		||||
            continue;
 | 
			
		||||
 | 
			
		||||
        s->tx_fn(s->fft, s->fft_data[ch], s->fft_input[ch], sizeof(float));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -392,6 +427,9 @@ static int plot_freqs(AVFilterLink *inlink, int64_t pts)
 | 
			
		||||
        if (color)
 | 
			
		||||
            av_parse_color(fg, color, -1, ctx);
 | 
			
		||||
 | 
			
		||||
        if (s->bypass[ch])
 | 
			
		||||
            continue;
 | 
			
		||||
 | 
			
		||||
        switch (s->data_mode) {
 | 
			
		||||
        case MAGNITUDE:
 | 
			
		||||
            a = av_clipd(M(RE(0, ch), 0) / s->scale, 0, 1);
 | 
			
		||||
@ -482,6 +520,7 @@ static av_cold void uninit(AVFilterContext *ctx)
 | 
			
		||||
    ShowFreqsContext *s = ctx->priv;
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    av_channel_layout_uninit(&s->ch_layout);
 | 
			
		||||
    av_tx_uninit(&s->fft);
 | 
			
		||||
    for (i = 0; i < s->nb_channels; i++) {
 | 
			
		||||
        if (s->fft_input)
 | 
			
		||||
@ -491,6 +530,7 @@ static av_cold void uninit(AVFilterContext *ctx)
 | 
			
		||||
        if (s->avg_data)
 | 
			
		||||
            av_freep(&s->avg_data[i]);
 | 
			
		||||
    }
 | 
			
		||||
    av_freep(&s->bypass);
 | 
			
		||||
    av_freep(&s->fft_input);
 | 
			
		||||
    av_freep(&s->fft_data);
 | 
			
		||||
    av_freep(&s->avg_data);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user