diff --git a/mythplugins/mythmusic/mythmusic/aacdecoder.cpp b/mythplugins/mythmusic/mythmusic/aacdecoder.cpp
index 0e5b1ed..968c211 100644
--- a/mythplugins/mythmusic/mythmusic/aacdecoder.cpp
+++ b/mythplugins/mythmusic/mythmusic/aacdecoder.cpp
@@ -29,6 +29,7 @@
 // MythTV headers
 #include <mythtv/audiooutput.h>
 #include <mythtv/mythcontext.h>
+#include <mythtv/libavcodec/avcodec.h>
 
 // MythMusic headers
 #include "aacdecoder.h"
@@ -401,7 +402,7 @@ bool aacDecoder::initializeMP4()
     if (output())
     {
         const AudioSettings settings(
-            16 /*bits*/, channels, sample_rate,
+            16 /*bits*/, channels, CODEC_ID_AAC, sample_rate,
             false /* AC3/DTS pass through */);
         output()->Reconfigure(settings);
         output()->SetSourceBitrate(bitrate);
diff --git a/mythplugins/mythmusic/mythmusic/avfdecoder.cpp b/mythplugins/mythmusic/mythmusic/avfdecoder.cpp
index 260612f..c7e2ace 100644
--- a/mythplugins/mythmusic/mythmusic/avfdecoder.cpp
+++ b/mythplugins/mythmusic/mythmusic/avfdecoder.cpp
@@ -253,8 +253,8 @@ bool avfDecoder::initialize()
     if (output())
     {
         const AudioSettings settings(
-            16 /*bits*/, m_audioDec->channels, m_audioDec->sample_rate,
-            false /* AC3/DTS pass through */);
+            16 /*bits*/, m_audioDec->channels, m_audioDec->codec_id, 
+            m_audioDec->sample_rate, false /* AC3/DTS pass through */);
         output()->Reconfigure(settings);
         output()->SetSourceBitrate(m_audioDec->bit_rate);
     }
diff --git a/mythplugins/mythmusic/mythmusic/cddecoder.cpp b/mythplugins/mythmusic/mythmusic/cddecoder.cpp
index 9eb0d74..9caaf24 100644
--- a/mythplugins/mythmusic/mythmusic/cddecoder.cpp
+++ b/mythplugins/mythmusic/mythmusic/cddecoder.cpp
@@ -14,6 +14,7 @@ using namespace std;
 
 #include <mythtv/mythcontext.h>
 #include <mythtv/mythmediamonitor.h>
+#include <mythtv/libavcodec/avcodec.h>
 
 CdDecoder::CdDecoder(const QString &file, DecoderFactory *d, QIODevice *i,
                      AudioOutput *o) :
@@ -149,7 +150,8 @@ bool CdDecoder::initialize()
     if (output())
     {
         const AudioSettings settings(
-            16 /*bits*/, chan, freq, false /* AC3/DTS passthru */);
+            16 /*bits*/, chan, CODEC_ID_PCM_S16LE, freq,
+            false /* AC3/DTS passthru */);
         output()->Reconfigure(settings);
         output()->SetSourceBitrate(44100 * 2 * 16);
     }
diff --git a/mythplugins/mythmusic/mythmusic/main.cpp b/mythplugins/mythmusic/mythmusic/main.cpp
index cde9575..c520219 100644
--- a/mythplugins/mythmusic/mythmusic/main.cpp
+++ b/mythplugins/mythmusic/mythmusic/main.cpp
@@ -367,6 +367,7 @@ void setupKeys(void)
     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 --git a/mythplugins/mythmusic/mythmusic/musicplayer.cpp b/mythplugins/mythmusic/mythmusic/musicplayer.cpp
index fad20ee..088f88b 100644
--- a/mythplugins/mythmusic/mythmusic/musicplayer.cpp
+++ b/mythplugins/mythmusic/mythmusic/musicplayer.cpp
@@ -348,16 +348,18 @@ void MusicPlayer::stopDecoder(void)
 
 void MusicPlayer::openOutputDevice(void)
 {
-    QString adevice;
+    QString adevice, pdevice;
 
     if (gContext->GetSetting("MusicAudioDevice") == "default")
         adevice = gContext->GetSetting("AudioOutputDevice");
     else
         adevice = gContext->GetSetting("MusicAudioDevice");
 
+    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, 0, 44100,
+                                      AUDIOOUTPUT_MUSIC, true, false);
     m_output->setBufferSize(256 * 1024);
     m_output->SetBlocking(false);
 
diff --git a/mythplugins/mythmusic/mythmusic/playbackbox.cpp b/mythplugins/mythmusic/mythmusic/playbackbox.cpp
index f8a2bc7..0a6a061 100644
--- a/mythplugins/mythmusic/mythmusic/playbackbox.cpp
+++ b/mythplugins/mythmusic/mythmusic/playbackbox.cpp
@@ -367,6 +367,8 @@ void PlaybackBoxMusic::keyPressEvent(QKeyEvent *e)
             changeSpeed(true);
         else if (action == "MUTE")
             toggleMute();
+        else if (action == "TOGGLEUPMIX")
+            toggleUpmix();
         else if (action == "MENU" && visualizer_status != 2)
         {
             menufilters = false;
@@ -1202,6 +1204,13 @@ void PlaybackBoxMusic::toggleMute()
     }
 }
 
+void PlaybackBoxMusic::toggleUpmix()
+{
+    if (gPlayer->getOutput())
+        gPlayer->getOutput()->ToggleUpmix();
+}
+    
+
 void PlaybackBoxMusic::showProgressBar()
 {
     if (progress_bar && visualizer_status != 2)
diff --git a/mythplugins/mythmusic/mythmusic/playbackbox.h b/mythplugins/mythmusic/mythmusic/playbackbox.h
index ecc0207..b22c6ce 100644
--- a/mythplugins/mythmusic/mythmusic/playbackbox.h
+++ b/mythplugins/mythmusic/mythmusic/playbackbox.h
@@ -69,6 +69,7 @@ class PlaybackBoxMusic : public MythThemedDialog
     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 --git a/mythtv/libs/libavcodec/ac3dec.c b/mythtv/libs/libavcodec/ac3dec.c
index 99cd4e4..99c99be 100644
--- a/mythtv/libs/libavcodec/ac3dec.c
+++ b/mythtv/libs/libavcodec/ac3dec.c
@@ -115,6 +115,8 @@ static const uint8_t ac3_default_coeffs[8][5][2] = {
     { { 2, 7 }, { 5, 5 }, { 7, 2 }, { 6, 7 }, { 7, 6 }, },
 };
 
+static const int channel_map[6] = { 0, 2, 3, 4, 1, 5 };
+
 /**
  * Symmetrical Dequantization
  * reference: Section 7.3.3 Expansion of Mantissas for Symmetrical Quantization
@@ -1225,6 +1227,7 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data, int *data_size,
     int blk, ch, err;
     const uint8_t *channel_map;
     const float *output[AC3_MAX_CHANNELS];
+    int16_t tmp;
 
     /* initialize the GetBitContext with the start of valid AC-3 Frame */
     if (s->input_buffer) {
@@ -1327,6 +1330,15 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data, int *data_size,
         out_samples += 256 * s->out_channels;
     }
     *data_size = s->num_blocks * 256 * avctx->channels * sizeof (int16_t);
+    if (avctx->channels == 6) {
+        for (int i = 0; i < *data_size / sizeof(int16_t); i += avctx->channels) {
+            tmp = out_samples[i+1];
+            out_samples[i+1] = out_samples[i+2];
+            out_samples[i+2] = out_samples[i+3];
+            out_samples[i+3] = out_samples[i+4];
+            out_samples[i+4] = tmp;
+        }
+    }
     return s->frame_size;
 }
 
diff --git a/mythtv/libs/libavcodec/dca.c b/mythtv/libs/libavcodec/dca.c
index b42d3df..2f571d2 100644
--- a/mythtv/libs/libavcodec/dca.c
+++ b/mythtv/libs/libavcodec/dca.c
@@ -1241,6 +1241,7 @@ static int dca_decode_frame(AVCodecContext * avctx,
     int16_t *samples = data;
     DCAContext *s = avctx->priv_data;
     int channels;
+    int16_t tmp;
 
 
     s->dca_buffer_size = dca_convert_bitstream(buf, buf_size, s->dca_buffer, DCA_MAX_FRAME_SIZE);
@@ -1297,7 +1298,18 @@ static int dca_decode_frame(AVCodecContext * avctx,
         s->dsp.float_to_int16_interleave(samples, s->samples_chanptr, 256, channels);
         samples += 256 * channels;
     }
-
+     
+    if (channels == 6) {
+        for (i = 0; i < *data_size / sizeof(int16_t); i += channels) {
+            tmp = samples[i];
+            samples[i] = samples[i+1];
+            samples[i+1] = samples[i+2];
+            samples[i+2] = samples[i+3];
+            samples[i+3] = samples[i+4];
+            samples[i+4] = tmp;
+        }
+    }
+        
     return buf_size;
 }
 
diff --git a/mythtv/libs/libmyth/audiooutput.cpp b/mythtv/libs/libmyth/audiooutput.cpp
index 17f7c64..f97fe44 100644
--- a/mythtv/libs/libmyth/audiooutput.cpp
+++ b/mythtv/libs/libmyth/audiooutput.cpp
@@ -33,13 +33,14 @@ using namespace std;
 AudioOutput *AudioOutput::OpenAudio(
     const QString &main_device,
     const QString &passthru_device,
-    int audio_bits, int audio_channels, int audio_samplerate,
+    int audio_bits, int audio_channels, 
+    int audio_codec, int audio_samplerate,
     AudioOutputSource source,
     bool set_initial_vol, bool audio_passthru)
 {
     AudioSettings settings(
         main_device, passthru_device, audio_bits,
-        audio_channels, audio_samplerate, source,
+        audio_channels, audio_codec, audio_samplerate, source,
         set_initial_vol, audio_passthru);
 
     settings.FixPassThrough();
diff --git a/mythtv/libs/libmyth/audiooutput.h b/mythtv/libs/libmyth/audiooutput.h
index 943bd77..7c55ac0 100644
--- a/mythtv/libs/libmyth/audiooutput.h
+++ b/mythtv/libs/libmyth/audiooutput.h
@@ -15,7 +15,8 @@ class MPUBLIC AudioOutput : public VolumeBase, public OutputListeners
     static AudioOutput *OpenAudio(
         const QString &audiodevice,
         const QString &passthrudevice,
-        int audio_bits, int audio_channels, int audio_samplerate,
+        int audio_bits, int audio_channels, 
+        int audio_codec, int audio_samplerate,
         AudioOutputSource source,
         bool set_initial_vol, bool audio_passthru);
 
@@ -68,6 +69,7 @@ class MPUBLIC AudioOutput : public VolumeBase, public OutputListeners
     
     virtual void bufferOutputData(bool y) = 0;
     virtual int readOutputData(unsigned char *read_buffer, int max_length) = 0;
+    virtual bool ToggleUpmix(void) = 0;
 
   protected:
     void Error(const QString &msg);
diff --git a/mythtv/libs/libmyth/audiooutputalsa.cpp b/mythtv/libs/libmyth/audiooutputalsa.cpp
index 5bd6445..788ae18 100644
--- a/mythtv/libs/libmyth/audiooutputalsa.cpp
+++ b/mythtv/libs/libmyth/audiooutputalsa.cpp
@@ -32,6 +32,107 @@ AudioOutputALSA::AudioOutputALSA(const AudioSettings &settings) :
 AudioOutputALSA::~AudioOutputALSA()
 {
     KillAudio();
+    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"));
+    
+    snd_ctl_open(&ctl, "default", 0);
+    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);
+
+}
+
+vector<int> AudioOutputALSA::GetSupportedRates()
+{
+    snd_pcm_hw_params_t *params;
+    int err;
+    const int srates[] = { 8000, 11025, 16000, 22050, 32000, 44100, 48000 };
+    vector<int> rates(srates, srates + sizeof(srates) / sizeof(int) );
+    QString real_device;
+    
+    if (audio_passthru || audio_enc)
+        real_device = audio_passthru_device;
+    else 
+        real_device = audio_main_device;
+
+    if((err = snd_pcm_open(&pcm_handle, real_device.toAscii(),
+                           SND_PCM_STREAM_PLAYBACK, 
+                           SND_PCM_NONBLOCK|SND_PCM_NO_AUTO_RESAMPLE)) < 0)
+    { 
+        Error(QString("snd_pcm_open(%1): %2")
+              .arg(real_device).arg(snd_strerror(err)));
+
+        if (pcm_handle)
+        {
+            snd_pcm_close(pcm_handle);
+            pcm_handle = NULL;
+        }
+        rates.clear();
+        return rates;
+    }
+    
+    snd_pcm_hw_params_alloca(&params);
+
+    if ((err = snd_pcm_hw_params_any(pcm_handle, params)) < 0)
+    {
+        Error(QString("Broken configuration for playback; no configurations"
+              " available: %1").arg(snd_strerror(err)));
+        snd_pcm_close(pcm_handle);
+        pcm_handle = NULL;
+        rates.clear();
+        return rates;
+    }
+    
+    vector<int>::iterator it;
+
+    for (it = rates.begin(); it < rates.end(); it++)
+        if(snd_pcm_hw_params_test_rate(pcm_handle, params, *it, 0) < 0)
+            rates.erase(it--);
+    
+    snd_pcm_close(pcm_handle);
+    pcm_handle = NULL;
+
+    return rates;
 }
 
 bool AudioOutputALSA::OpenDevice()
@@ -39,15 +140,24 @@ bool AudioOutputALSA::OpenDevice()
     snd_pcm_format_t format;
     unsigned int buffer_time, period_time;
     int err;
+    QString real_device;
 
     if (pcm_handle != NULL)
         CloseDevice();
 
     pcm_handle = NULL;
     numbadioctls = 0;
-
-    QString real_device = (audio_passthru) ?
-        audio_passthru_device : audio_main_device;
+    
+    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));
diff --git a/mythtv/libs/libmyth/audiooutputalsa.h b/mythtv/libs/libmyth/audiooutputalsa.h
index a156edd..c260982 100644
--- a/mythtv/libs/libmyth/audiooutputalsa.h
+++ b/mythtv/libs/libmyth/audiooutputalsa.h
@@ -65,8 +65,10 @@ class AudioOutputALSA : public AudioOutputBase
     virtual void WriteAudio(unsigned char *aubuf, int size);
     virtual int  GetSpaceOnSoundcard(void) const;
     virtual int  GetBufferedOnSoundcard(void) const;
+    virtual vector<int> GetSupportedRates(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,
diff --git a/mythtv/libs/libmyth/audiooutputarts.h b/mythtv/libs/libmyth/audiooutputarts.h
index f985ef8..35ec39f 100644
--- a/mythtv/libs/libmyth/audiooutputarts.h
+++ b/mythtv/libs/libmyth/audiooutputarts.h
@@ -27,8 +27,8 @@ class AudioOutputARTS : public AudioOutputBase
     virtual void WriteAudio(unsigned char *aubuf, int size);
     virtual int  GetSpaceOnSoundcard(void) const;
     virtual int  GetBufferedOnSoundcard(void) const;
-
-     
+    virtual vector<int> GetSupportedRates(void) 
+        { vector<int> rates; return rates; }
 
   private:
     arts_stream_t pcm_handle;
diff --git a/mythtv/libs/libmyth/audiooutputbase.cpp b/mythtv/libs/libmyth/audiooutputbase.cpp
index ef2f3d5..63f90a4 100644
--- a/mythtv/libs/libmyth/audiooutputbase.cpp
+++ b/mythtv/libs/libmyth/audiooutputbase.cpp
@@ -21,16 +21,16 @@
 AudioOutputBase::AudioOutputBase(const AudioSettings &settings) :
     // protected
     effdsp(0),                  effdspstretched(0),
-    audio_channels(-1),         audio_bytes_per_sample(0),
-    audio_bits(-1),             audio_samplerate(-1),
-    audio_buffer_unused(0),
+    audio_channels(-1),         audio_codec(CODEC_ID_NONE),
+    audio_bytes_per_sample(0),  audio_bits(-1),
+    audio_samplerate(-1),       audio_buffer_unused(0),
     fragment_size(0),           soundcard_buffer_size(0),
 
     audio_main_device(settings.GetMainDevice()),
     audio_passthru_device(settings.GetPassthruDevice()),
-    audio_passthru(false),      audio_stretchfactor(1.0f),
+    audio_passthru(false),      audio_enc(false),
+    audio_reenc(false),         audio_stretchfactor(1.0f),
 
-    audio_codec(NULL),
     source(settings.source),    killaudio(false),
 
     pauseaudio(false),          audio_actually_paused(false),
@@ -48,9 +48,11 @@ AudioOutputBase::AudioOutputBase(const AudioSettings &settings) :
     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),
 
@@ -79,6 +81,9 @@ AudioOutputBase::AudioOutputBase(const AudioSettings &settings) :
     memset(&audiotime_updated, 0, sizeof(audiotime_updated));
     memset(audiobuffer,        0, sizeof(char)  * kAudioRingBufferSize);
     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);
 
     // You need to call Reconfigure from your concrete class.
     // Reconfigure(laudio_bits,       laudio_channels,
@@ -124,40 +129,9 @@ void AudioOutputBase::SetStretchFactorLocked(float laudio_stretchfactor)
             VERBOSE(VB_GENERAL, LOC + QString("Using time stretch %1")
                                         .arg(audio_stretchfactor));
             pSoundStretch = new soundtouch::SoundTouch();
-            if (audio_codec)
-            {
-                if (!encoder)
-                {
-                    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
-                                ))
-                    {
-                        // 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
-            {
-                pSoundStretch->setSampleRate(audio_samplerate);
-                pSoundStretch->setChannels(audio_channels);
-            }
+            pSoundStretch->setSampleRate(audio_samplerate);
+            pSoundStretch->setChannels(upmixer ? 
+                configured_audio_channels : source_audio_channels);
 
             pSoundStretch->setTempo(audio_stretchfactor);
             pSoundStretch->setSetting(SETTING_SEQUENCE_MS, 35);
@@ -165,7 +139,6 @@ void AudioOutputBase::SetStretchFactorLocked(float laudio_stretchfactor)
             // 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);
         }
@@ -183,35 +156,43 @@ float AudioOutputBase::GetStretchFactor(void) const
     return audio_stretchfactor;
 }
 
+bool AudioOutputBase::ToggleUpmix(void)
+{
+    if (orig_config_channels == 2 || source_audio_channels > 2 || 
+        audio_passthru)
+        return false;
+    if (configured_audio_channels == 6)
+        configured_audio_channels = 2;
+    else
+        configured_audio_channels = 6;
+
+    const AudioSettings settings(audio_bits, source_audio_channels, 
+                                 audio_codec, source_audio_samplerate, 
+                                 audio_passthru);
+    Reconfigure(settings); 
+    return (configured_audio_channels == 6);
+}
+
+
 void AudioOutputBase::Reconfigure(const AudioSettings &orig_settings)
 {
     AudioSettings settings = orig_settings;
 
-    int codec_id = CODEC_ID_NONE;
-    int lcodec_id = CODEC_ID_NONE;
-    int lcchannels = 0;
-    int cchannels = 0;
     int lsource_audio_channels = settings.channels;
     bool lneeds_upmix = false;
+    bool laudio_reenc = false;
 
-    if (settings.codec)
+    // Are we reencoding a (previously) timestretched bitstream?
+    if ((settings.codec == CODEC_ID_AC3 || settings.codec == CODEC_ID_DTS) && 
+        !settings.use_passthru && allow_ac3_passthru) 
     {
-        lcodec_id = ((AVCodecContext*)settings.codec)->codec_id;
-        settings.bits = 16;
-        settings.channels = 2;
-        lsource_audio_channels = settings.channels;
-        settings.samplerate = 48000;
-        lcchannels = ((AVCodecContext*)settings.codec)->channels;
+        laudio_reenc = true;
+        VERBOSE(VB_AUDIO, LOC + "Reencoding decoded AC3/DTS to AC3");
     }
 
-    if (audio_codec)
-    {
-        codec_id = audio_codec->codec_id;
-        cchannels = ((AVCodecContext*)audio_codec)->channels;
-    }
-
-    if ((configured_audio_channels == 6) &&
-        !(settings.codec || audio_codec))
+    // Enough channels? Upmix if not
+    if (settings.channels < configured_audio_channels && 
+        !settings.use_passthru)
     {
         settings.channels = configured_audio_channels;
         lneeds_upmix = true;
@@ -224,7 +205,7 @@ void AudioOutputBase::Reconfigure(const AudioSettings &orig_settings)
         settings.samplerate == audio_samplerate && !need_resampler &&
         settings.use_passthru == audio_passthru &&
         lneeds_upmix == needs_upmix &&
-        lcodec_id == codec_id && lcchannels == cchannels);
+        laudio_reenc == audio_reenc);
     bool upmix_deps =
         (lsource_audio_channels == source_audio_channels);
     if (general_deps && upmix_deps)
@@ -251,12 +232,11 @@ void AudioOutputBase::Reconfigure(const AudioSettings &orig_settings)
     waud = raud = 0;
     audio_actually_paused = false;
 
-    bool redo_stretch = (pSoundStretch && audio_channels != settings.channels);
     audio_channels = settings.channels;
     source_audio_channels = lsource_audio_channels;
     audio_bits = settings.bits;
-    audio_samplerate = settings.samplerate;
-    audio_codec = (AVCodecContext*)settings.codec;
+    source_audio_samplerate = audio_samplerate = settings.samplerate;
+    audio_reenc = laudio_reenc;
     audio_passthru = settings.use_passthru;
     needs_upmix = lneeds_upmix;
 
@@ -265,8 +245,9 @@ void AudioOutputBase::Reconfigure(const AudioSettings &orig_settings)
         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;
+    
+    VERBOSE(VB_AUDIO, LOC + QString("Original audio codec was %1")
+                            .arg(codec_id_string((CodecID)audio_codec)));
 
     need_resampler = false;
     killaudio = false;
@@ -275,7 +256,73 @@ void AudioOutputBase::Reconfigure(const AudioSettings &orig_settings)
     internal_vol = gContext->GetNumSetting("MythControlsVolume", 0);
 
     numlowbuffer = 0;
+    
+    // Find out what sample rates we can output (if output layer supports it)
+    vector<int> rates = GetSupportedRates();
+    vector<int>::iterator it;
+    bool resample = true;
+
+    for (it = rates.begin(); it < rates.end(); it++)
+    {
+        VERBOSE(VB_AUDIO, LOC + QString("Sample rate %1 is supported")
+                                .arg(*it));
+        if (*it == audio_samplerate)
+            resample = false;
+    }
+
+    // Assume 48k if we can't get supported rates
+    if (rates.empty())
+        rates.push_back(48000);
+
+    if (resample)
+    {
+        int error;
+        audio_samplerate = *(rates.end());
+        VERBOSE(VB_GENERAL, LOC + QString("Using resampler. From: %1 to %2")
+            .arg(settings.samplerate).arg(audio_samplerate));
+        src_ctx = src_new(3-src_quality, source_audio_channels, &error);
+        if (error)
+        {
+            Error(QString("Error creating resampler, the error was: %1")
+                  .arg(src_strerror(error)) );
+	    src_ctx = NULL;
+            return;
+        }
+        src_data.src_ratio = (double) audio_samplerate / settings.samplerate;
+        src_data.data_in = src_in;
+        src_data.data_out = src_out;
+        src_data.output_frames = 16384*6;
+        need_resampler = true;
+    }
+    
+    // Encode to AC-3 if not passing thru , there's > 2 channels
+    // and a passthru device is defined
+    if (
+        !audio_passthru && allow_ac3_passthru &&
+        (audio_channels > 2 || audio_reenc)
+       )
+    {
+        VERBOSE(VB_AUDIO, LOC + "Creating AC-3 Encoder");
+        encoder = new AudioOutputDigitalEncoder();
+        if (!encoder->Init(CODEC_ID_AC3, 448000, audio_samplerate, 
+                           audio_channels)) 
+        {
+            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;
 
+    
     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));
@@ -309,27 +356,6 @@ void AudioOutputBase::Reconfigure(const AudioSettings &orig_settings)
     current_seconds = -1;
     source_bitrate = -1;
 
-    // NOTE: this won't do anything as above samplerate vars are set equal
-    // Check if we need the resampler
-    if (audio_samplerate != settings.samplerate)
-    {
-        int error;
-        VERBOSE(VB_GENERAL, LOC + QString("Using resampler. From: %1 to %2")
-                               .arg(settings.samplerate).arg(audio_samplerate));
-        src_ctx = src_new (SRC_SINC_BEST_QUALITY, audio_channels, &error);
-        if (error)
-        {
-            Error(QString("Error creating resampler, the error was: %1")
-                  .arg(src_strerror(error)) );
-            return;
-        }
-        src_data.src_ratio = (double) audio_samplerate / settings.samplerate;
-        src_data.data_in = src_in;
-        src_data.data_out = src_out;
-        src_data.output_frames = 16384*6;
-        need_resampler = true;
-    }
-
     if (needs_upmix)
     {
         VERBOSE(VB_AUDIO, LOC + QString("create upmixer"));
@@ -344,63 +370,15 @@ void AudioOutputBase::Reconfigure(const AudioSettings &orig_settings)
             (FreeSurround::SurroundMode)surround_mode);
 
         VERBOSE(VB_AUDIO, LOC +
-                QString("create upmixer done with surround mode %1")
+                QString("Create upmixer done with surround mode %1")
                 .arg(surround_mode));
     }
 
     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)
-    {
-        delete pSoundStretch;
-        pSoundStretch = NULL;
-        SetStretchFactorLocked(audio_stretchfactor);
-    }
-    else
-    {
-        SetStretchFactorLocked(audio_stretchfactor);
-        if (pSoundStretch)
-        {
-            // if its passthru then we need to reencode
-            if (audio_codec)
-            {
-                if (!encoder)
-                {
-                    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
-                                ))
-                    {
-                        // 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);
-            }
-        }
-    }
 
+    SetStretchFactorLocked(old_audio_stretchfactor);
+    
     // Setup visualisations, zero the visualisations buffers
     prepareVisuals();
 
@@ -436,10 +414,15 @@ void AudioOutputBase::KillAudio()
     VERBOSE(VB_AUDIO, LOC + "Killing AudioOutputDSP");
     killaudio = true;
     StopOutputThread();
+    QMutexLocker lock1(&audio_buflock);
 
     // Close resampler?
     if (src_ctx)
+    {
         src_delete(src_ctx);
+        src_ctx = NULL;
+    }
+		
     need_resampler = false;
 
     // close sound stretcher
@@ -447,6 +430,8 @@ void AudioOutputBase::KillAudio()
     {
         delete pSoundStretch;
         pSoundStretch = NULL;
+        old_audio_stretchfactor = audio_stretchfactor;
+        audio_stretchfactor = 1.0;
     }
 
     if (encoder)
@@ -461,6 +446,7 @@ void AudioOutputBase::KillAudio()
         upmixer = NULL;
     }
     needs_upmix = false;
+    audio_enc = false;
 
     CloseDevice();
 
@@ -562,7 +548,6 @@ int AudioOutputBase::GetAudiotime(void)
     ret += (now.tv_usec - audiotime_updated.tv_usec) / 1000;
     ret = (long long)(ret * audio_stretchfactor);
 
-#if 1
     VERBOSE(VB_AUDIO+VB_TIMESTAMP,
             QString("GetAudiotime now=%1.%2, set=%3.%4, ret=%5, audt=%6 sf=%7")
             .arg(now.tv_sec).arg(now.tv_usec)
@@ -571,7 +556,6 @@ int AudioOutputBase::GetAudiotime(void)
             .arg(audiotime)
             .arg(audio_stretchfactor)
            );
-#endif
 
     ret += audiotime;
 
@@ -611,26 +595,20 @@ void AudioOutputBase::SetAudiotime(void)
 
     // 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);
-        // add the effect of unprocessed samples in time stretch algo
         totalbuffer += (int)((pSoundStretch->numUnprocessedSamples() *
                               audio_bytes_per_sample) / audio_stretchfactor);
-    }
 
     if (upmixer && needs_upmix)
-    {
         totalbuffer += upmixer->sampleLatency() * audio_bytes_per_sample;
-    }
+
+    if (encoder) 
+         totalbuffer += encoder->Buffered();
 
     audiotime = audbuf_timecode - (int)(totalbuffer * 100000.0 /
                                    (audio_bytes_per_sample * effdspstretched));
 
     gettimeofday(&audiotime_updated, NULL);
-#if 1
+    
     VERBOSE(VB_AUDIO+VB_TIMESTAMP,
             QString("SetAudiotime set=%1.%2, audt=%3 atc=%4 "
                     "tb=%5 sb=%6 eds=%7 abps=%8 sf=%9")
@@ -642,7 +620,6 @@ void AudioOutputBase::SetAudiotime(void)
             .arg(effdspstretched)
             .arg(audio_bytes_per_sample)
             .arg(audio_stretchfactor));
-#endif
 }
 
 int AudioOutputBase::GetAudioBufferedTime(void)
@@ -681,6 +658,8 @@ bool AudioOutputBase::AddSamples(char *buffers[], int samples,
         return false; // would overflow
     }
 
+    QMutexLocker lock1(&audio_buflock);
+
     // resample input if necessary
     if (need_resampler && src_ctx)
     {
@@ -725,6 +704,10 @@ bool AudioOutputBase::AddSamples(char *buffer, int samples, long long timecode)
     int abps = (encoder) ?
         encoder->audio_bytes_per_sample : audio_bytes_per_sample;
     int len = samples * abps;
+    
+    // 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)
@@ -749,6 +732,8 @@ bool AudioOutputBase::AddSamples(char *buffer, int samples, long long timecode)
         return false; // would overflow
     }
 
+    QMutexLocker lock1(&audio_buflock);
+
     // resample input if necessary
     if (need_resampler && src_ctx)
     {
@@ -808,10 +793,13 @@ int AudioOutputBase::WaitForFreeSpace(int samples)
             if (src_ctx)
             {
                 int error = src_reset(src_ctx);
-                if (error)
+                if (error) 
+                {
                     VERBOSE(VB_IMPORTANT, LOC_ERR + QString(
                             "Error occured while resetting resampler: %1")
                             .arg(src_strerror(error)));
+                    src_ctx = NULL;
+                }
             }
         }
     }
@@ -821,8 +809,6 @@ int AudioOutputBase::WaitForFreeSpace(int samples)
 void AudioOutputBase::_AddSamples(void *buffer, bool interleaved, int samples,
                                   long long timecode)
 {
-    audio_buflock.lock();
-
     int len; // = samples * audio_bytes_per_sample;
     int audio_bytes = audio_bits / 8;
     int org_waud = waud;
@@ -839,17 +825,17 @@ void AudioOutputBase::_AddSamples(void *buffer, bool interleaved, int samples,
             .arg(samples * abps)
             .arg(kAudioRingBufferSize-afree).arg(afree).arg(timecode)
             .arg(needs_upmix));
-
+    
+    len = WaitForFreeSpace(samples);
+        
     if (upmixer && needs_upmix)
     {
         int out_samples = 0;
+        org_waud = waud;
         int step = (interleaved)?source_audio_channels:1;
-        len = WaitForFreeSpace(samples);    // test
+	
         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
-            audio_buflock.unlock();
             if (audio_bytes == 2)
             {
                 itemp += upmixer->putSamples(
@@ -866,7 +852,6 @@ void AudioOutputBase::_AddSamples(void *buffer, bool interleaved, int samples,
                     source_audio_channels,
                     (interleaved) ? 0 : samples);
             }
-            audio_buflock.lock();
 
             int copy_samples = upmixer->numSamples();
             if (copy_samples)
@@ -900,8 +885,6 @@ void AudioOutputBase::_AddSamples(void *buffer, bool interleaved, int samples,
     }
     else
     {
-        len = WaitForFreeSpace(samples);
-
         if (interleaved)
         {
             char *mybuf = (char*)buffer;
@@ -936,138 +919,106 @@ void AudioOutputBase::_AddSamples(void *buffer, bool interleaved, int samples,
         }
     }
 
-    if (samples > 0)
+    if (samples <= 0)
+        return;
+        
+    if (pSoundStretch)
     {
-        if (pSoundStretch)
+        // does not change the timecode, only the number of samples
+        // back to orig pos
+        org_waud = waud;
+        int bdiff = kAudioRingBufferSize - 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);
+        }
 
-            // does not change the timecode, only the number of samples
-            // back to orig pos
-            org_waud = waud;
-            int bdiff = kAudioRingBufferSize - 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);
+        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 = kAudioRingBufferSize/abps;
             }
-            else
-            {
-                pSoundStretch->putSamples((soundtouch::SAMPLETYPE*)
-                                          (audiobuffer + org_waud),
-                                          len / abps);
+            else {
+                org_waud += nSamples * abps;
+                nSamplesToEnd -= nSamples;
             }
+            
+        }
+        
+    }
 
-            if (encoder)
-            {
-                // pull out a packet's worth and reencode it until we
-                // don't have enough for any more packets
-                soundtouch::SAMPLETYPE *temp_buff =
-                    (soundtouch::SAMPLETYPE*)encoder->GetFrameBuffer();
-                size_t frameSize = encoder->FrameSize()/abps;
+    // Encode to AC-3? 
+    if (encoder) 
+    {
+        
+        org_waud = waud;
+        int bdiff = kAudioRingBufferSize - org_waud;
+        int to_get = 0;
 
-                VERBOSE(VB_AUDIO+VB_TIMESTAMP,
-                        QString("_AddSamples Enc sfs=%1 bfs=%2 sss=%3")
-                        .arg(frameSize)
-                        .arg(encoder->FrameSize())
-                        .arg(pSoundStretch->numSamples()));
-
-                // process the same number of samples as it creates
-                // a full encoded buffer just like before
-                while (pSoundStretch->numSamples() >= frameSize)
-                {
-                    int got = pSoundStretch->receiveSamples(
-                        temp_buff, frameSize);
-                    int amount = encoder->Encode(temp_buff);
-
-                    VERBOSE(VB_AUDIO+VB_TIMESTAMP,
-                            QString("_AddSamples Enc bytes=%1 got=%2 left=%3")
-                            .arg(amount)
-                            .arg(got)
-                            .arg(pSoundStretch->numSamples()));
-
-                    if (!amount)
-                        continue;
-
-                    //len = WaitForFreeSpace(amount);
-                    char *ob = encoder->GetOutBuff();
-                    if (amount >= bdiff)
-                    {
-                        memcpy(audiobuffer + org_waud, ob, bdiff);
-                        ob += bdiff;
-                        amount -= bdiff;
-                        org_waud = 0;
-                    }
-                    if (amount > 0)
-                        memcpy(audiobuffer + org_waud, ob, amount);
-
-                    bdiff = kAudioRingBufferSize - amount;
-                    org_waud = (org_waud + amount) % kAudioRingBufferSize;
-                }
-            }
-            else
+        if (bdiff < len) 
+        {
+            encoder->Encode(audiobuffer + org_waud, bdiff);
+            to_get = encoder->Encode(audiobuffer, len - bdiff);
+        }
+        else 
+            to_get = encoder->Encode(audiobuffer + org_waud, len);
+        
+        if (to_get > 0) 
+        {
+            
+            if (to_get >= bdiff)
             {
-                int newLen = 0;
-                int nSamples;
-                len = WaitForFreeSpace(pSoundStretch->numSamples() *
-                                       audio_bytes_per_sample);
-                do
-                {
-                    int samplesToGet = len/audio_bytes_per_sample;
-                    if (samplesToGet > nSamplesToEnd)
-                    {
-                        samplesToGet = nSamplesToEnd;
-                    }
-
-                    nSamples = pSoundStretch->receiveSamples(
-                        (soundtouch::SAMPLETYPE*)
-                        (audiobuffer + org_waud), samplesToGet);
-                    if (nSamples == nSamplesToEnd)
-                    {
-                        org_waud = 0;
-                        nSamplesToEnd = kAudioRingBufferSize/audio_bytes_per_sample;
-                    }
-                    else
-                    {
-                        int bufsz = nSamples * audio_bytes_per_sample;
-                        org_waud = (org_waud + bufsz) % kAudioRingBufferSize;
-                        nSamplesToEnd -= nSamples;
-                    }
-
-                    newLen += nSamples * audio_bytes_per_sample;
-                    len -= nSamples * audio_bytes_per_sample;
-                } while (nSamples > 0);
+                encoder->GetFrames(audiobuffer + org_waud, bdiff);
+                to_get -= bdiff;
+                org_waud = 0;
             }
-        }
+            if (to_get > 0)
+                encoder->GetFrames(audiobuffer + org_waud, to_get);
 
-        waud = org_waud;
-        lastaudiolen = audiolen(false);
+            org_waud += to_get;
 
-        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);
 
-        if (interleaved)
-        {
-            dispatchVisual((unsigned char *)buffer, len, timecode,
-                           source_audio_channels, audio_bits);
-        }
     }
 
-    audio_buflock.unlock();
+    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);
+
 }
 
 void AudioOutputBase::Status()
diff --git a/mythtv/libs/libmyth/audiooutputbase.h b/mythtv/libs/libmyth/audiooutputbase.h
index 1f636e2..4bcaaa4 100644
--- a/mythtv/libs/libmyth/audiooutputbase.h
+++ b/mythtv/libs/libmyth/audiooutputbase.h
@@ -43,6 +43,7 @@ class AudioOutputBase : public AudioOutput, public QThread
 
     virtual void SetStretchFactor(float factor);
     virtual float GetStretchFactor(void) const;
+    virtual bool ToggleUpmix(void);
 
     virtual void Reset(void);
 
@@ -85,6 +86,8 @@ class AudioOutputBase : public AudioOutput, public QThread
     virtual void WriteAudio(unsigned char *aubuf, int size) = 0;
     virtual int  GetSpaceOnSoundcard(void) const = 0;
     virtual int  GetBufferedOnSoundcard(void) const = 0;
+    virtual vector<int> GetSupportedRates(void) = 0;
+
     /// You need to call this from any implementation in the dtor.
     void KillAudio(void);
 
@@ -122,6 +125,7 @@ class AudioOutputBase : public AudioOutput, public QThread
 
     // Basic details about the audio stream
     int audio_channels;
+    int audio_codec;
     int audio_bytes_per_sample;
     int audio_bits;
     int audio_samplerate;
@@ -132,9 +136,10 @@ class AudioOutputBase : public AudioOutput, public QThread
     QString audio_passthru_device;
 
     bool audio_passthru;
+    bool audio_enc;
+    bool audio_reenc;
 
     float audio_stretchfactor;
-    AVCodecContext *audio_codec;
     AudioOutputSource source;
 
     bool killaudio;
@@ -144,6 +149,8 @@ class AudioOutputBase : public AudioOutput, public QThread
     bool buffer_output_data_for_use; //  used by AudioOutputNULL
 
     int configured_audio_channels;
+    int orig_config_channels;
+    int src_quality;
 
  private:
     // resampler
@@ -156,9 +163,12 @@ class AudioOutputBase : public AudioOutput, public QThread
     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 --git a/mythtv/libs/libmyth/audiooutputca.h b/mythtv/libs/libmyth/audiooutputca.h
index 5afe3e0..14192bb 100644
--- a/mythtv/libs/libmyth/audiooutputca.h
+++ b/mythtv/libs/libmyth/audiooutputca.h
@@ -49,6 +49,8 @@ protected:
     
     virtual bool StartOutputThread(void) { return true; }
     virtual void StopOutputThread(void) {}
+    virtual vector<int> GetSupportedRates(void) 
+        { vector<int> rates; return rates; }
 
 private:
 
diff --git a/mythtv/libs/libmyth/audiooutputdigitalencoder.cpp b/mythtv/libs/libmyth/audiooutputdigitalencoder.cpp
index a9688c9..f3bce4c 100644
--- a/mythtv/libs/libmyth/audiooutputdigitalencoder.cpp
+++ b/mythtv/libs/libmyth/audiooutputdigitalencoder.cpp
@@ -32,9 +32,8 @@ extern "C" {
 AudioOutputDigitalEncoder::AudioOutputDigitalEncoder(void) :
     audio_bytes_per_sample(0),
     av_context(NULL),
-    outbuf(NULL),
-    outbuf_size(0),
-    frame_buffer(NULL),
+    outbuflen(0),
+    inbuflen(0),
     one_frame_bytes(0)
 {
 }
@@ -52,20 +51,6 @@ void AudioOutputDigitalEncoder::Dispose()
         av_free(av_context);
         av_context = NULL;
     }
-
-    if (outbuf)
-    {
-        delete [] outbuf;
-        outbuf = NULL;
-        outbuf_size = 0;
-    }
-
-    if (frame_buffer)
-    {
-        delete [] frame_buffer;
-        frame_buffer = NULL;
-        one_frame_bytes = 0;
-    }
 }
 
 //CODEC_ID_AC3
@@ -80,8 +65,10 @@ bool AudioOutputDigitalEncoder::Init(
             .arg(bitrate)
             .arg(samplerate)
             .arg(channels));
-
-    //codec = avcodec_find_encoder(codec_id);
+    
+    // We need to do this when called from mythmusic
+    avcodec_init();
+    avcodec_register_all();
     // always AC3 as there is no DTS encoder at the moment 2005/1/9
     codec = avcodec_find_encoder(CODEC_ID_AC3);
     if (!codec)
@@ -110,8 +97,6 @@ bool AudioOutputDigitalEncoder::Init(
     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,13 +241,26 @@ typedef struct {
 
 } 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 enc_len)
 {
     unsigned char *payload = data + 8;  // skip header, currently 52 or 54bits
-    size_t         enc_len;
     int            flags, sample_rate, bit_rate;
 
     // we don't do any length/crc validation of the AC3 frame here; presumably
@@ -273,7 +271,8 @@ static int encode_frame(
     // 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(payload, &flags, &sample_rate, &bit_rate);
@@ -302,13 +301,6 @@ static int encode_frame(
         }
     }
 
-    if (enc_len == 0 || enc_len > len)
-    {
-        int l = len;
-        len = 0;
-        return l;
-    }
-
     enc_len = std::min((uint)enc_len, block_len - 8);
 
     //uint32_t x = *(uint32_t*)payload;
@@ -361,31 +353,45 @@ static int encode_frame(
     data[6] = (enc_len << 3) & 0xFF;
     data[7] = (enc_len >> 5) & 0xFF;
     memset(payload + enc_len, 0, block_len - 8 - enc_len);
-    len = block_len;
 
     return enc_len;
 }
 
 // must have exactly 1 frames worth of data
-size_t AudioOutputDigitalEncoder::Encode(short *buff)
+size_t AudioOutputDigitalEncoder::Encode(void *buf, int len)
 {
-    int encsize = 0;
     size_t outsize = 0;
  
-    // put data in the correct spot for encode frame
-    outsize = avcodec_encode_audio(
-        av_context, ((uchar*)outbuf) + 8, outbuf_size - 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);
+    int fs = FrameSize();
+    memcpy(inbuf+inbuflen, buf, len);
+    inbuflen += len;
+    int frames = inbuflen / fs;
 
-    VERBOSE(VB_AUDIO+VB_TIMESTAMP, 
-            QString("DigitalEncoder::Encode len1=%1 len2=%2 finallen=%3")
-                .arg(tmpsize).arg(encsize).arg(outsize));
+    while (frames--) 
+    {
+        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
+        );
+
+        outbuflen += MAX_AC3_FRAME_SIZE;
+        inbuflen -= fs;
+        memmove(inbuf, inbuf+fs, inbuflen);
+    }
+  
+    return outbuflen;
+}
 
-    return outsize;
+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 --git a/mythtv/libs/libmyth/audiooutputdigitalencoder.h b/mythtv/libs/libmyth/audiooutputdigitalencoder.h
index 8a4689a..8d81298 100644
--- a/mythtv/libs/libmyth/audiooutputdigitalencoder.h
+++ b/mythtv/libs/libmyth/audiooutputdigitalencoder.h
@@ -5,6 +5,9 @@ extern "C" {
 #include "libavcodec/avcodec.h"
 };
 
+#define INBUFSIZE 131072
+#define OUTBUFSIZE 98304
+
 class AudioOutputDigitalEncoder
 {
   public:
@@ -13,29 +16,21 @@ class AudioOutputDigitalEncoder
 
     bool   Init(CodecID codec_id, int bitrate, int samplerate, int channels);
     void   Dispose(void);
-    size_t Encode(short * buff);
-
-    inline char *GetFrameBuffer(void);
+    size_t Encode(void *buf, int len);
+    void   GetFrames(void *ptr, int maxlen);
     size_t FrameSize(void)  const { return one_frame_bytes; }
-    char  *GetOutBuff(void) const { return outbuf;          }
+    int    Buffered(void) const { return inbuflen; }
 
   public:
     size_t audio_bytes_per_sample;
 
   private:
     AVCodecContext *av_context;
-    char           *outbuf;
-    int             outbuf_size;
-    char           *frame_buffer;
+    char            outbuf[OUTBUFSIZE];
+    char            inbuf[INBUFSIZE];
+    int             outbuflen;
+    int             inbuflen;
     size_t          one_frame_bytes;
 };
 
-inline char *AudioOutputDigitalEncoder::GetFrameBuffer(void)
-{
-    if (!frame_buffer && av_context)
-        frame_buffer = new char [one_frame_bytes];
-
-    return frame_buffer; 
-}
-
 #endif
diff --git a/mythtv/libs/libmyth/audiooutputdx.h b/mythtv/libs/libmyth/audiooutputdx.h
index e0d3e24..485adb1 100644
--- a/mythtv/libs/libmyth/audiooutputdx.h
+++ b/mythtv/libs/libmyth/audiooutputdx.h
@@ -45,6 +45,8 @@ public:
     // Volume control
     virtual int GetVolumeChannel(int channel) const; // Returns 0-100
     virtual void SetVolumeChannel(int channel, int volume); // range 0-100 for vol
+    virtual vector<int> GetSupportedRates(void) 
+        { vector<int> rates; return rates; }
 
  private:
     HINSTANCE dsound_dll;      /* handle of the opened dsound dll */
diff --git a/mythtv/libs/libmyth/audiooutputjack.cpp b/mythtv/libs/libmyth/audiooutputjack.cpp
index 7e0ad0d..f9a5848 100644
--- a/mythtv/libs/libmyth/audiooutputjack.cpp
+++ b/mythtv/libs/libmyth/audiooutputjack.cpp
@@ -30,6 +30,42 @@ AudioOutputJACK::AudioOutputJACK(const AudioSettings &settings) :
     Reconfigure(settings);
 }
 
+vector<int> AudioOutputJACK::GetSupportedRates()
+{
+    const int srates[] = { 8000, 11025, 16000, 22050, 32000, 44100, 48000 };
+    vector<int> rates(srates, srates + sizeof(srates) / sizeof(int) );
+    unsigned long jack_port_flags = 0;
+    unsigned int jack_port_name_count = 1;
+    const char *jack_port_name = audio_main_device.ascii();
+    int err = -1;
+    audioid = -1;
+    vector<int>::iterator it;
+
+    for (it = rates.begin(); it < rates.end(); it++)
+    {
+        err = JACK_OpenEx(&audioid, 16, (unsigned long *)it,
+                          2, 2, &jack_port_name, jack_port_name_count, 
+                          jack_port_flags);
+        
+        if (err == 1) 
+        {
+            Error(QString("Error connecting to jackd: %1. Is it running?")
+                  .arg(audio_main_device));
+            rates.clear();
+            return rates;
+        } 
+        else if (err == 2) 
+            rates.erase(it--);
+
+        JACK_Close(audioid);
+        audioid = -1;
+        
+    }
+ 
+    return rates;
+}
+
+
 AudioOutputJACK::~AudioOutputJACK()
 {
     // Close down all audio stuff
diff --git a/mythtv/libs/libmyth/audiooutputjack.h b/mythtv/libs/libmyth/audiooutputjack.h
index f87538e..259c202 100644
--- a/mythtv/libs/libmyth/audiooutputjack.h
+++ b/mythtv/libs/libmyth/audiooutputjack.h
@@ -23,6 +23,7 @@ class AudioOutputJACK : public AudioOutputBase
     virtual void WriteAudio(unsigned char *aubuf, int size);
     virtual int  GetSpaceOnSoundcard(void) const;
     virtual int  GetBufferedOnSoundcard(void) const;
+    virtual vector<int> GetSupportedRates(void); 
 
   private:
 
diff --git a/mythtv/libs/libmyth/audiooutputnull.h b/mythtv/libs/libmyth/audiooutputnull.h
index 7eb247d..78a0f54 100644
--- a/mythtv/libs/libmyth/audiooutputnull.h
+++ b/mythtv/libs/libmyth/audiooutputnull.h
@@ -41,6 +41,8 @@ class AudioOutputNULL : public AudioOutputBase
     virtual void WriteAudio(unsigned char *aubuf, int size);
     virtual int  GetSpaceOnSoundcard(void) const;
     virtual int  GetBufferedOnSoundcard(void) const;
+    virtual vector<int> GetSupportedRates(void) 
+        { vector<int> rates; return rates; }
 
   private:
     QMutex        pcm_output_buffer_mutex;
diff --git a/mythtv/libs/libmyth/audiooutputoss.cpp b/mythtv/libs/libmyth/audiooutputoss.cpp
index 127bf6e..8d3b135 100644
--- a/mythtv/libs/libmyth/audiooutputoss.cpp
+++ b/mythtv/libs/libmyth/audiooutputoss.cpp
@@ -42,6 +42,32 @@ AudioOutputOSS::~AudioOutputOSS()
     KillAudio();
 }
 
+vector<int> AudioOutputOSS::GetSupportedRates()
+{
+    const int srates[] = { 8000, 11025, 16000, 22050, 32000, 44100, 48000 };
+    vector<int> rates(srates, srates + sizeof(srates) / sizeof(int) );
+    audiofd = open(audio_main_device.toAscii(), O_WRONLY | O_NONBLOCK);
+    
+    if (audiofd < 0) 
+    {
+        VERBOSE(VB_IMPORTANT, QString("Error opening audio device (%1), the"
+                " error was: %2").arg(audio_main_device).arg(strerror(errno)));
+        rates.clear();
+        return rates;
+    }
+    
+    vector<int>::iterator it;
+
+    for (it = rates.begin(); it < rates.end(); it++)
+        if(ioctl(audiofd, SNDCTL_DSP_SPEED, &audio_samplerate) < 0)
+            rates.erase(it--);
+    
+    close(audiofd);
+    audiofd = -1;
+   
+    return rates;
+}
+
 bool AudioOutputOSS::OpenDevice()
 {
     numbadioctls = 0;
diff --git a/mythtv/libs/libmyth/audiooutputoss.h b/mythtv/libs/libmyth/audiooutputoss.h
index d5105a2..e218e31 100644
--- a/mythtv/libs/libmyth/audiooutputoss.h
+++ b/mythtv/libs/libmyth/audiooutputoss.h
@@ -23,6 +23,7 @@ class AudioOutputOSS : public AudioOutputBase
     virtual void WriteAudio(unsigned char *aubuf, int size);
     virtual int  GetSpaceOnSoundcard(void) const;
     virtual int  GetBufferedOnSoundcard(void) const;
+    virtual vector<int> GetSupportedRates(void);
 
   private:
     void VolumeInit(void);
diff --git a/mythtv/libs/libmyth/audiooutputwin.h b/mythtv/libs/libmyth/audiooutputwin.h
index 8ba37e4..5fd5945 100644
--- a/mythtv/libs/libmyth/audiooutputwin.h
+++ b/mythtv/libs/libmyth/audiooutputwin.h
@@ -23,6 +23,8 @@ class AudioOutputWin : public AudioOutputBase
     virtual void WriteAudio(unsigned char *aubuf, int size);
     virtual int  GetSpaceOnSoundcard(void) const;
     virtual int  GetBufferedOnSoundcard(void) const;
+    virtual vector<int> GetSupportedRates(void) 
+        { vector<int> rates; return rates; }
 
   protected:
     AudioOutputWinPrivate *m_priv;
diff --git a/mythtv/libs/libmyth/audiosettings.cpp b/mythtv/libs/libmyth/audiosettings.cpp
index 68e515b..1f4ef18 100644
--- a/mythtv/libs/libmyth/audiosettings.cpp
+++ b/mythtv/libs/libmyth/audiosettings.cpp
@@ -12,10 +12,10 @@ AudioSettings::AudioSettings() :
     passthru_device(QString::null),
     bits(-1),
     channels(-1),
+    codec(0),
     samplerate(-1),
     set_initial_vol(false),
     use_passthru(false),
-    codec(NULL),
     source(AUDIOOUTPUT_UNKNOWN)
 {
 }
@@ -25,10 +25,10 @@ AudioSettings::AudioSettings(const AudioSettings &other) :
     passthru_device(other.passthru_device),
     bits(other.bits),
     channels(other.channels),
+    codec(other.codec),
     samplerate(other.samplerate),
     set_initial_vol(other.set_initial_vol),
     use_passthru(other.use_passthru),
-    codec(other.codec),
     source(other.source)
 {
 }
@@ -38,19 +38,19 @@ AudioSettings::AudioSettings(
     const QString &audio_passthru_device,
     int audio_bits,
     int audio_channels,
+    int audio_codec,
     int audio_samplerate,
     AudioOutputSource audio_source,
     bool audio_set_initial_vol,
-    bool audio_use_passthru,
-    void *audio_codec) :
+    bool audio_use_passthru) :
     main_device(audio_main_device),
     passthru_device(audio_passthru_device),
     bits(audio_bits),
     channels(audio_channels),
+    codec(audio_codec),
     samplerate(audio_samplerate),
     set_initial_vol(audio_set_initial_vol),
     use_passthru(audio_use_passthru),
-    codec(audio_codec),
     source(audio_source)
 {
 }
@@ -58,17 +58,17 @@ AudioSettings::AudioSettings(
 AudioSettings::AudioSettings(
     int   audio_bits, 
     int   audio_channels, 
+    int   audio_codec,
     int   audio_samplerate,
-    bool  audio_use_passthru,
-    void *audio_codec) :
+    bool  audio_use_passthru) :
     main_device(QString::null),
     passthru_device(QString::null),
     bits(audio_bits),
     channels(audio_channels),
+    codec(audio_codec),
     samplerate(audio_samplerate),
     set_initial_vol(false),
     use_passthru(audio_use_passthru),
-    codec(audio_codec),
     source(AUDIOOUTPUT_UNKNOWN)
 {
 }
diff --git a/mythtv/libs/libmyth/audiosettings.h b/mythtv/libs/libmyth/audiosettings.h
index f9349f4..ba38f51 100644
--- a/mythtv/libs/libmyth/audiosettings.h
+++ b/mythtv/libs/libmyth/audiosettings.h
@@ -29,17 +29,17 @@ class MPUBLIC AudioSettings
         const QString    &audio_passthru_device,
         int               audio_bits,
         int               audio_channels,
+        int               audio_codec,
         int               audio_samplerate,
         AudioOutputSource audio_source,
         bool              audio_set_initial_vol,
-        bool              audio_use_passthru,
-        void             *audio_codec = NULL);
+        bool              audio_use_passthru);
 
     AudioSettings(int   audio_bits, 
                   int   audio_channels, 
+                  int   audio_codec,
                   int   audio_samplerate,
-                  bool  audio_use_passthru,
-                  void *audio_codec = NULL);
+                  bool  audio_use_passthru);
 
     void FixPassThrough(void);
     void TrimDeviceType(void);
@@ -54,10 +54,10 @@ class MPUBLIC AudioSettings
   public:
     int     bits;
     int     channels;
+    int     codec;
     int     samplerate;
     bool    set_initial_vol;
     bool    use_passthru;
-    void   *codec;
     AudioOutputSource source;
 };
 
diff --git a/mythtv/libs/libmythfreesurround/el_processor.cpp b/mythtv/libs/libmythfreesurround/el_processor.cpp
index 8f24737..1cf0dc8 100644
--- a/mythtv/libs/libmythfreesurround/el_processor.cpp
+++ b/mythtv/libs/libmythfreesurround/el_processor.cpp
@@ -40,17 +40,7 @@ typedef std::complex<float> cfloat;
 
 const float PI = 3.141592654;
 const float epsilon = 0.000001;
-//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
-//const float center_level = 0.5;   // gain of the center channel
-
-// should be .6-.7
-// but with centerlevel 2x what its supposed to be, we halve 0.68
-// to keep center from clipping
-//const float window_gain = 0.34;     
-//const float window_gain = 0.68;     
-const float window_gain = 0.95;     // to prive a bit of margin
+const float center_level = 0.5*sqrt(0.5);
 
 // private implementation of the surround decoder
 class decoder_impl {
@@ -98,19 +88,11 @@ public:
             outbuf[c].resize(N);
             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);
+        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,10 +174,10 @@ public:
     // set lfe filter params
     void sample_rate(unsigned int srate) {
         // lfe filter is just straight through band limited
-        unsigned int cutoff = (250*N)/srate;
+        unsigned int cutoff = (30*N)/srate;
         for (unsigned f=0;f<=halfN;f++) {           
-            if ((f>=2) && (f<cutoff))
-                filter[5][f] = 1.0;
+            if (f<cutoff)
+                filter[5][f] = 0.5*sqrt(0.5);
             else
                 filter[5][f] = 0.0;
         }
@@ -214,12 +196,6 @@ public:
         E = (o+v)*n; F = (o+u)*n; G = (o-v)*n;  H = (o-u)*n;
     }
 
-    void surround_gain(float gain) {
-        master_gain = gain * window_gain * 0.5 * 0.25;
-        for (unsigned k=0;k<N;k++)
-            wnd[k] = sqrt(master_gain*(1-cos(2*PI*k/N))/N);
-    }
-
     // set the phase shifting mode
     void phase_mode(unsigned mode) {
         const float modes[4][2] = {{0,0},{0,PI},{PI,0},{-PI/2,PI/2}};
@@ -290,7 +266,7 @@ private:
 
         // 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++) {           
+        for (unsigned f=0;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]);
@@ -305,41 +281,6 @@ private:
             phaseDiff = abs(phaseDiff);
 
             if (linear_steering) {
-/*              cfloat w = polar(sqrt(ampL*ampL+ampR*ampR), (phaseL+phaseR)/2);
-                cfloat lt = cfloat(dftL[f][0],dftL[f][1])/w, rt = cfloat(dftR[f][0],dftR[f][1])/w;              */
-//              xfs[f] = -(C*(rt-H) - B*E + F*A + G*(D-lt)) / (G*A - C*E).real();
-//              yfs[f] = (rt - (xfs[f]*E+H))/(F+xfs[f]*G);
-
-                /*
-                Problem: 
-                This assumes that the values are interpolated linearly between the cardinal points.
-                But this way we have no chance of knowing the average volume...
-                - Can we solve that computing everything under the assumption of normalized volume?
-                  No. Seemingly not.
-                - Maybe we should add w explitcitly into the equation and see if we can solve it...
-                */
-
-
-                //cfloat lt(0.5,0),rt(0.5,0);
-                //cfloat x(0,0), y(1,0);
-                /*cfloat p = (C*(rt-H) - B*E + F*A + G*(D-lt)) / (G*A - C*E);
-                cfloat q = B*(rt+H) + F*(D-lt) / (G*A - C*E);
-                cfloat s = sqrt(p*p/4.0f - q);
-                cfloat x = -p;
-                cfloat x1 = -p/2.0f + s;
-                cfloat x2 = -p/2.0f - s;
-                float x = 0;
-                if (x1.real() >= -1 && x1.real() <= 1)
-                    x = x1.real();
-                else if (x2.real() >= -1 && x2.real() <= 1)
-                    x = x2.real();*/
-
-                //cfloat yp = (rt - (x*E+H))/(F+x*G);
-                //cfloat xp = (lt - (y*B+D))/(A+y*C);
-
-                /*xfs[f] = x;
-                yfs[f] = y.real();*/
-
                 // --- this is the fancy new linear mode ---
 
                 // get sound field x/y position
@@ -597,7 +538,6 @@ private:
     float surround_high,surround_low;  // high and low surround mixing coefficient (e.g. 0.8165/0.5774)
     float surround_balance;            // the xfs balance that follows from the coeffs
     float surround_level;              // gain for the surround channels (follows from the coeffs
-    float master_gain;                 // gain for all channels
     float phase_offsetL, phase_offsetR;// phase shifts to be applied to the rear channels
     float front_separation;            // front stereo separation
     float rear_separation;             // rear stereo separation
@@ -625,8 +565,6 @@ void fsurround_decoder::flush() { impl->flush(); }
 
 void fsurround_decoder::surround_coefficients(float a, float b) { impl->surround_coefficients(a,b); }
 
-void fsurround_decoder::gain(float gain) { impl->surround_gain(gain); }
-
 void fsurround_decoder::phase_mode(unsigned mode) { impl->phase_mode(mode); }
 
 void fsurround_decoder::steering_mode(bool mode) { impl->steering_mode(mode); }
diff --git a/mythtv/libs/libmythfreesurround/el_processor.h b/mythtv/libs/libmythfreesurround/el_processor.h
index 021786a..26452f6 100644
--- a/mythtv/libs/libmythfreesurround/el_processor.h
+++ b/mythtv/libs/libmythfreesurround/el_processor.h
@@ -47,9 +47,6 @@ public:
 	//  a is the coefficient of left rear in left total, b is the coefficient of left rear in right total; the same is true for right.
 	void surround_coefficients(float a, float b);
 
-	// override for master surround gain
-	void gain(float gain);
-
 	// set the phase shifting mode for decoding
 	// 0 = (+0°,+0°)   - music mode
 	// 1 = (+0°,+180°) - PowerDVD compatibility
diff --git a/mythtv/libs/libmythfreesurround/freesurround.cpp b/mythtv/libs/libmythfreesurround/freesurround.cpp
index fc7ed8f..bf93d28 100644
--- a/mythtv/libs/libmythfreesurround/freesurround.cpp
+++ b/mythtv/libs/libmythfreesurround/freesurround.cpp
@@ -63,10 +63,9 @@ using namespace std;
 const unsigned default_block_size = 8192;
 // there will be a slider for this in the future
 //const float master_gain = 1.0;
-//#define MASTER_GAIN * master_gain
+//#define MASTER_GAIN * master_gain 
 #define MASTER_GAIN
-//const float master_gain = 1.0/(1<<15);
-//const float inv_master_gain = (1<<15);
+//const float inv_master_gain = 1.0;
 //#define INV_MASTER_GAIN * inv_master_gain
 #define INV_MASTER_GAIN
 
@@ -192,15 +191,13 @@ FreeSurround::FreeSurround(uint srate, bool moviemode, SurroundMode smode) :
     if (moviemode)
     {
         params.phasemode = 1;
-        params.center_width = 0;
-        params.gain = 1.0;
+        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;
+        params.center_width = 65;
+        params.dimension = 0.3;
     }
     switch (surround_mode)
     {
@@ -236,7 +233,6 @@ void FreeSurround::SetParams()
         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);
     }
 }
 
@@ -250,8 +246,7 @@ FreeSurround::fsurround_params::fsurround_params(
     phasemode(0),
     steering(1),
     front_sep(100),
-    rear_sep(100), 
-    gain(1.0)
+    rear_sep(100) 
 {
 }
 
@@ -655,16 +650,6 @@ void FreeSurround::process_block()
     {
         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);
         }
     }
diff --git a/mythtv/libs/libmythsamplerate/samplerate.c b/mythtv/libs/libmythsamplerate/samplerate.c
index adaccf0..a53a942 100644
--- a/mythtv/libs/libmythsamplerate/samplerate.c
+++ b/mythtv/libs/libmythsamplerate/samplerate.c
@@ -452,11 +452,11 @@ src_float_to_short_array (const float *in, short *out, int len)
 	{	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 --git a/mythtv/libs/libmythtv/NuppelVideoPlayer.cpp b/mythtv/libs/libmythtv/NuppelVideoPlayer.cpp
index 7ebedfe..d45c010 100644
--- a/mythtv/libs/libmythtv/NuppelVideoPlayer.cpp
+++ b/mythtv/libs/libmythtv/NuppelVideoPlayer.cpp
@@ -218,9 +218,9 @@ NuppelVideoPlayer::NuppelVideoPlayer()
       audioOutput(NULL),
       audio_main_device(QString::null),
       audio_passthru_device(QString::null),
-      audio_channels(2),            audio_bits(-1),
-      audio_samplerate(44100),      audio_stretchfactor(1.0f),
-      audio_codec(NULL),
+      audio_channels(2),            audio_codec(0),
+      audio_bits(-1),               audio_samplerate(44100),
+      audio_stretchfactor(1.0f),
       // Picture-in-Picture stuff
       pip_active(false),            pip_visible(true),
       // Preview window support
@@ -899,8 +899,8 @@ QString NuppelVideoPlayer::ReinitAudio(void)
         bool setVolume = gContext->GetNumSetting("MythControlsVolume", 1);
         audioOutput = AudioOutput::OpenAudio(audio_main_device,
                                              audio_passthru_device,
-                                             audio_bits, audio_channels,
-                                             audio_samplerate,
+                                             audio_bits, audio_channels, 
+                                             audio_codec, audio_samplerate,
                                              AUDIOOUTPUT_VIDEO,
                                              setVolume, audio_passthru);
         if (!audioOutput)
@@ -928,10 +928,11 @@ QString NuppelVideoPlayer::ReinitAudio(void)
 
     if (audioOutput)
     {
-        const AudioSettings settings(
-            audio_bits, audio_channels, audio_samplerate,
-            audio_passthru, audio_codec);
+        const AudioSettings settings(audio_bits, audio_channels, audio_codec,
+                                     audio_samplerate, audio_passthru);
         audioOutput->Reconfigure(settings);
+        if (audio_passthru)
+            audio_channels = 2;
         errMsg = audioOutput->GetError();
         if (!errMsg.isEmpty())
             audioOutput->SetStretchFactor(audio_stretchfactor);
@@ -3862,20 +3863,16 @@ bool NuppelVideoPlayer::StartPlaying(bool openfile)
     return !IsErrored();
 }
 
-void NuppelVideoPlayer::SetAudioParams(int bps, int channels,
+void NuppelVideoPlayer::SetAudioParams(int bps, int channels, int codec,
                                        int samplerate, bool passthru)
 {
     audio_bits = bps;
     audio_channels = channels;
+    audio_codec = codec;
     audio_samplerate = samplerate;
     audio_passthru = passthru;
 }
 
-void NuppelVideoPlayer::SetAudioCodec(void *ac)
-{
-    audio_codec = ac;
-}
-
 void NuppelVideoPlayer::SetEffDsp(int dsprate)
 {
     if (audioOutput)
@@ -5294,6 +5291,13 @@ void NuppelVideoPlayer::ToggleAdjustFill(AdjustFillMode adjustfillMode)
     }
 }
 
+bool NuppelVideoPlayer::ToggleUpmix()
+{
+    if (audioOutput)
+        return audioOutput->ToggleUpmix();
+    return false;
+}
+
 void NuppelVideoPlayer::Zoom(ZoomDirection direction)
 {
     if (videoOutput)
diff --git a/mythtv/libs/libmythtv/NuppelVideoPlayer.h b/mythtv/libs/libmythtv/NuppelVideoPlayer.h
index 2ceb683..06743d4 100644
--- a/mythtv/libs/libmythtv/NuppelVideoPlayer.h
+++ b/mythtv/libs/libmythtv/NuppelVideoPlayer.h
@@ -125,7 +125,8 @@ class MPUBLIC NuppelVideoPlayer : public CC608Reader, public CC708Reader
     void SetAudioStretchFactor(float factor)  { audio_stretchfactor = factor; }
     void SetAudioOutput(AudioOutput *ao)      { audioOutput = ao; }
     void SetAudioInfo(const QString &main, const QString &passthru, uint rate);
-    void SetAudioParams(int bits, int channels, int samplerate, bool passthru);
+    void SetAudioParams(int bits, int channels, int codec, int samplerate, 
+                        bool passthru);
     void SetEffDsp(int dsprate);
     uint AdjustVolume(int change);
     bool SetMuted(bool mute);
@@ -179,6 +180,7 @@ class MPUBLIC NuppelVideoPlayer : public CC608Reader, public CC708Reader
     // 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; }
@@ -711,10 +713,10 @@ class MPUBLIC NuppelVideoPlayer : public CC608Reader, public CC708Reader
     QString  audio_main_device;
     QString  audio_passthru_device;
     int      audio_channels;
+    int      audio_codec;
     int      audio_bits;
     int      audio_samplerate;
     float    audio_stretchfactor;
-    void    *audio_codec;
     bool     audio_passthru;
 
     // Picture-in-Picture
diff --git a/mythtv/libs/libmythtv/avformatdecoder.cpp b/mythtv/libs/libmythtv/avformatdecoder.cpp
index bbc68e3..4530bc4 100644
--- a/mythtv/libs/libmythtv/avformatdecoder.cpp
+++ b/mythtv/libs/libmythtv/avformatdecoder.cpp
@@ -444,7 +444,7 @@ AvFormatDecoder::AvFormatDecoder(NuppelVideoPlayer *parent,
       audioSamples(NULL),
       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),
@@ -2019,7 +2019,7 @@ int AvFormatDecoder::ScanStreams(bool novideo)
     // waiting on audio.
     if (GetNVP()->HasAudioIn() && tracks[kTrackTypeAudio].empty())
     {
-        GetNVP()->SetAudioParams(-1, -1, -1, false /* AC3/DTS pass-through */);
+        GetNVP()->SetAudioParams(-1, -1, CODEC_ID_NONE, -1, false /* AC3/DTS pass-through */);
         GetNVP()->ReinitAudio();
         if (ringBuffer && ringBuffer->isDVD())
             audioIn = AudioInfo();
@@ -3054,15 +3054,9 @@ int AvFormatDecoder::AutoSelectAudioTrack(void)
     {
         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
@@ -3196,6 +3190,7 @@ static void extract_mono_channel(uint channel, AudioInfo *audioInfo,
 bool AvFormatDecoder::GetFrame(int onlyvideo)
 {
     AVPacket *pkt = NULL;
+    AC3HeaderInfo hdr;
     int len;
     unsigned char *ptr;
     int data_size = 0;
@@ -3392,12 +3387,13 @@ bool AvFormatDecoder::GetFrame(int onlyvideo)
         pts = 0;
 
         AVStream *curstream = ic->streams[pkt->stream_index];
+        AVCodecContext *ctx = curstream->codec;
 
         if (pkt->dts != (int64_t)AV_NOPTS_VALUE)
             pts = (long long)(av_q2d(curstream->time_base) * pkt->dts * 1000);
 
-        if (ringBuffer->isDVD() &&
-            curstream->codec->codec_type == CODEC_TYPE_VIDEO)
+        if (ringBuffer->isDVD() && 
+            ctx->codec_type == CODEC_TYPE_VIDEO)
         {
             MpegPreProcessPkt(curstream, pkt);
 
@@ -3419,7 +3415,7 @@ bool AvFormatDecoder::GetFrame(int onlyvideo)
 
             if (!d->HasMPEG2Dec())
             {
-                int current_width = curstream->codec->width;
+                int current_width = ctx->width;
                 int video_width = GetNVP()->GetVideoSize().width();
                 if (dvd_xvmc_enabled && GetNVP() && GetNVP()->getVideoOutput())
                 {
@@ -3460,7 +3456,7 @@ bool AvFormatDecoder::GetFrame(int onlyvideo)
         }
 
         if (storevideoframes &&
-            curstream->codec->codec_type == CODEC_TYPE_VIDEO)
+            ctx->codec_type == CODEC_TYPE_VIDEO)
         {
             av_dup_packet(pkt);
             storedPackets.append(pkt);
@@ -3468,20 +3464,19 @@ bool AvFormatDecoder::GetFrame(int onlyvideo)
             continue;
         }
 
-        if (len > 0 && curstream->codec->codec_type == CODEC_TYPE_VIDEO &&
+        if (len > 0 && ctx->codec_type == CODEC_TYPE_VIDEO &&
             pkt->stream_index == selectedVideoIndex)
         {
-            AVCodecContext *context = curstream->codec;
 
-            if (context->codec_id == CODEC_ID_MPEG1VIDEO ||
-                context->codec_id == CODEC_ID_MPEG2VIDEO ||
-                context->codec_id == CODEC_ID_MPEG2VIDEO_XVMC ||
-                context->codec_id == CODEC_ID_MPEG2VIDEO_XVMC_VLD)
+            if (ctx->codec_id == CODEC_ID_MPEG1VIDEO ||
+                ctx->codec_id == CODEC_ID_MPEG2VIDEO ||
+                ctx->codec_id == CODEC_ID_MPEG2VIDEO_XVMC ||
+                ctx->codec_id == CODEC_ID_MPEG2VIDEO_XVMC_VLD)
             {
                 if (!ringBuffer->isDVD())
                     MpegPreProcessPkt(curstream, pkt);
             }
-            else if (context->codec_id == CODEC_ID_H264)
+            else if (ctx->codec_id == CODEC_ID_H264)
             {
                 H264PreProcessPkt(curstream, pkt);
             }
@@ -3526,8 +3521,8 @@ bool AvFormatDecoder::GetFrame(int onlyvideo)
         }
 
         if (len > 0 &&
-            curstream->codec->codec_type == CODEC_TYPE_DATA &&
-            curstream->codec->codec_id   == CODEC_ID_MPEG2VBI)
+            ctx->codec_type == CODEC_TYPE_DATA &&
+            ctx->codec_id   == CODEC_ID_MPEG2VBI)
         {
             ProcessVBIDataPacket(curstream, pkt);
 
@@ -3536,8 +3531,8 @@ bool AvFormatDecoder::GetFrame(int onlyvideo)
         }
 
         if (len > 0 &&
-            curstream->codec->codec_type == CODEC_TYPE_DATA &&
-            curstream->codec->codec_id   == CODEC_ID_DVB_VBI)
+            ctx->codec_type == CODEC_TYPE_DATA &&
+            ctx->codec_id   == CODEC_ID_DVB_VBI)
         {
             ProcessDVBDataPacket(curstream, pkt);
 
@@ -3547,8 +3542,8 @@ bool AvFormatDecoder::GetFrame(int onlyvideo)
 
 #ifdef USING_MHEG
         if (len > 0 &&
-            curstream->codec->codec_type == CODEC_TYPE_DATA &&
-            curstream->codec->codec_id   == CODEC_ID_DSMCC_B)
+            ctx->codec_type == CODEC_TYPE_DATA &&
+            ctx->codec_id   == CODEC_ID_DSMCC_B)
         {
             ProcessDSMCCPacket(curstream, pkt);
 
@@ -3569,20 +3564,20 @@ bool AvFormatDecoder::GetFrame(int onlyvideo)
 #endif // USING_MHEG
 
         // we don't care about other data streams
-        if (curstream->codec->codec_type == CODEC_TYPE_DATA)
+        if (ctx->codec_type == CODEC_TYPE_DATA)
         {
             av_free_packet(pkt);
             continue;
         }
 
-        if (!curstream->codec->codec)
+        if (!ctx->codec)
         {
             VERBOSE(VB_PLAYBACK, LOC +
                     QString("No codec for stream index %1, type(%2) id(%3:%4)")
                     .arg(pkt->stream_index)
-                    .arg(codec_type_string(curstream->codec->codec_type))
-                    .arg(codec_id_string(curstream->codec->codec_id))
-                    .arg(curstream->codec->codec_id));
+                    .arg(codec_type_string(ctx->codec_type))
+                    .arg(codec_id_string(ctx->codec_id))
+                    .arg(ctx->codec_id));
             av_free_packet(pkt);
             continue;
         }
@@ -3591,7 +3586,7 @@ bool AvFormatDecoder::GetFrame(int onlyvideo)
         have_err = false;
 
         avcodeclock.lock();
-        int ctype  = curstream->codec->codec_type;
+        int ctype  = ctx->codec_type;
         int audIdx = selectedTrack[kTrackTypeAudio].av_stream_index;
         int audSubIdx = selectedTrack[kTrackTypeAudio].av_substream_index;
         int subIdx = selectedTrack[kTrackTypeSubtitle].av_stream_index;
@@ -3616,51 +3611,57 @@ bool AvFormatDecoder::GetFrame(int onlyvideo)
 
                     // detect switches between stereo and dual languages
                     bool wasDual = audSubIdx != -1;
-                    bool isDual = curstream->codec->avcodec_dual_language;
+                    bool isDual = ctx->avcodec_dual_language;
                     if ((wasDual && !isDual) || (!wasDual &&  isDual))
                     {
                         SetupAudioStreamSubIndexes(audIdx);
                         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;
-                    if (!curstream->codec->channels)
+                    if (!ctx->channels)
                     {
                         QMutexLocker locker(&avcodeclock);
                         VERBOSE(VB_IMPORTANT, LOC +
                                 QString("Setting channels to %1")
                                 .arg(audioOut.channels));
 
-                        if (using_passthru)
+                        if (DoPassThrough(ctx))
                         {
                             // for passthru let it select the max number
                             // of channels
-                            curstream->codec->channels = 0;
-                            curstream->codec->request_channels = 0;
+                            ctx->channels = 0;
+                            ctx->request_channels = 0;
                         }
                         else
                         {
-                            curstream->codec->channels = audioOut.channels;
-                            curstream->codec->request_channels =
+                            ctx->channels = audioOut.channels;
+                            ctx->request_channels =
                                 audioOut.channels;
                         }
+                        
                         data_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
-                        ret = avcodec_decode_audio2(curstream->codec,
-                                                    audioSamples, &data_size,
-                                                    ptr, len);
+                        ret = avcodec_decode_audio2(ctx, audioSamples,
+                                                   &data_size, ptr, len);
                         already_decoded = true;
 
-                        reselectAudioTrack |= curstream->codec->channels;
+                        reselectAudioTrack |= ctx->channels;
+                    }
+
+                    if (ctx->codec_id == CODEC_ID_AC3)
+                    {
+                        GetBitContext gbc;
+                        init_get_bits(&gbc, ptr, len * 8);
+                        if (!ff_ac3_parse_header(&gbc, &hdr)) 
+                        {
+                            if (hdr.channels != last_ac3_channels) 
+                            {
+                                last_ac3_channels = ctx->channels = hdr.channels;
+                                SetupAudioStream();
+                            }
+                        }
                     }
 
                     if (reselectAudioTrack)
@@ -3676,6 +3677,7 @@ bool AvFormatDecoder::GetFrame(int onlyvideo)
                             .av_stream_index;
                         audSubIdx = selectedTrack[kTrackTypeAudio]
                             .av_substream_index;
+                        ctx = curstream->codec;
                     }
 
                     if ((onlyvideo > 0) || (pkt->stream_index != audIdx))
@@ -3707,14 +3709,12 @@ bool AvFormatDecoder::GetFrame(int onlyvideo)
                     if (audioOut.do_passthru)
                     {
                         data_size = pkt->size;
-                        bool dts = CODEC_ID_DTS == curstream->codec->codec_id;
+                        bool dts = CODEC_ID_DTS == ctx->codec_id;
                         ret = encode_frame(dts, ptr, len,
                                            audioSamples, data_size);
                     }
                     else
                     {
-                        AVCodecContext *ctx = curstream->codec;
-
                         if ((ctx->channels == 0) ||
                             (ctx->channels > audioOut.channels))
                         {
@@ -3723,10 +3723,9 @@ bool AvFormatDecoder::GetFrame(int onlyvideo)
 
                         if (!already_decoded)
                         {
-                            curstream->codec->request_channels =
-                                audioOut.channels;
                             data_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
-                            ret = avcodec_decode_audio2(ctx, audioSamples,
+                            ctx->request_channels = audioOut.channels;
+                            ret = avcodec_decode_audio2(ctx, audioSamples, 
                                                         &data_size, ptr, len);
                         }
 
@@ -3742,6 +3741,7 @@ bool AvFormatDecoder::GetFrame(int onlyvideo)
                             audIdx = -1;
                             AutoSelectAudioTrack();
                             data_size = 0;
+                            ctx = curstream->codec;
                         }
                     }
                     avcodeclock.unlock();
@@ -3759,8 +3759,7 @@ bool AvFormatDecoder::GetFrame(int onlyvideo)
 
                     // calc for next frame
                     lastapts += (long long)((double)(data_size * 1000) /
-                                (curstream->codec->channels * 2) /
-                                curstream->codec->sample_rate);
+                                (ctx->channels * 2) / ctx->sample_rate);
 
                     VERBOSE(VB_PLAYBACK+VB_TIMESTAMP,
                             LOC + QString("audio timecode %1 %2 %3 %4")
@@ -3828,7 +3827,6 @@ bool AvFormatDecoder::GetFrame(int onlyvideo)
                         continue;
                     }
 
-                    AVCodecContext *context = curstream->codec;
                     AVFrame mpa_pic;
                     bzero(&mpa_pic, sizeof(AVFrame));
 
@@ -3843,24 +3841,24 @@ bool AvFormatDecoder::GetFrame(int onlyvideo)
                             // HACK
                             while (!gotpicture && count < 5)
                             {
-                                ret = d->DecodeMPEG2Video(context, &mpa_pic,
+                                ret = d->DecodeMPEG2Video(ctx, &mpa_pic,
                                                   &gotpicture, ptr, len);
                                 count++;
                             }
                         }
                         else
                         {
-                            ret = d->DecodeMPEG2Video(context, &mpa_pic,
+                            ret = d->DecodeMPEG2Video(ctx, &mpa_pic,
                                                 &gotpicture, ptr, len);
                         }
                     }
                     else
                     {
-                        ret = avcodec_decode_video(context, &mpa_pic,
+                        ret = avcodec_decode_video(ctx, &mpa_pic,
                                                    &gotpicture, ptr, len);
                         // Reparse it to not drop the DVD still frame
                         if (decodeStillFrame)
-                            ret = avcodec_decode_video(context, &mpa_pic,
+                            ret = avcodec_decode_video(ctx, &mpa_pic,
                                                         &gotpicture, ptr, len);
                     }
                     avcodeclock.unlock();
@@ -3928,9 +3926,9 @@ bool AvFormatDecoder::GetFrame(int onlyvideo)
                         myth_sws_img_convert(
                             &tmppicture, PIX_FMT_YUV420P,
                                     (AVPicture *)&mpa_pic,
-                                    context->pix_fmt,
-                                    context->width,
-                                    context->height);
+                                    ctx->pix_fmt,
+                                    ctx->width,
+                                    ctx->height);
 
                         if (xf)
                         {
@@ -3953,10 +3951,10 @@ bool AvFormatDecoder::GetFrame(int onlyvideo)
                         (temppts + 10000 > lastvpts || temppts < 0))
                     {
                         temppts = lastvpts;
-                        temppts += (long long)(1000 * av_q2d(context->time_base));
+                        temppts += (long long)(1000 * av_q2d(ctx->time_base));
                         // MPEG2 frames can be repeated, update pts accordingly
                         temppts += (long long)(mpa_pic.repeat_pict * 500
-                                      * av_q2d(curstream->codec->time_base));
+                                      * av_q2d(ctx->time_base));
                     }
 
                     VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, LOC +
@@ -3992,7 +3990,7 @@ bool AvFormatDecoder::GetFrame(int onlyvideo)
                     picframe->frameNumber = framesPlayed;
                     GetNVP()->ReleaseNextVideoFrame(picframe, temppts);
                     if (d->HasMPEG2Dec() && mpa_pic.data[3])
-                        context->release_buffer(context, &mpa_pic);
+                        ctx->release_buffer(ctx, &mpa_pic);
 
                     decoded_video_frame = picframe;
                     gotvideo = 1;
@@ -4048,11 +4046,10 @@ bool AvFormatDecoder::GetFrame(int onlyvideo)
                 }
                 default:
                 {
-                    AVCodecContext *enc = curstream->codec;
                     VERBOSE(VB_IMPORTANT, LOC_ERR +
                             QString("Decoding - id(%1) type(%2)")
-                            .arg(codec_id_string(enc->codec_id))
-                            .arg(codec_type_string(enc->codec_type)));
+                            .arg(codec_id_string(ctx->codec_id))
+                            .arg(codec_type_string(ctx->codec_type)));
                     have_err = true;
                     break;
                 }
@@ -4201,6 +4198,24 @@ void AvFormatDecoder::SetDisablePassThrough(bool disable)
     }
 }
 
+bool AvFormatDecoder::DoPassThrough(const AVCodecContext *ctx)
+{
+    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.
  *
@@ -4214,7 +4229,6 @@ bool AvFormatDecoder::SetupAudioStream(void)
     AVStream *curstream = NULL;
     AVCodecContext *codec_ctx = NULL;
     AudioInfo old_in  = audioIn;
-    AudioInfo old_out = audioOut;
     bool using_passthru = false;
 
     if ((currentTrack[kTrackTypeAudio] >= 0) &&
@@ -4228,14 +4242,9 @@ bool AvFormatDecoder::SetupAudioStream(void)
         codec_ctx = curstream->codec;
         if (codec_ctx)
         {
-            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);
+            info = AudioInfo(codec_ctx->codec_id, codec_ctx->sample_rate, 
+                            codec_ctx->channels, using_passthru);
         }
     }
 
@@ -4252,41 +4261,25 @@ bool AvFormatDecoder::SetupAudioStream(void)
             QString("audio track #%1").arg(currentTrack[kTrackTypeAudio]+1));
 
     audioOut = audioIn = info;
-    AudioInfo tmpAudioOut = audioOut;
 
-    // A passthru stream looks like a 48KHz 2ch (@ 16bit) to the sound card
-    if (using_passthru && !disable_passthru)
+    if (!using_passthru && audioOut.channels > (int)max_channels)
     {
-        tmpAudioOut.channels    = 2;
-        tmpAudioOut.sample_rate = 48000;
-        tmpAudioOut.sample_size = 4;
-    }
-
-    if (audioOut.channels > (int) max_channels)
-    {
-        audioOut.channels    = (int) max_channels;
+        audioOut.channels = (int)max_channels;
         audioOut.sample_size = audioOut.channels * 2;
-        codec_ctx->channels  = audioOut.channels;
+        codec_ctx->channels = audioOut.channels;
     }
 
-    if (!using_passthru)
-        tmpAudioOut = audioOut;
-
     VERBOSE(VB_AUDIO, LOC + "Audio format changed " +
-            QString("%1%2\n\t\t\tfrom %3 ; %4\n\t\t\tto   %5 ; %6")
-            .arg((using_passthru) ? "digital passthrough " : "")
-            .arg((using_passthru) ? tmpAudioOut.toString() : QString(""))
-            .arg(old_in.toString()).arg(old_out.toString())
-            .arg(audioIn.toString()).arg(audioOut.toString()));
+            QString("\n\t\t\tfrom %1 to %2")
+            .arg(old_in.toString()).arg(audioOut.toString()));
 
-    if (tmpAudioOut.sample_rate > 0)
-        GetNVP()->SetEffDsp(tmpAudioOut.sample_rate * 100);
+    if (audioOut.sample_rate > 0)
+        GetNVP()->SetEffDsp(audioOut.sample_rate * 100);
 
-    GetNVP()->SetAudioParams(tmpAudioOut.bps(), tmpAudioOut.channels,
-                             tmpAudioOut.sample_rate, audioIn.do_passthru);
+    GetNVP()->SetAudioParams(audioOut.bps(), audioOut.channels, 
+                             audioOut.codec_id, audioOut.sample_rate, 
+                             audioOut.do_passthru);
 
-    // allow the audio stuff to reencode
-    GetNVP()->SetAudioCodec((using_passthru) ? codec_ctx : NULL);
     GetNVP()->ReinitAudio();
 
     return true;
diff --git a/mythtv/libs/libmythtv/avformatdecoder.h b/mythtv/libs/libmythtv/avformatdecoder.h
index 9ead273..ea1fb23 100644
--- a/mythtv/libs/libmythtv/avformatdecoder.h
+++ b/mythtv/libs/libmythtv/avformatdecoder.h
@@ -198,6 +198,7 @@ class AvFormatDecoder : public DecoderBase
 
     void SeekReset(long long, uint skipFrames, bool doFlush, bool discardFrames);
 
+    bool DoPassThrough(const AVCodecContext *ctx);
     bool SetupAudioStream(void);
     void SetupAudioStreamSubIndexes(int streamIndex);
     void RemoveAudioStreams();
@@ -270,6 +271,7 @@ class AvFormatDecoder : public DecoderBase
     bool              allow_dts_passthru;
     bool              disable_passthru;
     uint              max_channels;
+    uint              last_ac3_channels;
 
     VideoFrame       *dummy_frame;
 
diff --git a/mythtv/libs/libmythtv/nuppeldecoder.cpp b/mythtv/libs/libmythtv/nuppeldecoder.cpp
index 88d2fbb..010a458 100644
--- a/mythtv/libs/libmythtv/nuppeldecoder.cpp
+++ b/mythtv/libs/libmythtv/nuppeldecoder.cpp
@@ -495,6 +495,7 @@ int NuppelDecoder::OpenFile(RingBuffer *rbuffer, bool novideo,
 #endif
         GetNVP()->SetAudioParams(extradata.audio_bits_per_sample,
                                  extradata.audio_channels, 
+                                 CODEC_ID_NONE,
                                  extradata.audio_sample_rate,
                                  false /* AC3/DTS pass through */);
         GetNVP()->ReinitAudio();
diff --git a/mythtv/libs/libmythtv/tv_play.cpp b/mythtv/libs/libmythtv/tv_play.cpp
index babe363..99e62a0 100644
--- a/mythtv/libs/libmythtv/tv_play.cpp
+++ b/mythtv/libs/libmythtv/tv_play.cpp
@@ -491,6 +491,7 @@ void TV::InitKeys(void)
     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 view",
             "V");
     REG_KEY("TV Playback", "TOGGLEPBPMODE", "Toggle Picture-by-Picture view",
@@ -630,7 +631,7 @@ void TV::InitKeys(void)
   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
 */
 }
 
@@ -4345,6 +4346,8 @@ bool TV::ToggleHandleAction(PlayerContext *ctx,
         DoTogglePictureAttribute(ctx, kAdjustingPicture_Playback);
     else if (has_action("TOGGLESTRETCH", actions))
         ToggleTimeStretch(ctx);
+    else if (has_action("TOGGLEUPMIX", actions))
+        ToggleUpmix(ctx);
     else if (has_action("TOGGLESLEEP", actions))
         ToggleSleepTimer(ctx);
     else if (has_action("TOGGLERECORD", actions) && islivetv)
@@ -8010,6 +8013,20 @@ void TV::ChangeTimeStretch(PlayerContext *ctx, int dir, bool allowEdit)
     SetSpeedChangeTimer(0, __LINE__);
 }
 
+void TV::ToggleUpmix(PlayerContext *ctx)
+{
+    if (!ctx->nvp || !ctx->nvp->HasAudioOut())
+        return;
+    QString text;
+    if (ctx->nvp->ToggleUpmix())
+        text = tr("Upmixer On");
+    else
+        text = tr("Upmixer Off");
+    
+    if (ctx->nvp->GetOSD() && !browsemode)
+        ctx->nvp->GetOSD()->SetSettingsText(text, 5);
+}
+    
 // dir in 10ms jumps
 void TV::ChangeAudioSync(PlayerContext *ctx, int dir, bool allowEdit)
 {
@@ -9642,6 +9659,8 @@ void TV::TreeMenuSelected(OSDListTreeItemSelectedEvent *e)
         SetManualZoom(actx, true, tr("Zoom Mode ON"));
     else if (action == "TOGGLESTRETCH")
         ToggleTimeStretch(actx);
+    else if (action == "TOGGLEUPMIX")
+        ToggleUpmix(actx);
     else if (action.left(13) == "ADJUSTSTRETCH")
     {
         bool floatRead;
@@ -9995,6 +10014,8 @@ void TV::FillOSDTreeMenu(
 
     if (category == "AUDIOSYNC")
         new OSDGenericTree(treeMenu, tr("Adjust Audio Sync"), "TOGGLEAUDIOSYNC");
+    else if (category == "TOGGLEUPMIX")
+        new OSDGenericTree(treeMenu, tr("Toggle Upmixer"), "TOGGLEUPMIX");
     else if (category == "TIMESTRETCH")
         FillMenuTimeStretch(ctx, treeMenu);
     else if (category == "VIDEOSCAN")
diff --git a/mythtv/libs/libmythtv/tv_play.h b/mythtv/libs/libmythtv/tv_play.h
index b361a7e..f9b93bf 100644
--- a/mythtv/libs/libmythtv/tv_play.h
+++ b/mythtv/libs/libmythtv/tv_play.h
@@ -419,6 +419,7 @@ class MPUBLIC TV : public QThread
         ARBSEEK_FORWARD,
         ARBSEEK_END
     };
+    
     void DoArbSeek(PlayerContext*, ArbSeekWhence whence);
     void NormalSpeed(PlayerContext*);
     void ChangeSpeed(PlayerContext*, int direction);
@@ -427,6 +428,7 @@ class MPUBLIC TV : public QThread
     bool TimeStretchHandleAction(PlayerContext*,
                                  const QStringList &actions);
 
+    void ToggleUpmix(PlayerContext*);
     void ChangeAudioSync(PlayerContext*, int dir, bool allowEdit = true);
     bool AudioSyncHandleAction(PlayerContext*, const QStringList &actions);
 
diff --git a/mythtv/libs/libmythtv/tvosdmenuentry.cpp b/mythtv/libs/libmythtv/tvosdmenuentry.cpp
index 994dcb2..ef714ea 100644
--- a/mythtv/libs/libmythtv/tvosdmenuentry.cpp
+++ b/mythtv/libs/libmythtv/tvosdmenuentry.cpp
@@ -232,6 +232,8 @@ void TVOSDMenuEntryList::InitDefaultEntries(void)
     curMenuEntries.append(
         new TVOSDMenuEntry("AUDIOSYNC",           1, 1, 1, 1 , "Audio Sync"));
     curMenuEntries.append(
+        new TVOSDMenuEntry("TOGGLEUPMIX",        1, 1, 1, 1, "Toggle Upmixer"));
+    curMenuEntries.append(
         new TVOSDMenuEntry("TIMESTRETCH",        1, 1, 1, 1, "Time Stretch"));
     curMenuEntries.append(
         new TVOSDMenuEntry("VIDEOSCAN",            1, 1, 1, 1, "Video Scan"));
diff --git a/mythtv/programs/mythfrontend/globalsettings.cpp b/mythtv/programs/mythfrontend/globalsettings.cpp
index d61cf26..c5d0406 100644
--- a/mythtv/programs/mythfrontend/globalsettings.cpp
+++ b/mythtv/programs/mythfrontend/globalsettings.cpp
@@ -119,6 +119,27 @@ static HostComboBox *AudioUpmixType()
     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->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%. "
+            )
+    );
+    return gc;
+}
+
+
 static HostComboBox *PassThroughOutputDevice()
 {
     HostComboBox *gc = new HostComboBox("PassThruOutputDevice", true);
@@ -3446,6 +3467,7 @@ class AudioSystemSettingsGroup : public VerticalConfigurationGroup
 
         addChild(MaxAudioChannels());
         addChild(AudioUpmixType());
+        addChild(SRCQuality());
 
         // General boolean settings
         addChild(AC3PassThrough());
diff --git a/mythtv/programs/mythtranscode/transcode.cpp b/mythtv/programs/mythtranscode/transcode.cpp
index a69ceb1..9958473 100644
--- a/mythtv/programs/mythtranscode/transcode.cpp
+++ b/mythtv/programs/mythtranscode/transcode.cpp
@@ -49,7 +49,7 @@ class AudioReencodeBuffer : public AudioOutput
     AudioReencodeBuffer(int audio_bits, int audio_channels)
     {
         Reset();
-        const AudioSettings settings(audio_bits, audio_channels, 0, false);
+        const AudioSettings settings(audio_bits, audio_channels, 0, 0, false);
         Reconfigure(settings);
         bufsize = 512000;
         audiobuffer = new unsigned char[bufsize];
@@ -222,6 +222,11 @@ class AudioReencodeBuffer : public AudioOutput
         // Do nothing
         return kMuteOff;
     }
+    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; }
