| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright (c) 2017 Paul B Mahol | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This file is part of FFmpeg. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * FFmpeg is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU Lesser General Public | 
					
						
							|  |  |  |  * License as published by the Free Software Foundation; either | 
					
						
							|  |  |  |  * version 2.1 of the License, or (at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * FFmpeg is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
					
						
							|  |  |  |  * Lesser General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU Lesser General Public | 
					
						
							|  |  |  |  * License along with FFmpeg; if not, write to the Free Software | 
					
						
							|  |  |  |  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * @file | 
					
						
							|  |  |  |  * An arbitrary audio FIR filter | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-29 18:24:22 +02:00
										 |  |  | #include <float.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-10 14:53:44 +02:00
										 |  |  | #include "libavutil/avassert.h"
 | 
					
						
							| 
									
										
										
										
											2022-12-11 18:29:31 +01:00
										 |  |  | #include "libavutil/cpu.h"
 | 
					
						
							| 
									
										
										
										
											2022-01-29 11:35:40 +01:00
										 |  |  | #include "libavutil/tx.h"
 | 
					
						
							| 
									
										
										
										
											2020-01-09 20:06:57 +01:00
										 |  |  | #include "libavutil/avstring.h"
 | 
					
						
							| 
									
										
										
										
											2021-06-12 01:10:58 +02:00
										 |  |  | #include "libavutil/channel_layout.h"
 | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  | #include "libavutil/common.h"
 | 
					
						
							|  |  |  | #include "libavutil/float_dsp.h"
 | 
					
						
							| 
									
										
										
										
											2022-05-03 05:37:15 +02:00
										 |  |  | #include "libavutil/frame.h"
 | 
					
						
							| 
									
										
										
										
											2018-05-29 18:24:22 +02:00
										 |  |  | #include "libavutil/intreadwrite.h"
 | 
					
						
							| 
									
										
										
										
											2022-05-03 05:37:15 +02:00
										 |  |  | #include "libavutil/log.h"
 | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  | #include "libavutil/opt.h"
 | 
					
						
							| 
									
										
										
										
											2022-05-03 05:37:15 +02:00
										 |  |  | #include "libavutil/rational.h"
 | 
					
						
							| 
									
										
										
										
											2018-05-29 18:24:22 +02:00
										 |  |  | #include "libavutil/xga_font_data.h"
 | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "audio.h"
 | 
					
						
							|  |  |  | #include "avfilter.h"
 | 
					
						
							| 
									
										
										
										
											2018-09-15 20:35:08 +02:00
										 |  |  | #include "filters.h"
 | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  | #include "formats.h"
 | 
					
						
							|  |  |  | #include "internal.h"
 | 
					
						
							| 
									
										
										
										
											2022-05-14 10:28:49 +02:00
										 |  |  | #include "af_afir.h"
 | 
					
						
							| 
									
										
										
										
											2022-05-03 05:37:15 +02:00
										 |  |  | #include "af_afirdsp.h"
 | 
					
						
							| 
									
										
										
										
											2023-08-03 13:03:17 +02:00
										 |  |  | #include "video.h"
 | 
					
						
							| 
									
										
										
										
											2022-05-03 05:37:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-14 10:28:49 +02:00
										 |  |  | static void drawtext(AVFrame *pic, int x, int y, const char *txt, uint32_t color) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const uint8_t *font; | 
					
						
							|  |  |  |     int font_height; | 
					
						
							|  |  |  |     int i; | 
					
						
							| 
									
										
										
										
											2022-05-03 05:37:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-14 10:28:49 +02:00
										 |  |  |     font = avpriv_cga_font, font_height = 8; | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-14 10:28:49 +02:00
										 |  |  |     for (i = 0; txt[i]; i++) { | 
					
						
							|  |  |  |         int char_y, mask; | 
					
						
							| 
									
										
										
										
											2020-01-09 18:32:11 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-14 10:28:49 +02:00
										 |  |  |         uint8_t *p = pic->data[0] + y * pic->linesize[0] + (x + i * 8) * 4; | 
					
						
							|  |  |  |         for (char_y = 0; char_y < font_height; char_y++) { | 
					
						
							|  |  |  |             for (mask = 0x80; mask; mask >>= 1) { | 
					
						
							|  |  |  |                 if (font[txt[i] * font_height + char_y] & mask) | 
					
						
							|  |  |  |                     AV_WL32(p, color); | 
					
						
							|  |  |  |                 p += 4; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             p += pic->linesize[0] - 8 * 4; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-08-23 17:50:00 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-14 10:28:49 +02:00
										 |  |  | static void draw_line(AVFrame *out, int x0, int y0, int x1, int y1, uint32_t color) | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-05-14 10:28:49 +02:00
										 |  |  |     int dx = FFABS(x1-x0); | 
					
						
							|  |  |  |     int dy = FFABS(y1-y0), sy = y0 < y1 ? 1 : -1; | 
					
						
							|  |  |  |     int err = (dx>dy ? dx : -dy) / 2, e2; | 
					
						
							| 
									
										
										
										
											2020-01-09 18:32:11 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-14 10:28:49 +02:00
										 |  |  |     for (;;) { | 
					
						
							|  |  |  |         AV_WL32(out->data[0] + y0 * out->linesize[0] + x0 * 4, color); | 
					
						
							| 
									
										
										
										
											2020-01-09 18:32:11 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-14 10:28:49 +02:00
										 |  |  |         if (x0 == x1 && y0 == y1) | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2020-01-09 18:32:11 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-14 10:28:49 +02:00
										 |  |  |         e2 = err; | 
					
						
							| 
									
										
										
										
											2020-01-09 18:32:11 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-14 10:28:49 +02:00
										 |  |  |         if (e2 >-dx) { | 
					
						
							|  |  |  |             err -= dy; | 
					
						
							|  |  |  |             x0--; | 
					
						
							| 
									
										
										
										
											2020-01-09 18:32:11 +01:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-14 10:28:49 +02:00
										 |  |  |         if (e2 < dy) { | 
					
						
							|  |  |  |             err += dx; | 
					
						
							|  |  |  |             y0 += sy; | 
					
						
							| 
									
										
										
										
											2018-12-29 11:40:13 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-05-14 10:28:49 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2018-12-29 11:40:13 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-14 10:28:49 +02:00
										 |  |  | #define DEPTH 32
 | 
					
						
							|  |  |  | #include "afir_template.c"
 | 
					
						
							| 
									
										
										
										
											2018-12-29 10:46:25 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-14 10:28:49 +02:00
										 |  |  | #undef DEPTH
 | 
					
						
							|  |  |  | #define DEPTH 64
 | 
					
						
							|  |  |  | #include "afir_template.c"
 | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-31 18:04:59 +01:00
										 |  |  | static int fir_channel(AVFilterContext *ctx, AVFrame *out, int ch) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     AudioFIRContext *s = ctx->priv; | 
					
						
							| 
									
										
										
										
											2022-12-13 11:46:02 +01:00
										 |  |  |     const int min_part_size = s->min_part_size; | 
					
						
							| 
									
										
										
										
											2023-04-23 23:30:42 +02:00
										 |  |  |     const int prev_selir = s->prev_selir; | 
					
						
							|  |  |  |     const int selir = s->selir; | 
					
						
							| 
									
										
										
										
											2018-12-31 18:04:59 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-13 11:46:02 +01:00
										 |  |  |     for (int offset = 0; offset < out->nb_samples; offset += min_part_size) { | 
					
						
							| 
									
										
										
										
											2022-05-14 10:28:49 +02:00
										 |  |  |         switch (s->format) { | 
					
						
							|  |  |  |         case AV_SAMPLE_FMT_FLTP: | 
					
						
							| 
									
										
										
										
											2023-04-25 20:33:08 +02:00
										 |  |  |             if (prev_selir != selir && s->loading[ch] != 0) { | 
					
						
							| 
									
										
										
										
											2023-04-25 15:21:51 +02:00
										 |  |  |                 const float *xfade0 = (const float *)s->xfade[0]->extended_data[ch]; | 
					
						
							|  |  |  |                 const float *xfade1 = (const float *)s->xfade[1]->extended_data[ch]; | 
					
						
							|  |  |  |                 float *src0 = (float *)s->fadein[0]->extended_data[ch]; | 
					
						
							|  |  |  |                 float *src1 = (float *)s->fadein[1]->extended_data[ch]; | 
					
						
							|  |  |  |                 float *dst = ((float *)out->extended_data[ch]) + offset; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 memset(src0, 0, min_part_size * sizeof(float)); | 
					
						
							|  |  |  |                 memset(src1, 0, min_part_size * sizeof(float)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 fir_quantum_float(ctx, s->fadein[0], ch, offset, 0, prev_selir); | 
					
						
							|  |  |  |                 fir_quantum_float(ctx, s->fadein[1], ch, offset, 0, selir); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-25 20:33:08 +02:00
										 |  |  |                 if (s->loading[ch] > s->max_offset[selir]) { | 
					
						
							| 
									
										
										
										
											2023-04-25 15:21:51 +02:00
										 |  |  |                     for (int n = 0; n < min_part_size; n++) | 
					
						
							|  |  |  |                         dst[n] = xfade1[n] * src0[n] + xfade0[n] * src1[n]; | 
					
						
							|  |  |  |                     s->loading[ch] = 0; | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     memcpy(dst, src0, min_part_size * sizeof(float)); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 fir_quantum_float(ctx, out, ch, offset, offset, selir); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-05-14 10:28:49 +02:00
										 |  |  |             break; | 
					
						
							|  |  |  |         case AV_SAMPLE_FMT_DBLP: | 
					
						
							| 
									
										
										
										
											2023-04-25 20:33:08 +02:00
										 |  |  |             if (prev_selir != selir && s->loading[ch] != 0) { | 
					
						
							| 
									
										
										
										
											2023-04-25 15:21:51 +02:00
										 |  |  |                 const double *xfade0 = (const double *)s->xfade[0]->extended_data[ch]; | 
					
						
							|  |  |  |                 const double *xfade1 = (const double *)s->xfade[1]->extended_data[ch]; | 
					
						
							|  |  |  |                 double *src0 = (double *)s->fadein[0]->extended_data[ch]; | 
					
						
							|  |  |  |                 double *src1 = (double *)s->fadein[1]->extended_data[ch]; | 
					
						
							|  |  |  |                 double *dst = ((double *)out->extended_data[ch]) + offset; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 memset(src0, 0, min_part_size * sizeof(double)); | 
					
						
							|  |  |  |                 memset(src1, 0, min_part_size * sizeof(double)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 fir_quantum_double(ctx, s->fadein[0], ch, offset, 0, prev_selir); | 
					
						
							|  |  |  |                 fir_quantum_double(ctx, s->fadein[1], ch, offset, 0, selir); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-25 20:33:08 +02:00
										 |  |  |                 if (s->loading[ch] > s->max_offset[selir]) { | 
					
						
							| 
									
										
										
										
											2023-04-25 15:21:51 +02:00
										 |  |  |                     for (int n = 0; n < min_part_size; n++) | 
					
						
							|  |  |  |                         dst[n] = xfade1[n] * src0[n] + xfade0[n] * src1[n]; | 
					
						
							|  |  |  |                     s->loading[ch] = 0; | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     memcpy(dst, src0, min_part_size * sizeof(double)); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 fir_quantum_double(ctx, out, ch, offset, offset, selir); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-05-14 10:28:49 +02:00
										 |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-04-25 15:21:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-25 20:33:08 +02:00
										 |  |  |         if (selir != prev_selir && s->loading[ch] != 0) | 
					
						
							|  |  |  |             s->loading[ch] += min_part_size; | 
					
						
							| 
									
										
										
										
											2018-12-31 18:04:59 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-30 17:40:31 +01:00
										 |  |  | static int fir_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     AVFrame *out = arg; | 
					
						
							| 
									
										
										
										
											2021-08-31 11:03:14 -03:00
										 |  |  |     const int start = (out->ch_layout.nb_channels * jobnr) / nb_jobs; | 
					
						
							|  |  |  |     const int end = (out->ch_layout.nb_channels * (jobnr+1)) / nb_jobs; | 
					
						
							| 
									
										
										
										
											2018-12-30 17:40:31 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-13 11:46:02 +01:00
										 |  |  |     for (int ch = start; ch < end; ch++) | 
					
						
							| 
									
										
										
										
											2018-12-30 17:40:31 +01:00
										 |  |  |         fir_channel(ctx, out, ch); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-15 20:35:08 +02:00
										 |  |  | static int fir_frame(AudioFIRContext *s, AVFrame *in, AVFilterLink *outlink) | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     AVFilterContext *ctx = outlink->src; | 
					
						
							| 
									
										
										
										
											2022-12-18 23:50:24 +01:00
										 |  |  |     AVFrame *out; | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-27 14:11:12 +01:00
										 |  |  |     out = ff_get_audio_buffer(outlink, in->nb_samples); | 
					
						
							| 
									
										
										
										
											2018-11-09 10:40:16 +01:00
										 |  |  |     if (!out) { | 
					
						
							|  |  |  |         av_frame_free(&in); | 
					
						
							|  |  |  |         return AVERROR(ENOMEM); | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-01-17 14:33:23 +01:00
										 |  |  |     av_frame_copy_props(out, in); | 
					
						
							| 
									
										
										
										
											2022-12-13 11:46:02 +01:00
										 |  |  |     out->pts = s->pts = in->pts; | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-08 19:23:45 +01:00
										 |  |  |     s->in = in; | 
					
						
							| 
									
										
										
										
											2021-08-15 21:33:25 +02:00
										 |  |  |     ff_filter_execute(ctx, fir_channels, out, NULL, | 
					
						
							| 
									
										
										
										
											2021-08-31 11:03:14 -03:00
										 |  |  |                       FFMIN(outlink->ch_layout.nb_channels, ff_filter_get_nb_threads(ctx))); | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-15 20:35:08 +02:00
										 |  |  |     av_frame_free(&in); | 
					
						
							| 
									
										
										
										
											2020-01-08 19:23:45 +01:00
										 |  |  |     s->in = NULL; | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-09 10:40:16 +01:00
										 |  |  |     return ff_filter_frame(outlink, out); | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-31 23:31:31 +01:00
										 |  |  | static int init_segment(AVFilterContext *ctx, AudioFIRSegment *seg, int selir, | 
					
						
							| 
									
										
										
										
											2022-12-13 11:46:02 +01:00
										 |  |  |                         int offset, int nb_partitions, int part_size, int index) | 
					
						
							| 
									
										
										
										
											2018-12-28 18:31:36 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-12-29 11:40:13 +01:00
										 |  |  |     AudioFIRContext *s = ctx->priv; | 
					
						
							| 
									
										
										
										
											2022-12-11 18:29:31 +01:00
										 |  |  |     const size_t cpu_align = av_cpu_max_align(); | 
					
						
							| 
									
										
										
										
											2022-12-12 01:55:06 +01:00
										 |  |  |     union { double d; float f; } cscale, scale, iscale; | 
					
						
							|  |  |  |     enum AVTXType tx_type; | 
					
						
							| 
									
										
										
										
											2022-11-09 16:58:04 +01:00
										 |  |  |     int ret; | 
					
						
							| 
									
										
										
										
											2018-12-29 11:40:13 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-31 11:03:14 -03:00
										 |  |  |     seg->tx  = av_calloc(ctx->inputs[0]->ch_layout.nb_channels, sizeof(*seg->tx)); | 
					
						
							| 
									
										
										
										
											2022-12-13 11:46:02 +01:00
										 |  |  |     seg->ctx = av_calloc(ctx->inputs[0]->ch_layout.nb_channels, sizeof(*seg->ctx)); | 
					
						
							| 
									
										
										
										
											2021-08-31 11:03:14 -03:00
										 |  |  |     seg->itx = av_calloc(ctx->inputs[0]->ch_layout.nb_channels, sizeof(*seg->itx)); | 
					
						
							| 
									
										
										
										
											2022-12-13 11:46:02 +01:00
										 |  |  |     if (!seg->tx || !seg->ctx || !seg->itx) | 
					
						
							| 
									
										
										
										
											2018-12-28 18:31:36 +01:00
										 |  |  |         return AVERROR(ENOMEM); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-25 10:21:47 +01:00
										 |  |  |     seg->fft_length    = (part_size + 1) * 2; | 
					
						
							| 
									
										
										
										
											2018-12-29 11:40:13 +01:00
										 |  |  |     seg->part_size     = part_size; | 
					
						
							| 
									
										
										
										
											2022-12-11 18:29:31 +01:00
										 |  |  |     seg->coeff_size    = FFALIGN(seg->part_size + 1, cpu_align); | 
					
						
							| 
									
										
										
										
											2023-07-24 10:34:17 +02:00
										 |  |  |     seg->block_size    = FFMAX(seg->coeff_size * 2, FFALIGN(seg->fft_length, cpu_align)); | 
					
						
							| 
									
										
										
										
											2018-12-28 18:31:36 +01:00
										 |  |  |     seg->nb_partitions = nb_partitions; | 
					
						
							| 
									
										
										
										
											2018-12-29 11:40:13 +01:00
										 |  |  |     seg->input_size    = offset + s->min_part_size; | 
					
						
							|  |  |  |     seg->input_offset  = offset; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-31 11:03:14 -03:00
										 |  |  |     seg->part_index    = av_calloc(ctx->inputs[0]->ch_layout.nb_channels, sizeof(*seg->part_index)); | 
					
						
							|  |  |  |     seg->output_offset = av_calloc(ctx->inputs[0]->ch_layout.nb_channels, sizeof(*seg->output_offset)); | 
					
						
							| 
									
										
										
										
											2023-04-23 23:30:42 +02:00
										 |  |  |     if (!seg->part_index || !seg->output_offset) | 
					
						
							| 
									
										
										
										
											2018-12-29 11:40:13 +01:00
										 |  |  |         return AVERROR(ENOMEM); | 
					
						
							| 
									
										
										
										
											2018-12-28 18:31:36 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-12 01:55:06 +01:00
										 |  |  |     switch (s->format) { | 
					
						
							|  |  |  |     case AV_SAMPLE_FMT_FLTP: | 
					
						
							|  |  |  |         cscale.f = 1.f; | 
					
						
							|  |  |  |         scale.f  = 1.f / sqrtf(2.f * part_size); | 
					
						
							|  |  |  |         iscale.f = 1.f / sqrtf(2.f * part_size); | 
					
						
							|  |  |  |         tx_type  = AV_TX_FLOAT_RDFT; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case AV_SAMPLE_FMT_DBLP: | 
					
						
							|  |  |  |         cscale.d = 1.0; | 
					
						
							|  |  |  |         scale.d  = 1.0 / sqrt(2.0 * part_size); | 
					
						
							|  |  |  |         iscale.d = 1.0 / sqrt(2.0 * part_size); | 
					
						
							|  |  |  |         tx_type  = AV_TX_DOUBLE_RDFT; | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2024-06-10 14:53:44 +02:00
										 |  |  |     default: | 
					
						
							|  |  |  |         av_assert1(0); | 
					
						
							| 
									
										
										
										
											2022-12-12 01:55:06 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-05-14 10:28:49 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-12 01:55:06 +01:00
										 |  |  |     for (int ch = 0; ch < ctx->inputs[0]->ch_layout.nb_channels && part_size >= 1; ch++) { | 
					
						
							| 
									
										
										
										
											2022-12-13 11:46:02 +01:00
										 |  |  |         ret = av_tx_init(&seg->ctx[ch], &seg->ctx_fn, tx_type, | 
					
						
							|  |  |  |                          0, 2 * part_size, &cscale,  0); | 
					
						
							|  |  |  |         if (ret < 0) | 
					
						
							|  |  |  |             return ret; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-09 16:58:04 +01:00
										 |  |  |         ret = av_tx_init(&seg->tx[ch],  &seg->tx_fn,  tx_type, | 
					
						
							|  |  |  |                          0, 2 * part_size, &scale,  0); | 
					
						
							|  |  |  |         if (ret < 0) | 
					
						
							|  |  |  |             return ret; | 
					
						
							|  |  |  |         ret = av_tx_init(&seg->itx[ch], &seg->itx_fn, tx_type, | 
					
						
							|  |  |  |                          1, 2 * part_size, &iscale, 0); | 
					
						
							|  |  |  |         if (ret < 0) | 
					
						
							|  |  |  |             return ret; | 
					
						
							| 
									
										
										
										
											2018-12-28 18:31:36 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-29 11:35:40 +01:00
										 |  |  |     seg->sumin  = ff_get_audio_buffer(ctx->inputs[0], seg->fft_length); | 
					
						
							|  |  |  |     seg->sumout = ff_get_audio_buffer(ctx->inputs[0], seg->fft_length); | 
					
						
							| 
									
										
										
										
											2022-12-13 11:46:02 +01:00
										 |  |  |     seg->blockout = ff_get_audio_buffer(ctx->inputs[0], seg->block_size * seg->nb_partitions); | 
					
						
							|  |  |  |     seg->tempin = ff_get_audio_buffer(ctx->inputs[0], seg->block_size); | 
					
						
							|  |  |  |     seg->tempout = ff_get_audio_buffer(ctx->inputs[0], seg->block_size); | 
					
						
							| 
									
										
										
										
											2018-12-28 18:31:36 +01:00
										 |  |  |     seg->buffer = ff_get_audio_buffer(ctx->inputs[0], seg->part_size); | 
					
						
							| 
									
										
										
										
											2018-12-29 11:40:13 +01:00
										 |  |  |     seg->input  = ff_get_audio_buffer(ctx->inputs[0], seg->input_size); | 
					
						
							| 
									
										
										
										
											2022-12-31 23:31:31 +01:00
										 |  |  |     seg->output = ff_get_audio_buffer(ctx->inputs[0], seg->part_size * 5); | 
					
						
							| 
									
										
										
										
											2022-12-25 00:42:17 +01:00
										 |  |  |     if (!seg->buffer || !seg->sumin || !seg->sumout || !seg->blockout || | 
					
						
							| 
									
										
										
										
											2022-12-31 23:31:31 +01:00
										 |  |  |         !seg->input || !seg->output || !seg->tempin || !seg->tempout) | 
					
						
							| 
									
										
										
										
											2018-12-28 18:31:36 +01:00
										 |  |  |         return AVERROR(ENOMEM); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-09 20:06:57 +01:00
										 |  |  | static void uninit_segment(AVFilterContext *ctx, AudioFIRSegment *seg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     AudioFIRContext *s = ctx->priv; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-13 11:46:02 +01:00
										 |  |  |     if (seg->ctx) { | 
					
						
							|  |  |  |         for (int ch = 0; ch < s->nb_channels; ch++) | 
					
						
							|  |  |  |             av_tx_uninit(&seg->ctx[ch]); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     av_freep(&seg->ctx); | 
					
						
							| 
									
										
										
										
											2022-12-12 01:55:06 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-29 11:35:40 +01:00
										 |  |  |     if (seg->tx) { | 
					
						
							| 
									
										
										
										
											2022-12-13 11:46:02 +01:00
										 |  |  |         for (int ch = 0; ch < s->nb_channels; ch++) | 
					
						
							| 
									
										
										
										
											2022-01-29 11:35:40 +01:00
										 |  |  |             av_tx_uninit(&seg->tx[ch]); | 
					
						
							| 
									
										
										
										
											2020-01-09 20:06:57 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-01-29 11:35:40 +01:00
										 |  |  |     av_freep(&seg->tx); | 
					
						
							| 
									
										
										
										
											2020-01-09 20:06:57 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-29 11:35:40 +01:00
										 |  |  |     if (seg->itx) { | 
					
						
							| 
									
										
										
										
											2022-12-13 11:46:02 +01:00
										 |  |  |         for (int ch = 0; ch < s->nb_channels; ch++) | 
					
						
							| 
									
										
										
										
											2022-01-29 11:35:40 +01:00
										 |  |  |             av_tx_uninit(&seg->itx[ch]); | 
					
						
							| 
									
										
										
										
											2020-01-09 20:06:57 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-01-29 11:35:40 +01:00
										 |  |  |     av_freep(&seg->itx); | 
					
						
							| 
									
										
										
										
											2020-01-09 20:06:57 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     av_freep(&seg->output_offset); | 
					
						
							|  |  |  |     av_freep(&seg->part_index); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-13 11:46:02 +01:00
										 |  |  |     av_frame_free(&seg->tempin); | 
					
						
							|  |  |  |     av_frame_free(&seg->tempout); | 
					
						
							| 
									
										
										
										
											2022-01-29 11:35:40 +01:00
										 |  |  |     av_frame_free(&seg->blockout); | 
					
						
							|  |  |  |     av_frame_free(&seg->sumin); | 
					
						
							|  |  |  |     av_frame_free(&seg->sumout); | 
					
						
							| 
									
										
										
										
											2020-01-09 20:06:57 +01:00
										 |  |  |     av_frame_free(&seg->buffer); | 
					
						
							|  |  |  |     av_frame_free(&seg->input); | 
					
						
							|  |  |  |     av_frame_free(&seg->output); | 
					
						
							|  |  |  |     seg->input_size = 0; | 
					
						
							| 
									
										
										
										
											2022-12-31 23:31:31 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     for (int i = 0; i < MAX_IR_STREAMS; i++) | 
					
						
							| 
									
										
										
										
											2023-04-23 23:30:42 +02:00
										 |  |  |         av_frame_free(&seg->coeff); | 
					
						
							| 
									
										
										
										
											2020-01-09 20:06:57 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-13 11:46:02 +01:00
										 |  |  | static int convert_coeffs(AVFilterContext *ctx, int selir) | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     AudioFIRContext *s = ctx->priv; | 
					
						
							| 
									
										
										
										
											2022-12-31 23:31:31 +01:00
										 |  |  |     int ret, nb_taps, cur_nb_taps; | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-13 11:46:02 +01:00
										 |  |  |     if (!s->nb_taps[selir]) { | 
					
						
							| 
									
										
										
										
											2020-01-09 20:06:57 +01:00
										 |  |  |         int part_size, max_part_size; | 
					
						
							|  |  |  |         int left, offset = 0; | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-13 11:46:02 +01:00
										 |  |  |         s->nb_taps[selir] = ff_inlink_queued_samples(ctx->inputs[1 + selir]); | 
					
						
							|  |  |  |         if (s->nb_taps[selir] <= 0) | 
					
						
							| 
									
										
										
										
											2020-01-09 20:06:57 +01:00
										 |  |  |             return AVERROR(EINVAL); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-13 11:46:02 +01:00
										 |  |  |         if (s->minp > s->maxp) | 
					
						
							| 
									
										
										
										
											2020-01-09 20:06:57 +01:00
										 |  |  |             s->maxp = s->minp; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-23 23:30:42 +02:00
										 |  |  |         if (s->nb_segments[selir]) | 
					
						
							| 
									
										
										
										
											2022-12-13 11:46:02 +01:00
										 |  |  |             goto skip; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         left = s->nb_taps[selir]; | 
					
						
							| 
									
										
										
										
											2020-01-09 20:06:57 +01:00
										 |  |  |         part_size = 1 << av_log2(s->minp); | 
					
						
							|  |  |  |         max_part_size = 1 << av_log2(s->maxp); | 
					
						
							| 
									
										
										
										
											2018-12-28 18:07:13 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-13 11:46:02 +01:00
										 |  |  |         for (int i = 0; left > 0; i++) { | 
					
						
							| 
									
										
										
										
											2023-04-25 15:21:51 +02:00
										 |  |  |             int step = (part_size == max_part_size) ? INT_MAX : 1 + (i == 0); | 
					
						
							| 
									
										
										
										
											2020-01-09 20:06:57 +01:00
										 |  |  |             int nb_partitions = FFMIN(step, (left + part_size - 1) / part_size); | 
					
						
							| 
									
										
										
										
											2018-12-29 11:40:13 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-23 23:30:42 +02:00
										 |  |  |             s->nb_segments[selir] = i + 1; | 
					
						
							|  |  |  |             ret = init_segment(ctx, &s->seg[selir][i], selir, offset, nb_partitions, part_size, i); | 
					
						
							| 
									
										
										
										
											2020-01-09 20:06:57 +01:00
										 |  |  |             if (ret < 0) | 
					
						
							|  |  |  |                 return ret; | 
					
						
							|  |  |  |             offset += nb_partitions * part_size; | 
					
						
							| 
									
										
										
										
											2023-04-25 20:33:08 +02:00
										 |  |  |             s->max_offset[selir] = offset; | 
					
						
							| 
									
										
										
										
											2020-01-09 20:06:57 +01:00
										 |  |  |             left -= nb_partitions * part_size; | 
					
						
							|  |  |  |             part_size *= 2; | 
					
						
							|  |  |  |             part_size = FFMIN(part_size, max_part_size); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-12-29 11:40:13 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-13 11:46:02 +01:00
										 |  |  | skip: | 
					
						
							|  |  |  |     if (!s->ir[selir]) { | 
					
						
							|  |  |  |         ret = ff_inlink_consume_samples(ctx->inputs[1 + selir], s->nb_taps[selir], s->nb_taps[selir], &s->ir[selir]); | 
					
						
							| 
									
										
										
										
											2018-12-29 11:40:13 +01:00
										 |  |  |         if (ret < 0) | 
					
						
							|  |  |  |             return ret; | 
					
						
							| 
									
										
										
										
											2020-01-09 20:06:57 +01:00
										 |  |  |         if (ret == 0) | 
					
						
							|  |  |  |             return AVERROR_BUG; | 
					
						
							| 
									
										
										
										
											2018-12-29 11:40:13 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-14 10:28:49 +02:00
										 |  |  |     if (s->response) { | 
					
						
							|  |  |  |         switch (s->format) { | 
					
						
							|  |  |  |         case AV_SAMPLE_FMT_FLTP: | 
					
						
							|  |  |  |             draw_response_float(ctx, s->video); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case AV_SAMPLE_FMT_DBLP: | 
					
						
							|  |  |  |             draw_response_double(ctx, s->video); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-05-29 18:24:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-13 11:46:02 +01:00
										 |  |  |     cur_nb_taps  = s->ir[selir]->nb_samples; | 
					
						
							| 
									
										
										
										
											2022-12-31 23:31:31 +01:00
										 |  |  |     nb_taps      = cur_nb_taps; | 
					
						
							| 
									
										
										
										
											2018-10-03 21:43:40 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-31 23:31:31 +01:00
										 |  |  |     if (!s->norm_ir[selir] || s->norm_ir[selir]->nb_samples < nb_taps) { | 
					
						
							|  |  |  |         av_frame_free(&s->norm_ir[selir]); | 
					
						
							|  |  |  |         s->norm_ir[selir] = ff_get_audio_buffer(ctx->inputs[0], FFALIGN(nb_taps, 8)); | 
					
						
							|  |  |  |         if (!s->norm_ir[selir]) | 
					
						
							| 
									
										
										
										
											2022-12-13 11:46:02 +01:00
										 |  |  |             return AVERROR(ENOMEM); | 
					
						
							| 
									
										
										
										
											2018-10-03 21:43:40 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-12-31 19:09:07 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-09 20:06:57 +01:00
										 |  |  |     av_log(ctx, AV_LOG_DEBUG, "nb_taps: %d\n", cur_nb_taps); | 
					
						
							| 
									
										
										
										
											2023-04-23 23:30:42 +02:00
										 |  |  |     av_log(ctx, AV_LOG_DEBUG, "nb_segments: %d\n", s->nb_segments[selir]); | 
					
						
							| 
									
										
										
										
											2018-12-29 10:39:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-31 23:31:31 +01:00
										 |  |  |     switch (s->format) { | 
					
						
							|  |  |  |     case AV_SAMPLE_FMT_FLTP: | 
					
						
							|  |  |  |         for (int ch = 0; ch < s->nb_channels; ch++) { | 
					
						
							|  |  |  |             const float *tsrc = (const float *)s->ir[selir]->extended_data[!s->one2many * ch]; | 
					
						
							|  |  |  |             float *time = (float *)s->norm_ir[selir]->extended_data[ch]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             memcpy(time, tsrc, sizeof(*time) * nb_taps); | 
					
						
							|  |  |  |             for (int i = FFMAX(1, s->length * nb_taps); i < nb_taps; i++) | 
					
						
							|  |  |  |                 time[i] = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             get_power_float(ctx, s, nb_taps, ch, time); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-23 23:30:42 +02:00
										 |  |  |             for (int n = 0; n < s->nb_segments[selir]; n++) { | 
					
						
							|  |  |  |                 AudioFIRSegment *seg = &s->seg[selir][n]; | 
					
						
							| 
									
										
										
										
											2022-12-31 23:31:31 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-23 23:30:42 +02:00
										 |  |  |                 if (!seg->coeff) | 
					
						
							|  |  |  |                     seg->coeff = ff_get_audio_buffer(ctx->inputs[0], seg->nb_partitions * seg->coeff_size * 2); | 
					
						
							|  |  |  |                 if (!seg->coeff) | 
					
						
							| 
									
										
										
										
											2022-12-31 23:31:31 +01:00
										 |  |  |                     return AVERROR(ENOMEM); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 for (int i = 0; i < seg->nb_partitions; i++) | 
					
						
							|  |  |  |                     convert_channel_float(ctx, s, ch, seg, i, selir); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case AV_SAMPLE_FMT_DBLP: | 
					
						
							|  |  |  |         for (int ch = 0; ch < s->nb_channels; ch++) { | 
					
						
							|  |  |  |             const double *tsrc = (const double *)s->ir[selir]->extended_data[!s->one2many * ch]; | 
					
						
							|  |  |  |             double *time = (double *)s->norm_ir[selir]->extended_data[ch]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             memcpy(time, tsrc, sizeof(*time) * nb_taps); | 
					
						
							|  |  |  |             for (int i = FFMAX(1, s->length * nb_taps); i < nb_taps; i++) | 
					
						
							|  |  |  |                 time[i] = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             get_power_double(ctx, s, nb_taps, ch, time); | 
					
						
							| 
									
										
										
										
											2023-04-23 23:30:42 +02:00
										 |  |  |             for (int n = 0; n < s->nb_segments[selir]; n++) { | 
					
						
							|  |  |  |                 AudioFIRSegment *seg = &s->seg[selir][n]; | 
					
						
							| 
									
										
										
										
											2022-12-31 23:31:31 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-23 23:30:42 +02:00
										 |  |  |                 if (!seg->coeff) | 
					
						
							|  |  |  |                     seg->coeff = ff_get_audio_buffer(ctx->inputs[0], seg->nb_partitions * seg->coeff_size * 2); | 
					
						
							|  |  |  |                 if (!seg->coeff) | 
					
						
							| 
									
										
										
										
											2022-12-31 23:31:31 +01:00
										 |  |  |                     return AVERROR(ENOMEM); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 for (int i = 0; i < seg->nb_partitions; i++) | 
					
						
							|  |  |  |                     convert_channel_double(ctx, s, ch, seg, i, selir); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-13 11:46:02 +01:00
										 |  |  |     s->have_coeffs[selir] = 1; | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-30 14:06:40 +02:00
										 |  |  | static int check_ir(AVFilterLink *link, int selir) | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     AVFilterContext *ctx = link->dst; | 
					
						
							|  |  |  |     AudioFIRContext *s = ctx->priv; | 
					
						
							| 
									
										
										
										
											2018-10-03 12:49:44 +02:00
										 |  |  |     int nb_taps, max_nb_taps; | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-03 12:49:44 +02:00
										 |  |  |     nb_taps = ff_inlink_queued_samples(link); | 
					
						
							| 
									
										
										
										
											2018-04-16 19:06:09 +02:00
										 |  |  |     max_nb_taps = s->max_ir_len * ctx->outputs[0]->sample_rate; | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  |     if (nb_taps > max_nb_taps) { | 
					
						
							|  |  |  |         av_log(ctx, AV_LOG_ERROR, "Too big number of coefficients: %d > %d.\n", nb_taps, max_nb_taps); | 
					
						
							|  |  |  |         return AVERROR(EINVAL); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-30 14:06:40 +02:00
										 |  |  |     if (ff_inlink_check_available_samples(link, nb_taps + 1) == 1) | 
					
						
							|  |  |  |         s->eof_coeffs[selir] = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-15 20:35:08 +02:00
										 |  |  | static int activate(AVFilterContext *ctx) | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     AudioFIRContext *s = ctx->priv; | 
					
						
							|  |  |  |     AVFilterLink *outlink = ctx->outputs[0]; | 
					
						
							| 
									
										
										
										
											2018-12-31 18:04:59 +01:00
										 |  |  |     int ret, status, available, wanted; | 
					
						
							| 
									
										
										
										
											2018-09-15 20:35:08 +02:00
										 |  |  |     AVFrame *in = NULL; | 
					
						
							|  |  |  |     int64_t pts; | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-15 20:35:08 +02:00
										 |  |  |     FF_FILTER_FORWARD_STATUS_BACK_ALL(ctx->outputs[0], ctx); | 
					
						
							|  |  |  |     if (s->response) | 
					
						
							|  |  |  |         FF_FILTER_FORWARD_STATUS_BACK_ALL(ctx->outputs[1], ctx); | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-25 15:42:44 +02:00
										 |  |  |     for (int i = 0; i < s->nb_irs; i++) { | 
					
						
							|  |  |  |         const int selir = i; | 
					
						
							| 
									
										
										
										
											2018-09-15 20:35:08 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-25 15:42:44 +02:00
										 |  |  |         if (s->ir_load && selir != s->selir) | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!s->eof_coeffs[selir]) { | 
					
						
							| 
									
										
										
										
											2023-05-30 14:06:40 +02:00
										 |  |  |             ret = check_ir(ctx->inputs[1 + selir], selir); | 
					
						
							| 
									
										
										
										
											2023-04-25 15:42:44 +02:00
										 |  |  |             if (ret < 0) | 
					
						
							|  |  |  |                 return ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (!s->eof_coeffs[selir]) { | 
					
						
							|  |  |  |                 if (ff_outlink_frame_wanted(ctx->outputs[0])) | 
					
						
							|  |  |  |                     ff_inlink_request_frame(ctx->inputs[1 + selir]); | 
					
						
							|  |  |  |                 else if (s->response && ff_outlink_frame_wanted(ctx->outputs[1])) | 
					
						
							|  |  |  |                     ff_inlink_request_frame(ctx->inputs[1 + selir]); | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2018-09-15 20:35:08 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-11-20 13:25:39 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-25 15:42:44 +02:00
										 |  |  |         if (!s->have_coeffs[selir] && s->eof_coeffs[selir]) { | 
					
						
							|  |  |  |             ret = convert_coeffs(ctx, selir); | 
					
						
							|  |  |  |             if (ret < 0) | 
					
						
							|  |  |  |                 return ret; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-31 18:04:59 +01:00
										 |  |  |     available = ff_inlink_queued_samples(ctx->inputs[0]); | 
					
						
							|  |  |  |     wanted = FFMAX(s->min_part_size, (available / s->min_part_size) * s->min_part_size); | 
					
						
							|  |  |  |     ret = ff_inlink_consume_samples(ctx->inputs[0], wanted, wanted, &in); | 
					
						
							| 
									
										
										
										
											2018-11-08 11:14:04 +01:00
										 |  |  |     if (ret > 0) | 
					
						
							| 
									
										
										
										
											2018-09-15 20:35:08 +02:00
										 |  |  |         ret = fir_frame(s, in, outlink); | 
					
						
							| 
									
										
										
										
											2018-05-29 18:24:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-25 20:33:08 +02:00
										 |  |  |     if (s->selir != s->prev_selir && s->loading[0] == 0) | 
					
						
							| 
									
										
										
										
											2023-04-23 23:30:42 +02:00
										 |  |  |         s->prev_selir = s->selir; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-15 20:35:08 +02:00
										 |  |  |     if (ret < 0) | 
					
						
							|  |  |  |         return ret; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-13 11:46:02 +01:00
										 |  |  |     if (s->response && s->have_coeffs[s->selir]) { | 
					
						
							| 
									
										
										
										
											2018-11-08 12:46:29 +01:00
										 |  |  |         int64_t old_pts = s->video->pts; | 
					
						
							|  |  |  |         int64_t new_pts = av_rescale_q(s->pts, ctx->inputs[0]->time_base, ctx->outputs[1]->time_base); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (ff_outlink_frame_wanted(ctx->outputs[1]) && old_pts < new_pts) { | 
					
						
							| 
									
										
										
										
											2020-01-14 16:07:35 +01:00
										 |  |  |             AVFrame *clone; | 
					
						
							| 
									
										
										
										
											2018-11-08 12:46:29 +01:00
										 |  |  |             s->video->pts = new_pts; | 
					
						
							| 
									
										
										
										
											2020-01-14 16:07:35 +01:00
										 |  |  |             clone = av_frame_clone(s->video); | 
					
						
							|  |  |  |             if (!clone) | 
					
						
							|  |  |  |                 return AVERROR(ENOMEM); | 
					
						
							|  |  |  |             return ff_filter_frame(ctx->outputs[1], clone); | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-29 11:40:13 +01:00
										 |  |  |     if (ff_inlink_queued_samples(ctx->inputs[0]) >= s->min_part_size) { | 
					
						
							| 
									
										
										
										
											2018-11-08 12:46:29 +01:00
										 |  |  |         ff_filter_set_ready(ctx, 10); | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-15 20:35:08 +02:00
										 |  |  |     if (ff_inlink_acknowledge_status(ctx->inputs[0], &status, &pts)) { | 
					
						
							|  |  |  |         if (status == AVERROR_EOF) { | 
					
						
							|  |  |  |             ff_outlink_set_status(ctx->outputs[0], status, pts); | 
					
						
							|  |  |  |             if (s->response) | 
					
						
							|  |  |  |                 ff_outlink_set_status(ctx->outputs[1], status, pts); | 
					
						
							|  |  |  |             return 0; | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-30 14:06:40 +02:00
										 |  |  |     if (ff_outlink_frame_wanted(ctx->outputs[0])) { | 
					
						
							| 
									
										
										
										
											2018-09-15 20:35:08 +02:00
										 |  |  |         ff_inlink_request_frame(ctx->inputs[0]); | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-08 12:46:29 +01:00
										 |  |  |     if (s->response && | 
					
						
							| 
									
										
										
										
											2023-05-30 14:06:40 +02:00
										 |  |  |         ff_outlink_frame_wanted(ctx->outputs[1])) { | 
					
						
							| 
									
										
										
										
											2018-09-15 20:35:08 +02:00
										 |  |  |         ff_inlink_request_frame(ctx->inputs[0]); | 
					
						
							|  |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-09-15 20:35:08 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-08 12:46:29 +01:00
										 |  |  |     return FFERROR_NOT_READY; | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int query_formats(AVFilterContext *ctx) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-05-29 18:24:22 +02:00
										 |  |  |     AudioFIRContext *s = ctx->priv; | 
					
						
							| 
									
										
										
										
											2022-05-14 10:28:49 +02:00
										 |  |  |     static const enum AVSampleFormat sample_fmts[3][3] = { | 
					
						
							|  |  |  |         { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_DBLP, AV_SAMPLE_FMT_NONE }, | 
					
						
							|  |  |  |         { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, | 
					
						
							|  |  |  |         { AV_SAMPLE_FMT_DBLP, AV_SAMPLE_FMT_NONE }, | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  |     }; | 
					
						
							| 
									
										
										
										
											2018-05-29 18:24:22 +02:00
										 |  |  |     static const enum AVPixelFormat pix_fmts[] = { | 
					
						
							|  |  |  |         AV_PIX_FMT_RGB0, | 
					
						
							|  |  |  |         AV_PIX_FMT_NONE | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2018-10-04 21:10:47 +02:00
										 |  |  |     int ret; | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-29 18:24:22 +02:00
										 |  |  |     if (s->response) { | 
					
						
							|  |  |  |         AVFilterLink *videolink = ctx->outputs[1]; | 
					
						
							| 
									
										
										
										
											2021-08-10 01:25:31 +02:00
										 |  |  |         AVFilterFormats *formats = ff_make_format_list(pix_fmts); | 
					
						
							| 
									
										
										
										
											2020-08-24 12:16:34 +02:00
										 |  |  |         if ((ret = ff_formats_ref(formats, &videolink->incfg.formats)) < 0) | 
					
						
							| 
									
										
										
										
											2018-05-29 18:24:22 +02:00
										 |  |  |             return ret; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-04 21:10:47 +02:00
										 |  |  |     if (s->ir_format) { | 
					
						
							| 
									
										
										
										
											2021-08-10 01:25:31 +02:00
										 |  |  |         ret = ff_set_common_all_channel_counts(ctx); | 
					
						
							| 
									
										
										
										
											2018-10-04 21:10:47 +02:00
										 |  |  |         if (ret < 0) | 
					
						
							|  |  |  |             return ret; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         AVFilterChannelLayouts *mono = NULL; | 
					
						
							| 
									
										
										
										
											2021-08-10 01:25:31 +02:00
										 |  |  |         AVFilterChannelLayouts *layouts = ff_all_channel_counts(); | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-24 12:16:34 +02:00
										 |  |  |         if ((ret = ff_channel_layouts_ref(layouts, &ctx->inputs[0]->outcfg.channel_layouts)) < 0) | 
					
						
							| 
									
										
										
										
											2018-10-04 21:10:47 +02:00
										 |  |  |             return ret; | 
					
						
							| 
									
										
										
										
											2020-08-24 12:16:34 +02:00
										 |  |  |         if ((ret = ff_channel_layouts_ref(layouts, &ctx->outputs[0]->incfg.channel_layouts)) < 0) | 
					
						
							| 
									
										
										
										
											2018-10-04 21:10:47 +02:00
										 |  |  |             return ret; | 
					
						
							| 
									
										
										
										
											2020-08-07 04:58:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-31 11:03:14 -03:00
										 |  |  |         ret = ff_add_channel_layout(&mono, &(AVChannelLayout)AV_CHANNEL_LAYOUT_MONO); | 
					
						
							| 
									
										
										
										
											2020-08-07 04:58:56 +02:00
										 |  |  |         if (ret) | 
					
						
							|  |  |  |             return ret; | 
					
						
							| 
									
										
										
										
											2020-01-09 20:06:57 +01:00
										 |  |  |         for (int i = 1; i < ctx->nb_inputs; i++) { | 
					
						
							| 
									
										
										
										
											2020-08-24 12:16:34 +02:00
										 |  |  |             if ((ret = ff_channel_layouts_ref(mono, &ctx->inputs[i]->outcfg.channel_layouts)) < 0) | 
					
						
							| 
									
										
										
										
											2020-01-09 20:06:57 +01:00
										 |  |  |                 return ret; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-14 10:28:49 +02:00
										 |  |  |     if ((ret = ff_set_common_formats_from_list(ctx, sample_fmts[s->precision])) < 0) | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  |         return ret; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-10 01:25:31 +02:00
										 |  |  |     return ff_set_common_all_samplerates(ctx); | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int config_output(AVFilterLink *outlink) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     AVFilterContext *ctx = outlink->src; | 
					
						
							|  |  |  |     AudioFIRContext *s = ctx->priv; | 
					
						
							| 
									
										
										
										
											2021-08-31 11:03:14 -03:00
										 |  |  |     int ret; | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-31 11:03:14 -03:00
										 |  |  |     s->one2many = ctx->inputs[1 + s->selir]->ch_layout.nb_channels == 1; | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  |     outlink->sample_rate = ctx->inputs[0]->sample_rate; | 
					
						
							|  |  |  |     outlink->time_base   = ctx->inputs[0]->time_base; | 
					
						
							| 
									
										
										
										
											2021-08-31 11:03:14 -03:00
										 |  |  | #if FF_API_OLD_CHANNEL_LAYOUT
 | 
					
						
							|  |  |  | FF_DISABLE_DEPRECATION_WARNINGS | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  |     outlink->channel_layout = ctx->inputs[0]->channel_layout; | 
					
						
							| 
									
										
										
										
											2021-08-31 11:03:14 -03:00
										 |  |  | FF_ENABLE_DEPRECATION_WARNINGS | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     if ((ret = av_channel_layout_copy(&outlink->ch_layout, &ctx->inputs[0]->ch_layout)) < 0) | 
					
						
							|  |  |  |         return ret; | 
					
						
							|  |  |  |     outlink->ch_layout.nb_channels = ctx->inputs[0]->ch_layout.nb_channels; | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-14 10:28:49 +02:00
										 |  |  |     s->format = outlink->format; | 
					
						
							| 
									
										
										
										
											2022-12-13 11:46:02 +01:00
										 |  |  |     s->nb_channels = outlink->ch_layout.nb_channels; | 
					
						
							| 
									
										
										
										
											2023-04-23 23:30:42 +02:00
										 |  |  |     s->loading = av_calloc(ctx->inputs[0]->ch_layout.nb_channels, sizeof(*s->loading)); | 
					
						
							|  |  |  |     if (!s->loading) | 
					
						
							|  |  |  |         return AVERROR(ENOMEM); | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-25 15:21:51 +02:00
										 |  |  |     s->fadein[0] = ff_get_audio_buffer(outlink, s->min_part_size); | 
					
						
							|  |  |  |     s->fadein[1] = ff_get_audio_buffer(outlink, s->min_part_size); | 
					
						
							|  |  |  |     if (!s->fadein[0] || !s->fadein[1]) | 
					
						
							|  |  |  |         return AVERROR(ENOMEM); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-24 17:31:18 +02:00
										 |  |  |     s->xfade[0] = ff_get_audio_buffer(outlink, s->min_part_size); | 
					
						
							|  |  |  |     s->xfade[1] = ff_get_audio_buffer(outlink, s->min_part_size); | 
					
						
							|  |  |  |     if (!s->xfade[0] || !s->xfade[1]) | 
					
						
							|  |  |  |         return AVERROR(ENOMEM); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     switch (s->format) { | 
					
						
							|  |  |  |     case AV_SAMPLE_FMT_FLTP: | 
					
						
							|  |  |  |         for (int ch = 0; ch < s->nb_channels; ch++) { | 
					
						
							|  |  |  |             float *dst0 = (float *)s->xfade[0]->extended_data[ch]; | 
					
						
							|  |  |  |             float *dst1 = (float *)s->xfade[1]->extended_data[ch]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             for (int n = 0; n < s->min_part_size; n++) { | 
					
						
							|  |  |  |                 dst0[n] = (n + 1.f) / s->min_part_size; | 
					
						
							|  |  |  |                 dst1[n] = 1.f - dst0[n]; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case AV_SAMPLE_FMT_DBLP: | 
					
						
							|  |  |  |         for (int ch = 0; ch < s->nb_channels; ch++) { | 
					
						
							|  |  |  |             double *dst0 = (double *)s->xfade[0]->extended_data[ch]; | 
					
						
							|  |  |  |             double *dst1 = (double *)s->xfade[1]->extended_data[ch]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             for (int n = 0; n < s->min_part_size; n++) { | 
					
						
							|  |  |  |                 dst0[n] = (n + 1.0) / s->min_part_size; | 
					
						
							|  |  |  |                 dst1[n] = 1.0 - dst0[n]; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-28 18:45:55 +01:00
										 |  |  | static av_cold void uninit(AVFilterContext *ctx) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     AudioFIRContext *s = ctx->priv; | 
					
						
							| 
									
										
										
										
											2018-12-28 17:57:24 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  |     av_freep(&s->fdsp); | 
					
						
							| 
									
										
										
										
											2023-04-23 23:30:42 +02:00
										 |  |  |     av_freep(&s->loading); | 
					
						
							| 
									
										
										
										
											2020-01-09 20:06:57 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-31 23:31:31 +01:00
										 |  |  |     for (int i = 0; i < s->nb_irs; i++) { | 
					
						
							| 
									
										
										
										
											2023-04-23 23:30:42 +02:00
										 |  |  |         for (int j = 0; j < s->nb_segments[i]; j++) | 
					
						
							|  |  |  |             uninit_segment(ctx, &s->seg[i][j]); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-09 20:06:57 +01:00
										 |  |  |         av_frame_free(&s->ir[i]); | 
					
						
							| 
									
										
										
										
											2022-12-31 23:31:31 +01:00
										 |  |  |         av_frame_free(&s->norm_ir[i]); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-01-09 20:06:57 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-25 15:21:51 +02:00
										 |  |  |     av_frame_free(&s->fadein[0]); | 
					
						
							|  |  |  |     av_frame_free(&s->fadein[1]); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-24 17:31:18 +02:00
										 |  |  |     av_frame_free(&s->xfade[0]); | 
					
						
							|  |  |  |     av_frame_free(&s->xfade[1]); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-29 18:24:22 +02:00
										 |  |  |     av_frame_free(&s->video); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int config_video(AVFilterLink *outlink) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     AVFilterContext *ctx = outlink->src; | 
					
						
							|  |  |  |     AudioFIRContext *s = ctx->priv; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     outlink->sample_aspect_ratio = (AVRational){1,1}; | 
					
						
							|  |  |  |     outlink->w = s->w; | 
					
						
							|  |  |  |     outlink->h = s->h; | 
					
						
							| 
									
										
										
										
											2018-11-08 12:46:29 +01:00
										 |  |  |     outlink->frame_rate = s->frame_rate; | 
					
						
							|  |  |  |     outlink->time_base = av_inv_q(outlink->frame_rate); | 
					
						
							| 
									
										
										
										
											2018-05-29 18:24:22 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     av_frame_free(&s->video); | 
					
						
							|  |  |  |     s->video = ff_get_video_buffer(outlink, outlink->w, outlink->h); | 
					
						
							|  |  |  |     if (!s->video) | 
					
						
							|  |  |  |         return AVERROR(ENOMEM); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static av_cold int init(AVFilterContext *ctx) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     AudioFIRContext *s = ctx->priv; | 
					
						
							| 
									
										
										
										
											2018-05-29 18:24:22 +02:00
										 |  |  |     AVFilterPad pad, vpad; | 
					
						
							| 
									
										
										
										
											2018-09-15 20:03:40 +02:00
										 |  |  |     int ret; | 
					
						
							| 
									
										
										
										
											2018-05-29 18:24:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-13 11:46:02 +01:00
										 |  |  |     s->prev_selir = FFMIN(s->nb_irs - 1, s->selir); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-09 20:06:57 +01:00
										 |  |  |     pad = (AVFilterPad) { | 
					
						
							| 
									
										
										
										
											2020-08-22 05:20:01 +02:00
										 |  |  |         .name = "main", | 
					
						
							| 
									
										
										
										
											2020-01-09 20:06:57 +01:00
										 |  |  |         .type = AVMEDIA_TYPE_AUDIO, | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-16 20:48:00 +02:00
										 |  |  |     ret = ff_append_inpad(ctx, &pad); | 
					
						
							| 
									
										
										
										
											2020-08-22 05:20:01 +02:00
										 |  |  |     if (ret < 0) | 
					
						
							| 
									
										
										
										
											2020-01-09 20:06:57 +01:00
										 |  |  |         return ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (int n = 0; n < s->nb_irs; n++) { | 
					
						
							|  |  |  |         pad = (AVFilterPad) { | 
					
						
							|  |  |  |             .name = av_asprintf("ir%d", n), | 
					
						
							|  |  |  |             .type = AVMEDIA_TYPE_AUDIO, | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!pad.name) | 
					
						
							|  |  |  |             return AVERROR(ENOMEM); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-16 21:39:50 +02:00
										 |  |  |         ret = ff_append_inpad_free_name(ctx, &pad); | 
					
						
							|  |  |  |         if (ret < 0) | 
					
						
							| 
									
										
										
										
											2020-01-09 20:06:57 +01:00
										 |  |  |             return ret; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     pad = (AVFilterPad) { | 
					
						
							| 
									
										
										
										
											2020-08-22 05:20:01 +02:00
										 |  |  |         .name          = "default", | 
					
						
							| 
									
										
										
										
											2018-05-29 18:24:22 +02:00
										 |  |  |         .type          = AVMEDIA_TYPE_AUDIO, | 
					
						
							|  |  |  |         .config_props  = config_output, | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-16 20:48:00 +02:00
										 |  |  |     ret = ff_append_outpad(ctx, &pad); | 
					
						
							| 
									
										
										
										
											2020-08-22 05:20:01 +02:00
										 |  |  |     if (ret < 0) | 
					
						
							| 
									
										
										
										
											2020-05-25 08:48:12 +08:00
										 |  |  |         return ret; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-29 18:24:22 +02:00
										 |  |  |     if (s->response) { | 
					
						
							|  |  |  |         vpad = (AVFilterPad){ | 
					
						
							| 
									
										
										
										
											2020-08-22 05:20:01 +02:00
										 |  |  |             .name         = "filter_response", | 
					
						
							| 
									
										
										
										
											2018-05-29 18:24:22 +02:00
										 |  |  |             .type         = AVMEDIA_TYPE_VIDEO, | 
					
						
							|  |  |  |             .config_props = config_video, | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-16 20:48:00 +02:00
										 |  |  |         ret = ff_append_outpad(ctx, &vpad); | 
					
						
							| 
									
										
										
										
											2020-08-22 05:20:01 +02:00
										 |  |  |         if (ret < 0) | 
					
						
							| 
									
										
										
										
											2018-09-15 20:03:40 +02:00
										 |  |  |             return ret; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     s->fdsp = avpriv_float_dsp_alloc(0); | 
					
						
							|  |  |  |     if (!s->fdsp) | 
					
						
							|  |  |  |         return AVERROR(ENOMEM); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-02 20:54:18 -03:00
										 |  |  |     ff_afir_init(&s->afirdsp); | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-24 17:31:18 +02:00
										 |  |  |     s->min_part_size = 1 << av_log2(s->minp); | 
					
						
							| 
									
										
										
										
											2023-04-25 15:21:51 +02:00
										 |  |  |     s->max_part_size = 1 << av_log2(s->maxp); | 
					
						
							| 
									
										
										
										
											2023-04-24 17:31:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-09 20:06:57 +01:00
										 |  |  | static int process_command(AVFilterContext *ctx, | 
					
						
							|  |  |  |                            const char *cmd, | 
					
						
							|  |  |  |                            const char *arg, | 
					
						
							|  |  |  |                            char *res, | 
					
						
							|  |  |  |                            int res_len, | 
					
						
							|  |  |  |                            int flags) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     AudioFIRContext *s = ctx->priv; | 
					
						
							| 
									
										
										
										
											2022-12-25 18:07:47 +01:00
										 |  |  |     int prev_selir, ret; | 
					
						
							| 
									
										
										
										
											2020-01-09 20:06:57 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-25 18:07:47 +01:00
										 |  |  |     prev_selir = s->selir; | 
					
						
							| 
									
										
										
										
											2022-12-13 11:46:02 +01:00
										 |  |  |     ret = ff_filter_process_command(ctx, cmd, arg, res, res_len, flags); | 
					
						
							| 
									
										
										
										
											2020-01-09 20:06:57 +01:00
										 |  |  |     if (ret < 0) | 
					
						
							|  |  |  |         return ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     s->selir = FFMIN(s->nb_irs - 1, s->selir); | 
					
						
							| 
									
										
										
										
											2023-04-25 20:33:08 +02:00
										 |  |  |     if (s->selir != prev_selir) { | 
					
						
							| 
									
										
										
										
											2022-12-25 18:07:47 +01:00
										 |  |  |         s->prev_selir = prev_selir; | 
					
						
							| 
									
										
										
										
											2020-01-09 20:06:57 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-25 20:33:08 +02:00
										 |  |  |         for (int ch = 0; ch < s->nb_channels; ch++) | 
					
						
							|  |  |  |             s->loading[ch] = 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-09 20:06:57 +01:00
										 |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define AF AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
 | 
					
						
							| 
									
										
										
										
											2020-01-09 20:06:57 +01:00
										 |  |  | #define AFR AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM
 | 
					
						
							| 
									
										
										
										
											2018-05-29 18:24:22 +02:00
										 |  |  | #define VF AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
 | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  | #define OFFSET(x) offsetof(AudioFIRContext, x)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const AVOption afir_options[] = { | 
					
						
							| 
									
										
										
										
											2022-12-22 17:04:29 +01:00
										 |  |  |     { "dry",    "set dry gain",      OFFSET(dry_gain),   AV_OPT_TYPE_FLOAT, {.dbl=1},    0, 10, AFR }, | 
					
						
							|  |  |  |     { "wet",    "set wet gain",      OFFSET(wet_gain),   AV_OPT_TYPE_FLOAT, {.dbl=1},    0, 10, AFR }, | 
					
						
							| 
									
										
										
										
											2018-04-16 19:06:09 +02:00
										 |  |  |     { "length", "set IR length",     OFFSET(length),     AV_OPT_TYPE_FLOAT, {.dbl=1},    0,  1, AF }, | 
					
						
							| 
									
										
										
										
											2022-12-13 11:46:02 +01:00
										 |  |  |     { "gtype",  "set IR auto gain type",OFFSET(gtype),   AV_OPT_TYPE_INT,   {.i64=0},   -1,  4, AF, "gtype" }, | 
					
						
							| 
									
										
										
										
											2018-10-10 19:55:30 +02:00
										 |  |  |     {  "none",  "without auto gain", 0,                  AV_OPT_TYPE_CONST, {.i64=-1},   0,  0, AF, "gtype" }, | 
					
						
							| 
									
										
										
										
											2018-10-03 21:43:40 +02:00
										 |  |  |     {  "peak",  "peak gain",         0,                  AV_OPT_TYPE_CONST, {.i64=0},    0,  0, AF, "gtype" }, | 
					
						
							|  |  |  |     {  "dc",    "DC gain",           0,                  AV_OPT_TYPE_CONST, {.i64=1},    0,  0, AF, "gtype" }, | 
					
						
							|  |  |  |     {  "gn",    "gain to noise",     0,                  AV_OPT_TYPE_CONST, {.i64=2},    0,  0, AF, "gtype" }, | 
					
						
							| 
									
										
										
										
											2022-12-13 11:46:02 +01:00
										 |  |  |     {  "ac",    "AC gain",           0,                  AV_OPT_TYPE_CONST, {.i64=3},    0,  0, AF, "gtype" }, | 
					
						
							|  |  |  |     {  "rms",   "RMS gain",          0,                  AV_OPT_TYPE_CONST, {.i64=4},    0,  0, AF, "gtype" }, | 
					
						
							| 
									
										
										
										
											2018-10-03 21:43:40 +02:00
										 |  |  |     { "irgain", "set IR gain",       OFFSET(ir_gain),    AV_OPT_TYPE_FLOAT, {.dbl=1},    0,  1, AF }, | 
					
						
							| 
									
										
										
										
											2018-10-04 21:10:47 +02:00
										 |  |  |     { "irfmt",  "set IR format",     OFFSET(ir_format),  AV_OPT_TYPE_INT,   {.i64=1},    0,  1, AF, "irfmt" }, | 
					
						
							|  |  |  |     {  "mono",  "single channel",    0,                  AV_OPT_TYPE_CONST, {.i64=0},    0,  0, AF, "irfmt" }, | 
					
						
							|  |  |  |     {  "input", "same as input",     0,                  AV_OPT_TYPE_CONST, {.i64=1},    0,  0, AF, "irfmt" }, | 
					
						
							| 
									
										
										
										
											2018-05-29 18:24:22 +02:00
										 |  |  |     { "maxir",  "set max IR length", OFFSET(max_ir_len), AV_OPT_TYPE_FLOAT, {.dbl=30}, 0.1, 60, AF }, | 
					
						
							|  |  |  |     { "response", "show IR frequency response", OFFSET(response), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, VF }, | 
					
						
							|  |  |  |     { "channel", "set IR channel to display frequency response", OFFSET(ir_channel), AV_OPT_TYPE_INT, {.i64=0}, 0, 1024, VF }, | 
					
						
							|  |  |  |     { "size",   "set video size",    OFFSET(w),          AV_OPT_TYPE_IMAGE_SIZE, {.str = "hd720"}, 0, 0, VF }, | 
					
						
							| 
									
										
										
										
											2018-11-08 12:46:29 +01:00
										 |  |  |     { "rate",   "set video rate",    OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT32_MAX, VF }, | 
					
						
							| 
									
										
										
										
											2022-12-25 10:21:47 +01:00
										 |  |  |     { "minp",   "set min partition size", OFFSET(minp),  AV_OPT_TYPE_INT,   {.i64=8192}, 1, 65536, AF }, | 
					
						
							|  |  |  |     { "maxp",   "set max partition size", OFFSET(maxp),  AV_OPT_TYPE_INT,   {.i64=8192}, 8, 65536, AF }, | 
					
						
							| 
									
										
										
										
											2020-01-09 20:06:57 +01:00
										 |  |  |     { "nbirs",  "set number of input IRs",OFFSET(nb_irs),AV_OPT_TYPE_INT,   {.i64=1},    1,    32, AF }, | 
					
						
							|  |  |  |     { "ir",     "select IR",              OFFSET(selir), AV_OPT_TYPE_INT,   {.i64=0},    0,    31, AFR }, | 
					
						
							| 
									
										
										
										
											2022-05-14 10:28:49 +02:00
										 |  |  |     { "precision", "set processing precision",    OFFSET(precision), AV_OPT_TYPE_INT,   {.i64=0}, 0, 2, AF, "precision" }, | 
					
						
							|  |  |  |     {  "auto", "set auto processing precision",                   0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "precision" }, | 
					
						
							|  |  |  |     {  "float", "set single-floating point processing precision", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "precision" }, | 
					
						
							|  |  |  |     {  "double","set double-floating point processing precision", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, AF, "precision" }, | 
					
						
							| 
									
										
										
										
											2023-04-25 15:42:44 +02:00
										 |  |  |     { "irload", "set IR loading type", OFFSET(ir_load), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, AF, "irload" }, | 
					
						
							|  |  |  |     {  "init",   "load all IRs on init", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "irload" }, | 
					
						
							|  |  |  |     {  "access", "load IR on access",    0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "irload" }, | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  |     { NULL } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | AVFILTER_DEFINE_CLASS(afir); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-19 18:33:56 +02:00
										 |  |  | const AVFilter ff_af_afir = { | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  |     .name          = "afir", | 
					
						
							| 
									
										
										
										
											2020-01-09 20:06:57 +01:00
										 |  |  |     .description   = NULL_IF_CONFIG_SMALL("Apply Finite Impulse Response filter with supplied coefficients in additional stream(s)."), | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  |     .priv_size     = sizeof(AudioFIRContext), | 
					
						
							|  |  |  |     .priv_class    = &afir_class, | 
					
						
							| 
									
										
										
										
											2021-09-27 12:07:35 +02:00
										 |  |  |     FILTER_QUERY_FUNC(query_formats), | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  |     .init          = init, | 
					
						
							| 
									
										
										
										
											2018-09-15 20:35:08 +02:00
										 |  |  |     .activate      = activate, | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  |     .uninit        = uninit, | 
					
						
							| 
									
										
										
										
											2020-01-09 20:06:57 +01:00
										 |  |  |     .process_command = process_command, | 
					
						
							|  |  |  |     .flags         = AVFILTER_FLAG_DYNAMIC_INPUTS  | | 
					
						
							|  |  |  |                      AVFILTER_FLAG_DYNAMIC_OUTPUTS | | 
					
						
							| 
									
										
										
										
											2018-05-29 18:24:22 +02:00
										 |  |  |                      AVFILTER_FLAG_SLICE_THREADS, | 
					
						
							| 
									
										
										
										
											2017-01-26 17:03:08 +01:00
										 |  |  | }; |