| ... | ... |
@@ -461,6 +461,74 @@ static void swap_channel_layouts(AVFilterGraph *graph) |
| 461 | 461 |
swap_channel_layouts_on_filter(graph->filters[i]); |
| 462 | 462 |
} |
| 463 | 463 |
|
| 464 |
+static void swap_sample_fmts_on_filter(AVFilterContext *filter) |
|
| 465 |
+{
|
|
| 466 |
+ AVFilterLink *link = NULL; |
|
| 467 |
+ int format, bps; |
|
| 468 |
+ int i, j; |
|
| 469 |
+ |
|
| 470 |
+ for (i = 0; i < filter->input_count; i++) {
|
|
| 471 |
+ link = filter->inputs[i]; |
|
| 472 |
+ |
|
| 473 |
+ if (link->type == AVMEDIA_TYPE_AUDIO && |
|
| 474 |
+ link->out_formats->format_count == 1) |
|
| 475 |
+ break; |
|
| 476 |
+ } |
|
| 477 |
+ if (i == filter->input_count) |
|
| 478 |
+ return; |
|
| 479 |
+ |
|
| 480 |
+ format = link->out_formats->formats[0]; |
|
| 481 |
+ bps = av_get_bytes_per_sample(format); |
|
| 482 |
+ |
|
| 483 |
+ for (i = 0; i < filter->output_count; i++) {
|
|
| 484 |
+ AVFilterLink *outlink = filter->outputs[i]; |
|
| 485 |
+ int best_idx, best_score = INT_MIN; |
|
| 486 |
+ |
|
| 487 |
+ if (outlink->type != AVMEDIA_TYPE_AUDIO || |
|
| 488 |
+ outlink->in_formats->format_count < 2) |
|
| 489 |
+ continue; |
|
| 490 |
+ |
|
| 491 |
+ for (j = 0; j < outlink->in_formats->format_count; j++) {
|
|
| 492 |
+ int out_format = outlink->in_formats->formats[j]; |
|
| 493 |
+ int out_bps = av_get_bytes_per_sample(out_format); |
|
| 494 |
+ int score; |
|
| 495 |
+ |
|
| 496 |
+ if (av_get_packed_sample_fmt(out_format) == format || |
|
| 497 |
+ av_get_planar_sample_fmt(out_format) == format) {
|
|
| 498 |
+ best_idx = j; |
|
| 499 |
+ break; |
|
| 500 |
+ } |
|
| 501 |
+ |
|
| 502 |
+ /* for s32 and float prefer double to prevent loss of information */ |
|
| 503 |
+ if (bps == 4 && out_bps == 8) {
|
|
| 504 |
+ best_idx = j; |
|
| 505 |
+ break; |
|
| 506 |
+ } |
|
| 507 |
+ |
|
| 508 |
+ /* prefer closest higher or equal bps */ |
|
| 509 |
+ score = -abs(out_bps - bps); |
|
| 510 |
+ if (out_bps >= bps) |
|
| 511 |
+ score += INT_MAX/2; |
|
| 512 |
+ |
|
| 513 |
+ if (score > best_score) {
|
|
| 514 |
+ best_score = score; |
|
| 515 |
+ best_idx = j; |
|
| 516 |
+ } |
|
| 517 |
+ } |
|
| 518 |
+ FFSWAP(int, outlink->in_formats->formats[0], |
|
| 519 |
+ outlink->in_formats->formats[best_idx]); |
|
| 520 |
+ } |
|
| 521 |
+} |
|
| 522 |
+ |
|
| 523 |
+static void swap_sample_fmts(AVFilterGraph *graph) |
|
| 524 |
+{
|
|
| 525 |
+ int i; |
|
| 526 |
+ |
|
| 527 |
+ for (i = 0; i < graph->filter_count; i++) |
|
| 528 |
+ swap_sample_fmts_on_filter(graph->filters[i]); |
|
| 529 |
+ |
|
| 530 |
+} |
|
| 531 |
+ |
|
| 464 | 532 |
static int pick_formats(AVFilterGraph *graph) |
| 465 | 533 |
{
|
| 466 | 534 |
int i, j, ret; |
| ... | ... |
@@ -491,8 +559,9 @@ int ff_avfilter_graph_config_formats(AVFilterGraph *graph, AVClass *log_ctx) |
| 491 | 491 |
* of format conversion inside filters */ |
| 492 | 492 |
reduce_formats(graph); |
| 493 | 493 |
|
| 494 |
- /* for audio filters, ensure the best sample rate and channel layout |
|
| 494 |
+ /* for audio filters, ensure the best format, sample rate and channel layout |
|
| 495 | 495 |
* is selected */ |
| 496 |
+ swap_sample_fmts(graph); |
|
| 496 | 497 |
swap_samplerates(graph); |
| 497 | 498 |
swap_channel_layouts(graph); |
| 498 | 499 |
|