History

lavfi: better channel layout negotiation

Allow substitution of channel pairs in the input for nearby channel pairs in the output in order to get a closer match. Also weigh LFE channel mismatch differently to favor matching the same layout without LFE over one less channel with LFE.

Justin Ruggles committed 14 years ago

Commit 743f0701 parent 81f548d1 file · +72 −11Browse files

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

Unified · Split

libavfilter/avfiltergraph.c+72−11
@@ -424,11 +424,44 @@ static void swap_samplerates(AVFilterGraph *graph) · 423 unmodified lines
424424 swap_samplerates_on_filter(graph->filters[i]);
425425 }
426426
427+#define CH_CENTER_PAIR (AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER)
428+#define CH_FRONT_PAIR (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT)
429+#define CH_STEREO_PAIR (AV_CH_STEREO_LEFT | AV_CH_STEREO_RIGHT)
430+#define CH_WIDE_PAIR (AV_CH_WIDE_LEFT | AV_CH_WIDE_RIGHT)
431+#define CH_SIDE_PAIR (AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT)
432+#define CH_DIRECT_PAIR (AV_CH_SURROUND_DIRECT_LEFT | AV_CH_SURROUND_DIRECT_RIGHT)
433+#define CH_BACK_PAIR (AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT)
434+
435+/* allowable substitutions for channel pairs when comparing layouts,
436+ * ordered by priority for both values */
437+static const uint64_t ch_subst[][2] = {
438+ { CH_FRONT_PAIR, CH_CENTER_PAIR },
439+ { CH_FRONT_PAIR, CH_WIDE_PAIR },
440+ { CH_FRONT_PAIR, AV_CH_FRONT_CENTER },
441+ { CH_CENTER_PAIR, CH_FRONT_PAIR },
442+ { CH_CENTER_PAIR, CH_WIDE_PAIR },
443+ { CH_CENTER_PAIR, AV_CH_FRONT_CENTER },
444+ { CH_WIDE_PAIR, CH_FRONT_PAIR },
445+ { CH_WIDE_PAIR, CH_CENTER_PAIR },
446+ { CH_WIDE_PAIR, AV_CH_FRONT_CENTER },
447+ { AV_CH_FRONT_CENTER, CH_FRONT_PAIR },
448+ { AV_CH_FRONT_CENTER, CH_CENTER_PAIR },
449+ { AV_CH_FRONT_CENTER, CH_WIDE_PAIR },
450+ { CH_SIDE_PAIR, CH_DIRECT_PAIR },
451+ { CH_SIDE_PAIR, CH_BACK_PAIR },
452+ { CH_SIDE_PAIR, AV_CH_BACK_CENTER },
453+ { CH_BACK_PAIR, CH_DIRECT_PAIR },
454+ { CH_BACK_PAIR, CH_SIDE_PAIR },
455+ { CH_BACK_PAIR, AV_CH_BACK_CENTER },
456+ { AV_CH_BACK_CENTER, CH_BACK_PAIR },
457+ { AV_CH_BACK_CENTER, CH_DIRECT_PAIR },
458+ { AV_CH_BACK_CENTER, CH_SIDE_PAIR },
459+};
460+
427461 static void swap_channel_layouts_on_filter(AVFilterContext *filter)
428462 {
429463 AVFilterLink *link = NULL;
430− uint64_t chlayout;
431− int i, j;
464+ int i, j, k;
432465
433466 for (i = 0; i < filter->nb_inputs; i++) {
434467 link = filter->inputs[i];
@@ -440,27 +473,55 @@ static void swap_channel_layouts_on_filter(AVFilterContext *filter) · 5 unmodified lines
440473 if (i == filter->nb_inputs)
441474 return;
442475
443− chlayout = link->out_channel_layouts->channel_layouts[0];
444−
445476 for (i = 0; i < filter->nb_outputs; i++) {
446477 AVFilterLink *outlink = filter->outputs[i];
447− int best_idx, best_score = INT_MIN;
478+ int best_idx, best_score = INT_MIN, best_count_diff = INT_MAX;
448479
449480 if (outlink->type != AVMEDIA_TYPE_AUDIO ||
450481 outlink->in_channel_layouts->nb_channel_layouts < 2)
451482 continue;
452483
453484 for (j = 0; j < outlink->in_channel_layouts->nb_channel_layouts; j++) {
485+ uint64_t in_chlayout = link->out_channel_layouts->channel_layouts[0];
454486 uint64_t out_chlayout = outlink->in_channel_layouts->channel_layouts[j];
455− int matched_channels = av_get_channel_layout_nb_channels(chlayout &
456− out_chlayout);
457− int extra_channels = av_get_channel_layout_nb_channels(out_chlayout &
458− (~chlayout));
459− int score = matched_channels - extra_channels;
487+ int in_channels = av_get_channel_layout_nb_channels(in_chlayout);
488+ int out_channels = av_get_channel_layout_nb_channels(out_chlayout);
489+ int count_diff = out_channels - in_channels;
490+ int matched_channels, extra_channels;
491+ int score = 0;
492+
493+ /* channel substitution */
494+ for (k = 0; k < FF_ARRAY_ELEMS(ch_subst); k++) {
495+ uint64_t cmp0 = ch_subst[k][0];
496+ uint64_t cmp1 = ch_subst[k][1];
497+ if (( in_chlayout & cmp0) && (!(out_chlayout & cmp0)) &&
498+ (out_chlayout & cmp1) && (!( in_chlayout & cmp1))) {
499+ in_chlayout &= ~cmp0;
500+ out_chlayout &= ~cmp1;
501+ /* add score for channel match, minus a deduction for
502+ having to do the substitution */
503+ score += 10 * av_get_channel_layout_nb_channels(cmp1) - 2;
504+ }
505+ }
460506
461− if (score > best_score) {
507+ /* no penalty for LFE channel mismatch */
508+ if ( (in_chlayout & AV_CH_LOW_FREQUENCY) &&
509+ (out_chlayout & AV_CH_LOW_FREQUENCY))
510+ score += 10;
511+ in_chlayout &= ~AV_CH_LOW_FREQUENCY;
512+ out_chlayout &= ~AV_CH_LOW_FREQUENCY;
513+
514+ matched_channels = av_get_channel_layout_nb_channels(in_chlayout &
515+ out_chlayout);
516+ extra_channels = av_get_channel_layout_nb_channels(out_chlayout &
517+ (~in_chlayout));
518+ score += 10 * matched_channels - 5 * extra_channels;
519+
520+ if (score > best_score ||
521+ (count_diff < best_count_diff && score == best_score)) {
462522 best_score = score;
463523 best_idx = j;
524+ best_count_diff = count_diff;
464525 }
465526 }
466527 FFSWAP(uint64_t, outlink->in_channel_layouts->channel_layouts[0],

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