All pastes #1747729 Raw Edit

Unnamed

public text v1 · immutable
#1747729 ·published 2010-01-12 01:58 UTC
rendered paste body
Index: xbmc/cores/dvdplayer/DVDAudio.cpp
===================================================================
--- xbmc/cores/dvdplayer/DVDAudio.cpp	(revision 26651)
+++ xbmc/cores/dvdplayer/DVDAudio.cpp	(working copy)
@@ -92,7 +92,7 @@
   else
     codecstring = "PCM";
 
-  m_pAudioDecoder = CAudioRendererFactory::Create(m_pCallback, audioframe.channels, audioframe.sample_rate, audioframe.bits_per_sample, false, codecstring, false, audioframe.passthrough);
+  m_pAudioDecoder = CAudioRendererFactory::Create(m_pCallback, audioframe.channels, audioframe.channel_map, audioframe.sample_rate, audioframe.bits_per_sample, false, codecstring, false, audioframe.passthrough);
 
   if (!m_pAudioDecoder) return false;
 
@@ -345,4 +345,4 @@
   if(!m_pAudioDecoder)
     return 0.0;
   return m_pAudioDecoder->GetCacheTotal();
-}
\ No newline at end of file
+}
Index: xbmc/cores/dvdplayer/DVDPlayerAudio.cpp
===================================================================
--- xbmc/cores/dvdplayer/DVDPlayerAudio.cpp	(revision 26651)
+++ xbmc/cores/dvdplayer/DVDPlayerAudio.cpp	(working copy)
@@ -316,6 +316,7 @@
       audioframe.size = m_pAudioCodec->GetData(&audioframe.data);
       audioframe.pts = m_audioClock;
       audioframe.channels = m_pAudioCodec->GetChannels();
+      audioframe.channel_map = m_pAudioCodec->GetChannelMap();
       audioframe.bits_per_sample = m_pAudioCodec->GetBitsPerSample();
       audioframe.sample_rate = m_pAudioCodec->GetSampleRate();
       audioframe.passthrough = m_pAudioCodec->NeedPassthrough();
Index: xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecLiba52.h
===================================================================
--- xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecLiba52.h	(revision 26651)
+++ xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecLiba52.h	(working copy)
@@ -40,11 +40,12 @@
   virtual int Decode(BYTE* pData, int iSize);
   virtual int GetData(BYTE** dst);
   virtual void Reset();
-  virtual int GetChannels()      { return m_iOutputChannels; }
-  virtual int GetSampleRate()    { return m_iSourceSampleRate; }
-  virtual int GetBufferSize()    { return m_inputSize; }
-  virtual int GetBitsPerSample() { return 16; }
-  virtual const char* GetName() { return "liba52"; }
+  virtual int GetChannels()        { return m_iOutputChannels; }
+  virtual uint8_t *GetChannelMap() { return m_pChannelMap; }
+  virtual int GetSampleRate()      { return m_iSourceSampleRate; }
+  virtual int GetBufferSize()      { return m_inputSize; }
+  virtual int GetBitsPerSample()   { return 16; }
+  virtual const char* GetName()    { return "liba52"; }
 
 protected:
   void SetDefault();
@@ -64,7 +65,7 @@
 
   int m_iOutputFlags;
   int m_iOutputChannels;
-  unsigned int m_iOutputMapping;
+  uint8_t *m_pChannelMap;
 
   DllLiba52 m_dll;
 
Index: xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodec.h
===================================================================
--- xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodec.h	(revision 26651)
+++ xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodec.h	(working copy)
@@ -22,6 +22,7 @@
  */
 
 #include "system.h"
+#include "../../../../utils/PCMRemap.h"
 
 #if (defined HAVE_CONFIG_H) && (!defined WIN32)
   #include "config.h"
@@ -90,6 +91,11 @@
   virtual int GetChannels() = 0;
 
   /*
+   * returns the channel mapping
+   */
+  virtual uint8_t* GetChannelMap() = 0;
+
+  /*
    * returns the samplerate for the decoded audio stream
    */
   virtual int GetSampleRate() = 0;
Index: xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.cpp
===================================================================
--- xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.cpp	(revision 26651)
+++ xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.cpp	(working copy)
@@ -78,6 +78,7 @@
   m_pCodecContext->block_align = hints.blockalign;
   m_pCodecContext->bit_rate = hints.bitrate;
   m_pCodecContext->bits_per_coded_sample = hints.bitspersample;
+  m_pCodecContext->request_channel_layout = CH_LAYOUT_NATIVE;
 
   if(m_pCodecContext->bits_per_coded_sample == 0)
     m_pCodecContext->bits_per_coded_sample = 16;
@@ -218,6 +219,11 @@
   return 0;
 }
 
+uint8_t* CDVDAudioCodecFFmpeg::GetChannelMap()
+{
+
+}
+
 int CDVDAudioCodecFFmpeg::GetSampleRate()
 {
   if (m_pCodecContext) return m_pCodecContext->sample_rate;
Index: xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.h
===================================================================
--- xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.h	(revision 26651)
+++ xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.h	(working copy)
@@ -36,6 +36,7 @@
   virtual int GetData(BYTE** dst);
   virtual void Reset();
   virtual int GetChannels();
+  virtual uint8_t *GetChannelMap();
   virtual int GetSampleRate();
   virtual int GetBitsPerSample();
   virtual const char* GetName() { return "FFmpeg"; }
Index: xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthrough.h
===================================================================
--- xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthrough.h	(revision 26651)
+++ xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthrough.h	(working copy)
@@ -37,6 +37,7 @@
   virtual int GetData(BYTE** dst);
   virtual void Reset();
   virtual int GetChannels();
+  virtual uint8_t *GetChannelMap() { static uint8_t map[2] = {PCM_FRONT_LEFT, PCM_FRONT_RIGHT}; return map; }
   virtual int GetSampleRate();
   virtual int GetBitsPerSample();
   virtual bool NeedPassthrough() { return true; }
Index: xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecLiba52.cpp
===================================================================
--- xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecLiba52.cpp	(revision 26651)
+++ xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecLiba52.cpp	(working copy)
@@ -47,23 +47,19 @@
  * into the interleaved int16 format used by us.
  * \param in the input buffer containing the planar samples.
  * \param out the output buffer where the interleaved result is stored.
+ * \param channels the total number of channels in the decoded data
  */
-static int resample_int16(sample_t * in, int16_t *out, int32_t channel_map)
+static int resample_int16(sample_t * in, int16_t *out, unsigned int channels)
 {
-    unsigned long i;
+    unsigned int i, ch;
     int16_t *p = out;
-    for (i = 0; i != 256; i++) {
-	unsigned long map = channel_map;
-	do {
-	    unsigned long ch = map & 15;
-	    if (ch == 15)
-		*p = 0;
-	    else
-		*p = convert( ((int32_t*)in)[i + ((ch-1)<<8)] );
-	    p++;
-	} while ((map >>= 4));
+    for(i = 0; i < 256; ++i) {
+      for(ch = 0; ch < channels; ++ch) {
+        *p = convert( ((int32_t*)in)[i + (ch << 8)] );
+        ++p;
+      }
     }
-    return (int16_t*) p - out;
+    return p - out; 
 }
 
 
@@ -109,90 +105,56 @@
 
 void CDVDAudioCodecLiba52::SetupChannels(int flags)
 {
-/* Internal AC3 ordering for different configs
- * A52_CHANNEL: 1+1 2 Ch1, Ch2
- * A52_MONO   : 1/0 1 C
- * A52_STEREO : 2/0 2 L, R
- * A52_3F     : 3/0 3 L, C, R
- * A52_2F1R   : 2/1 3 L, R, S
- * A52_3F1R   : 3/1 4 L, C, R, S
- * A52_2F2R   : 2/2 4 L, R, SL, SR
- * A52_3F2R   : 3/2 5 L, C, R, SL, SR
-*/
+  /* These are channel mappings that liba52 outputs */
+  static uint8_t channelMaps[18][6] =
+  {
+    /* Without LFE */
+    {/* A52_MONO    */ PCM_FRONT_CENTER                                                                                             },
+    {/* A52_STEREO  */ PCM_FRONT_LEFT  , PCM_FRONT_RIGHT                                                                            },
+    {/* A52_3F      */ PCM_FRONT_LEFT  , PCM_FRONT_CENTER , PCM_FRONT_RIGHT               	                                    },
+    {/* A52_2F1R    */ PCM_FRONT_LEFT  , PCM_FRONT_RIGHT  , PCM_BACK_CENTER                                                         },
+    {/* A52_3F1R    */ PCM_FRONT_LEFT  , PCM_FRONT_CENTER , PCM_FRONT_RIGHT, PCM_BACK_CENTER                                        },
+    {/* A52_2F2R    */ PCM_FRONT_LEFT  , PCM_FRONT_RIGHT  , PCM_BACK_LEFT  , PCM_BACK_RIGHT                                         },
+    {/* A52_3F2R    */ PCM_FRONT_LEFT  , PCM_FRONT_CENTER , PCM_FRONT_RIGHT, PCM_BACK_LEFT  , PCM_BACK_RIGHT                        },
+    /* With LFE */
+    {/* A52_MONO    */ PCM_LOW_FREQUENCY, PCM_FRONT_CENTER                                                                          },
+    {/* A52_STEREO  */ PCM_LOW_FREQUENCY, PCM_FRONT_LEFT  , PCM_FRONT_RIGHT                                                         },
+    {/* A52_3F      */ PCM_LOW_FREQUENCY, PCM_FRONT_LEFT  , PCM_FRONT_CENTER , PCM_FRONT_RIGHT                                      },
+    {/* A52_2F1R    */ PCM_LOW_FREQUENCY, PCM_FRONT_LEFT  , PCM_FRONT_RIGHT  , PCM_BACK_CENTER                                      },
+    {/* A52_3F1R    */ PCM_LOW_FREQUENCY, PCM_FRONT_LEFT  , PCM_FRONT_CENTER , PCM_FRONT_RIGHT, PCM_BACK_CENTER                     },
+    {/* A52_2F2R    */ PCM_LOW_FREQUENCY, PCM_FRONT_LEFT  , PCM_FRONT_RIGHT  , PCM_BACK_LEFT  , PCM_BACK_RIGHT                      },
+    {/* A52_3F2R    */ PCM_LOW_FREQUENCY, PCM_FRONT_LEFT  , PCM_FRONT_CENTER , PCM_FRONT_RIGHT, PCM_BACK_LEFT    , PCM_BACK_RIGHT   }
+  };
 
   m_iSourceFlags = flags;
-  // setup channel map for how to translate to linear format
-  // standard windows format
-  if(m_iSourceFlags & A52_LFE)
+
+  // setup channel map
+  int channels = 0;
+  int chOffset = (flags & A52_LFE) ? 7 : 0;
+  switch (m_iSourceFlags &~ A52_LFE)
   {
-    switch (m_iSourceFlags&~A52_LFE) {
-      case A52_MONO   : m_iOutputMapping = 0x12ffff; break;
-      case A52_CHANNEL:
-      case A52_STEREO :
-      case A52_DOLBY  : m_iOutputMapping = 0x1fff32; break;
-      case A52_2F1R   : m_iOutputMapping = 0x1f5542; break;
-      case A52_2F2R   : m_iOutputMapping = 0x1f5432; break;
-      case A52_3F     : m_iOutputMapping = 0x13ff42; break;
-      case A52_3F1R   : m_iOutputMapping = 0x135542; break;
-      case A52_3F2R   : m_iOutputMapping = 0x136542; break;
-      default         : m_iOutputMapping = 0x000000; break;
-    }
+    case A52_MONO   : m_pChannelMap = channelMaps[chOffset + 0]; channels = 1; break;
+    case A52_CHANNEL:
+    case A52_DOLBY  :
+    case A52_STEREO : m_pChannelMap = channelMaps[chOffset + 1]; channels = 2; break;
+    case A52_3F     : m_pChannelMap = channelMaps[chOffset + 2]; channels = 3; break;
+    case A52_2F1R   : m_pChannelMap = channelMaps[chOffset + 3]; channels = 3; break;
+    case A52_3F1R   : m_pChannelMap = channelMaps[chOffset + 4]; channels = 4; break;
+    case A52_2F2R   : m_pChannelMap = channelMaps[chOffset + 5]; channels = 4; break;
+    case A52_3F2R   : m_pChannelMap = channelMaps[chOffset + 6]; channels = 5; break;
+    default         : m_pChannelMap = NULL;                                    break;
   }
-  else
-  {
-    switch (m_iSourceFlags) {
-      case A52_MONO   : m_iOutputMapping =     0x1; break;
-      case A52_CHANNEL:
-      case A52_STEREO :
-      case A52_DOLBY  : m_iOutputMapping =    0x21; break;
-      case A52_2F1R   : m_iOutputMapping =  0x2231; break;
-      case A52_2F2R   : m_iOutputMapping =  0x4321; break;
-      case A52_3F     : m_iOutputMapping = 0x2ff31; break;
-      case A52_3F1R   : m_iOutputMapping = 0x24431; break;
-      case A52_3F2R   : m_iOutputMapping = 0x25431; break;
-      default         : m_iOutputMapping =     0x0; break;
-    }
-  }
-
-  if(m_iOutputMapping == 0x0)
+  
+  if(m_pChannelMap == NULL)
     CLog::Log(LOGERROR, "CDVDAudioCodecLiba52::SetupChannels - Invalid channel mapping");
 
-  int channels = 0;
-  unsigned int m = m_iOutputMapping<<4;
-  while(m>>=4) channels++;
-
-  // xbox can't handle these
-  if(channels == 5 || channels == 3)
-    channels = 6;
-
   if(m_iSourceChannels > 0 && m_iSourceChannels != channels)
     CLog::Log(LOGINFO, "%s - Number of channels changed in stream from %d to %d, data might be truncated", __FUNCTION__, m_iOutputChannels, channels);
 
   m_iSourceChannels = channels;
-
-  // make sure map contains enough channels
-  for(int i=0;i<m_iSourceChannels;i++)
-  {
-    if((m_iOutputMapping & (0xf<<(i*4))) == 0)
-      m_iOutputMapping |= 0xf<<(i*4);
-  }
-  // and nothing more
-  m_iOutputMapping &= ~(0xffffffff<<(m_iSourceChannels*4));
-
-
   m_iOutputChannels = m_iSourceChannels;
   m_iOutputFlags    = m_iSourceFlags;
 
-  // If we can't support multichannel output downmix
-  if (g_guiSettings.GetBool("audiooutput.downmixmultichannel"))
-  {
-    m_iOutputChannels = 2;
-    m_iOutputMapping = 0x21;
-    m_iOutputFlags = A52_STEREO;
-    if (m_iSourceChannels > 2)
-      m_Gain = pow(2.0f, g_advancedSettings.m_ac3Gain/6.0f); // Hack for downmix attenuation
-  }
-
   /* adjust level should always be set, to keep samples in proper range */
   /* after any downmixing has been done */
   m_iOutputFlags |= A52_ADJUST_LEVEL;
@@ -318,7 +280,7 @@
       CLog::Log(LOGERROR, "CDVDAudioCodecLiba52::Decode - a52_block failed");
       break;
     }
-    m_decodedSize += 2*resample_int16(m_fSamples, (int16_t*)(m_decodedData + m_decodedSize), m_iOutputMapping);
+    m_decodedSize += 2*resample_int16(m_fSamples, (int16_t*)(m_decodedData + m_decodedSize), m_iSourceChannels);
   }
   return len;
 }
Index: xbmc/cores/dvdplayer/DVDPlayerAudio.h
===================================================================
--- xbmc/cores/dvdplayer/DVDPlayerAudio.h	(revision 26651)
+++ xbmc/cores/dvdplayer/DVDPlayerAudio.h	(working copy)
@@ -54,6 +54,7 @@
   unsigned int size;
 
   int channels;
+  uint8_t *channel_map;
   int bits_per_sample;
   int sample_rate;
   bool passthrough;
Index: xbmc/cores/AudioRenderers/IAudioRenderer.h
===================================================================
--- xbmc/cores/AudioRenderers/IAudioRenderer.h	(revision 26651)
+++ xbmc/cores/AudioRenderers/IAudioRenderer.h	(working copy)
@@ -31,6 +31,7 @@
 
 #include "StdString.h"
 #include "IAudioCallback.h"
+#include "PCMRemap.h"
 extern void RegisterAudioCallback(IAudioCallback* pCallback);
 extern void UnRegisterAudioCallback();
 
@@ -42,7 +43,7 @@
 public:
   IAudioRenderer() {};
   virtual ~IAudioRenderer() {};
-  virtual bool Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, const char* strAudioCodec = "", bool bIsMusic=false, bool bPassthrough = false) = 0;
+  virtual bool Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, uint8_t *channelMap, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, const char* strAudioCodec = "", bool bIsMusic=false, bool bPassthrough = false) = 0;
   virtual void UnRegisterAudioCallback() = 0;
   virtual void RegisterAudioCallback(IAudioCallback* pCallback) = 0;
   virtual float GetDelay() = 0;
@@ -66,6 +67,9 @@
   virtual void WaitCompletion() = 0;
   virtual void SwitchChannels(int iAudioStream, bool bAudioOnAllSpeakers) = 0;
 
+protected:
+  CPCMRemap m_remap;
+
 private:
 };
 
Index: xbmc/cores/AudioRenderers/NullDirectSound.cpp
===================================================================
--- xbmc/cores/AudioRenderers/NullDirectSound.cpp	(revision 26651)
+++ xbmc/cores/AudioRenderers/NullDirectSound.cpp	(working copy)
@@ -41,7 +41,7 @@
 CNullDirectSound::CNullDirectSound()
 {
 }
-bool CNullDirectSound::Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, const char* strAudioCodec, bool bIsMusic, bool bPassthrough)
+bool CNullDirectSound::Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, uint8_t *channelMap, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, const char* strAudioCodec, bool bIsMusic, bool bPassthrough)
 {
   CLog::Log(LOGERROR,"Creating a Null Audio Renderer, Check your audio settings as this should not happen");
   if (iChannels == 0)
Index: xbmc/cores/AudioRenderers/PulseAudioDirectSound.cpp
===================================================================
--- xbmc/cores/AudioRenderers/PulseAudioDirectSound.cpp	(revision 26651)
+++ xbmc/cores/AudioRenderers/PulseAudioDirectSound.cpp	(working copy)
@@ -143,7 +143,7 @@
 {
 }
 
-bool CPulseAudioDirectSound::Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, const char* strAudioCodec, bool bIsMusic, bool bPassthrough)
+bool CPulseAudioDirectSound::Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, uint8_t *channelMap, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, const char* strAudioCodec, bool bIsMusic, bool bPassthrough)
 {
   CLog::Log(LOGDEBUG,"PulseAudio: Opening Channels: %i - SampleRate: %i - SampleBit: %i - Resample %s - Codec %s - IsMusic %s - IsPassthrough %s - device: %s", iChannels, uiSamplesPerSec, uiBitsPerSample, bResample ? "true" : "false", strAudioCodec, bIsMusic ? "true" : "false", bPassthrough ? "true" : "false", device.c_str());
   if (iChannels == 0)
Index: xbmc/cores/AudioRenderers/AudioRendererFactory.cpp
===================================================================
--- xbmc/cores/AudioRenderers/AudioRendererFactory.cpp	(revision 26651)
+++ xbmc/cores/AudioRenderers/AudioRendererFactory.cpp	(working copy)
@@ -41,7 +41,7 @@
 
 #define ReturnOnValidInitialize()          \
 {                                          \
-  if (audioSink->Initialize(pCallback, device, iChannels, uiSamplesPerSec, uiBitsPerSample, bResample, strAudioCodec, bIsMusic, bPassthrough))  \
+  if (audioSink->Initialize(pCallback, device, iChannels, channelMap, uiSamplesPerSec, uiBitsPerSample, bResample, strAudioCodec, bIsMusic, bPassthrough))  \
     return audioSink;                      \
   else                                     \
   {                                        \
@@ -51,7 +51,7 @@
   }                                        \
 }\
 
-IAudioRenderer* CAudioRendererFactory::Create(IAudioCallback* pCallback, int iChannels, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, const char* strAudioCodec, bool bIsMusic, bool bPassthrough)
+IAudioRenderer* CAudioRendererFactory::Create(IAudioCallback* pCallback, int iChannels, uint8_t *channelMap, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, const char* strAudioCodec, bool bIsMusic, bool bPassthrough)
 {
   IAudioRenderer* audioSink = NULL;
 
@@ -91,7 +91,7 @@
 #endif
 
       audioSink = new CNullDirectSound();
-      audioSink->Initialize(pCallback, device, iChannels, uiSamplesPerSec, uiBitsPerSample, bResample, strAudioCodec, bIsMusic, bPassthrough);
+      audioSink->Initialize(pCallback, device, iChannels, channelMap, uiSamplesPerSec, uiBitsPerSample, bResample, strAudioCodec, bIsMusic, bPassthrough);
       return audioSink;
     }
   }
@@ -119,7 +119,7 @@
 #endif
 
   audioSink = new CNullDirectSound();
-  audioSink->Initialize(pCallback, device, iChannels, uiSamplesPerSec, uiBitsPerSample, bResample, strAudioCodec, bIsMusic, bPassthrough);
+  audioSink->Initialize(pCallback, device, iChannels, channelMap, uiSamplesPerSec, uiBitsPerSample, bResample, strAudioCodec, bIsMusic, bPassthrough);
   return audioSink;
 }
 
Index: xbmc/cores/AudioRenderers/NullDirectSound.h
===================================================================
--- xbmc/cores/AudioRenderers/NullDirectSound.h	(revision 26651)
+++ xbmc/cores/AudioRenderers/NullDirectSound.h	(working copy)
@@ -41,7 +41,7 @@
   virtual float GetDelay();
   virtual float GetCacheTime();
   CNullDirectSound();
-  virtual bool Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, const char* strAudioCodec = "", bool bIsMusic=false, bool bPassthrough = false);
+  virtual bool Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, uint8_t *channelMap, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, const char* strAudioCodec = "", bool bIsMusic=false, bool bPassthrough = false);
   virtual ~CNullDirectSound();
 
   virtual unsigned int AddPackets(const void* data, unsigned int len);
Index: xbmc/cores/AudioRenderers/PulseAudioDirectSound.h
===================================================================
--- xbmc/cores/AudioRenderers/PulseAudioDirectSound.h	(revision 26651)
+++ xbmc/cores/AudioRenderers/PulseAudioDirectSound.h	(working copy)
@@ -47,7 +47,7 @@
   virtual float GetCacheTime();
   virtual float GetCacheTotal();
   CPulseAudioDirectSound();
-  virtual bool Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, const char* strAudioCodec = "", bool bIsMusic=false, bool bPassthrough = false);
+  virtual bool Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, uint8_t *channelMap, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, const char* strAudioCodec = "", bool bIsMusic=false, bool bPassthrough = false);
   virtual ~CPulseAudioDirectSound();
 
   virtual unsigned int AddPackets(const void* data, unsigned int len);
Index: xbmc/cores/AudioRenderers/ALSADirectSound.cpp
===================================================================
--- xbmc/cores/AudioRenderers/ALSADirectSound.cpp	(revision 26651)
+++ xbmc/cores/AudioRenderers/ALSADirectSound.cpp	(working copy)
@@ -37,6 +37,13 @@
   return result;
 }
 
+static uint8_t ALSAChannelMap[8] = {
+  PCM_FRONT_LEFT  , PCM_FRONT_RIGHT  ,
+  PCM_BACK_LEFT   , PCM_BACK_RIGHT   ,
+  PCM_FRONT_CENTER, PCM_LOW_FREQUENCY,
+  PCM_SIDE_LEFT   , PCM_SIDE_RIGHT
+};
+
 //////////////////////////////////////////////////////////////////////
 // Construction/Destruction
 //////////////////////////////////////////////////////////////////////
@@ -47,7 +54,7 @@
   m_bIsAllocated = false;
 }
 
-bool CALSADirectSound::Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, const char* strAudioCodec, bool bIsMusic, bool bPassthrough)
+bool CALSADirectSound::Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, uint8_t *channelMap, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, const char* strAudioCodec, bool bIsMusic, bool bPassthrough)
 {
   CStdString deviceuse;
 
@@ -56,6 +63,10 @@
   if (iChannels == 0)
     iChannels = 2;
 
+  /* setup the channel mapping */
+  m_remap.SetInputFormat (iChannels, channelMap, uiBitsPerSample / 8);
+  m_remap.SetOutputFormat(iChannels, ALSAChannelMap);
+
   bool bAudioOnAllSpeakers(false);
   g_audioContext.SetupSpeakerConfig(iChannels, bAudioOnAllSpeakers, bIsMusic);
   g_audioContext.SetActiveDevice(CAudioContext::DIRECTSOUND_DEVICE);
@@ -471,7 +482,14 @@
     writeResult = snd_pcm_writei(m_pPlayHandle, dummy, framesToWrite);
   }
   else
-    writeResult = snd_pcm_writei(m_pPlayHandle, pcmPtr, framesToWrite);
+  {
+    /* remap the data to the correct channels */
+    uint8_t outData[bytesToWrite];
+    m_remap.Remap((void*)pcmPtr, outData, framesToWrite);
+
+    /* write it out */
+    writeResult = snd_pcm_writei(m_pPlayHandle, outData, framesToWrite);
+  }
   if (  writeResult == -EPIPE  ) {
     CLog::Log(LOGDEBUG, "CALSADirectSound::AddPackets - buffer underun (tried to write %d frames)",
             framesToWrite);
Index: xbmc/cores/AudioRenderers/AudioRendererFactory.h
===================================================================
--- xbmc/cores/AudioRenderers/AudioRendererFactory.h	(revision 26651)
+++ xbmc/cores/AudioRenderers/AudioRendererFactory.h	(working copy)
@@ -31,7 +31,7 @@
 class CAudioRendererFactory
 {
 public:
-  static IAudioRenderer *Create(IAudioCallback* pCallback, int iChannels, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, const char* strAudioCodec, bool bIsMusic, bool bPassthrough);
+  static IAudioRenderer *Create(IAudioCallback* pCallback, int iChannels, uint8_t *channelMap, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, const char* strAudioCodec, bool bIsMusic, bool bPassthrough);
   static void EnumerateAudioSinks(AudioSinkList& vAudioSinks, bool passthrough);
 private:
   static IAudioRenderer *CreateFromUri(const CStdString &soundsystem);
Index: xbmc/cores/AudioRenderers/ALSADirectSound.h
===================================================================
--- xbmc/cores/AudioRenderers/ALSADirectSound.h	(revision 26651)
+++ xbmc/cores/AudioRenderers/ALSADirectSound.h	(working copy)
@@ -51,7 +51,7 @@
   virtual float GetCacheTime();
   virtual float GetCacheTotal();
   CALSADirectSound();
-  virtual bool Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, const char* strAudioCodec = "", bool bIsMusic=false, bool bPassthrough = false);
+  virtual bool Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, uint8_t *channelMap, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, const char* strAudioCodec = "", bool bIsMusic=false, bool bPassthrough = false);
   virtual ~CALSADirectSound();
 
   virtual unsigned int AddPackets(const void* data, unsigned int len);
Index: xbmc/cores/paplayer/PAPlayer.h
===================================================================
--- xbmc/cores/paplayer/PAPlayer.h	(revision 26651)
+++ xbmc/cores/paplayer/PAPlayer.h	(working copy)
@@ -166,6 +166,7 @@
 
   unsigned int     m_SampleRate;
   unsigned int     m_Channels;
+  uint8_t*         m_ChannelMap;
   unsigned int     m_BitsPerSample;
 
   unsigned int     m_SampleRateOutput;
@@ -179,6 +180,7 @@
 
   // format (this should be stored/retrieved from the audio device object probably)
   unsigned int     m_channelCount[2];
+  uint8_t*         m_channelMap[2];
   unsigned int     m_sampleRate[2];
   unsigned int     m_bitsPerSample[2];
   unsigned int     m_BytesPerSecond;
Index: xbmc/cores/paplayer/PAPlayer.cpp
===================================================================
--- xbmc/cores/paplayer/PAPlayer.cpp	(revision 26651)
+++ xbmc/cores/paplayer/PAPlayer.cpp	(working copy)
@@ -372,7 +372,7 @@
     m_BytesPerSecond      = (m_bitsPerSample[num] / 8)* outputSampleRate * channels;
 
     /* Open the device */
-    m_pAudioDecoder[num] = CAudioRendererFactory::Create(m_pCallback, m_channelCount[num], m_sampleRate[num], m_bitsPerSample[num], false, codec.c_str(), true, false);
+    m_pAudioDecoder[num] = CAudioRendererFactory::Create(m_pCallback, m_channelCount[num], m_channelMap[num], m_sampleRate[num], m_bitsPerSample[num], false, codec.c_str(), true, false);
 
     if (!m_pAudioDecoder[num]) return false;
 
Index: xbmc/utils/PCMRemap.h
===================================================================
--- xbmc/utils/PCMRemap.h	(revision 0)
+++ xbmc/utils/PCMRemap.h	(revision 0)
@@ -0,0 +1,65 @@
+#ifndef __PCM_REMAP__H__
+#define __PCM_REMAP__H__
+
+/*
+ *      Copyright (C) 2005-2010 Team XBMC
+ *      http://www.xbmc.org
+ *
+ *  This Program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  This Program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with XBMC; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *  http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#include <stdint.h>
+
+#define PCM_FRONT_LEFT            0
+#define PCM_FRONT_RIGHT           1
+#define PCM_FRONT_CENTER          2
+#define PCM_LOW_FREQUENCY         3
+#define PCM_BACK_LEFT             4
+#define PCM_BACK_RIGHT            5
+#define PCM_FRONT_LEFT_OF_CENTER  6
+#define PCM_FRONT_RIGHT_OF_CENTER 7
+#define PCM_BACK_CENTER           8
+#define PCM_SIDE_LEFT             9
+#define PCM_SIDE_RIGHT            10
+#define PCM_TOP_CENTER            11
+#define PCM_TOP_FRONT_LEFT        12
+#define PCM_TOP_FRONT_CENTER      13
+#define PCM_TOP_FRONT_RIGHT       14
+#define PCM_TOP_BACK_LEFT         15
+#define PCM_TOP_BACK_CENTER       16
+#define PCM_TOP_BACK_RIGHT        17
+
+class CPCMRemap
+{
+protected:
+  bool     m_inSet     , m_outSet;
+  uint8_t  m_inChannels, m_outChannels;
+  uint8_t *m_inMap     , *m_outMap;
+  uint8_t  m_inSampleSize;
+  uint8_t *m_chLookup;
+
+  void BuildMap();
+public:
+  CPCMRemap();
+  ~CPCMRemap();
+
+  void SetInputFormat (uint8_t channels, uint8_t *channelMap, uint8_t sampleSize);
+  void SetOutputFormat(uint8_t channels, uint8_t *channelMap);
+  void Remap(void *data, void *out, unsigned int samples);
+};
+
+#endif
Index: xbmc/utils/PCMRemap.cpp
===================================================================
--- xbmc/utils/PCMRemap.cpp	(revision 0)
+++ xbmc/utils/PCMRemap.cpp	(revision 0)
@@ -0,0 +1,123 @@
+/*
+ *      Copyright (C) 2005-2010 Team XBMC
+ *      http://www.xbmc.org
+ *
+ *  This Program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  This Program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with XBMC; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *  http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#include "PCMRemap.h"
+#include <cstdlib>
+#include <string.h>
+#include <stdio.h>
+
+CPCMRemap::CPCMRemap() :
+  m_inSet   (false),
+  m_outSet  (false),
+  m_chLookup(NULL )
+{
+}
+
+CPCMRemap::~CPCMRemap()
+{
+  if (m_chLookup != NULL)
+    free(m_chLookup);
+}
+
+/*
+  builds a lookup table to convert from the input mapping to the output
+  mapping, this decreases the amount of work per sample to remap it.
+*/
+void CPCMRemap::BuildMap()
+{
+  unsigned int in_ch, out_ch;
+
+  if (!m_inSet || !m_outSet) return;
+  if (m_chLookup != NULL)
+  {
+    free(m_chLookup);
+    m_chLookup = NULL;
+  }
+
+  m_chLookup = (uint8_t*)malloc(m_inChannels);
+  for(in_ch = 0; in_ch < m_inChannels; ++in_ch)
+  {
+    for(out_ch = 0; out_ch < m_outChannels; ++out_ch)
+    {
+      if (m_outMap[out_ch] == m_inMap[in_ch])
+      {
+        m_chLookup[in_ch] = out_ch;
+        break;
+      }
+    }
+  }
+
+}
+
+/* sets the input format */
+void CPCMRemap::SetInputFormat(uint8_t channels, uint8_t *channelMap, uint8_t sampleSize)
+{
+  m_inChannels   = channels;
+  m_inMap        = channelMap;
+  m_inSampleSize = sampleSize;
+  m_inSet        = true;
+
+  BuildMap();
+}
+
+/* sets the output format required */
+void CPCMRemap::SetOutputFormat(uint8_t channels, uint8_t *channelMap)
+{
+  m_outChannels   = channels;
+  m_outMap        = channelMap;
+  m_outSet        = true;
+
+  BuildMap();
+}
+
+/* remap the supplied data into out, which must be pre-allocated */
+void CPCMRemap::Remap(void *data, void *out, unsigned int samples)
+{
+  unsigned int i, ch;
+  uint8_t      *insample, *outsample;
+  uint8_t      *src, *dst;
+
+  insample  = (uint8_t*)data;
+  outsample = (uint8_t*)out;
+
+  /*
+    the output may have channels the input does not have, so zero the data
+    to stop random data being sent to them, it would be nice to add a
+    up/down mixer to this class to emulate the missing channels, anyone?.
+  */
+  memset(out, 0, m_inSampleSize * m_outChannels);
+
+  for(i = 0; i < samples; ++i)
+  {
+    for(ch = 0; ch < m_inChannels; ++ch)
+    {
+      if (m_chLookup[ch] != ch)
+      {
+        src = insample  + m_chLookup[ch] * m_inSampleSize;
+        dst = outsample +            ch  * m_inSampleSize;
+        memcpy(dst, src, m_inSampleSize);
+      }
+    }
+    insample  += m_inSampleSize * m_inChannels;
+    outsample += m_inSampleSize * m_outChannels;
+  }
+}
+
Index: xbmc/utils/Makefile
===================================================================
--- xbmc/utils/Makefile	(revision 26657)
+++ xbmc/utils/Makefile	(working copy)
@@ -32,6 +32,7 @@
      Win32Exception.cpp \
      CPUInfo.cpp \
      PCMAmplifier.cpp \
+     PCMRemap.cpp \
      LabelFormatter.cpp \
      Network.cpp \
      BitstreamStats.cpp \