From afdc060bb3d2558130e48a76a0a342be034e294c Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 12 Jun 2015 19:23:46 +0200 Subject: chmap_sel: improve speaker replacement handling This didn't really work since the last time the channel map fallback code was touched. In some cases, quite bad results were selected. --- audio/chmap_sel.c | 50 +++++++++++++++++++++++++++++++++----------------- test/chmap_sel.c | 15 +++++++++++++++ 2 files changed, 48 insertions(+), 17 deletions(-) diff --git a/audio/chmap_sel.c b/audio/chmap_sel.c index 855d0dc683..d1f6f2eee0 100644 --- a/audio/chmap_sel.c +++ b/audio/chmap_sel.c @@ -234,29 +234,45 @@ bool mp_chmap_sel_fallback(const struct mp_chmap_sel *s, struct mp_chmap *map) return true; } - struct mp_chmap best = {0}; + struct mp_chmap best_of_best = {0}; + + for (int i = -1; i < (int)MP_ARRAY_SIZE(speaker_replacements); i++) { + struct mp_chmap best = {0}; + struct mp_chmap t = *map; + + if (i >= 0) { + struct mp_chmap *r = (struct mp_chmap *)speaker_replacements[i]; + if (!replace_speakers(&t, r)) + continue; + } + + for (int n = 0; n < s->num_chmaps; n++) { + struct mp_chmap e = s->chmaps[n]; + + if (mp_chmap_is_unknown(&e)) + continue; - for (int n = 0; n < s->num_chmaps; n++) { - struct mp_chmap e = s->chmaps[n]; - - if (mp_chmap_is_unknown(&e)) - continue; - - // in case we didn't match any fallback retry after replacing speakers - for (int i = -1; i < (int)MP_ARRAY_SIZE(speaker_replacements); i++) { - struct mp_chmap t = *map; - if (i >= 0) { - struct mp_chmap *r = (struct mp_chmap *)speaker_replacements[i]; - if (!replace_speakers(&t, r)) - continue; - } if (mp_chmap_is_better(&t, &best, &e)) best = e; } + + if (best.num) { + if (best_of_best.num) { + // If best (without replacements) is not worse, but is actually + // better with replacements applied, pick it. + int bbest_lost = mp_chmap_diffn(map, &best_of_best); + int best_lost = mp_chmap_diffn(map, &best); + int repl_lost = mp_chmap_diffn(&t, &best); + if (best_lost <= bbest_lost && repl_lost < bbest_lost) + best_of_best = best; + } else { + best_of_best = best; + } + } } - if (best.num) { - *map = best; + if (best_of_best.num) { + *map = best_of_best; return true; } diff --git a/test/chmap_sel.c b/test/chmap_sel.c index 914e00368f..928320058c 100644 --- a/test/chmap_sel.c +++ b/test/chmap_sel.c @@ -87,6 +87,20 @@ static void test_mp_chmap_sel_fallback_reject_unknown(void **state) { assert_string_equal(mp_chmap_to_str(&b), "5.1"); } +static void test_mp_chmap_sel_fallback_more_replacements(void **state) { + test_sel("quad", "quad(side)", LAYOUTS("quad(side)", "stereo")); + test_sel("quad", "7.0", LAYOUTS("quad(side)", "7.0")); + test_sel("quad", "7.0", LAYOUTS("7.0", "quad(side)")); + test_sel("quad", "7.1(wide-side)", LAYOUTS("7.1(wide-side)", "stereo")); + test_sel("quad", "7.1(wide-side)", LAYOUTS("stereo", "7.1(wide-side)")); + test_sel("quad", "fl-fr-fc-bl-br", + LAYOUTS("fl-fr-fc-bl-br", "fl-fr-sl-sr")); + test_sel("quad", "fl-fr-bl-br-na-na-na-na", + LAYOUTS("fl-fr-bl-br-na-na-na-na", "quad(side)", "stereo")); + test_sel("quad", "fl-fr-bl-br-na-na-na-na", + LAYOUTS("stereo", "quad(side)", "fl-fr-bl-br-na-na-na-na")); +} + int main(void) { const UnitTest tests[] = { unit_test(test_mp_chmap_sel_fallback_upmix), @@ -101,6 +115,7 @@ int main(void) { unit_test(test_mp_chmap_sel_fallback_no_downmix), unit_test(test_mp_chmap_sel_fallback_minimal_downmix), unit_test(test_mp_chmap_sel_fallback_reject_unknown), + unit_test(test_mp_chmap_sel_fallback_more_replacements), }; return run_tests(tests); } -- cgit v1.2.3