avfiltergraph.c 24.8 KB
Newer Older
1
/*
2
 * filter graphs
3 4
 * Copyright (c) 2008 Vitor Sessak
 * Copyright (c) 2007 Bobby Bingham
5
 *
6
 * This file is part of Libav.
7
 *
8
 * Libav is free software; you can redistribute it and/or
9 10 11 12
 * 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.
 *
13
 * Libav is distributed in the hope that it will be useful,
14 15 16 17 18
 * 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
19
 * License along with Libav; if not, write to the Free Software
20 21 22
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

23 24 25
#include <ctype.h>
#include <string.h>

26 27
#include "avfilter.h"
#include "avfiltergraph.h"
28
#include "formats.h"
29
#include "internal.h"
30

31
#include "libavutil/audioconvert.h"
32
#include "libavutil/avassert.h"
33
#include "libavutil/common.h"
34 35 36 37 38 39 40 41
#include "libavutil/log.h"

static const AVClass filtergraph_class = {
    .class_name = "AVFilterGraph",
    .item_name  = av_default_item_name,
    .version    = LIBAVUTIL_VERSION_INT,
};

42 43
AVFilterGraph *avfilter_graph_alloc(void)
{
44 45 46 47 48
    AVFilterGraph *ret = av_mallocz(sizeof(AVFilterGraph));
    if (!ret)
        return NULL;
    ret->av_class = &filtergraph_class;
    return ret;
49 50
}

51
void avfilter_graph_free(AVFilterGraph **graph)
Vitor Sessak's avatar
Vitor Sessak committed
52
{
53
    if (!*graph)
54
        return;
55 56 57 58 59
    for (; (*graph)->filter_count > 0; (*graph)->filter_count--)
        avfilter_free((*graph)->filters[(*graph)->filter_count - 1]);
    av_freep(&(*graph)->scale_sws_opts);
    av_freep(&(*graph)->filters);
    av_freep(graph);
60 61
}

Vitor Sessak's avatar
Vitor Sessak committed
62
int avfilter_graph_add_filter(AVFilterGraph *graph, AVFilterContext *filter)
63
{
64 65 66
    AVFilterContext **filters = av_realloc(graph->filters,
                                           sizeof(AVFilterContext*) * (graph->filter_count+1));
    if (!filters)
67
        return AVERROR(ENOMEM);
Vitor Sessak's avatar
Vitor Sessak committed
68

69 70
    graph->filters = filters;
    graph->filters[graph->filter_count++] = filter;
Vitor Sessak's avatar
Vitor Sessak committed
71 72

    return 0;
73 74
}

75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
int avfilter_graph_create_filter(AVFilterContext **filt_ctx, AVFilter *filt,
                                 const char *name, const char *args, void *opaque,
                                 AVFilterGraph *graph_ctx)
{
    int ret;

    if ((ret = avfilter_open(filt_ctx, filt, name)) < 0)
        goto fail;
    if ((ret = avfilter_init_filter(*filt_ctx, args, opaque)) < 0)
        goto fail;
    if ((ret = avfilter_graph_add_filter(graph_ctx, *filt_ctx)) < 0)
        goto fail;
    return 0;

fail:
    if (*filt_ctx)
        avfilter_free(*filt_ctx);
    *filt_ctx = NULL;
    return ret;
}

96 97 98 99 100 101 102 103 104
/**
 * Check for the validity of graph.
 *
 * A graph is considered valid if all its input and output pads are
 * connected.
 *
 * @return 0 in case of success, a negative value otherwise
 */
static int graph_check_validity(AVFilterGraph *graph, AVClass *log_ctx)
105 106 107 108
{
    AVFilterContext *filt;
    int i, j;

109
    for (i = 0; i < graph->filter_count; i++) {
110 111
        filt = graph->filters[i];

112
        for (j = 0; j < filt->nb_inputs; j++) {
113 114 115 116
            if (!filt->inputs[j] || !filt->inputs[j]->src) {
                av_log(log_ctx, AV_LOG_ERROR,
                       "Input pad \"%s\" for the filter \"%s\" of type \"%s\" not connected to any source\n",
                       filt->input_pads[j].name, filt->name, filt->filter->name);
117
                return AVERROR(EINVAL);
118 119 120
            }
        }

121
        for (j = 0; j < filt->nb_outputs; j++) {
122 123 124 125
            if (!filt->outputs[j] || !filt->outputs[j]->dst) {
                av_log(log_ctx, AV_LOG_ERROR,
                       "Output pad \"%s\" for the filter \"%s\" of type \"%s\" not connected to any destination\n",
                       filt->output_pads[j].name, filt->name, filt->filter->name);
126
                return AVERROR(EINVAL);
127 128 129 130 131 132 133
            }
        }
    }

    return 0;
}

134 135 136 137 138 139
/**
 * Configure all the links of graphctx.
 *
 * @return 0 in case of success, a negative value otherwise
 */
static int graph_config_links(AVFilterGraph *graph, AVClass *log_ctx)
140 141 142 143 144 145 146
{
    AVFilterContext *filt;
    int i, ret;

    for (i=0; i < graph->filter_count; i++) {
        filt = graph->filters[i];

147
        if (!filt->nb_outputs) {
148 149 150 151 152 153 154 155
            if ((ret = avfilter_config_links(filt)))
                return ret;
        }
    }

    return 0;
}

156
AVFilterContext *avfilter_graph_get_filter(AVFilterGraph *graph, char *name)
157 158 159
{
    int i;

160 161
    for (i = 0; i < graph->filter_count; i++)
        if (graph->filters[i]->name && !strcmp(name, graph->filters[i]->name))
162 163 164 165 166
            return graph->filters[i];

    return NULL;
}

167
static int query_formats(AVFilterGraph *graph, AVClass *log_ctx)
Vitor Sessak's avatar
Vitor Sessak committed
168
{
169
    int i, j, ret;
170
    int scaler_count = 0, resampler_count = 0;
Vitor Sessak's avatar
Vitor Sessak committed
171

172
    /* ask all the sub-filters for their supported media formats */
173 174
    for (i = 0; i < graph->filter_count; i++) {
        if (graph->filters[i]->filter->query_formats)
Vitor Sessak's avatar
Vitor Sessak committed
175 176
            graph->filters[i]->filter->query_formats(graph->filters[i]);
        else
177
            ff_default_query_formats(graph->filters[i]);
Vitor Sessak's avatar
Vitor Sessak committed
178 179 180
    }

    /* go through and merge as many format lists as possible */
181
    for (i = 0; i < graph->filter_count; i++) {
Vitor Sessak's avatar
Vitor Sessak committed
182 183
        AVFilterContext *filter = graph->filters[i];

184
        for (j = 0; j < filter->nb_inputs; j++) {
Vitor Sessak's avatar
Vitor Sessak committed
185
            AVFilterLink *link = filter->inputs[j];
186 187 188 189 190 191
            int convert_needed = 0;

            if (!link)
                continue;

            if (link->in_formats != link->out_formats &&
192
                !ff_merge_formats(link->in_formats,
193 194 195 196 197 198 199 200 201 202 203 204 205 206
                                        link->out_formats))
                convert_needed = 1;
            if (link->type == AVMEDIA_TYPE_AUDIO) {
                if (link->in_channel_layouts != link->out_channel_layouts &&
                    !ff_merge_channel_layouts(link->in_channel_layouts,
                                              link->out_channel_layouts))
                    convert_needed = 1;
                if (link->in_samplerates != link->out_samplerates &&
                    !ff_merge_samplerates(link->in_samplerates,
                                          link->out_samplerates))
                    convert_needed = 1;
            }

            if (convert_needed) {
Anton Khirnov's avatar
Anton Khirnov committed
207 208 209 210 211 212 213 214 215
                AVFilterContext *convert;
                AVFilter *filter;
                AVFilterLink *inlink, *outlink;
                char scale_args[256];
                char inst_name[30];

                /* couldn't merge format lists. auto-insert conversion filter */
                switch (link->type) {
                case AVMEDIA_TYPE_VIDEO:
216 217 218 219 220 221
                    if (!(filter = avfilter_get_by_name("scale"))) {
                        av_log(log_ctx, AV_LOG_ERROR, "'scale' filter "
                               "not present, cannot convert pixel formats.\n");
                        return AVERROR(EINVAL);
                    }

Anton Khirnov's avatar
Anton Khirnov committed
222 223 224
                    snprintf(inst_name, sizeof(inst_name), "auto-inserted scaler %d",
                             scaler_count++);
                    snprintf(scale_args, sizeof(scale_args), "0:0:%s", graph->scale_sws_opts);
225
                    if ((ret = avfilter_graph_create_filter(&convert, filter,
Anton Khirnov's avatar
Anton Khirnov committed
226 227 228 229 230 231 232 233
                                                            inst_name, scale_args, NULL,
                                                            graph)) < 0)
                        return ret;
                    break;
                case AVMEDIA_TYPE_AUDIO:
                    if (!(filter = avfilter_get_by_name("resample"))) {
                        av_log(log_ctx, AV_LOG_ERROR, "'resample' filter "
                               "not present, cannot convert audio formats.\n");
234 235 236
                        return AVERROR(EINVAL);
                    }

Anton Khirnov's avatar
Anton Khirnov committed
237 238
                    snprintf(inst_name, sizeof(inst_name), "auto-inserted resampler %d",
                             resampler_count++);
239
                    if ((ret = avfilter_graph_create_filter(&convert, filter,
Anton Khirnov's avatar
Anton Khirnov committed
240
                                                            inst_name, NULL, NULL, graph)) < 0)
241
                        return ret;
Anton Khirnov's avatar
Anton Khirnov committed
242 243 244 245 246 247 248 249 250 251 252
                    break;
                default:
                    return AVERROR(EINVAL);
                }

                if ((ret = avfilter_insert_filter(link, convert, 0, 0)) < 0)
                    return ret;

                convert->filter->query_formats(convert);
                inlink  = convert->inputs[0];
                outlink = convert->outputs[0];
253 254
                if (!ff_merge_formats( inlink->in_formats,  inlink->out_formats) ||
                    !ff_merge_formats(outlink->in_formats, outlink->out_formats))
Anton Khirnov's avatar
Anton Khirnov committed
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274
                    ret |= AVERROR(ENOSYS);
                if (inlink->type == AVMEDIA_TYPE_AUDIO &&
                    (!ff_merge_samplerates(inlink->in_samplerates,
                                           inlink->out_samplerates) ||
                     !ff_merge_channel_layouts(inlink->in_channel_layouts,
                                               inlink->out_channel_layouts)))
                    ret |= AVERROR(ENOSYS);
                if (outlink->type == AVMEDIA_TYPE_AUDIO &&
                    (!ff_merge_samplerates(outlink->in_samplerates,
                                           outlink->out_samplerates) ||
                     !ff_merge_channel_layouts(outlink->in_channel_layouts,
                                               outlink->out_channel_layouts)))
                    ret |= AVERROR(ENOSYS);

                if (ret < 0) {
                    av_log(log_ctx, AV_LOG_ERROR,
                           "Impossible to convert between the formats supported by the filter "
                           "'%s' and the filter '%s'\n", link->src->name, link->dst->name);
                    return ret;
                }
Vitor Sessak's avatar
Vitor Sessak committed
275 276 277 278 279 280 281
            }
        }
    }

    return 0;
}

282
static int pick_format(AVFilterLink *link)
Vitor Sessak's avatar
Vitor Sessak committed
283
{
284
    if (!link || !link->in_formats)
285
        return 0;
Vitor Sessak's avatar
Vitor Sessak committed
286 287 288 289

    link->in_formats->format_count = 1;
    link->format = link->in_formats->formats[0];

290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309
    if (link->type == AVMEDIA_TYPE_AUDIO) {
        if (!link->in_samplerates->format_count) {
            av_log(link->src, AV_LOG_ERROR, "Cannot select sample rate for"
                   " the link between filters %s and %s.\n", link->src->name,
                   link->dst->name);
            return AVERROR(EINVAL);
        }
        link->in_samplerates->format_count = 1;
        link->sample_rate = link->in_samplerates->formats[0];

        if (!link->in_channel_layouts->nb_channel_layouts) {
            av_log(link->src, AV_LOG_ERROR, "Cannot select channel layout for"
                   "the link between filters %s and %s.\n", link->src->name,
                   link->dst->name);
            return AVERROR(EINVAL);
        }
        link->in_channel_layouts->nb_channel_layouts = 1;
        link->channel_layout = link->in_channel_layouts->channel_layouts[0];
    }

310 311 312 313
    ff_formats_unref(&link->in_formats);
    ff_formats_unref(&link->out_formats);
    ff_formats_unref(&link->in_samplerates);
    ff_formats_unref(&link->out_samplerates);
314 315 316 317
    ff_channel_layouts_unref(&link->in_channel_layouts);
    ff_channel_layouts_unref(&link->out_channel_layouts);

    return 0;
Vitor Sessak's avatar
Vitor Sessak committed
318 319
}

320 321
#define REDUCE_FORMATS(fmt_type, list_type, list, var, nb, add_format) \
do {                                                                   \
322
    for (i = 0; i < filter->nb_inputs; i++) {                          \
323 324 325 326 327 328 329
        AVFilterLink *link = filter->inputs[i];                        \
        fmt_type fmt;                                                  \
                                                                       \
        if (!link->out_ ## list || link->out_ ## list->nb != 1)        \
            continue;                                                  \
        fmt = link->out_ ## list->var[0];                              \
                                                                       \
330
        for (j = 0; j < filter->nb_outputs; j++) {                     \
331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354
            AVFilterLink *out_link = filter->outputs[j];               \
            list_type *fmts;                                           \
                                                                       \
            if (link->type != out_link->type ||                        \
                out_link->in_ ## list->nb == 1)                        \
                continue;                                              \
            fmts = out_link->in_ ## list;                              \
                                                                       \
            if (!out_link->in_ ## list->nb) {                          \
                add_format(&out_link->in_ ##list, fmt);                \
                break;                                                 \
            }                                                          \
                                                                       \
            for (k = 0; k < out_link->in_ ## list->nb; k++)            \
                if (fmts->var[k] == fmt) {                             \
                    fmts->var[0]  = fmt;                               \
                    fmts->nb = 1;                                      \
                    ret = 1;                                           \
                    break;                                             \
                }                                                      \
        }                                                              \
    }                                                                  \
} while (0)

355 356 357 358
static int reduce_formats_on_filter(AVFilterContext *filter)
{
    int i, j, k, ret = 0;

359
    REDUCE_FORMATS(int,      AVFilterFormats,        formats,         formats,
360
                   format_count, ff_add_format);
361
    REDUCE_FORMATS(int,      AVFilterFormats,        samplerates,     formats,
362
                   format_count, ff_add_format);
363 364
    REDUCE_FORMATS(uint64_t, AVFilterChannelLayouts, channel_layouts,
                   channel_layouts, nb_channel_layouts, ff_add_channel_layout);
365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380

    return ret;
}

static void reduce_formats(AVFilterGraph *graph)
{
    int i, reduced;

    do {
        reduced = 0;

        for (i = 0; i < graph->filter_count; i++)
            reduced |= reduce_formats_on_filter(graph->filters[i]);
    } while (reduced);
}

381 382 383 384 385 386
static void swap_samplerates_on_filter(AVFilterContext *filter)
{
    AVFilterLink *link = NULL;
    int sample_rate;
    int i, j;

387
    for (i = 0; i < filter->nb_inputs; i++) {
388 389 390 391 392 393
        link = filter->inputs[i];

        if (link->type == AVMEDIA_TYPE_AUDIO &&
            link->out_samplerates->format_count == 1)
            break;
    }
394
    if (i == filter->nb_inputs)
395 396 397 398
        return;

    sample_rate = link->out_samplerates->formats[0];

399
    for (i = 0; i < filter->nb_outputs; i++) {
400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427
        AVFilterLink *outlink = filter->outputs[i];
        int best_idx, best_diff = INT_MAX;

        if (outlink->type != AVMEDIA_TYPE_AUDIO ||
            outlink->in_samplerates->format_count < 2)
            continue;

        for (j = 0; j < outlink->in_samplerates->format_count; j++) {
            int diff = abs(sample_rate - outlink->in_samplerates->formats[j]);

            if (diff < best_diff) {
                best_diff = diff;
                best_idx  = j;
            }
        }
        FFSWAP(int, outlink->in_samplerates->formats[0],
               outlink->in_samplerates->formats[best_idx]);
    }
}

static void swap_samplerates(AVFilterGraph *graph)
{
    int i;

    for (i = 0; i < graph->filter_count; i++)
        swap_samplerates_on_filter(graph->filters[i]);
}

428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461
#define CH_CENTER_PAIR (AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER)
#define CH_FRONT_PAIR  (AV_CH_FRONT_LEFT           | AV_CH_FRONT_RIGHT)
#define CH_STEREO_PAIR (AV_CH_STEREO_LEFT          | AV_CH_STEREO_RIGHT)
#define CH_WIDE_PAIR   (AV_CH_WIDE_LEFT            | AV_CH_WIDE_RIGHT)
#define CH_SIDE_PAIR   (AV_CH_SIDE_LEFT            | AV_CH_SIDE_RIGHT)
#define CH_DIRECT_PAIR (AV_CH_SURROUND_DIRECT_LEFT | AV_CH_SURROUND_DIRECT_RIGHT)
#define CH_BACK_PAIR   (AV_CH_BACK_LEFT            | AV_CH_BACK_RIGHT)

/* allowable substitutions for channel pairs when comparing layouts,
 * ordered by priority for both values */
static const uint64_t ch_subst[][2] = {
    { CH_FRONT_PAIR,      CH_CENTER_PAIR     },
    { CH_FRONT_PAIR,      CH_WIDE_PAIR       },
    { CH_FRONT_PAIR,      AV_CH_FRONT_CENTER },
    { CH_CENTER_PAIR,     CH_FRONT_PAIR      },
    { CH_CENTER_PAIR,     CH_WIDE_PAIR       },
    { CH_CENTER_PAIR,     AV_CH_FRONT_CENTER },
    { CH_WIDE_PAIR,       CH_FRONT_PAIR      },
    { CH_WIDE_PAIR,       CH_CENTER_PAIR     },
    { CH_WIDE_PAIR,       AV_CH_FRONT_CENTER },
    { AV_CH_FRONT_CENTER, CH_FRONT_PAIR      },
    { AV_CH_FRONT_CENTER, CH_CENTER_PAIR     },
    { AV_CH_FRONT_CENTER, CH_WIDE_PAIR       },
    { CH_SIDE_PAIR,       CH_DIRECT_PAIR     },
    { CH_SIDE_PAIR,       CH_BACK_PAIR       },
    { CH_SIDE_PAIR,       AV_CH_BACK_CENTER  },
    { CH_BACK_PAIR,       CH_DIRECT_PAIR     },
    { CH_BACK_PAIR,       CH_SIDE_PAIR       },
    { CH_BACK_PAIR,       AV_CH_BACK_CENTER  },
    { AV_CH_BACK_CENTER,  CH_BACK_PAIR       },
    { AV_CH_BACK_CENTER,  CH_DIRECT_PAIR     },
    { AV_CH_BACK_CENTER,  CH_SIDE_PAIR       },
};

462
static void swap_channel_layouts_on_filter(AVFilterContext *filter)
Vitor Sessak's avatar
Vitor Sessak committed
463
{
464
    AVFilterLink *link = NULL;
465
    int i, j, k;
Vitor Sessak's avatar
Vitor Sessak committed
466

467
    for (i = 0; i < filter->nb_inputs; i++) {
468 469 470 471 472 473
        link = filter->inputs[i];

        if (link->type == AVMEDIA_TYPE_AUDIO &&
            link->out_channel_layouts->nb_channel_layouts == 1)
            break;
    }
474
    if (i == filter->nb_inputs)
475 476
        return;

477
    for (i = 0; i < filter->nb_outputs; i++) {
478
        AVFilterLink *outlink = filter->outputs[i];
479
        int best_idx, best_score = INT_MIN, best_count_diff = INT_MAX;
480 481 482 483 484 485

        if (outlink->type != AVMEDIA_TYPE_AUDIO ||
            outlink->in_channel_layouts->nb_channel_layouts < 2)
            continue;

        for (j = 0; j < outlink->in_channel_layouts->nb_channel_layouts; j++) {
486
            uint64_t  in_chlayout = link->out_channel_layouts->channel_layouts[0];
487
            uint64_t out_chlayout = outlink->in_channel_layouts->channel_layouts[j];
488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506
            int  in_channels      = av_get_channel_layout_nb_channels(in_chlayout);
            int out_channels      = av_get_channel_layout_nb_channels(out_chlayout);
            int count_diff        = out_channels - in_channels;
            int matched_channels, extra_channels;
            int score = 0;

            /* channel substitution */
            for (k = 0; k < FF_ARRAY_ELEMS(ch_subst); k++) {
                uint64_t cmp0 = ch_subst[k][0];
                uint64_t cmp1 = ch_subst[k][1];
                if (( in_chlayout & cmp0) && (!(out_chlayout & cmp0)) &&
                    (out_chlayout & cmp1) && (!( in_chlayout & cmp1))) {
                    in_chlayout  &= ~cmp0;
                    out_chlayout &= ~cmp1;
                    /* add score for channel match, minus a deduction for
                       having to do the substitution */
                    score += 10 * av_get_channel_layout_nb_channels(cmp1) - 2;
                }
            }
507

508 509 510 511 512 513 514 515 516 517 518 519 520 521 522
            /* no penalty for LFE channel mismatch */
            if ( (in_chlayout & AV_CH_LOW_FREQUENCY) &&
                (out_chlayout & AV_CH_LOW_FREQUENCY))
                score += 10;
            in_chlayout  &= ~AV_CH_LOW_FREQUENCY;
            out_chlayout &= ~AV_CH_LOW_FREQUENCY;

            matched_channels = av_get_channel_layout_nb_channels(in_chlayout &
                                                                 out_chlayout);
            extra_channels   = av_get_channel_layout_nb_channels(out_chlayout &
                                                                 (~in_chlayout));
            score += 10 * matched_channels - 5 * extra_channels;

            if (score > best_score ||
                (count_diff < best_count_diff && score == best_score)) {
523 524
                best_score = score;
                best_idx   = j;
525
                best_count_diff = count_diff;
526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541
            }
        }
        FFSWAP(uint64_t, outlink->in_channel_layouts->channel_layouts[0],
               outlink->in_channel_layouts->channel_layouts[best_idx]);
    }

}

static void swap_channel_layouts(AVFilterGraph *graph)
{
    int i;

    for (i = 0; i < graph->filter_count; i++)
        swap_channel_layouts_on_filter(graph->filters[i]);
}

542 543 544 545 546 547
static void swap_sample_fmts_on_filter(AVFilterContext *filter)
{
    AVFilterLink *link = NULL;
    int format, bps;
    int i, j;

548
    for (i = 0; i < filter->nb_inputs; i++) {
549 550 551 552 553 554
        link = filter->inputs[i];

        if (link->type == AVMEDIA_TYPE_AUDIO &&
            link->out_formats->format_count == 1)
            break;
    }
555
    if (i == filter->nb_inputs)
556 557 558 559 560
        return;

    format = link->out_formats->formats[0];
    bps    = av_get_bytes_per_sample(format);

561
    for (i = 0; i < filter->nb_outputs; i++) {
562
        AVFilterLink *outlink = filter->outputs[i];
563
        int best_idx = -1, best_score = INT_MIN;
564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595

        if (outlink->type != AVMEDIA_TYPE_AUDIO ||
            outlink->in_formats->format_count < 2)
            continue;

        for (j = 0; j < outlink->in_formats->format_count; j++) {
            int out_format = outlink->in_formats->formats[j];
            int out_bps    = av_get_bytes_per_sample(out_format);
            int score;

            if (av_get_packed_sample_fmt(out_format) == format ||
                av_get_planar_sample_fmt(out_format) == format) {
                best_idx   = j;
                break;
            }

            /* for s32 and float prefer double to prevent loss of information */
            if (bps == 4 && out_bps == 8) {
                best_idx = j;
                break;
            }

            /* prefer closest higher or equal bps */
            score = -abs(out_bps - bps);
            if (out_bps >= bps)
                score += INT_MAX/2;

            if (score > best_score) {
                best_score = score;
                best_idx   = j;
            }
        }
596
        av_assert0(best_idx >= 0);
597 598 599 600 601 602 603 604 605 606 607 608 609 610
        FFSWAP(int, outlink->in_formats->formats[0],
               outlink->in_formats->formats[best_idx]);
    }
}

static void swap_sample_fmts(AVFilterGraph *graph)
{
    int i;

    for (i = 0; i < graph->filter_count; i++)
        swap_sample_fmts_on_filter(graph->filters[i]);

}

611 612 613 614
static int pick_formats(AVFilterGraph *graph)
{
    int i, j, ret;

615
    for (i = 0; i < graph->filter_count; i++) {
Vitor Sessak's avatar
Vitor Sessak committed
616 617
        AVFilterContext *filter = graph->filters[i];

618
        for (j = 0; j < filter->nb_inputs; j++)
619 620
            if ((ret = pick_format(filter->inputs[j])) < 0)
                return ret;
621
        for (j = 0; j < filter->nb_outputs; j++)
622 623
            if ((ret = pick_format(filter->outputs[j])) < 0)
                return ret;
Vitor Sessak's avatar
Vitor Sessak committed
624
    }
625
    return 0;
Vitor Sessak's avatar
Vitor Sessak committed
626 627
}

628 629 630 631
/**
 * Configure the formats of all the links in the graph.
 */
static int graph_config_formats(AVFilterGraph *graph, AVClass *log_ctx)
Vitor Sessak's avatar
Vitor Sessak committed
632
{
633 634
    int ret;

635
    /* find supported formats from sub-filters, and merge along links */
636 637
    if ((ret = query_formats(graph, log_ctx)) < 0)
        return ret;
Vitor Sessak's avatar
Vitor Sessak committed
638 639

    /* Once everything is merged, it's possible that we'll still have
640 641 642 643
     * multiple valid media format choices. We try to minimize the amount
     * of format conversion inside filters */
    reduce_formats(graph);

644
    /* for audio filters, ensure the best format, sample rate and channel layout
645
     * is selected */
646
    swap_sample_fmts(graph);
647 648 649 650 651
    swap_samplerates(graph);
    swap_channel_layouts(graph);

    if ((ret = pick_formats(graph)) < 0)
        return ret;
Vitor Sessak's avatar
Vitor Sessak committed
652 653 654 655

    return 0;
}

656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693
static int graph_insert_fifos(AVFilterGraph *graph, AVClass *log_ctx)
{
    AVFilterContext *f;
    int i, j, ret;
    int fifo_count = 0;

    for (i = 0; i < graph->filter_count; i++) {
        f = graph->filters[i];

        for (j = 0; j < f->nb_inputs; j++) {
            AVFilterLink *link = f->inputs[j];
            AVFilterContext *fifo_ctx;
            AVFilter *fifo;
            char name[32];

            if (!link->dstpad->needs_fifo)
                continue;

            fifo = f->inputs[j]->type == AVMEDIA_TYPE_VIDEO ?
                   avfilter_get_by_name("fifo") :
                   avfilter_get_by_name("afifo");

            snprintf(name, sizeof(name), "auto-inserted fifo %d", fifo_count++);

            ret = avfilter_graph_create_filter(&fifo_ctx, fifo, name, NULL,
                                               NULL, graph);
            if (ret < 0)
                return ret;

            ret = avfilter_insert_filter(link, fifo_ctx, 0, 0);
            if (ret < 0)
                return ret;
        }
    }

    return 0;
}

694
int avfilter_graph_config(AVFilterGraph *graphctx, void *log_ctx)
695 696 697
{
    int ret;

698
    if ((ret = graph_check_validity(graphctx, log_ctx)))
699
        return ret;
700 701
    if ((ret = graph_insert_fifos(graphctx, log_ctx)) < 0)
        return ret;
702
    if ((ret = graph_config_formats(graphctx, log_ctx)))
703
        return ret;
704
    if ((ret = graph_config_links(graphctx, log_ctx)))
705 706 707 708
        return ret;

    return 0;
}