History

lavfi: add channel layout/sample rate negotiation.

Anton Khirnov committed 14 years ago

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

Unified · Split

4 files
  1. libavfilter/af_resample.c +11 −0
  2. libavfilter/avfilter.c +15 −6
  3. libavfilter/avfiltergraph.c +222 −35
  4. libavfilter/defaults.c +46 −26
libavfilter/af_resample.c+11−0
@@ -31,6 +31,7 @@ · 30 unmodified lines
3131
3232 #include "audio.h"
3333 #include "avfilter.h"
34+#include "formats.h"
3435 #include "internal.h"
3536
3637 typedef struct ResampleContext {
@@ -56,10 +57,20 @@ static int query_formats(AVFilterContext *ctx) · 19 unmodified lines
5657
5758 AVFilterFormats *in_formats = avfilter_all_formats(AVMEDIA_TYPE_AUDIO);
5859 AVFilterFormats *out_formats = avfilter_all_formats(AVMEDIA_TYPE_AUDIO);
60+ AVFilterFormats *in_samplerates = ff_all_samplerates();
61+ AVFilterFormats *out_samplerates = ff_all_samplerates();
62+ AVFilterChannelLayouts *in_layouts = ff_all_channel_layouts();
63+ AVFilterChannelLayouts *out_layouts = ff_all_channel_layouts();
5964
6065 avfilter_formats_ref(in_formats, &inlink->out_formats);
6166 avfilter_formats_ref(out_formats, &outlink->in_formats);
6267
68+ avfilter_formats_ref(in_samplerates, &inlink->out_samplerates);
69+ avfilter_formats_ref(out_samplerates, &outlink->in_samplerates);
70+
71+ ff_channel_layouts_ref(in_layouts, &inlink->out_channel_layouts);
72+ ff_channel_layouts_ref(out_layouts, &outlink->in_channel_layouts);
73+
6374 return 0;
6475 }
6576
libavfilter/avfilter.c+15−6
@@ -28,6 +28,7 @@ · 27 unmodified lines
2828 #include "libavcodec/avcodec.h"
2929
3030 #include "avfilter.h"
31+#include "formats.h"
3132 #include "internal.h"
3233
3334 unsigned avfilter_version(void) {
@@ -176,6 +177,12 @@ int avfilter_insert_filter(AVFilterLink *link, AVFilterContext *filt, · 142 unmodified lines
176177 if (link->out_formats)
177178 avfilter_formats_changeref(&link->out_formats,
178179 &filt->outputs[filt_dstpad_idx]->out_formats);
180+ if (link->out_samplerates)
181+ avfilter_formats_changeref(&link->out_samplerates,
182+ &filt->outputs[filt_dstpad_idx]->out_samplerates);
183+ if (link->out_channel_layouts)
184+ ff_channel_layouts_changeref(&link->out_channel_layouts,
185+ &filt->outputs[filt_dstpad_idx]->out_channel_layouts);
179186
180187 return 0;
181188 }
@@ -216,12 +223,6 @@ int avfilter_config_links(AVFilterContext *filter) · 34 unmodified lines
216223 link->sample_aspect_ratio = link->src->input_count ?
217224 link->src->inputs[0]->sample_aspect_ratio : (AVRational){1,1};
218225
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−
225226 if ((config_link = link->dstpad->config_props))
226227 if ((ret = config_link(link)) < 0)
227228 return ret;
@@ -614,6 +615,10 @@ void avfilter_free(AVFilterContext *filter) · 386 unmodified lines
614615 link->src->outputs[link->srcpad - link->src->output_pads] = NULL;
615616 avfilter_formats_unref(&link->in_formats);
616617 avfilter_formats_unref(&link->out_formats);
618+ avfilter_formats_unref(&link->in_samplerates);
619+ avfilter_formats_unref(&link->out_samplerates);
620+ ff_channel_layouts_unref(&link->in_channel_layouts);
621+ ff_channel_layouts_unref(&link->out_channel_layouts);
617622 }
618623 av_freep(&link);
619624 }
@@ -623,6 +628,10 @@ void avfilter_free(AVFilterContext *filter) · 3 unmodified lines
623628 link->dst->inputs[link->dstpad - link->dst->input_pads] = NULL;
624629 avfilter_formats_unref(&link->in_formats);
625630 avfilter_formats_unref(&link->out_formats);
631+ avfilter_formats_unref(&link->in_samplerates);
632+ avfilter_formats_unref(&link->out_samplerates);
633+ ff_channel_layouts_unref(&link->in_channel_layouts);
634+ ff_channel_layouts_unref(&link->out_channel_layouts);
626635 }
627636 av_freep(&link);
628637 }
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 }
libavfilter/defaults.c+46−26
@@ -25,6 +25,7 @@ · 24 unmodified lines
2525
2626 #include "avfilter.h"
2727 #include "internal.h"
28+#include "formats.h"
2829
2930 /* TODO: buffer pool. see comment for avfilter_default_get_video_buffer() */
3031 void ff_avfilter_default_free_buffer(AVFilterBuffer *ptr)
@@ -112,9 +113,6 @@ int avfilter_default_config_output_link(AVFilterLink *link) · 81 unmodified lines
112113 link->w = link->src->inputs[0]->w;
113114 link->h = link->src->inputs[0]->h;
114115 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;
118116 }
119117 } else {
120118 /* 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) · 4 unmodified lines
125123 return 0;
126124 }
127125
126+#define SET_COMMON_FORMATS(ctx, fmts, in_fmts, out_fmts, ref, list) \
127+{ \
128+ int count = 0, i; \
129+ \
130+ for (i = 0; i < ctx->input_count; i++) { \
131+ if (ctx->inputs[i]) { \
132+ ref(fmts, &ctx->inputs[i]->out_fmts); \
133+ count++; \
134+ } \
135+ } \
136+ for (i = 0; i < ctx->output_count; i++) { \
137+ if (ctx->outputs[i]) { \
138+ ref(fmts, &ctx->outputs[i]->in_fmts); \
139+ count++; \
140+ } \
141+ } \
142+ \
143+ if (!count) { \
144+ av_freep(&fmts->list); \
145+ av_freep(&fmts->refs); \
146+ av_freep(&fmts); \
147+ } \
148+}
149+
150+void ff_set_common_channel_layouts(AVFilterContext *ctx,
151+ AVFilterChannelLayouts *layouts)
152+{
153+ SET_COMMON_FORMATS(ctx, layouts, in_channel_layouts, out_channel_layouts,
154+ ff_channel_layouts_ref, channel_layouts);
155+}
156+
157+void ff_set_common_samplerates(AVFilterContext *ctx,
158+ AVFilterFormats *samplerates)
159+{
160+ SET_COMMON_FORMATS(ctx, samplerates, in_samplerates, out_samplerates,
161+ avfilter_formats_ref, formats);
162+}
163+
128164 /**
129165 * A helper for query_formats() which sets all links to the same list of
130166 * formats. If there are no links hooked to this filter, the list of formats is
131167 * freed.
132− *
133− * FIXME: this will need changed for filters with a mix of pad types
134− * (video + audio, etc)
135168 */
136169 void avfilter_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats)
137170 {
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− }
171+ SET_COMMON_FORMATS(ctx, formats, in_formats, out_formats,
172+ avfilter_formats_ref, formats);
158173 }
159174
160175 int avfilter_default_query_formats(AVFilterContext *ctx)
@@ -164,6 +179,11 @@ int avfilter_default_query_formats(AVFilterContext *ctx) · 3 unmodified lines
164179 AVMEDIA_TYPE_VIDEO;
165180
166181 avfilter_set_common_formats(ctx, avfilter_all_formats(type));
182+ if (type == AVMEDIA_TYPE_AUDIO) {
183+ ff_set_common_channel_layouts(ctx, ff_all_channel_layouts());
184+ ff_set_common_samplerates(ctx, ff_all_samplerates());
185+ }
186+
167187 return 0;
168188 }
169189

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