Browse code

lavfi: add channel layout/sample rate negotiation.

Anton Khirnov authored on 2012/05/06 14:00:22
Showing 4 changed files
... ...
@@ -31,6 +31,7 @@
31 31
 
32 32
 #include "audio.h"
33 33
 #include "avfilter.h"
34
+#include "formats.h"
34 35
 #include "internal.h"
35 36
 
36 37
 typedef struct ResampleContext {
... ...
@@ -56,10 +57,20 @@ static int query_formats(AVFilterContext *ctx)
56 56
 
57 57
     AVFilterFormats        *in_formats      = avfilter_all_formats(AVMEDIA_TYPE_AUDIO);
58 58
     AVFilterFormats        *out_formats     = avfilter_all_formats(AVMEDIA_TYPE_AUDIO);
59
+    AVFilterFormats        *in_samplerates  = ff_all_samplerates();
60
+    AVFilterFormats        *out_samplerates = ff_all_samplerates();
61
+    AVFilterChannelLayouts *in_layouts      = ff_all_channel_layouts();
62
+    AVFilterChannelLayouts *out_layouts     = ff_all_channel_layouts();
59 63
 
60 64
     avfilter_formats_ref(in_formats,  &inlink->out_formats);
61 65
     avfilter_formats_ref(out_formats, &outlink->in_formats);
62 66
 
67
+    avfilter_formats_ref(in_samplerates,  &inlink->out_samplerates);
68
+    avfilter_formats_ref(out_samplerates, &outlink->in_samplerates);
69
+
70
+    ff_channel_layouts_ref(in_layouts,  &inlink->out_channel_layouts);
71
+    ff_channel_layouts_ref(out_layouts, &outlink->in_channel_layouts);
72
+
63 73
     return 0;
64 74
 }
65 75
 
... ...
@@ -28,6 +28,7 @@
28 28
 #include "libavcodec/avcodec.h"
29 29
 
30 30
 #include "avfilter.h"
31
+#include "formats.h"
31 32
 #include "internal.h"
32 33
 
33 34
 unsigned avfilter_version(void) {
... ...
@@ -176,6 +177,12 @@ int avfilter_insert_filter(AVFilterLink *link, AVFilterContext *filt,
176 176
     if (link->out_formats)
177 177
         avfilter_formats_changeref(&link->out_formats,
178 178
                                    &filt->outputs[filt_dstpad_idx]->out_formats);
179
+    if (link->out_samplerates)
180
+        avfilter_formats_changeref(&link->out_samplerates,
181
+                                   &filt->outputs[filt_dstpad_idx]->out_samplerates);
182
+    if (link->out_channel_layouts)
183
+        ff_channel_layouts_changeref(&link->out_channel_layouts,
184
+                                     &filt->outputs[filt_dstpad_idx]->out_channel_layouts);
179 185
 
180 186
     return 0;
181 187
 }
... ...
@@ -216,12 +223,6 @@ int avfilter_config_links(AVFilterContext *filter)
216 216
                 link->sample_aspect_ratio = link->src->input_count ?
217 217
                     link->src->inputs[0]->sample_aspect_ratio : (AVRational){1,1};
218 218
 
219
-            if (link->sample_rate == 0 && link->src && link->src->input_count)
220
-                link->sample_rate = link->src->inputs[0]->sample_rate;
221
-
222
-            if (link->channel_layout == 0 && link->src && link->src->input_count)
223
-                link->channel_layout = link->src->inputs[0]->channel_layout;
224
-
225 219
             if ((config_link = link->dstpad->config_props))
226 220
                 if ((ret = config_link(link)) < 0)
227 221
                     return ret;
... ...
@@ -614,6 +615,10 @@ void avfilter_free(AVFilterContext *filter)
614 614
                 link->src->outputs[link->srcpad - link->src->output_pads] = NULL;
615 615
             avfilter_formats_unref(&link->in_formats);
616 616
             avfilter_formats_unref(&link->out_formats);
617
+            avfilter_formats_unref(&link->in_samplerates);
618
+            avfilter_formats_unref(&link->out_samplerates);
619
+            ff_channel_layouts_unref(&link->in_channel_layouts);
620
+            ff_channel_layouts_unref(&link->out_channel_layouts);
617 621
         }
618 622
         av_freep(&link);
619 623
     }
... ...
@@ -623,6 +628,10 @@ void avfilter_free(AVFilterContext *filter)
623 623
                 link->dst->inputs[link->dstpad - link->dst->input_pads] = NULL;
624 624
             avfilter_formats_unref(&link->in_formats);
625 625
             avfilter_formats_unref(&link->out_formats);
626
+            avfilter_formats_unref(&link->in_samplerates);
627
+            avfilter_formats_unref(&link->out_samplerates);
628
+            ff_channel_layouts_unref(&link->in_channel_layouts);
629
+            ff_channel_layouts_unref(&link->out_channel_layouts);
626 630
         }
627 631
         av_freep(&link);
628 632
     }
... ...
@@ -25,8 +25,10 @@
25 25
 
26 26
 #include "avfilter.h"
27 27
 #include "avfiltergraph.h"
28
+#include "formats.h"
28 29
 #include "internal.h"
29 30
 
31
+#include "libavutil/audioconvert.h"
30 32
 #include "libavutil/log.h"
31 33
 
32 34
 static const AVClass filtergraph_class = {
... ...
@@ -168,9 +170,27 @@ static int query_formats(AVFilterGraph *graph, AVClass *log_ctx)
168 168
 
169 169
         for (j = 0; j < filter->input_count; j++) {
170 170
             AVFilterLink *link = filter->inputs[j];
171
-            if (link && link->in_formats != link->out_formats) {
172
-                if (!avfilter_merge_formats(link->in_formats,
173
-                                            link->out_formats)) {
171
+            int convert_needed = 0;
172
+
173
+            if (!link)
174
+                continue;
175
+
176
+            if (link->in_formats != link->out_formats &&
177
+                !avfilter_merge_formats(link->in_formats,
178
+                                        link->out_formats))
179
+                convert_needed = 1;
180
+            if (link->type == AVMEDIA_TYPE_AUDIO) {
181
+                if (link->in_channel_layouts != link->out_channel_layouts &&
182
+                    !ff_merge_channel_layouts(link->in_channel_layouts,
183
+                                              link->out_channel_layouts))
184
+                    convert_needed = 1;
185
+                if (link->in_samplerates != link->out_samplerates &&
186
+                    !ff_merge_samplerates(link->in_samplerates,
187
+                                          link->out_samplerates))
188
+                    convert_needed = 1;
189
+            }
190
+
191
+            if (convert_needed) {
174 192
                     AVFilterContext *convert;
175 193
                     AVFilter *filter;
176 194
                     AVFilterLink *inlink, *outlink;
... ...
@@ -214,13 +234,27 @@ static int query_formats(AVFilterGraph *graph, AVClass *log_ctx)
214 214
                     inlink  = convert->inputs[0];
215 215
                     outlink = convert->outputs[0];
216 216
                     if (!avfilter_merge_formats( inlink->in_formats,  inlink->out_formats) ||
217
-                        !avfilter_merge_formats(outlink->in_formats, outlink->out_formats)) {
217
+                        !avfilter_merge_formats(outlink->in_formats, outlink->out_formats))
218
+                        ret |= AVERROR(ENOSYS);
219
+                    if (inlink->type == AVMEDIA_TYPE_AUDIO &&
220
+                        (!ff_merge_samplerates(inlink->in_samplerates,
221
+                                               inlink->out_samplerates) ||
222
+                         !ff_merge_channel_layouts(inlink->in_channel_layouts,
223
+                                                   inlink->out_channel_layouts)))
224
+                        ret |= AVERROR(ENOSYS);
225
+                    if (outlink->type == AVMEDIA_TYPE_AUDIO &&
226
+                        (!ff_merge_samplerates(outlink->in_samplerates,
227
+                                               outlink->out_samplerates) ||
228
+                         !ff_merge_channel_layouts(outlink->in_channel_layouts,
229
+                                                   outlink->out_channel_layouts)))
230
+                        ret |= AVERROR(ENOSYS);
231
+
232
+                    if (ret < 0) {
218 233
                         av_log(log_ctx, AV_LOG_ERROR,
219 234
                                "Impossible to convert between the formats supported by the filter "
220 235
                                "'%s' and the filter '%s'\n", link->src->name, link->dst->name);
221
-                        return AVERROR(EINVAL);
236
+                        return ret;
222 237
                     }
223
-                }
224 238
             }
225 239
         }
226 240
     }
... ...
@@ -228,46 +262,90 @@ static int query_formats(AVFilterGraph *graph, AVClass *log_ctx)
228 228
     return 0;
229 229
 }
230 230
 
231
-static void pick_format(AVFilterLink *link)
231
+static int pick_format(AVFilterLink *link)
232 232
 {
233 233
     if (!link || !link->in_formats)
234
-        return;
234
+        return 0;
235 235
 
236 236
     link->in_formats->format_count = 1;
237 237
     link->format = link->in_formats->formats[0];
238 238
 
239
+    if (link->type == AVMEDIA_TYPE_AUDIO) {
240
+        if (!link->in_samplerates->format_count) {
241
+            av_log(link->src, AV_LOG_ERROR, "Cannot select sample rate for"
242
+                   " the link between filters %s and %s.\n", link->src->name,
243
+                   link->dst->name);
244
+            return AVERROR(EINVAL);
245
+        }
246
+        link->in_samplerates->format_count = 1;
247
+        link->sample_rate = link->in_samplerates->formats[0];
248
+
249
+        if (!link->in_channel_layouts->nb_channel_layouts) {
250
+            av_log(link->src, AV_LOG_ERROR, "Cannot select channel layout for"
251
+                   "the link between filters %s and %s.\n", link->src->name,
252
+                   link->dst->name);
253
+            return AVERROR(EINVAL);
254
+        }
255
+        link->in_channel_layouts->nb_channel_layouts = 1;
256
+        link->channel_layout = link->in_channel_layouts->channel_layouts[0];
257
+    }
258
+
239 259
     avfilter_formats_unref(&link->in_formats);
240 260
     avfilter_formats_unref(&link->out_formats);
261
+    avfilter_formats_unref(&link->in_samplerates);
262
+    avfilter_formats_unref(&link->out_samplerates);
263
+    ff_channel_layouts_unref(&link->in_channel_layouts);
264
+    ff_channel_layouts_unref(&link->out_channel_layouts);
265
+
266
+    return 0;
241 267
 }
242 268
 
269
+#define REDUCE_FORMATS(fmt_type, list_type, list, var, nb, add_format) \
270
+do {                                                                   \
271
+    for (i = 0; i < filter->input_count; i++) {                        \
272
+        AVFilterLink *link = filter->inputs[i];                        \
273
+        fmt_type fmt;                                                  \
274
+                                                                       \
275
+        if (!link->out_ ## list || link->out_ ## list->nb != 1)        \
276
+            continue;                                                  \
277
+        fmt = link->out_ ## list->var[0];                              \
278
+                                                                       \
279
+        for (j = 0; j < filter->output_count; j++) {                   \
280
+            AVFilterLink *out_link = filter->outputs[j];               \
281
+            list_type *fmts;                                           \
282
+                                                                       \
283
+            if (link->type != out_link->type ||                        \
284
+                out_link->in_ ## list->nb == 1)                        \
285
+                continue;                                              \
286
+            fmts = out_link->in_ ## list;                              \
287
+                                                                       \
288
+            if (!out_link->in_ ## list->nb) {                          \
289
+                add_format(&out_link->in_ ##list, fmt);                \
290
+                break;                                                 \
291
+            }                                                          \
292
+                                                                       \
293
+            for (k = 0; k < out_link->in_ ## list->nb; k++)            \
294
+                if (fmts->var[k] == fmt) {                             \
295
+                    fmts->var[0]  = fmt;                               \
296
+                    fmts->nb = 1;                                      \
297
+                    ret = 1;                                           \
298
+                    break;                                             \
299
+                }                                                      \
300
+        }                                                              \
301
+    }                                                                  \
302
+} while (0)
303
+
243 304
 static int reduce_formats_on_filter(AVFilterContext *filter)
244 305
 {
245 306
     int i, j, k, ret = 0;
246 307
 
247
-    for (i = 0; i < filter->input_count; i++) {
248
-        AVFilterLink *link = filter->inputs[i];
249
-        int         format = link->out_formats->formats[0];
250
-
251
-        if (link->out_formats->format_count != 1)
252
-            continue;
253
-
254
-        for (j = 0; j < filter->output_count; j++) {
255
-            AVFilterLink *out_link = filter->outputs[j];
256
-            AVFilterFormats  *fmts = out_link->in_formats;
308
+    REDUCE_FORMATS(int,      AVFilterFormats,        formats,         formats,
309
+                   format_count, avfilter_add_format);
310
+    REDUCE_FORMATS(int,      AVFilterFormats,        samplerates,     formats,
311
+                   format_count, avfilter_add_format);
312
+    REDUCE_FORMATS(uint64_t, AVFilterChannelLayouts, channel_layouts,
313
+                   channel_layouts, nb_channel_layouts, ff_add_channel_layout);
257 314
 
258
-            if (link->type != out_link->type ||
259
-                out_link->in_formats->format_count == 1)
260
-                continue;
261
-
262
-            for (k = 0; k < out_link->in_formats->format_count; k++)
263
-                if (fmts->formats[k] == format) {
264
-                    fmts->formats[0]   = format;
265
-                    fmts->format_count = 1;
266
-                    ret = 1;
267
-                    break;
268
-                }
269
-        }
270
-    }
271 315
     return ret;
272 316
 }
273 317
 
... ...
@@ -283,18 +361,121 @@ static void reduce_formats(AVFilterGraph *graph)
283 283
     } while (reduced);
284 284
 }
285 285
 
286
-static void pick_formats(AVFilterGraph *graph)
286
+static void swap_samplerates_on_filter(AVFilterContext *filter)
287
+{
288
+    AVFilterLink *link = NULL;
289
+    int sample_rate;
290
+    int i, j;
291
+
292
+    for (i = 0; i < filter->input_count; i++) {
293
+        link = filter->inputs[i];
294
+
295
+        if (link->type == AVMEDIA_TYPE_AUDIO &&
296
+            link->out_samplerates->format_count == 1)
297
+            break;
298
+    }
299
+    if (i == filter->input_count)
300
+        return;
301
+
302
+    sample_rate = link->out_samplerates->formats[0];
303
+
304
+    for (i = 0; i < filter->output_count; i++) {
305
+        AVFilterLink *outlink = filter->outputs[i];
306
+        int best_idx, best_diff = INT_MAX;
307
+
308
+        if (outlink->type != AVMEDIA_TYPE_AUDIO ||
309
+            outlink->in_samplerates->format_count < 2)
310
+            continue;
311
+
312
+        for (j = 0; j < outlink->in_samplerates->format_count; j++) {
313
+            int diff = abs(sample_rate - outlink->in_samplerates->formats[j]);
314
+
315
+            if (diff < best_diff) {
316
+                best_diff = diff;
317
+                best_idx  = j;
318
+            }
319
+        }
320
+        FFSWAP(int, outlink->in_samplerates->formats[0],
321
+               outlink->in_samplerates->formats[best_idx]);
322
+    }
323
+}
324
+
325
+static void swap_samplerates(AVFilterGraph *graph)
326
+{
327
+    int i;
328
+
329
+    for (i = 0; i < graph->filter_count; i++)
330
+        swap_samplerates_on_filter(graph->filters[i]);
331
+}
332
+
333
+static void swap_channel_layouts_on_filter(AVFilterContext *filter)
287 334
 {
335
+    AVFilterLink *link = NULL;
336
+    uint64_t chlayout;
288 337
     int i, j;
289 338
 
339
+    for (i = 0; i < filter->input_count; i++) {
340
+        link = filter->inputs[i];
341
+
342
+        if (link->type == AVMEDIA_TYPE_AUDIO &&
343
+            link->out_channel_layouts->nb_channel_layouts == 1)
344
+            break;
345
+    }
346
+    if (i == filter->input_count)
347
+        return;
348
+
349
+    chlayout = link->out_channel_layouts->channel_layouts[0];
350
+
351
+    for (i = 0; i < filter->output_count; i++) {
352
+        AVFilterLink *outlink = filter->outputs[i];
353
+        int best_idx, best_score = INT_MIN;
354
+
355
+        if (outlink->type != AVMEDIA_TYPE_AUDIO ||
356
+            outlink->in_channel_layouts->nb_channel_layouts < 2)
357
+            continue;
358
+
359
+        for (j = 0; j < outlink->in_channel_layouts->nb_channel_layouts; j++) {
360
+            uint64_t out_chlayout = outlink->in_channel_layouts->channel_layouts[j];
361
+            int matched_channels  = av_get_channel_layout_nb_channels(chlayout &
362
+                                                                      out_chlayout);
363
+            int extra_channels     = av_get_channel_layout_nb_channels(out_chlayout &
364
+                                                                       (~chlayout));
365
+            int score = matched_channels - extra_channels;
366
+
367
+            if (score > best_score) {
368
+                best_score = score;
369
+                best_idx   = j;
370
+            }
371
+        }
372
+        FFSWAP(uint64_t, outlink->in_channel_layouts->channel_layouts[0],
373
+               outlink->in_channel_layouts->channel_layouts[best_idx]);
374
+    }
375
+
376
+}
377
+
378
+static void swap_channel_layouts(AVFilterGraph *graph)
379
+{
380
+    int i;
381
+
382
+    for (i = 0; i < graph->filter_count; i++)
383
+        swap_channel_layouts_on_filter(graph->filters[i]);
384
+}
385
+
386
+static int pick_formats(AVFilterGraph *graph)
387
+{
388
+    int i, j, ret;
389
+
290 390
     for (i = 0; i < graph->filter_count; i++) {
291 391
         AVFilterContext *filter = graph->filters[i];
292 392
 
293 393
         for (j = 0; j < filter->input_count; j++)
294
-            pick_format(filter->inputs[j]);
394
+            if ((ret = pick_format(filter->inputs[j])) < 0)
395
+                return ret;
295 396
         for (j = 0; j < filter->output_count; j++)
296
-            pick_format(filter->outputs[j]);
397
+            if ((ret = pick_format(filter->outputs[j])) < 0)
398
+                return ret;
297 399
     }
400
+    return 0;
298 401
 }
299 402
 
300 403
 int ff_avfilter_graph_config_formats(AVFilterGraph *graph, AVClass *log_ctx)
... ...
@@ -310,7 +491,13 @@ int ff_avfilter_graph_config_formats(AVFilterGraph *graph, AVClass *log_ctx)
310 310
      * of format conversion inside filters */
311 311
     reduce_formats(graph);
312 312
 
313
-    pick_formats(graph);
313
+    /* for audio filters, ensure the best sample rate and channel layout
314
+     * is selected */
315
+    swap_samplerates(graph);
316
+    swap_channel_layouts(graph);
317
+
318
+    if ((ret = pick_formats(graph)) < 0)
319
+        return ret;
314 320
 
315 321
     return 0;
316 322
 }
... ...
@@ -25,6 +25,7 @@
25 25
 
26 26
 #include "avfilter.h"
27 27
 #include "internal.h"
28
+#include "formats.h"
28 29
 
29 30
 /* TODO: buffer pool.  see comment for avfilter_default_get_video_buffer() */
30 31
 void ff_avfilter_default_free_buffer(AVFilterBuffer *ptr)
... ...
@@ -112,9 +113,6 @@ int avfilter_default_config_output_link(AVFilterLink *link)
112 112
             link->w = link->src->inputs[0]->w;
113 113
             link->h = link->src->inputs[0]->h;
114 114
             link->time_base = link->src->inputs[0]->time_base;
115
-        } else if (link->type == AVMEDIA_TYPE_AUDIO) {
116
-            link->channel_layout = link->src->inputs[0]->channel_layout;
117
-            link->sample_rate    = link->src->inputs[0]->sample_rate;
118 115
         }
119 116
     } else {
120 117
         /* XXX: any non-simple filter which would cause this branch to be taken
... ...
@@ -125,36 +123,53 @@ int avfilter_default_config_output_link(AVFilterLink *link)
125 125
     return 0;
126 126
 }
127 127
 
128
+#define SET_COMMON_FORMATS(ctx, fmts, in_fmts, out_fmts, ref, list) \
129
+{                                                                   \
130
+    int count = 0, i;                                               \
131
+                                                                    \
132
+    for (i = 0; i < ctx->input_count; i++) {                        \
133
+        if (ctx->inputs[i]) {                                       \
134
+            ref(fmts, &ctx->inputs[i]->out_fmts);                   \
135
+            count++;                                                \
136
+        }                                                           \
137
+    }                                                               \
138
+    for (i = 0; i < ctx->output_count; i++) {                       \
139
+        if (ctx->outputs[i]) {                                      \
140
+            ref(fmts, &ctx->outputs[i]->in_fmts);                   \
141
+            count++;                                                \
142
+        }                                                           \
143
+    }                                                               \
144
+                                                                    \
145
+    if (!count) {                                                   \
146
+        av_freep(&fmts->list);                                      \
147
+        av_freep(&fmts->refs);                                      \
148
+        av_freep(&fmts);                                            \
149
+    }                                                               \
150
+}
151
+
152
+void ff_set_common_channel_layouts(AVFilterContext *ctx,
153
+                                   AVFilterChannelLayouts *layouts)
154
+{
155
+    SET_COMMON_FORMATS(ctx, layouts, in_channel_layouts, out_channel_layouts,
156
+                       ff_channel_layouts_ref, channel_layouts);
157
+}
158
+
159
+void ff_set_common_samplerates(AVFilterContext *ctx,
160
+                               AVFilterFormats *samplerates)
161
+{
162
+    SET_COMMON_FORMATS(ctx, samplerates, in_samplerates, out_samplerates,
163
+                       avfilter_formats_ref, formats);
164
+}
165
+
128 166
 /**
129 167
  * A helper for query_formats() which sets all links to the same list of
130 168
  * formats. If there are no links hooked to this filter, the list of formats is
131 169
  * freed.
132
- *
133
- * FIXME: this will need changed for filters with a mix of pad types
134
- * (video + audio, etc)
135 170
  */
136 171
 void avfilter_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats)
137 172
 {
138
-    int count = 0, i;
139
-
140
-    for (i = 0; i < ctx->input_count; i++) {
141
-        if (ctx->inputs[i]) {
142
-            avfilter_formats_ref(formats, &ctx->inputs[i]->out_formats);
143
-            count++;
144
-        }
145
-    }
146
-    for (i = 0; i < ctx->output_count; i++) {
147
-        if (ctx->outputs[i]) {
148
-            avfilter_formats_ref(formats, &ctx->outputs[i]->in_formats);
149
-            count++;
150
-        }
151
-    }
152
-
153
-    if (!count) {
154
-        av_free(formats->formats);
155
-        av_free(formats->refs);
156
-        av_free(formats);
157
-    }
173
+    SET_COMMON_FORMATS(ctx, formats, in_formats, out_formats,
174
+                       avfilter_formats_ref, formats);
158 175
 }
159 176
 
160 177
 int avfilter_default_query_formats(AVFilterContext *ctx)
... ...
@@ -164,6 +179,11 @@ int avfilter_default_query_formats(AVFilterContext *ctx)
164 164
                             AVMEDIA_TYPE_VIDEO;
165 165
 
166 166
     avfilter_set_common_formats(ctx, avfilter_all_formats(type));
167
+    if (type == AVMEDIA_TYPE_AUDIO) {
168
+        ff_set_common_channel_layouts(ctx, ff_all_channel_layouts());
169
+        ff_set_common_samplerates(ctx, ff_all_samplerates());
170
+    }
171
+
167 172
     return 0;
168 173
 }
169 174