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.
This commit is contained in:
wm4 2015-06-12 19:23:46 +02:00
parent 55624a70ee
commit afdc060bb3
2 changed files with 46 additions and 15 deletions

View File

@ -234,29 +234,45 @@ bool mp_chmap_sel_fallback(const struct mp_chmap_sel *s, struct mp_chmap *map)
return true; return true;
} }
struct mp_chmap best = {0}; struct mp_chmap best_of_best = {0};
for (int n = 0; n < s->num_chmaps; n++) { for (int i = -1; i < (int)MP_ARRAY_SIZE(speaker_replacements); i++) {
struct mp_chmap e = s->chmaps[n]; struct mp_chmap best = {0};
struct mp_chmap t = *map;
if (mp_chmap_is_unknown(&e)) if (i >= 0) {
continue; 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;
// 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)) if (mp_chmap_is_better(&t, &best, &e))
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) { if (best_of_best.num) {
*map = best; *map = best_of_best;
return true; return true;
} }

View File

@ -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"); 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) { int main(void) {
const UnitTest tests[] = { const UnitTest tests[] = {
unit_test(test_mp_chmap_sel_fallback_upmix), 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_no_downmix),
unit_test(test_mp_chmap_sel_fallback_minimal_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_reject_unknown),
unit_test(test_mp_chmap_sel_fallback_more_replacements),
}; };
return run_tests(tests); return run_tests(tests);
} }