History

lavfi: add channel layout/sample rate negotiation.

Anton Khirnov committed 14 years ago

Commit ff1f51a1 parent 5775a184 files · +294 −67Browse files

Showing the changes to libavfilter/avfiltergraph.c (1 of 4 files). Show all

Unified · Split

libavfilter/avfiltergraph.c+222−35
@@ -25,8 +25,10 @@ · 24 unmodified lines
2525
2626 #include "avfilter.h"
2727 #include "avfiltergraph.h"
28+#include "formats.h"
2829 #include "internal.h"
2930
31+#include "libavutil/audioconvert.h"
3032 #include "libavutil/log.h"
3133
3234 static const AVClass filtergraph_class = {
@@ -168,9 +170,27 @@ static int query_formats(AVFilterGraph *graph, AVClass *log_ctx) · 135 unmodified lines
168170
169171 for (j = 0; j < filter->input_count; j++) {
170172 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)) {
173+ int convert_needed = 0;
174+
175+ if (!link)
176+ continue;
177+
178+ if (link->in_formats != link->out_formats &&
179+ !avfilter_merge_formats(link->in_formats,
180+ link->out_formats))
181+ convert_needed = 1;
182+ if (link->type == AVMEDIA_TYPE_AUDIO) {
183+ if (link->in_channel_layouts != link->out_channel_layouts &&
184+ !ff_merge_channel_layouts(link->in_channel_layouts,
185+ link->out_channel_layouts))
186+ convert_needed = 1;
187+ if (link->in_samplerates != link->out_samplerates &&
188+ !ff_merge_samplerates(link->in_samplerates,
189+ link->out_samplerates))
190+ convert_needed = 1;
191+ }
192+
193+ if (convert_needed) {
174194 AVFilterContext *convert;
175195 AVFilter *filter;
176196 AVFilterLink *inlink, *outlink;
@@ -214,13 +234,27 @@ static int query_formats(AVFilterGraph *graph, AVClass *log_ctx) · 37 unmodified lines
214234 inlink = convert->inputs[0];
215235 outlink = convert->outputs[0];
216236 if (!avfilter_merge_formats( inlink->in_formats, inlink->out_formats) ||
217− !avfilter_merge_formats(outlink->in_formats, outlink->out_formats)) {
237+ !avfilter_merge_formats(outlink->in_formats, outlink->out_formats))
238+ ret |= AVERROR(ENOSYS);
239+ if (inlink->type == AVMEDIA_TYPE_AUDIO &&
240+ (!ff_merge_samplerates(inlink->in_samplerates,
241+ inlink->out_samplerates) ||
242+ !ff_merge_channel_layouts(inlink->in_channel_layouts,
243+ inlink->out_channel_layouts)))
244+ ret |= AVERROR(ENOSYS);
245+ if (outlink->type == AVMEDIA_TYPE_AUDIO &&
246+ (!ff_merge_samplerates(outlink->in_samplerates,
247+ outlink->out_samplerates) ||
248+ !ff_merge_channel_layouts(outlink->in_channel_layouts,
249+ outlink->out_channel_layouts)))
250+ ret |= AVERROR(ENOSYS);
251+
252+ if (ret < 0) {
218253 av_log(log_ctx, AV_LOG_ERROR,
219254 "Impossible to convert between the formats supported by the filter "
220255 "'%s' and the filter '%s'\n", link->src->name, link->dst->name);
221− return AVERROR(EINVAL);
256+ return ret;
222257 }
223− }
224258 }
225259 }
226260 }
@@ -228,46 +262,90 @@ static int query_formats(AVFilterGraph *graph, AVClass *log_ctx) · 1 unmodified line
228262 return 0;
229263 }
230264
231−static void pick_format(AVFilterLink *link)
265+static int pick_format(AVFilterLink *link)
232266 {
233267 if (!link || !link->in_formats)
234− return;
268+ return 0;
235269
236270 link->in_formats->format_count = 1;
237271 link->format = link->in_formats->formats[0];
238272
273+ if (link->type == AVMEDIA_TYPE_AUDIO) {
274+ if (!link->in_samplerates->format_count) {
275+ av_log(link->src, AV_LOG_ERROR, "Cannot select sample rate for"
276+ " the link between filters %s and %s.\n", link->src->name,
277+ link->dst->name);
278+ return AVERROR(EINVAL);
279+ }
280+ link->in_samplerates->format_count = 1;
281+ link->sample_rate = link->in_samplerates->formats[0];
282+
283+ if (!link->in_channel_layouts->nb_channel_layouts) {
284+ av_log(link->src, AV_LOG_ERROR, "Cannot select channel layout for"
285+ "the link between filters %s and %s.\n", link->src->name,
286+ link->dst->name);
287+ return AVERROR(EINVAL);
288+ }
289+ link->in_channel_layouts->nb_channel_layouts = 1;
290+ link->channel_layout = link->in_channel_layouts->channel_layouts[0];
291+ }
292+
239293 avfilter_formats_unref(&link->in_formats);
240294 avfilter_formats_unref(&link->out_formats);
295+ avfilter_formats_unref(&link->in_samplerates);
296+ avfilter_formats_unref(&link->out_samplerates);
297+ ff_channel_layouts_unref(&link->in_channel_layouts);
298+ ff_channel_layouts_unref(&link->out_channel_layouts);
299+
300+ return 0;
241301 }
242302
303+#define REDUCE_FORMATS(fmt_type, list_type, list, var, nb, add_format) \
304+do { \
305+ for (i = 0; i < filter->input_count; i++) { \
306+ AVFilterLink *link = filter->inputs[i]; \
307+ fmt_type fmt; \
308+ \
309+ if (!link->out_ ## list || link->out_ ## list->nb != 1) \
310+ continue; \
311+ fmt = link->out_ ## list->var[0]; \
312+ \
313+ for (j = 0; j < filter->output_count; j++) { \
314+ AVFilterLink *out_link = filter->outputs[j]; \
315+ list_type *fmts; \
316+ \
317+ if (link->type != out_link->type || \
318+ out_link->in_ ## list->nb == 1) \
319+ continue; \
320+ fmts = out_link->in_ ## list; \
321+ \
322+ if (!out_link->in_ ## list->nb) { \
323+ add_format(&out_link->in_ ##list, fmt); \
324+ break; \
325+ } \
326+ \
327+ for (k = 0; k < out_link->in_ ## list->nb; k++) \
328+ if (fmts->var[k] == fmt) { \
329+ fmts->var[0] = fmt; \
330+ fmts->nb = 1; \
331+ ret = 1; \
332+ break; \
333+ } \
334+ } \
335+ } \
336+} while (0)
337+
243338 static int reduce_formats_on_filter(AVFilterContext *filter)
244339 {
245340 int i, j, k, ret = 0;
246341
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;
342+ REDUCE_FORMATS(int, AVFilterFormats, formats, formats,
343+ format_count, avfilter_add_format);
344+ REDUCE_FORMATS(int, AVFilterFormats, samplerates, formats,
345+ format_count, avfilter_add_format);
346+ REDUCE_FORMATS(uint64_t, AVFilterChannelLayouts, channel_layouts,
347+ channel_layouts, nb_channel_layouts, ff_add_channel_layout);
257348
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− }
271349 return ret;
272350 }
273351
@@ -283,18 +361,121 @@ static void reduce_formats(AVFilterGraph *graph) · 9 unmodified lines
283361 } while (reduced);
284362 }
285363
286−static void pick_formats(AVFilterGraph *graph)
364+static void swap_samplerates_on_filter(AVFilterContext *filter)
365+{
366+ AVFilterLink *link = NULL;
367+ int sample_rate;
368+ int i, j;
369+
370+ for (i = 0; i < filter->input_count; i++) {
371+ link = filter->inputs[i];
372+
373+ if (link->type == AVMEDIA_TYPE_AUDIO &&
374+ link->out_samplerates->format_count == 1)
375+ break;
376+ }
377+ if (i == filter->input_count)
378+ return;
379+
380+ sample_rate = link->out_samplerates->formats[0];
381+
382+ for (i = 0; i < filter->output_count; i++) {
383+ AVFilterLink *outlink = filter->outputs[i];
384+ int best_idx, best_diff = INT_MAX;
385+
386+ if (outlink->type != AVMEDIA_TYPE_AUDIO ||
387+ outlink->in_samplerates->format_count < 2)
388+ continue;
389+
390+ for (j = 0; j < outlink->in_samplerates->format_count; j++) {
391+ int diff = abs(sample_rate - outlink->in_samplerates->formats[j]);
392+
393+ if (diff < best_diff) {
394+ best_diff = diff;
395+ best_idx = j;
396+ }
397+ }
398+ FFSWAP(int, outlink->in_samplerates->formats[0],
399+ outlink->in_samplerates->formats[best_idx]);
400+ }
401+}
402+
403+static void swap_samplerates(AVFilterGraph *graph)
404+{
405+ int i;
406+
407+ for (i = 0; i < graph->filter_count; i++)
408+ swap_samplerates_on_filter(graph->filters[i]);
409+}
410+
411+static void swap_channel_layouts_on_filter(AVFilterContext *filter)
287412 {
413+ AVFilterLink *link = NULL;
414+ uint64_t chlayout;
288415 int i, j;
289416
417+ for (i = 0; i < filter->input_count; i++) {
418+ link = filter->inputs[i];
419+
420+ if (link->type == AVMEDIA_TYPE_AUDIO &&
421+ link->out_channel_layouts->nb_channel_layouts == 1)
422+ break;
423+ }
424+ if (i == filter->input_count)
425+ return;
426+
427+ chlayout = link->out_channel_layouts->channel_layouts[0];
428+
429+ for (i = 0; i < filter->output_count; i++) {
430+ AVFilterLink *outlink = filter->outputs[i];
431+ int best_idx, best_score = INT_MIN;
432+
433+ if (outlink->type != AVMEDIA_TYPE_AUDIO ||
434+ outlink->in_channel_layouts->nb_channel_layouts < 2)
435+ continue;
436+
437+ for (j = 0; j < outlink->in_channel_layouts->nb_channel_layouts; j++) {
438+ uint64_t out_chlayout = outlink->in_channel_layouts->channel_layouts[j];
439+ int matched_channels = av_get_channel_layout_nb_channels(chlayout &
440+ out_chlayout);
441+ int extra_channels = av_get_channel_layout_nb_channels(out_chlayout &
442+ (~chlayout));
443+ int score = matched_channels - extra_channels;
444+
445+ if (score > best_score) {
446+ best_score = score;
447+ best_idx = j;
448+ }
449+ }
450+ FFSWAP(uint64_t, outlink->in_channel_layouts->channel_layouts[0],
451+ outlink->in_channel_layouts->channel_layouts[best_idx]);
452+ }
453+
454+}
455+
456+static void swap_channel_layouts(AVFilterGraph *graph)
457+{
458+ int i;
459+
460+ for (i = 0; i < graph->filter_count; i++)
461+ swap_channel_layouts_on_filter(graph->filters[i]);
462+}
463+
464+static int pick_formats(AVFilterGraph *graph)
465+{
466+ int i, j, ret;
467+
290468 for (i = 0; i < graph->filter_count; i++) {
291469 AVFilterContext *filter = graph->filters[i];
292470
293471 for (j = 0; j < filter->input_count; j++)
294− pick_format(filter->inputs[j]);
472+ if ((ret = pick_format(filter->inputs[j])) < 0)
473+ return ret;
295474 for (j = 0; j < filter->output_count; j++)
296− pick_format(filter->outputs[j]);
475+ if ((ret = pick_format(filter->outputs[j])) < 0)
476+ return ret;
297477 }
478+ return 0;
298479 }
299480
300481 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) · 9 unmodified lines
310491 * of format conversion inside filters */
311492 reduce_formats(graph);
312493
313− pick_formats(graph);
494+ /* for audio filters, ensure the best sample rate and channel layout
495+ * is selected */
496+ swap_samplerates(graph);
497+ swap_channel_layouts(graph);
498+
499+ if ((ret = pick_formats(graph)) < 0)
500+ return ret;
314501
315502 return 0;
316503 }

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t