From ef6e0314b8c0930e63ef8715c8bbb504e9adae52 Mon Sep 17 00:00:00 2001 From: Thomas Reufer Date: Mon, 29 Sep 2014 21:36:38 +0200 Subject: set HDMI speaker layout to fix channel mapping for multi channel PCM output --- HISTORY | 1 + audio.c | 3 +++ setup.c | 43 +++++++++++++++++++++++++++++++++++++++++++ setup.h | 2 ++ 4 files changed, 49 insertions(+) diff --git a/HISTORY b/HISTORY index 3c15dc4..bc5f14f 100644 --- a/HISTORY +++ b/HISTORY @@ -2,6 +2,7 @@ VDR Plugin 'rpihddevice' Revision History ----------------------------------------- - new: + - set HDMI speaker layout to fix channel mapping for multi channel PCM output - support building against external ffmpeg/libav by setting EXT_LIBAV - support for >=ffmpeg-1.2 and >=libav-0.8 with resampling - setup option for video framing mode in case of incompatible aspect ratio diff --git a/audio.c b/audio.c index 9cf9f17..c99c51b 100644 --- a/audio.c +++ b/audio.c @@ -1170,6 +1170,9 @@ void cRpiAudioDecoder::SetCodec(cAudioCodec::eCodec codec, unsigned int &channel cRpiAudioPort::Str(outputPort), channels, cAudioCodec::Str(outputFormat), samplingRate / 1000, (samplingRate % 1000) / 100, m_passthrough ? " (pass-through)" : ""); + + if (outputPort == cRpiAudioPort::eHDMI) + cRpiSetup::SetHDMIChannelMapping(m_passthrough, channels); } } diff --git a/setup.c b/setup.c index fe2cd36..711f5b9 100644 --- a/setup.c +++ b/setup.c @@ -226,6 +226,49 @@ int cRpiSetup::GetDisplaySize(int &width, int &height, double &aspect) return 0; } +void cRpiSetup::SetHDMIChannelMapping(bool passthrough, int channels) +{ + char command[80], response[80]; + + sprintf(command, "hdmi_stream_channels %d", passthrough ? 1 : 0); + vc_gencmd(response, sizeof response, command); + + uint32_t channel_map = 0; + + if (!passthrough && channels > 0 && channels <= 6) + { + const unsigned char ch_mapping[6][8] = + { + { 0, 0, 0, 0, 0, 0, 0, 0 }, // not supported + { 1, 2, 0, 0, 0, 0, 0, 0 }, // 2.0 + { 1, 2, 4, 0, 0, 0, 0, 0 }, // 2.1 + { 0, 0, 0, 0, 0, 0, 0, 0 }, // not supported + { 0, 0, 0, 0, 0, 0, 0, 0 }, // not supported + { 1, 2, 4, 3, 5, 6, 0, 0 }, // 5.1 + }; + + // speaker layout according CEA 861, Table 28: Audio InfoFrame, byte 4 + const unsigned char cea_map[] = + { + 0xff, // not supported + 0x00, // 2.0 + 0x01, // 2.1 + 0xff, // not supported + 0xff, // not supported + 0x0b // 5.1 + }; + + for (int ch = 0; ch < channels; ch++) + if (ch_mapping[channels - 1][ch]) + channel_map |= (ch_mapping[channels - 1][ch] - 1) << (3 * ch); + + channel_map |= cea_map[channels - 1] << 24; + } + + sprintf(command, "hdmi_channel_map 0x%08x", channel_map); + vc_gencmd(response, sizeof response, command); +} + cMenuSetupPage* cRpiSetup::GetSetupPage(void) { return new cRpiSetupPage(m_audio, m_video); diff --git a/setup.h b/setup.h index 146fe53..d1b29c1 100644 --- a/setup.h +++ b/setup.h @@ -72,6 +72,8 @@ public: static int GetDisplaySize(int &width, int &height, double &aspect); + static void SetHDMIChannelMapping(bool passthrough, int channels); + static bool IsDisplayProgressive(void) { return GetInstance()->m_isProgressive; } -- cgit v1.2.3