Skip to content
Browse files

Merge temp/newaudiosettings branch.

In short:
- Add new configuration screen, with testing screen
- No need to press Scan Audio Device anymore
- DTS-HD MA, E-AC3 and TrueHD passthrough
  • Loading branch information...
2 parents 7504555 + aa7298c commit b2a86a2ad29cef7b7d8c19cc5929510be30c94fa @jyavenard jyavenard committed
Showing with 2,148 additions and 1,265 deletions.
  1. +2 −2 mythtv/libs/libmyth/audio/audiooutput.cpp
  2. +4 −1 mythtv/libs/libmyth/audio/audiooutput.h
  3. +20 −25 mythtv/libs/libmyth/audio/audiooutputalsa.cpp
  4. +0 −2 mythtv/libs/libmyth/audio/audiooutputalsa.h
  5. +88 −22 mythtv/libs/libmyth/audio/audiooutputbase.cpp
  6. +4 −1 mythtv/libs/libmyth/audio/audiooutputbase.h
  7. +24 −269 mythtv/libs/libmyth/audio/audiooutputdigitalencoder.cpp
  8. +7 −3 mythtv/libs/libmyth/audio/audiooutputdigitalencoder.h
  9. +31 −10 mythtv/libs/libmyth/audio/audiooutputsettings.cpp
  10. +38 −1 mythtv/libs/libmyth/audio/audiooutputsettings.h
  11. +50 −2 mythtv/libs/libmyth/audio/audiooutpututil.cpp
  12. +5 −0 mythtv/libs/libmyth/audio/audiooutpututil.h
  13. +39 −13 mythtv/libs/libmyth/audio/audiosettings.cpp
  14. +30 −27 mythtv/libs/libmyth/audio/audiosettings.h
  15. +96 −0 mythtv/libs/libmyth/audio/pink.c
  16. +22 −0 mythtv/libs/libmyth/audio/pink.h
  17. +191 −0 mythtv/libs/libmyth/audio/spdifencoder.cpp
  18. +36 −0 mythtv/libs/libmyth/audio/spdifencoder.h
  19. +5 −4 mythtv/libs/libmyth/libmyth.pro
  20. +7 −0 mythtv/libs/libmyth/settings.cpp
  21. +3 −1 mythtv/libs/libmyth/settings.h
  22. +20 −4 mythtv/libs/libmythtv/audioplayer.cpp
  23. +2 −0 mythtv/libs/libmythtv/audioplayer.h
  24. +25 −223 mythtv/libs/libmythtv/avformatdecoder.cpp
  25. +4 −0 mythtv/libs/libmythtv/avformatdecoder.h
  26. +3 −3 mythtv/libs/libmythtv/playercontext.cpp
  27. +1,145 −0 mythtv/programs/mythfrontend/audiogeneralsettings.cpp
  28. +205 −0 mythtv/programs/mythfrontend/audiogeneralsettings.h
  29. +0 −584 mythtv/programs/mythfrontend/globalsettings.cpp
  30. +0 −65 mythtv/programs/mythfrontend/globalsettings.h
  31. +12 −0 mythtv/programs/mythfrontend/main.cpp
  32. +2 −2 mythtv/programs/mythfrontend/mythfrontend.pro
  33. +0 −1 mythtv/programs/mythtranscode/transcode.cpp
  34. +7 −0 mythtv/themes/DVR/main_settings.xml
  35. +7 −0 mythtv/themes/classic/main_settings.xml
  36. +7 −0 mythtv/themes/defaultmenu/main_settings.xml
  37. +7 −0 mythtv/themes/mediacentermenu/main_settings.xml
View
4 mythtv/libs/libmyth/audio/audiooutput.cpp
@@ -48,11 +48,11 @@ AudioOutput *AudioOutput::OpenAudio(
const QString &main_device, const QString &passthru_device,
AudioFormat format, int channels, int codec, int samplerate,
AudioOutputSource source, bool set_initial_vol, bool passthru,
- int upmixer_startup)
+ int upmixer_startup, AudioOutputSettings *custom)
{
AudioSettings settings(
main_device, passthru_device, format, channels, codec, samplerate,
- source, set_initial_vol, passthru, upmixer_startup);
+ source, set_initial_vol, passthru, upmixer_startup, custom);
return OpenAudio(settings);
}
View
5 mythtv/libs/libmyth/audio/audiooutput.h
@@ -41,7 +41,7 @@ class MPUBLIC AudioOutput : public VolumeBase, public OutputListeners
const QString &audiodevice, const QString &passthrudevice,
AudioFormat format, int channels, int codec, int samplerate,
AudioOutputSource source, bool set_initial_vol, bool passthru,
- int upmixer_startup = 0);
+ int upmixer_startup = 0, AudioOutputSettings *custom = NULL);
static AudioOutput *OpenAudio(AudioSettings &settings,
bool willsuspendpa = true);
static AudioOutput *OpenAudio(
@@ -60,6 +60,9 @@ class MPUBLIC AudioOutput : public VolumeBase, public OutputListeners
virtual void SetStretchFactor(float factor);
virtual float GetStretchFactor(void) const { return 1.0f; }
+ virtual int GetChannels(void) const { return 2; }
+ virtual AudioFormat GetFormat(void) const { return FORMAT_S16; };
+ virtual int GetBytesPerFrame(void) const { return 4; };
virtual AudioOutputSettings* GetOutputSettingsCleaned(void)
{ return new AudioOutputSettings; }
View
45 mythtv/libs/libmyth/audio/audiooutputalsa.cpp
@@ -55,7 +55,7 @@ AudioOutputALSA::AudioOutputALSA(const AudioSettings &settings) :
if (args < 0)
{
/* no existing parameters: add it behind device name */
- passthru_device += ":AES0=6";
+ passthru_device += ":AES0=6,AES1=0x82,AES2=0x00,AES3=0x01";
}
else
{
@@ -66,12 +66,12 @@ AudioOutputALSA::AudioOutputALSA(const AudioSettings &settings) :
if (args == passthru_device.length())
{
/* ":" but no parameters */
- passthru_device += "AES0=6";
+ passthru_device += "AES0=6,AES1=0x82,AES2=0x00,AES3=0x01";
}
else if (passthru_device[args] != '{')
{
/* a simple list of parameters: add it at the end of the list */
- passthru_device += ",AES0=6";
+ passthru_device += ",AES0=6,AES1=0x82,AES2=0x00,AES3=0x01";
}
else
{
@@ -80,7 +80,8 @@ AudioOutputALSA::AudioOutputALSA(const AudioSettings &settings) :
--len;
while (len > 0 && passthru_device[len].isSpace());
if (passthru_device[len] == '}')
- passthru_device = passthru_device.insert(len, " AES0=6");
+ passthru_device = passthru_device.insert(
+ len, " AES0=6 AES1 0x82 AES2=0x00 AES3=0x01");
}
}
}
@@ -106,6 +107,7 @@ int AudioOutputALSA::TryOpenDevice(int open_mode, int try_ac3)
if (try_ac3)
{
dev_ba = passthru_device.toAscii();
+ VBAUDIO(QString("OpenDevice %1 for passthrough").arg(passthru_device));
err = snd_pcm_open(&pcm_handle, dev_ba.constData(),
SND_PCM_STREAM_PLAYBACK, open_mode);
m_lastdevice = passthru_device;
@@ -120,6 +122,7 @@ int AudioOutputALSA::TryOpenDevice(int open_mode, int try_ac3)
if (!try_ac3 || err < 0)
{
// passthru open failed, retry default device
+ VBAUDIO(QString("OpenDevice %1").arg(main_device));
dev_ba = main_device.toAscii();
err = snd_pcm_open(&pcm_handle, dev_ba.constData(),
SND_PCM_STREAM_PLAYBACK, open_mode);
@@ -243,7 +246,8 @@ bool AudioOutputALSA::IncPreallocBufferSize(int buffer_time)
(buffer_time / 1000) *
output_bytes_per_frame / 1024;
- VBAUDIO(QString("Prealloc buffer cur: %1 max: %3").arg(cur).arg(max));
+ VBAUDIO(QString("Prealloc buffer cur: %1 need: %2 max: %3")
+ .arg(cur).arg(size).arg(max));
if (size > max)
{
@@ -406,7 +410,7 @@ bool AudioOutputALSA::OpenDevice()
}
period_time = 50000; // aim for an interrupt every 50ms
- buffer_time = period_time << 2; // buffer 200ms worth of samples
+ buffer_time = period_time << 3; // buffer 400ms worth of samples
err = SetParameters(pcm_handle, format, channels, samplerate,
buffer_time, period_time);
@@ -488,7 +492,10 @@ void AudioOutputALSA::WriteAudio(uchar *aubuf, int size)
return;
}
- if ((!passthru && channels == 6) || channels == 8)
+ /* Audio received is using SMPTE channel ordering
+ * ALSA uses its own channel order.
+ * Do not re-order passthu audio */
+ if (!passthru && (channels == 6 || channels == 8))
ReorderSmpteToAlsa(aubuf, frames, output_format, channels - 6);
VERBOSE(VB_AUDIO+VB_TIMESTAMP,
@@ -497,7 +504,7 @@ void AudioOutputALSA::WriteAudio(uchar *aubuf, int size)
while (frames > 0)
{
- lw = pcm_write_func(pcm_handle, tmpbuf, frames);
+ lw = snd_pcm_writei(pcm_handle, tmpbuf, frames);
if (lw >= 0)
{
@@ -517,7 +524,7 @@ void AudioOutputALSA::WriteAudio(uchar *aubuf, int size)
case -EPIPE:
if (snd_pcm_state(pcm_handle) == SND_PCM_STATE_XRUN)
{
- VBERROR("WriteAudio: buffer underrun");
+ VBAUDIO("WriteAudio: buffer underrun");
if ((err = snd_pcm_prepare(pcm_handle)) < 0)
{
AERROR("WriteAudio: unable to recover from xrun");
@@ -604,22 +611,10 @@ int AudioOutputALSA::SetParameters(snd_pcm_t *handle, snd_pcm_format_t format,
err = snd_pcm_hw_params_any(handle, params);
CHECKERR("No playback configurations available");
- /* set the interleaved read/write format, use mmap if available */
- pcm_write_func = &snd_pcm_mmap_writei;
- if ((err = snd_pcm_hw_params_set_access(handle, params,
- SND_PCM_ACCESS_MMAP_INTERLEAVED)) < 0)
- {
- Warn("mmap not available, attempting to fall back to slow writes");
- QString old_err = snd_strerror(err);
- pcm_write_func = &snd_pcm_writei;
- if ((err = snd_pcm_hw_params_set_access(handle, params,
- SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
- {
- Error("Interleaved sound types MMAP & RW are not available");
- AERROR(QString("MMAP Error: %1\n\t\t\tRW Error").arg(old_err));
- return err;
- }
- }
+ /* set the interleaved read/write format */
+ err = snd_pcm_hw_params_set_access(handle, params,
+ SND_PCM_ACCESS_RW_INTERLEAVED);
+ CHECKERR(QString("Interleaved RW audio not available"));
/* set the sample format */
err = snd_pcm_hw_params_set_format(handle, params, format);
View
2 mythtv/libs/libmyth/audio/audiooutputalsa.h
@@ -46,8 +46,6 @@ class AudioOutputALSA : public AudioOutputBase
int pbufsize;
int m_card, m_device, m_subdevice;
QMutex killAudioLock;
- snd_pcm_sframes_t (*pcm_write_func)(snd_pcm_t*, const void*,
- snd_pcm_uframes_t);
bool m_autopassthrough;
QString m_lastdevice;
View
110 mythtv/libs/libmyth/audio/audiooutputbase.cpp
@@ -73,7 +73,7 @@ AudioOutputBase::AudioOutputBase(const AudioSettings &settings) :
pSoundStretch(NULL),
encoder(NULL), upmixer(NULL),
source_channels(-1), source_samplerate(0),
- source_bytes_per_frame(0),
+ source_bytes_per_frame(0), upmix_default(false),
needs_upmix(false), needs_downmix(false),
surround_mode(QUALITY_LOW), old_stretchfactor(1.0f),
volume(80), volumeControl(QString()),
@@ -107,8 +107,7 @@ AudioOutputBase::AudioOutputBase(const AudioSettings &settings) :
src_quality = QUALITY_MEDIUM;
// Handle override of SRC quality settings
- if (gCoreContext->GetNumSetting("AdvancedAudioSettings", false) &&
- gCoreContext->GetNumSetting("SRCQualityOverride", false))
+ if (gCoreContext->GetNumSetting("SRCQualityOverride", false))
{
src_quality = gCoreContext->GetNumSetting("SRCQuality", QUALITY_MEDIUM);
// Extra test to keep backward compatibility with earlier SRC setting
@@ -145,6 +144,17 @@ AudioOutputBase::~AudioOutputBase()
void AudioOutputBase::InitSettings(const AudioSettings &settings)
{
+ if (settings.custom)
+ {
+ // got a custom audio report already, use it
+ // this was likely provided by the AudioTest utility
+ output_settings = new AudioOutputSettings;
+ *output_settings = *settings.custom;
+ max_channels = output_settings->BestSupportedChannels();
+ configured_channels = max_channels;
+ return;
+ }
+
// Ask the subclass what we can send to the device
output_settings = GetOutputSettingsUsers();
@@ -163,7 +173,7 @@ void AudioOutputBase::InitSettings(const AudioSettings &settings)
/**
* Returns capabilities supported by the audio device
* amended to take into account the digital audio
- * options (AC3 and DTS)
+ * options (AC3, DTS, E-AC3 and TrueHD)
*/
AudioOutputSettings* AudioOutputBase::GetOutputSettingsCleaned(void)
{
@@ -185,7 +195,7 @@ AudioOutputSettings* AudioOutputBase::GetOutputSettingsCleaned(void)
/**
* Returns capabilities supported by the audio device
* amended to take into account the digital audio
- * options (AC3 and DTS) as well as the user settings
+ * options (AC3, DTS, E-AC3 and TrueHD) as well as the user settings
*/
AudioOutputSettings* AudioOutputBase::GetOutputSettingsUsers(void)
{
@@ -211,10 +221,12 @@ bool AudioOutputBase::CanPassthrough(int samplerate, int channels) const
// Don't know any cards that support spdif clocked at < 44100
// Some US cable transmissions have 2ch 32k AC-3 streams
ret &= samplerate >= 44100;
- // Will downmix if we can't support the amount of channels
- ret &= channels <= max_channels;
- // Stereo content will always be decoded so it can later be upmixed
- ret &= channels != 2;
+ // Will passthrough if surround audio was defined. Amplifier will
+ // do the downmix if required
+ ret &= max_channels >= 6;
+ // Stereo content will always be decoded so it can later be upmixed
+ // unless audio is configured for stereoo
+ ret |= channels == 2 && max_channels == 2;
return ret;
}
@@ -419,7 +431,8 @@ void AudioOutputBase::Reconfigure(const AudioSettings &orig_settings)
VBAUDIO(QString("Original codec was %1, %2, %3 kHz, %4 channels")
.arg(ff_codec_id_string((CodecID)codec))
.arg(output_settings->FormatToString(format))
- .arg(samplerate/1000).arg(source_channels));
+ .arg(samplerate/1000)
+ .arg(source_channels));
/* Encode to AC-3 if we're allowed to passthru but aren't currently
and we have more than 2 channels but multichannel PCM is not supported
@@ -429,22 +442,25 @@ void AudioOutputBase::Reconfigure(const AudioSettings &orig_settings)
output_settings->canAC3() &&
((!output_settings->canLPCM() && configured_channels > 2) ||
!output_settings->IsSupportedChannels(channels)));
- VBAUDIO(QString("enc(%1), passthru(%2), canAC3(%3), canDTS(%4), canLPCM(%5)"
- ", configured_channels(%6), %7 channels supported(%8)")
+ VBAUDIO(QString("enc(%1), passthru(%2), canAC3(%3), canDTS(%4), canHD(%5), "
+ "canHDLL(%6), canLPCM(%7), "
+ "configured_channels(%8), %9 channels supported(%10)")
.arg(enc)
.arg(passthru)
.arg(output_settings->canAC3())
.arg(output_settings->canDTS())
+ .arg(output_settings->canHD())
+ .arg(output_settings->canHDLL())
.arg(output_settings->canLPCM())
.arg(configured_channels)
- .arg(channels).arg(output_settings->IsSupportedChannels(channels)));
+ .arg(channels)
+ .arg(output_settings->IsSupportedChannels(channels)));
int dest_rate = 0;
// Force resampling if we are encoding to AC3 and sr > 48k
// or if 48k override was checked in settings
if ((samplerate != 48000 &&
- gCoreContext->GetNumSetting("AdvancedAudioSettings", false) &&
gCoreContext->GetNumSetting("Audio48kOverride", false)) ||
(enc && (samplerate > 48000 || (need_resampler && dest_rate > 48000))))
{
@@ -511,8 +527,46 @@ void AudioOutputBase::Reconfigure(const AudioSettings &orig_settings)
}
}
- source_bytes_per_frame = source_channels *
- output_settings->SampleSize(format);
+ if (passthru)
+ {
+ switch (settings.codec)
+ {
+ case CODEC_ID_EAC3:
+ samplerate *= 4;
+ case CODEC_ID_AC3:
+ case CODEC_ID_DTS:
+ channels = 2;
+ break;
+ case CODEC_ID_TRUEHD:
+ channels = 8;
+ switch(samplerate)
+ {
+ case 48000:
+ case 96000:
+ case 192000:
+ samplerate = 192000;
+ break;
+ case 44100:
+ case 88200:
+ case 176400:
+ samplerate = 176400;
+ break;
+ default:
+ VBAUDIO("TrueHD: Unsupported samplerate");
+ break;
+ }
+ break;
+ }
+ //AC3, DTS, DTS-HD MA and TrueHD use 16 bits samples
+ format = output_format = FORMAT_S16;
+ source_bytes_per_frame = channels *
+ output_settings->SampleSize(format);
+ }
+ else
+ {
+ source_bytes_per_frame = source_channels *
+ output_settings->SampleSize(format);
+ }
// Turn on float conversion?
if (need_resampler || needs_upmix || needs_downmix ||
@@ -525,12 +579,20 @@ void AudioOutputBase::Reconfigure(const AudioSettings &orig_settings)
if (enc)
output_format = FORMAT_S16; // Output s16le for AC-3 encoder
else
- output_format = output_settings->BestSupportedFormat();
+ {
+ // re-encode audio using same format as input if upmixing
+ // to minimize the memory sound buffer usage. There should be
+ // no siginificant quality loss
+ if (needs_upmix &&
+ output_settings->IsSupportedFormat(format))
+ {
+ output_format = format;
+ }
+ else
+ output_format = output_settings->BestSupportedFormat();
+ }
}
- if (passthru)
- channels = 2; // IEC958 bitstream - 2 ch
-
bytes_per_frame = processing ? 4 : output_settings->SampleSize(format);
bytes_per_frame *= channels;
@@ -967,6 +1029,7 @@ int AudioOutputBase::CopyWithUpmix(char *buffer, int frames, int &org_waud)
if (!needs_upmix)
{
int num = len;
+
if (bdiff <= num)
{
memcpy(WPOS, buffer, bdiff);
@@ -1045,7 +1108,8 @@ bool AudioOutputBase::AddFrames(void *in_buffer, int in_frames,
int org_waud = waud, afree = audiofree();
int frames = in_frames;
void *buffer = in_buffer;
- int bpf = bytes_per_frame, len = frames * source_bytes_per_frame;
+ int bpf = bytes_per_frame;
+ int len = frames * source_bytes_per_frame;
int used = kAudioRingBufferSize - afree;
bool music = false;
int bdiff;
@@ -1110,7 +1174,8 @@ bool AudioOutputBase::AddFrames(void *in_buffer, int in_frames,
int frames_remaining = in_frames;
int frames_final = 0;
- int maxframes = (kAudioSRCInputSize / source_channels) & ~0xf;
+ int maxframes = (kAudioSRCInputSize /
+ (passthru ? channels : source_channels)) & ~0xf;
int offset = 0;
while(frames_remaining > 0)
@@ -1131,6 +1196,7 @@ bool AudioOutputBase::AddFrames(void *in_buffer, int in_frames,
// Convert to floats
len = AudioOutputUtil::toFloat(format, src_in, buffer, len);
}
+
frames_remaining -= frames;
// Perform downmix if necessary
View
5 mythtv/libs/libmyth/audio/audiooutputbase.h
@@ -61,6 +61,9 @@ class AudioOutputBase : public AudioOutput, public QThread
// timestretch
virtual void SetStretchFactor(float factor);
virtual float GetStretchFactor(void) const;
+ virtual int GetChannels(void) const { return channels; }
+ virtual AudioFormat GetFormat(void) const { return format; };
+ virtual int GetBytesPerFrame(void) const { return source_bytes_per_frame; };
virtual bool CanPassthrough(int samplerate, int channels) const;
virtual bool ToggleUpmix(void);
@@ -181,8 +184,8 @@ class AudioOutputBase : public AudioOutput, public QThread
int source_channels;
int source_samplerate;
int source_bytes_per_frame;
- bool needs_upmix;
bool upmix_default;
+ bool needs_upmix;
bool needs_downmix;
int surround_mode;
float old_stretchfactor;
View
293 mythtv/libs/libmyth/audio/audiooutputdigitalencoder.cpp
@@ -8,27 +8,7 @@
// libav headers
extern "C" {
#include "libavutil/mem.h" // for av_free
-
-// copied from libavutil/internal.h
-#include "libavutil/common.h" // for AV_GCC_VERSION_AT_LEAST()
-#ifndef av_alias
-#if HAVE_ATTRIBUTE_MAY_ALIAS && (!defined(__ICC) || __ICC > 1110) && AV_GCC_VERSION_AT_LEAST(3,3)
-# define av_alias __attribute__((may_alias))
-#else
-# define av_alias
-#endif
-#endif
-
#include "libavcodec/avcodec.h"
-#if CONFIG_AC3_DECODER
-#include "libavcodec/ac3.h"
-#ifndef INT_BIT
-#define INT_BIT (CHAR_BIT * sizeof(int))
-#endif
-#include "libavcodec/ac3_parser.h"
-#else
-#include <a52dec/a52.h>
-#endif
}
// MythTV headers
@@ -40,16 +20,15 @@ extern "C" {
#define LOC QString("DEnc: ")
#define LOC_ERR QString("DEnc, Error: ")
-#define MAX_AC3_FRAME_SIZE 6144
-
AudioOutputDigitalEncoder::AudioOutputDigitalEncoder(void) :
bytes_per_sample(0),
av_context(NULL),
outlen(0),
inlen(0),
- one_frame_bytes(0)
+ one_frame_bytes(0),
+ m_spdifenc(NULL)
{
- in = (char *)(((long)&inbuf + 15) & ~15);
+ in = (unsigned char *)(((long)&inbuf + 15) & ~15);
}
AudioOutputDigitalEncoder::~AudioOutputDigitalEncoder()
@@ -65,9 +44,13 @@ void AudioOutputDigitalEncoder::Dispose()
av_free(av_context);
av_context = NULL;
}
+ if (m_spdifenc)
+ {
+ delete m_spdifenc;
+ m_spdifenc = NULL;
+ }
}
-//CODEC_ID_AC3
bool AudioOutputDigitalEncoder::Init(
CodecID codec_id, int bitrate, int samplerate, int channels)
{
@@ -83,7 +66,6 @@ bool AudioOutputDigitalEncoder::Init(
// 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)
{
@@ -107,6 +89,12 @@ bool AudioOutputDigitalEncoder::Init(
return false;
}
+ if (m_spdifenc)
+ {
+ delete m_spdifenc;
+ }
+ m_spdifenc = new SPDIFEncoder("spdif", av_context);
+
bytes_per_sample = av_context->channels * sizeof(short);
one_frame_bytes = bytes_per_sample * av_context->frame_size;
@@ -118,242 +106,10 @@ bool AudioOutputDigitalEncoder::Init(
return true;
}
-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_decode_header(uint8_t *indata_ptr, int *rate,
- int *nblks, int *sfreq)
-{
- uint id = ((indata_ptr[0] << 24) | (indata_ptr[1] << 16) |
- (indata_ptr[2] << 8) | (indata_ptr[3]));
-
- if (id != 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;
-
- int fsize = (indata_ptr[5] & 0x03) << 12 |
- (indata_ptr[6] << 4) | (indata_ptr[7] >> 4);
- ++fsize;
-
- *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;
-}
-
-static int dts_syncinfo(uint8_t *indata_ptr, int *flags,
- int *sample_rate, int *bit_rate)
-{
- (void) flags;
-
- int nblks;
- int rate;
- int sfreq;
-
- int fsize = dts_decode_header(indata_ptr, &rate, &nblks, &sfreq);
- if (fsize >= 0)
- {
- *bit_rate = (rate >= 0 && rate <= 29) ? DTS_BITRATES[rate] : 0;
- *sample_rate = (sfreq >= 1 && sfreq <= 15)? DTS_SAMPLEFREQS[sfreq] : 0;
- }
-
- return fsize;
-}
-
-// from http://www.ebu.ch/CMSimages/en/tec_AES-EBU_eg_tcm6-11890.pdf
-// http://en.wikipedia.org/wiki/S/PDIF
-typedef struct {
- // byte 0
- unsigned professional_consumer:1;
- unsigned non_data:1;
- // 4 - no emphasis
- // 6 - 50/15us
- // 7 - CCITT J17
- unsigned audio_signal_emphasis:3;
- unsigned SSFL:1;
- // 0
- // 1 - 48k
- // 2 - 44.1k
- // 3 - 32k
- unsigned sample_frequency:2;
- // byte 1
- // 0
- // 1 - 2 ch
- // 2 - mono
- // 3 - prim/sec
- // 4 - stereo
- unsigned channel_mode:4;
- // 0
- // 1 - 192 bit block
- // 2 - AES18
- // 3 - user def
- unsigned user_bit_management:4;
- // byte 2
- // 1 - audio data
- // 2 - co-ordn
- unsigned auxiliary_bits:3;
- // 4 - 16 bits
- // 5-7 - redither to 16 bits
- unsigned source_word_length:3;
- unsigned reserved:2;
- // byte 3
- unsigned multi_channel_function_description:8;
- // byte 4
- unsigned digital_audio_reference_signal:2;
- unsigned reserved2:6;
-
-} AESHeader;
-
-static int encode_frame(
- bool dts,
- unsigned char *data,
- size_t enc_len)
-{
- unsigned char *payload = data + 8; // skip header, currently 52 or 54bits
- int flags, sample_rate, bit_rate;
-
- // we don't do any length/crc validation of the AC3 frame here; presumably
- // the receiver will have enough sense to do that. if someone has a
- // receiver that doesn't, here would be a good place to put in a call
- // to a52_crc16_block(samples+2, data_size-2) - but what do we do if the
- // packet is bad? we'd need to send something that the receiver would
- // ignore, and if so, may as well just assume that it will ignore
- // anything with a bad CRC...
-
- uint nr_samples = 0, block_len = 0;
-
- if (dts)
- {
- enc_len = dts_syncinfo(payload, &flags, &sample_rate, &bit_rate);
- int rate, sfreq, nblks;
- dts_decode_header(payload, &rate, &nblks, &sfreq);
- nr_samples = nblks * 32;
- block_len = nr_samples * 2 * 2;
- }
- else if (CONFIG_AC3_DECODER)
- {
- int err;
- AC3HeaderInfo hdr;
- GetBitContext gbc;
-
- init_get_bits(&gbc, payload, 54);
- err = ff_ac3_parse_header(&gbc, &hdr);
-
- if(err < 0)
- enc_len = 0;
- else
- {
- sample_rate = hdr.sample_rate;
- bit_rate = hdr.bit_rate;
- enc_len = hdr.frame_size;
- block_len = AC3_FRAME_SIZE * 4;
- }
- }
-
- enc_len = std::min((uint)enc_len, block_len - 8);
-
- swab((const char *)payload, (char *)payload, enc_len);
-
- // the following values come from libmpcodecs/ad_hwac3.c in mplayer.
- // they form a valid IEC958 AC3 header.
- data[0] = 0x72;
- data[1] = 0xF8;
- data[2] = 0x1F;
- data[3] = 0x4E;
- data[4] = 0x01;
- if (dts)
- {
- switch(nr_samples)
- {
- case 256:
- data[4] = 0x0A; /* DTS-? (256-sample bursts) */
- break;
-
- case 512:
- data[4] = 0x0B; /* DTS-1 (512-sample bursts) */
- break;
-
- case 1024:
- data[4] = 0x0C; /* DTS-2 (1024-sample bursts) */
- break;
-
- case 2048:
- data[4] = 0x0D; /* DTS-3 (2048-sample bursts) */
- break;
-
- case 4096:
- data[4] = 0x0E; /* DTS-? (4096-sample bursts) */
- break;
-
- default:
- VERBOSE(VB_IMPORTANT, LOC +
- QString("DTS: %1-sample bursts not supported")
- .arg(nr_samples));
- data[4] = 0x00;
- break;
- }
- }
- data[5] = 0x00;
- data[6] = (enc_len << 3) & 0xFF;
- data[7] = (enc_len >> 5) & 0xFF;
- memset(payload + enc_len, 0, block_len - 8 - enc_len);
-
- return enc_len;
-}
-
size_t AudioOutputDigitalEncoder::Encode(void *buf, int len, bool isFloat)
{
size_t outsize = 0;
+ int data_size;
if (isFloat)
inlen += AudioOutputUtil::fromFloat(FORMAT_S16, in + inlen, buf, len);
@@ -368,10 +124,9 @@ size_t AudioOutputDigitalEncoder::Encode(void *buf, int len, bool isFloat)
while (i < frames)
{
- // put data in the correct spot for encode frame
outsize = avcodec_encode_audio(av_context,
- ((uchar*)out) + outlen + 8,
- OUTBUFSIZE - outlen - 8,
+ m_encodebuffer,
+ FF_MIN_BUFFER_SIZE,
(short *)(in + i * one_frame_bytes));
if (outsize < 0)
{
@@ -379,13 +134,13 @@ size_t AudioOutputDigitalEncoder::Encode(void *buf, int len, bool isFloat)
return outlen;
}
- encode_frame(
- /*av_context->codec_id==CODEC_ID_DTS*/ false,
- (uchar*)out + outlen, outsize
- );
-
-
- outlen += MAX_AC3_FRAME_SIZE;
+ if (!m_spdifenc)
+ {
+ m_spdifenc = new SPDIFEncoder("spdif", av_context);
+ }
+ m_spdifenc->WriteFrame(m_encodebuffer, outsize);
+ m_spdifenc->GetData(out + outlen, data_size);
+ outlen += data_size;
inlen -= one_frame_bytes;
i++;
}
View
10 mythtv/libs/libmyth/audio/audiooutputdigitalencoder.h
@@ -5,6 +5,8 @@ extern "C" {
#include "libavcodec/avcodec.h"
};
+#include "spdifencoder.h"
+
#define INBUFSIZE 131072
#define OUTBUFSIZE 98304
#define ENCODER_INBUFSIZE INBUFSIZE
@@ -27,12 +29,14 @@ class AudioOutputDigitalEncoder
private:
AVCodecContext *av_context;
- char out[OUTBUFSIZE];
- char inbuf[INBUFSIZE+16];
- char *in;
+ unsigned char out[OUTBUFSIZE];
+ unsigned char inbuf[INBUFSIZE+16];
+ unsigned char *in;
int outlen;
int inlen;
size_t one_frame_bytes;
+ uint8_t m_encodebuffer[FF_MIN_BUFFER_SIZE];
+ SPDIFEncoder *m_spdifenc;
};
#endif
View
41 mythtv/libs/libmyth/audio/audiooutputsettings.cpp
@@ -1,6 +1,6 @@
/* -*- Mode: c++ -*-
*
- * Copyright (C) foobum@gmail.com 2010
+ * Copyright (C) 2010 foobum@gmail.com and jyavenard@gmail.com
*
* Licensed under the GPL v2 or a later version at your choosing.
*/
@@ -14,11 +14,15 @@ using namespace std;
#include "mythverbose.h"
#include "mythcorecontext.h"
+extern "C" {
+#include "libavutil/avutil.h" // to check version of libavformat
+}
+
#define LOC QString("AO: ")
AudioOutputSettings::AudioOutputSettings(bool invalid) :
- m_passthrough(-1), m_AC3(false), m_DTS(false), m_LPCM(false),
- m_invalid(invalid)
+ m_passthrough(-1), m_AC3(false), m_DTS(false), m_LPCM(false),
+ m_HD(false) , m_HDLL(false), m_invalid(invalid)
{
m_sr.assign(srs, srs +
sizeof(srs) / sizeof(int));
@@ -51,6 +55,8 @@ AudioOutputSettings& AudioOutputSettings::operator=(
m_AC3 = rhs.m_AC3;
m_DTS = rhs.m_DTS;
m_LPCM = rhs.m_LPCM;
+ m_HD = rhs.m_HD;
+ m_HDLL = rhs.m_HDLL;
m_invalid = rhs.m_invalid;
m_sr_it = m_sr.begin() + (rhs.m_sr_it - rhs.m_sr.begin());
m_sf_it = m_sf.begin() + (rhs.m_sf_it - rhs.m_sf.begin());
@@ -269,9 +275,16 @@ AudioOutputSettings* AudioOutputSettings::GetCleaned(bool newcopy)
int mchannels = BestSupportedChannels();
aosettings->m_LPCM = (mchannels > 2);
+ // E-AC3 is transferred as sterep PCM at 4 times the rates
+ // assume all amplifier supporting E-AC3 also supports 7.1 LPCM
+ // as it's required under the bluray standard
+#if LIBAVFORMAT_VERSION_INT > AV_VERSION_INT( 52, 83, 0 )
+ aosettings->m_HD = (mchannels == 8 && BestSupportedRate() == 192000);
+ aosettings->m_HDLL = (mchannels == 8 && BestSupportedRate() == 192000);
+#endif
if (mchannels == 2 && m_passthrough >= 0)
{
- VERBOSE(VB_AUDIO, LOC + QString("AC3 or DTS capable"));
+ VERBOSE(VB_AUDIO, LOC + QString("may be AC3 or DTS capable"));
aosettings->AddSupportedChannels(6);
}
aosettings->m_DTS = aosettings->m_AC3 = (m_passthrough >= 0);
@@ -299,15 +312,20 @@ AudioOutputSettings* AudioOutputSettings::GetUsers(bool newcopy)
int cur_channels = gCoreContext->GetNumSetting("MaxChannels", 2);
int max_channels = aosettings->BestSupportedChannels();
- bool bAdv = gCoreContext->GetNumSetting("AdvancedAudioSettings", false);
- bool bForceDigital = bAdv &&
- gCoreContext->GetNumSetting("PassThruDeviceOverride", false);
+ bool bForceDigital = gCoreContext->GetNumSetting(
+ "PassThruDeviceOverride", false);
bool bAC3 = (aosettings->m_AC3 || bForceDigital) &&
gCoreContext->GetNumSetting("AC3PassThru", false);
bool bDTS = (aosettings->m_DTS || bForceDigital) &&
gCoreContext->GetNumSetting("DTSPassThru", false);
bool bLPCM = aosettings->m_LPCM &&
- !(bAdv && gCoreContext->GetNumSetting("StereoPCM", false));
+ !gCoreContext->GetNumSetting("StereoPCM", false);
+ bool bHD = bLPCM && aosettings->m_HD &&
+ gCoreContext->GetNumSetting("EAC3PassThru", false) &&
+ !gCoreContext->GetNumSetting("Audio48kOverride", false);
+ bool bHDLL = bLPCM && aosettings->m_HD &&
+ gCoreContext->GetNumSetting("TrueHDPassThru", false) &&
+ !gCoreContext->GetNumSetting("Audio48kOverride", false);
if (max_channels > 2 && !bLPCM)
max_channels = 2;
@@ -318,8 +336,11 @@ AudioOutputSettings* AudioOutputSettings::GetUsers(bool newcopy)
cur_channels = max_channels;
aosettings->SetBestSupportedChannels(cur_channels);
- aosettings->m_AC3 = bAC3;
- aosettings->m_DTS = bDTS;
+ aosettings->m_AC3 = bAC3;
+ aosettings->m_DTS = bDTS;
+ aosettings->m_HD = bHD;
+ aosettings->m_HDLL = bHDLL;
+
aosettings->m_LPCM = bLPCM;
return aosettings;
View
39 mythtv/libs/libmyth/audio/audiooutputsettings.h
@@ -57,14 +57,48 @@ class MPUBLIC AudioOutputSettings
void setPassthrough(int val) { m_passthrough = val; };
int canPassthrough() { return m_passthrough; };
+ /**
+ * return true if device can or may support AC3
+ */
bool canAC3() { return m_AC3; };
+ /**
+ * return true if device can or may support DTS
+ */
bool canDTS() { return m_DTS; };
+ /**
+ * return true if device supports multichannels PCM
+ */
bool canLPCM() { return m_LPCM; };
+ /**
+ * return true if device supports E-AC3 or DTS-HD passthrough
+ */
+ bool canHD() { return m_HD; };
+ /**
+ * return true if device supports TrueHD or DTS-HD passthrough
+ */
+ bool canHDLL() { return m_HDLL; };
+ /**
+ * return true if class instance is marked invalid.
+ * if true, you can not assume any of the other method returned
+ * values are valid
+ */
bool IsInvalid() { return m_invalid; };
+ /**
+ * return true if device supports TrueHD or DTS-HD passthrough
+ */
+ void setAC3(bool b) { m_AC3 = b; };
+ void setDTS(bool b) { m_DTS = b; };
+ void setLPCM(bool b) { m_LPCM = b; };
+ void setHD(bool b) { m_HD = b; };
+ void setHDLL(bool b) { m_HDLL = b; };
+ /**
+ * Force set the greatest number of channels supported by the audio
+ * device
+ */
+ void SetBestSupportedChannels(int channels);
private:
void SortSupportedChannels();
- void SetBestSupportedChannels(int channels);
/* passthrough status
* -1 : no
@@ -75,6 +109,9 @@ class MPUBLIC AudioOutputSettings
bool m_AC3;
bool m_DTS;
bool m_LPCM;
+ bool m_HD;
+ bool m_HDLL;
+
bool m_invalid;
vector<int> m_sr, m_rates, m_channels;
View
52 mythtv/libs/libmyth/audio/audiooutpututil.cpp
@@ -3,9 +3,11 @@
using namespace std;
#include "mythconfig.h"
#include "audiooutpututil.h"
+#include <sys/types.h>
+#include <byteswap.h>
-#define LOC QString("AO: ")
-#define LOC_ERR QString("AO, ERROR: ")
+#define LOC QString("AOUtil: ")
+#define LOC_ERR QString("AOUtil, ERROR: ")
#if ARCH_X86
static int has_sse2 = -1;
@@ -629,3 +631,49 @@ void AudioOutputUtil::MuteChannel(int obits, int channels, int ch,
else
_MuteChannel((int *)buffer, channels, ch, frames);
}
+
+#if HAVE_BIGENDIAN
+#define LE_SHORT(v) bswap_16(v)
+#define LE_INT(v) bswap_32(v)
+#else
+#define LE_SHORT(v) (v)
+#define LE_INT(v) (v)
+#endif
+
+char *AudioOutputUtil::GeneratePinkSamples(char *frames, int channels,
+ int channel, int count, int bits)
+{
+ pink_noise_t pink;
+
+ initialize_pink_noise(&pink, bits);
+
+ double res;
+ int32_t ires;
+ int16_t *samp16 = (int16_t*) frames;
+ int32_t *samp32 = (int32_t*) frames;
+
+ while (count-- > 0)
+ {
+ for(int chn = 0 ; chn < channels; chn++)
+ {
+ if (chn==channel)
+ {
+ res = generate_pink_noise_sample(&pink) * 0x03fffffff; /* Don't use MAX volume */
+ ires = res;
+ if (bits == 16)
+ *samp16++ = LE_SHORT(ires >> 16);
+ else
+ *samp32++ = LE_INT(ires);
+ }
+ else
+ {
+ if (bits == 16)
+ *samp16++ = 0;
+ else
+ *samp32++ = 0;
+ }
+ }
+ }
+ return frames;
+}
+
View
5 mythtv/libs/libmyth/audio/audiooutpututil.h
@@ -4,6 +4,9 @@
using namespace std;
#include "mythverbose.h"
#include "audiooutputsettings.h"
+extern "C" {
+#include "pink.h"
+}
class MPUBLIC AudioOutputUtil
{
@@ -16,6 +19,8 @@ class MPUBLIC AudioOutputUtil
bool music, bool upmix);
static void MuteChannel(int obits, int channels, int ch,
void *buffer, int bytes);
+ static char *GeneratePinkSamples(char *frames, int channels,
+ int channel, int count, int bits = 16);
};
#endif
View
52 mythtv/libs/libmyth/audio/audiosettings.cpp
@@ -19,7 +19,8 @@ AudioSettings::AudioSettings() :
use_passthru(false),
source(AUDIOOUTPUT_UNKNOWN),
upmixer(0),
- init(false)
+ init(false),
+ custom(NULL)
{
}
@@ -36,19 +37,28 @@ AudioSettings::AudioSettings(const AudioSettings &other) :
upmixer(other.upmixer),
init(true)
{
+ if (other.custom)
+ {
+ // make a copy of it
+ custom = new AudioOutputSettings;
+ *custom = *other.custom;
+ }
+ else
+ custom = NULL;
}
AudioSettings::AudioSettings(
- const QString &main_device,
- const QString &passthru_device,
- AudioFormat format,
- int channels,
- int codec,
- int samplerate,
- AudioOutputSource source,
- bool set_initial_vol,
- bool use_passthru,
- int upmixer_startup) :
+ const QString &main_device,
+ const QString &passthru_device,
+ AudioFormat format,
+ int channels,
+ int codec,
+ int samplerate,
+ AudioOutputSource source,
+ bool set_initial_vol,
+ bool use_passthru,
+ int upmixer_startup,
+ AudioOutputSettings *custom) :
main_device(main_device),
passthru_device(passthru_device),
format(format),
@@ -61,6 +71,14 @@ AudioSettings::AudioSettings(
upmixer(upmixer_startup),
init(true)
{
+ if (custom)
+ {
+ // make a copy of it
+ this->custom = new AudioOutputSettings;
+ *this->custom = *custom;
+ }
+ else
+ this->custom = NULL;
}
AudioSettings::AudioSettings(
@@ -80,7 +98,8 @@ AudioSettings::AudioSettings(
use_passthru(use_passthru),
source(AUDIOOUTPUT_UNKNOWN),
upmixer(upmixer_startup),
- init(true)
+ init(true),
+ custom(NULL)
{
}
@@ -97,8 +116,15 @@ AudioSettings::AudioSettings(
use_passthru(false),
source(AUDIOOUTPUT_UNKNOWN),
upmixer(0),
- init(false)
+ init(false),
+ custom(NULL)
+{
+}
+
+AudioSettings::~AudioSettings()
{
+ if (custom)
+ delete custom;
}
void AudioSettings::FixPassThrough(void)
View
57 mythtv/libs/libmyth/audio/audiosettings.h
@@ -26,27 +26,29 @@ class MPUBLIC AudioSettings
AudioSettings();
AudioSettings(const AudioSettings &other);
AudioSettings(
- const QString &main_device,
- const QString &passthru_device,
- AudioFormat format,
- int channels,
- int codec,
- int samplerate,
- AudioOutputSource source,
- bool set_initial_vol,
- bool use_passthru,
- int upmixer_startup = 0);
+ const QString &main_device,
+ const QString &passthru_device,
+ AudioFormat format,
+ int channels,
+ int codec,
+ int samplerate,
+ AudioOutputSource source,
+ bool set_initial_vol,
+ bool use_passthru,
+ int upmixer_startup = 0,
+ AudioOutputSettings *custom = NULL);
- AudioSettings(AudioFormat format,
- int channels,
- int codec,
- int samplerate,
- bool use_passthru,
- int upmixer_startup = 0);
+ AudioSettings(AudioFormat format,
+ int channels,
+ int codec,
+ int samplerate,
+ bool use_passthru,
+ int upmixer_startup = 0);
AudioSettings(const QString &main_device,
const QString &passthru_device = QString::null);
+ ~AudioSettings();
void FixPassThrough(void);
void TrimDeviceType(void);
@@ -54,17 +56,18 @@ class MPUBLIC AudioSettings
QString GetPassthruDevice(void) const;
public:
- QString main_device;
- QString passthru_device;
- AudioFormat format;
- int channels;
- int codec;
- int samplerate;
- bool set_initial_vol;
- bool use_passthru;
- AudioOutputSource source;
- int upmixer;
- bool init;
+ QString main_device;
+ QString passthru_device;
+ AudioFormat format;
+ int channels;
+ int codec;
+ int samplerate;
+ bool set_initial_vol;
+ bool use_passthru;
+ AudioOutputSource source;
+ int upmixer;
+ bool init;
+ AudioOutputSettings *custom;
};
#endif // _AUDIO_SETTINGS_H_
View
96 mythtv/libs/libmyth/audio/pink.c
@@ -0,0 +1,96 @@
+/*
+ patest_pink.c
+
+ generate Pink Noise using Gardner method.
+ Optimization suggested by James McCartney uses a tree
+ to select which random value to replace.
+
+ x x x x x x x x x x x x x x x x
+ x x x x x x x x
+ x x x x
+ x x
+ x
+
+ Tree is generated by counting trailing zeros in an increasing index.
+ When the index is zero, no random number is selected.
+
+ This program uses the Portable Audio library which is under development.
+ For more information see: http://www.audiomulch.com/portaudio/
+
+ Author: Phil Burk, http://www.softsynth.com
+
+ Revision History:
+
+ Copyleft 1999 Phil Burk - No rights reserved.
+*/
+
+#include <stdio.h>
+#include <math.h>
+#include "pink.h"
+
+/************************************************************/
+/* Calculate pseudo-random 32 bit number based on linear congruential method. */
+static unsigned long generate_random_number( void )
+{
+ static unsigned long rand_seed = 22222; /* Change this for different random sequences. */
+ rand_seed = (rand_seed * 196314165) + 907633515;
+ return rand_seed;
+}
+
+/* Setup PinkNoise structure for N rows of generators. */
+void initialize_pink_noise( pink_noise_t *pink, int num_rows )
+{
+ int i;
+ long pmax;
+ pink->pink_index = 0;
+ pink->pink_index_mask = (1<<num_rows) - 1;
+/* Calculate maximum possible signed random value. Extra 1 for white noise always added. */
+ pmax = (num_rows + 1) * (1<<(PINK_RANDOM_BITS-1));
+ pink->pink_scalar = 1.0f / pmax;
+/* Initialize rows. */
+ for( i=0; i<num_rows; i++ ) pink->pink_rows[i] = 0;
+ pink->pink_running_sum = 0;
+}
+
+/* generate Pink noise values between -1.0 and +1.0 */
+float generate_pink_noise_sample( pink_noise_t *pink )
+{
+ long new_random;
+ long sum;
+ float output;
+
+/* Increment and mask index. */
+ pink->pink_index = (pink->pink_index + 1) & pink->pink_index_mask;
+
+/* If index is zero, don't update any random values. */
+ if( pink->pink_index != 0 )
+ {
+ /* Determine how many trailing zeros in PinkIndex. */
+ /* This algorithm will hang if n==0 so test first. */
+ int num_zeros = 0;
+ int n = pink->pink_index;
+ while( (n & 1) == 0 )
+ {
+ n = n >> 1;
+ num_zeros++;
+ }
+
+ /* Replace the indexed ROWS random value.
+ * Subtract and add back to Running_sum instead of adding all the random
+ * values together. Only one changes each time.
+ */
+ pink->pink_running_sum -= pink->pink_rows[num_zeros];
+ new_random = ((long)generate_random_number()) >> PINK_RANDOM_SHIFT;
+ pink->pink_running_sum += new_random;
+ pink->pink_rows[num_zeros] = new_random;
+ }
+
+/* Add extra white noise value. */
+ new_random = ((long)generate_random_number()) >> PINK_RANDOM_SHIFT;
+ sum = pink->pink_running_sum + new_random;
+
+/* Scale to range of -1.0 to 0.9999. */
+ output = pink->pink_scalar * sum;
+
+ return output;
+}
View
22 mythtv/libs/libmyth/audio/pink.h
@@ -0,0 +1,22 @@
+#ifndef AUDIOPINK
+#define AUDIOPINK
+
+#include "mythexp.h"
+
+#define PINK_MAX_RANDOM_ROWS (30)
+#define PINK_RANDOM_BITS (24)
+#define PINK_RANDOM_SHIFT ((sizeof(long)*8)-PINK_RANDOM_BITS)
+
+typedef struct
+{
+ long pink_rows[PINK_MAX_RANDOM_ROWS];
+ long pink_running_sum; /* Used to optimize summing of generators. */
+ int pink_index; /* Incremented each sample. */
+ int pink_index_mask; /* Index wrapped by ANDing with this mask. */
+ float pink_scalar; /* Used to scale within range of -1.0 to +1.0 */
+} pink_noise_t;
+
+void initialize_pink_noise( pink_noise_t *pink, int num_rows );
+float generate_pink_noise_sample( pink_noise_t *pink );
+
+#endif
View
191 mythtv/libs/libmyth/audio/spdifencoder.cpp
@@ -0,0 +1,191 @@
+#include "config.h"
+
+#include "compat.h"
+#include "spdifencoder.h"
+#include "mythverbose.h"
+
+#define LOC QString("SPDIFEncoder: ")
+#define LOC_ERR QString("SPDIFEncoder, Error: ")
+
+/*
+ * SPDIFEncoder constructor
+ * Args:
+ * QString muxer : name of the muxer.
+ * Use "spdif" for IEC 958 or IEC 61937 encapsulation
+ * (AC3, DTS, E-AC3, TrueHD, DTS-HD-MA)
+ * Use "adts" for ADTS encpsulation (AAC)
+ * AVCodecContext *ctx : CodecContext to be encaspulated
+ */
+
+SPDIFEncoder::SPDIFEncoder(QString muxer, AVCodecContext *ctx)
+ : m_complete(false), m_oc(NULL), m_stream(NULL), m_size(0)
+{
+ QByteArray dev_ba = muxer.toAscii();
+ AVOutputFormat *fmt =
+ av_guess_format(dev_ba.constData(), NULL, NULL);
+
+ if (!fmt)
+ {
+ VERBOSE(VB_AUDIO, LOC_ERR + "av_guess_format");
+ return;
+ }
+
+ m_oc = avformat_alloc_context();
+ if (!m_oc)
+ {
+ VERBOSE(VB_AUDIO, LOC_ERR + "avformat_alloc_context");
+ return;
+ }
+ m_oc->oformat = fmt;
+
+ if (av_set_parameters(m_oc, NULL) < 0)
+ {
+ VERBOSE(VB_AUDIO, LOC_ERR + "av_set_parameters");
+ Destroy();
+ return;
+ }
+
+ m_oc->pb = av_alloc_put_byte(m_buffer, sizeof(m_buffer), URL_RDONLY,
+ this, NULL, funcIO, NULL);
+ if (!m_oc->pb)
+ {
+ VERBOSE(VB_AUDIO, LOC_ERR + "av_alloc_put_byte");
+ Destroy();
+ return;
+ }
+
+ m_oc->pb->is_streamed = true;
+ m_oc->flags |= AVFMT_NOFILE | AVFMT_FLAG_IGNIDX;
+
+ if (av_set_parameters(m_oc, NULL) != 0)
+ {
+ VERBOSE(VB_AUDIO, LOC_ERR + "av_set_parameters");
+ Destroy();
+ return;
+ }
+
+ m_stream = av_new_stream(m_oc, 1);
+ if (!m_stream)
+ {
+ VERBOSE(VB_AUDIO, LOC_ERR + "av_new_stream");
+ Destroy();
+ return;
+ }
+
+ // copy without decoding or reencoding
+ m_stream->stream_copy = true;
+
+ AVCodecContext *codec = m_stream->codec;
+
+ codec->codec_type = ctx->codec_type;
+ codec->codec_id = ctx->codec_id;
+ codec->sample_rate = ctx->sample_rate;
+ codec->sample_fmt = ctx->sample_fmt;
+ codec->channels = ctx->channels;
+ codec->bit_rate = ctx->bit_rate;
+ codec->extradata = new uint8_t[ctx->extradata_size];
+ codec->extradata_size = ctx->extradata_size;
+ memcpy(codec->extradata, ctx->extradata, ctx->extradata_size);
+
+ av_write_header(m_oc);
+
+ VERBOSE(VB_AUDIO, LOC + QString("Creating %1 encoder (%2, %3Hz)")
+ .arg(muxer).arg(ff_codec_id_string((CodecID)codec->codec_type))
+ .arg(codec->sample_rate));
+
+ m_complete = true;
+}
+
+SPDIFEncoder::~SPDIFEncoder(void)
+{
+ Destroy();
+}
+
+/*
+ * Encode data through created muxer
+ * unsigned char data: pointer to data to encode
+ * int size: size of data to encode
+ */
+
+void SPDIFEncoder::WriteFrame(unsigned char *data, int size)
+{
+ AVPacket packet;
+
+ av_init_packet(&packet);
+ packet.data = data;
+ packet.size = size;
+
+ if (av_write_frame(m_oc, &packet) < 0)
+ {
+ VERBOSE(VB_AUDIO, LOC_ERR + "av_write_frame");
+ }
+}
+
+/*
+ * Retrieve encoded data and copy it in the provided buffer.
+ * Return -1 if there is no data to retrieve.
+ * On return, dest_size will contain the length of the data copied
+ * Upon completion, the internal encoder buffer is emptied.
+ */
+int SPDIFEncoder::GetData(unsigned char *buffer, int &dest_size)
+{
+ if(m_size > 0)
+ {
+ memcpy(buffer, m_buffer, m_size);
+ dest_size = m_size;
+ m_size = 0;
+ return dest_size;
+ }
+ return -1;
+}
+
+/*
+ * Reset the internal encoder buffer
+ */
+void SPDIFEncoder::Reset()
+{
+ m_size = 0;
+}
+
+/*
+ * funcIO: Internal callback function that will receive encoded frames
+ */
+
+int SPDIFEncoder::funcIO(void *opaque, unsigned char *buf, int size)
+{
+ SPDIFEncoder *enc = (SPDIFEncoder *)opaque;
+
+ memcpy(enc->m_buffer + enc->m_size, buf, size);
+ enc->m_size += size;
+ return size;
+}
+
+/*
+ * Destroy and free all allocated memory
+ */
+
+void SPDIFEncoder::Destroy()
+{
+ Reset();
+
+ if (m_complete)
+ {
+ av_write_trailer(m_oc);
+ }
+
+ if (m_stream)
+ {
+ delete[] m_stream->codec->extradata;
+ avcodec_close(m_stream->codec);
+ av_freep(&m_stream);
+ }
+
+ if (m_oc )
+ {
+ if (m_oc->pb)
+ {
+ av_freep(&m_oc->pb);
+ }
+ av_free(m_oc);
+ }
+}
View
36 mythtv/libs/libmyth/audio/spdifencoder.h
@@ -0,0 +1,36 @@
+#ifndef SPDIFENCODER_H_
+#define SPDIFENCODER_H_
+
+#include <QString>
+
+#include "output.h"
+
+extern "C" {
+#include "libavcodec/avcodec.h"
+#include "libavformat/avformat.h"
+#include "libavcodec/audioconvert.h"
+}
+
+class MPUBLIC SPDIFEncoder
+{
+
+ public:
+ SPDIFEncoder(QString muxer, AVCodecContext *ctx);
+ ~SPDIFEncoder();
+ void WriteFrame(unsigned char *data, int size);
+ int GetData(unsigned char *buffer, int &dest_size);
+ void Reset();
+
+ private:
+ static int funcIO(void *opaque, unsigned char *buf, int size);
+ void Destroy();
+
+ private:
+ bool m_complete;
+ AVFormatContext *m_oc;
+ AVStream *m_stream;
+ unsigned char m_buffer[AVCODEC_MAX_AUDIO_FRAME_SIZE];
+ long m_size;
+};
+
+#endif
View
9 mythtv/libs/libmyth/libmyth.pro
@@ -13,8 +13,8 @@ QMAKE_CLEAN += $(TARGET) $(TARGETA) $(TARGETD) $(TARGET0) $(TARGET1) $(TARGET2)
# Input
HEADERS += audio/audiooutput.h audio/audiooutputbase.h audio/audiooutputnull.h
HEADERS += audio/audiooutpututil.h audio/audiooutputdownmix.h
-HEADERS += audio/audiooutputdigitalencoder.h audio/audiosettings.h
-HEADERS += audio/audiooutputsettings.h
+HEADERS += audio/audiooutputdigitalencoder.h udip/spdifencoder.h
+HEADERS += audio/audiosettings.h audio/audiooutputsettings.h audio/pink.h
HEADERS += backendselect.h dbsettings.h dialogbox.h
HEADERS += generictree.h langsettings.h
HEADERS += managedlist.h mythconfigdialogs.h mythconfiggroups.h
@@ -40,9 +40,10 @@ HEADERS += rssparse.h netutils.h
HEADERS += virtualkeyboard_qt.h
SOURCES += audio/audiooutput.cpp audio/audiooutputbase.cpp
-SOURCES += audio/audiooutputnull.cpp audio/audiooutputdigitalencoder.cpp
+SOURCES += audio/spdifencoder.cpp audio/audiooutputdigitalencoder.cpp
+SOURCES += audio/audiooutputnull.cpp
SOURCES += audio/audiooutpututil.cpp audio/audiooutputdownmix.cpp
-SOURCES += audio/audiosettings.cpp audio/audiooutputsettings.cpp
+SOURCES += audio/audiosettings.cpp audio/audiooutputsettings.cpp audio/pink.c
SOURCES += volumebase.cpp xmlparse.cpp
SOURCES += backendselect.cpp dbsettings.cpp dialogbox.cpp
View
7 mythtv/libs/libmyth/settings.cpp
@@ -1346,6 +1346,13 @@ void ButtonSetting::setEnabled(bool fEnabled)
button->setEnabled(fEnabled);
}
+void ButtonSetting::setLabel(QString str)
+{
+ if (button)
+ button->setText(str);
+ Setting::setLabel(str);
+}
+
void ButtonSetting::setHelpText(const QString &str)
{
if (button)
View
4 mythtv/libs/libmyth/settings.h
@@ -54,7 +54,7 @@ class MPUBLIC Configurable : public QObject
virtual Setting* byName(const QString &name) = 0;
// A label displayed to the user
- void setLabel(QString str) { label = str; }
+ virtual void setLabel(QString str) { label = str; }
QString getLabel(void) const { return label; }
void setLabelAboveWidget(bool l = true) { labelAboveWidget = l; }
@@ -580,6 +580,8 @@ class MPUBLIC ButtonSetting: public Setting
virtual void setEnabled(bool b);
+ virtual void setLabel(QString);
+
virtual void setHelpText(const QString &);
signals:
View
24 mythtv/libs/libmythtv/audioplayer.cpp
@@ -106,8 +106,6 @@ QString AudioPlayer::ReinitAudio(void)
const AudioSettings settings(m_format, m_channels, m_codec,
m_samplerate, m_passthru);
m_audioOutput->Reconfigure(settings);
- if (m_passthru)
- m_channels = 2;
errMsg = m_audioOutput->GetError();
SetStretchFactor(m_stretchfactor);
}
@@ -313,6 +311,22 @@ bool AudioPlayer::CanDTS(void)
return ret;
}
+bool AudioPlayer::CanHD(void)
+{
+ bool ret = false;
+ if (m_audioOutput)
+ ret = m_audioOutput->GetOutputSettingsUsers()->canHD();
+ return ret;
+}
+
+bool AudioPlayer::CanHDLL(void)
+{
+ bool ret = false;
+ if (m_audioOutput)
+ ret = m_audioOutput->GetOutputSettingsUsers()->canHDLL();
+ return ret;
+}
+
uint AudioPlayer::GetMaxChannels(void)
{
uint ret = 2;
@@ -334,12 +348,14 @@ void AudioPlayer::AddAudioData(char *buffer, int len, int64_t timecode)
if (m_parent->PrepareAudioSample(timecode) && m_audioOutput &&
!no_audio_out)
m_audioOutput->Drain();
- int samplesize = m_channels * AudioOutputSettings::SampleSize(m_format);
+ int samplesize = m_audioOutput->GetBytesPerFrame();
+
if ((samplesize <= 0) || !m_audioOutput)
return;
int frames = len / samplesize;
+
if (!m_audioOutput->AddFrames(buffer, frames, timecode))
- VERBOSE(VB_PLAYBACK, LOC + "AddAudioData():p1: "
+ VERBOSE(VB_PLAYBACK, LOC + "AddAudioData(): "
"Audio buffer overflow, audio data lost!");
}
View
2 mythtv/libs/libmythtv/audioplayer.h
@@ -42,6 +42,8 @@ class MPUBLIC AudioPlayer
bool CanPassthrough(int samplerate, int channels);
bool CanAC3(void);
bool CanDTS(void);
+ bool CanHD(void);
+ bool CanHDLL(void);
uint GetMaxChannels(void);
int64_t GetAudioTime(void);
View
248 mythtv/libs/libmythtv/avformatdecoder.cpp
@@ -73,12 +73,6 @@ static int cc608_parity(uint8_t byte);
static int cc608_good_parity(const int *parity_table, uint16_t data);
static void cc608_build_parity_table(int *parity_table);
-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);
-static int encode_frame(bool dts, unsigned char* data, int len,
- short *samples, int &samples_size);
static QSize get_video_dim(const AVCodecContext &ctx)
{
return QSize(ctx.width >> ctx.lowres, ctx.height >> ctx.lowres);
@@ -263,7 +257,8 @@ AvFormatDecoder::AvFormatDecoder(MythPlayer *parent,
internal_vol(false),
disable_passthru(false),
dummy_frame(NULL),
- m_fps(0.0f)
+ m_fps(0.0f),
+ m_spdifenc(NULL)
{
bzero(&params, sizeof(AVFormatParameters));
bzero(&readcontext, sizeof(readcontext));
@@ -335,6 +330,9 @@ AvFormatDecoder::~AvFormatDecoder()
lcd->setVariousLEDs(VARIOUS_SPDIF, false);
lcd->setSpeakerLEDs(SPEAKER_71, false); // should clear any and all speaker LEDs
}
+
+ if (m_spdifenc)
+ delete m_spdifenc;
}
void AvFormatDecoder::CloseCodecs()
@@ -3632,7 +3630,7 @@ bool AvFormatDecoder::ProcessAudioPacket(AVStream *curstream, AVPacket *pkt,
long long pts = 0;
int ret = 0;
int data_size = 0;
- bool firstloop = true, dts = false;
+ bool firstloop = true;
avcodeclock->lock();
int audIdx = selectedTrack[kTrackTypeAudio].av_stream_index;
@@ -3733,10 +3731,18 @@ bool AvFormatDecoder::ProcessAudioPacket(AVStream *curstream, AVPacket *pkt,
if (audioOut.do_passthru)
{
+ if (!m_spdifenc)
+ {
+ m_spdifenc = new SPDIFEncoder("spdif", ctx);
+ }
+ m_spdifenc->WriteFrame(tmp_pkt.data, tmp_pkt.size);
data_size = tmp_pkt.size;
- dts = CODEC_ID_DTS == ctx->codec_id;
- ret = encode_frame(dts, tmp_pkt.data, tmp_pkt.size, audioSamples,
- data_size);
+ ret = m_spdifenc->GetData((unsigned char *)audioSamples, data_size);
+ if (ret < 0)
+ {
+ avcodeclock->unlock();
+ return true;
+ }
}
else
{
@@ -3773,8 +3779,7 @@ bool AvFormatDecoder::ProcessAudioPacket(AVStream *curstream, AVPacket *pkt,
if (ret < 0)
{
- if (!dts)
- VERBOSE(VB_IMPORTANT, LOC_ERR + "Unknown audio decoding error");
+ VERBOSE(VB_IMPORTANT, LOC_ERR + "Unknown audio decoding error");
return false;
}
@@ -4258,6 +4263,10 @@ bool AvFormatDecoder::DoPassThrough(const AVCodecContext *ctx)
passthru = m_audio->CanAC3();
else if (ctx->codec_id == CODEC_ID_DTS)
passthru = m_audio->CanDTS();
+ else if (ctx->codec_id == CODEC_ID_EAC3)
+ passthru = m_audio->CanHD();
+ else if (ctx->codec_id == CODEC_ID_TRUEHD)
+ passthru = m_audio->CanHDLL();
passthru &= m_audio->CanPassthrough(ctx->sample_rate, ctx->channels);
passthru &= !internal_vol;
passthru &= !transcoding && !disable_passthru;
@@ -4361,6 +4370,9 @@ bool AvFormatDecoder::SetupAudioStream(void)
audioOut.do_passthru);
m_audio->ReinitAudio();
+ delete m_spdifenc;
+ m_spdifenc = NULL;
+
if (LCD *lcd = LCD::Get())
{
LCDAudioFormatSet audio_format;
@@ -4426,216 +4438,6 @@ bool AvFormatDecoder::SetupAudioStream(void)
return true;
}
-static int encode_frame(bool dts, unsigned char *data, int len,
- short *samples, int &samples_size)
-{
- int enc_len;
- int flags, sample_rate, bit_rate;
- unsigned char* ucsamples = (unsigned char*) samples;
-
- // we don't do any length/crc validation of the AC3 frame here; presumably
- // the receiver will have enough sense to do that. if someone has a
- // receiver that doesn't, here would be a good place to put in a call
- // to a52_crc16_block(samples+2, data_size-2) - but what do we do if the
- // packet is bad? we'd need to send something that the receiver would
- // ignore, and if so, may as well just assume that it will ignore
- // anything with a bad CRC...
-
- uint nr_samples = 0, block_len;
- if (dts)
- {
- enc_len = dts_syncinfo(data, &flags, &sample_rate, &bit_rate);
- if (enc_len < 0)
- return enc_len;
- int rate, sfreq, nblks;
- dts_decode_header(data, &rate, &nblks, &sfreq);
- nr_samples = nblks * 32;
- block_len = nr_samples * 2 * 2;
- }
- else
- {
- AC3HeaderInfo hdr;
- GetBitContext gbc;
- init_get_bits(&gbc, data, len * 8); // XXX HACK: assumes 8 bit per char
- if (!ff_ac3_parse_header(&gbc, &hdr))
- {
- enc_len = hdr.frame_size;
- }
- else
- {
- // creates endless loop
- enc_len = 0;
- }
- block_len = MAX_AC3_FRAME_SIZE;
- }
-
- if (enc_len == 0 || enc_len > len)
- {
- samples_size = 0;
- return len;
- }
-
- enc_len = min((uint)enc_len, block_len - 8);
-
- swab((const char*) data, (char*) (ucsamples + 8), enc_len);
-
- // 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;
- }
- }
- ucsamples[5] = 0x00;
- ucsamples[6] = (enc_len << 3) & 0xFF;
- ucsamples[7] = (enc_len >> 5) & 0xFF;
- memset(ucsamples + 8 + enc_len, 0, block_len - 8 - enc_len);
- samples_size = block_len;
-
- return enc_len;
-}
-
-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;
-}
-
-// defines from libavcodec/dca.h
-#define DCA_MARKER_RAW_BE 0x7FFE8001
-#define DCA_MARKER_RAW_LE 0xFE7F0180
-#define DCA_MARKER_14B_BE 0x1FFFE800
-#define DCA_MARKER_14B_LE 0xFF1F00E8
-#define DCA_HD_MARKER 0x64582025
-
-static int dts_decode_header(uint8_t *indata_ptr, int *rate,
- int *nblks, int *sfreq)
-{
- uint id = ((indata_ptr[0] << 24) | (indata_ptr[1] << 16) |
- (indata_ptr[2] << 8) | (indata_ptr[3]));
-
- switch (id)
- {
- case DCA_MARKER_RAW_BE:
- break;
- case DCA_MARKER_RAW_LE:
- case DCA_MARKER_14B_BE:
- case DCA_MARKER_14B_LE:
- case DCA_HD_MARKER:
- VERBOSE(VB_AUDIO+VB_EXTRA, LOC +
- QString("DTS: Unsupported frame (id 0x%1)").arg(id, 8, 16));
- return -1;
- break;
- default:
- VERBOSE(VB_IMPORTANT, LOC_ERR +
- QString("DTS: Unknown frame (id 0x%1)").arg(id, 8, 16));
- 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;
-
- int fsize = (indata_ptr[5] & 0x03) << 12 |
- (indata_ptr[6] << 4) | (indata_ptr[7] >> 4);
- ++fsize;
-
- *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;
-}
-
void AvFormatDecoder::av_update_stream_timings_video(AVFormatContext *ic)
{
int64_t start_time, start_time1, end_time, end_time1;
View
4 mythtv/libs/libmythtv/avformatdecoder.h
@@ -12,6 +12,7 @@
#include "decoderbase.h"
#include "privatedecoder.h"
#include "audiooutputsettings.h"
+#include "spdifencoder.h"
#include "vbilut.h"
#include "H264Parser.h"
#include "videodisplayprofile.h"
@@ -327,6 +328,9 @@ class AvFormatDecoder : public DecoderBase
AudioInfo audioOut;
float m_fps;
+
+ // SPDIF Encoder for digital passthrough
+ SPDIFEncoder *m_spdifenc;
};
#endif
View
6 mythtv/libs/libmythtv/playercontext.cpp
@@ -418,9 +418,9 @@ bool PlayerContext::CreatePlayer(TV *tv, QWidget *widget,
if (nohardwaredecoders)
player->DisableHardwareDecoders();
- QString passthru_device = gCoreContext->GetNumSetting("AdvancedAudioSettings", false) &&
- gCoreContext->GetNumSetting("PassThruDeviceOverride", false) ?
- gCoreContext->GetSetting("PassThruOutputDevice") : QString::null;
+ QString passthru_device = gCoreContext->GetNumSetting(
+ "PassThruDeviceOverride", false) ?
+ gCoreContext->GetSetting("PassThruOutputDevice") : QString::null;
player->SetPlayerInfo(tv, widget, exact_seeking, this);
AudioPlayer *audio = player->GetAudio();
View
1,145 mythtv/programs/mythfrontend/audiogeneralsettings.cpp
@@ -0,0 +1,1145 @@
+
+// -*- Mode: c++ -*-
+
+// Standard UNIX C headers
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+// Qt headers
+#include <QCoreApplication>
+#include <QEvent>
+#include <QDir>
+
+// MythTV headers
+#include "mythconfig.h"
+#include "mythcorecontext.h"
+#include "mythdbcon.h"
+#include "mythverbose.h"
+#include "audiooutpututil.h"
+#include "audiogeneralsettings.h"
+#include "mythdialogbox.h"
+
+extern "C" {
+#include "libavformat/avformat.h"
+}
+
+
+class TriggeredItem : public TriggeredConfigurationGroup
+{
+ public:
+ TriggeredItem(Setting *checkbox, ConfigurationGroup *group) :
+ TriggeredConfigurationGroup(false, false, false, false)
+ {
+ setTrigger(checkbox);
+
+ addTarget("1", group);
+ addTarget("0", new VerticalConfigurationGroup(true));
+ }
+ TriggeredItem(Setting *checkbox, Setting *setting) :
+ TriggeredConfigurationGroup(false, false, false, false)
+ {
+ setTrigger(checkbox);
+
+ addTarget("1", setting);