+static int parse_channel_name(char **arg, int *rchannel)
+{
+ char buf[8];
+ int len, i, channel_id = 0;
+ int64_t layout, layout0;
+
+ /* try to parse a channel name, e.g. "FL" */
+ if (sscanf(*arg, "%7[A-Z]%n", buf, &len)) {
+ layout0 = layout = av_get_channel_layout(buf);
+ /* channel_id <- first set bit in layout */
+ for (i = 32; i > 0; i >>= 1) {
+ if (layout >= (int64_t)1 << i) {
+ channel_id += i;
+ layout >>= i;
+ }
+ }
+ /* reject layouts that are not a single channel */
+ if (channel_id >= 64 || layout0 != (int64_t)1 << channel_id)
+ return AVERROR(EINVAL);
+ *rchannel = channel_id;
+ *arg += len;
+ return 0;
+ }
+ return AVERROR(EINVAL);
+}
+
+static void parse_speaker_pos(AVFilterContext *ctx, int64_t in_channel_layout)
+{
+ SOFAlizerContext *s = ctx->priv;
+ char *arg, *tokenizer, *p, *args = av_strdup(s->speakers_pos);
+
+ if (!args)
+ return;
+ p = args;
+
+ while ((arg = av_strtok(p, "|", &tokenizer))) {
+ float azim, elev;
+ int out_ch_id;
+
+ p = NULL;
+ if (parse_channel_name(&arg, &out_ch_id))
+ continue;
+ if (sscanf(arg, "%f %f", &azim, &elev) == 2) {
+ s->vspkrpos[out_ch_id].set = 1;
+ s->vspkrpos[out_ch_id].azim = azim;
+ s->vspkrpos[out_ch_id].elev = elev;
+ } else if (sscanf(arg, "%f", &azim) == 1) {
+ s->vspkrpos[out_ch_id].set = 1;
+ s->vspkrpos[out_ch_id].azim = azim;
+ s->vspkrpos[out_ch_id].elev = 0;
+ }
+ }
+
+ av_free(args);
+}
+