Browse code

avfiltergraph: smarter sample format selection.

Anton Khirnov authored on 2012/05/19 16:19:41
Showing 1 changed files
... ...
@@ -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