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
424 swap_samplerates_on_filter(graph->filters[i]);424 swap_samplerates_on_filter(graph->filters[i]);
425}425}
426 426
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 */
437static 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
427static void swap_channel_layouts_on_filter(AVFilterContext *filter)461static void swap_channel_layouts_on_filter(AVFilterContext *filter)
428{462{
429 AVFilterLink *link = NULL;463 AVFilterLink *link = NULL;
430 uint64_t chlayout;464 int i, j, k;
431 int i, j;
432 465
433 for (i = 0; i < filter->nb_inputs; i++) {466 for (i = 0; i < filter->nb_inputs; i++) {
434 link = filter->inputs[i];467 link = filter->inputs[i];
@@ -440,27 +473,55 @@ static void swap_channel_layouts_on_filter(AVFilterContext *filter) · 5 unmodified lines
440 if (i == filter->nb_inputs)473 if (i == filter->nb_inputs)
441 return;474 return;
442 475
443 chlayout = link->out_channel_layouts->channel_layouts[0];
444
445 for (i = 0; i < filter->nb_outputs; i++) {476 for (i = 0; i < filter->nb_outputs; i++) {
446 AVFilterLink *outlink = filter->outputs[i];477 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;
448 479
449 if (outlink->type != AVMEDIA_TYPE_AUDIO ||480 if (outlink->type != AVMEDIA_TYPE_AUDIO ||
450 outlink->in_channel_layouts->nb_channel_layouts < 2)481 outlink->in_channel_layouts->nb_channel_layouts < 2)
451 continue;482 continue;
452 483
453 for (j = 0; j < outlink->in_channel_layouts->nb_channel_layouts; j++) {484 for (j = 0; j < outlink->in_channel_layouts->nb_channel_layouts; j++) {
485 uint64_t in_chlayout = link->out_channel_layouts->channel_layouts[0];
454 uint64_t out_chlayout = outlink->in_channel_layouts->channel_layouts[j];486 uint64_t out_chlayout = outlink->in_channel_layouts->channel_layouts[j];
455 int matched_channels = av_get_channel_layout_nb_channels(chlayout &487 int in_channels = av_get_channel_layout_nb_channels(in_chlayout);
456 out_chlayout);488 int out_channels = av_get_channel_layout_nb_channels(out_chlayout);
457 int extra_channels = av_get_channel_layout_nb_channels(out_chlayout &489 int count_diff = out_channels - in_channels;
458 (~chlayout));490 int matched_channels, extra_channels;
459 int score = 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 }
460 506
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)) {
462 best_score = score;522 best_score = score;
463 best_idx = j;523 best_idx = j;
524 best_count_diff = count_diff;
464 }525 }
465 }526 }
466 FFSWAP(uint64_t, outlink->in_channel_layouts->channel_layouts[0],527 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