* qatar/master: (26 commits) fate: use diff -b in oneline comparison Add missing version bumps and APIchanges/Changelog entries. lavfi: move buffer management function to a separate file. lavfi: move formats-related functions from default.c to formats.c lavfi: move video-related functions to a separate file. fate: make smjpeg a demux test fate: separate sierra-vmd audio and video tests fate: separate smacker audio and video tests libmp3lame: set supported channel layouts. avconv: automatically insert asyncts when -async is used. avconv: add support for audio filters. lavfi: add asyncts filter. lavfi: add aformat filter lavfi: add an audio buffer sink. lavfi: add an audio buffer source. buffersrc: add av_buffersrc_write_frame(). buffersrc: fix invalid read in uninit if the fifo hasn't been allocated lavfi: rename vsrc_buffer.c to buffersrc.c avfiltergraph: reindent lavfi: add channel layout/sample rate negotiation. ... Conflicts: Changelog doc/APIchanges doc/filters.texi ffmpeg.c ffprobe.c libavcodec/libmp3lame.c libavfilter/Makefile libavfilter/af_aformat.c libavfilter/allfilters.c libavfilter/avfilter.c libavfilter/avfilter.h libavfilter/avfiltergraph.c libavfilter/buffersrc.c libavfilter/defaults.c libavfilter/formats.c libavfilter/src_buffer.c libavfilter/version.h libavfilter/vf_yadif.c libavfilter/vsrc_buffer.c libavfilter/vsrc_buffer.h libavutil/avutil.h tests/fate/audio.mak tests/fate/demux.mak tests/fate/video.mak
Showing the changes to libavfilter/avfiltergraph.c (1 of 52 files). Show all
Unified · Split
| @@ -28,8 +28,10 @@ · 27 unmodified lines | ||
| 28 | 28 | #include "libavutil/pixdesc.h" |
| 29 | 29 | #include "avfilter.h" |
| 30 | 30 | #include "avfiltergraph.h" |
| 31 | +#include "formats.h" | |
| 31 | 32 | #include "internal.h" |
| 32 | 33 | |
| 34 | +#include "libavutil/audioconvert.h" | |
| 33 | 35 | #include "libavutil/log.h" |
| 34 | 36 | |
| 35 | 37 | static const AVClass filtergraph_class = { |
| @@ -198,10 +200,10 @@ static int insert_conv_filter(AVFilterGraph *graph, AVFilterLink *link, · 162 unmodified lines | ||
| 198 | 200 | |
| 199 | 201 | if (link->type == AVMEDIA_TYPE_AUDIO && |
| 200 | 202 | (((link = filt_ctx-> inputs[0]) && |
| 201 | − (!avfilter_merge_formats(link->in_chlayouts, link->out_chlayouts) || | |
| 203 | + (!ff_merge_channel_layouts(link->in_channel_layouts, link->out_channel_layouts) || | |
| 202 | 204 | !avfilter_merge_formats(link->in_packing, link->out_packing))) || |
| 203 | 205 | ((link = filt_ctx->outputs[0]) && |
| 204 | − (!avfilter_merge_formats(link->in_chlayouts, link->out_chlayouts) || | |
| 206 | + (!ff_merge_channel_layouts(link->in_channel_layouts, link->out_channel_layouts) || | |
| 205 | 207 | !avfilter_merge_formats(link->in_packing, link->out_packing)))) |
| 206 | 208 | ) { |
| 207 | 209 | av_log(NULL, AV_LOG_ERROR, |
| @@ -217,7 +219,10 @@ static int query_formats(AVFilterGraph *graph, AVClass *log_ctx) · 9 unmodified lines | ||
| 217 | 219 | { |
| 218 | 220 | int i, j, ret; |
| 219 | 221 | char filt_args[128]; |
| 220 | − AVFilterFormats *formats, *chlayouts, *packing; | |
| 222 | + AVFilterFormats *formats, *packing; | |
| 223 | + AVFilterChannelLayouts *chlayouts; | |
| 224 | + AVFilterFormats *samplerates; | |
| 225 | + int scaler_count = 0, resampler_count = 0; | |
| 221 | 226 | |
| 222 | 227 | /* ask all the sub-filters for their supported media formats */ |
| 223 | 228 | for (i = 0; i < graph->filter_count; i++) { |
| @@ -233,6 +238,7 @@ static int query_formats(AVFilterGraph *graph, AVClass *log_ctx) · 9 unmodified lines | ||
| 233 | 238 | |
| 234 | 239 | for (j = 0; j < filter->input_count; j++) { |
| 235 | 240 | AVFilterLink *link = filter->inputs[j]; |
| 241 | +#if 0 | |
| 236 | 242 | if (!link) continue; |
| 237 | 243 | |
| 238 | 244 | if (!link->in_formats || !link->out_formats) |
| @@ -248,7 +254,7 @@ static int query_formats(AVFilterGraph *graph, AVClass *log_ctx) · 9 unmodified lines | ||
| 248 | 254 | return ret; |
| 249 | 255 | } |
| 250 | 256 | else if (link->type == AVMEDIA_TYPE_AUDIO) { |
| 251 | − if (!link->in_chlayouts || !link->out_chlayouts || | |
| 257 | + if (!link->in_channel_layouts || !link->out_channel_layouts || | |
| 252 | 258 | !link->in_packing || !link->out_packing) |
| 253 | 259 | return AVERROR(EINVAL); |
| 254 | 260 | |
| @@ -256,11 +262,100 @@ static int query_formats(AVFilterGraph *graph, AVClass *log_ctx) · 1 unmodified line | ||
| 256 | 262 | * three categories, aconvert will use a common format |
| 257 | 263 | * whenever possible. */ |
| 258 | 264 | formats = avfilter_merge_formats(link->in_formats, link->out_formats); |
| 259 | − chlayouts = avfilter_merge_formats(link->in_chlayouts, link->out_chlayouts); | |
| 265 | + chlayouts = ff_merge_channel_layouts(link->in_channel_layouts , link->out_channel_layouts); | |
| 266 | + samplerates = ff_merge_samplerates (link->in_samplerates, link->out_samplerates); | |
| 260 | 267 | packing = avfilter_merge_formats(link->in_packing, link->out_packing); |
| 261 | − if (!formats || !chlayouts || !packing) | |
| 268 | + | |
| 269 | + if (!formats || !chlayouts || !packing || !samplerates) | |
| 262 | 270 | if (ret = insert_conv_filter(graph, link, "aconvert", NULL)) |
| 263 | 271 | return ret; |
| 272 | +#else | |
| 273 | + int convert_needed = 0; | |
| 274 | + | |
| 275 | + if (!link) | |
| 276 | + continue; | |
| 277 | + | |
| 278 | + if (link->in_formats != link->out_formats && | |
| 279 | + !avfilter_merge_formats(link->in_formats, | |
| 280 | + link->out_formats)) | |
| 281 | + convert_needed = 1; | |
| 282 | + if (link->type == AVMEDIA_TYPE_AUDIO) { | |
| 283 | + if (link->in_channel_layouts != link->out_channel_layouts && | |
| 284 | + !ff_merge_channel_layouts(link->in_channel_layouts, | |
| 285 | + link->out_channel_layouts)) | |
| 286 | + convert_needed = 1; | |
| 287 | + if (link->in_samplerates != link->out_samplerates && | |
| 288 | + !ff_merge_samplerates(link->in_samplerates, | |
| 289 | + link->out_samplerates)) | |
| 290 | + convert_needed = 1; | |
| 291 | + } | |
| 292 | + | |
| 293 | + if (convert_needed) { | |
| 294 | + AVFilterContext *convert; | |
| 295 | + AVFilter *filter; | |
| 296 | + AVFilterLink *inlink, *outlink; | |
| 297 | + char scale_args[256]; | |
| 298 | + char inst_name[30]; | |
| 299 | + | |
| 300 | + /* couldn't merge format lists. auto-insert conversion filter */ | |
| 301 | + switch (link->type) { | |
| 302 | + case AVMEDIA_TYPE_VIDEO: | |
| 303 | + snprintf(inst_name, sizeof(inst_name), "auto-inserted scaler %d", | |
| 304 | + scaler_count++); | |
| 305 | + snprintf(scale_args, sizeof(scale_args), "0:0:%s", graph->scale_sws_opts); | |
| 306 | + if ((ret = avfilter_graph_create_filter(&convert, | |
| 307 | + avfilter_get_by_name("scale"), | |
| 308 | + inst_name, scale_args, NULL, | |
| 309 | + graph)) < 0) | |
| 310 | + return ret; | |
| 311 | + break; | |
| 312 | + case AVMEDIA_TYPE_AUDIO: | |
| 313 | + if (!(filter = avfilter_get_by_name("resample"))) { | |
| 314 | + av_log(log_ctx, AV_LOG_ERROR, "'resample' filter " | |
| 315 | + "not present, cannot convert audio formats.\n"); | |
| 316 | + return AVERROR(EINVAL); | |
| 317 | + } | |
| 318 | + | |
| 319 | + snprintf(inst_name, sizeof(inst_name), "auto-inserted resampler %d", | |
| 320 | + resampler_count++); | |
| 321 | + if ((ret = avfilter_graph_create_filter(&convert, | |
| 322 | + avfilter_get_by_name("resample"), | |
| 323 | + inst_name, NULL, NULL, graph)) < 0) | |
| 324 | + return ret; | |
| 325 | + break; | |
| 326 | + default: | |
| 327 | + return AVERROR(EINVAL); | |
| 328 | + } | |
| 329 | + | |
| 330 | + if ((ret = avfilter_insert_filter(link, convert, 0, 0)) < 0) | |
| 331 | + return ret; | |
| 332 | + | |
| 333 | + convert->filter->query_formats(convert); | |
| 334 | + inlink = convert->inputs[0]; | |
| 335 | + outlink = convert->outputs[0]; | |
| 336 | + if (!avfilter_merge_formats( inlink->in_formats, inlink->out_formats) || | |
| 337 | + !avfilter_merge_formats(outlink->in_formats, outlink->out_formats)) | |
| 338 | + ret |= AVERROR(ENOSYS); | |
| 339 | + if (inlink->type == AVMEDIA_TYPE_AUDIO && | |
| 340 | + (!ff_merge_samplerates(inlink->in_samplerates, | |
| 341 | + inlink->out_samplerates) || | |
| 342 | + !ff_merge_channel_layouts(inlink->in_channel_layouts, | |
| 343 | + inlink->out_channel_layouts))) | |
| 344 | + ret |= AVERROR(ENOSYS); | |
| 345 | + if (outlink->type == AVMEDIA_TYPE_AUDIO && | |
| 346 | + (!ff_merge_samplerates(outlink->in_samplerates, | |
| 347 | + outlink->out_samplerates) || | |
| 348 | + !ff_merge_channel_layouts(outlink->in_channel_layouts, | |
| 349 | + outlink->out_channel_layouts))) | |
| 350 | + ret |= AVERROR(ENOSYS); | |
| 351 | + | |
| 352 | + if (ret < 0) { | |
| 353 | + av_log(log_ctx, AV_LOG_ERROR, | |
| 354 | + "Impossible to convert between the formats supported by the filter " | |
| 355 | + "'%s' and the filter '%s'\n", link->src->name, link->dst->name); | |
| 356 | + return ret; | |
| 357 | + } | |
| 358 | +#endif | |
| 264 | 359 | } |
| 265 | 360 | } |
| 266 | 361 | } |
| @@ -268,10 +363,10 @@ static int query_formats(AVFilterGraph *graph, AVClass *log_ctx) · 1 unmodified line | ||
| 268 | 363 | return 0; |
| 269 | 364 | } |
| 270 | 365 | |
| 271 | −static void pick_format(AVFilterLink *link, AVFilterLink *ref) | |
| 366 | +static int pick_format(AVFilterLink *link, AVFilterLink *ref) | |
| 272 | 367 | { |
| 273 | 368 | if (!link || !link->in_formats) |
| 274 | − return; | |
| 369 | + return 0; | |
| 275 | 370 | |
| 276 | 371 | if (link->type == AVMEDIA_TYPE_VIDEO) { |
| 277 | 372 | if(ref && ref->type == AVMEDIA_TYPE_VIDEO){ |
| @@ -288,50 +383,83 @@ static void pick_format(AVFilterLink *link, AVFilterLink *ref) · 10 unmodified lines | ||
| 288 | 383 | |
| 289 | 384 | link->in_formats->format_count = 1; |
| 290 | 385 | link->format = link->in_formats->formats[0]; |
| 291 | − avfilter_formats_unref(&link->in_formats); | |
| 292 | − avfilter_formats_unref(&link->out_formats); | |
| 293 | 386 | |
| 294 | 387 | if (link->type == AVMEDIA_TYPE_AUDIO) { |
| 295 | − link->in_chlayouts->format_count = 1; | |
| 296 | − link->channel_layout = link->in_chlayouts->formats[0]; | |
| 297 | − avfilter_formats_unref(&link->in_chlayouts); | |
| 298 | − avfilter_formats_unref(&link->out_chlayouts); | |
| 299 | − | |
| 300 | − link->in_packing->format_count = 1; | |
| 301 | − link->planar = link->in_packing->formats[0] == AVFILTER_PLANAR; | |
| 302 | − avfilter_formats_unref(&link->in_packing); | |
| 303 | − avfilter_formats_unref(&link->out_packing); | |
| 388 | + if (!link->in_samplerates->format_count) { | |
| 389 | + av_log(link->src, AV_LOG_ERROR, "Cannot select sample rate for" | |
| 390 | + " the link between filters %s and %s.\n", link->src->name, | |
| 391 | + link->dst->name); | |
| 392 | + return AVERROR(EINVAL); | |
| 393 | + } | |
| 394 | + link->in_samplerates->format_count = 1; | |
| 395 | + link->sample_rate = link->in_samplerates->formats[0]; | |
| 396 | + | |
| 397 | + if (!link->in_channel_layouts->nb_channel_layouts) { | |
| 398 | + av_log(link->src, AV_LOG_ERROR, "Cannot select channel layout for" | |
| 399 | + "the link between filters %s and %s.\n", link->src->name, | |
| 400 | + link->dst->name); | |
| 401 | + return AVERROR(EINVAL); | |
| 402 | + } | |
| 403 | + link->in_channel_layouts->nb_channel_layouts = 1; | |
| 404 | + link->channel_layout = link->in_channel_layouts->channel_layouts[0]; | |
| 304 | 405 | } |
| 406 | + | |
| 407 | + avfilter_formats_unref(&link->in_formats); | |
| 408 | + avfilter_formats_unref(&link->out_formats); | |
| 409 | + avfilter_formats_unref(&link->in_samplerates); | |
| 410 | + avfilter_formats_unref(&link->out_samplerates); | |
| 411 | + ff_channel_layouts_unref(&link->in_channel_layouts); | |
| 412 | + ff_channel_layouts_unref(&link->out_channel_layouts); | |
| 413 | + | |
| 414 | + return 0; | |
| 305 | 415 | } |
| 306 | 416 | |
| 417 | +#define REDUCE_FORMATS(fmt_type, list_type, list, var, nb, add_format) \ | |
| 418 | +do { \ | |
| 419 | + for (i = 0; i < filter->input_count; i++) { \ | |
| 420 | + AVFilterLink *link = filter->inputs[i]; \ | |
| 421 | + fmt_type fmt; \ | |
| 422 | + \ | |
| 423 | + if (!link->out_ ## list || link->out_ ## list->nb != 1) \ | |
| 424 | + continue; \ | |
| 425 | + fmt = link->out_ ## list->var[0]; \ | |
| 426 | + \ | |
| 427 | + for (j = 0; j < filter->output_count; j++) { \ | |
| 428 | + AVFilterLink *out_link = filter->outputs[j]; \ | |
| 429 | + list_type *fmts; \ | |
| 430 | + \ | |
| 431 | + if (link->type != out_link->type || \ | |
| 432 | + out_link->in_ ## list->nb == 1) \ | |
| 433 | + continue; \ | |
| 434 | + fmts = out_link->in_ ## list; \ | |
| 435 | + \ | |
| 436 | + if (!out_link->in_ ## list->nb) { \ | |
| 437 | + add_format(&out_link->in_ ##list, fmt); \ | |
| 438 | + break; \ | |
| 439 | + } \ | |
| 440 | + \ | |
| 441 | + for (k = 0; k < out_link->in_ ## list->nb; k++) \ | |
| 442 | + if (fmts->var[k] == fmt) { \ | |
| 443 | + fmts->var[0] = fmt; \ | |
| 444 | + fmts->nb = 1; \ | |
| 445 | + ret = 1; \ | |
| 446 | + break; \ | |
| 447 | + } \ | |
| 448 | + } \ | |
| 449 | + } \ | |
| 450 | +} while (0) | |
| 451 | + | |
| 307 | 452 | static int reduce_formats_on_filter(AVFilterContext *filter) |
| 308 | 453 | { |
| 309 | 454 | int i, j, k, ret = 0; |
| 310 | 455 | |
| 311 | − for (i = 0; i < filter->input_count; i++) { | |
| 312 | − AVFilterLink *link = filter->inputs[i]; | |
| 313 | − int format = link->out_formats->formats[0]; | |
| 314 | − | |
| 315 | − if (link->out_formats->format_count != 1) | |
| 316 | − continue; | |
| 317 | − | |
| 318 | − for (j = 0; j < filter->output_count; j++) { | |
| 319 | − AVFilterLink *out_link = filter->outputs[j]; | |
| 320 | − AVFilterFormats *fmts = out_link->in_formats; | |
| 321 | − | |
| 322 | − if (link->type != out_link->type || | |
| 323 | − out_link->in_formats->format_count == 1) | |
| 324 | − continue; | |
| 456 | + REDUCE_FORMATS(int, AVFilterFormats, formats, formats, | |
| 457 | + format_count, avfilter_add_format); | |
| 458 | + REDUCE_FORMATS(int, AVFilterFormats, samplerates, formats, | |
| 459 | + format_count, avfilter_add_format); | |
| 460 | + REDUCE_FORMATS(uint64_t, AVFilterChannelLayouts, channel_layouts, | |
| 461 | + channel_layouts, nb_channel_layouts, ff_add_channel_layout); | |
| 325 | 462 | |
| 326 | − for (k = 0; k < out_link->in_formats->format_count; k++) | |
| 327 | − if (fmts->formats[k] == format) { | |
| 328 | − fmts->formats[0] = format; | |
| 329 | − fmts->format_count = 1; | |
| 330 | − ret = 1; | |
| 331 | − break; | |
| 332 | − } | |
| 333 | − } | |
| 334 | − } | |
| 335 | 463 | return ret; |
| 336 | 464 | } |
| 337 | 465 | |
| @@ -347,9 +475,109 @@ static void reduce_formats(AVFilterGraph *graph) · 9 unmodified lines | ||
| 347 | 475 | } while (reduced); |
| 348 | 476 | } |
| 349 | 477 | |
| 350 | −static void pick_formats(AVFilterGraph *graph) | |
| 478 | +static void swap_samplerates_on_filter(AVFilterContext *filter) | |
| 479 | +{ | |
| 480 | + AVFilterLink *link = NULL; | |
| 481 | + int sample_rate; | |
| 482 | + int i, j; | |
| 483 | + | |
| 484 | + for (i = 0; i < filter->input_count; i++) { | |
| 485 | + link = filter->inputs[i]; | |
| 486 | + | |
| 487 | + if (link->type == AVMEDIA_TYPE_AUDIO && | |
| 488 | + link->out_samplerates->format_count == 1) | |
| 489 | + break; | |
| 490 | + } | |
| 491 | + if (i == filter->input_count) | |
| 492 | + return; | |
| 493 | + | |
| 494 | + sample_rate = link->out_samplerates->formats[0]; | |
| 495 | + | |
| 496 | + for (i = 0; i < filter->output_count; i++) { | |
| 497 | + AVFilterLink *outlink = filter->outputs[i]; | |
| 498 | + int best_idx, best_diff = INT_MAX; | |
| 499 | + | |
| 500 | + if (outlink->type != AVMEDIA_TYPE_AUDIO || | |
| 501 | + outlink->in_samplerates->format_count < 2) | |
| 502 | + continue; | |
| 503 | + | |
| 504 | + for (j = 0; j < outlink->in_samplerates->format_count; j++) { | |
| 505 | + int diff = abs(sample_rate - outlink->in_samplerates->formats[j]); | |
| 506 | + | |
| 507 | + if (diff < best_diff) { | |
| 508 | + best_diff = diff; | |
| 509 | + best_idx = j; | |
| 510 | + } | |
| 511 | + } | |
| 512 | + FFSWAP(int, outlink->in_samplerates->formats[0], | |
| 513 | + outlink->in_samplerates->formats[best_idx]); | |
| 514 | + } | |
| 515 | +} | |
| 516 | + | |
| 517 | +static void swap_samplerates(AVFilterGraph *graph) | |
| 351 | 518 | { |
| 519 | + int i; | |
| 520 | + | |
| 521 | + for (i = 0; i < graph->filter_count; i++) | |
| 522 | + swap_samplerates_on_filter(graph->filters[i]); | |
| 523 | +} | |
| 524 | + | |
| 525 | +static void swap_channel_layouts_on_filter(AVFilterContext *filter) | |
| 526 | +{ | |
| 527 | + AVFilterLink *link = NULL; | |
| 528 | + uint64_t chlayout; | |
| 352 | 529 | int i, j; |
| 530 | + | |
| 531 | + for (i = 0; i < filter->input_count; i++) { | |
| 532 | + link = filter->inputs[i]; | |
| 533 | + | |
| 534 | + if (link->type == AVMEDIA_TYPE_AUDIO && | |
| 535 | + link->out_channel_layouts->nb_channel_layouts == 1) | |
| 536 | + break; | |
| 537 | + } | |
| 538 | + if (i == filter->input_count) | |
| 539 | + return; | |
| 540 | + | |
| 541 | + chlayout = link->out_channel_layouts->channel_layouts[0]; | |
| 542 | + | |
| 543 | + for (i = 0; i < filter->output_count; i++) { | |
| 544 | + AVFilterLink *outlink = filter->outputs[i]; | |
| 545 | + int best_idx, best_score = INT_MIN; | |
| 546 | + | |
| 547 | + if (outlink->type != AVMEDIA_TYPE_AUDIO || | |
| 548 | + outlink->in_channel_layouts->nb_channel_layouts < 2) | |
| 549 | + continue; | |
| 550 | + | |
| 551 | + for (j = 0; j < outlink->in_channel_layouts->nb_channel_layouts; j++) { | |
| 552 | + uint64_t out_chlayout = outlink->in_channel_layouts->channel_layouts[j]; | |
| 553 | + int matched_channels = av_get_channel_layout_nb_channels(chlayout & | |
| 554 | + out_chlayout); | |
| 555 | + int extra_channels = av_get_channel_layout_nb_channels(out_chlayout & | |
| 556 | + (~chlayout)); | |
| 557 | + int score = matched_channels - extra_channels; | |
| 558 | + | |
| 559 | + if (score > best_score) { | |
| 560 | + best_score = score; | |
| 561 | + best_idx = j; | |
| 562 | + } | |
| 563 | + } | |
| 564 | + FFSWAP(uint64_t, outlink->in_channel_layouts->channel_layouts[0], | |
| 565 | + outlink->in_channel_layouts->channel_layouts[best_idx]); | |
| 566 | + } | |
| 567 | + | |
| 568 | +} | |
| 569 | + | |
| 570 | +static void swap_channel_layouts(AVFilterGraph *graph) | |
| 571 | +{ | |
| 572 | + int i; | |
| 573 | + | |
| 574 | + for (i = 0; i < graph->filter_count; i++) | |
| 575 | + swap_channel_layouts_on_filter(graph->filters[i]); | |
| 576 | +} | |
| 577 | + | |
| 578 | +static int pick_formats(AVFilterGraph *graph) | |
| 579 | +{ | |
| 580 | + int i, j, ret; | |
| 353 | 581 | int change; |
| 354 | 582 | |
| 355 | 583 | do{ |
| @@ -385,13 +613,15 @@ static void pick_formats(AVFilterGraph *graph) · 29 unmodified lines | ||
| 385 | 613 | |
| 386 | 614 | for (i = 0; i < graph->filter_count; i++) { |
| 387 | 615 | AVFilterContext *filter = graph->filters[i]; |
| 388 | − if (1) { | |
| 389 | − for (j = 0; j < filter->input_count; j++) | |
| 390 | − pick_format(filter->inputs[j], NULL); | |
| 391 | − for (j = 0; j < filter->output_count; j++) | |
| 392 | − pick_format(filter->outputs[j], NULL); | |
| 393 | − } | |
| 616 | + | |
| 617 | + for (j = 0; j < filter->input_count; j++) | |
| 618 | + if ((ret = pick_format(filter->inputs[j], NULL)) < 0) | |
| 619 | + return ret; | |
| 620 | + for (j = 0; j < filter->output_count; j++) | |
| 621 | + if ((ret = pick_format(filter->outputs[j], NULL)) < 0) | |
| 622 | + return ret; | |
| 394 | 623 | } |
| 624 | + return 0; | |
| 395 | 625 | } |
| 396 | 626 | |
| 397 | 627 | int ff_avfilter_graph_config_formats(AVFilterGraph *graph, AVClass *log_ctx) |
| @@ -407,7 +637,13 @@ int ff_avfilter_graph_config_formats(AVFilterGraph *graph, AVClass *log_ctx) · 9 unmodified lines | ||
| 407 | 637 | * of format conversion inside filters */ |
| 408 | 638 | reduce_formats(graph); |
| 409 | 639 | |
| 410 | − pick_formats(graph); | |
| 640 | + /* for audio filters, ensure the best sample rate and channel layout | |
| 641 | + * is selected */ | |
| 642 | + swap_samplerates(graph); | |
| 643 | + swap_channel_layouts(graph); | |
| 644 | + | |
| 645 | + if ((ret = pick_formats(graph)) < 0) | |
| 646 | + return ret; | |
| 411 | 647 | |
| 412 | 648 | return 0; |
| 413 | 649 | } |