summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--audio/chmap_sel.c50
-rw-r--r--test/chmap_sel.c15
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);
}