From bf014677cecbc5ff425f0ad9f23e41c19be4ad3d Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 6 Apr 2013 23:36:00 +0200 Subject: ao_pulse: try to set correct channel layout Like most other AOs, ao_pulse set the channel count only, always using a default layout. Try to set the exact layout. For this, we need a big lookup table to map waveex/lavc/mpv speaker position to PulseAudio's, since PA_CHANNEL_POSITION_ is apparently not compatible to waveext, and I haven't seen any API functions that would help mapping them. Completely untested. (Let's leave that to someone else...) --- audio/out/ao_pulse.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-) (limited to 'audio') diff --git a/audio/out/ao_pulse.c b/audio/out/ao_pulse.c index 7f3619386e..dedb067357 100644 --- a/audio/out/ao_pulse.c +++ b/audio/out/ao_pulse.c @@ -143,6 +143,50 @@ static const struct format_map { {AF_FORMAT_UNKNOWN, 0} }; +static const int speaker_map[][2] = { + {PA_CHANNEL_POSITION_MONO, MP_SPEAKER_ID_FC}, + {PA_CHANNEL_POSITION_FRONT_LEFT, MP_SPEAKER_ID_FL}, + {PA_CHANNEL_POSITION_FRONT_RIGHT, MP_SPEAKER_ID_FR}, + {PA_CHANNEL_POSITION_FRONT_CENTER, MP_SPEAKER_ID_FC}, + {PA_CHANNEL_POSITION_REAR_CENTER, MP_SPEAKER_ID_BC}, + {PA_CHANNEL_POSITION_REAR_LEFT, MP_SPEAKER_ID_BL}, + {PA_CHANNEL_POSITION_REAR_RIGHT, MP_SPEAKER_ID_BR}, + {PA_CHANNEL_POSITION_LFE, MP_SPEAKER_ID_LFE}, + {PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER, MP_SPEAKER_ID_FLC}, + {PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER, MP_SPEAKER_ID_FRC}, + {PA_CHANNEL_POSITION_SIDE_LEFT, MP_SPEAKER_ID_SL}, + {PA_CHANNEL_POSITION_SIDE_RIGHT, MP_SPEAKER_ID_SR}, + {PA_CHANNEL_POSITION_TOP_CENTER, MP_SPEAKER_ID_TC}, + {PA_CHANNEL_POSITION_TOP_FRONT_LEFT, MP_SPEAKER_ID_TFL}, + {PA_CHANNEL_POSITION_TOP_FRONT_RIGHT, MP_SPEAKER_ID_TFR}, + {PA_CHANNEL_POSITION_TOP_FRONT_CENTER, MP_SPEAKER_ID_TFC}, + {PA_CHANNEL_POSITION_TOP_REAR_LEFT, MP_SPEAKER_ID_TBL}, + {PA_CHANNEL_POSITION_TOP_REAR_RIGHT, MP_SPEAKER_ID_TBR}, + {PA_CHANNEL_POSITION_TOP_REAR_CENTER, MP_SPEAKER_ID_TBC}, + {PA_CHANNEL_POSITION_INVALID, -1} +}; + +static bool chmap_pa_from_mp(pa_channel_map *dst, struct mp_chmap *src) +{ + if (src->num > PA_CHANNELS_MAX) + return false; + dst->channels = src->num; + for (int n = 0; n < src->num; n++) { + int mp_speaker = src->speaker[n]; + int pa_speaker = PA_CHANNEL_POSITION_INVALID; + for (int i = 0; speaker_map[i][1] != -1; i++) { + if (speaker_map[i][1] == mp_speaker) { + pa_speaker = speaker_map[i][0]; + break; + } + } + if (pa_speaker == PA_CHANNEL_POSITION_INVALID) + return false; + dst->map[n] = pa_speaker; + } + return true; +} + static void uninit(struct ao *ao, bool cut_audio) { struct priv *priv = ao->priv; @@ -230,8 +274,16 @@ static int init(struct ao *ao, char *params) goto fail; } - mp_chmap_reorder_to_waveext(&ao->channels); - pa_channel_map_init_auto(&map, ss.channels, PA_CHANNEL_MAP_WAVEEX); + if (!chmap_pa_from_mp(&map, &ao->channels)) { + char *name = mp_chmap_to_str(&ao->channels); + mp_msg(MSGT_AO, MSGL_ERR, "AO: [pulse] Can't map %s channel layout\n", + name); + talloc_free(name); + // Not a really good fallback, since this doesn't trigger if the + // channel map is valid, but unsupported by the output device. + ao->channels = (struct mp_chmap) MP_CHMAP_INIT_STEREO; + pa_channel_map_init_stereo(&map); + } ao->bps = pa_bytes_per_second(&ss); -- cgit v1.2.3