diff -Naur --exclude=.svn a/mythplugins/mythmusic/mythmusic/main.cpp c/mythplugins/mythmusic/mythmusic/main.cpp
--- a/mythplugins/mythmusic/mythmusic/main.cpp	2009-06-01 02:25:52.000000000 +1000
+++ c/mythplugins/mythmusic/mythmusic/main.cpp	2009-06-01 02:14:00.000000000 +1000
@@ -378,6 +378,7 @@
     REG_KEY("Music", "VOLUMEDOWN", "Volume down",       "[,{,F10,Volume Down");
     REG_KEY("Music", "VOLUMEUP",   "Volume up",         "],},F11,Volume Up");
     REG_KEY("Music", "MUTE",       "Mute",              "|,\\,F9,Volume Mute");
+    REG_KEY("Music", "TOGGLEUPMIX","Toggle upmixer",             "Ctrl+U");
     REG_KEY("Music", "CYCLEVIS",   "Cycle visualizer mode",      "6");
     REG_KEY("Music", "BLANKSCR",   "Blank screen",               "5");
     REG_KEY("Music", "THMBUP",     "Increase rating",            "9");
diff -Naur --exclude=.svn a/mythplugins/mythmusic/mythmusic/musicplayer.cpp c/mythplugins/mythmusic/mythmusic/musicplayer.cpp
--- a/mythplugins/mythmusic/mythmusic/musicplayer.cpp	2009-06-01 02:25:53.000000000 +1000
+++ c/mythplugins/mythmusic/mythmusic/musicplayer.cpp	2009-06-01 02:14:00.000000000 +1000
@@ -347,16 +347,22 @@
 
 void MusicPlayer::openOutputDevice(void)
 {
-    QString adevice;
+    QString adevice, pdevice;
+    bool isAC3upmix = gContext->GetNumSetting("MythAC3Upmix", 0);
 
     if (gContext->GetSetting("MusicAudioDevice") == "default")
         adevice = gContext->GetSetting("AudioOutputDevice");
     else
         adevice = gContext->GetSetting("MusicAudioDevice");
 
+    if (!isAC3upmix)
+        pdevice = "default";
+    else
+        pdevice = gContext->GetSetting("PassThruOutputDevice");
+
     // TODO: Error checking that device is opened correctly!
-    m_output = AudioOutput::OpenAudio(adevice, "default", 16, 2, 44100,
-                                    AUDIOOUTPUT_MUSIC, true, false);
+    m_output = AudioOutput::OpenAudio(adevice, pdevice, 16, 2, 44100,
+                                    AUDIOOUTPUT_MUSIC, true, false, isAC3upmix);
     m_output->setBufferSize(256 * 1024);
     m_output->SetBlocking(false);
 
diff -Naur --exclude=.svn a/mythplugins/mythmusic/mythmusic/playbackbox.cpp c/mythplugins/mythmusic/mythmusic/playbackbox.cpp
--- a/mythplugins/mythmusic/mythmusic/playbackbox.cpp	2009-06-01 02:25:52.000000000 +1000
+++ c/mythplugins/mythmusic/mythmusic/playbackbox.cpp	2009-06-01 02:14:00.000000000 +1000
@@ -358,6 +358,8 @@
             changeSpeed(true);
         else if (action == "MUTE")
             toggleMute();
+        else if (action == "TOGGLEUPMIX")
+            toggleUpmix();
         else if (action == "MENU" && visualizer_status != 2)
         {
             menufilters = false;
@@ -1178,6 +1180,13 @@
     }
 }
 
+void PlaybackBoxMusic::toggleUpmix()
+{
+    if (gPlayer->getOutput())
+        gPlayer->getOutput()->ToggleUpmix();
+}
+    
+
 void PlaybackBoxMusic::showProgressBar()
 {
     if (progress_bar)
diff -Naur --exclude=.svn a/mythplugins/mythmusic/mythmusic/playbackbox.h c/mythplugins/mythmusic/mythmusic/playbackbox.h
--- a/mythplugins/mythmusic/mythmusic/playbackbox.h	2009-06-01 02:25:53.000000000 +1000
+++ c/mythplugins/mythmusic/mythmusic/playbackbox.h	2009-06-01 02:14:00.000000000 +1000
@@ -69,6 +69,7 @@
     void changeVolume(bool up_or_down);
     void changeSpeed(bool up_or_down);
     void toggleMute();
+    void toggleUpmix();
     void resetTimer();
     void hideVolume(){showVolume(false);}
     void showVolume(bool on_or_off);
diff -Naur --exclude=.svn a/mythtv/libs/libmyth/audiooutput.cpp c/mythtv/libs/libmyth/audiooutput.cpp
--- a/mythtv/libs/libmyth/audiooutput.cpp	2009-05-02 07:32:08.000000000 +1000
+++ c/mythtv/libs/libmyth/audiooutput.cpp	2009-06-01 02:14:00.000000000 +1000
@@ -36,7 +36,7 @@
                                     int audio_bits,
                                     int audio_channels, int audio_samplerate,
                                     AudioOutputSource source,
-                                    bool set_initial_vol, bool audio_passthru)
+                                    bool set_initial_vol, bool audio_passthru, bool AC3upmix)
 {
     if (passthru_device.isEmpty() || passthru_device.lower() == "default")
         passthru_device = main_device;
@@ -47,7 +47,7 @@
         return new AudioOutputALSA(main_device.remove(0, 5),
                                    passthru_device.remove(0, 5), audio_bits,
                                    audio_channels, audio_samplerate, source,
-                                   set_initial_vol, audio_passthru);
+                                   set_initial_vol, audio_passthru, AC3upmix);
 #else
         VERBOSE(VB_IMPORTANT, "Audio output device is set to an ALSA device "
                               "but ALSA support is not compiled in!");
diff -Naur --exclude=.svn a/mythtv/libs/libmyth/audiooutput.h c/mythtv/libs/libmyth/audiooutput.h
--- a/mythtv/libs/libmyth/audiooutput.h	2009-05-02 07:32:08.000000000 +1000
+++ c/mythtv/libs/libmyth/audiooutput.h	2009-06-01 02:14:00.000000000 +1000
@@ -22,11 +22,12 @@
                                   int audio_bits,
                                   int audio_channels, int audio_samplerate,
                                   AudioOutputSource source,
-                                  bool set_initial_vol, bool audio_passthru);
+                                  bool set_initial_vol, bool audio_passthru, bool AC3upmix=false);
 
     AudioOutput() :
         VolumeBase(),             OutputListeners(),
-        lastError(QString::null), lastWarn(QString::null) {}
+        isAC3upmix(false),
+        lastError(QString::null), lastWarn(QString::null) { };
 
     virtual ~AudioOutput() { };
 
@@ -39,6 +40,8 @@
     
     virtual void SetStretchFactor(float factor);
     virtual float GetStretchFactor(void) { return 1.0f; }
+    virtual bool ToggleUpmix(void) = 0;
+    bool isAC3upmix;
 
     // do AddSamples calls block?
     virtual void SetBlocking(bool blocking) = 0;
diff -Naur --exclude=.svn a/mythtv/libs/libmyth/audiooutputalsa.cpp c/mythtv/libs/libmyth/audiooutputalsa.cpp
--- a/mythtv/libs/libmyth/audiooutputalsa.cpp	2009-05-02 07:32:08.000000000 +1000
+++ c/mythtv/libs/libmyth/audiooutputalsa.cpp	2009-06-01 02:14:45.000000000 +1000
@@ -8,6 +8,7 @@
 
 #include "mythcontext.h"
 #include "audiooutputalsa.h"
+#include "audiooutputdigitalencoder.h"
     
 #define LOC QString("ALSA: ")
 #define LOC_WARN QString("ALSA, Warning: ")
@@ -17,11 +18,13 @@
     QString laudio_main_device, QString           laudio_passthru_device,
     int     laudio_bits,        int               laudio_channels,
     int     laudio_samplerate,  AudioOutputSource lsource,
-    bool    lset_initial_vol,   bool              laudio_passthru) :
+    bool    lset_initial_vol,   bool              laudio_passthru,
+    bool    AC3upmix) :
     AudioOutputBase(laudio_main_device, laudio_passthru_device,
                     laudio_bits,        laudio_channels,
                     laudio_samplerate,  lsource,
-                    lset_initial_vol,   laudio_passthru),
+                    lset_initial_vol,   laudio_passthru,
+                    AC3upmix),
     pcm_handle(NULL),             numbadioctls(0),
     killAudioLock(false),         mixer_handle(NULL),
     mixer_control(QString::null), volume_range_multiplier(1.0f),
@@ -35,6 +38,62 @@
 AudioOutputALSA::~AudioOutputALSA()
 {
     KillAudio();
+    if (isAC3upmix)
+        SetIECStatus(true);
+}
+
+void AudioOutputALSA::SetIECStatus(bool audio) {
+    
+    snd_ctl_t *ctl;
+    const char *spdif_str = SND_CTL_NAME_IEC958("", PLAYBACK, DEFAULT);
+    int spdif_index = -1;
+    snd_ctl_elem_list_t *clist;
+    snd_ctl_elem_id_t *cid;
+    snd_ctl_elem_value_t *cval;
+    snd_aes_iec958_t iec958;
+    int cidx, controls;
+
+    VERBOSE(VB_AUDIO, QString("Setting IEC958 status: %1")
+                      .arg(audio ? "audio" : "non-audio"));
+    
+    int err;
+    if ((err = snd_ctl_open(&ctl, "default", 0)) < 0)
+    {
+        Error(QString("AudioOutputALSA::SetIECStatus: snd_ctl_open(default): %1")
+              .arg(snd_strerror(err)));
+        return;
+    }
+    snd_ctl_elem_list_alloca(&clist);
+    snd_ctl_elem_list(ctl, clist);
+    snd_ctl_elem_list_alloc_space(clist, snd_ctl_elem_list_get_count(clist));
+    snd_ctl_elem_list(ctl, clist);
+    controls = snd_ctl_elem_list_get_used(clist);
+    for (cidx = 0; cidx < controls; cidx++) 
+    {
+        if (!strcmp(snd_ctl_elem_list_get_name(clist, cidx), spdif_str))
+            if (spdif_index < 0 ||
+                snd_ctl_elem_list_get_index(clist, cidx) == (uint)spdif_index)
+                    break;
+    }
+
+    if (cidx >= controls)
+        return;
+
+    snd_ctl_elem_id_alloca(&cid);
+    snd_ctl_elem_list_get_id(clist, cidx, cid);
+    snd_ctl_elem_value_alloca(&cval);
+    snd_ctl_elem_value_set_id(cval, cid);
+    snd_ctl_elem_read(ctl,cval);
+    snd_ctl_elem_value_get_iec958(cval, &iec958);
+    
+    if (!audio) 
+        iec958.status[0] |= IEC958_AES0_NONAUDIO;
+    else
+        iec958.status[0] &= ~IEC958_AES0_NONAUDIO;
+
+    snd_ctl_elem_value_set_iec958(cval, &iec958);
+    snd_ctl_elem_write(ctl, cval);
+
 }
 
 bool AudioOutputALSA::OpenDevice()
@@ -42,6 +101,7 @@
     snd_pcm_format_t format;
     unsigned int buffer_time, period_time;
     int err;
+    QString real_device;
 
     if (pcm_handle != NULL)
         CloseDevice();
@@ -49,8 +109,21 @@
     pcm_handle = NULL;
     numbadioctls = 0;
 
-    QString real_device = (audio_passthru) ?
-        audio_passthru_device : audio_main_device;
+    if (!isAC3upmix) {
+        real_device = (audio_passthru) ?
+            audio_passthru_device : audio_main_device;
+    }
+    else
+        if (audio_passthru || audio_enc)
+        {
+            real_device = audio_passthru_device;
+            SetIECStatus(false);
+        }
+        else 
+        {
+            real_device = audio_main_device;
+            SetIECStatus(true);
+        }
 
     VERBOSE(VB_GENERAL, QString("Opening ALSA audio device '%1'.")
             .arg(real_device));
@@ -148,6 +221,20 @@
 }
 
 
+void AudioOutputALSA::reorder_6ch_ac3(void *buf, unsigned int len) {
+    unsigned short *src = (unsigned short *)buf;
+    unsigned short tmp;
+    unsigned int samples = len >> 1;
+
+    for (uint i = 0; i < samples; i += 6) {
+        tmp = src[i+1];
+        src[i+1] = src[i+2];
+        src[i+2] = src[i+3];
+        src[i+3] = src[i+4];
+        src[i+4] = tmp;
+    }
+}
+
 void AudioOutputALSA::WriteAudio(unsigned char *aubuf, int size)
 {
     unsigned char *tmpbuf;
@@ -159,7 +246,16 @@
         VERBOSE(VB_IMPORTANT, QString("WriteAudio() called with pcm_handle == NULL!"));
         return;
     }
-    
+
+    // Re-Order channels mapping if analog output is used and source is AC3 multi-channels
+    if (isAC3upmix && !(audio_passthru || audio_enc)
+        && audio_codec && (audio_codec->codec_id == CODEC_ID_AC3)
+        && (source_audio_channels > 2)) {
+        VERBOSE(VB_AUDIO|VB_TIMESTAMP,
+                QString("WriteAudio: Re-ordering audio channels %1 bytes (%2 frames)")
+                .arg(size).arg(frames));
+        reorder_6ch_ac3(aubuf, size);
+    }
     tmpbuf = aubuf;
 
     VERBOSE(VB_AUDIO|VB_TIMESTAMP,
diff -Naur --exclude=.svn a/mythtv/libs/libmyth/audiooutputalsa.h c/mythtv/libs/libmyth/audiooutputalsa.h
--- a/mythtv/libs/libmyth/audiooutputalsa.h	2009-05-02 07:32:09.000000000 +1000
+++ c/mythtv/libs/libmyth/audiooutputalsa.h	2009-06-01 02:14:00.000000000 +1000
@@ -20,7 +20,8 @@
                     int laudio_bits,
                     int laudio_channels, int laudio_samplerate,
                     AudioOutputSource source,
-                    bool set_initial_vol, bool laudio_passthru);
+                    bool set_initial_vol, bool laudio_passthru,
+                    bool AC3upmix = false);
     virtual ~AudioOutputALSA();
 
     // Volume control
@@ -37,6 +38,7 @@
     virtual inline int getBufferedOnSoundcard(void);
 
   private:
+    void SetIECStatus(bool audio);
     inline int SetParameters(snd_pcm_t *handle,
                              snd_pcm_format_t format, unsigned int channels,
                              unsigned int rate, unsigned int buffer_time,
@@ -49,6 +51,7 @@
     void CloseMixer(void);
     void SetupMixer(void);
     void GetVolumeRange(snd_mixer_elem_t *elem);
+    void reorder_6ch_ac3(void *buf, unsigned int len);
 
   private:
     snd_pcm_t   *pcm_handle;
diff -Naur --exclude=.svn a/mythtv/libs/libmyth/audiooutputbase.cpp c/mythtv/libs/libmyth/audiooutputbase.cpp
--- a/mythtv/libs/libmyth/audiooutputbase.cpp	2009-05-02 07:32:08.000000000 +1000
+++ c/mythtv/libs/libmyth/audiooutputbase.cpp	2009-06-01 02:14:00.000000000 +1000
@@ -27,7 +27,8 @@
     QString laudio_main_device,    QString           laudio_passthru_device,
     int     /*laudio_bits*/,       int               /*laudio_channels*/,
     int     /*laudio_samplerate*/, AudioOutputSource lsource,
-    bool    lset_initial_vol,      bool              /*laudio_passthru*/) :
+    bool    lset_initial_vol,      bool              /*laudio_passthru*/,
+    bool    AC3upmix) :
 
     effdsp(0),                  effdspstretched(0),
     audio_channels(-1),         audio_bytes_per_sample(0),
@@ -37,7 +38,8 @@
 
     audio_main_device(QDeepCopy<QString>(laudio_main_device)),
     audio_passthru_device(QDeepCopy<QString>(laudio_passthru_device)),
-    audio_passthru(false),      audio_stretchfactor(1.0f),
+    audio_passthru(false),      audio_enc(false),
+    audio_reenc(false),         audio_stretchfactor(1.0f),
 
     audio_codec(NULL),
     source(lsource),            killaudio(false),
@@ -54,10 +56,13 @@
     pSoundStretch(NULL),        
     encoder(NULL),
     upmixer(NULL),
+
     source_audio_channels(-1),
+    source_audio_samplerate(0),
     source_audio_bytes_per_sample(0),
     needs_upmix(false),
     surround_mode(FreeSurround::SurroundModePassive),
+    old_audio_stretchfactor(1.0),
 
     blocking(false),
 
@@ -84,6 +89,10 @@
     memset(&audiotime_updated, 0, sizeof(audiotime_updated));
     memset(audiobuffer,        0, sizeof(char)  * AUDBUFSIZE);
     configured_audio_channels = gContext->GetNumSetting("MaxChannels", 2);
+    orig_config_channels = configured_audio_channels;
+    allow_ac3_passthru = gContext->GetNumSetting("AC3PassThru", false);
+    src_quality = gContext->GetNumSetting("SRCQuality", 3);
+    isAC3upmix = AC3upmix;
 
     // You need to call Reconfigure from your concrete class.
     // Reconfigure(laudio_bits,       laudio_channels,
@@ -110,7 +119,7 @@
 void AudioOutputBase::SetStretchFactorLocked(float laudio_stretchfactor)
 {
     effdspstretched = (int)((float)effdsp / laudio_stretchfactor);
-    if (audio_stretchfactor != laudio_stretchfactor)
+    if ((audio_stretchfactor != laudio_stretchfactor) || !pSoundStretch)
     {
         audio_stretchfactor = laudio_stretchfactor;
         if (pSoundStretch)
@@ -124,48 +133,52 @@
             VERBOSE(VB_GENERAL, LOC + QString("Using time stretch %1")
                                         .arg(audio_stretchfactor));
             pSoundStretch = new soundtouch::SoundTouch();
-            if (audio_codec)
-            {
-                if (!encoder)
+            if (!isAC3upmix) {
+                if (audio_codec)
                 {
-                    VERBOSE(VB_AUDIO, LOC +
-                            QString("Creating Encoder for codec %1 origfs %2")
-                            .arg(audio_codec->codec_id)
-                            .arg(audio_codec->frame_size));
-
-                    encoder = new AudioOutputDigitalEncoder();
-                    if (!encoder->Init(audio_codec->codec_id,
-                                audio_codec->bit_rate,
-                                audio_codec->sample_rate,
-                                audio_codec->channels
-                                ))
+                    if (!encoder)
                     {
-                        // eeks
-                        delete encoder;
-                        encoder = NULL;
                         VERBOSE(VB_AUDIO, LOC +
-                                QString("Failed to Create Encoder"));
+                                QString("Creating Encoder for codec %1 origfs %2")
+                                .arg(audio_codec->codec_id)
+                                .arg(audio_codec->frame_size));
+
+                        encoder = new AudioOutputDigitalEncoder(isAC3upmix);
+                        if (!encoder->Init(audio_codec->codec_id,
+                                    audio_codec->bit_rate,
+                                    audio_codec->sample_rate,
+                                    audio_codec->channels
+                                    ))
+                        {
+                            // eeks
+                            delete encoder;
+                            encoder = NULL;
+                            VERBOSE(VB_AUDIO, LOC +
+                                    QString("Failed to Create Encoder"));
+                        }
                     }
                 }
-            }
-            if (audio_codec && encoder)
-            {
-                pSoundStretch->setSampleRate(audio_codec->sample_rate);
-                pSoundStretch->setChannels(audio_codec->channels);
-            }
-            else
-            {
+                if (audio_codec && encoder)
+                {
+                    pSoundStretch->setSampleRate(audio_codec->sample_rate);
+                    pSoundStretch->setChannels(audio_codec->channels);
+                }
+                else
+                {
+                    pSoundStretch->setSampleRate(audio_samplerate);
+                    pSoundStretch->setChannels(audio_channels);
+                }
+            } else {
                 pSoundStretch->setSampleRate(audio_samplerate);
-                pSoundStretch->setChannels(audio_channels);
+                pSoundStretch->setChannels(upmixer ? 
+                    configured_audio_channels : source_audio_channels);
             }
-
             pSoundStretch->setTempo(audio_stretchfactor);
             pSoundStretch->setSetting(SETTING_SEQUENCE_MS, 35);
 
             // dont need these with only tempo change
             //pSoundStretch->setPitch(1.0);
             //pSoundStretch->setRate(1.0);
-
             //pSoundStretch->setSetting(SETTING_USE_QUICKSEEK, true);
             //pSoundStretch->setSetting(SETTING_USE_AA_FILTER, false);
         }
@@ -184,6 +197,20 @@
     return audio_stretchfactor;
 }
 
+bool AudioOutputBase::ToggleUpmix(void)
+{
+    if (orig_config_channels == 2 || audio_passthru)
+        return false;
+    if (configured_audio_channels == 6)
+        configured_audio_channels = 2;
+    else
+        configured_audio_channels = 6;
+    
+    Reconfigure(audio_bits, source_audio_channels, 
+        source_audio_samplerate, audio_passthru);
+    return (configured_audio_channels == 6);
+}
+
 void AudioOutputBase::Reconfigure(int laudio_bits, int laudio_channels, 
                                   int laudio_samplerate, bool laudio_passthru,
                                   void *laudio_codec)
@@ -194,38 +221,56 @@
     int cchannels = 0;
     int lsource_audio_channels = laudio_channels;
     bool lneeds_upmix = false;
+    bool laudio_reenc = false;
 
-    if (laudio_codec)
-    {
-        lcodec_id = ((AVCodecContext*)laudio_codec)->codec_id;
-        laudio_bits = 16;
-        laudio_channels = 2;
-        lsource_audio_channels = laudio_channels;
-        laudio_samplerate = 48000;
-        lcchannels = ((AVCodecContext*)laudio_codec)->channels;
-    }
+    if (!isAC3upmix) {
+        if (laudio_codec)
+        {
+            lcodec_id = ((AVCodecContext*)laudio_codec)->codec_id;
+            laudio_bits = 16;
+            laudio_channels = 2;
+            lsource_audio_channels = laudio_channels;
+            laudio_samplerate = 48000;
+            lcchannels = ((AVCodecContext*)laudio_codec)->channels;
+        }
 
-    if (audio_codec)
-    {
-        codec_id = audio_codec->codec_id;
-        cchannels = ((AVCodecContext*)audio_codec)->channels;
-    }
+        if (audio_codec)
+        {
+            codec_id = audio_codec->codec_id;
+            cchannels = ((AVCodecContext*)audio_codec)->channels;
+        }
 
-    if ((configured_audio_channels == 6) && 
-        !(laudio_codec || audio_codec))
-    {
-        laudio_channels = configured_audio_channels;
-        lneeds_upmix = true;
-        VERBOSE(VB_AUDIO,LOC + "Needs upmix");
+        if ((configured_audio_channels == 6) && 
+            !(laudio_codec || audio_codec))
+        {
+            laudio_channels = configured_audio_channels;
+            lneeds_upmix = true;
+            VERBOSE(VB_AUDIO,LOC + "Needs upmix");
+        }
+    } else { //AC3 Upmix
+        // Are we perhaps reencoding a (previously) timestretched bitstream?
+        if (laudio_channels > 2 && !laudio_passthru)
+            laudio_reenc = true;
+  
+        // Enough channels? Upmix if not
+        if (laudio_channels < configured_audio_channels && !laudio_passthru)
+        {
+            laudio_channels = configured_audio_channels;
+            lneeds_upmix = true;
+            VERBOSE(VB_AUDIO,LOC + "Needs upmix");
+        }
+        if (laudio_codec)
+            audio_codec = (AVCodecContext*)laudio_codec;
     }
-
+    
     ClearError();
     bool general_deps = (laudio_bits == audio_bits && 
         laudio_channels == audio_channels &&
         laudio_samplerate == audio_samplerate && !need_resampler &&
         laudio_passthru == audio_passthru &&
         lneeds_upmix == needs_upmix &&
-        lcodec_id == codec_id && lcchannels == cchannels);
+        (isAC3upmix ? (laudio_reenc == audio_reenc) : (lcodec_id == codec_id && lcchannels == cchannels))
+        );
     bool upmix_deps =
         (lsource_audio_channels == source_audio_channels);
     if (general_deps && upmix_deps)
@@ -256,8 +301,13 @@
     audio_channels = laudio_channels;
     source_audio_channels = lsource_audio_channels;
     audio_bits = laudio_bits;
-    audio_samplerate = laudio_samplerate;
-    audio_codec = (AVCodecContext*)laudio_codec;
+    if (!isAC3upmix) {
+        audio_samplerate = laudio_samplerate;
+        audio_codec = (AVCodecContext*)laudio_codec;
+    } else {
+        source_audio_samplerate = audio_samplerate = laudio_samplerate;
+        audio_reenc = laudio_reenc;
+    }
     audio_passthru = laudio_passthru;
     needs_upmix = lneeds_upmix;
 
@@ -268,8 +318,6 @@
         Error("AudioOutput only supports 8 or 16bit audio.");
         return;
     }
-    audio_bytes_per_sample = audio_channels * audio_bits / 8;
-    source_audio_bytes_per_sample = source_audio_channels * audio_bits / 8;
     
     need_resampler = false;
     killaudio = false;
@@ -279,6 +327,61 @@
     
     numlowbuffer = 0;
 
+    if (!isAC3upmix) {
+    audio_bytes_per_sample = audio_channels * audio_bits / 8;
+    source_audio_bytes_per_sample = source_audio_channels * audio_bits / 8;
+    } else {
+    // Encode to AC-3 if not passing thru, there's more than 2 channels
+    // and we're allowed to passthru AC-3
+    // This won't reencode timestretched 2ch AC-3 but there's no point doing so
+    if (!audio_passthru && audio_channels > 2 && allow_ac3_passthru) 
+    {
+        VERBOSE(VB_AUDIO, LOC + "Creating AC-3 Encoder");
+        int srate = src_quality == 0 ? audio_samplerate : 48000;
+        encoder = new AudioOutputDigitalEncoder(isAC3upmix);
+        if (!encoder->Init(CODEC_ID_AC3, 448000, srate, 
+                           audio_channels, audio_reenc)) 
+        {
+            VERBOSE(VB_AUDIO, LOC + "Can't create AC-3 encoder");
+            delete encoder;
+            encoder = NULL;
+        }
+        
+        audio_enc = true;
+    }        
+    
+    if(audio_passthru || audio_enc)
+        // AC-3 output - soundcard expects a 2ch 48k stream
+	audio_channels = 2;
+    
+    audio_bytes_per_sample = audio_channels * audio_bits / 8;
+    source_audio_bytes_per_sample = source_audio_channels * audio_bits / 8;
+
+    // Always resample to 48k - many cards can't do anything else
+    // and ALSA will do it with linear interpolation (yuk) if we don't anyway
+    if (src_quality != 0 && audio_samplerate != 48000)
+    {
+        int error;
+        audio_samplerate = 48000;
+        VERBOSE(VB_GENERAL, LOC + QString("Using resampler. From: %1 to %2")
+            .arg(laudio_samplerate).arg(audio_samplerate));
+        src_ctx = src_new(3-src_quality, audio_channels, &error);
+        if (error)
+        {
+            Error(QString("Error creating resampler, the error was: %1")
+                  .arg(src_strerror(error)) );
+            pthread_mutex_unlock(&avsync_lock);
+            pthread_mutex_unlock(&audio_buflock);
+	    src_ctx = NULL;
+            return;
+        }
+        src_data.src_ratio = (double) audio_samplerate / laudio_samplerate;
+        src_data.data_in = src_in;
+        src_data.data_out = src_out;
+        src_data.output_frames = 16384*6;
+        need_resampler = true;
+    }
+    }
     VERBOSE(VB_GENERAL, QString("Opening audio device '%1'. ch %2(%3) sr %4")
             .arg(audio_main_device).arg(audio_channels)
             .arg(source_audio_channels).arg(audio_samplerate));
@@ -314,6 +417,7 @@
     current_seconds = -1;
     source_bitrate = -1;
 
+    if (!isAC3upmix) {
     // NOTE: this won't do anything as above samplerate vars are set equal
     // Check if we need the resampler
     if (audio_samplerate != laudio_samplerate)
@@ -336,7 +440,7 @@
         src_data.output_frames = 16384*6;
         need_resampler = true;
     }
-
+    }
     if (needs_upmix)
     {
         VERBOSE(VB_AUDIO, LOC + QString("create upmixer"));
@@ -348,7 +452,7 @@
         upmixer = new FreeSurround(
             audio_samplerate, 
             source == AUDIOOUTPUT_VIDEO, 
-            (FreeSurround::SurroundMode)surround_mode);
+            (FreeSurround::SurroundMode)surround_mode,isAC3upmix);
 
         VERBOSE(VB_AUDIO, LOC +
                 QString("create upmixer done with surround mode %1")
@@ -357,59 +461,60 @@
 
     VERBOSE(VB_AUDIO, LOC + QString("Audio Stretch Factor: %1")
             .arg(audio_stretchfactor));
-    VERBOSE(VB_AUDIO, QString("Audio Codec Used: %1")
-            .arg((audio_codec) ?
-                 codec_id_string(audio_codec->codec_id) : "not set"));
-
-    if (redo_stretch)
-    {
-        float laudio_stretchfactor = audio_stretchfactor;
-        delete pSoundStretch;
-        pSoundStretch = NULL;
-        audio_stretchfactor = 0.0f;
-        SetStretchFactorLocked(laudio_stretchfactor);
-    }
-    else
-    {
-        SetStretchFactorLocked(audio_stretchfactor);
-        if (pSoundStretch)
+    if (!isAC3upmix) {
+        VERBOSE(VB_AUDIO, QString("Audio Codec Used: %1")
+                .arg((audio_codec) ?
+                  codec_id_string(audio_codec->codec_id) : "not set"));
+
+        if (redo_stretch)
+        {
+            delete pSoundStretch;
+            pSoundStretch = NULL;
+            SetStretchFactorLocked(audio_stretchfactor);
+        }
+        else
         {
-            // if its passthru then we need to reencode
-            if (audio_codec)
+            SetStretchFactorLocked(audio_stretchfactor);
+            if (pSoundStretch)
             {
-                if (!encoder)
+                // if its passthru then we need to reencode
+                if (audio_codec)
                 {
-                    VERBOSE(VB_AUDIO, LOC +
-                            QString("Creating Encoder for codec %1")
-                            .arg(audio_codec->codec_id));
-
-                    encoder = new AudioOutputDigitalEncoder();
-                    if (!encoder->Init(audio_codec->codec_id,
-                                audio_codec->bit_rate,
-                                audio_codec->sample_rate,
-                                audio_codec->channels
-                                ))
+                    if (!encoder)
                     {
-                        // eeks
-                        delete encoder;
-                        encoder = NULL;
-                        VERBOSE(VB_AUDIO, LOC + "Failed to Create Encoder");
+                        VERBOSE(VB_AUDIO, LOC +
+                                QString("Creating Encoder for codec %1")
+                                .arg(audio_codec->codec_id));
+
+                        encoder = new AudioOutputDigitalEncoder(isAC3upmix);
+                        if (!encoder->Init(audio_codec->codec_id,
+                                    audio_codec->bit_rate,
+                                    audio_codec->sample_rate,
+                                    audio_codec->channels
+                                    ))
+                        {
+                            // eeks
+                            delete encoder;
+                            encoder = NULL;
+                            VERBOSE(VB_AUDIO, LOC + "Failed to Create Encoder");
+                        }
                     }
                 }
-            }
-            if (audio_codec && encoder)
-            {
-                pSoundStretch->setSampleRate(audio_codec->sample_rate);
-                pSoundStretch->setChannels(audio_codec->channels);
-            }
-            else
-            {
-                pSoundStretch->setSampleRate(audio_samplerate);
-                pSoundStretch->setChannels(audio_channels);
+                if (audio_codec && encoder)
+                {
+                    pSoundStretch->setSampleRate(audio_codec->sample_rate);
+                    pSoundStretch->setChannels(audio_codec->channels);
+                }
+                else
+                {
+                    pSoundStretch->setSampleRate(audio_samplerate);
+                    pSoundStretch->setChannels(audio_channels);
+                }
             }
         }
+    } else {
+        SetStretchFactorLocked(old_audio_stretchfactor);
     }
-
     // Setup visualisations, zero the visualisations buffers
     prepareVisuals();
 
@@ -456,9 +561,15 @@
     killaudio = true;
     StopOutputThread();
 
+    if (isAC3upmix)
+        pthread_mutex_lock(&audio_buflock);
+
     // Close resampler?
-    if (src_ctx)
+    if (src_ctx) {
         src_delete(src_ctx);
+        if (isAC3upmix)
+            src_ctx = NULL;
+    }
     need_resampler = false;
 
     // close sound stretcher
@@ -466,6 +577,10 @@
     {
         delete pSoundStretch;
         pSoundStretch = NULL;
+        if (isAC3upmix) {
+            old_audio_stretchfactor = audio_stretchfactor;
+            audio_stretchfactor = 1.0;
+        }
     }
 
     if (encoder)
@@ -480,9 +595,13 @@
         upmixer = NULL;
     }
     needs_upmix = false;
+    if (isAC3upmix)
+        audio_enc = false;
 
     CloseDevice();
 
+    if (isAC3upmix)
+        pthread_mutex_unlock(&audio_buflock);
     killAudioLock.unlock();
 }
 
@@ -642,10 +761,12 @@
     // include algorithmic latencies
     if (pSoundStretch)
     {
-        // add the effect of any unused but processed samples,
-        // AC3 reencode does this
-        totalbuffer += (int)(pSoundStretch->numSamples() *
-                             audio_bytes_per_sample);
+        if (!isAC3upmix) {
+            // add the effect of any unused but processed samples,
+            // AC3 reencode does this
+            totalbuffer += (int)(pSoundStretch->numSamples() *
+                                 audio_bytes_per_sample);
+        }
         // add the effect of unprocessed samples in time stretch algo
         totalbuffer += (int)((pSoundStretch->numUnprocessedSamples() *
                               audio_bytes_per_sample) / audio_stretchfactor);
@@ -656,6 +777,9 @@
         totalbuffer += upmixer->sampleLatency() * audio_bytes_per_sample;
     }
 
+    if (isAC3upmix && encoder) 
+        totalbuffer += encoder->Buffered();
+
     audiotime = audbuf_timecode - (int)(totalbuffer * 100000.0 /
                                    (audio_bytes_per_sample * effdspstretched));
  
@@ -709,6 +833,9 @@
         return false; // would overflow
     }
 
+    if (isAC3upmix)
+        pthread_mutex_lock(&audio_buflock);
+
     // resample input if necessary
     if (need_resampler && src_ctx) 
     {
@@ -742,6 +869,9 @@
         _AddSamples(buffers, false, samples, timecode);
     }
 
+    if (isAC3upmix)
+        pthread_mutex_unlock(&audio_buflock);
+
     return true;
 }
 
@@ -753,6 +883,12 @@
     int abps = (encoder) ?
         encoder->audio_bytes_per_sample : audio_bytes_per_sample;
     int len = samples * abps;
+ 
+    if (isAC3upmix) {
+        // Give original samples to mythmusic visualisation
+        dispatchVisual((unsigned char *)buffer, len, timecode,
+                       source_audio_channels, audio_bits);
+    }
 
     // Check we have enough space to write the data
     if (need_resampler && src_ctx)
@@ -777,6 +913,9 @@
         return false; // would overflow
     }
 
+    if (isAC3upmix)
+        pthread_mutex_lock(&audio_buflock);
+
     // resample input if necessary
     if (need_resampler && src_ctx) 
     {
@@ -805,6 +944,9 @@
         _AddSamples(buffer, true, samples, timecode);
     }
 
+    if (isAC3upmix)
+        pthread_mutex_unlock(&audio_buflock);
+
     return true;
 }
 
@@ -837,9 +979,13 @@
             {
                 int error = src_reset(src_ctx);
                 if (error)
+                {
                     VERBOSE(VB_IMPORTANT, LOC_ERR + QString(
                             "Error occured while resetting resampler: %1")
                             .arg(src_strerror(error)));
+                    if (isAC3upmix)
+                        src_ctx = NULL;
+                }
             }
         }
     }
@@ -849,7 +995,8 @@
 void AudioOutputBase::_AddSamples(void *buffer, bool interleaved, int samples, 
                                   long long timecode)
 {
-    pthread_mutex_lock(&audio_buflock);
+    if (!isAC3upmix)
+        pthread_mutex_lock(&audio_buflock);
 
     int len; // = samples * audio_bytes_per_sample;
     int audio_bytes = audio_bits / 8;
@@ -868,16 +1015,24 @@
             .arg(AUDBUFSIZE-afree).arg(afree).arg(timecode)
             .arg(needs_upmix));
     
+    if (isAC3upmix)
+        len = WaitForFreeSpace(samples);
+    
     if (upmixer && needs_upmix)
     {
         int out_samples = 0;
         int step = (interleaved)?source_audio_channels:1;
-        len = WaitForFreeSpace(samples);    // test
+	
+        if (!isAC3upmix) {
+            org_waud = waud;
+            len = WaitForFreeSpace(samples);
+        }
         for (int itemp = 0; itemp < samples; )
         {
             // just in case it does a processing cycle, release the lock
             // to allow the output loop to do output
-            pthread_mutex_unlock(&audio_buflock);
+            if (!isAC3upmix)
+                pthread_mutex_unlock(&audio_buflock);
             if (audio_bytes == 2)
             {
                 itemp += upmixer->putSamples(
@@ -894,7 +1049,8 @@
                     source_audio_channels,
                     (interleaved) ? 0 : samples);
             }
-            pthread_mutex_lock(&audio_buflock);
+            if (!isAC3upmix)
+                pthread_mutex_lock(&audio_buflock);
 
             int copy_samples = upmixer->numSamples();
             if (copy_samples)
@@ -928,8 +1084,8 @@
     }
     else
     {
-        len = WaitForFreeSpace(samples);
-
+        if (!isAC3upmix)
+            len = WaitForFreeSpace(samples);
         if (interleaved) 
         {
             char *mybuf = (char*)buffer;
@@ -965,6 +1121,7 @@
         }
     }
 
+    if (!isAC3upmix) {
     if (samples > 0)
     {
         if (pSoundStretch)
@@ -1022,7 +1179,7 @@
                         continue;
 
                     //len = WaitForFreeSpace(amount);
-                    char *ob = encoder->GetOutBuff();
+                    const char *ob = encoder->GetOutBuff();
                     if (amount >= bdiff)
                     {
                         memcpy(audiobuffer + org_waud, ob, bdiff);
@@ -1035,6 +1192,11 @@
 
                     bdiff = AUDBUFSIZE - amount;
                     org_waud += amount;
+                    if (org_waud >= AUDBUFSIZE)
+                    {
+                        VERBOSE(VB_IMPORTANT, QString("org_waud >= kAudioRingBufferSize %1 %2").arg(org_waud).arg(amount));
+                        org_waud -= AUDBUFSIZE;
+                    }
                 }
             }
             else
@@ -1064,6 +1226,11 @@
                         org_waud += nSamples * audio_bytes_per_sample;
                         nSamplesToEnd -= nSamples;
                     }
+                    if (org_waud >= AUDBUFSIZE)
+                    {
+                        VERBOSE(VB_IMPORTANT, QString("org_waud >= kAudioRingBufferSize %1 %2 %3").arg(org_waud).arg(nSamples).arg(audio_bytes_per_sample));
+                        org_waud -= AUDBUFSIZE;
+                    }
 
                     newLen += nSamples * audio_bytes_per_sample;
                     len -= nSamples * audio_bytes_per_sample;
@@ -1096,6 +1263,105 @@
     }
 
     pthread_mutex_unlock(&audio_buflock);
+    } else {
+    if (samples <= 0)
+        return;
+    
+    if (pSoundStretch)
+    {
+        // does not change the timecode, only the number of samples
+        // back to orig pos
+        org_waud = waud;
+        int bdiff = AUDBUFSIZE - org_waud;
+        int nSamplesToEnd = bdiff/abps;
+        if (bdiff < len)
+        {
+            pSoundStretch->putSamples((soundtouch::SAMPLETYPE*)
+                                      (audiobuffer + 
+                                       org_waud), nSamplesToEnd);
+            pSoundStretch->putSamples((soundtouch::SAMPLETYPE*)audiobuffer,
+                                      (len - bdiff) / abps);
+        }
+        else
+            pSoundStretch->putSamples((soundtouch::SAMPLETYPE*)
+                                      (audiobuffer + org_waud),
+                                      len / abps);
+
+        int nSamples = pSoundStretch->numSamples();
+        len = WaitForFreeSpace(nSamples); 
+        
+        while ((nSamples = pSoundStretch->numSamples())) 
+        {
+            if (nSamples > nSamplesToEnd) 
+                nSamples = nSamplesToEnd;
+            
+            nSamples = pSoundStretch->receiveSamples(
+                (soundtouch::SAMPLETYPE*)
+                (audiobuffer + org_waud), nSamples
+            );
+            
+            if (nSamples == nSamplesToEnd) {
+                org_waud = 0;
+                nSamplesToEnd = AUDBUFSIZE/abps;
+            }
+            else {
+                org_waud += nSamples * abps;
+                nSamplesToEnd -= nSamples;
+            }
+            
+        }
+        
+    }
+
+    // Encode to AC-3? 
+    if (encoder) 
+    {
+        
+        org_waud = waud;
+        int bdiff = AUDBUFSIZE - org_waud;
+        int to_get = 0;
+
+        if (bdiff < len) 
+        {
+            encoder->EncodeUpmix(audiobuffer + org_waud, bdiff);
+            to_get = encoder->EncodeUpmix(audiobuffer, len - bdiff);
+        }
+        else 
+            to_get = encoder->EncodeUpmix(audiobuffer + org_waud, len);
+        
+        if (to_get > 0) 
+        {
+            
+            if (to_get >= bdiff)
+            {
+                encoder->GetFrames(audiobuffer + org_waud, bdiff);
+                to_get -= bdiff;
+                org_waud = 0;
+            }
+            if (to_get > 0)
+                encoder->GetFrames(audiobuffer + org_waud, to_get);
+
+            org_waud += to_get;
+
+        }
+
+    }
+
+    waud = org_waud;
+    lastaudiolen = audiolen(false);
+
+    if (timecode < 0)
+        // mythmusic doesn't give timestamps..
+        timecode = (int)((samples_buffered * 100000.0) / effdsp);
+    
+    samples_buffered += samples;
+    
+    /* we want the time at the end -- but the file format stores
+       time at the start of the chunk. */
+    // even with timestretch, timecode is still calculated from original
+    // sample count
+    audbuf_timecode = timecode + (int)((samples * 100000.0) / effdsp);
+    } // End AC3 upmiz
 }
 
 void AudioOutputBase::Status()
diff -Naur --exclude=.svn a/mythtv/libs/libmyth/audiooutputbase.h c/mythtv/libs/libmyth/audiooutputbase.h
--- a/mythtv/libs/libmyth/audiooutputbase.h	2009-05-02 07:32:08.000000000 +1000
+++ c/mythtv/libs/libmyth/audiooutputbase.h	2009-06-01 02:14:00.000000000 +1000
@@ -41,7 +41,8 @@
                     int laudio_bits,
                     int laudio_channels, int laudio_samplerate,
                     AudioOutputSource lsource,
-                    bool lset_initial_vol, bool laudio_passthru);
+                    bool lset_initial_vol, bool laudio_passthru,
+                    bool AC3upmix = false);
     virtual ~AudioOutputBase();
 
     // reconfigure sound out for new params
@@ -59,6 +60,7 @@
 
     virtual void SetStretchFactor(float factor);
     virtual float GetStretchFactor(void);
+    virtual bool ToggleUpmix(void);
 
     virtual void Reset(void);
 
@@ -139,6 +141,8 @@
     QString audio_passthru_device;
 
     bool audio_passthru;
+    bool audio_enc;
+    bool audio_reenc;
 
     float audio_stretchfactor;
     AVCodecContext *audio_codec;
@@ -151,6 +155,9 @@
     bool buffer_output_data_for_use; //  used by AudioOutputNULL
     
     int configured_audio_channels;
+    int orig_config_channels;
+    int src_quality;
+    int source_audio_channels;
 
  private:
     // resampler
@@ -166,10 +173,12 @@
     AudioOutputDigitalEncoder *encoder;
     FreeSurround              *upmixer;
 
-    int source_audio_channels;
+    int source_audio_samplerate;
     int source_audio_bytes_per_sample;
     bool needs_upmix;
     int surround_mode;
+    bool allow_ac3_passthru;
+    float old_audio_stretchfactor;
 
     bool blocking; // do AddSamples calls block?
 
diff -Naur --exclude=.svn a/mythtv/libs/libmyth/audiooutputdigitalencoder.cpp c/mythtv/libs/libmyth/audiooutputdigitalencoder.cpp
--- a/mythtv/libs/libmyth/audiooutputdigitalencoder.cpp	2009-05-02 07:32:08.000000000 +1000
+++ c/mythtv/libs/libmyth/audiooutputdigitalencoder.cpp	2009-06-01 02:14:00.000000000 +1000
@@ -27,10 +27,23 @@
 
 AudioOutputDigitalEncoder::AudioOutputDigitalEncoder(void) :
     av_context(NULL),
-    outbuf(NULL),
-    outbuf_size(0),
     frame_buffer(NULL),
-    one_frame_bytes(0)
+    one_frame_bytes(0),
+    outbuflen(0),
+    inbuflen(0),
+    reorder(true),
+    isAC3upmix(false)
+{
+}
+
+AudioOutputDigitalEncoder::AudioOutputDigitalEncoder(bool AC3upmix) :
+    av_context(NULL),
+    frame_buffer(NULL),
+    one_frame_bytes(0),
+    outbuflen(0),
+    inbuflen(0),
+    reorder(true),
+    isAC3upmix(AC3upmix)
 {
 }
 
@@ -48,14 +61,7 @@
         av_context = NULL;
     }
 
-    if (outbuf)
-    {
-        delete [] outbuf;
-        outbuf = NULL;
-        outbuf_size = 0;
-    }
-
-    if (frame_buffer)
+    if (!isAC3upmix && frame_buffer)
     {
         delete [] frame_buffer;
         frame_buffer = NULL;
@@ -65,17 +71,25 @@
 
 //CODEC_ID_AC3
 bool AudioOutputDigitalEncoder::Init(
-    CodecID codec_id, int bitrate, int samplerate, int channels)
+    CodecID codec_id, int bitrate, int samplerate, int channels, bool reencoding)
 {
     AVCodec *codec;
     int ret;
 
-    VERBOSE(VB_AUDIO, LOC + QString("Init codecid=%1, br=%2, sr=%3, ch=%4")
+    VERBOSE(VB_AUDIO, LOC + QString("Init codecid=%1, br=%2, sr=%3, ch=%4 re=%5")
             .arg(codec_id_string(codec_id))
             .arg(bitrate)
             .arg(samplerate)
-            .arg(channels));
-
+            .arg(channels)
+            .arg(reencoding));
+    
+    reorder = !reencoding;
+
+    // We need to do this when called from mythmusic
+    if (isAC3upmix) {
+        avcodec_init();
+        avcodec_register_all();
+    }
     //codec = avcodec_find_encoder(codec_id);
     // always AC3 as there is no DTS encoder at the moment 2005/1/9
     codec = avcodec_find_encoder(CODEC_ID_AC3);
@@ -105,8 +119,6 @@
     audio_bytes_per_sample = bytes_per_frame;
     one_frame_bytes = bytes_per_frame * av_context->frame_size;
 
-    outbuf_size = 16384;    // ok for AC3 but DTS?
-    outbuf = new char [outbuf_size];
     VERBOSE(VB_AUDIO, QString("DigitalEncoder::Init fs=%1, bpf=%2 ofb=%3")
             .arg(av_context->frame_size)
             .arg(bytes_per_frame)
@@ -256,12 +268,26 @@
 
 } AESHeader;
 
+void reorder_6ch_ac3(void *buf, unsigned int len) {
+    unsigned short *src = (unsigned short *)buf;
+    unsigned short tmp;
+    unsigned int samples = len >> 1;
+
+    for (uint i = 0; i < samples; i += 6) {
+        tmp = src[i+4];
+        src[i+4] = src[i+3];
+        src[i+3] = src[i+2];
+        src[i+2] = src[i+1];
+        src[i+1] = tmp;
+    }
+}
+
 static int encode_frame(
         bool dts, 
         unsigned char *data,
-        size_t &len)
+        size_t &len, bool AC3upmix)
 {
-    size_t enc_len;
+    size_t enc_len = len;
     int flags, sample_rate, bit_rate;
 
     // we don't do any length/crc validation of the AC3 frame here; presumably
@@ -272,7 +298,8 @@
     // ignore, and if so, may as well just assume that it will ignore
     // anything with a bad CRC...
 
-    uint nr_samples = 0, block_len;
+    uint nr_samples = 0, block_len = 0;
+    
     if (dts)
     {
         enc_len = dts_syncinfo(data+8, &flags, &sample_rate, &bit_rate);
@@ -293,7 +320,7 @@
 #endif
     }
 
-    if (enc_len == 0 || enc_len > len)
+    if (!AC3upmix && (enc_len == 0 || enc_len > len))
     {
         int l = len;
         len = 0;
@@ -352,7 +379,8 @@
     data[6] = (enc_len << 3) & 0xFF;
     data[7] = (enc_len >> 5) & 0xFF;
     memset(data + 8 + enc_len, 0, block_len - 8 - enc_len);
-    len = block_len;
+    if (!AC3upmix)
+        len = block_len;
 
     return enc_len;
 }
@@ -365,14 +393,14 @@
  
     // put data in the correct spot for encode frame
     outsize = avcodec_encode_audio(
-        av_context, ((uchar*)outbuf) + 8, outbuf_size - 8, buff);
+        av_context, ((uchar*)outbuf) + 8, OUTBUFSIZE - 8, buff);
 
     size_t tmpsize = outsize;
 
     outsize = MAX_AC3_FRAME_SIZE;
     encsize = encode_frame(
         /*av_context->codec_id==CODEC_ID_DTS*/ false,
-        (unsigned char*)outbuf, outsize);
+        (unsigned char*)outbuf, outsize, false);
 
     VERBOSE(VB_AUDIO|VB_TIMESTAMP, 
             QString("DigitalEncoder::Encode len1=%1 len2=%2 finallen=%3")
@@ -380,3 +408,42 @@
 
     return outsize;
 }
+
+size_t AudioOutputDigitalEncoder::EncodeUpmix(void *buf, int len)
+{
+    size_t outsize = 0;
+ 
+    int fs = FrameSize();
+    memcpy(inbuf+inbuflen, buf, len);
+    inbuflen += len;
+    int frames = inbuflen / fs;
+
+    while (frames--) 
+    {
+        if (reorder)
+            reorder_6ch_ac3(inbuf, fs);
+        
+	// put data in the correct spot for encode frame
+        outsize = avcodec_encode_audio(
+            av_context, ((uchar*)outbuf) + outbuflen + 8, OUTBUFSIZE - 8, (short int *)inbuf);
+
+        encode_frame(
+            /*av_context->codec_id==CODEC_ID_DTS*/ false,
+            (unsigned char*)outbuf + outbuflen, outsize, true
+        );
+
+        outbuflen += MAX_AC3_FRAME_SIZE;
+        inbuflen -= fs;
+        memmove(inbuf, inbuf+fs, inbuflen);
+    }
+
+    return outbuflen;
+}
+
+void AudioOutputDigitalEncoder::GetFrames(void *ptr, int maxlen)
+{
+    int len = (maxlen < outbuflen ? maxlen : outbuflen);
+    memcpy(ptr, outbuf, len);
+    outbuflen -= len;
+    memmove(outbuf, outbuf+len, outbuflen);
+}
diff -Naur --exclude=.svn a/mythtv/libs/libmyth/audiooutputdigitalencoder.h c/mythtv/libs/libmyth/audiooutputdigitalencoder.h
--- a/mythtv/libs/libmyth/audiooutputdigitalencoder.h	2009-05-02 07:32:08.000000000 +1000
+++ c/mythtv/libs/libmyth/audiooutputdigitalencoder.h	2009-06-01 02:14:00.000000000 +1000
@@ -5,29 +5,43 @@
 #include "libavcodec/avcodec.h"
 };
 
+#define INBUFSIZE 131072
+#define OUTBUFSIZE 98304
+
 class AudioOutputDigitalEncoder
 {
   public:
     AudioOutputDigitalEncoder(void);
+    AudioOutputDigitalEncoder(bool AC3upmix);
     ~AudioOutputDigitalEncoder();
 
-    bool   Init(CodecID codec_id, int bitrate, int samplerate, int channels);
+    bool   Init(CodecID codec_id, int bitrate, int samplerate, 
+                int channels, bool reencoding = false);
     void   Dispose(void);
     size_t Encode(short * buff);
 
     inline char *GetFrameBuffer(void);
     size_t FrameSize(void)  const { return one_frame_bytes; }
-    char  *GetOutBuff(void) const { return outbuf;          }
+    const char  *GetOutBuff(void) const { return outbuf; }
+    //AC3 upmix
+    size_t EncodeUpmix(void *buf, int len);
+    void   GetFrames(void *ptr, int maxlen);
+    int    Buffered(void) const { return inbuflen; }
 
   public:
     size_t audio_bytes_per_sample;
 
   private:
     AVCodecContext *av_context;
-    char           *outbuf;
-    int             outbuf_size;
+    char            outbuf[OUTBUFSIZE];
     char           *frame_buffer;
     size_t          one_frame_bytes;
+    // AC3 upmix
+    char            inbuf[INBUFSIZE];
+    int             outbuflen;
+    int             inbuflen;
+    bool            reorder;
+    bool            isAC3upmix;
 };
 
 inline char *AudioOutputDigitalEncoder::GetFrameBuffer(void)
diff -Naur --exclude=.svn a/mythtv/libs/libmythfreesurround/el_processor.cpp c/mythtv/libs/libmythfreesurround/el_processor.cpp
--- a/mythtv/libs/libmythfreesurround/el_processor.cpp	2009-05-02 07:32:14.000000000 +1000
+++ c/mythtv/libs/libmythfreesurround/el_processor.cpp	2009-06-01 02:14:00.000000000 +1000
@@ -40,6 +40,7 @@
 
 const float PI = 3.141592654;
 const float epsilon = 0.000001;
+const float center_level_upmix = 0.5*sqrt(0.5);
 //const float center_level = 0.5*sqrt(0.5);   // gain of the center channel
 //const float center_level = sqrt(0.5);   // gain of the center channel
 const float center_level = 1.0;   // gain of the center channel
@@ -57,7 +58,7 @@
 public:
     // create an instance of the decoder
     //  blocksize is fixed over the lifetime of this object for performance reasons
-    decoder_impl(unsigned blocksize=8192): N(blocksize), halfN(blocksize/2) {
+  decoder_impl(unsigned blocksize=8192, bool AC3upmix=false): N(blocksize), halfN(blocksize/2), isAC3upmix(AC3upmix) {
 #ifdef USE_FFTW3
         // create FFTW buffers
         lt = (float*)fftwf_malloc(sizeof(float)*N);
@@ -99,18 +100,26 @@
             filter[c].resize(N);
         }
         // DC component of filters is always 0
-        for (unsigned c=0;c<5;c++)
-        {
-            filter[c][0] = 0.0;
-            filter[c][1] = 0.0;
-            filter[c][halfN] = 0.0;
-        }
-        sample_rate(48000);
-        // generate the window function (square root of hann, b/c it is applied before and after the transform)
-        wnd.resize(N);
-        // dft normalization included in the window for zero cost scaling
-        // also add a gain factor of *2 due to processing gain in algo (see center_level)
-        surround_gain(1.0);
+        if (!isAC3upmix) {
+            for (unsigned c=0;c<5;c++)
+            {
+                filter[c][0] = 0.0;
+                filter[c][1] = 0.0;
+                filter[c][halfN] = 0.0;
+            }
+            sample_rate(48000);
+            // generate the window function (square root of hann, b/c it is applied before and after the transform)
+            wnd.resize(N);
+            // dft normalization included in the window for zero cost scaling
+            // also add a gain factor of *2 due to processing gain in algo (see center_level)
+            surround_gain(1.0);
+        } else {
+            sample_rate(48000);
+            // generate the window function (square root of hann, b/c it is applied before and after the transform)
+            wnd.resize(N);
+            for (unsigned k=0;k<N;k++)
+                wnd[k] = sqrt(0.5*(1-cos(2*PI*k/N))/N);
+        }
         current_buf = 0;
         // set the default coefficients
         surround_coefficients(0.8165,0.5774);
@@ -192,12 +201,23 @@
     // set lfe filter params
     void sample_rate(unsigned int srate) {
         // lfe filter is just straight through band limited
-        unsigned int cutoff = (250*N)/srate;
-        for (unsigned f=0;f<=halfN;f++) {           
-            if ((f>=2) && (f<cutoff))
-                filter[5][f] = 1.0;
-            else
-                filter[5][f] = 0.0;
+        unsigned int cutoff;
+        if (!isAC3upmix) {
+             cutoff = (250*N)/srate;
+            for (unsigned f=0;f<=halfN;f++) {           
+                if ((f>=2) && (f<cutoff))
+                    filter[5][f] = 1.0;
+                else
+                    filter[5][f] = 0.0;
+            }
+        } else {
+            cutoff = (30*N)/srate;
+            for (unsigned f=0;f<=halfN;f++) {           
+                if (f<cutoff)
+                    filter[5][f] = 0.5*sqrt(0.5);
+                else
+                    filter[5][f] = 0.0;
+            }
         }
     }
 
@@ -237,6 +257,7 @@
     }
 
 private:
+    bool isAC3upmix;
     // polar <-> cartesian coodinates conversion
     static inline float amplitude(const float cf[2]) { return sqrt(cf[0]*cf[0] + cf[1]*cf[1]); }
     static inline float phase(const float cf[2]) { return atan2(cf[1],cf[0]); }
@@ -290,7 +311,8 @@
 
         // 2. compare amplitude and phase of each DFT bin and produce the X/Y coordinates in the sound field
         //    but dont do DC or N/2 component
-        for (unsigned f=2;f<halfN;f++) {           
+        unsigned start_f = isAC3upmix ? 0:2;
+        for (unsigned f=start_f;f<halfN;f++) {           
             // get left/right amplitudes/phases
             float ampL = amplitude(dftL[f]), ampR = amplitude(dftR[f]);
             float phaseL = phase(dftL[f]), phaseR = phase(dftR[f]);
@@ -357,7 +379,7 @@
                 float front = (1+yfs[f])/2, back = (1-yfs[f])/2;
                 float volume[5] = {
                     front * (left * center_width + max(0,-xfs[f]) * (1-center_width)),  // left
-                    front * center_level*((1-abs(xfs[f])) * (1-center_width)),          // center
+                    front * (isAC3upmix ? center_level_upmix : center_level) *((1-abs(xfs[f])) * (1-center_width)),          // center
                     front * (right * center_width + max(0, xfs[f]) * (1-center_width)), // right
                     back * surround_level * left,                                       // left surround
                     back * surround_level * right                                       // right surround
@@ -402,7 +424,7 @@
                 float front = (1+yfs[f])/2, back = (1-yfs[f])/2;
                 float volume[5] = {
                     front * (left * center_width + max(0,-xfs[f]) * (1-center_width)),      // left
-                    front * center_level*((1-abs(xfs[f])) * (1-center_width)),              // center
+                    front * (isAC3upmix ? center_level_upmix : center_level) *((1-abs(xfs[f])) * (1-center_width)),          // center
                     front * (right * center_width + max(0, xfs[f]) * (1-center_width)),     // right
                     back * surround_level*max(0,min(1,((1-(xfs[f]/surround_balance))/2))),  // left surround
                     back * surround_level*max(0,min(1,((1+(xfs[f]/surround_balance))/2)))   // right surround
@@ -613,7 +635,7 @@
 
 // implementation of the shell class
 
-fsurround_decoder::fsurround_decoder(unsigned blocksize): impl(new decoder_impl(blocksize)) { }
+fsurround_decoder::fsurround_decoder(unsigned blocksize, bool AC3upmix): impl(new decoder_impl(blocksize,AC3upmix)) { }
 
 fsurround_decoder::~fsurround_decoder() { delete impl; }
 
diff -Naur --exclude=.svn a/mythtv/libs/libmythfreesurround/el_processor.h c/mythtv/libs/libmythfreesurround/el_processor.h
--- a/mythtv/libs/libmythfreesurround/el_processor.h	2009-05-02 07:32:14.000000000 +1000
+++ c/mythtv/libs/libmythfreesurround/el_processor.h	2009-06-01 02:14:00.000000000 +1000
@@ -24,7 +24,7 @@
 public:
 	// create an instance of the decoder
 	//  blocksize is fixed over the lifetime of this object for performance reasons
-	fsurround_decoder(unsigned blocksize=8192);
+        fsurround_decoder(unsigned blocksize=8192, bool AC3upmix=false);
 	// destructor
 	~fsurround_decoder();
 	
@@ -51,10 +51,10 @@
 	void gain(float gain);
 
 	// set the phase shifting mode for decoding
-	// 0 = (+0°,+0°)   - music mode
-	// 1 = (+0°,+180°) - PowerDVD compatibility
-	// 2 = (+180°,+0°) - BeSweet compatibility
-	// 3 = (-90°,+90°) - This seems to work. I just don't know why.
+	// 0 = (+0οΎ°,+0οΎ°)   - music mode
+	// 1 = (+0οΎ°,+180οΎ°) - PowerDVD compatibility
+	// 2 = (+180οΎ°,+0οΎ°) - BeSweet compatibility
+	// 3 = (-90οΎ°,+90οΎ°) - This seems to work. I just don't know why.
 	void phase_mode(unsigned mode);
 
 	// override the steering mode
@@ -71,6 +71,7 @@
 
 private:
 	class decoder_impl *impl; // private implementation (details hidden)
+	bool isAC3upmix;
 };
 
 
diff -Naur --exclude=.svn a/mythtv/libs/libmythfreesurround/freesurround.cpp c/mythtv/libs/libmythfreesurround/freesurround.cpp
--- a/mythtv/libs/libmythfreesurround/freesurround.cpp	2009-05-02 07:32:14.000000000 +1000
+++ c/mythtv/libs/libmythfreesurround/freesurround.cpp	2009-06-01 02:14:00.000000000 +1000
@@ -163,10 +163,12 @@
 
 // construction methods
 void *new_decoder() { return new fsurround_decoder(block_size); }
+void *new_decoder_upmix() { return new fsurround_decoder(block_size,true); }
 void *new_buffers() { return new buffers(block_size/2); }
 void *new_int16buffers() { return new int16buffers(block_size/2); }
 
 object_pool dp(&new_decoder);
+object_pool dp_upmix(&new_decoder_upmix);
 //object_pool bp(&new_buffers);
 object_pool bp16(&new_int16buffers);
 
@@ -175,7 +177,7 @@
 int channel_select = -1;
 #endif
 
-FreeSurround::FreeSurround(uint srate, bool moviemode, SurroundMode smode) :
+FreeSurround::FreeSurround(uint srate, bool moviemode, SurroundMode smode, bool AC3upmix) :
         srate(srate),
         open_(false),
         initialized_(false),
@@ -185,21 +187,32 @@
         in_count(0),
         out_count(0),
         processed(true),
-        surround_mode(smode)
+        surround_mode(smode),
+        isAC3upmix(AC3upmix)
 {
     VERBOSE(QString("FreeSurround::FreeSurround rate %1 moviemode %2").arg(srate).arg(moviemode));
     if (moviemode)
     {
         params.phasemode = 1;
-        params.center_width = 0;
-        params.gain = 1.0;
+        if (!isAC3upmix) {
+            params.center_width = 0;
+            params.gain = 1.0;
+        } else {
+            params.center_width = 25;
+            params.dimension = 0.5;
+        }
     }
     else
     {
-        params.center_width = 70;
-        // for 50, gain should be about 1.9, c/lr about 2.7
-        // for 70, gain should be about 3.1, c/lr about 1.5
-        params.gain = 3.1;
+        if (!isAC3upmix) {
+            params.center_width = 70;
+            // for 50, gain should be about 1.9, c/lr about 2.7
+            // for 70, gain should be about 3.1, c/lr about 1.5
+            params.gain = 3.1;
+        } else {
+            params.center_width = 65;
+            params.dimension = 0.3;
+        }
     }
     switch (surround_mode)
     {
@@ -235,7 +248,8 @@
         decoder->phase_mode(params.phasemode);
         decoder->surround_coefficients(params.coeff_a, params.coeff_b);				
         decoder->separation(params.front_sep/100.0,params.rear_sep/100.0);
-        decoder->gain(params.gain);
+        if (!isAC3upmix)
+            decoder->gain(params.gain);
     }
 }
 
@@ -654,16 +668,6 @@
     {
         if (decoder) 
         {
-            // actually these params need only be set when they change... but it doesn't hurt
-#if 0
-            decoder->steering_mode(params.steering);
-            decoder->phase_mode(params.phasemode);
-            decoder->surround_coefficients(params.coeff_a, params.coeff_b);				
-            decoder->separation(params.front_sep/100.0,params.rear_sep/100.0);
-#endif
-            // decode the bufs->block
-            //decoder->decode(input,output,params.center_width/100.0,params.dimension/100.0);
-            //decoder->decode(output,params.center_width/100.0,params.dimension/100.0);
             decoder->decode(params.center_width/100.0,params.dimension/100.0);
         }
     }
@@ -693,7 +697,10 @@
 {		
     if (!decoder)
     {
-        decoder = (fsurround_decoder*)dp.acquire((void*)1);
+        if (!isAC3upmix)
+            decoder = (fsurround_decoder*)dp.acquire((void*)1);
+        else
+	    decoder = (fsurround_decoder*)dp_upmix.acquire((void*)1);
         decoder->flush();
         //if (bufs)
         //    bufs->clear();
@@ -708,7 +715,10 @@
 {
     if (decoder)
     {
-        dp.release(this);
+        if (!isAC3upmix)
+            dp.release(this);
+	else
+            dp_upmix.release(this);
         decoder = 0;
     }
 }
diff -Naur --exclude=.svn a/mythtv/libs/libmythfreesurround/freesurround.h c/mythtv/libs/libmythfreesurround/freesurround.h
--- a/mythtv/libs/libmythfreesurround/freesurround.h	2009-05-02 07:32:14.000000000 +1000
+++ c/mythtv/libs/libmythfreesurround/freesurround.h	2009-06-01 02:14:00.000000000 +1000
@@ -31,7 +31,7 @@
         SurroundModeActiveLinear
     } SurroundMode;
 public:
-    FreeSurround(uint srate, bool moviemode, SurroundMode mode);
+    FreeSurround(uint srate, bool moviemode, SurroundMode mode, bool AC3upmix=false);
     ~FreeSurround();
 
     // put samples in buffer, returns number of samples used
@@ -88,6 +88,7 @@
     bool processed;             // whether processing is enabled or not for latency calc
     int processed_size;         // amount processed
     SurroundMode surround_mode; // 1 of 3 surround modes supported
+    bool isAC3upmix;
 
 };
 
diff -Naur --exclude=.svn a/mythtv/libs/libmythsamplerate/samplerate.c c/mythtv/libs/libmythsamplerate/samplerate.c
--- a/mythtv/libs/libmythsamplerate/samplerate.c	2009-05-02 07:30:54.000000000 +1000
+++ c/mythtv/libs/libmythsamplerate/samplerate.c	2009-06-01 02:14:00.000000000 +1000
@@ -428,7 +428,7 @@
 
 	error = src_process (src_state, src_data) ;
 
-	src_state = src_delete (src_state) ;
+	src_delete (src_state) ;
 
 	return error ;
 } /* src_simple */
@@ -452,11 +452,11 @@
 	{	len -- ;
 
 		scaled_value = in [len] * (8.0 * 0x10000000) ;
-		if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF))
+		if (scaled_value >= (1.0 * 0x7FFFFFFF))
 		{	out [len] = 32767 ;
 			continue ;
 			} ;
-		if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000))
+		if (scaled_value <= (-8.0 * 0x10000000))
 		{	out [len] = -32768 ;
 			continue ;
 			} ;
diff -Naur --exclude=.svn a/mythtv/libs/libmythtv/NuppelVideoPlayer.cpp c/mythtv/libs/libmythtv/NuppelVideoPlayer.cpp
--- a/mythtv/libs/libmythtv/NuppelVideoPlayer.cpp	2009-05-31 17:53:27.000000000 +1000
+++ c/mythtv/libs/libmythtv/NuppelVideoPlayer.cpp	2009-06-01 02:27:36.000000000 +1000
@@ -769,6 +769,14 @@
 
     no_audio_in = false;
 
+    bool isAC3upmix = gContext->GetNumSetting("MythAC3Upmix",0);
+    // If previously AC3 upmixer was different than current state, delete AudioOutput
+    if (audioOutput && (audioOutput->isAC3upmix != isAC3upmix))
+    {
+        delete audioOutput;
+        audioOutput = NULL;
+    }
+
     if (!audioOutput && !using_null_videoout)
     {
         bool setVolume = gContext->GetNumSetting("MythControlsVolume", 1);
@@ -777,7 +785,7 @@
                                              audio_bits, audio_channels,
                                              audio_samplerate,
                                              AUDIOOUTPUT_VIDEO,
-                                             setVolume, audio_passthru);
+                                             setVolume, audio_passthru, isAC3upmix);
         if (!audioOutput)
             errMsg = QObject::tr("Unable to create AudioOutput.");
         else
@@ -806,6 +814,8 @@
         audioOutput->Reconfigure(audio_bits, audio_channels,
                                  audio_samplerate, audio_passthru,
                                  audio_codec);
+	if (audioOutput->isAC3upmix && audio_passthru)
+	    audio_channels = 2;
         errMsg = audioOutput->GetError();
         if (!errMsg.isEmpty())
             audioOutput->SetStretchFactor(audio_stretchfactor);
@@ -4931,6 +4941,13 @@
     }
 }
 
+bool NuppelVideoPlayer::ToggleUpmix()
+{
+    if (audioOutput)
+        return audioOutput->ToggleUpmix();
+    return false;
+}
+
 void NuppelVideoPlayer::Zoom(ZoomDirection direction)
 {
     if (videoOutput)
diff -Naur --exclude=.svn a/mythtv/libs/libmythtv/NuppelVideoPlayer.h c/mythtv/libs/libmythtv/NuppelVideoPlayer.h
--- a/mythtv/libs/libmythtv/NuppelVideoPlayer.h	2009-05-02 07:30:34.000000000 +1000
+++ c/mythtv/libs/libmythtv/NuppelVideoPlayer.h	2009-06-01 02:28:59.000000000 +1000
@@ -175,6 +175,7 @@
     // Toggle Sets
     void ToggleAspectOverride(AspectOverrideMode aspectMode = kAspect_Toggle);
     void ToggleAdjustFill(AdjustFillMode adjustfillMode = kAdjustFill_Toggle);
+    bool ToggleUpmix(void);
 
     // Gets
     QSize   GetVideoBufferSize(void) const    { return video_dim; }
diff -Naur --exclude=.svn a/mythtv/libs/libmythtv/avformatdecoder.cpp c/mythtv/libs/libmythtv/avformatdecoder.cpp
--- a/mythtv/libs/libmythtv/avformatdecoder.cpp	2009-05-31 17:53:27.000000000 +1000
+++ c/mythtv/libs/libmythtv/avformatdecoder.cpp	2009-06-01 02:33:31.000000000 +1000
@@ -411,7 +411,7 @@
       audioSamples(new short int[AVCODEC_MAX_AUDIO_FRAME_SIZE]),
       allow_ac3_passthru(false),    allow_dts_passthru(false),
       disable_passthru(false),      max_channels(2),
-      dummy_frame(NULL),
+      last_ac3_channels(0),	    dummy_frame(NULL),
       // DVD
       lastdvdtitle(-1),
       decodeStillFrame(false),
@@ -429,6 +429,7 @@
     allow_ac3_passthru = gContext->GetNumSetting("AC3PassThru", false);
     allow_dts_passthru = gContext->GetNumSetting("DTSPassThru", false);
     max_channels = (uint) gContext->GetNumSetting("MaxChannels", 2);
+    isAC3upmix = gContext->GetNumSetting("MythAC3Upmix", 0);
 
     audioIn.sample_size = -32; // force SetupAudioStream to run once
     itv = GetNVP()->GetInteractiveTV();
@@ -2829,15 +2830,9 @@
     {
         int idx = atracks[i].av_stream_index;
         AVCodecContext *codec_ctx = ic->streams[idx]->codec;
-        bool do_ac3_passthru = (allow_ac3_passthru && !transcoding &&
-                                !disable_passthru &&
-                                (codec_ctx->codec_id == CODEC_ID_AC3));
-        bool do_dts_passthru = (allow_dts_passthru && !transcoding &&
-                                !disable_passthru &&
-                                (codec_ctx->codec_id == CODEC_ID_DTS));
         AudioInfo item(codec_ctx->codec_id,
                        codec_ctx->sample_rate, codec_ctx->channels,
-                       do_ac3_passthru || do_dts_passthru);
+                       DoPassThrough(codec_ctx));
         VERBOSE(VB_AUDIO, LOC + " * " + item.toString());
     }
 #endif
@@ -2971,6 +2966,7 @@
 bool AvFormatDecoder::GetFrame(int onlyvideo)
 {
     AVPacket *pkt = NULL;
+    AC3HeaderInfo hdr;
     int len;
     unsigned char *ptr;
     int data_size = 0;
@@ -3393,14 +3389,6 @@
                         reselectAudioTrack = true;
                     }                            
 
-                    bool do_ac3_passthru =
-                        (allow_ac3_passthru && !transcoding &&
-                         (curstream->codec->codec_id == CODEC_ID_AC3));
-                    bool do_dts_passthru =
-                        (allow_dts_passthru && !transcoding &&
-                         (curstream->codec->codec_id == CODEC_ID_DTS));
-                    bool using_passthru = do_ac3_passthru || do_dts_passthru;
-
                     // detect channels on streams that need
                     // to be decoded before we can know this
                     bool already_decoded = false;
@@ -3411,7 +3399,7 @@
                                 QString("Setting channels to %1")
                                 .arg(audioOut.channels));
 
-                        if (using_passthru)
+                        if (DoPassThrough(curstream->codec))
                         {
                             // for passthru let it select the max number
                             // of channels
@@ -3432,6 +3420,16 @@
                         reselectAudioTrack |= curstream->codec->channels;
                     }
 
+                    if (isAC3upmix && curstream->codec->codec_id == CODEC_ID_AC3 &&
+                        !ff_ac3_parse_header(ptr, &hdr)) 
+                    {
+                        if (hdr.channels != last_ac3_channels) 
+                        {
+                            last_ac3_channels = curstream->codec->channels = hdr.channels;
+                            SetupAudioStream();
+                        }
+                    }
+
                     if (reselectAudioTrack)
                     {
                         QMutexLocker locker(&avcodeclock);
@@ -3959,6 +3957,35 @@
     }
 }
 
+bool AvFormatDecoder::DoPassThrough(const AVCodecContext *ctx)
+{
+    bool do_ac3_passthru =
+        (allow_ac3_passthru && !transcoding &&
+        (ctx->codec_id == CODEC_ID_AC3));
+    bool do_dts_passthru =
+        (allow_dts_passthru && !transcoding &&
+        (ctx->codec_id == CODEC_ID_DTS));
+    bool using_passthru = do_ac3_passthru || do_dts_passthru;
+
+    if (!isAC3upmix)
+        return using_passthru;
+
+    bool passthru = false; 
+
+    if (ctx->codec_id == CODEC_ID_AC3)
+        passthru = allow_ac3_passthru && 
+                   ctx->channels >= (int)max_channels;
+    else if (ctx->codec_id == CODEC_ID_DTS)
+        passthru = allow_dts_passthru;
+    
+    passthru &= !transcoding && !disable_passthru;
+    // Don't know any cards that support spdif clocked at < 44100
+    // Some US cable transmissions have 2ch 32k AC-3 streams
+    passthru &= ctx->sample_rate >= 44100;
+
+    return passthru;
+}
+
 /** \fn AvFormatDecoder::SetupAudioStream(void)
  *  \brief Reinitializes audio if it needs to be reinitialized.
  *
@@ -3984,14 +4011,14 @@
         assert(curstream);
         assert(curstream->codec);
         codec_ctx = curstream->codec;        
-        bool do_ac3_passthru = (allow_ac3_passthru && !transcoding &&
-                                (codec_ctx->codec_id == CODEC_ID_AC3));
-        bool do_dts_passthru = (allow_dts_passthru && !transcoding &&
-                                (codec_ctx->codec_id == CODEC_ID_DTS));
-        using_passthru = do_ac3_passthru || do_dts_passthru;
-        info = AudioInfo(codec_ctx->codec_id,
-                         codec_ctx->sample_rate, codec_ctx->channels,
-                         using_passthru && !disable_passthru);
+        using_passthru = DoPassThrough(codec_ctx);
+        if (!isAC3upmix)
+            info = AudioInfo(codec_ctx->codec_id,
+                             codec_ctx->sample_rate, codec_ctx->channels,
+                             using_passthru && !disable_passthru);
+        else
+            info = AudioInfo(codec_ctx->codec_id, codec_ctx->sample_rate, 
+                             codec_ctx->channels, using_passthru);
     }
 
     if (info == audioIn)
@@ -4002,6 +4029,7 @@
             QString("audio track #%1").arg(currentTrack[kTrackTypeAudio]+1));
 
     audioOut = audioIn = info;
+    if (!isAC3upmix) {
     if (using_passthru)
     {
         // A passthru stream looks like a 48KHz 2ch (@ 16bit) to the sound card
@@ -4058,6 +4086,28 @@
 
     // allow the audio stuff to reencode
     GetNVP()->SetAudioCodec(using_passthru?codec_ctx:NULL);
+    } else {
+
+    if (!using_passthru && audioOut.channels > (int)max_channels)
+    {
+        audioOut.channels = (int)max_channels;
+        audioOut.sample_size = audioOut.channels * 2;
+        codec_ctx->channels = audioOut.channels;
+    }
+    
+    VERBOSE(VB_AUDIO, LOC + "Audio format changed " +
+            QString("\n\t\t\tfrom %1 to %2")
+            .arg(old_in.toString()).arg(audioOut.toString()));
+
+    if (audioOut.sample_rate > 0)
+        GetNVP()->SetEffDsp(audioOut.sample_rate * 100);
+
+    GetNVP()->SetAudioCodec(codec_ctx);
+    GetNVP()->SetAudioParams(audioOut.bps(), audioOut.channels,
+                             audioOut.sample_rate,
+                             audioOut.do_passthru);
+    
+    }
     QString errMsg = GetNVP()->ReinitAudio();
     bool audiook = errMsg.isEmpty();
 
diff -Naur --exclude=.svn a/mythtv/libs/libmythtv/avformatdecoder.h c/mythtv/libs/libmythtv/avformatdecoder.h
--- a/mythtv/libs/libmythtv/avformatdecoder.h	2009-05-02 07:30:35.000000000 +1000
+++ c/mythtv/libs/libmythtv/avformatdecoder.h	2009-06-01 02:14:00.000000000 +1000
@@ -183,7 +183,7 @@
     void InitVideoCodec(AVStream *stream, AVCodecContext *enc,
                         bool selectedStream = false);
 
-    /// Preprocess a packet, setting the video parms if nessesary.
+    /// Preprocess a packet, setting the video parms if necessary.
     void MpegPreProcessPkt(AVStream *stream, AVPacket *pkt);
     void H264PreProcessPkt(AVStream *stream, AVPacket *pkt);
 
@@ -196,6 +196,7 @@
 
     void SeekReset(long long, uint skipFrames, bool doFlush, bool discardFrames);
 
+    bool DoPassThrough(const AVCodecContext *ctx);
     bool SetupAudioStream(void);
     void SetupAudioStreamSubIndexes(int streamIndex);
     void RemoveAudioStreams();
@@ -264,6 +265,8 @@
     bool              allow_dts_passthru;
     bool              disable_passthru;
     uint              max_channels;
+    uint              last_ac3_channels;
+    bool              isAC3upmix;
 
     VideoFrame       *dummy_frame;
 
diff -Naur --exclude=.svn a/mythtv/libs/libmythtv/tv_play.cpp c/mythtv/libs/libmythtv/tv_play.cpp
--- a/mythtv/libs/libmythtv/tv_play.cpp	2009-05-31 17:53:27.000000000 +1000
+++ c/mythtv/libs/libmythtv/tv_play.cpp	2009-06-01 02:14:00.000000000 +1000
@@ -348,6 +348,7 @@
     REG_KEY("TV Playback", "VOLUMEDOWN", "Volume down", "[,{,F10,Volume Down");
     REG_KEY("TV Playback", "VOLUMEUP",   "Volume up",   "],},F11,Volume Up");
     REG_KEY("TV Playback", "MUTE",       "Mute",        "|,\\,F9,Volume Mute");
+    REG_KEY("TV Playback", "TOGGLEUPMIX", "Toggle upmixer", "Ctrl+U");
     REG_KEY("TV Playback", "TOGGLEPIPMODE", "Toggle Picture-in-Picture mode",
             "V");
     REG_KEY("TV Playback", "TOGGLEPIPWINDOW", "Toggle active PiP window", "B");
@@ -480,7 +481,7 @@
   Teletext     F2,F3,F4,F5,F6,F7,F8
   ITV          F2,F3,F4,F5,F6,F7,F12
 
-  Playback: Ctrl-B,Ctrl-G,Ctrl-Y
+  Playback: Ctrl-B,Ctrl-G,Ctrl-Y,Ctrl-U
 */
 }
 
@@ -2710,7 +2711,7 @@
             else if (action == "VOLUMEDOWN" || action == "VOLUMEUP" ||
                      action == "STRETCHINC" || action == "STRETCHDEC" ||
                      action == "MUTE"       || action == "TOGGLEASPECT" ||
-                     action == "TOGGLEFILL" )
+                     action == "TOGGLEFILL" || action == "TOGGLEUPMIX")
             {
                 passThru = 1;
                 handled = false;
@@ -2765,7 +2766,7 @@
             else if (action == "VOLUMEDOWN" || action == "VOLUMEUP" ||
                      action == "STRETCHINC" || action == "STRETCHDEC" ||
                      action == "MUTE" || action == "PAUSE" ||
-                     action == "CLEAROSD")
+                     action == "CLEAROSD" || action == "TOGGLEUPMIX")
             {
                 passThru = 1;
                 handled = false;
@@ -3070,6 +3071,8 @@
             ChangeTimeStretch(0);   // just display
         else if (action == "TOGGLESTRETCH")
             ToggleTimeStretch();
+        else if (action == "TOGGLEUPMIX")
+            ToggleUpmix();
         else if (action == "CYCLECOMMSKIPMODE") {
             SetAutoCommercialSkip((enum commSkipMode)
                                   ((autoCommercialSkip + 1) % CommSkipModes));
@@ -6054,6 +6057,26 @@
     }
 }
 
+void TV::ToggleUpmix()
+{
+    AudioOutput *aud = nvp->getAudioOutput();
+    if (!aud)
+        return;
+    QString text;
+    if(!aud->isAC3upmix) {
+        text = tr("Upmixer disabled !");
+    } else {
+        if (aud->ToggleUpmix())
+            text = tr("Upmixer On");
+        else
+            text = tr("Upmixer Off");
+    }
+    
+    if (GetOSD() && !browsemode)
+        GetOSD()->SetSettingsText(text, 5);
+}
+    
+
 // dir in 10ms jumps
 void TV::ChangeAudioSync(int dir, bool allowEdit)
 {
@@ -7302,6 +7325,8 @@
 
         ChangeTimeStretch(0, !floatRead);   // just display
     }
+    else if (action == "TOGGLEUPMIX")
+        ToggleUpmix();
     else if (action.left(11) == "SELECTSCAN_")
         activenvp->SetScanType((FrameScanType) action.right(1).toInt());
     else if (action.left(15) == "TOGGLEAUDIOSYNC")
@@ -7550,6 +7575,9 @@
                                  (speedX100 == 150) ? 1 : 0, NULL,
                                  "STRETCHGROUP");
 
+    if(nvp && nvp->getAudioOutput()->isAC3upmix)
+        item = new OSDGenericTree(treeMenu, tr("Toggle Upmixer"), "TOGGLEUPMIX");
+
     // add scan mode override settings to menu
     FrameScanType scan_type = kScan_Ignore;
     bool scan_type_locked = false;
diff -Naur --exclude=.svn a/mythtv/libs/libmythtv/tv_play.h c/mythtv/libs/libmythtv/tv_play.h
--- a/mythtv/libs/libmythtv/tv_play.h	2009-05-02 07:30:34.000000000 +1000
+++ c/mythtv/libs/libmythtv/tv_play.h	2009-06-01 02:14:00.000000000 +1000
@@ -314,6 +314,7 @@
     void ChangeSpeed(int direction);
     void ToggleTimeStretch(void);
     void ChangeTimeStretch(int dir, bool allowEdit = true);
+    void ToggleUpmix(void);
     void ChangeAudioSync(int dir, bool allowEdit = true);
     float StopFFRew(void);
     void ChangeFFRew(int direction);
diff -Naur --exclude=.svn a/mythtv/programs/mythfrontend/globalsettings.cpp c/mythtv/programs/mythfrontend/globalsettings.cpp
--- a/mythtv/programs/mythfrontend/globalsettings.cpp	2009-05-02 07:32:18.000000000 +1000
+++ c/mythtv/programs/mythfrontend/globalsettings.cpp	2009-06-01 02:14:00.000000000 +1000
@@ -116,6 +116,35 @@
     return gc;
 }
 
+static HostCheckBox *AC3Upmix()
+{
+    HostCheckBox *gc = new HostCheckBox("MythAC3Upmix");
+    gc->setLabel(QObject::tr("AC3 audio upmixer"));
+    gc->setValue(false);
+    gc->setHelpText(QObject::tr("Enable AC3 upmixer and digital software volume control."));
+    return gc;
+}
+
+static HostComboBox *SRCQuality()
+{
+    HostComboBox *gc = new HostComboBox("SRCQuality", false);
+    gc->setLabel(QObject::tr("Sample Rate Conversion"));
+    gc->addSelection(QObject::tr("Best"), "3", true); // default
+    gc->addSelection(QObject::tr("Medium"), "2");
+    gc->addSelection(QObject::tr("Fastest"), "1");
+    gc->addSelection(QObject::tr("Disabled"), "0");
+    gc->setHelpText(
+            QObject::tr(
+                "Set the quality of audio sample rate conversion. "
+                "This only affects non 48000Hz PCM audio. "
+                "All three options offer a worst-case SNR of 97dB. "
+                "'Best' at a bandwidth of 97%. "
+                "'Medium' at a bandwidth of 90%. "
+                "'Fastest' at a bandwidth of 80%. "
+                "Set 'Disabled' only if you know what you are doing."));
+    return gc;
+}
+
 static HostComboBox *PassThroughOutputDevice()
 {
     HostComboBox *gc = new HostComboBox("PassThruOutputDevice", true);
@@ -3284,6 +3313,19 @@
     return gs;
 }
 
+class AC3UpmixSettings : public TriggeredConfigurationGroup
+{
+  public:
+     AC3UpmixSettings(Setting *checkbox, ConfigurationGroup *group) :
+         TriggeredConfigurationGroup(false, false, false, false)
+     {
+        setTrigger(checkbox);
+
+        addTarget("1", group);
+        addTarget("0", new VerticalConfigurationGroup(false,false));
+     }
+};
+
 class AudioSettings : public TriggeredConfigurationGroup
 {
   public:
@@ -3296,17 +3338,37 @@
          addChild(AudioOutputDevice());
          addChild(PassThroughOutputDevice());
 
-         // General boolean settings
-         VerticalConfigurationGroup *vgrp0 =
+        // General boolean settings
+        VerticalConfigurationGroup *vgrp0 =
              new VerticalConfigurationGroup(false, false, true, true);
-         vgrp0->addChild(AC3PassThrough());
-         vgrp0->addChild(DTSPassThrough());
+        vgrp0->addChild(AC3PassThrough());
+        vgrp0->addChild(DTSPassThrough());
 
-         HorizontalConfigurationGroup *agrp =
+        HorizontalConfigurationGroup *agrp =
              new HorizontalConfigurationGroup(false, false, true, true);
-         agrp->addChild(MaxAudioChannels());
-         agrp->addChild(AudioUpmixType());
-         addChild(agrp);
+        agrp->addChild(MaxAudioChannels());
+        agrp->addChild(AudioUpmixType());
+        addChild(agrp);
+
+        HorizontalConfigurationGroup *agrp1 =
+             new HorizontalConfigurationGroup(false, false, true, true);
+
+        VerticalConfigurationGroup *agrp1v1 =
+             new VerticalConfigurationGroup(false, false, true, true);
+
+        Setting* ac3upmix = AC3Upmix();
+            agrp1v1->addChild(ac3upmix);
+        agrp1->addChild(agrp1v1);
+
+        VerticalConfigurationGroup *agrp1v2 =
+            new VerticalConfigurationGroup(false, false, true, true);
+
+        agrp1v2->addChild(SRCQuality());
+
+        AC3UpmixSettings *sub1 =
+            new AC3UpmixSettings(ac3upmix, agrp1v2);
+        agrp1->addChild(sub1);
+        addChild(agrp1);
 
          VerticalConfigurationGroup *vgrp1 =
              new VerticalConfigurationGroup(false, false, true, true);
diff -Naur --exclude=.svn a/mythtv/programs/mythtranscode/transcode.cpp c/mythtv/programs/mythtranscode/transcode.cpp
--- a/mythtv/programs/mythtranscode/transcode.cpp	2009-05-02 07:32:21.000000000 +1000
+++ c/mythtv/programs/mythtranscode/transcode.cpp	2009-06-01 02:14:00.000000000 +1000
@@ -218,6 +218,11 @@
         // Do nothing
         return MUTE_OFF;
     }
+    virtual bool ToggleUpmix(void) 
+    {
+        // Do nothing
+        return false;
+    }
 
     //  These are pure virtual in AudioOutput, but we don't need them here
     virtual void bufferOutputData(bool){ return; }
