diff --git a/modules/audio_output/pipewire.c b/modules/audio_output/pipewire.c index 3c28ce7704..c3f3b045bd 100644 --- a/modules/audio_output/pipewire.c +++ b/modules/audio_output/pipewire.c @@ -446,6 +446,8 @@ static struct vlc_pw_stream *vlc_pw_stream_create(audio_output_t *aout, .channels = fmt->i_channels, }; + enum spa_audio_iec958_codec encoding = SPA_AUDIO_IEC958_CODEC_PCM; /* PCM by default */ + /* Map possible audio output formats */ switch (fmt->i_format) { case VLC_CODEC_FL64: @@ -464,11 +466,29 @@ static struct vlc_pw_stream *vlc_pw_stream_create(audio_output_t *aout, rawfmt.format = SPA_AUDIO_FORMAT_U8; break; case VLC_CODEC_A52: + fmt->i_format = VLC_CODEC_SPDIFL; + fmt->i_bytes_per_frame = 4; + fmt->i_frame_length = 1; + fmt->i_physical_channels = AOUT_CHANS_2_0; + fmt->i_channels = 2; + encoding = SPA_AUDIO_IEC958_CODEC_AC3; + break; case VLC_CODEC_EAC3: + fmt->i_format = VLC_CODEC_SPDIFL; + fmt->i_bytes_per_frame = 4; + fmt->i_frame_length = 1; + fmt->i_physical_channels = AOUT_CHANS_2_0; + fmt->i_channels = 2; + encoding = SPA_AUDIO_IEC958_CODEC_EAC3; + break; case VLC_CODEC_DTS: - /* TODO: pass-through */ - errno = ENOTSUP; - return NULL; + fmt->i_format = VLC_CODEC_SPDIFL; + fmt->i_bytes_per_frame = 4; + fmt->i_frame_length = 1; + fmt->i_physical_channels = AOUT_CHANS_2_0; + fmt->i_channels = 2; + encoding = SPA_AUDIO_IEC958_CODEC_DTS; + break; default: vlc_pw_error(sys->context, "unknown format"); errno = ENOTSUP; @@ -476,37 +496,40 @@ static struct vlc_pw_stream *vlc_pw_stream_create(audio_output_t *aout, } /* Map audio channels */ - size_t mapped = 0; + if (encoding == SPA_AUDIO_IEC958_CODEC_PCM) + { + size_t mapped = 0; - if (fmt->i_channels > SPA_AUDIO_MAX_CHANNELS) { - vlc_pw_error(sys->context, "too many channels"); - errno = ENOTSUP; - return NULL; - } + if (fmt->i_channels > SPA_AUDIO_MAX_CHANNELS) { + vlc_pw_error(sys->context, "too many channels"); + errno = ENOTSUP; + return NULL; + } - static const unsigned char map[] = { - SPA_AUDIO_CHANNEL_FC, - SPA_AUDIO_CHANNEL_FL, - SPA_AUDIO_CHANNEL_FR, - 0 /* unassigned */, - SPA_AUDIO_CHANNEL_RC, - SPA_AUDIO_CHANNEL_RL, - SPA_AUDIO_CHANNEL_RR, - 0 /* unassigned */, - SPA_AUDIO_CHANNEL_SL, - SPA_AUDIO_CHANNEL_SR, - 0 /* unassigned */, - 0 /* unassigned */, - SPA_AUDIO_CHANNEL_LFE, - }; + static const unsigned char map[] = { + SPA_AUDIO_CHANNEL_FC, + SPA_AUDIO_CHANNEL_FL, + SPA_AUDIO_CHANNEL_FR, + 0 /* unassigned */, + SPA_AUDIO_CHANNEL_RC, + SPA_AUDIO_CHANNEL_RL, + SPA_AUDIO_CHANNEL_RR, + 0 /* unassigned */, + SPA_AUDIO_CHANNEL_SL, + SPA_AUDIO_CHANNEL_SR, + 0 /* unassigned */, + 0 /* unassigned */, + SPA_AUDIO_CHANNEL_LFE, + }; - for (size_t i = 0; i < ARRAY_SIZE(map); i++) - if ((fmt->i_physical_channels >> i) & 1) - rawfmt.position[mapped++] = map[i]; + for (size_t i = 0; i < ARRAY_SIZE(map); i++) + if ((fmt->i_physical_channels >> i) & 1) + rawfmt.position[mapped++] = map[i]; - while (mapped < fmt->i_channels) { - rawfmt.position[mapped] = SPA_AUDIO_CHANNEL_START_Aux + mapped; - mapped++; + while (mapped < fmt->i_channels) { + rawfmt.position[mapped] = SPA_AUDIO_CHANNEL_START_Aux + mapped; + mapped++; + } } /* Assemble the stream format */ @@ -514,8 +537,20 @@ static struct vlc_pw_stream *vlc_pw_stream_create(audio_output_t *aout, unsigned char buf[1024]; struct spa_pod_builder builder = SPA_POD_BUILDER_INIT(buf, sizeof (buf)); - params[0] = spa_format_audio_raw_build(&builder, SPA_PARAM_EnumFormat, - &rawfmt); + if (encoding == SPA_AUDIO_IEC958_CODEC_PCM) + { + params[0] = spa_format_audio_raw_build(&builder, SPA_PARAM_EnumFormat, + &rawfmt); + } + else /* pass-through */ + { + struct spa_audio_info_iec958 iecfmt = { + .rate = fmt->i_rate, + .codec = encoding + }; + params[0] = spa_format_audio_iec958_build(&builder, SPA_PARAM_EnumFormat, + &iecfmt); + } /* Assemble stream properties */ struct pw_properties *props;