X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavfilter%2Faf_headphone.c;h=8db546adbfc8273ed289f3c2b25c0d4ed9b2d0e6;hb=8dda0d601becf19e6cdf350e2fe82b4db7339bd1;hp=6b210e1436de7de154b3dba95b09e6e95e39eeed;hpb=a12063b118ad05409ff775ba30fab00265ad3031;p=ffmpeg diff --git a/libavfilter/af_headphone.c b/libavfilter/af_headphone.c index 6b210e1436d..8db546adbfc 100644 --- a/libavfilter/af_headphone.c +++ b/libavfilter/af_headphone.c @@ -20,7 +20,6 @@ #include -#include "libavutil/audio_fifo.h" #include "libavutil/avstring.h" #include "libavutil/channel_layout.h" #include "libavutil/float_dsp.h" @@ -51,10 +50,9 @@ typedef struct HeadphoneContext { int eof_hrirs; int ir_len; + int air_len; - int mapping[64]; - - int nb_inputs; + int nb_hrir_inputs; int nb_irs; @@ -69,96 +67,71 @@ typedef struct HeadphoneContext { int size; int hrir_fmt; - int *delay[2]; float *data_ir[2]; float *temp_src[2]; FFTComplex *temp_fft[2]; + FFTComplex *temp_afft[2]; FFTContext *fft[2], *ifft[2]; FFTComplex *data_hrtf[2]; - AVFloatDSPContext *fdsp; - struct headphone_inputs { - AVAudioFifo *fifo; - AVFrame *frame; + float (*scalarproduct_float)(const float *v1, const float *v2, int len); + struct hrir_inputs { int ir_len; - int delay_l; - int delay_r; int eof; - } *in; + } hrir_in[64]; + uint64_t mapping[64]; } HeadphoneContext; -static int parse_channel_name(HeadphoneContext *s, int x, char **arg, int *rchannel, char *buf) +static int parse_channel_name(const char *arg, uint64_t *rchannel) { - int len, i, channel_id = 0; - int64_t layout, layout0; - - if (sscanf(*arg, "%7[A-Z]%n", buf, &len)) { - layout0 = layout = av_get_channel_layout(buf); - if (layout == AV_CH_LOW_FREQUENCY) - s->lfe_channel = x; - for (i = 32; i > 0; i >>= 1) { - if (layout >= 1LL << i) { - channel_id += i; - layout >>= i; - } - } - if (channel_id >= 64 || layout0 != 1LL << channel_id) - return AVERROR(EINVAL); - *rchannel = channel_id; - *arg += len; - return 0; - } - return AVERROR(EINVAL); + uint64_t layout = av_get_channel_layout(arg); + + if (av_get_channel_layout_nb_channels(layout) != 1) + return AVERROR(EINVAL); + *rchannel = layout; + return 0; } static void parse_map(AVFilterContext *ctx) { HeadphoneContext *s = ctx->priv; - char *arg, *tokenizer, *p, *args = av_strdup(s->map); - int i; - - if (!args) - return; - p = args; - - s->lfe_channel = -1; - s->nb_inputs = 1; - - for (i = 0; i < 64; i++) { - s->mapping[i] = -1; - } + char *arg, *tokenizer, *p; + uint64_t used_channels = 0; + p = s->map; while ((arg = av_strtok(p, "|", &tokenizer))) { - int out_ch_id; - char buf[8]; + uint64_t out_channel; p = NULL; - if (parse_channel_name(s, s->nb_irs, &arg, &out_ch_id, buf)) { - av_log(ctx, AV_LOG_WARNING, "Failed to parse \'%s\' as channel name.\n", buf); + if (parse_channel_name(arg, &out_channel)) { + av_log(ctx, AV_LOG_WARNING, "Failed to parse \'%s\' as channel name.\n", arg); continue; } - s->mapping[s->nb_irs] = out_ch_id; + if (used_channels & out_channel) { + av_log(ctx, AV_LOG_WARNING, "Ignoring duplicate channel '%s'.\n", arg); + continue; + } + used_channels |= out_channel; + s->mapping[s->nb_irs] = out_channel; s->nb_irs++; } if (s->hrir_fmt == HRIR_MULTI) - s->nb_inputs = 2; + s->nb_hrir_inputs = 1; else - s->nb_inputs = s->nb_irs + 1; - - av_free(args); + s->nb_hrir_inputs = s->nb_irs; } typedef struct ThreadData { AVFrame *in, *out; int *write; - int **delay; float **ir; int *n_clippings; float **ringbuffer; float **temp_src; FFTComplex **temp_fft; + FFTComplex **temp_afft; } ThreadData; static int headphone_convolute(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) @@ -168,18 +141,18 @@ static int headphone_convolute(AVFilterContext *ctx, void *arg, int jobnr, int n AVFrame *in = td->in, *out = td->out; int offset = jobnr; int *write = &td->write[jobnr]; - const int *const delay = td->delay[jobnr]; const float *const ir = td->ir[jobnr]; int *n_clippings = &td->n_clippings[jobnr]; float *ringbuffer = td->ringbuffer[jobnr]; float *temp_src = td->temp_src[jobnr]; const int ir_len = s->ir_len; + const int air_len = s->air_len; const float *src = (const float *)in->data[0]; float *dst = (float *)out->data[0]; const int in_channels = in->channels; const int buffer_length = s->buffer_length; const uint32_t modulo = (uint32_t)buffer_length - 1; - float *buffer[16]; + float *buffer[64]; int wr = *write; int read; int i, l; @@ -190,39 +163,37 @@ static int headphone_convolute(AVFilterContext *ctx, void *arg, int jobnr, int n } for (i = 0; i < in->nb_samples; i++) { - const float *temp_ir = ir; + const float *cur_ir = ir; *dst = 0; for (l = 0; l < in_channels; l++) { *(buffer[l] + wr) = src[l]; } - for (l = 0; l < in_channels; l++) { + for (l = 0; l < in_channels; cur_ir += air_len, l++) { const float *const bptr = buffer[l]; if (l == s->lfe_channel) { *dst += *(buffer[s->lfe_channel] + wr) * s->gain_lfe; - temp_ir += FFALIGN(ir_len, 16); continue; } - read = (wr - *(delay + l) - (ir_len - 1) + buffer_length) & modulo; + read = (wr - (ir_len - 1) + buffer_length) & modulo; if (read + ir_len < buffer_length) { memcpy(temp_src, bptr + read, ir_len * sizeof(*temp_src)); } else { - int len = FFMIN(ir_len - (read % ir_len), buffer_length - read); + int len = FFMIN(air_len - (read % ir_len), buffer_length - read); memcpy(temp_src, bptr + read, len * sizeof(*temp_src)); - memcpy(temp_src + len, bptr, (ir_len - len) * sizeof(*temp_src)); + memcpy(temp_src + len, bptr, (air_len - len) * sizeof(*temp_src)); } - dst[0] += s->fdsp->scalarproduct_float(temp_ir, temp_src, ir_len); - temp_ir += FFALIGN(ir_len, 16); + dst[0] += s->scalarproduct_float(cur_ir, temp_src, FFALIGN(ir_len, 32)); } - if (fabs(*dst) > 1) - *n_clippings += 1; + if (fabsf(dst[0]) > 1) + n_clippings[0]++; dst += 2; src += in_channels; @@ -251,6 +222,7 @@ static int headphone_fast_convolute(AVFilterContext *ctx, void *arg, int jobnr, const int buffer_length = s->buffer_length; const uint32_t modulo = (uint32_t)buffer_length - 1; FFTComplex *fft_in = s->temp_fft[jobnr]; + FFTComplex *fft_acc = s->temp_afft[jobnr]; FFTContext *ifft = s->ifft[jobnr]; FFTContext *fft = s->fft[jobnr]; const int n_fft = s->n_fft; @@ -262,7 +234,7 @@ static int headphone_fast_convolute(AVFilterContext *ctx, void *arg, int jobnr, dst += offset; - n_read = FFMIN(s->ir_len, in->nb_samples); + n_read = FFMIN(ir_len, in->nb_samples); for (j = 0; j < n_read; j++) { dst[2 * j] = ringbuffer[wr]; ringbuffer[wr] = 0.0; @@ -273,6 +245,8 @@ static int headphone_fast_convolute(AVFilterContext *ctx, void *arg, int jobnr, dst[2 * j] = 0; } + memset(fft_acc, 0, sizeof(FFTComplex) * n_fft); + for (i = 0; i < in_channels; i++) { if (i == s->lfe_channel) { for (j = 0; j < in->nb_samples; j++) { @@ -297,26 +271,26 @@ static int headphone_fast_convolute(AVFilterContext *ctx, void *arg, int jobnr, const float re = fft_in[j].re; const float im = fft_in[j].im; - fft_in[j].re = re * hcomplex->re - im * hcomplex->im; - fft_in[j].im = re * hcomplex->im + im * hcomplex->re; + fft_acc[j].re += re * hcomplex->re - im * hcomplex->im; + fft_acc[j].im += re * hcomplex->im + im * hcomplex->re; } + } - av_fft_permute(ifft, fft_in); - av_fft_calc(ifft, fft_in); + av_fft_permute(ifft, fft_acc); + av_fft_calc(ifft, fft_acc); - for (j = 0; j < in->nb_samples; j++) { - dst[2 * j] += fft_in[j].re * fft_scale; - } + for (j = 0; j < in->nb_samples; j++) { + dst[2 * j] += fft_acc[j].re * fft_scale; + } - for (j = 0; j < ir_len - 1; j++) { - int write_pos = (wr + j) & modulo; + for (j = 0; j < ir_len - 1; j++) { + int write_pos = (wr + j) & modulo; - *(ringbuffer + write_pos) += fft_in[in->nb_samples + j].re * fft_scale; - } + *(ringbuffer + write_pos) += fft_acc[in->nb_samples + j].re * fft_scale; } for (i = 0; i < out->nb_samples; i++) { - if (fabs(*dst) > 1) { + if (fabsf(dst[0]) > 1) { n_clippings[0]++; } @@ -328,26 +302,19 @@ static int headphone_fast_convolute(AVFilterContext *ctx, void *arg, int jobnr, return 0; } -static int read_ir(AVFilterLink *inlink, int input_number, AVFrame *frame) +static int check_ir(AVFilterLink *inlink, int input_number) { AVFilterContext *ctx = inlink->dst; HeadphoneContext *s = ctx->priv; - int ir_len, max_ir_len, ret; - - ret = av_audio_fifo_write(s->in[input_number].fifo, (void **)frame->extended_data, - frame->nb_samples); - av_frame_free(&frame); + int ir_len, max_ir_len; - if (ret < 0) - return ret; - - ir_len = av_audio_fifo_size(s->in[input_number].fifo); + ir_len = ff_inlink_queued_samples(inlink); max_ir_len = 65536; if (ir_len > max_ir_len) { av_log(ctx, AV_LOG_ERROR, "Too big length of IRs: %d > %d.\n", ir_len, max_ir_len); return AVERROR(EINVAL); } - s->in[input_number].ir_len = ir_len; + s->hrir_in[input_number].ir_len = ir_len; s->ir_len = FFMAX(ir_len, s->ir_len); return 0; @@ -368,9 +335,10 @@ static int headphone_frame(HeadphoneContext *s, AVFrame *in, AVFilterLink *outli out->pts = in->pts; td.in = in; td.out = out; td.write = s->write; - td.delay = s->delay; td.ir = s->data_ir; td.n_clippings = n_clippings; + td.ir = s->data_ir; td.n_clippings = n_clippings; td.ringbuffer = s->ringbuffer; td.temp_src = s->temp_src; td.temp_fft = s->temp_fft; + td.temp_afft = s->temp_afft; if (s->type == TIME_DOMAIN) { ctx->internal->execute(ctx, headphone_convolute, &td, NULL, 2); @@ -392,38 +360,25 @@ static int convert_coeffs(AVFilterContext *ctx, AVFilterLink *inlink) { struct HeadphoneContext *s = ctx->priv; const int ir_len = s->ir_len; - int nb_irs = s->nb_irs; int nb_input_channels = ctx->inputs[0]->channels; float gain_lin = expf((s->gain - 3 * nb_input_channels) / 20 * M_LN10); - FFTComplex *data_hrtf_l = NULL; - FFTComplex *data_hrtf_r = NULL; - FFTComplex *fft_in_l = NULL; - FFTComplex *fft_in_r = NULL; - float *data_ir_l = NULL; - float *data_ir_r = NULL; - int offset = 0, ret = 0; + AVFrame *frame; + int ret = 0; int n_fft; int i, j, k; - s->buffer_length = 1 << (32 - ff_clz(s->ir_len)); - s->n_fft = n_fft = 1 << (32 - ff_clz(s->ir_len + s->size)); + s->air_len = 1 << (32 - ff_clz(ir_len)); + if (s->type == TIME_DOMAIN) { + s->air_len = FFALIGN(s->air_len, 32); + } + s->buffer_length = 1 << (32 - ff_clz(s->air_len)); + s->n_fft = n_fft = 1 << (32 - ff_clz(ir_len + s->size)); if (s->type == FREQUENCY_DOMAIN) { - fft_in_l = av_calloc(n_fft, sizeof(*fft_in_l)); - fft_in_r = av_calloc(n_fft, sizeof(*fft_in_r)); - if (!fft_in_l || !fft_in_r) { - ret = AVERROR(ENOMEM); - goto fail; - } - - av_fft_end(s->fft[0]); - av_fft_end(s->fft[1]); - s->fft[0] = av_fft_init(log2(s->n_fft), 0); - s->fft[1] = av_fft_init(log2(s->n_fft), 0); - av_fft_end(s->ifft[0]); - av_fft_end(s->ifft[1]); - s->ifft[0] = av_fft_init(log2(s->n_fft), 1); - s->ifft[1] = av_fft_init(log2(s->n_fft), 1); + s->fft[0] = av_fft_init(av_log2(s->n_fft), 0); + s->fft[1] = av_fft_init(av_log2(s->n_fft), 0); + s->ifft[0] = av_fft_init(av_log2(s->n_fft), 1); + s->ifft[1] = av_fft_init(av_log2(s->n_fft), 1); if (!s->fft[0] || !s->fft[1] || !s->ifft[0] || !s->ifft[1]) { av_log(ctx, AV_LOG_ERROR, "Unable to create FFT contexts of size %d.\n", s->n_fft); @@ -432,11 +387,6 @@ static int convert_coeffs(AVFilterContext *ctx, AVFilterLink *inlink) } } - s->data_ir[0] = av_calloc(FFALIGN(s->ir_len, 16), sizeof(float) * s->nb_irs); - s->data_ir[1] = av_calloc(FFALIGN(s->ir_len, 16), sizeof(float) * s->nb_irs); - s->delay[0] = av_calloc(s->nb_irs, sizeof(float)); - s->delay[1] = av_calloc(s->nb_irs, sizeof(float)); - if (s->type == TIME_DOMAIN) { s->ringbuffer[0] = av_calloc(s->buffer_length, sizeof(float) * nb_input_channels); s->ringbuffer[1] = av_calloc(s->buffer_length, sizeof(float) * nb_input_channels); @@ -445,170 +395,114 @@ static int convert_coeffs(AVFilterContext *ctx, AVFilterLink *inlink) s->ringbuffer[1] = av_calloc(s->buffer_length, sizeof(float)); s->temp_fft[0] = av_calloc(s->n_fft, sizeof(FFTComplex)); s->temp_fft[1] = av_calloc(s->n_fft, sizeof(FFTComplex)); - if (!s->temp_fft[0] || !s->temp_fft[1]) { + s->temp_afft[0] = av_calloc(s->n_fft, sizeof(FFTComplex)); + s->temp_afft[1] = av_calloc(s->n_fft, sizeof(FFTComplex)); + if (!s->temp_fft[0] || !s->temp_fft[1] || + !s->temp_afft[0] || !s->temp_afft[1]) { ret = AVERROR(ENOMEM); goto fail; } } - if (!s->data_ir[0] || !s->data_ir[1] || - !s->ringbuffer[0] || !s->ringbuffer[1]) { + if (!s->ringbuffer[0] || !s->ringbuffer[1]) { ret = AVERROR(ENOMEM); goto fail; } - for (i = 0; i < s->nb_inputs - 1; i++) { - s->in[i + 1].frame = ff_get_audio_buffer(ctx->inputs[i + 1], s->ir_len); - if (!s->in[i + 1].frame) { - ret = AVERROR(ENOMEM); - goto fail; - } - } - if (s->type == TIME_DOMAIN) { - s->temp_src[0] = av_calloc(FFALIGN(ir_len, 16), sizeof(float)); - s->temp_src[1] = av_calloc(FFALIGN(ir_len, 16), sizeof(float)); + s->temp_src[0] = av_calloc(s->air_len, sizeof(float)); + s->temp_src[1] = av_calloc(s->air_len, sizeof(float)); - data_ir_l = av_calloc(nb_irs * FFALIGN(ir_len, 16), sizeof(*data_ir_l)); - data_ir_r = av_calloc(nb_irs * FFALIGN(ir_len, 16), sizeof(*data_ir_r)); - if (!data_ir_r || !data_ir_l || !s->temp_src[0] || !s->temp_src[1]) { + s->data_ir[0] = av_calloc(nb_input_channels * s->air_len, sizeof(*s->data_ir[0])); + s->data_ir[1] = av_calloc(nb_input_channels * s->air_len, sizeof(*s->data_ir[1])); + if (!s->data_ir[0] || !s->data_ir[1] || !s->temp_src[0] || !s->temp_src[1]) { ret = AVERROR(ENOMEM); goto fail; } } else { - data_hrtf_l = av_calloc(n_fft, sizeof(*data_hrtf_l) * nb_irs); - data_hrtf_r = av_calloc(n_fft, sizeof(*data_hrtf_r) * nb_irs); - if (!data_hrtf_r || !data_hrtf_l) { + s->data_hrtf[0] = av_calloc(n_fft, sizeof(*s->data_hrtf[0]) * nb_input_channels); + s->data_hrtf[1] = av_calloc(n_fft, sizeof(*s->data_hrtf[1]) * nb_input_channels); + if (!s->data_hrtf[0] || !s->data_hrtf[1]) { ret = AVERROR(ENOMEM); goto fail; } } - for (i = 0; i < s->nb_inputs - 1; i++) { - int len = s->in[i + 1].ir_len; - int delay_l = s->in[i + 1].delay_l; - int delay_r = s->in[i + 1].delay_r; + for (i = 0; i < s->nb_hrir_inputs; av_frame_free(&frame), i++) { + int len = s->hrir_in[i].ir_len; float *ptr; - av_audio_fifo_read(s->in[i + 1].fifo, (void **)s->in[i + 1].frame->extended_data, len); - ptr = (float *)s->in[i + 1].frame->extended_data[0]; + ret = ff_inlink_consume_samples(ctx->inputs[i + 1], len, len, &frame); + if (ret < 0) + goto fail; + ptr = (float *)frame->extended_data[0]; if (s->hrir_fmt == HRIR_STEREO) { - int idx = -1; - - for (j = 0; j < inlink->channels; j++) { - if (s->mapping[i] < 0) { - continue; - } - - if ((av_channel_layout_extract_channel(inlink->channel_layout, j)) == (1LL << s->mapping[i])) { - idx = i; - break; - } - } - - if (idx == -1) + int idx = av_get_channel_layout_channel_index(inlink->channel_layout, + s->mapping[i]); + if (idx < 0) continue; if (s->type == TIME_DOMAIN) { - offset = idx * FFALIGN(len, 16); + float *data_ir_l = s->data_ir[0] + idx * s->air_len; + float *data_ir_r = s->data_ir[1] + idx * s->air_len; + for (j = 0; j < len; j++) { - data_ir_l[offset + j] = ptr[len * 2 - j * 2 - 2] * gain_lin; - data_ir_r[offset + j] = ptr[len * 2 - j * 2 - 1] * gain_lin; + data_ir_l[j] = ptr[len * 2 - j * 2 - 2] * gain_lin; + data_ir_r[j] = ptr[len * 2 - j * 2 - 1] * gain_lin; } } else { - memset(fft_in_l, 0, n_fft * sizeof(*fft_in_l)); - memset(fft_in_r, 0, n_fft * sizeof(*fft_in_r)); + FFTComplex *fft_in_l = s->data_hrtf[0] + idx * n_fft; + FFTComplex *fft_in_r = s->data_hrtf[1] + idx * n_fft; - offset = idx * n_fft; for (j = 0; j < len; j++) { - fft_in_l[delay_l + j].re = ptr[j * 2 ] * gain_lin; - fft_in_r[delay_r + j].re = ptr[j * 2 + 1] * gain_lin; + fft_in_l[j].re = ptr[j * 2 ] * gain_lin; + fft_in_r[j].re = ptr[j * 2 + 1] * gain_lin; } av_fft_permute(s->fft[0], fft_in_l); av_fft_calc(s->fft[0], fft_in_l); - memcpy(data_hrtf_l + offset, fft_in_l, n_fft * sizeof(*fft_in_l)); av_fft_permute(s->fft[0], fft_in_r); av_fft_calc(s->fft[0], fft_in_r); - memcpy(data_hrtf_r + offset, fft_in_r, n_fft * sizeof(*fft_in_r)); } } else { int I, N = ctx->inputs[1]->channels; for (k = 0; k < N / 2; k++) { - int idx = -1; - - for (j = 0; j < inlink->channels; j++) { - if (s->mapping[k] < 0) { - continue; - } - - if ((av_channel_layout_extract_channel(inlink->channel_layout, j)) == (1LL << s->mapping[k])) { - idx = k; - break; - } - } - if (idx == -1) + int idx = av_get_channel_layout_channel_index(inlink->channel_layout, + s->mapping[k]); + if (idx < 0) continue; - I = idx * 2; + I = k * 2; if (s->type == TIME_DOMAIN) { - offset = idx * FFALIGN(len, 16); + float *data_ir_l = s->data_ir[0] + idx * s->air_len; + float *data_ir_r = s->data_ir[1] + idx * s->air_len; + for (j = 0; j < len; j++) { - data_ir_l[offset + j] = ptr[len * N - j * N - N + I ] * gain_lin; - data_ir_r[offset + j] = ptr[len * N - j * N - N + I + 1] * gain_lin; + data_ir_l[j] = ptr[len * N - j * N - N + I ] * gain_lin; + data_ir_r[j] = ptr[len * N - j * N - N + I + 1] * gain_lin; } } else { - memset(fft_in_l, 0, n_fft * sizeof(*fft_in_l)); - memset(fft_in_r, 0, n_fft * sizeof(*fft_in_r)); + FFTComplex *fft_in_l = s->data_hrtf[0] + idx * n_fft; + FFTComplex *fft_in_r = s->data_hrtf[1] + idx * n_fft; - offset = idx * n_fft; for (j = 0; j < len; j++) { - fft_in_l[delay_l + j].re = ptr[j * N + I ] * gain_lin; - fft_in_r[delay_r + j].re = ptr[j * N + I + 1] * gain_lin; + fft_in_l[j].re = ptr[j * N + I ] * gain_lin; + fft_in_r[j].re = ptr[j * N + I + 1] * gain_lin; } av_fft_permute(s->fft[0], fft_in_l); av_fft_calc(s->fft[0], fft_in_l); - memcpy(data_hrtf_l + offset, fft_in_l, n_fft * sizeof(*fft_in_l)); av_fft_permute(s->fft[0], fft_in_r); av_fft_calc(s->fft[0], fft_in_r); - memcpy(data_hrtf_r + offset, fft_in_r, n_fft * sizeof(*fft_in_r)); } } } } - if (s->type == TIME_DOMAIN) { - memcpy(s->data_ir[0], data_ir_l, sizeof(float) * nb_irs * FFALIGN(ir_len, 16)); - memcpy(s->data_ir[1], data_ir_r, sizeof(float) * nb_irs * FFALIGN(ir_len, 16)); - } else { - s->data_hrtf[0] = av_calloc(n_fft * s->nb_irs, sizeof(FFTComplex)); - s->data_hrtf[1] = av_calloc(n_fft * s->nb_irs, sizeof(FFTComplex)); - if (!s->data_hrtf[0] || !s->data_hrtf[1]) { - ret = AVERROR(ENOMEM); - goto fail; - } - - memcpy(s->data_hrtf[0], data_hrtf_l, - sizeof(FFTComplex) * nb_irs * n_fft); - memcpy(s->data_hrtf[1], data_hrtf_r, - sizeof(FFTComplex) * nb_irs * n_fft); - } - s->have_hrirs = 1; fail: - - av_freep(&data_ir_l); - av_freep(&data_ir_r); - - av_freep(&data_hrtf_l); - av_freep(&data_hrtf_r); - - av_freep(&fft_in_l); - av_freep(&fft_in_r); - return ret; } @@ -622,54 +516,38 @@ static int activate(AVFilterContext *ctx) FF_FILTER_FORWARD_STATUS_BACK_ALL(ctx->outputs[0], ctx); if (!s->eof_hrirs) { - for (i = 1; i < s->nb_inputs; i++) { - AVFrame *ir = NULL; - int64_t pts; - int status; + int eof = 1; + for (i = 0; i < s->nb_hrir_inputs; i++) { + AVFilterLink *input = ctx->inputs[i + 1]; - if (s->in[i].eof) + if (s->hrir_in[i].eof) continue; - if ((ret = ff_inlink_consume_frame(ctx->inputs[i], &ir)) > 0) { - ret = read_ir(ctx->inputs[i], i, ir); - if (ret < 0) - return ret; - } - if (ret < 0) + if ((ret = check_ir(input, i)) < 0) return ret; - if (!s->in[i].eof) { - if (ff_inlink_acknowledge_status(ctx->inputs[i], &status, &pts)) { - if (status == AVERROR_EOF) { - s->in[i].eof = 1; - } + if (ff_outlink_get_status(input) == AVERROR_EOF) { + if (!ff_inlink_queued_samples(input)) { + av_log(ctx, AV_LOG_ERROR, "No samples provided for " + "HRIR stream %d.\n", i); + return AVERROR_INVALIDDATA; } + s->hrir_in[i].eof = 1; + } else { + if (ff_outlink_frame_wanted(ctx->outputs[0])) + ff_inlink_request_frame(input); + eof = 0; } } - - for (i = 1; i < s->nb_inputs; i++) { - if (!s->in[i].eof) - break; - } - - if (i != s->nb_inputs) { - if (ff_outlink_frame_wanted(ctx->outputs[0])) { - for (i = 1; i < s->nb_inputs; i++) { - if (!s->in[i].eof) - ff_inlink_request_frame(ctx->inputs[i]); - } - } + if (!eof) return 0; - } else { - s->eof_hrirs = 1; - } - } + s->eof_hrirs = 1; - if (!s->have_hrirs && s->eof_hrirs) { ret = convert_coeffs(ctx, inlink); if (ret < 0) return ret; - } + } else if (!s->have_hrirs) + return AVERROR_EOF; if ((ret = ff_inlink_consume_samples(ctx->inputs[0], s->size, s->size, &in)) > 0) { ret = headphone_frame(s, in, outlink); @@ -707,33 +585,32 @@ static int query_formats(AVFilterContext *ctx) if (!layouts) return AVERROR(ENOMEM); - ret = ff_channel_layouts_ref(layouts, &ctx->inputs[0]->out_channel_layouts); + ret = ff_channel_layouts_ref(layouts, &ctx->inputs[0]->outcfg.channel_layouts); if (ret) return ret; ret = ff_add_channel_layout(&stereo_layout, AV_CH_LAYOUT_STEREO); + if (ret) + return ret; + ret = ff_channel_layouts_ref(stereo_layout, &ctx->outputs[0]->incfg.channel_layouts); if (ret) return ret; if (s->hrir_fmt == HRIR_MULTI) { hrir_layouts = ff_all_channel_counts(); if (!hrir_layouts) - ret = AVERROR(ENOMEM); - ret = ff_channel_layouts_ref(hrir_layouts, &ctx->inputs[1]->out_channel_layouts); + return AVERROR(ENOMEM); + ret = ff_channel_layouts_ref(hrir_layouts, &ctx->inputs[1]->outcfg.channel_layouts); if (ret) return ret; } else { - for (i = 1; i < s->nb_inputs; i++) { - ret = ff_channel_layouts_ref(stereo_layout, &ctx->inputs[i]->out_channel_layouts); + for (i = 1; i <= s->nb_hrir_inputs; i++) { + ret = ff_channel_layouts_ref(stereo_layout, &ctx->inputs[i]->outcfg.channel_layouts); if (ret) return ret; } } - ret = ff_channel_layouts_ref(stereo_layout, &ctx->outputs[0]->in_channel_layouts); - if (ret) - return ret; - formats = ff_all_samplerates(); if (!formats) return AVERROR(ENOMEM); @@ -750,6 +627,8 @@ static int config_input(AVFilterLink *inlink) return AVERROR(EINVAL); } + s->lfe_channel = av_get_channel_layout_channel_index(inlink->channel_layout, + AV_CH_LOW_FREQUENCY); return 0; } @@ -773,27 +652,27 @@ static av_cold int init(AVFilterContext *ctx) parse_map(ctx); - s->in = av_calloc(s->nb_inputs, sizeof(*s->in)); - if (!s->in) - return AVERROR(ENOMEM); - - for (i = 1; i < s->nb_inputs; i++) { - char *name = av_asprintf("hrir%d", i - 1); + for (i = 0; i < s->nb_hrir_inputs; i++) { + char *name = av_asprintf("hrir%d", i); AVFilterPad pad = { .name = name, .type = AVMEDIA_TYPE_AUDIO, }; if (!name) return AVERROR(ENOMEM); - if ((ret = ff_insert_inpad(ctx, i, &pad)) < 0) { + if ((ret = ff_insert_inpad(ctx, i + 1, &pad)) < 0) { av_freep(&pad.name); return ret; } } - s->fdsp = avpriv_float_dsp_alloc(0); - if (!s->fdsp) - return AVERROR(ENOMEM); + if (s->type == TIME_DOMAIN) { + AVFloatDSPContext *fdsp = avpriv_float_dsp_alloc(0); + if (!fdsp) + return AVERROR(ENOMEM); + s->scalarproduct_float = fdsp->scalarproduct_float; + av_free(fdsp); + } return 0; } @@ -803,7 +682,6 @@ static int config_output(AVFilterLink *outlink) AVFilterContext *ctx = outlink->src; HeadphoneContext *s = ctx->priv; AVFilterLink *inlink = ctx->inputs[0]; - int i; if (s->hrir_fmt == HRIR_MULTI) { AVFilterLink *hrir_link = ctx->inputs[1]; @@ -814,12 +692,7 @@ static int config_output(AVFilterLink *outlink) } } - for (i = 0; i < s->nb_inputs; i++) { - s->in[i].fifo = av_audio_fifo_alloc(ctx->inputs[i]->format, ctx->inputs[i]->channels, 1024); - if (!s->in[i].fifo) - return AVERROR(ENOMEM); - } - s->gain_lfe = expf((s->gain - 3 * inlink->channels - 6 + s->lfe_gain) / 20 * M_LN10); + s->gain_lfe = expf((s->gain - 3 * inlink->channels + s->lfe_gain) / 20 * M_LN10); return 0; } @@ -827,14 +700,11 @@ static int config_output(AVFilterLink *outlink) static av_cold void uninit(AVFilterContext *ctx) { HeadphoneContext *s = ctx->priv; - int i; av_fft_end(s->ifft[0]); av_fft_end(s->ifft[1]); av_fft_end(s->fft[0]); av_fft_end(s->fft[1]); - av_freep(&s->delay[0]); - av_freep(&s->delay[1]); av_freep(&s->data_ir[0]); av_freep(&s->data_ir[1]); av_freep(&s->ringbuffer[0]); @@ -843,17 +713,13 @@ static av_cold void uninit(AVFilterContext *ctx) av_freep(&s->temp_src[1]); av_freep(&s->temp_fft[0]); av_freep(&s->temp_fft[1]); + av_freep(&s->temp_afft[0]); + av_freep(&s->temp_afft[1]); av_freep(&s->data_hrtf[0]); av_freep(&s->data_hrtf[1]); - av_freep(&s->fdsp); - for (i = 0; i < s->nb_inputs; i++) { - av_frame_free(&s->in[i].frame); - av_audio_fifo_free(s->in[i].fifo); - if (ctx->input_pads && i) - av_freep(&ctx->input_pads[i].name); - } - av_freep(&s->in); + for (unsigned i = 1; i < ctx->nb_inputs; i++) + av_freep(&ctx->input_pads[i].name); } #define OFFSET(x) offsetof(HeadphoneContext, x)