Problem addressed by this patch:

DVB channels often have multiple audio track types, MPEG, AC3 (and various 
languages). By default mythtv will select and initialise iteself to the first 
audio track it finds. When you change between DVB channels with different 
audio track types, mythtv will only play the audio if it is the same type as 
the audio it was initalised with. 

The fix:

1. Added an option to the Configuration menu to enable and disable the 
selection of AC3 tracks. For frontends that support AC3 then this can be 
enabled and myth will select the AC3 track in preferrence to other tracks. If 
the option is disabled then myth will not select AC3 audio tracks.

3. Enhanced avformatdecoder to re-initalise the audio parameters when it 
encounters a change in audio codec (currently it is only re-initialised on a 
change in rate or channels which is not enough.)

4. dvbrecorder selects AC3 audio tracks in preference to MPEG if the AC3 
option is enabled. This piece will not be needed once PS recording is 
enhanced to recoord all audio tracks. 

After applying Patches 1 to 4, mythtv will support AC3 audio for DVB TS 
recordings. However, for PS recordings there is an additional hack patch that 
is needed to work around the fact that PS recordings only record a single 
audio track. I will post this patch shortly.
 
Cheers,
Mark Anderson
diff -rbupB ../mythtv.orig/libs/libmythtv/avformatdecoder.cpp ./libs/libmythtv/avformatdecoder.cpp
--- ../mythtv.orig/libs/libmythtv/avformatdecoder.cpp	2005-01-26 11:38:21.000000000 +1100
+++ ./libs/libmythtv/avformatdecoder.cpp	2005-01-26 12:49:57.797739737 +1100
@@ -151,6 +151,7 @@ AvFormatDecoder::AvFormatDecoder(NuppelV
     audio_channels = -1;
     audio_sample_size = -1;
     audio_sampling_rate = -1;
+    audio_codec = -1;
 
     exitafterdecoded = false;
     ateof = false;
@@ -644,8 +645,6 @@ int AvFormatDecoder::ScanStreams(bool no
                     QString("AvFormatDecoder: Could not find decoder for "
                             "codec,  ignoring (%1).")
                            .arg(enc->codec_id));
-            //If we don't find a codec for this stream then continue on in  
-            //case there is another stream with a codec we can handle.
             continue;
         }
 
@@ -716,28 +715,31 @@ bool AvFormatDecoder::CheckVideoParams(i
     return true;
 }
 
-void AvFormatDecoder::CheckAudioParams(int freq, int channels, bool safe)
+void AvFormatDecoder::CheckAudioParams(int freq, int channels, int codec_id, bool safe)
 {
     if (freq <= 0 || channels <= 0)
         return;
 
     if (safe || audio_check_1st == 2)
     {
-        if (freq == audio_sampling_rate && channels == audio_channels)
+        if (freq == audio_sampling_rate && channels == audio_channels && audio_codec == codec_id) 
             return;
         audio_check_1st = 1;
         audio_sampling_rate_2nd = freq;
         audio_channels_2nd = channels;
+        audio_codec_2nd = codec_id; 
         if (safe == false)
             return;
     }
     else
     {
         if (freq != audio_sampling_rate_2nd || channels != audio_channels_2nd ||
-            (freq == audio_sampling_rate && channels == audio_channels))
+            codec_id != audio_codec_2nd ||
+            (freq == audio_sampling_rate && channels == audio_channels && codec_id == audio_codec))
         {
             audio_sampling_rate_2nd = -1;
             audio_channels_2nd = -1;
+            audio_codec_2nd = -1;
             audio_check_1st = 2;
             return;
         }
@@ -752,9 +754,12 @@ void AvFormatDecoder::CheckAudioParams(i
     audio_check_1st = 2;
 
     if (audio_channels != -1)
-        VERBOSE(VB_AUDIO, QString("Audio format changed from %1 channels,"
-                " %2hz to %3 channels %4hz").arg(audio_channels)
-                .arg(audio_sampling_rate).arg(channels).arg(freq));
+    {
+        VERBOSE(VB_ALL, QString("Audio format changed from %1 channels,"
+                " %2hz codec %3 to %4 channels %5hz codec %6").arg(audio_channels)
+                .arg(audio_sampling_rate).arg(audio_codec).arg(channels)
+                .arg(freq).arg(codec_id));
+    }
 
     AVCodecContext *enc = &ic->streams[wantedAudioStream]->codec;
     AVCodec *codec = enc->codec;
@@ -1138,7 +1143,7 @@ void AvFormatDecoder::incCurrentAudioTra
         wantedAudioStream = audioStreams[currentAudioTrack];
 
         AVCodecContext *e = &ic->streams[wantedAudioStream]->codec;
-        CheckAudioParams(e->sample_rate, e->channels, true);
+        CheckAudioParams(e->sample_rate, e->channels, e->codec_id, true);
     }
 }
 
@@ -1155,7 +1160,7 @@ void AvFormatDecoder::decCurrentAudioTra
         wantedAudioStream = audioStreams[currentAudioTrack];
 
         AVCodecContext *e = &ic->streams[wantedAudioStream]->codec;
-        CheckAudioParams(e->sample_rate, e->channels, true);
+        CheckAudioParams(e->sample_rate, e->channels, e->codec_id, true);
     }
 }
 
@@ -1173,15 +1178,20 @@ bool AvFormatDecoder::setCurrentAudioTra
     wantedAudioStream = audioStreams[currentAudioTrack];
 
     AVCodecContext *e = &ic->streams[wantedAudioStream]->codec;
-    CheckAudioParams(e->sample_rate, e->channels, true);
+    CheckAudioParams(e->sample_rate, e->channels, e->codec_id, true);
     return true;
 }
 
-bool AvFormatDecoder::autoSelectAudioTrack()
+bool AvFormatDecoder::autoSelectAudioTrack(bool prefer_ac3)
 {
     if (!audioStreams.size())
         return false;
 
+    if (prefer_ac3)
+    {
+        prefer_ac3 = gContext->GetNumSetting("ac3wanted", true);
+    }
+
     bool foundAudio = false;
     int minChannels = 1;
     int maxTracks = (audioStreams.size() - 1);
@@ -1196,6 +1206,12 @@ bool AvFormatDecoder::autoSelectAudioTra
             int tempStream = audioStreams[track];
             AVCodecContext *e = &ic->streams[tempStream]->codec;
 
+            if (((prefer_ac3) && (e->codec_id != CODEC_ID_AC3)) || 
+                ((!prefer_ac3) && (e->codec_id == CODEC_ID_AC3))) 
+            {
+                continue;
+            }
+
             if (e->channels > minChannels)
             {
                 currentAudioTrack = track;
@@ -1206,16 +1222,26 @@ bool AvFormatDecoder::autoSelectAudioTra
                 VERBOSE(VB_AUDIO, 
                         QString("It has %1 channels and we needed at least %2")
                                .arg(e->channels).arg(minChannels + 1));
+                if (prefer_ac3)
+                {
+                    VERBOSE(VB_ALL, QString("AC3 stream has been selected"));
+                }
 
                 AVCodecContext *e = &ic->streams[wantedAudioStream]->codec;
-                CheckAudioParams(e->sample_rate, e->channels, true);
+                CheckAudioParams(e->sample_rate, e->channels, e->codec_id, true);
                 return true;
             }
         }
         minChannels--;
         if (minChannels < 0)
+        {
+            if (prefer_ac3)
+            {
+                return autoSelectAudioTrack(false);
+            }
             return false;
     }
+    }
 
     return false;
 }
@@ -1232,6 +1258,8 @@ void AvFormatDecoder::SetupAudioStream(v
     VERBOSE(VB_ALL, QString("Initializing audio parms from stream #%1.")
             .arg(currentAudioTrack));
 
+    audio_codec = curstream->codec.codec_id;
+
     m_parent->SetEffDsp(curstream->codec.sample_rate * 100);
 
     do_ac3_passthru = curstream->codec.codec_id == CODEC_ID_AC3 &&
@@ -1239,6 +1267,7 @@ void AvFormatDecoder::SetupAudioStream(v
 
     if (do_ac3_passthru)
     {
+        VERBOSE(VB_ALL, QString("AC3 passthrough is enabled"));
         // An AC3 stream looks like a 48KHz 2ch audio stream to
         // the sound card
         audio_sample_size = 4;
@@ -1423,7 +1452,9 @@ bool AvFormatDecoder::GetFrame(int onlyv
 
                     if (!do_ac3_passthru)
                         CheckAudioParams(curstream->codec.sample_rate,
-                                         curstream->codec.channels, false);
+                                         curstream->codec.channels, 
+                                         curstream->codec.codec_id,
+                                         false);
 
                     long long temppts = lastapts;
 
diff -rbupB ../mythtv.orig/libs/libmythtv/avformatdecoder.h ./libs/libmythtv/avformatdecoder.h
--- ../mythtv.orig/libs/libmythtv/avformatdecoder.h	2005-01-22 06:25:42.000000000 +1100
+++ ./libs/libmythtv/avformatdecoder.h	2005-01-26 12:50:08.497855250 +1100
@@ -78,7 +78,7 @@ class AvFormatDecoder : public DecoderBa
     /// Attempt to find the optimal audio stream to use based on the number of channels,
     /// and if we're doing AC3 passthrough.  This will select the highest stream number
     /// that matches our criteria.
-    bool autoSelectAudioTrack();
+    bool autoSelectAudioTrack(bool wantac3 = true);
 
     RingBuffer *getRingBuf(void) { return ringBuffer; }
 
@@ -112,7 +112,7 @@ class AvFormatDecoder : public DecoderBa
     bool CheckVideoParams(int width, int height);
 
     /// See if the audio parameters have changed, return true if so.
-    void CheckAudioParams(int freq, int channels, bool safe);
+    void CheckAudioParams(int freq, int channels, int codec, bool safe);
     void SetupAudioStream(void);
 
     int EncodeAC3Frame(unsigned char* data, int len, short *samples,
@@ -136,10 +136,12 @@ class AvFormatDecoder : public DecoderBa
     int audio_sample_size;
     int audio_sampling_rate;
     int audio_channels;
+    int audio_codec;
 
     int audio_check_1st;         ///< Used by CheckAudioParams
     int audio_sampling_rate_2nd; ///< Used by CheckAudioParams
     int audio_channels_2nd;      ///< Used by CheckAudioParams
+    int audio_codec_2nd;         ///< Used by CheckAudioParams
 
     int bitrate;
 
diff -rbupB ../mythtv.orig/libs/libmythtv/dvbrecorder.cpp ./libs/libmythtv/dvbrecorder.cpp
--- ../mythtv.orig/libs/libmythtv/dvbrecorder.cpp	2005-01-24 09:45:30.000000000 +1100
+++ ./libs/libmythtv/dvbrecorder.cpp	2005-01-26 13:00:25.527535827 +1100
@@ -48,6 +48,7 @@ using namespace std;
 
 #include "RingBuffer.h"
 #include "programinfo.h"
+#include "mythcontext.h"
 
 #include "transform.h"
 #include "dvbtypes.h"
@@ -353,7 +354,7 @@ void DVBRecorder::SetDemuxFilters()
     else
     {
         // PES recording currently only supports one video and one audio PID (I think???)
-        ElementaryPIDObject *as = m_pmt.PreferredAudioStream();
+        ElementaryPIDObject *as = m_pmt.PreferredAudioStream(gContext->GetNumSetting("ac3wanted", true));
         ElementaryPIDObject *vs = m_pmt.PreferredVideoStream();
 //        ElementaryPIDObject *sub = m_pmt.PreferredSubtitleStream();
 
diff -rbupB ../mythtv.orig/libs/libmythtv/sitypes.cpp ./libs/libmythtv/sitypes.cpp
--- ../mythtv.orig/libs/libmythtv/sitypes.cpp	2005-01-24 17:42:19.000000000 +1100
+++ ./libs/libmythtv/sitypes.cpp	2005-01-26 12:53:05.148745681 +1100
@@ -291,12 +291,11 @@ void PMTObject::Reset()
 
 // Try to auto detect which audio stream to use
 // NOTE!!! This is only used for PS recording via transform.c!
-ElementaryPIDObject *PMTObject::PreferredAudioStream()
+ElementaryPIDObject *PMTObject::PreferredAudioStream(bool prefer_ac3 = false)
 {
     QValueList<ElementaryPIDObject>::Iterator pit;
 
     // Change this if you prefer AC3
-    bool prefer_ac3 = false;
     if (prefer_ac3)
     {
         for (pit = Components.begin(); pit != Components.end(); ++pit)
diff -rbupB ../mythtv.orig/libs/libmythtv/sitypes.h ./libs/libmythtv/sitypes.h
--- ../mythtv.orig/libs/libmythtv/sitypes.h	2005-01-24 09:45:30.000000000 +1100
+++ ./libs/libmythtv/sitypes.h	2005-01-26 12:52:23.467085828 +1100
@@ -403,7 +403,7 @@ public:
     bool OnAir() { return TelevisionService(); }
     bool FTA() { return !hasCA; }
 
-    ElementaryPIDObject *PreferredAudioStream();
+    ElementaryPIDObject *PreferredAudioStream(bool prefer_ac3);
     ElementaryPIDObject *PreferredVideoStream();
     ElementaryPIDObject *PreferredSubtitleStream();
 
diff -rbupB ../mythtv.orig/programs/mythfrontend/globalsettings.cpp ./programs/mythfrontend/globalsettings.cpp
--- ../mythtv.orig/programs/mythfrontend/globalsettings.cpp	2005-01-22 09:37:04.000000000 +1100
+++ ./programs/mythfrontend/globalsettings.cpp	2005-01-26 12:40:27.000000000 +1100
@@ -185,6 +185,17 @@ static GenericCheckBox *IndividualMuteCo
     return gc;
 }
 
+static GenericCheckBox *WantAC3()
+{
+    GenericCheckBox *gc = new GenericCheckBox("ac3wanted");
+    gc->setLabel(QObject::tr("Use Dolby digital audio where available"));
+    gc->setValue(true);
+    gc->setHelpText(QObject::tr("Where a Dolby digital sound track is "
+                       "available (usually digital TV) use it. If this is not"
+                       " set then Dolby audio will be disabled"));
+    return gc;
+}
+
 static GenericCheckBox *AC3PassThrough()
 {
     GenericCheckBox *gc = new GenericCheckBox("AC3PassThru");
@@ -1914,6 +1925,7 @@ public:
          setUseLabel(false);
 
          addChild(AudioOutputDevice());
+         addChild(WantAC3());
          addChild(AC3PassThrough());
          addChild(AggressiveBuffer());
 

_______________________________________________
mythtv-dev mailing list
[email protected]
http://mythtv.org/cgi-bin/mailman/listinfo/mythtv-dev

Reply via email to