diff options
author | wm4 <wm4@nowhere> | 2015-11-04 13:50:22 +0100 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2015-11-04 21:48:37 +0100 |
commit | be49da72ea245e2b5227ce4b96b6c2c8f360cfaf (patch) | |
tree | fe5637e5874bb9fec414a3b150930012bc8b5212 /audio/out | |
parent | 46f59f25c23bf9fc4c73fd56b29cc39812bb42a5 (diff) | |
download | mpv-be49da72ea245e2b5227ce4b96b6c2c8f360cfaf.tar.bz2 mpv-be49da72ea245e2b5227ce4b96b6c2c8f360cfaf.tar.xz |
ao_alsa: fix 7.1 over HDMI
We need to effectively swap the last channel pair. See commit 4e358a96
and 5a18c5ea for details.
Doing this seems rather strange, as 7.1 just extends 5.1 with 2 new
speakers, and 5.1 doesn't need this change. Going by the HDMI standard
and the Intel HDA sources (cited in the referenced commits), it also
looks like 7.1 should simply append two channels to 5.1 as well. But
swapping them is apparently correct. This is also what XBMC does. (I
didn't find any other applications doing 7.1 PCM using the ALSA channel
map API. VLC seems to ignore the 7.1 case.) Testing reveals that at
least the end result is correct.
"Normal" ALSA 7.1 is unaffected by this, as it reports a different
(and saner) channel layout.
Diffstat (limited to 'audio/out')
-rw-r--r-- | audio/out/ao_alsa.c | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/audio/out/ao_alsa.c b/audio/out/ao_alsa.c index 3ee39d71de..6c34d6bcc1 100644 --- a/audio/out/ao_alsa.c +++ b/audio/out/ao_alsa.c @@ -284,6 +284,28 @@ static int find_mp_channel(int alsa_channel) return MP_SPEAKER_ID_COUNT; } +#define CHMAP(n, ...) &(struct mp_chmap) MP_CONCAT(MP_CHMAP, n) (__VA_ARGS__) + +// Replace each channel in a with b (a->num == b->num) +static void replace_submap(struct mp_chmap *dst, struct mp_chmap *a, + struct mp_chmap *b) +{ + struct mp_chmap t = *dst; + if (!mp_chmap_is_valid(&t) || mp_chmap_diffn(a, &t) != 0) + return; + assert(a->num == b->num); + for (int n = 0; n < t.num; n++) { + for (int i = 0; i < a->num; i++) { + if (t.speaker[n] == a->speaker[i]) { + t.speaker[n] = b->speaker[i]; + break; + } + } + } + if (mp_chmap_is_valid(&t)) + *dst = t; +} + static bool mp_chmap_from_alsa(struct mp_chmap *dst, snd_pcm_chmap_t *src) { *dst = (struct mp_chmap) {0}; @@ -299,6 +321,10 @@ static bool mp_chmap_from_alsa(struct mp_chmap *dst, snd_pcm_chmap_t *src) if (dst->num == 1) dst->speaker[0] = MP_SP(FC); + // Remap weird Intel HDA HDMI 7.1 layouts correctly. + replace_submap(dst, CHMAP(6, FL, FR, BL, BR, SDL, SDR), + CHMAP(6, FL, FR, SL, SR, BL, BR)); + return mp_chmap_is_valid(dst); } |