Index: libs/libmythtv/avformatdecoder.cpp
===================================================================
--- libs/libmythtv/avformatdecoder.cpp	(revision 8035)
+++ libs/libmythtv/avformatdecoder.cpp	(working copy)
@@ -29,6 +29,9 @@
 
 #define MAX_AC3_FRAME_SIZE 6144
 
+static int dts_syncinfo(uint8_t *indata_ptr, int *flags, int *sample_rate, int *bit_rate);
+static int dts_decode_header(uint8_t *indata_ptr, int *rate, int *nblks, int *sfreq);
+
 extern pthread_mutex_t avcodeclock;
 
 int get_avf_buffer_xvmc(struct AVCodecContext *c, AVFrame *pic);
@@ -919,6 +922,12 @@
                             <<") already open, leaving it alone.");
                 }
                 assert(enc->codec_id);
+                if (enc->codec_id == CODEC_ID_DTS)
+                {
+                    enc->sample_rate = 48000;
+                    enc->channels = 2;
+                    // enc->bit_rate = what??;
+                }
                 if (enc->channels > 2)
                     enc->channels = 2;
                 bitrate += enc->bit_rate;
@@ -1760,11 +1769,12 @@
 
 //
 // This function will select the best audio track
-// available usgin the following rules:
+// available using the following rules:
 //
-// 1. The fist AC3 track found will be select,
-// 2. If no AC3 is found then the audio track with
-// the most number of channels is selected. 
+// 1. The first DTS track found will be selected,
+// 2. If no DTS is found then the fist AC3 track will be selected,
+// 3. If no AC3 is found then the audio track with the most number
+//    of channels is selected.
 //
 // This code has no awareness to language preferences
 // although I don't think it would be too hard to 
@@ -1778,32 +1788,37 @@
         return false;
     }
 
-    int minChannels = 1;
     int maxTracks = (audioStreams.size() - 1);
     int track;
-    if (do_ac3_passthru)
-        minChannels = 2;
+    int firstAC3Track = -1;
+    int firstDtsTrack = -1;
 
     int selectedTrack = -1;
-    int selectedChannels = -1;
-    
-    while ((selectedTrack == -1) && (minChannels >= 0))
+    int selectedChannels = 0;
+
+    for (track = 0; track <= maxTracks; track++)
     {
-        for (track = 0; track <= maxTracks; track++)
+        int tempStream = audioStreams[track];
+        AVCodecContext *e = ic->streams[tempStream]->codec;
+
+        switch (e->codec_id)
         {
-            int tempStream = audioStreams[track];
-            AVCodecContext *e = ic->streams[tempStream]->codec;
+            case CODEC_ID_AC3:
+                if(firstAC3Track == -1)
+                {
+                    firstAC3Track = track;
+                }
+                break;
 
-            if (e->channels > minChannels)
-            {
-                //if we find an AC3 codec then we select it 
-                //as the preferred codec.
-                if (e->codec_id == CODEC_ID_AC3)
+            case CODEC_ID_DTS:
+                if(firstDtsTrack == -1)
                 {
-                    selectedTrack = track;
-                    break;
+                    firstDtsTrack = track;
                 }
+                break;
 
+            default:
+
                 if (e->channels > selectedChannels)
                 {
                     // this is a candidate with more channels
@@ -1812,12 +1827,19 @@
                     selectedChannels = e->channels;
                     selectedTrack = track;
                 }
-            }
         }
-        if (selectedTrack == -1)
+    }
+
+    if (!transcoding)
+    {
+        if (firstDtsTrack >= 0 && gContext->GetNumSetting("DTSPassThru", false))
         {
-            minChannels--;
+            selectedTrack = firstDtsTrack;
         }
+        else if(firstAC3Track >= 0 && gContext->GetNumSetting("AC3PassThru", false))
+        {
+            selectedTrack = firstAC3Track;
+        }
     }
 
     if (selectedTrack == -1)
@@ -1830,20 +1852,27 @@
     wantedAudioStream = audioStreams[currentAudioTrack];
      
     AVCodecContext *e = ic->streams[wantedAudioStream]->codec;
-    if (e->codec_id == CODEC_ID_AC3)
+    switch (e->codec_id)
     {
-        VERBOSE(VB_AUDIO, LOC +
-                QString("Auto-selecting AC3 audio track (stream #%2).")
-                .arg(wantedAudioStream)); 
+        case CODEC_ID_AC3:
+            VERBOSE(VB_AUDIO, LOC +
+                    QString("Auto-selecting AC3 audio track (stream #%2).")
+                    .arg(wantedAudioStream));
+            break;
+
+        case CODEC_ID_DTS:
+            VERBOSE(VB_AUDIO, LOC +
+                    QString("Auto-selecting DTS audio track (stream #%2).")
+                    .arg(wantedAudioStream));
+            break;
+
+        default:
+            VERBOSE(VB_AUDIO, LOC +
+                    QString("Auto-selecting audio track #%1 (stream #%2).")
+                    .arg(selectedTrack + 1).arg(wantedAudioStream) + "\n\t\t\t" +
+                    QString("It has %1 channels and we needed at least 1")
+                    .arg(selectedChannels));
     }
-    else
-    {
-        VERBOSE(VB_AUDIO, LOC +
-                QString("Auto-selecting audio track #%1 (stream #%2).")
-                .arg(selectedTrack + 1).arg(wantedAudioStream) + "\n\t\t\t" +
-                QString("It has %1 channels and we needed at least %2")
-                .arg(selectedChannels).arg(do_ac3_passthru ? 2 : 1));
-    }
     SetupAudioStream();
     CheckAudioParams(e->sample_rate, e->channels, true);
     return true;
@@ -1863,9 +1892,11 @@
 
     GetNVP()->SetEffDsp(curstream->codec->sample_rate * 100);
 
-    do_ac3_passthru = curstream->codec->codec_id == CODEC_ID_AC3 &&
-                      !transcoding &&
-                      gContext->GetNumSetting("AC3PassThru", false);
+    do_ac3_passthru = !transcoding &&
+                      (curstream->codec->codec_id == CODEC_ID_AC3 &&
+                       gContext->GetNumSetting("AC3PassThru", false) ||
+                       curstream->codec->codec_id == CODEC_ID_DTS &&
+                       gContext->GetNumSetting("DTSPassThru", false));
 }
 
 
@@ -2198,11 +2229,13 @@
                     }
                     pthread_mutex_unlock(&avcodeclock);
 
-                    ptr += ret;
-                    len -= ret;
 
                     if (data_size <= 0)
+                    {
+                        ptr += ret;
+                        len -= ret;
                         continue;
+                    }
 
                     if (!do_ac3_passthru)
                         CheckAudioParams(curstream->codec->sample_rate,
@@ -2385,6 +2418,8 @@
 {
     int enc_len;
     int flags, sample_rate, bit_rate;
+    int nr_samples = 0, block_len;
+    bool dts = false;
     unsigned char* ucsamples = (unsigned char*) samples;
 
     // we don't do any length/crc validation of the AC3 frame here; presumably
@@ -2395,7 +2430,20 @@
     // ignore, and if so, may as well just assume that it will ignore
     // anything with a bad CRC...
 
-    enc_len = a52_syncinfo(data, &flags, &sample_rate, &bit_rate);
+    enc_len = dts_syncinfo(data, &flags, &sample_rate, &bit_rate);
+    if(enc_len >= 10)
+    {
+        dts = true;
+        int rate, sfreq, nblks;
+        dts_decode_header(data, &rate, &nblks, &sfreq);
+        nr_samples = nblks * 32;
+        block_len = nr_samples * 2 * 2;
+    }
+    else
+    {
+        enc_len = a52_syncinfo(data, &flags, &sample_rate, &bit_rate);
+        block_len = MAX_AC3_FRAME_SIZE;
+    }
 
     if (enc_len == 0 || enc_len > len)
     {
@@ -2403,25 +2451,54 @@
         return len;
     }
 
-    if (enc_len > MAX_AC3_FRAME_SIZE - 8)
-        enc_len = MAX_AC3_FRAME_SIZE - 8;
+    if (enc_len > block_len - 8)
+    {
+        enc_len = block_len - 8;
+    }
 
     swab(data, ucsamples + 8, enc_len);
 
-    // the following values come from ao_hwac3.c in mplayer.
+    // the following values come from libmpcodecs/ad_hwac3.c in mplayer.
     // they form a valid IEC958 AC3 header.
     ucsamples[0] = 0x72;
     ucsamples[1] = 0xF8;
     ucsamples[2] = 0x1F;
     ucsamples[3] = 0x4E;
-    ucsamples[4] = 0x01;
+    if(dts)
+    {
+        switch(nr_samples)
+        {
+            case 512:
+                ucsamples[4] = 0x0B;      /* DTS-1 (512-sample bursts) */
+                break;
+
+            case 1024:
+                ucsamples[4] = 0x0C;      /* DTS-2 (1024-sample bursts) */
+                break;
+
+            case 2048:
+                ucsamples[4] = 0x0D;      /* DTS-3 (2048-sample bursts) */
+                break;
+
+            default:
+                VERBOSE(VB_IMPORTANT, LOC +
+                        QString("DTS: %1-sample bursts not supported")
+                        .arg(nr_samples));
+                ucsamples[4] = 0x00;
+                break;
+        }
+    }
+    else
+    {
+        ucsamples[4] = 0x01;
+    }
     ucsamples[5] = 0x00;
     ucsamples[6] = (enc_len << 3) & 0xFF;
     ucsamples[7] = (enc_len >> 5) & 0xFF;
-    memset(ucsamples + 8 + enc_len, 0, MAX_AC3_FRAME_SIZE - 8 - enc_len);
-    samples_size = MAX_AC3_FRAME_SIZE;
+    memset(ucsamples + 8 + enc_len, 0, block_len - 8 - enc_len);
+    samples_size = block_len;
 
-    return len;  // consume whole frame even if len > enc_len ?
+    return enc_len;
 }
 
 void AvFormatDecoder::AddTextData(unsigned char *buf, int len,
@@ -2429,3 +2506,134 @@
 {
     m_parent->AddTextData((char*)buf, len, timecode, type);
 }
+  
+static int DTS_SAMPLEFREQS[16] =
+{
+    0,
+    8000,
+    16000,
+    32000,
+    64000,
+    128000,
+    11025,
+    22050,
+    44100,
+    88200,
+    176400,
+    12000,
+    24000,
+    48000,
+    96000,
+    192000
+};
+
+static int DTS_BITRATES[30] =
+{
+    32000,
+    56000,
+    64000,
+    96000,
+    112000,
+    128000,
+    192000,
+    224000,
+    256000,
+    320000,
+    384000,
+    448000,
+    512000,
+    576000,
+    640000,
+    768000,
+    896000,
+    1024000,
+    1152000,
+    1280000,
+    1344000,
+    1408000,
+    1411200,
+    1472000,
+    1536000,
+    1920000,
+    2048000,
+    3072000,
+    3840000,
+    4096000
+};
+
+static int dts_syncinfo(uint8_t *indata_ptr, int */*flags*/, int *sample_rate, int *bit_rate)
+{
+    int nblks;
+    int rate;
+    int sfreq;
+
+    int fsize = dts_decode_header(indata_ptr, &rate, &nblks, &sfreq);
+    if(fsize >= 0)
+    {
+        if(rate >= 0 && rate <= 29)
+            *bit_rate = DTS_BITRATES[rate];
+        else
+            *bit_rate = 0;
+        if(sfreq >= 1 && sfreq <= 15)
+            *sample_rate = DTS_SAMPLEFREQS[sfreq];
+        else
+            *sample_rate = 0;
+    }
+    return fsize;
+}
+
+static int dts_decode_header(uint8_t *indata_ptr, int *rate, int *nblks, int *sfreq)
+{
+    if(((indata_ptr[0] << 24) | (indata_ptr[1] << 16) | (indata_ptr[2] << 8)
+        | (indata_ptr[3])) != 0x7ffe8001)
+        return -1;
+
+    int ftype = indata_ptr[4] >> 7;
+
+    int surp = (indata_ptr[4] >> 2) & 0x1f;
+    surp = (surp + 1) % 32;
+
+    *nblks = (indata_ptr[4] & 0x01) << 6 | (indata_ptr[5] >> 2);
+    *nblks = *nblks + 1;
+
+    int fsize = (indata_ptr[5] & 0x03) << 12 | (indata_ptr[6] << 4) | (indata_ptr[7] >> 4);
+    fsize = fsize + 1;
+
+    *sfreq = (indata_ptr[8] >> 2) & 0x0f;
+    *rate = (indata_ptr[8] & 0x03) << 3 | ((indata_ptr[9] >> 5) & 0x07);
+
+    if(ftype != 1)
+    {
+        VERBOSE(VB_IMPORTANT, LOC +
+                QString("DTS: Termination frames not handled (ftype %1)").arg(ftype));
+        return -1;
+    }
+
+    if(*sfreq != 13)
+    {
+        VERBOSE(VB_IMPORTANT, LOC +
+                QString("DTS: Only 48kHz supported (sfreq %1)").arg(*sfreq));
+        return -1;
+    }
+
+    if((fsize > 8192) || (fsize < 96))
+    {
+        VERBOSE(VB_IMPORTANT, LOC +
+                QString("DTS: fsize: %1 invalid").arg(fsize));
+        return -1;
+    }
+
+    if(*nblks != 8 &&
+       *nblks != 16 &&
+       *nblks != 32 &&
+       *nblks != 64 &&
+       *nblks != 128 &&
+       ftype == 1)
+    {
+        VERBOSE(VB_IMPORTANT, LOC +
+                QString("DTS: nblks %1 not valid for normal frame").arg(*nblks));
+        return -1;
+    }
+
+    return fsize;
+}
Index: libs/libavformat/mpeg.c
===================================================================
--- libs/libavformat/mpeg.c	(revision 8035)
+++ libs/libavformat/mpeg.c	(working copy)
@@ -88,7 +88,7 @@
 #define AUDIO_ID 0xc0
 #define VIDEO_ID 0xe0
 #define AC3_ID   0x80
-#define DTS_ID   0x8a
+#define DTS_ID   0x88
 #define LPCM_ID  0xa0
 #define SUB_ID   0x20
 
Index: programs/mythfrontend/globalsettings.cpp
===================================================================
--- programs/mythfrontend/globalsettings.cpp	(revision 8035)
+++ programs/mythfrontend/globalsettings.cpp	(working copy)
@@ -133,6 +133,20 @@
     return gc;
 }
 
+#ifdef CONFIG_DTS
+static HostCheckBox *DTSPassThrough()
+{
+    HostCheckBox *gc = new HostCheckBox("DTSPassThru");
+    gc->setLabel(QObject::tr("Enable DTS to SPDIF passthrough"));
+    gc->setValue(false);
+    gc->setHelpText(QObject::tr("Enable sending DTS audio directly to your "
+                    "sound card's SPDIF output, on sources which contain "
+                    "DTS soundtracks (usually DVDs).  Requires that the "
+                    "audio output device be set to something suitable."));
+    return gc;
+}
+#endif
+
 static HostCheckBox *Deinterlace()
 {
     HostCheckBox *gc = new HostCheckBox("Deinterlace");
@@ -2043,6 +2057,9 @@
 
          addChild(AudioOutputDevice());
          addChild(AC3PassThrough());
+#ifdef CONFIG_DTS
+         addChild(DTSPassThrough());
+#endif
          addChild(AggressiveBuffer());
 
          Setting* volumeControl = MythControlsVolume();
