int ir_len;
int air_len;
- int mapping[64];
-
int nb_inputs;
int nb_irs;
int delay_r;
int eof;
} *in;
+ 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;
+ char *arg, *tokenizer, *p;
+ uint64_t used_channels = 0;
s->lfe_channel = -1;
s->nb_inputs = 1;
- for (i = 0; i < 64; i++) {
- s->mapping[i] = -1;
- }
-
+ 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;
+ }
+ if (used_channels & out_channel) {
+ av_log(ctx, AV_LOG_WARNING, "Ignoring duplicate channel '%s'.\n", arg);
continue;
}
- s->mapping[s->nb_irs] = out_ch_id;
+ used_channels |= out_channel;
+ if (out_channel == AV_CH_LOW_FREQUENCY)
+ s->lfe_channel = s->nb_irs;
+ s->mapping[s->nb_irs] = out_channel;
s->nb_irs++;
}
s->nb_inputs = 2;
else
s->nb_inputs = s->nb_irs + 1;
-
- av_free(args);
}
typedef struct ThreadData {
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;
int i, j, k;
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));
goto fail;
}
- av_fft_end(s->fft[0]);
- av_fft_end(s->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);
- av_fft_end(s->ifft[0]);
- av_fft_end(s->ifft[1]);
s->ifft[0] = av_fft_init(av_log2(s->n_fft), 1);
s->ifft[1] = av_fft_init(av_log2(s->n_fft), 1);
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])) {
+ if ((av_channel_layout_extract_channel(inlink->channel_layout, j)) == s->mapping[i]) {
idx = i;
break;
}
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])) {
+ if ((av_channel_layout_extract_channel(inlink->channel_layout, j)) == s->mapping[k]) {
idx = k;
break;
}
FF_FILTER_FORWARD_STATUS_BACK_ALL(ctx->outputs[0], ctx);
if (!s->eof_hrirs) {
+ int eof = 1;
for (i = 1; i < s->nb_inputs; i++) {
if (s->in[i].eof)
continue;
if ((ret = check_ir(ctx->inputs[i], i)) < 0)
return ret;
- if (!s->in[i].eof) {
- if (ff_outlink_get_status(ctx->inputs[i]) == AVERROR_EOF)
+ if (ff_outlink_get_status(ctx->inputs[i]) == AVERROR_EOF) {
+ if (!ff_inlink_queued_samples(ctx->inputs[i])) {
+ av_log(ctx, AV_LOG_ERROR, "No samples provided for "
+ "HRIR stream %d.\n", i - 1);
+ return AVERROR_INVALIDDATA;
+ }
s->in[i].eof = 1;
+ } else {
+ if (ff_outlink_frame_wanted(ctx->outputs[0]))
+ ff_inlink_request_frame(ctx->inputs[i]);
+ 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);
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;
hrir_layouts = ff_all_channel_counts();
if (!hrir_layouts)
return AVERROR(ENOMEM);
- ret = ff_channel_layouts_ref(hrir_layouts, &ctx->inputs[1]->out_channel_layouts);
+ 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);
+ 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);