diff --git a/audio.c b/audio.c index a703d660..90ca8fac 100644 --- a/audio.c +++ b/audio.c @@ -458,7 +458,7 @@ uint32_t get_channel_settings(const char *stanza_name, const char *setting_name) for (i = 0; i < channel_counts_count; i++) { debug(3, "channel count setting %d: %d.", i, channel_counts[i]); - if ((channel_counts[i] >= 1) && (channel_counts[i] <= 8)) { + if ((channel_counts[i] >= 1) && (channel_counts[i] <= SPS_GREATEST_CHANNEL_COUNT)) { #ifdef CONFIG_FFMPEG channel_set |= (1 << channel_counts[i]); #else @@ -492,7 +492,7 @@ uint32_t get_channel_settings(const char *stanza_name, const char *setting_name) char numbuf[32]; unsigned int c; uint32_t t_channel_set = channel_set; - for (c = 0; c <= 8; c++) { + for (c = 0; c <= SPS_GREATEST_CHANNEL_COUNT; c++) { if ((t_channel_set & (1 << c)) != 0) { snprintf(numbuf, sizeof(numbuf) - 1, "%u", c); snprintf(p, sizeof(buf) - (p - buf) - 1, "%s", numbuf); diff --git a/common.h b/common.h index a7a0604d..e18af0f9 100644 --- a/common.h +++ b/common.h @@ -146,7 +146,13 @@ typedef enum { // these sets omit the _UNKNOWN, _AUTO and _ILLEGAL values #define SPS_FORMAT_SET (((1 << (SPS_FORMAT_HIGHEST_NATIVE + 1)) - 1) - (1 << SPS_FORMAT_UNKNOWN)) #define SPS_RATE_SET (((1 << (SPS_RATE_HIGHEST + 1)) - 1) - (1 << SPS_RATE_UNKNOWN)) -#define SPS_CHANNEL_SET (((1 << (8 + 1)) - 1) - (1 << 0)) // channels 1 to 8, not 0-based! + +// in SPS_CHANNEL_SET, bit 0 set means a channel set of no channels, bit 1 set means a channel set of 1 channel +// and so on to bit 31 meaning a channel set of 31 channels. We want to consider all possible channel sets +// apart from channel set 0. +#define SPS_GREATEST_CHANNEL_COUNT 31 // should be 32 to be fully in line with ALSA limits +#define SPS_CHANNEL_SET 0xFFFFFFFE // channel sets 31 to 1, but no channel set 0 +// #define SPS_CHANNEL_SET (((1 << (SPS_GREATEST_CHANNEL_COUNT + 1)) - 1) - (1 << 0)) // channels 1 to 31, not 0-based! #ifndef CONFIG_AIRPLAY_2 #define SPS_FORMAT_NON_FFMPEG_SET SPS_FORMAT_SET diff --git a/player.c b/player.c index 2d8b9081..3ccd33de 100644 --- a/player.c +++ b/player.c @@ -656,24 +656,43 @@ int setup_software_resampler(rtsp_conn_info *conn, ssrc_t ssrc) { // set the resampler's channel layout either automatically or use the // setting that has been given + // We impose the rule that, if the mixdown setting is "auto", + // we will not upmix if the number of output channels available + // is greater than the number of channels needed. + + // To do an upmix, you will have to specify the upmix target, e.g. "7.1" + // in the mixdown setting. + + // NOTE: upmixing at present, by default, simply copies the input channels to their + // equivalents in the output channel set. All the other channels are + // left alone. + #if LIBAVUTIL_VERSION_MAJOR >= 57 { AVChannelLayout input_channel_layout; av_channel_layout_from_mask(&input_channel_layout, input_layout); + int input_channel_count = input_channel_layout.nb_channels; av_opt_set_chlayout(swr, "in_chlayout", &input_channel_layout, 0); av_channel_layout_uninit(&input_channel_layout); AVChannelLayout output_channel_layout; if (config.mixdown_enable != 0) { if (config.mixdown_channel_layout == 0) { - av_channel_layout_default(&output_channel_layout, + if (CHANNELS_FROM_ENCODED_FORMAT(output_configuration) > (unsigned) input_channel_count) { + av_channel_layout_from_mask(&output_channel_layout, input_layout); + } else { + av_channel_layout_default(&output_channel_layout, CHANNELS_FROM_ENCODED_FORMAT(output_configuration)); + } } else { av_channel_layout_from_mask(&output_channel_layout, config.mixdown_channel_layout); } } else { av_channel_layout_from_mask(&output_channel_layout, output_layout); } + char layout_desc[2048]; + av_channel_layout_describe(&output_channel_layout, layout_desc, sizeof(layout_desc)); + debug(1,"output channel layout: \"%s\"", layout_desc); av_opt_set_chlayout(swr, "out_chlayout", &output_channel_layout, 0); av_channel_layout_uninit(&output_channel_layout); } @@ -681,8 +700,10 @@ int setup_software_resampler(rtsp_conn_info *conn, ssrc_t ssrc) { av_opt_set_int(swr, "in_channel_layout", input_layout, 0); if (config.mixdown_enable != 0) { if (config.mixdown_channel_layout == 0) { - output_layout = - av_get_default_channel_layout(CHANNELS_FROM_ENCODED_FORMAT(output_configuration)); + if (CHANNELS_FROM_ENCODED_FORMAT(output_configuration) < av_get_channel_layout_nb_channels(input_layout)) { + output_layout = + av_get_default_channel_layout(CHANNELS_FROM_ENCODED_FORMAT(output_configuration)); + } // else leave output_layout as it was: the sames as the input_layout. } else { output_layout = config.mixdown_channel_layout; } @@ -962,7 +983,7 @@ int setup_software_resampler(rtsp_conn_info *conn, ssrc_t ssrc) { if (output_configuration_changed != 0) { char channel_mapping_list[256] = ""; - for (c = 0; c < 8; c++) { + for (c = 0; c < SPS_GREATEST_CHANNEL_COUNT; c++) { if ((output_channels[c].allocated != 0) && (conn->output_channel_to_resampler_channel_map[c] != silent_channel_index)) { char channel_mapping[32] = "";