diff options
author | wm4 <wm4@nowhere> | 2015-06-27 12:09:30 +0200 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2015-06-27 12:09:30 +0200 |
commit | 09695023165f7527c9bd76bba8b4e1f4e330c25a (patch) | |
tree | 3ef15be23e22b28a7b9189acb209ab92af309472 /audio | |
parent | e0a7e094bc7fae61f1e9086f71a7b452eae08c50 (diff) |
chmap_sel: add a mechanism for preferred conversions
And use it for the mono case. This is slightly more formal and will make
it easier to add more such cases.
Diffstat (limited to 'audio')
-rw-r--r-- | audio/chmap_sel.c | 48 |
1 files changed, 39 insertions, 9 deletions
diff --git a/audio/chmap_sel.c b/audio/chmap_sel.c index 914a3c0da9..292aa8e20b 100644 --- a/audio/chmap_sel.c +++ b/audio/chmap_sel.c @@ -58,6 +58,29 @@ static bool replace_speakers(struct mp_chmap *map, struct mp_chmap list[2]) return false; } +// These go strictly from the first to the second entry and always use the +// full layout (possibly reordered and/or padding channels added). +static const struct mp_chmap preferred_remix[][2] = { + // mono can be perfectly played as stereo + { MP_CHMAP_INIT_MONO, MP_CHMAP_INIT_STEREO }, +}; + +// Conversion from src to dst is explicitly encouraged and should be preferred +// over "mathematical" upmixes or downmixes (which minimize lost channels). +static bool test_preferred_remix(const struct mp_chmap *src, + const struct mp_chmap *dst) +{ + struct mp_chmap src_p = *src, dst_p = *dst; + mp_chmap_remove_na(&src_p); + mp_chmap_remove_na(&dst_p); + for (int n = 0; n < MP_ARRAY_SIZE(preferred_remix); n++) { + if (mp_chmap_equals_reordered(&src_p, &preferred_remix[n][0]) && + mp_chmap_equals_reordered(&dst_p, &preferred_remix[n][1])) + return true; + } + return false; +} + // Allow all channel layouts that can be expressed with mp_chmap. // (By default, all layouts are rejected.) void mp_chmap_sel_add_any(struct mp_chmap_sel *s) @@ -218,6 +241,14 @@ static int mp_chmap_diffn_r(const struct mp_chmap *a, const struct mp_chmap *b) mindiff = d; } + // Special-case: we consider stereo a replacement for mono. (This is not + // true in the other direction. Also, fl-fr is generally not a replacement + // for fc. Thus it's not part of the speaker replacement list.) + struct mp_chmap mono = MP_CHMAP_INIT_MONO; + struct mp_chmap stereo = MP_CHMAP_INIT_STEREO; + if (mp_chmap_equals(&mono, b) && mp_chmap_equals(&stereo, a)) + mindiff = 0; + return mindiff; } @@ -238,6 +269,14 @@ static bool mp_chmap_is_better(struct mp_chmap *req, struct mp_chmap *old, if (mp_chmap_equals(req, new)) return true; + // If there's no exact match, strictly do a preferred conversion. + bool old_pref = test_preferred_remix(req, old); + bool new_pref = test_preferred_remix(req, new); + if (old_pref && !new_pref) + return false; + if (!old_pref && new_pref) + return true; + int old_lost_r = mp_chmap_diffn_r(req, old); // num. channels only in req int new_lost_r = mp_chmap_diffn_r(req, new); @@ -272,15 +311,6 @@ static bool mp_chmap_is_better(struct mp_chmap *req, struct mp_chmap *old, // Determine which channel map to fallback to given a source channel map. bool mp_chmap_sel_fallback(const struct mp_chmap_sel *s, struct mp_chmap *map) { - // special case: if possible always fallback mono to stereo (instead of - // looking for a multichannel upmix) - struct mp_chmap mono = MP_CHMAP_INIT_MONO; - struct mp_chmap stereo = MP_CHMAP_INIT_STEREO; - if (mp_chmap_equals(&mono, map) && test_layout(s, &stereo)) { - *map = stereo; - return true; - } - struct mp_chmap best = {0}; for (int n = 0; n < s->num_chmaps; n++) { |