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