[FFmpeg-cvslog] avfiltergraph: smarter sample format selection.

Anton Khirnov git at videolan.org
Wed May 23 22:00:58 CEST 2012


ffmpeg | branch: master | Anton Khirnov <anton at khirnov.net> | Sat May 19 09:19:41 2012 +0200| [ccefa89f398a30dcd24044621ec7013387aeb455] | committer: Anton Khirnov

avfiltergraph: smarter sample format selection.

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=ccefa89f398a30dcd24044621ec7013387aeb455
---

 libavfilter/avfiltergraph.c |   71 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 70 insertions(+), 1 deletion(-)

diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c
index f65faae..91a5f32 100644
--- a/libavfilter/avfiltergraph.c
+++ b/libavfilter/avfiltergraph.c
@@ -461,6 +461,74 @@ static void swap_channel_layouts(AVFilterGraph *graph)
         swap_channel_layouts_on_filter(graph->filters[i]);
 }
 
+static void swap_sample_fmts_on_filter(AVFilterContext *filter)
+{
+    AVFilterLink *link = NULL;
+    int format, bps;
+    int i, j;
+
+    for (i = 0; i < filter->input_count; i++) {
+        link = filter->inputs[i];
+
+        if (link->type == AVMEDIA_TYPE_AUDIO &&
+            link->out_formats->format_count == 1)
+            break;
+    }
+    if (i == filter->input_count)
+        return;
+
+    format = link->out_formats->formats[0];
+    bps    = av_get_bytes_per_sample(format);
+
+    for (i = 0; i < filter->output_count; i++) {
+        AVFilterLink *outlink = filter->outputs[i];
+        int best_idx, best_score = INT_MIN;
+
+        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;
+            }
+        }
+        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]);
+
+}
+
 static int pick_formats(AVFilterGraph *graph)
 {
     int i, j, ret;
@@ -491,8 +559,9 @@ int ff_avfilter_graph_config_formats(AVFilterGraph *graph, AVClass *log_ctx)
      * of format conversion inside filters */
     reduce_formats(graph);
 
-    /* for audio filters, ensure the best sample rate and channel layout
+    /* for audio filters, ensure the best format, sample rate and channel layout
      * is selected */
+    swap_sample_fmts(graph);
     swap_samplerates(graph);
     swap_channel_layouts(graph);
 



More information about the ffmpeg-cvslog mailing list