-
diff --git a/mfd/mfd/plugins/audio/audio.cpp b/mfd/mfd/plugins/audio/audio.cpp
index b2026bc..102c8bc 100644
a
|
b
|
AudioPlugin::AudioPlugin(MFD *owner, int identity) |
45 | 45 | // thr RTSP streamer can use to get PCM bits to send out. |
46 | 46 | // |
47 | 47 | |
48 | | output = AudioOutput::OpenAudio("NULL", "default", 16, 2, 44100, |
49 | | AUDIOOUTPUT_MUSIC, true, false ); |
| 48 | output = AudioOutput::OpenAudio("NULL", "default", 16, 2, CODEC_ID_NONE, |
| 49 | 44100, AUDIOOUTPUT_MUSIC, true, false ); |
50 | 50 | output->bufferOutputData(true); |
51 | 51 | output->setBufferSize(output_buffer_size * 1024); |
52 | 52 | output->SetBlocking(false); |
… |
… |
bool AudioPlugin::playUrl(QUrl url, int collection_id) |
517 | 517 | #else |
518 | 518 | QString adevice = gContext->GetSetting("AudioDevice"); |
519 | 519 | // TODO: Error checking that device is opened correctly! |
520 | | output = AudioOutput::OpenAudio(adevice, "default", 16, 2, 44100, |
| 520 | output = AudioOutput::OpenAudio(adevice, "default", 16, 2, |
| 521 | CODEC_ID_NONE, 44100, |
521 | 522 | AUDIOOUTPUT_MUSIC, true, false ); |
522 | 523 | output->setBufferSize(output_buffer_size * 1024); |
523 | 524 | output->SetBlocking(false); |
-
diff --git a/mfd/mfd/plugins/speakers/rtspin.cpp b/mfd/mfd/plugins/speakers/rtspin.cpp
index c6e9e9f..1703676 100644
a
|
b
|
RtspIn::RtspIn( |
80 | 80 | } |
81 | 81 | } |
82 | 82 | |
83 | | audio_output = AudioOutput::OpenAudio(adevice, "default", 16, 2, 44100, |
| 83 | audio_output = AudioOutput::OpenAudio(adevice, "default", 16, 2, |
| 84 | CODEC_ID_NONE, 44100, |
84 | 85 | AUDIOOUTPUT_MUSIC, false); |
85 | 86 | audio_output->setBufferSize(256 * 1024); |
86 | 87 | audio_output->SetBlocking(false); |
-
diff --git a/mythplugins/mythmusic/mythmusic/aacdecoder.cpp b/mythplugins/mythmusic/mythmusic/aacdecoder.cpp
index 4e350d3..6d0b11f 100644
a
|
b
|
|
28 | 28 | #include "metaiomp4.h" |
29 | 29 | |
30 | 30 | #include <mythtv/mythcontext.h> |
| 31 | #include <mythtv/ffmpeg/avcodec.h> |
31 | 32 | |
32 | 33 | // |
33 | 34 | // C style callbacks (jump right back into the aacDecoder object) |
… |
… |
bool aacDecoder::initializeMP4() |
384 | 385 | |
385 | 386 | if (output()) |
386 | 387 | { |
387 | | output()->Reconfigure(16, channels, sample_rate, |
| 388 | output()->Reconfigure(16, channels, CODEC_ID_AAC, sample_rate, |
388 | 389 | false /* AC3/DTS pass through */); |
389 | 390 | output()->SetSourceBitrate(bitrate); |
390 | 391 | } |
-
diff --git a/mythplugins/mythmusic/mythmusic/avfdecoder.cpp b/mythplugins/mythmusic/mythmusic/avfdecoder.cpp
index d4b7598..ff3fe59 100644
a
|
b
|
bool avfDecoder::initialize() |
184 | 184 | |
185 | 185 | if (output()) |
186 | 186 | { |
187 | | output()->Reconfigure(16, audio_dec->channels, audio_dec->sample_rate, |
| 187 | output()->Reconfigure(16, audio_dec->channels, audio_dec->codec_id, |
| 188 | audio_dec->sample_rate, |
188 | 189 | false /* AC3/DTS pass through */); |
189 | 190 | output()->SetSourceBitrate(audio_dec->bit_rate); |
190 | 191 | } |
-
diff --git a/mythplugins/mythmusic/mythmusic/cddecoder.cpp b/mythplugins/mythmusic/mythmusic/cddecoder.cpp
index 19f85b1..cf22083 100644
a
|
b
|
using namespace std; |
14 | 14 | |
15 | 15 | #include <mythtv/mythcontext.h> |
16 | 16 | #include <mythtv/mythmediamonitor.h> |
| 17 | #include <mythtv/ffmpeg/avcodec.h> |
17 | 18 | |
18 | 19 | CdDecoder::CdDecoder(const QString &file, DecoderFactory *d, QIODevice *i, |
19 | 20 | AudioOutput *o) |
… |
… |
bool CdDecoder::initialize() |
136 | 137 | |
137 | 138 | if (output()) |
138 | 139 | { |
139 | | output()->Reconfigure(16, chan, freq, false /* AC3/DTS passthru */); |
| 140 | output()->Reconfigure(16, chan, CODEC_ID_PCM_S16LE, freq, |
| 141 | false /* AC3/DTS passthru */); |
140 | 142 | output()->SetSourceBitrate(44100 * 2 * 16); |
141 | 143 | } |
142 | 144 | |
-
diff --git a/mythplugins/mythmusic/mythmusic/flacdecoder.cpp b/mythplugins/mythmusic/mythmusic/flacdecoder.cpp
index 9c891e1..d893ab5 100644
a
|
b
|
using namespace std; |
14 | 14 | |
15 | 15 | #include <mythtv/mythconfig.h> |
16 | 16 | #include <mythtv/mythcontext.h> |
| 17 | #include <mythtv/ffmpeg/avcodec.h> |
17 | 18 | |
18 | 19 | #include <qtimer.h> |
19 | 20 | |
… |
… |
void FlacDecoder::setFlacMetadata(const FLAC__StreamMetadata *metadata) |
150 | 151 | |
151 | 152 | if (output()) |
152 | 153 | { |
153 | | output()->Reconfigure(bitspersample, chan, |
| 154 | output()->Reconfigure(bitspersample, chan, CODEC_ID_FLAC, |
154 | 155 | freq, false /* AC3/DTS pass through */); |
155 | 156 | output()->SetSourceBitrate(44100 * 2 * 16); |
156 | 157 | } |
-
diff --git a/mythplugins/mythmusic/mythmusic/maddecoder.cpp b/mythplugins/mythmusic/mythmusic/maddecoder.cpp
index bd0c1fe..cc30fb3 100644
a
|
b
|
using namespace std; |
17 | 17 | |
18 | 18 | #include <mythtv/mythconfig.h> |
19 | 19 | #include <mythtv/mythcontext.h> |
| 20 | #include <mythtv/ffmpeg/avcodec.h> |
20 | 21 | |
21 | 22 | #define XING_MAGIC (('X' << 24) | ('i' << 16) | ('n' << 8) | 'g') |
22 | 23 | |
… |
… |
bool MadDecoder::initialize() |
111 | 112 | |
112 | 113 | if (output()) |
113 | 114 | { |
114 | | output()->Reconfigure(16, channels, freq, false /*AC3/DTS passthru*/); |
| 115 | output()->Reconfigure(16, channels, CODEC_ID_MP3, freq, |
| 116 | false /*AC3/DTS passthru*/); |
115 | 117 | output()->SetSourceBitrate(bitrate); |
116 | 118 | } |
117 | 119 | |
… |
… |
enum mad_flow MadDecoder::madOutput() |
479 | 481 | { |
480 | 482 | freq = newfreq; |
481 | 483 | channels = newchannels; |
482 | | output()->Reconfigure(16, channels, freq, false /*AC3/DTS passthru*/); |
| 484 | output()->Reconfigure(16, channels, CODEC_ID_MP3, freq, |
| 485 | false /*AC3/DTS passthru*/); |
483 | 486 | } |
484 | 487 | if (newbitrate != bitrate) |
485 | 488 | { |
-
diff --git a/mythplugins/mythmusic/mythmusic/main.cpp b/mythplugins/mythmusic/mythmusic/main.cpp
index 0ab4b45..490aab3 100644
a
|
b
|
void setupKeys(void) |
378 | 378 | REG_KEY("Music", "VOLUMEDOWN", "Volume down", "[,{,F10,Volume Down"); |
379 | 379 | REG_KEY("Music", "VOLUMEUP", "Volume up", "],},F11,Volume Up"); |
380 | 380 | REG_KEY("Music", "MUTE", "Mute", "|,\\,F9,Volume Mute"); |
| 381 | REG_KEY("Music", "TOGGLEUPMIX","Toggle upmixer", "Ctrl+U"); |
381 | 382 | REG_KEY("Music", "CYCLEVIS", "Cycle visualizer mode", "6"); |
382 | 383 | REG_KEY("Music", "BLANKSCR", "Blank screen", "5"); |
383 | 384 | REG_KEY("Music", "THMBUP", "Increase rating", "9"); |
-
diff --git a/mythplugins/mythmusic/mythmusic/musicplayer.cpp b/mythplugins/mythmusic/mythmusic/musicplayer.cpp
index ba0793d..92a4a49 100644
a
|
b
|
void MusicPlayer::stopDecoder(void) |
347 | 347 | |
348 | 348 | void MusicPlayer::openOutputDevice(void) |
349 | 349 | { |
350 | | QString adevice; |
| 350 | QString adevice, pdevice; |
351 | 351 | |
352 | 352 | if (gContext->GetSetting("MusicAudioDevice") == "default") |
353 | 353 | adevice = gContext->GetSetting("AudioOutputDevice"); |
354 | 354 | else |
355 | 355 | adevice = gContext->GetSetting("MusicAudioDevice"); |
356 | 356 | |
| 357 | pdevice = gContext->GetSetting("PassThruOutputDevice"); |
| 358 | |
357 | 359 | // TODO: Error checking that device is opened correctly! |
358 | | m_output = AudioOutput::OpenAudio(adevice, "default", 16, 2, 44100, |
359 | | AUDIOOUTPUT_MUSIC, true, false); |
| 360 | m_output = AudioOutput::OpenAudio(adevice, pdevice, 16, 2, |
| 361 | 0, 44100, |
| 362 | AUDIOOUTPUT_MUSIC, true, false); |
| 363 | |
360 | 364 | m_output->setBufferSize(256 * 1024); |
361 | 365 | m_output->SetBlocking(false); |
362 | 366 | |
-
diff --git a/mythplugins/mythmusic/mythmusic/playbackbox.cpp b/mythplugins/mythmusic/mythmusic/playbackbox.cpp
index 57c38a9..cc230c5 100644
a
|
b
|
void PlaybackBoxMusic::keyPressEvent(QKeyEvent *e) |
358 | 358 | changeSpeed(true); |
359 | 359 | else if (action == "MUTE") |
360 | 360 | toggleMute(); |
| 361 | else if (action == "TOGGLEUPMIX") |
| 362 | toggleUpmix(); |
361 | 363 | else if (action == "MENU" && visualizer_status != 2) |
362 | 364 | { |
363 | 365 | menufilters = false; |
… |
… |
void PlaybackBoxMusic::toggleMute() |
1178 | 1180 | } |
1179 | 1181 | } |
1180 | 1182 | |
| 1183 | void PlaybackBoxMusic::toggleUpmix() |
| 1184 | { |
| 1185 | if (gPlayer->getOutput()) |
| 1186 | gPlayer->getOutput()->ToggleUpmix(); |
| 1187 | } |
| 1188 | |
| 1189 | |
1181 | 1190 | void PlaybackBoxMusic::showProgressBar() |
1182 | 1191 | { |
1183 | 1192 | if (progress_bar) |
-
diff --git a/mythplugins/mythmusic/mythmusic/playbackbox.h b/mythplugins/mythmusic/mythmusic/playbackbox.h
index 038ad97..2950d0b 100644
a
|
b
|
class PlaybackBoxMusic : public MythThemedDialog |
69 | 69 | void changeVolume(bool up_or_down); |
70 | 70 | void changeSpeed(bool up_or_down); |
71 | 71 | void toggleMute(); |
| 72 | void toggleUpmix(); |
72 | 73 | void resetTimer(); |
73 | 74 | void hideVolume(){showVolume(false);} |
74 | 75 | void showVolume(bool on_or_off); |
-
diff --git a/mythplugins/mythmusic/mythmusic/vorbisdecoder.cpp b/mythplugins/mythmusic/mythmusic/vorbisdecoder.cpp
index 1dc90a8..702de6d 100644
a
|
b
|
using namespace std; |
14 | 14 | |
15 | 15 | #include <mythtv/mythconfig.h> |
16 | 16 | #include <mythtv/mythcontext.h> |
| 17 | #include <mythtv/ffmpeg/avcodec.h> |
17 | 18 | |
18 | 19 | // static functions for OggVorbis |
19 | 20 | |
… |
… |
bool VorbisDecoder::initialize() |
187 | 188 | |
188 | 189 | if (output()) |
189 | 190 | { |
190 | | output()->Reconfigure(16, chan, freq, false /*AC3/DTS pass through*/); |
| 191 | output()->Reconfigure(16, chan, CODEC_ID_VORBIS, freq, |
| 192 | false /*AC3/DTS pass through*/); |
191 | 193 | output()->SetSourceBitrate(bitrate); |
192 | 194 | } |
193 | 195 | |
-
diff --git a/mythplugins/mythphone/mythphone/audiodrv.cpp b/mythplugins/mythphone/mythphone/audiodrv.cpp
index 20662b8..048ac33 100644
a
|
b
|
void mythAudioDriver::Open() |
835 | 835 | cerr << "Cannot have matching spk and mic devices in this mode, should have chosen OSS mode\n"; |
836 | 836 | else |
837 | 837 | { |
838 | | mythOutput = AudioOutput::OpenAudio(spkDevice, "default", 16, 1, 8000, |
| 838 | mythOutput = AudioOutput::OpenAudio(spkDevice, "default", 16, 1, |
| 839 | CODEC_ID_NONE, 8000, |
839 | 840 | AUDIOOUTPUT_TELEPHONY, true, |
840 | 841 | false /* AC3/DTS pass through */); |
841 | 842 | if (mythOutput) |
-
diff --git a/mythplugins/mythphone/mythphone/tone.cpp b/mythplugins/mythphone/mythphone/tone.cpp
index 9056ab1..76f3c96 100644
a
|
b
|
void Tone::OpenSpeaker(QString devName) |
305 | 305 | return; |
306 | 306 | |
307 | 307 | #else |
308 | | mythOutput = AudioOutput::OpenAudio(devName, "default", 16, 1, 8000, |
| 308 | mythOutput = AudioOutput::OpenAudio(devName, "default", 16, 1, |
| 309 | CODEC_ID_NONE, 8000, |
309 | 310 | AUDIOOUTPUT_TELEPHONY, true, |
310 | 311 | false /* AC3/DTS pass through */); |
311 | 312 | if (mythOutput) |
-
diff --git a/mythtv/libs/libavcodec/ac3dec.c b/mythtv/libs/libavcodec/ac3dec.c
index 76c6284..1b4d996 100644
a
|
b
|
static const uint8_t ac3_default_coeffs[8][5][2] = { |
121 | 121 | { { 1, 0 }, { 3, 3 }, { 0, 1 }, { 4, 0 }, { 0, 4 }, }, |
122 | 122 | }; |
123 | 123 | |
| 124 | static const int channel_map[6] = { 0, 2, 3, 4, 1, 5 }; |
| 125 | |
124 | 126 | /* override ac3.h to include coupling channel */ |
125 | 127 | #undef AC3_MAX_CHANNELS |
126 | 128 | #define AC3_MAX_CHANNELS 7 |
… |
… |
static int ac3_decode_frame(AVCodecContext * avctx, void *data, int *data_size, |
1174 | 1176 | *data_size = 0; |
1175 | 1177 | return ctx->frame_size; |
1176 | 1178 | } |
1177 | | for (i = 0; i < 256; i++) |
1178 | | for (ch = 0; ch < ctx->out_channels; ch++) |
1179 | | *(out_samples++) = ctx->int_output[ch][i]; |
| 1179 | if (ctx->out_channels == 6) { |
| 1180 | for (i = 0; i < 256; i++) |
| 1181 | for (ch = 0; ch < ctx->out_channels; ch++) |
| 1182 | *(out_samples++) = ctx->int_output[channel_map[ch]][i]; |
| 1183 | } |
| 1184 | else { |
| 1185 | for (i = 0; i < 256; i++) |
| 1186 | for (ch = 0; ch < ctx->out_channels; ch++) |
| 1187 | *(out_samples++) = ctx->int_output[ch][i]; |
| 1188 | } |
1180 | 1189 | } |
1181 | 1190 | *data_size = NB_BLOCKS * 256 * avctx->channels * sizeof (int16_t); |
1182 | 1191 | return ctx->frame_size; |
-
diff --git a/mythtv/libs/libavcodec/dca.c b/mythtv/libs/libavcodec/dca.c
index b3803ad..af974f0 100644
a
|
b
|
static BitAlloc dca_smpl_bitalloc[11]; ///< samples VLCs |
87 | 87 | /** Pre-calculated cosine modulation coefs for the QMF */ |
88 | 88 | static float cos_mod[544]; |
89 | 89 | |
| 90 | static const int channel_map[6] = { 1, 2, 3, 4, 0, 5 }; |
| 91 | |
90 | 92 | static av_always_inline int get_bitalloc(GetBitContext *gb, BitAlloc *ba, int idx) |
91 | 93 | { |
92 | 94 | return get_vlc2(gb, ba->vlc[idx].table, ba->vlc[idx].bits, ba->wrap) + ba->offset; |
… |
… |
static int dca_decode_frame(AVCodecContext * avctx, |
1189 | 1191 | dca_decode_block(s); |
1190 | 1192 | s->dsp.float_to_int16(s->tsamples, s->samples, 256 * channels); |
1191 | 1193 | /* interleave samples */ |
1192 | | for (j = 0; j < 256; j++) { |
1193 | | for (k = 0; k < channels; k++) |
1194 | | samples[k] = s->tsamples[j + k * 256]; |
1195 | | samples += channels; |
| 1194 | if (channels == 6) { |
| 1195 | for (j = 0; j < 256; j++) { |
| 1196 | for (k = 0; k < channels; k++) |
| 1197 | samples[k] = s->tsamples[j + channel_map[k] * 256]; |
| 1198 | samples += channels; |
| 1199 | } |
| 1200 | } |
| 1201 | else { |
| 1202 | for (j = 0; j < 256; j++) { |
| 1203 | for (k = 0; k < channels; k++) |
| 1204 | samples[k] = s->tsamples[j + k * 256]; |
| 1205 | samples += channels; |
| 1206 | } |
1196 | 1207 | } |
1197 | 1208 | *data_size += 256 * sizeof(int16_t) * channels; |
1198 | 1209 | } |
-
diff --git a/mythtv/libs/libmyth/audiooutput.cpp b/mythtv/libs/libmyth/audiooutput.cpp
index 1eab657..dbd6618 100644
a
|
b
|
using namespace std; |
34 | 34 | AudioOutput *AudioOutput::OpenAudio(QString main_device, |
35 | 35 | QString passthru_device, |
36 | 36 | int audio_bits, |
37 | | int audio_channels, int audio_samplerate, |
| 37 | int audio_channels, |
| 38 | int audio_codec, |
| 39 | int audio_samplerate, |
38 | 40 | AudioOutputSource source, |
39 | 41 | bool set_initial_vol, bool audio_passthru) |
40 | 42 | { |
… |
… |
AudioOutput *AudioOutput::OpenAudio(QString main_device, |
46 | 48 | #ifdef USE_ALSA |
47 | 49 | return new AudioOutputALSA(main_device.remove(0, 5), |
48 | 50 | passthru_device.remove(0, 5), audio_bits, |
49 | | audio_channels, audio_samplerate, source, |
| 51 | audio_channels, audio_codec, |
| 52 | audio_samplerate, source, |
50 | 53 | set_initial_vol, audio_passthru); |
51 | 54 | #else |
52 | 55 | VERBOSE(VB_IMPORTANT, "Audio output device is set to an ALSA device " |
… |
… |
AudioOutput *AudioOutput::OpenAudio(QString main_device, |
57 | 60 | else if (main_device.startsWith("NULL")) |
58 | 61 | { |
59 | 62 | return new AudioOutputNULL(main_device, passthru_device, audio_bits, |
60 | | audio_channels, audio_samplerate, source, |
| 63 | audio_channels, audio_codec, |
| 64 | audio_samplerate, source, |
61 | 65 | set_initial_vol, audio_passthru); |
62 | 66 | } |
63 | 67 | else if (main_device.startsWith("ARTS:")) |
… |
… |
AudioOutput *AudioOutput::OpenAudio(QString main_device, |
65 | 69 | #ifdef USE_ARTS |
66 | 70 | return new AudioOutputARTS(main_device.remove(0, 5), |
67 | 71 | passthru_device.remove(0, 5), audio_bits, |
68 | | audio_channels, audio_samplerate, source, |
| 72 | audio_channels, audio_codec, |
| 73 | audio_samplerate, source, |
69 | 74 | set_initial_vol, audio_passthru); |
70 | 75 | #else |
71 | 76 | VERBOSE(VB_IMPORTANT, "Audio output device is set to an ARTS device " |
… |
… |
AudioOutput *AudioOutput::OpenAudio(QString main_device, |
78 | 83 | #ifdef USE_JACK |
79 | 84 | return new AudioOutputJACK(main_device.remove(0, 5), |
80 | 85 | passthru_device.remove(0, 5), audio_bits, |
81 | | audio_channels, audio_samplerate, source, |
| 86 | audio_channels, audio_codec, |
| 87 | audio_samplerate, source, |
82 | 88 | set_initial_vol, audio_passthru); |
83 | 89 | #else |
84 | 90 | VERBOSE(VB_IMPORTANT, "Audio output device is set to a JACK device " |
… |
… |
AudioOutput *AudioOutput::OpenAudio(QString main_device, |
90 | 96 | { |
91 | 97 | #ifdef USING_DIRECTX |
92 | 98 | return new AudioOutputDX(main_device, passthru_device, audio_bits, |
93 | | audio_channels, audio_samplerate, source, |
| 99 | audio_channels, audio_codec, |
| 100 | audio_samplerate, source, |
94 | 101 | set_initial_vol, audio_passthru); |
95 | 102 | #else |
96 | 103 | VERBOSE(VB_IMPORTANT, "Audio output device is set to DirectX device " |
… |
… |
AudioOutput *AudioOutput::OpenAudio(QString main_device, |
102 | 109 | { |
103 | 110 | #ifdef USING_WINAUDIO |
104 | 111 | return new AudioOutputWin(main_device, passthru_device, audio_bits, |
105 | | audio_channels, audio_samplerate, source, |
| 112 | audio_channels, audio_codec, |
| 113 | audio_samplerate, source, |
106 | 114 | set_initial_vol, audio_passthru); |
107 | 115 | #else |
108 | 116 | VERBOSE(VB_IMPORTANT, "Audio output device is set to a Windows device " |
… |
… |
AudioOutput *AudioOutput::OpenAudio(QString main_device, |
113 | 121 | #if defined(USING_OSS) |
114 | 122 | else |
115 | 123 | return new AudioOutputOSS(main_device, passthru_device, audio_bits, |
116 | | audio_channels, audio_samplerate, source, |
| 124 | audio_channels, audio_codec, |
| 125 | audio_samplerate, source, |
117 | 126 | set_initial_vol, audio_passthru); |
118 | 127 | #elif defined(CONFIG_DARWIN) |
119 | 128 | else |
120 | 129 | return new AudioOutputCA(main_device, passthru_device, audio_bits, |
121 | | audio_channels, audio_samplerate, source, |
| 130 | audio_channels, audio_codec, |
| 131 | audio_samplerate, source, |
122 | 132 | set_initial_vol, audio_passthru); |
123 | 133 | #endif |
124 | 134 | |
-
diff --git a/mythtv/libs/libmyth/audiooutput.h b/mythtv/libs/libmyth/audiooutput.h
index 7d65a51..1de4f96 100644
a
|
b
|
class MPUBLIC AudioOutput : public VolumeBase, public OutputListeners |
19 | 19 | public: |
20 | 20 | // opens one of the concrete subclasses |
21 | 21 | static AudioOutput *OpenAudio(QString audiodevice, QString passthrudevice, |
22 | | int audio_bits, |
23 | | int audio_channels, int audio_samplerate, |
| 22 | int audio_bits, int audio_channels, |
| 23 | int audio_codec, int audio_samplerate, |
24 | 24 | AudioOutputSource source, |
25 | 25 | bool set_initial_vol, bool audio_passthru); |
26 | 26 | |
… |
… |
class MPUBLIC AudioOutput : public VolumeBase, public OutputListeners |
33 | 33 | // reconfigure sound out for new params |
34 | 34 | virtual void Reconfigure(int audio_bits, |
35 | 35 | int audio_channels, |
| 36 | int audio_codec, |
36 | 37 | int audio_samplerate, |
37 | | bool audio_passthru, |
38 | | void* audio_codec = NULL) = 0; |
| 38 | bool audio_passthru) = 0; |
39 | 39 | |
40 | 40 | virtual void SetStretchFactor(float factor); |
41 | 41 | virtual float GetStretchFactor(void) { return 1.0f; } |
| 42 | virtual bool ToggleUpmix(void) = 0; |
42 | 43 | |
43 | 44 | // do AddSamples calls block? |
44 | 45 | virtual void SetBlocking(bool blocking) = 0; |
-
diff --git a/mythtv/libs/libmyth/audiooutputalsa.cpp b/mythtv/libs/libmyth/audiooutputalsa.cpp
index ba86f3b..dd5bad9 100644
a
|
b
|
using namespace std; |
16 | 16 | AudioOutputALSA::AudioOutputALSA( |
17 | 17 | QString laudio_main_device, QString laudio_passthru_device, |
18 | 18 | int laudio_bits, int laudio_channels, |
19 | | int laudio_samplerate, AudioOutputSource lsource, |
20 | | bool lset_initial_vol, bool laudio_passthru) : |
| 19 | int laudio_codec, int laudio_samplerate, |
| 20 | AudioOutputSource lsource, bool lset_initial_vol, |
| 21 | bool laudio_passthru) : |
21 | 22 | AudioOutputBase(laudio_main_device, laudio_passthru_device, |
22 | 23 | laudio_bits, laudio_channels, |
23 | 24 | laudio_samplerate, lsource, |
… |
… |
AudioOutputALSA::AudioOutputALSA( |
28 | 29 | playback_vol_min(0), playback_vol_max(1) |
29 | 30 | { |
30 | 31 | // Set everything up |
31 | | Reconfigure(laudio_bits, laudio_channels, |
| 32 | Reconfigure(laudio_bits, laudio_channels, laudio_codec, |
32 | 33 | laudio_samplerate, laudio_passthru); |
33 | 34 | } |
34 | 35 | |
35 | 36 | AudioOutputALSA::~AudioOutputALSA() |
36 | 37 | { |
37 | 38 | KillAudio(); |
| 39 | SetIECStatus(true); |
| 40 | } |
| 41 | |
| 42 | void AudioOutputALSA::SetIECStatus(bool audio) { |
| 43 | |
| 44 | snd_ctl_t *ctl; |
| 45 | const char *spdif_str = SND_CTL_NAME_IEC958("", PLAYBACK, DEFAULT); |
| 46 | int spdif_index = -1; |
| 47 | snd_ctl_elem_list_t *clist; |
| 48 | snd_ctl_elem_id_t *cid; |
| 49 | snd_ctl_elem_value_t *cval; |
| 50 | snd_aes_iec958_t iec958; |
| 51 | int cidx, controls; |
| 52 | |
| 53 | VERBOSE(VB_AUDIO, QString("Setting IEC958 status: %1") |
| 54 | .arg(audio ? "audio" : "non-audio")); |
| 55 | |
| 56 | snd_ctl_open(&ctl, "default", 0); |
| 57 | snd_ctl_elem_list_alloca(&clist); |
| 58 | snd_ctl_elem_list(ctl, clist); |
| 59 | snd_ctl_elem_list_alloc_space(clist, snd_ctl_elem_list_get_count(clist)); |
| 60 | snd_ctl_elem_list(ctl, clist); |
| 61 | controls = snd_ctl_elem_list_get_used(clist); |
| 62 | for (cidx = 0; cidx < controls; cidx++) |
| 63 | { |
| 64 | if (!strcmp(snd_ctl_elem_list_get_name(clist, cidx), spdif_str)) |
| 65 | if (spdif_index < 0 || |
| 66 | snd_ctl_elem_list_get_index(clist, cidx) == (uint)spdif_index) |
| 67 | break; |
| 68 | } |
| 69 | |
| 70 | if (cidx >= controls) |
| 71 | return; |
| 72 | |
| 73 | snd_ctl_elem_id_alloca(&cid); |
| 74 | snd_ctl_elem_list_get_id(clist, cidx, cid); |
| 75 | snd_ctl_elem_value_alloca(&cval); |
| 76 | snd_ctl_elem_value_set_id(cval, cid); |
| 77 | snd_ctl_elem_read(ctl,cval); |
| 78 | snd_ctl_elem_value_get_iec958(cval, &iec958); |
| 79 | |
| 80 | if (!audio) |
| 81 | iec958.status[0] |= IEC958_AES0_NONAUDIO; |
| 82 | else |
| 83 | iec958.status[0] &= ~IEC958_AES0_NONAUDIO; |
| 84 | |
| 85 | snd_ctl_elem_value_set_iec958(cval, &iec958); |
| 86 | snd_ctl_elem_write(ctl, cval); |
| 87 | |
| 88 | } |
| 89 | |
| 90 | vector<int> AudioOutputALSA::GetSupportedRates() |
| 91 | { |
| 92 | snd_pcm_hw_params_t *params; |
| 93 | int err; |
| 94 | const int srates[] = { 8000, 11025, 16000, 22050, 32000, 44100, 48000 }; |
| 95 | vector<int> rates(srates, srates + sizeof(srates) / sizeof(int) ); |
| 96 | QString real_device; |
| 97 | |
| 98 | if (audio_passthru || audio_enc) |
| 99 | real_device = audio_passthru_device; |
| 100 | else |
| 101 | real_device = audio_main_device; |
| 102 | |
| 103 | if((err = snd_pcm_open(&pcm_handle, real_device, |
| 104 | SND_PCM_STREAM_PLAYBACK, |
| 105 | SND_PCM_NONBLOCK|SND_PCM_NO_AUTO_RESAMPLE)) < 0) |
| 106 | { |
| 107 | Error(QString("snd_pcm_open(%1): %2") |
| 108 | .arg(real_device).arg(snd_strerror(err))); |
| 109 | |
| 110 | if (pcm_handle) |
| 111 | { |
| 112 | snd_pcm_close(pcm_handle); |
| 113 | pcm_handle = NULL; |
| 114 | } |
| 115 | rates.clear(); |
| 116 | return rates; |
| 117 | } |
| 118 | |
| 119 | snd_pcm_hw_params_alloca(¶ms); |
| 120 | |
| 121 | if ((err = snd_pcm_hw_params_any(pcm_handle, params)) < 0) |
| 122 | { |
| 123 | Error(QString("Broken configuration for playback; no configurations" |
| 124 | " available: %1").arg(snd_strerror(err))); |
| 125 | snd_pcm_close(pcm_handle); |
| 126 | pcm_handle = NULL; |
| 127 | rates.clear(); |
| 128 | return rates; |
| 129 | } |
| 130 | |
| 131 | vector<int>::iterator it; |
| 132 | |
| 133 | for (it = rates.begin(); it < rates.end(); it++) |
| 134 | if(snd_pcm_hw_params_test_rate(pcm_handle, params, *it, 0) < 0) |
| 135 | rates.erase(it--); |
| 136 | |
| 137 | snd_pcm_close(pcm_handle); |
| 138 | pcm_handle = NULL; |
| 139 | |
| 140 | return rates; |
38 | 141 | } |
39 | 142 | |
40 | 143 | bool AudioOutputALSA::OpenDevice() |
… |
… |
bool AudioOutputALSA::OpenDevice() |
42 | 145 | snd_pcm_format_t format; |
43 | 146 | unsigned int buffer_time, period_time; |
44 | 147 | int err; |
| 148 | QString real_device; |
45 | 149 | |
46 | 150 | if (pcm_handle != NULL) |
47 | 151 | CloseDevice(); |
48 | 152 | |
49 | 153 | pcm_handle = NULL; |
50 | 154 | numbadioctls = 0; |
51 | | |
52 | | QString real_device = (audio_passthru) ? |
53 | | audio_passthru_device : audio_main_device; |
| 155 | |
| 156 | if (audio_passthru || audio_enc) |
| 157 | { |
| 158 | real_device = audio_passthru_device; |
| 159 | SetIECStatus(false); |
| 160 | } |
| 161 | else |
| 162 | { |
| 163 | real_device = audio_main_device; |
| 164 | SetIECStatus(true); |
| 165 | } |
54 | 166 | |
55 | 167 | VERBOSE(VB_GENERAL, QString("Opening ALSA audio device '%1'.") |
56 | 168 | .arg(real_device)); |
… |
… |
bool AudioOutputALSA::OpenDevice() |
63 | 175 | Error(QString("snd_pcm_open(%1): %2") |
64 | 176 | .arg(real_device).arg(snd_strerror(err))); |
65 | 177 | |
66 | | if (pcm_handle) |
67 | | CloseDevice(); |
| 178 | CloseDevice(); |
68 | 179 | return false; |
69 | 180 | } |
70 | 181 | |
-
diff --git a/mythtv/libs/libmyth/audiooutputalsa.h b/mythtv/libs/libmyth/audiooutputalsa.h
index 79c923b..3f3440a 100644
a
|
b
|
class AudioOutputALSA : public AudioOutputBase |
17 | 17 | { |
18 | 18 | public: |
19 | 19 | AudioOutputALSA(QString laudio_main_device, QString laudio_passthru_device, |
20 | | int laudio_bits, |
21 | | int laudio_channels, int laudio_samplerate, |
22 | | AudioOutputSource source, |
23 | | bool set_initial_vol, bool laudio_passthru); |
| 20 | int laudio_bits, int laudio_channels, |
| 21 | int laudio_codec, int laudio_samplerate, |
| 22 | AudioOutputSource source, bool set_initial_vol, |
| 23 | bool laudio_passthru); |
24 | 24 | virtual ~AudioOutputALSA(); |
25 | 25 | |
26 | 26 | // Volume control |
27 | 27 | virtual int GetVolumeChannel(int channel); // Returns 0-100 |
28 | 28 | virtual void SetVolumeChannel(int channel, int volume); // range 0-100 for vol |
29 | | |
30 | 29 | |
31 | 30 | protected: |
32 | 31 | // You need to implement the following functions |
… |
… |
class AudioOutputALSA : public AudioOutputBase |
35 | 34 | virtual void WriteAudio(unsigned char *aubuf, int size); |
36 | 35 | virtual inline int getSpaceOnSoundcard(void); |
37 | 36 | virtual inline int getBufferedOnSoundcard(void); |
| 37 | vector<int> GetSupportedRates(void); |
38 | 38 | |
39 | 39 | private: |
| 40 | void SetIECStatus(bool audio); |
40 | 41 | inline int SetParameters(snd_pcm_t *handle, |
41 | 42 | snd_pcm_format_t format, unsigned int channels, |
42 | 43 | unsigned int rate, unsigned int buffer_time, |
-
diff --git a/mythtv/libs/libmyth/audiooutputarts.cpp b/mythtv/libs/libmyth/audiooutputarts.cpp
index a257c6b..d7626f2 100644
a
|
b
|
using namespace std; |
10 | 10 | AudioOutputARTS::AudioOutputARTS( |
11 | 11 | QString laudio_main_device, QString laudio_passthru_device, |
12 | 12 | int laudio_bits, int laudio_channels, |
13 | | int laudio_samplerate, AudioOutputSource lsource, |
14 | | bool lset_initial_vol, bool laudio_passthru) : |
| 13 | int laudio_codec, int laudio_samplerate, |
| 14 | AudioOutputSource lsource, bool lset_initial_vol, |
| 15 | bool laudio_passthru) : |
15 | 16 | AudioOutputBase(laudio_main_device, laudio_passthru_device, |
16 | 17 | laudio_bits, laudio_channels, |
17 | 18 | laudio_samplerate, lsource, |
… |
… |
AudioOutputARTS::AudioOutputARTS( |
19 | 20 | pcm_handle(NULL), buff_size(-1), can_hw_pause(false) |
20 | 21 | { |
21 | 22 | // Set everything up |
22 | | Reconfigure(laudio_bits, laudio_channels, |
| 23 | Reconfigure(laudio_bits, laudio_channels, laudio_codec, |
23 | 24 | laudio_samplerate, laudio_passthru); |
24 | 25 | } |
25 | 26 | |
-
diff --git a/mythtv/libs/libmyth/audiooutputarts.h b/mythtv/libs/libmyth/audiooutputarts.h
index ee65be3..d731c31 100644
a
|
b
|
class AudioOutputARTS : public AudioOutputBase |
15 | 15 | { |
16 | 16 | public: |
17 | 17 | AudioOutputARTS(QString main_device, QString passthru_device, |
18 | | int audio_bits, |
19 | | int audio_channels, int audio_samplerate, |
| 18 | int audio_bits, int audio_channels, |
| 19 | int audio_codec, int audio_samplerate, |
20 | 20 | AudioOutputSource source, |
21 | 21 | bool set_initial_vol, bool laudio_passthru); |
22 | 22 | virtual ~AudioOutputARTS(); |
… |
… |
class AudioOutputARTS : public AudioOutputBase |
33 | 33 | virtual void WriteAudio(unsigned char *aubuf, int size); |
34 | 34 | virtual inline int getSpaceOnSoundcard(void); |
35 | 35 | virtual inline int getBufferedOnSoundcard(void); |
36 | | |
37 | | |
| 36 | virtual vector<int> GetSupportedRates(void) |
| 37 | { vector<int> rates; return rates; } |
38 | 38 | |
39 | 39 | private: |
40 | 40 | arts_stream_t pcm_handle; |
-
diff --git a/mythtv/libs/libmyth/audiooutputbase.cpp b/mythtv/libs/libmyth/audiooutputbase.cpp
index 883136d..2cb54ea 100644
a
|
b
|
AudioOutputBase::AudioOutputBase( |
30 | 30 | bool lset_initial_vol, bool /*laudio_passthru*/) : |
31 | 31 | |
32 | 32 | effdsp(0), effdspstretched(0), |
33 | | audio_channels(-1), audio_bytes_per_sample(0), |
34 | | audio_bits(-1), audio_samplerate(-1), |
35 | | audio_buffer_unused(0), |
| 33 | audio_channels(-1), audio_codec(CODEC_ID_NONE), |
| 34 | audio_bytes_per_sample(0), audio_bits(-1), |
| 35 | audio_samplerate(-1), audio_buffer_unused(0), |
36 | 36 | fragment_size(0), soundcard_buffer_size(0), |
37 | 37 | |
38 | 38 | audio_main_device(QDeepCopy<QString>(laudio_main_device)), |
39 | 39 | audio_passthru_device(QDeepCopy<QString>(laudio_passthru_device)), |
40 | | audio_passthru(false), audio_stretchfactor(1.0f), |
| 40 | audio_passthru(false), audio_enc(false), |
| 41 | audio_reenc(false), audio_stretchfactor(1.0f), |
41 | 42 | |
42 | | audio_codec(NULL), |
43 | 43 | source(lsource), killaudio(false), |
44 | 44 | |
45 | 45 | pauseaudio(false), audio_actually_paused(false), |
… |
… |
AudioOutputBase::AudioOutputBase( |
54 | 54 | pSoundStretch(NULL), |
55 | 55 | encoder(NULL), |
56 | 56 | upmixer(NULL), |
| 57 | |
57 | 58 | source_audio_channels(-1), |
| 59 | source_audio_samplerate(0), |
58 | 60 | source_audio_bytes_per_sample(0), |
59 | 61 | needs_upmix(false), |
60 | 62 | surround_mode(FreeSurround::SurroundModePassive), |
| 63 | old_audio_stretchfactor(1.0), |
61 | 64 | |
62 | 65 | blocking(false), |
63 | 66 | |
… |
… |
AudioOutputBase::AudioOutputBase( |
84 | 87 | memset(&audiotime_updated, 0, sizeof(audiotime_updated)); |
85 | 88 | memset(audiobuffer, 0, sizeof(char) * AUDBUFSIZE); |
86 | 89 | configured_audio_channels = gContext->GetNumSetting("MaxChannels", 2); |
| 90 | orig_config_channels = configured_audio_channels; |
| 91 | allow_ac3_passthru = gContext->GetNumSetting("AC3PassThru", false); |
| 92 | src_quality = gContext->GetNumSetting("SRCQuality", 2); |
87 | 93 | |
88 | 94 | // You need to call Reconfigure from your concrete class. |
89 | 95 | // Reconfigure(laudio_bits, laudio_channels, |
… |
… |
void AudioOutputBase::SetStretchFactorLocked(float laudio_stretchfactor) |
124 | 130 | VERBOSE(VB_GENERAL, LOC + QString("Using time stretch %1") |
125 | 131 | .arg(audio_stretchfactor)); |
126 | 132 | pSoundStretch = new soundtouch::SoundTouch(); |
127 | | if (audio_codec) |
128 | | { |
129 | | if (!encoder) |
130 | | { |
131 | | VERBOSE(VB_AUDIO, LOC + |
132 | | QString("Creating Encoder for codec %1 origfs %2") |
133 | | .arg(audio_codec->codec_id) |
134 | | .arg(audio_codec->frame_size)); |
135 | | |
136 | | encoder = new AudioOutputDigitalEncoder(); |
137 | | if (!encoder->Init(audio_codec->codec_id, |
138 | | audio_codec->bit_rate, |
139 | | audio_codec->sample_rate, |
140 | | audio_codec->channels |
141 | | )) |
142 | | { |
143 | | // eeks |
144 | | delete encoder; |
145 | | encoder = NULL; |
146 | | VERBOSE(VB_AUDIO, LOC + |
147 | | QString("Failed to Create Encoder")); |
148 | | } |
149 | | } |
150 | | } |
151 | | if (audio_codec && encoder) |
152 | | { |
153 | | pSoundStretch->setSampleRate(audio_codec->sample_rate); |
154 | | pSoundStretch->setChannels(audio_codec->channels); |
155 | | } |
156 | | else |
157 | | { |
158 | | pSoundStretch->setSampleRate(audio_samplerate); |
159 | | pSoundStretch->setChannels(audio_channels); |
160 | | } |
| 133 | pSoundStretch->setSampleRate(audio_samplerate); |
| 134 | pSoundStretch->setChannels(upmixer ? |
| 135 | configured_audio_channels : source_audio_channels); |
161 | 136 | |
162 | 137 | pSoundStretch->setTempo(audio_stretchfactor); |
163 | 138 | pSoundStretch->setSetting(SETTING_SEQUENCE_MS, 35); |
… |
… |
void AudioOutputBase::SetStretchFactorLocked(float laudio_stretchfactor) |
165 | 140 | // dont need these with only tempo change |
166 | 141 | //pSoundStretch->setPitch(1.0); |
167 | 142 | //pSoundStretch->setRate(1.0); |
168 | | |
169 | 143 | //pSoundStretch->setSetting(SETTING_USE_QUICKSEEK, true); |
170 | 144 | //pSoundStretch->setSetting(SETTING_USE_AA_FILTER, false); |
171 | 145 | } |
… |
… |
float AudioOutputBase::GetStretchFactor(void) |
184 | 158 | return audio_stretchfactor; |
185 | 159 | } |
186 | 160 | |
| 161 | bool AudioOutputBase::ToggleUpmix(void) |
| 162 | { |
| 163 | if (orig_config_channels == 2 || source_audio_channels > 2 || |
| 164 | audio_passthru) |
| 165 | return false; |
| 166 | |
| 167 | if (configured_audio_channels == 6) |
| 168 | configured_audio_channels = 2; |
| 169 | else |
| 170 | configured_audio_channels = 6; |
| 171 | |
| 172 | Reconfigure(audio_bits, source_audio_channels, audio_codec, |
| 173 | source_audio_samplerate, audio_passthru); |
| 174 | return (configured_audio_channels == 6); |
| 175 | } |
| 176 | |
187 | 177 | void AudioOutputBase::Reconfigure(int laudio_bits, int laudio_channels, |
188 | | int laudio_samplerate, bool laudio_passthru, |
189 | | void *laudio_codec) |
| 178 | int laudio_codec, int laudio_samplerate, |
| 179 | bool laudio_passthru) |
190 | 180 | { |
191 | | int codec_id = CODEC_ID_NONE; |
192 | | int lcodec_id = CODEC_ID_NONE; |
193 | | int lcchannels = 0; |
194 | | int cchannels = 0; |
195 | 181 | int lsource_audio_channels = laudio_channels; |
196 | 182 | bool lneeds_upmix = false; |
197 | | |
198 | | if (laudio_codec) |
| 183 | bool laudio_reenc = false; |
| 184 | |
| 185 | // Are we reencoding a timestretched / softvol'd bitstream? |
| 186 | if ((laudio_codec == CODEC_ID_AC3 || laudio_codec == CODEC_ID_DTS) && |
| 187 | !laudio_passthru && allow_ac3_passthru) |
199 | 188 | { |
200 | | lcodec_id = ((AVCodecContext*)laudio_codec)->codec_id; |
201 | | laudio_bits = 16; |
202 | | laudio_channels = 2; |
203 | | lsource_audio_channels = laudio_channels; |
204 | | laudio_samplerate = 48000; |
205 | | lcchannels = ((AVCodecContext*)laudio_codec)->channels; |
| 189 | VERBOSE(VB_AUDIO,LOC + "Reencoding decoded AC3/DTS to AC3"); |
| 190 | laudio_reenc = true; |
206 | 191 | } |
207 | | |
208 | | if (audio_codec) |
209 | | { |
210 | | codec_id = audio_codec->codec_id; |
211 | | cchannels = ((AVCodecContext*)audio_codec)->channels; |
212 | | } |
213 | | |
214 | | if ((configured_audio_channels == 6) && |
215 | | !(laudio_codec || audio_codec)) |
| 192 | // Enough channels? Upmix if not |
| 193 | if (laudio_channels < configured_audio_channels && !laudio_passthru) |
216 | 194 | { |
217 | 195 | laudio_channels = configured_audio_channels; |
218 | 196 | lneeds_upmix = true; |
… |
… |
void AudioOutputBase::Reconfigure(int laudio_bits, int laudio_channels, |
225 | 203 | laudio_samplerate == audio_samplerate && !need_resampler && |
226 | 204 | laudio_passthru == audio_passthru && |
227 | 205 | lneeds_upmix == needs_upmix && |
228 | | lcodec_id == codec_id && lcchannels == cchannels); |
| 206 | laudio_reenc == audio_reenc); |
229 | 207 | bool upmix_deps = |
230 | 208 | (lsource_audio_channels == source_audio_channels); |
231 | 209 | if (general_deps && upmix_deps) |
… |
… |
void AudioOutputBase::Reconfigure(int laudio_bits, int laudio_channels, |
252 | 230 | waud = raud = 0; |
253 | 231 | audio_actually_paused = false; |
254 | 232 | |
255 | | bool redo_stretch = (pSoundStretch && audio_channels != laudio_channels); |
256 | 233 | audio_channels = laudio_channels; |
| 234 | audio_codec = laudio_codec; |
257 | 235 | source_audio_channels = lsource_audio_channels; |
258 | 236 | audio_bits = laudio_bits; |
259 | | audio_samplerate = laudio_samplerate; |
260 | | audio_codec = (AVCodecContext*)laudio_codec; |
| 237 | source_audio_samplerate = audio_samplerate = laudio_samplerate; |
| 238 | audio_reenc = laudio_reenc; |
261 | 239 | audio_passthru = laudio_passthru; |
262 | 240 | needs_upmix = lneeds_upmix; |
263 | 241 | |
… |
… |
void AudioOutputBase::Reconfigure(int laudio_bits, int laudio_channels, |
268 | 246 | Error("AudioOutput only supports 8 or 16bit audio."); |
269 | 247 | return; |
270 | 248 | } |
271 | | audio_bytes_per_sample = audio_channels * audio_bits / 8; |
272 | | source_audio_bytes_per_sample = source_audio_channels * audio_bits / 8; |
273 | | |
| 249 | |
| 250 | VERBOSE(VB_AUDIO, LOC + QString("Original audio format was %1") |
| 251 | .arg(codec_id_string((CodecID)audio_codec))); |
| 252 | |
274 | 253 | need_resampler = false; |
275 | 254 | killaudio = false; |
276 | 255 | pauseaudio = false; |
… |
… |
void AudioOutputBase::Reconfigure(int laudio_bits, int laudio_channels, |
278 | 257 | internal_vol = gContext->GetNumSetting("MythControlsVolume", 0); |
279 | 258 | |
280 | 259 | numlowbuffer = 0; |
| 260 | |
| 261 | // Find out what sample rates we can output (if output layer supports it) |
| 262 | vector<int> rates = GetSupportedRates(); |
| 263 | vector<int>::iterator it; |
| 264 | bool resample = true; |
| 265 | |
| 266 | for (it = rates.begin(); it < rates.end(); it++) |
| 267 | { |
| 268 | VERBOSE(VB_AUDIO, LOC + QString("Sample rate %1 is supported") |
| 269 | .arg(*it)); |
| 270 | if (*it == audio_samplerate) |
| 271 | resample = false; |
| 272 | } |
| 273 | |
| 274 | // Assume 48k if we can't get supported rates |
| 275 | if (rates.empty()) |
| 276 | rates.push_back(48000); |
| 277 | |
| 278 | if (resample) |
| 279 | { |
| 280 | int error; |
| 281 | audio_samplerate = *(rates.end()); |
| 282 | VERBOSE(VB_GENERAL, LOC + QString("Using resampler. From: %1 to %2") |
| 283 | .arg(laudio_samplerate).arg(audio_samplerate)); |
| 284 | src_ctx = src_new(3-src_quality, source_audio_channels, &error); |
| 285 | if (error) |
| 286 | { |
| 287 | Error(QString("Error creating resampler, the error was: %1") |
| 288 | .arg(src_strerror(error)) ); |
| 289 | pthread_mutex_unlock(&avsync_lock); |
| 290 | pthread_mutex_unlock(&audio_buflock); |
| 291 | src_ctx = NULL; |
| 292 | return; |
| 293 | } |
| 294 | src_data.src_ratio = (double) audio_samplerate / laudio_samplerate; |
| 295 | src_data.data_in = src_in; |
| 296 | src_data.data_out = src_out; |
| 297 | src_data.output_frames = 16384*6; |
| 298 | need_resampler = true; |
| 299 | } |
| 300 | |
| 301 | // Encode to AC-3 if not passing thru, there's more than 2 channels |
| 302 | // and we're allowed to passthru AC-3 |
| 303 | if ( |
| 304 | !audio_passthru && allow_ac3_passthru && |
| 305 | (audio_channels > 2 || audio_reenc) |
| 306 | ) |
| 307 | { |
| 308 | VERBOSE(VB_AUDIO, LOC + "Creating AC-3 Encoder"); |
| 309 | encoder = new AudioOutputDigitalEncoder(); |
| 310 | if ( |
| 311 | !encoder->Init( |
| 312 | CODEC_ID_AC3, 448000, audio_samplerate, audio_channels |
| 313 | ) |
| 314 | ) |
| 315 | { |
| 316 | VERBOSE(VB_AUDIO, LOC + "Can't create AC-3 encoder"); |
| 317 | delete encoder; |
| 318 | encoder = NULL; |
| 319 | } |
| 320 | |
| 321 | audio_enc = true; |
| 322 | } |
| 323 | |
| 324 | if(audio_passthru || audio_enc) |
| 325 | // bitstream output - soundcard expects a 2ch 48k stream |
| 326 | audio_channels = 2; |
| 327 | |
| 328 | audio_bytes_per_sample = audio_channels * audio_bits / 8; |
| 329 | source_audio_bytes_per_sample = source_audio_channels * audio_bits / 8; |
281 | 330 | |
282 | 331 | VERBOSE(VB_GENERAL, QString("Opening audio device '%1'. ch %2(%3) sr %4") |
283 | 332 | .arg(audio_main_device).arg(audio_channels) |
… |
… |
void AudioOutputBase::Reconfigure(int laudio_bits, int laudio_channels, |
314 | 363 | current_seconds = -1; |
315 | 364 | source_bitrate = -1; |
316 | 365 | |
317 | | // NOTE: this won't do anything as above samplerate vars are set equal |
318 | | // Check if we need the resampler |
319 | | if (audio_samplerate != laudio_samplerate) |
320 | | { |
321 | | int error; |
322 | | VERBOSE(VB_GENERAL, LOC + QString("Using resampler. From: %1 to %2") |
323 | | .arg(laudio_samplerate).arg(audio_samplerate)); |
324 | | src_ctx = src_new (SRC_SINC_BEST_QUALITY, audio_channels, &error); |
325 | | if (error) |
326 | | { |
327 | | Error(QString("Error creating resampler, the error was: %1") |
328 | | .arg(src_strerror(error)) ); |
329 | | pthread_mutex_unlock(&avsync_lock); |
330 | | pthread_mutex_unlock(&audio_buflock); |
331 | | return; |
332 | | } |
333 | | src_data.src_ratio = (double) audio_samplerate / laudio_samplerate; |
334 | | src_data.data_in = src_in; |
335 | | src_data.data_out = src_out; |
336 | | src_data.output_frames = 16384*6; |
337 | | need_resampler = true; |
338 | | } |
339 | | |
340 | 366 | if (needs_upmix) |
341 | 367 | { |
342 | | VERBOSE(VB_AUDIO, LOC + QString("create upmixer")); |
343 | 368 | if (configured_audio_channels == 6) |
344 | | { |
345 | 369 | surround_mode = gContext->GetNumSetting("AudioUpmixType", 2); |
346 | | } |
347 | 370 | |
348 | 371 | upmixer = new FreeSurround( |
349 | 372 | audio_samplerate, |
… |
… |
void AudioOutputBase::Reconfigure(int laudio_bits, int laudio_channels, |
351 | 374 | (FreeSurround::SurroundMode)surround_mode); |
352 | 375 | |
353 | 376 | VERBOSE(VB_AUDIO, LOC + |
354 | | QString("create upmixer done with surround mode %1") |
| 377 | QString("Create upmixer done with surround mode %1") |
355 | 378 | .arg(surround_mode)); |
356 | 379 | } |
357 | 380 | |
358 | 381 | VERBOSE(VB_AUDIO, LOC + QString("Audio Stretch Factor: %1") |
359 | 382 | .arg(audio_stretchfactor)); |
360 | | VERBOSE(VB_AUDIO, QString("Audio Codec Used: %1") |
361 | | .arg((audio_codec) ? |
362 | | codec_id_string(audio_codec->codec_id) : "not set")); |
363 | 383 | |
364 | | if (redo_stretch) |
365 | | { |
366 | | float laudio_stretchfactor = audio_stretchfactor; |
367 | | delete pSoundStretch; |
368 | | pSoundStretch = NULL; |
369 | | audio_stretchfactor = 0.0f; |
370 | | SetStretchFactorLocked(laudio_stretchfactor); |
371 | | } |
372 | | else |
373 | | { |
374 | | SetStretchFactorLocked(audio_stretchfactor); |
375 | | if (pSoundStretch) |
376 | | { |
377 | | // if its passthru then we need to reencode |
378 | | if (audio_codec) |
379 | | { |
380 | | if (!encoder) |
381 | | { |
382 | | VERBOSE(VB_AUDIO, LOC + |
383 | | QString("Creating Encoder for codec %1") |
384 | | .arg(audio_codec->codec_id)); |
385 | | |
386 | | encoder = new AudioOutputDigitalEncoder(); |
387 | | if (!encoder->Init(audio_codec->codec_id, |
388 | | audio_codec->bit_rate, |
389 | | audio_codec->sample_rate, |
390 | | audio_codec->channels |
391 | | )) |
392 | | { |
393 | | // eeks |
394 | | delete encoder; |
395 | | encoder = NULL; |
396 | | VERBOSE(VB_AUDIO, LOC + "Failed to Create Encoder"); |
397 | | } |
398 | | } |
399 | | } |
400 | | if (audio_codec && encoder) |
401 | | { |
402 | | pSoundStretch->setSampleRate(audio_codec->sample_rate); |
403 | | pSoundStretch->setChannels(audio_codec->channels); |
404 | | } |
405 | | else |
406 | | { |
407 | | pSoundStretch->setSampleRate(audio_samplerate); |
408 | | pSoundStretch->setChannels(audio_channels); |
409 | | } |
410 | | } |
411 | | } |
| 384 | SetStretchFactorLocked(old_audio_stretchfactor); |
412 | 385 | |
413 | 386 | // Setup visualisations, zero the visualisations buffers |
414 | 387 | prepareVisuals(); |
… |
… |
void AudioOutputBase::StopOutputThread(void) |
451 | 424 | void AudioOutputBase::KillAudio() |
452 | 425 | { |
453 | 426 | killAudioLock.lock(); |
454 | | |
455 | 427 | VERBOSE(VB_AUDIO, LOC + "Killing AudioOutputDSP"); |
456 | 428 | killaudio = true; |
457 | 429 | StopOutputThread(); |
| 430 | |
| 431 | pthread_mutex_lock(&audio_buflock); |
458 | 432 | |
459 | 433 | // Close resampler? |
460 | 434 | if (src_ctx) |
| 435 | { |
461 | 436 | src_delete(src_ctx); |
| 437 | src_ctx = NULL; |
| 438 | } |
| 439 | |
462 | 440 | need_resampler = false; |
463 | 441 | |
464 | 442 | // close sound stretcher |
… |
… |
void AudioOutputBase::KillAudio() |
466 | 444 | { |
467 | 445 | delete pSoundStretch; |
468 | 446 | pSoundStretch = NULL; |
| 447 | old_audio_stretchfactor = audio_stretchfactor; |
| 448 | audio_stretchfactor = 1.0; |
469 | 449 | } |
470 | 450 | |
471 | 451 | if (encoder) |
… |
… |
void AudioOutputBase::KillAudio() |
480 | 460 | upmixer = NULL; |
481 | 461 | } |
482 | 462 | needs_upmix = false; |
| 463 | audio_enc = false; |
483 | 464 | |
484 | 465 | CloseDevice(); |
485 | 466 | |
| 467 | pthread_mutex_unlock(&audio_buflock); |
486 | 468 | killAudioLock.unlock(); |
487 | 469 | } |
488 | 470 | |
… |
… |
int AudioOutputBase::GetAudiotime(void) |
591 | 573 | ret += (now.tv_usec - audiotime_updated.tv_usec) / 1000; |
592 | 574 | ret = (long long)(ret * audio_stretchfactor); |
593 | 575 | |
594 | | #if 1 |
595 | 576 | VERBOSE(VB_AUDIO|VB_TIMESTAMP, |
596 | 577 | QString("GetAudiotime now=%1.%2, set=%3.%4, ret=%5, audt=%6 sf=%7") |
597 | 578 | .arg(now.tv_sec).arg(now.tv_usec) |
… |
… |
int AudioOutputBase::GetAudiotime(void) |
600 | 581 | .arg(audiotime) |
601 | 582 | .arg(audio_stretchfactor) |
602 | 583 | ); |
603 | | #endif |
604 | 584 | |
605 | 585 | ret += audiotime; |
606 | 586 | |
… |
… |
void AudioOutputBase::SetAudiotime(void) |
638 | 618 | |
639 | 619 | soundcard_buffer = getBufferedOnSoundcard(); // bytes |
640 | 620 | totalbuffer = audiolen(false) + soundcard_buffer; |
641 | | |
| 621 | |
642 | 622 | // include algorithmic latencies |
643 | 623 | if (pSoundStretch) |
644 | | { |
645 | | // add the effect of any unused but processed samples, |
646 | | // AC3 reencode does this |
647 | | totalbuffer += (int)(pSoundStretch->numSamples() * |
648 | | audio_bytes_per_sample); |
649 | | // add the effect of unprocessed samples in time stretch algo |
650 | 624 | totalbuffer += (int)((pSoundStretch->numUnprocessedSamples() * |
651 | 625 | audio_bytes_per_sample) / audio_stretchfactor); |
652 | | } |
653 | 626 | |
654 | 627 | if (upmixer && needs_upmix) |
655 | | { |
656 | 628 | totalbuffer += upmixer->sampleLatency() * audio_bytes_per_sample; |
657 | | } |
| 629 | |
| 630 | if (encoder) |
| 631 | totalbuffer += encoder->Buffered(); |
658 | 632 | |
659 | 633 | audiotime = audbuf_timecode - (int)(totalbuffer * 100000.0 / |
660 | 634 | (audio_bytes_per_sample * effdspstretched)); |
661 | 635 | |
662 | 636 | gettimeofday(&audiotime_updated, NULL); |
663 | | #if 1 |
| 637 | |
664 | 638 | VERBOSE(VB_AUDIO|VB_TIMESTAMP, |
665 | 639 | QString("SetAudiotime set=%1.%2, audt=%3 atc=%4 " |
666 | 640 | "tb=%5 sb=%6 eds=%7 abps=%8 sf=%9") |
… |
… |
void AudioOutputBase::SetAudiotime(void) |
672 | 646 | .arg(effdspstretched) |
673 | 647 | .arg(audio_bytes_per_sample) |
674 | 648 | .arg(audio_stretchfactor)); |
675 | | #endif |
676 | 649 | |
677 | 650 | pthread_mutex_unlock(&avsync_lock); |
678 | 651 | pthread_mutex_unlock(&audio_buflock); |
… |
… |
bool AudioOutputBase::AddSamples(char *buffers[], int samples, |
686 | 659 | int abps = (encoder) ? |
687 | 660 | encoder->audio_bytes_per_sample : audio_bytes_per_sample; |
688 | 661 | int len = samples * abps; |
689 | | |
| 662 | |
690 | 663 | // Check we have enough space to write the data |
691 | 664 | if (need_resampler && src_ctx) |
692 | 665 | len = (int)ceilf(float(len) * src_data.src_ratio); |
… |
… |
bool AudioOutputBase::AddSamples(char *buffers[], int samples, |
708 | 681 | |
709 | 682 | return false; // would overflow |
710 | 683 | } |
| 684 | |
| 685 | pthread_mutex_lock(&audio_buflock); |
711 | 686 | |
712 | 687 | // resample input if necessary |
713 | 688 | if (need_resampler && src_ctx) |
… |
… |
bool AudioOutputBase::AddSamples(char *buffers[], int samples, |
741 | 716 | // Call our function to do the work |
742 | 717 | _AddSamples(buffers, false, samples, timecode); |
743 | 718 | } |
| 719 | |
| 720 | pthread_mutex_unlock(&audio_buflock); |
744 | 721 | |
745 | 722 | return true; |
746 | 723 | } |
… |
… |
bool AudioOutputBase::AddSamples(char *buffer, int samples, long long timecode) |
753 | 730 | int abps = (encoder) ? |
754 | 731 | encoder->audio_bytes_per_sample : audio_bytes_per_sample; |
755 | 732 | int len = samples * abps; |
| 733 | |
| 734 | // Give original samples to mythmusic visualisation |
| 735 | dispatchVisual((unsigned char *)buffer, len, timecode, |
| 736 | source_audio_channels, audio_bits); |
756 | 737 | |
757 | 738 | // Check we have enough space to write the data |
758 | 739 | if (need_resampler && src_ctx) |
… |
… |
bool AudioOutputBase::AddSamples(char *buffer, int samples, long long timecode) |
776 | 757 | .arg(timecode)); |
777 | 758 | return false; // would overflow |
778 | 759 | } |
| 760 | |
| 761 | pthread_mutex_lock(&audio_buflock); |
779 | 762 | |
780 | 763 | // resample input if necessary |
781 | 764 | if (need_resampler && src_ctx) |
… |
… |
bool AudioOutputBase::AddSamples(char *buffer, int samples, long long timecode) |
804 | 787 | // Call our function to do the work |
805 | 788 | _AddSamples(buffer, true, samples, timecode); |
806 | 789 | } |
| 790 | |
| 791 | pthread_mutex_unlock(&audio_buflock); |
807 | 792 | |
808 | 793 | return true; |
809 | 794 | } |
… |
… |
int AudioOutputBase::WaitForFreeSpace(int samples) |
836 | 821 | if (src_ctx) |
837 | 822 | { |
838 | 823 | int error = src_reset(src_ctx); |
839 | | if (error) |
| 824 | if (error) |
| 825 | { |
840 | 826 | VERBOSE(VB_IMPORTANT, LOC_ERR + QString( |
841 | 827 | "Error occured while resetting resampler: %1") |
842 | 828 | .arg(src_strerror(error))); |
| 829 | src_ctx = NULL; |
| 830 | } |
843 | 831 | } |
844 | 832 | } |
845 | 833 | } |
… |
… |
int AudioOutputBase::WaitForFreeSpace(int samples) |
849 | 837 | void AudioOutputBase::_AddSamples(void *buffer, bool interleaved, int samples, |
850 | 838 | long long timecode) |
851 | 839 | { |
852 | | pthread_mutex_lock(&audio_buflock); |
853 | | |
854 | 840 | int len; // = samples * audio_bytes_per_sample; |
855 | 841 | int audio_bytes = audio_bits / 8; |
856 | 842 | int org_waud = waud; |
… |
… |
void AudioOutputBase::_AddSamples(void *buffer, bool interleaved, int samples, |
867 | 853 | .arg(samples * abps) |
868 | 854 | .arg(AUDBUFSIZE-afree).arg(afree).arg(timecode) |
869 | 855 | .arg(needs_upmix)); |
| 856 | |
| 857 | len = WaitForFreeSpace(samples); |
870 | 858 | |
871 | 859 | if (upmixer && needs_upmix) |
872 | 860 | { |
873 | 861 | int out_samples = 0; |
| 862 | org_waud = waud; |
874 | 863 | int step = (interleaved)?source_audio_channels:1; |
875 | | len = WaitForFreeSpace(samples); // test |
| 864 | |
876 | 865 | for (int itemp = 0; itemp < samples; ) |
877 | 866 | { |
878 | | // just in case it does a processing cycle, release the lock |
879 | | // to allow the output loop to do output |
880 | | pthread_mutex_unlock(&audio_buflock); |
881 | 867 | if (audio_bytes == 2) |
882 | 868 | { |
883 | 869 | itemp += upmixer->putSamples( |
… |
… |
void AudioOutputBase::_AddSamples(void *buffer, bool interleaved, int samples, |
894 | 880 | source_audio_channels, |
895 | 881 | (interleaved) ? 0 : samples); |
896 | 882 | } |
897 | | pthread_mutex_lock(&audio_buflock); |
898 | 883 | |
899 | 884 | int copy_samples = upmixer->numSamples(); |
900 | 885 | if (copy_samples) |
… |
… |
void AudioOutputBase::_AddSamples(void *buffer, bool interleaved, int samples, |
913 | 898 | (short*)(audiobuffer), (copy_samples - bdiff_samples)); |
914 | 899 | } |
915 | 900 | else |
916 | | { |
917 | 901 | upmixer->receiveSamples( |
918 | 902 | (short*)(audiobuffer + org_waud), copy_samples); |
919 | | } |
| 903 | |
920 | 904 | org_waud = (org_waud + copy_len) % AUDBUFSIZE; |
921 | 905 | } |
922 | 906 | } |
… |
… |
void AudioOutputBase::_AddSamples(void *buffer, bool interleaved, int samples, |
928 | 912 | } |
929 | 913 | else |
930 | 914 | { |
931 | | len = WaitForFreeSpace(samples); |
932 | | |
933 | 915 | if (interleaved) |
934 | 916 | { |
935 | 917 | char *mybuf = (char*)buffer; |
… |
… |
void AudioOutputBase::_AddSamples(void *buffer, bool interleaved, int samples, |
964 | 946 | } |
965 | 947 | } |
966 | 948 | } |
967 | | |
968 | | if (samples > 0) |
| 949 | |
| 950 | if (samples <= 0) |
| 951 | return; |
| 952 | |
| 953 | if (pSoundStretch) |
969 | 954 | { |
970 | | if (pSoundStretch) |
| 955 | // does not change the timecode, only the number of samples |
| 956 | // back to orig pos |
| 957 | org_waud = waud; |
| 958 | int bdiff = AUDBUFSIZE - org_waud; |
| 959 | int nSamplesToEnd = bdiff/abps; |
| 960 | if (bdiff < len) |
971 | 961 | { |
| 962 | pSoundStretch->putSamples((soundtouch::SAMPLETYPE*) |
| 963 | (audiobuffer + |
| 964 | org_waud), nSamplesToEnd); |
| 965 | pSoundStretch->putSamples((soundtouch::SAMPLETYPE*)audiobuffer, |
| 966 | (len - bdiff) / abps); |
| 967 | } |
| 968 | else |
| 969 | pSoundStretch->putSamples((soundtouch::SAMPLETYPE*) |
| 970 | (audiobuffer + org_waud), |
| 971 | len / abps); |
972 | 972 | |
973 | | // does not change the timecode, only the number of samples |
974 | | // back to orig pos |
975 | | org_waud = waud; |
976 | | int bdiff = AUDBUFSIZE - org_waud; |
977 | | int nSamplesToEnd = bdiff/abps; |
978 | | if (bdiff < len) |
979 | | { |
980 | | pSoundStretch->putSamples((soundtouch::SAMPLETYPE*) |
981 | | (audiobuffer + |
982 | | org_waud), nSamplesToEnd); |
983 | | pSoundStretch->putSamples((soundtouch::SAMPLETYPE*)audiobuffer, |
984 | | (len - bdiff) / abps); |
985 | | } |
986 | | else |
987 | | { |
988 | | pSoundStretch->putSamples((soundtouch::SAMPLETYPE*) |
989 | | (audiobuffer + org_waud), |
990 | | len / abps); |
| 973 | int nSamples = pSoundStretch->numSamples(); |
| 974 | len = WaitForFreeSpace(nSamples); |
| 975 | |
| 976 | while ((nSamples = pSoundStretch->numSamples())) |
| 977 | { |
| 978 | if (nSamples > nSamplesToEnd) |
| 979 | nSamples = nSamplesToEnd; |
| 980 | |
| 981 | nSamples = pSoundStretch->receiveSamples( |
| 982 | (soundtouch::SAMPLETYPE*) |
| 983 | (audiobuffer + org_waud), nSamples |
| 984 | ); |
| 985 | |
| 986 | if (nSamples == nSamplesToEnd) { |
| 987 | org_waud = 0; |
| 988 | nSamplesToEnd = AUDBUFSIZE/abps; |
991 | 989 | } |
992 | | |
993 | | if (encoder) |
994 | | { |
995 | | // pull out a packet's worth and reencode it until we |
996 | | // don't have enough for any more packets |
997 | | soundtouch::SAMPLETYPE *temp_buff = |
998 | | (soundtouch::SAMPLETYPE*)encoder->GetFrameBuffer(); |
999 | | size_t frameSize = encoder->FrameSize()/abps; |
1000 | | |
1001 | | VERBOSE(VB_AUDIO|VB_TIMESTAMP, |
1002 | | QString("_AddSamples Enc sfs=%1 bfs=%2 sss=%3") |
1003 | | .arg(frameSize) |
1004 | | .arg(encoder->FrameSize()) |
1005 | | .arg(pSoundStretch->numSamples())); |
1006 | | |
1007 | | // process the same number of samples as it creates |
1008 | | // a full encoded buffer just like before |
1009 | | while (pSoundStretch->numSamples() >= frameSize) |
1010 | | { |
1011 | | int got = pSoundStretch->receiveSamples( |
1012 | | temp_buff, frameSize); |
1013 | | int amount = encoder->Encode(temp_buff); |
1014 | | |
1015 | | VERBOSE(VB_AUDIO|VB_TIMESTAMP, |
1016 | | QString("_AddSamples Enc bytes=%1 got=%2 left=%3") |
1017 | | .arg(amount) |
1018 | | .arg(got) |
1019 | | .arg(pSoundStretch->numSamples())); |
1020 | | |
1021 | | if (!amount) |
1022 | | continue; |
1023 | | |
1024 | | //len = WaitForFreeSpace(amount); |
1025 | | char *ob = encoder->GetOutBuff(); |
1026 | | if (amount >= bdiff) |
1027 | | { |
1028 | | memcpy(audiobuffer + org_waud, ob, bdiff); |
1029 | | ob += bdiff; |
1030 | | amount -= bdiff; |
1031 | | org_waud = 0; |
1032 | | } |
1033 | | if (amount > 0) |
1034 | | memcpy(audiobuffer + org_waud, ob, amount); |
1035 | | |
1036 | | bdiff = AUDBUFSIZE - amount; |
1037 | | org_waud += amount; |
1038 | | } |
1039 | | } |
1040 | | else |
1041 | | { |
1042 | | int newLen = 0; |
1043 | | int nSamples; |
1044 | | len = WaitForFreeSpace(pSoundStretch->numSamples() * |
1045 | | audio_bytes_per_sample); |
1046 | | do |
1047 | | { |
1048 | | int samplesToGet = len/audio_bytes_per_sample; |
1049 | | if (samplesToGet > nSamplesToEnd) |
1050 | | { |
1051 | | samplesToGet = nSamplesToEnd; |
1052 | | } |
1053 | | |
1054 | | nSamples = pSoundStretch->receiveSamples( |
1055 | | (soundtouch::SAMPLETYPE*) |
1056 | | (audiobuffer + org_waud), samplesToGet); |
1057 | | if (nSamples == nSamplesToEnd) |
1058 | | { |
1059 | | org_waud = 0; |
1060 | | nSamplesToEnd = AUDBUFSIZE/audio_bytes_per_sample; |
1061 | | } |
1062 | | else |
1063 | | { |
1064 | | org_waud += nSamples * audio_bytes_per_sample; |
1065 | | nSamplesToEnd -= nSamples; |
1066 | | } |
1067 | | |
1068 | | newLen += nSamples * audio_bytes_per_sample; |
1069 | | len -= nSamples * audio_bytes_per_sample; |
1070 | | } while (nSamples > 0); |
| 990 | else { |
| 991 | org_waud += nSamples * abps; |
| 992 | nSamplesToEnd -= nSamples; |
1071 | 993 | } |
| 994 | |
1072 | 995 | } |
| 996 | |
| 997 | } |
1073 | 998 | |
1074 | | waud = org_waud; |
1075 | | lastaudiolen = audiolen(false); |
| 999 | // Encode to AC-3? |
| 1000 | if (encoder) |
| 1001 | { |
| 1002 | |
| 1003 | org_waud = waud; |
| 1004 | int bdiff = AUDBUFSIZE - org_waud; |
| 1005 | int to_get = 0; |
1076 | 1006 | |
1077 | | if (timecode < 0) |
| 1007 | if (bdiff < len) |
1078 | 1008 | { |
1079 | | // mythmusic doesn't give timestamps.. |
1080 | | timecode = (int)((samples_buffered * 100000.0) / effdsp); |
| 1009 | encoder->Encode(audiobuffer + org_waud, bdiff); |
| 1010 | to_get = encoder->Encode(audiobuffer, len - bdiff); |
1081 | 1011 | } |
| 1012 | else |
| 1013 | to_get = encoder->Encode(audiobuffer + org_waud, len); |
1082 | 1014 | |
1083 | | samples_buffered += samples; |
1084 | | |
1085 | | /* we want the time at the end -- but the file format stores |
1086 | | time at the start of the chunk. */ |
1087 | | // even with timestretch, timecode is still calculated from original |
1088 | | // sample count |
1089 | | audbuf_timecode = timecode + (int)((samples * 100000.0) / effdsp); |
1090 | | |
1091 | | if (interleaved) |
| 1015 | if (to_get > 0) |
1092 | 1016 | { |
1093 | | dispatchVisual((unsigned char *)buffer, len, timecode, |
1094 | | source_audio_channels, audio_bits); |
| 1017 | |
| 1018 | if (to_get >= bdiff) |
| 1019 | { |
| 1020 | encoder->GetFrames(audiobuffer + org_waud, bdiff); |
| 1021 | to_get -= bdiff; |
| 1022 | org_waud = 0; |
| 1023 | } |
| 1024 | if (to_get > 0) |
| 1025 | encoder->GetFrames(audiobuffer + org_waud, to_get); |
| 1026 | |
| 1027 | org_waud += to_get; |
| 1028 | |
1095 | 1029 | } |
| 1030 | |
1096 | 1031 | } |
1097 | 1032 | |
1098 | | pthread_mutex_unlock(&audio_buflock); |
| 1033 | waud = org_waud; |
| 1034 | lastaudiolen = audiolen(false); |
| 1035 | |
| 1036 | if (timecode < 0) |
| 1037 | // mythmusic doesn't give timestamps.. |
| 1038 | timecode = (int)((samples_buffered * 100000.0) / effdsp); |
| 1039 | |
| 1040 | samples_buffered += samples; |
| 1041 | |
| 1042 | /* we want the time at the end -- but the file format stores |
| 1043 | time at the start of the chunk. */ |
| 1044 | // even with timestretch, timecode is still calculated from original |
| 1045 | // sample count |
| 1046 | audbuf_timecode = timecode + (int)((samples * 100000.0) / effdsp); |
| 1047 | |
1099 | 1048 | } |
1100 | 1049 | |
1101 | 1050 | void AudioOutputBase::Status() |
-
diff --git a/mythtv/libs/libmyth/audiooutputbase.h b/mythtv/libs/libmyth/audiooutputbase.h
index d60c687..bdf808c 100644
a
|
b
|
class AudioOutputBase : public AudioOutput |
47 | 47 | // reconfigure sound out for new params |
48 | 48 | virtual void Reconfigure(int audio_bits, |
49 | 49 | int audio_channels, |
| 50 | int audio_codec, |
50 | 51 | int audio_samplerate, |
51 | | bool audio_passthru, |
52 | | void *audio_codec = NULL); |
| 52 | bool audio_passthru); |
53 | 53 | |
54 | 54 | // do AddSamples calls block? |
55 | 55 | virtual void SetBlocking(bool blocking); |
… |
… |
class AudioOutputBase : public AudioOutput |
59 | 59 | |
60 | 60 | virtual void SetStretchFactor(float factor); |
61 | 61 | virtual float GetStretchFactor(void); |
| 62 | virtual bool ToggleUpmix(void); |
62 | 63 | |
63 | 64 | virtual void Reset(void); |
64 | 65 | |
… |
… |
class AudioOutputBase : public AudioOutput |
97 | 98 | virtual int getBufferedOnSoundcard(void) = 0; |
98 | 99 | virtual int GetVolumeChannel(int channel) = 0; // Returns 0-100 |
99 | 100 | virtual void SetVolumeChannel(int channel, int volume) = 0; // range 0-100 for vol |
| 101 | virtual vector<int> GetSupportedRates(void) = 0; |
100 | 102 | |
101 | 103 | // The following functions may be overridden, but don't need to be |
102 | 104 | virtual bool StartOutputThread(void); |
… |
… |
class AudioOutputBase : public AudioOutput |
129 | 131 | |
130 | 132 | // Basic details about the audio stream |
131 | 133 | int audio_channels; |
| 134 | int audio_codec; |
132 | 135 | int audio_bytes_per_sample; |
133 | 136 | int audio_bits; |
134 | 137 | int audio_samplerate; |
… |
… |
class AudioOutputBase : public AudioOutput |
139 | 142 | QString audio_passthru_device; |
140 | 143 | |
141 | 144 | bool audio_passthru; |
| 145 | bool audio_enc; |
| 146 | bool audio_reenc; |
142 | 147 | |
143 | 148 | float audio_stretchfactor; |
144 | | AVCodecContext *audio_codec; |
145 | 149 | AudioOutputSource source; |
146 | 150 | |
147 | 151 | bool killaudio; |
… |
… |
class AudioOutputBase : public AudioOutput |
151 | 155 | bool buffer_output_data_for_use; // used by AudioOutputNULL |
152 | 156 | |
153 | 157 | int configured_audio_channels; |
| 158 | int orig_config_channels; |
| 159 | int src_quality; |
154 | 160 | |
155 | 161 | private: |
156 | 162 | // resampler |
… |
… |
class AudioOutputBase : public AudioOutput |
167 | 173 | FreeSurround *upmixer; |
168 | 174 | |
169 | 175 | int source_audio_channels; |
| 176 | int source_audio_samplerate; |
170 | 177 | int source_audio_bytes_per_sample; |
171 | 178 | bool needs_upmix; |
172 | 179 | int surround_mode; |
| 180 | bool allow_ac3_passthru; |
| 181 | float old_audio_stretchfactor; |
173 | 182 | |
174 | 183 | bool blocking; // do AddSamples calls block? |
175 | 184 | |
-
diff --git a/mythtv/libs/libmyth/audiooutputca.cpp b/mythtv/libs/libmyth/audiooutputca.cpp
index c90e967..0e10fc0 100644
a
|
b
|
static OSStatus RenderCallbackSPDIF(AudioDeviceID inDevice, |
114 | 114 | AudioOutputCA::AudioOutputCA(QString laudio_main_device, |
115 | 115 | QString laudio_passthru_device, |
116 | 116 | int laudio_bits, int laudio_channels, |
117 | | int laudio_samplerate, |
| 117 | int laudio_codec, int laudio_samplerate, |
118 | 118 | AudioOutputSource lsource, |
119 | 119 | bool lset_initial_vol, bool laudio_passthru) |
120 | 120 | : AudioOutputBase(laudio_main_device, laudio_passthru_device, |
… |
… |
AudioOutputCA::AudioOutputCA(QString laudio_main_device, |
123 | 123 | lset_initial_vol, laudio_passthru), |
124 | 124 | d(new CoreAudioData(this)) |
125 | 125 | { |
126 | | Reconfigure(laudio_bits, laudio_channels, |
| 126 | Reconfigure(laudio_bits, laudio_channels, laudio_codec |
127 | 127 | laudio_samplerate, laudio_passthru); |
128 | 128 | } |
129 | 129 | |
-
diff --git a/mythtv/libs/libmyth/audiooutputca.h b/mythtv/libs/libmyth/audiooutputca.h
index 2fa8920..d5c9464 100644
a
|
b
|
class AudioOutputCA : public AudioOutputBase |
20 | 20 | public: |
21 | 21 | AudioOutputCA(QString laudio_main_device, |
22 | 22 | QString laudio_passthru_device, |
23 | | int laudio_bits, |
24 | | int laudio_channels, int laudio_samplerate, |
| 23 | int laudio_bits, int laudio_channels, |
| 24 | int laudio_codec, int laudio_samplerate, |
25 | 25 | AudioOutputSource lsource, |
26 | 26 | bool lset_initial_vol, bool laudio_passthru); |
27 | 27 | virtual ~AudioOutputCA(); |
… |
… |
protected: |
57 | 57 | |
58 | 58 | virtual bool StartOutputThread(void) { return true; } |
59 | 59 | virtual void StopOutputThread(void) {} |
| 60 | virtual vector<int> GetSupportedRates(void) |
| 61 | { vector<int> rates; return rates; } |
60 | 62 | |
61 | 63 | private: |
62 | 64 | |
-
diff --git a/mythtv/libs/libmyth/audiooutputdigitalencoder.cpp b/mythtv/libs/libmyth/audiooutputdigitalencoder.cpp
index 40c4acb..a349cc3 100644
a
|
b
|
extern "C" { |
27 | 27 | |
28 | 28 | AudioOutputDigitalEncoder::AudioOutputDigitalEncoder(void) : |
29 | 29 | av_context(NULL), |
30 | | outbuf(NULL), |
31 | | outbuf_size(0), |
32 | | frame_buffer(NULL), |
| 30 | outbuflen(0), |
| 31 | inbuflen(0), |
33 | 32 | one_frame_bytes(0) |
34 | 33 | { |
35 | 34 | } |
… |
… |
void AudioOutputDigitalEncoder::Dispose() |
47 | 46 | av_free(av_context); |
48 | 47 | av_context = NULL; |
49 | 48 | } |
50 | | |
51 | | if (outbuf) |
52 | | { |
53 | | delete [] outbuf; |
54 | | outbuf = NULL; |
55 | | outbuf_size = 0; |
56 | | } |
57 | | |
58 | | if (frame_buffer) |
59 | | { |
60 | | delete [] frame_buffer; |
61 | | frame_buffer = NULL; |
62 | | one_frame_bytes = 0; |
63 | | } |
64 | 49 | } |
65 | 50 | |
66 | 51 | //CODEC_ID_AC3 |
67 | 52 | bool AudioOutputDigitalEncoder::Init( |
68 | | CodecID codec_id, int bitrate, int samplerate, int channels) |
| 53 | CodecID codec_id, int bitrate, int samplerate, int channels |
| 54 | ) |
69 | 55 | { |
70 | 56 | AVCodec *codec; |
71 | 57 | int ret; |
… |
… |
bool AudioOutputDigitalEncoder::Init( |
75 | 61 | .arg(bitrate) |
76 | 62 | .arg(samplerate) |
77 | 63 | .arg(channels)); |
78 | | |
79 | | //codec = avcodec_find_encoder(codec_id); |
| 64 | |
| 65 | // We need to do this when called from mythmusic |
| 66 | avcodec_init(); |
| 67 | avcodec_register_all(); |
80 | 68 | // always AC3 as there is no DTS encoder at the moment 2005/1/9 |
81 | 69 | codec = avcodec_find_encoder(CODEC_ID_AC3); |
82 | 70 | if (!codec) |
… |
… |
bool AudioOutputDigitalEncoder::Init( |
105 | 93 | audio_bytes_per_sample = bytes_per_frame; |
106 | 94 | one_frame_bytes = bytes_per_frame * av_context->frame_size; |
107 | 95 | |
108 | | outbuf_size = 16384; // ok for AC3 but DTS? |
109 | | outbuf = new char [outbuf_size]; |
110 | 96 | VERBOSE(VB_AUDIO, QString("DigitalEncoder::Init fs=%1, bpf=%2 ofb=%3") |
111 | 97 | .arg(av_context->frame_size) |
112 | 98 | .arg(bytes_per_frame) |
… |
… |
typedef struct { |
256 | 242 | |
257 | 243 | } AESHeader; |
258 | 244 | |
| 245 | |
| 246 | void reorder_6ch_ac3(void *buf, unsigned int len) { |
| 247 | unsigned short *src = (unsigned short *)buf; |
| 248 | unsigned short tmp; |
| 249 | unsigned int samples = len >> 1; |
| 250 | |
| 251 | for (uint i = 0; i < samples; i += 6) { |
| 252 | tmp = src[i+4]; |
| 253 | src[i+4] = src[i+3]; |
| 254 | src[i+3] = src[i+2]; |
| 255 | src[i+2] = src[i+1]; |
| 256 | src[i+1] = tmp; |
| 257 | } |
| 258 | } |
| 259 | |
259 | 260 | static int encode_frame( |
260 | 261 | bool dts, |
261 | 262 | unsigned char *data, |
262 | | size_t &len) |
| 263 | size_t enc_len) |
263 | 264 | { |
264 | | size_t enc_len; |
265 | 265 | int flags, sample_rate, bit_rate; |
266 | 266 | |
267 | 267 | // we don't do any length/crc validation of the AC3 frame here; presumably |
… |
… |
static int encode_frame( |
273 | 273 | // anything with a bad CRC... |
274 | 274 | |
275 | 275 | uint nr_samples = 0, block_len; |
| 276 | |
276 | 277 | if (dts) |
277 | 278 | { |
278 | 279 | enc_len = dts_syncinfo(data+8, &flags, &sample_rate, &bit_rate); |
… |
… |
static int encode_frame( |
293 | 294 | #endif |
294 | 295 | } |
295 | 296 | |
296 | | if (enc_len == 0 || enc_len > len) |
297 | | { |
298 | | int l = len; |
299 | | len = 0; |
300 | | return l; |
301 | | } |
302 | | |
303 | 297 | enc_len = min((uint)enc_len, block_len - 8); |
304 | | |
| 298 | |
305 | 299 | //uint32_t x = *(uint32_t*)(data+8); |
306 | 300 | // in place swab |
307 | 301 | swab((const char *)data + 8, (char *)data + 8, enc_len); |
… |
… |
static int encode_frame( |
348 | 342 | break; |
349 | 343 | } |
350 | 344 | } |
351 | | data[5] = 0x00; |
| 345 | data[5] = 0; |
352 | 346 | data[6] = (enc_len << 3) & 0xFF; |
353 | 347 | data[7] = (enc_len >> 5) & 0xFF; |
354 | 348 | memset(data + 8 + enc_len, 0, block_len - 8 - enc_len); |
355 | | len = block_len; |
356 | 349 | |
357 | 350 | return enc_len; |
358 | 351 | } |
359 | 352 | |
360 | | // must have exactly 1 frames worth of data |
361 | | size_t AudioOutputDigitalEncoder::Encode(short *buff) |
| 353 | size_t AudioOutputDigitalEncoder::Encode(void *buf, int len) |
362 | 354 | { |
363 | | int encsize = 0; |
364 | 355 | size_t outsize = 0; |
365 | 356 | |
366 | | // put data in the correct spot for encode frame |
367 | | outsize = avcodec_encode_audio( |
368 | | av_context, ((uchar*)outbuf) + 8, outbuf_size - 8, buff); |
| 357 | int fs = FrameSize(); |
| 358 | memcpy(inbuf+inbuflen, buf, len); |
| 359 | inbuflen += len; |
| 360 | int frames = inbuflen / fs; |
369 | 361 | |
370 | | size_t tmpsize = outsize; |
371 | | |
372 | | outsize = MAX_AC3_FRAME_SIZE; |
373 | | encsize = encode_frame( |
374 | | /*av_context->codec_id==CODEC_ID_DTS*/ false, |
375 | | (unsigned char*)outbuf, outsize); |
| 362 | while (frames--) |
| 363 | { |
| 364 | reorder_6ch_ac3(inbuf, fs); |
| 365 | |
| 366 | // put data in the correct spot for encode frame |
| 367 | outsize = avcodec_encode_audio( |
| 368 | av_context, ((uchar*)outbuf) + outbuflen + 8, OUTBUFSIZE - 8, (short int *)inbuf); |
| 369 | |
| 370 | encode_frame( |
| 371 | /*av_context->codec_id==CODEC_ID_DTS*/ false, |
| 372 | (unsigned char*)outbuf + outbuflen, outsize |
| 373 | ); |
| 374 | |
| 375 | outbuflen += MAX_AC3_FRAME_SIZE; |
| 376 | inbuflen -= fs; |
| 377 | memmove(inbuf, inbuf+fs, inbuflen); |
| 378 | } |
376 | 379 | |
377 | | VERBOSE(VB_AUDIO|VB_TIMESTAMP, |
378 | | QString("DigitalEncoder::Encode len1=%1 len2=%2 finallen=%3") |
379 | | .arg(tmpsize).arg(encsize).arg(outsize)); |
| 380 | return outbuflen; |
| 381 | } |
380 | 382 | |
381 | | return outsize; |
| 383 | void AudioOutputDigitalEncoder::GetFrames(void *ptr, int maxlen) |
| 384 | { |
| 385 | int len = (maxlen < outbuflen ? maxlen : outbuflen); |
| 386 | memcpy(ptr, outbuf, len); |
| 387 | outbuflen -= len; |
| 388 | memmove(outbuf, outbuf+len, outbuflen); |
382 | 389 | } |
-
diff --git a/mythtv/libs/libmyth/audiooutputdigitalencoder.h b/mythtv/libs/libmyth/audiooutputdigitalencoder.h
index 8a4689a..0a9f122 100644
a
|
b
|
extern "C" { |
5 | 5 | #include "libavcodec/avcodec.h" |
6 | 6 | }; |
7 | 7 | |
| 8 | #define INBUFSIZE 131072 |
| 9 | #define OUTBUFSIZE 98304 |
| 10 | |
8 | 11 | class AudioOutputDigitalEncoder |
9 | 12 | { |
10 | 13 | public: |
11 | 14 | AudioOutputDigitalEncoder(void); |
12 | 15 | ~AudioOutputDigitalEncoder(); |
13 | 16 | |
14 | | bool Init(CodecID codec_id, int bitrate, int samplerate, int channels); |
| 17 | bool Init(CodecID codec_id, int bitrate, int samplerate, |
| 18 | int channels); |
15 | 19 | void Dispose(void); |
16 | | size_t Encode(short * buff); |
17 | | |
18 | | inline char *GetFrameBuffer(void); |
| 20 | size_t Encode(void *buf, int len); |
| 21 | void GetFrames(void *ptr, int maxlen); |
19 | 22 | size_t FrameSize(void) const { return one_frame_bytes; } |
20 | | char *GetOutBuff(void) const { return outbuf; } |
| 23 | int Buffered(void) const { return inbuflen; } |
21 | 24 | |
22 | 25 | public: |
23 | 26 | size_t audio_bytes_per_sample; |
24 | 27 | |
25 | 28 | private: |
26 | 29 | AVCodecContext *av_context; |
27 | | char *outbuf; |
28 | | int outbuf_size; |
29 | | char *frame_buffer; |
| 30 | char outbuf[OUTBUFSIZE]; |
| 31 | char inbuf[INBUFSIZE]; |
| 32 | int outbuflen; |
| 33 | int inbuflen; |
30 | 34 | size_t one_frame_bytes; |
31 | 35 | }; |
32 | 36 | |
33 | | inline char *AudioOutputDigitalEncoder::GetFrameBuffer(void) |
34 | | { |
35 | | if (!frame_buffer && av_context) |
36 | | frame_buffer = new char [one_frame_bytes]; |
37 | | |
38 | | return frame_buffer; |
39 | | } |
40 | | |
41 | 37 | #endif |
-
diff --git a/mythtv/libs/libmyth/audiooutputdx.cpp b/mythtv/libs/libmyth/audiooutputdx.cpp
index adbbc4f..dad9197 100644
a
|
b
|
DEFINE_GUID( _KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF, WAVE_FORMAT_DOLBY_AC3_SPDIF, |
98 | 98 | AudioOutputDX::AudioOutputDX( |
99 | 99 | QString laudio_main_device, QString laudio_passthru_device, |
100 | 100 | int laudio_bits, int laudio_channels, |
101 | | int laudio_samplerate, AudioOutputSource lsource, |
102 | | bool lset_initial_vol, bool laudio_passthru) : |
| 101 | int laudio_codec, int laudio_samplerate, |
| 102 | AudioOutputSource lsource, bool lset_initial_vol, |
| 103 | bool laudio_passthru) : |
103 | 104 | AudioOutputBase(laudio_main_device, laudio_passthru_device, |
104 | 105 | laudio_bits, laudio_channels, |
105 | 106 | laudio_samplerate, lsource, |
… |
… |
AudioOutputDX::AudioOutputDX( |
121 | 122 | { |
122 | 123 | InitDirectSound(); |
123 | 124 | |
124 | | Reconfigure(laudio_bits, laudio_channels, |
| 125 | Reconfigure(laudio_bits, laudio_channels, laudio_codec |
125 | 126 | laudio_samplerate, laudio_passthru); |
126 | 127 | } |
127 | 128 | |
-
diff --git a/mythtv/libs/libmyth/audiooutputdx.h b/mythtv/libs/libmyth/audiooutputdx.h
index 00978b4..d975c46 100644
a
|
b
|
class AudioOutputDX : public AudioOutputBase |
19 | 19 | public: |
20 | 20 | AudioOutputDX(QString laudio_main_device, |
21 | 21 | QString laudio_passthru_device, |
22 | | int laudio_bits, |
23 | | int laudio_channels, int laudio_samplerate, |
| 22 | int laudio_bits, int laudio_channels, |
| 23 | int laudio_codec, int laudio_samplerate, |
24 | 24 | AudioOutputSource lsource, |
25 | 25 | bool lset_initial_vol, bool laudio_passthru); |
26 | 26 | virtual ~AudioOutputDX(); |
… |
… |
public: |
56 | 56 | // Volume control |
57 | 57 | virtual int GetVolumeChannel(int channel); // Returns 0-100 |
58 | 58 | virtual void SetVolumeChannel(int channel, int volume); // range 0-100 for vol |
| 59 | virtual vector<int> GetSupportedRates(void) |
| 60 | { vector<int> rates; return rates; } |
59 | 61 | |
60 | 62 | private: |
61 | 63 | HINSTANCE dsound_dll; /* handle of the opened dsound dll */ |
-
diff --git a/mythtv/libs/libmyth/audiooutputjack.cpp b/mythtv/libs/libmyth/audiooutputjack.cpp
index f1c62bb..c89a7f9 100644
a
|
b
|
extern "C" |
24 | 24 | AudioOutputJACK::AudioOutputJACK( |
25 | 25 | QString laudio_main_device, QString laudio_passthru_device, |
26 | 26 | int laudio_bits, int laudio_channels, |
27 | | int laudio_samplerate, AudioOutputSource lsource, |
28 | | bool lset_initial_vol, bool laudio_passthru) : |
| 27 | int laudio_codec, int laudio_samplerate, |
| 28 | AudioOutputSource lsource, bool lset_initial_vol, |
| 29 | bool laudio_passthru) : |
29 | 30 | AudioOutputBase(laudio_main_device, laudio_passthru_device, |
30 | 31 | laudio_bits, laudio_channels, |
31 | 32 | laudio_samplerate, lsource, |
… |
… |
AudioOutputJACK::AudioOutputJACK( |
36 | 37 | JACK_Init(); |
37 | 38 | |
38 | 39 | // Set everything up |
39 | | Reconfigure(laudio_bits, laudio_channels, |
| 40 | Reconfigure(laudio_bits, laudio_channels, laudio_codec |
40 | 41 | laudio_samplerate, laudio_passthru); |
41 | 42 | } |
42 | 43 | |
| 44 | vector<int> AudioOutputJACK::GetSupportedRates() |
| 45 | { |
| 46 | const int srates[] = { 8000, 11025, 16000, 22050, 32000, 44100, 48000 }; |
| 47 | vector<int> rates(srates, srates + sizeof(srates) / sizeof(int) ); |
| 48 | unsigned long jack_port_flags = 0; |
| 49 | unsigned int jack_port_name_count = 1; |
| 50 | const char *jack_port_name = audio_main_device.ascii(); |
| 51 | int err = -1; |
| 52 | audioid = -1; |
| 53 | vector<int>::iterator it; |
| 54 | |
| 55 | for (it = rates.begin(); it < rates.end(); it++) |
| 56 | { |
| 57 | err = JACK_OpenEx(&audioid, 16, (unsigned long *)it, |
| 58 | 2, 2, &jack_port_name, jack_port_name_count, |
| 59 | jack_port_flags); |
| 60 | |
| 61 | if (err == 1) |
| 62 | { |
| 63 | Error(QString("Error connecting to jackd: %1. Is it running?") |
| 64 | .arg(audio_main_device)); |
| 65 | rates.clear(); |
| 66 | return rates; |
| 67 | } |
| 68 | else if (err == 2) |
| 69 | rates.erase(it--); |
| 70 | |
| 71 | JACK_Close(audioid); |
| 72 | audioid = -1; |
| 73 | |
| 74 | } |
| 75 | |
| 76 | return rates; |
| 77 | } |
| 78 | |
43 | 79 | AudioOutputJACK::~AudioOutputJACK() |
44 | 80 | { |
45 | 81 | // Close down all audio stuff |
46 | 82 | KillAudio(); |
47 | 83 | } |
48 | 84 | |
| 85 | |
49 | 86 | bool AudioOutputJACK::OpenDevice() |
50 | 87 | { |
51 | 88 | MythTimer timer; |
-
diff --git a/mythtv/libs/libmyth/audiooutputjack.h b/mythtv/libs/libmyth/audiooutputjack.h
index 19ce22a..a0b5b4a 100644
a
|
b
|
class AudioOutputJACK : public AudioOutputBase |
14 | 14 | public: |
15 | 15 | AudioOutputJACK(QString laudio_main_device, |
16 | 16 | QString laudio_passthru_device, |
17 | | int laudio_bits, |
18 | | int laudio_channels, int laudio_samplerate, |
| 17 | int laudio_bits, int laudio_channels, |
| 18 | int laudio_codec, int laudio_samplerate, |
19 | 19 | AudioOutputSource lsource, |
20 | 20 | bool lset_initial_vol, bool laudio_passthru); |
21 | 21 | virtual ~AudioOutputJACK(); |
… |
… |
class AudioOutputJACK : public AudioOutputBase |
32 | 32 | virtual void WriteAudio(unsigned char *aubuf, int size); |
33 | 33 | virtual inline int getSpaceOnSoundcard(void); |
34 | 34 | virtual inline int getBufferedOnSoundcard(void); |
| 35 | virtual vector<int> GetSupportedRates(void); |
35 | 36 | |
36 | 37 | private: |
37 | 38 | |
-
diff --git a/mythtv/libs/libmyth/audiooutputnull.cpp b/mythtv/libs/libmyth/audiooutputnull.cpp
index 190364b..4a79730 100644
a
|
b
|
using namespace std; |
19 | 19 | |
20 | 20 | #include "mythcontext.h" |
21 | 21 | #include "audiooutputnull.h" |
| 22 | #include "avcodec.h" |
22 | 23 | |
23 | 24 | AudioOutputNULL::AudioOutputNULL( |
24 | 25 | QString laudio_main_device, QString laudio_passthru_device, |
25 | 26 | int laudio_bits, int laudio_channels, |
26 | | int laudio_samplerate, AudioOutputSource lsource, |
27 | | bool lset_initial_vol, bool laudio_passthru) : |
| 27 | int laudio_codec, int laudio_samplerate, |
| 28 | AudioOutputSource lsource, bool lset_initial_vol, |
| 29 | bool laudio_passthru) : |
28 | 30 | AudioOutputBase(laudio_main_device, laudio_passthru_device, |
29 | 31 | laudio_bits, laudio_channels, |
30 | 32 | laudio_samplerate, lsource, |
… |
… |
AudioOutputNULL::AudioOutputNULL( |
37 | 39 | { |
38 | 40 | bzero(pcm_output_buffer, sizeof(char) * NULLAUDIO_OUTPUT_BUFFER_SIZE); |
39 | 41 | |
40 | | Reconfigure(laudio_bits, laudio_channels, |
| 42 | Reconfigure(laudio_bits, laudio_channels, laudio_codec, |
41 | 43 | laudio_samplerate, laudio_passthru); |
42 | 44 | } |
43 | 45 | |
-
diff --git a/mythtv/libs/libmyth/audiooutputnull.h b/mythtv/libs/libmyth/audiooutputnull.h
index acaa17a..d7b3c8f 100644
a
|
b
|
class AudioOutputNULL : public AudioOutputBase |
26 | 26 | public: |
27 | 27 | AudioOutputNULL(QString laudio_main_device, |
28 | 28 | QString laudio_passthru_device, |
29 | | int laudio_bits, |
30 | | int laudio_channels, int laudio_samplerate, |
| 29 | int laudio_bits, int laudio_channels, |
| 30 | int laudio_codec, int laudio_samplerate, |
31 | 31 | AudioOutputSource lsource, |
32 | 32 | bool lset_initial_vol, bool laudio_passthru); |
33 | 33 | virtual ~AudioOutputNULL(); |
… |
… |
protected: |
48 | 48 | virtual void WriteAudio(unsigned char *aubuf, int size); |
49 | 49 | virtual inline int getSpaceOnSoundcard(void); |
50 | 50 | virtual inline int getBufferedOnSoundcard(void); |
| 51 | virtual vector<int> GetSupportedRates(void) |
| 52 | { vector<int> rates; return rates; } |
51 | 53 | |
52 | 54 | private: |
53 | 55 | |
-
diff --git a/mythtv/libs/libmyth/audiooutputoss.cpp b/mythtv/libs/libmyth/audiooutputoss.cpp
index 3436579..0f67c6a 100644
a
|
b
|
using namespace std; |
23 | 23 | |
24 | 24 | #include "mythcontext.h" |
25 | 25 | #include "audiooutputoss.h" |
| 26 | #include "avcodec.h" |
26 | 27 | #include "util.h" |
27 | 28 | |
28 | 29 | AudioOutputOSS::AudioOutputOSS( |
29 | 30 | QString laudio_main_device, QString laudio_passthru_device, |
30 | 31 | int laudio_bits, int laudio_channels, |
31 | | int laudio_samplerate, AudioOutputSource lsource, |
32 | | bool lset_initial_vol, bool laudio_passthru) : |
| 32 | int laudio_codec, int laudio_samplerate, |
| 33 | AudioOutputSource lsource, bool lset_initial_vol, |
| 34 | bool laudio_passthru) : |
33 | 35 | AudioOutputBase(laudio_main_device, laudio_passthru_device, |
34 | 36 | laudio_bits, laudio_channels, |
35 | 37 | laudio_samplerate, lsource, |
… |
… |
AudioOutputOSS::AudioOutputOSS( |
38 | 40 | mixerfd(-1), control(SOUND_MIXER_VOLUME) |
39 | 41 | { |
40 | 42 | // Set everything up |
41 | | Reconfigure(laudio_bits, laudio_channels, |
| 43 | Reconfigure(laudio_bits, laudio_channels, laudio_codec, |
42 | 44 | laudio_samplerate, laudio_passthru); |
43 | 45 | } |
44 | 46 | |
… |
… |
AudioOutputOSS::~AudioOutputOSS() |
47 | 49 | KillAudio(); |
48 | 50 | } |
49 | 51 | |
| 52 | vector<int> AudioOutputOSS::GetSupportedRates() |
| 53 | { |
| 54 | const int srates[] = { 8000, 11025, 16000, 22050, 32000, 44100, 48000 }; |
| 55 | vector<int> rates(srates, srates + sizeof(srates) / sizeof(int) ); |
| 56 | audiofd = open(audio_main_device.ascii(), O_WRONLY | O_NONBLOCK); |
| 57 | |
| 58 | if (audiofd < 0) |
| 59 | { |
| 60 | VERBOSE(VB_IMPORTANT, QString("Error opening audio device (%1), the" |
| 61 | " error was: %2").arg(audio_main_device).arg(strerror(errno))); |
| 62 | rates.clear(); |
| 63 | return rates; |
| 64 | } |
| 65 | |
| 66 | vector<int>::iterator it; |
| 67 | |
| 68 | for (it = rates.begin(); it < rates.end(); it++) |
| 69 | if(ioctl(audiofd, SNDCTL_DSP_SPEED, &audio_samplerate) < 0) |
| 70 | rates.erase(it--); |
| 71 | |
| 72 | close(audiofd); |
| 73 | audiofd = -1; |
| 74 | |
| 75 | return rates; |
| 76 | } |
| 77 | |
50 | 78 | bool AudioOutputOSS::OpenDevice() |
51 | 79 | { |
52 | 80 | numbadioctls = 0; |
-
diff --git a/mythtv/libs/libmyth/audiooutputoss.h b/mythtv/libs/libmyth/audiooutputoss.h
index 8efd49d..49bcbb3 100644
a
|
b
|
class AudioOutputOSS : public AudioOutputBase |
14 | 14 | { |
15 | 15 | public: |
16 | 16 | AudioOutputOSS(QString audiodevice, QString passthrudevice, |
17 | | int laudio_bits, |
18 | | int laudio_channels, int laudio_samplerate, |
| 17 | int laudio_bits, int laudio_channels, |
| 18 | int laudio_codec, int laudio_samplerate, |
19 | 19 | AudioOutputSource source, bool set_initial_vol, |
20 | 20 | bool laudio_passthru); |
21 | 21 | virtual ~AudioOutputOSS(); |
… |
… |
protected: |
31 | 31 | virtual void WriteAudio(unsigned char *aubuf, int size); |
32 | 32 | virtual inline int getSpaceOnSoundcard(void); |
33 | 33 | virtual inline int getBufferedOnSoundcard(void); |
| 34 | virtual vector<int> GetSupportedRates(void); |
34 | 35 | |
35 | 36 | private: |
36 | 37 | void VolumeInit(void); |
-
diff --git a/mythtv/libs/libmyth/audiooutputwin.cpp b/mythtv/libs/libmyth/audiooutputwin.cpp
index e051605..79e22f5 100644
a
|
b
|
void CALLBACK AudioOutputWinPrivate::waveOutProc( |
74 | 74 | AudioOutputWin::AudioOutputWin( |
75 | 75 | QString laudio_main_device, QString laudio_passthru_device, |
76 | 76 | int laudio_bits, int laudio_channels, |
77 | | int laudio_samplerate, AudioOutputSource lsource, |
78 | | bool lset_initial_vol, bool laudio_passthru) : |
| 77 | int laudio_codec, int laudio_samplerate, |
| 78 | AudioOutputSource lsource, bool lset_initial_vol, |
| 79 | bool laudio_passthru) : |
79 | 80 | AudioOutputBase(laudio_main_device, laudio_passthru_device, |
80 | 81 | laudio_bits, laudio_channels, |
81 | 82 | laudio_samplerate, lsource, |
… |
… |
AudioOutputWin::AudioOutputWin( |
85 | 86 | m_CurrentPkt(0), |
86 | 87 | m_OutPkts(NULL) |
87 | 88 | { |
88 | | Reconfigure(laudio_bits, laudio_channels, |
| 89 | Reconfigure(laudio_bits, laudio_channels, laudio_codec |
89 | 90 | laudio_samplerate, laudio_passthru); |
90 | 91 | |
91 | 92 | m_OutPkts = (unsigned char**) calloc(kPacketCnt, sizeof(unsigned char*)); |
-
diff --git a/mythtv/libs/libmyth/audiooutputwin.h b/mythtv/libs/libmyth/audiooutputwin.h
index e53a9e8..ea71f99 100644
a
|
b
|
class AudioOutputWin : public AudioOutputBase |
15 | 15 | public: |
16 | 16 | AudioOutputWin(QString laudio_main_device, |
17 | 17 | QString laudio_passthru_device, |
18 | | int laudio_bits, |
19 | | int laudio_channels, int laudio_samplerate, |
| 18 | int laudio_bits, int laudio_channels, |
| 19 | int laudio_codec, int laudio_samplerate, |
20 | 20 | AudioOutputSource lsource, |
21 | 21 | bool lset_initial_vol, bool laudio_passthru); |
22 | 22 | virtual ~AudioOutputWin(); |
… |
… |
class AudioOutputWin : public AudioOutputBase |
31 | 31 | virtual void WriteAudio(unsigned char *aubuf, int size); |
32 | 32 | virtual inline int getSpaceOnSoundcard(void); |
33 | 33 | virtual inline int getBufferedOnSoundcard(void); |
| 34 | virtual vector<int> GetSupportedRates(void) |
| 35 | { vector<int> rates; return rates; } |
34 | 36 | |
35 | 37 | protected: |
36 | 38 | AudioOutputWinPrivate *m_priv; |
-
diff --git a/mythtv/libs/libmythfreesurround/el_processor.cpp b/mythtv/libs/libmythfreesurround/el_processor.cpp
index 8f24737..cc0dbea 100644
a
|
b
|
extern "C" { |
31 | 31 | typedef FFTSample FFTComplexArray[2]; |
32 | 32 | #endif |
33 | 33 | |
34 | | |
35 | 34 | #ifdef USE_FFTW3 |
36 | 35 | #pragma comment (lib,"libfftw3f-3.lib") |
37 | 36 | #endif |
… |
… |
typedef std::complex<float> cfloat; |
40 | 39 | |
41 | 40 | const float PI = 3.141592654; |
42 | 41 | const float epsilon = 0.000001; |
43 | | //const float center_level = 0.5*sqrt(0.5); // gain of the center channel |
44 | | //const float center_level = sqrt(0.5); // gain of the center channel |
45 | | const float center_level = 1.0; // gain of the center channel |
46 | | //const float center_level = 0.5; // gain of the center channel |
47 | | |
48 | | // should be .6-.7 |
49 | | // but with centerlevel 2x what its supposed to be, we halve 0.68 |
50 | | // to keep center from clipping |
51 | | //const float window_gain = 0.34; |
52 | | //const float window_gain = 0.68; |
53 | | const float window_gain = 0.95; // to prive a bit of margin |
| 42 | const float center_level = 0.5*sqrt(0.5); |
54 | 43 | |
55 | 44 | // private implementation of the surround decoder |
56 | 45 | class decoder_impl { |
… |
… |
public: |
98 | 87 | outbuf[c].resize(N); |
99 | 88 | filter[c].resize(N); |
100 | 89 | } |
101 | | // DC component of filters is always 0 |
102 | | for (unsigned c=0;c<5;c++) |
103 | | { |
104 | | filter[c][0] = 0.0; |
105 | | filter[c][1] = 0.0; |
106 | | filter[c][halfN] = 0.0; |
107 | | } |
108 | 90 | sample_rate(48000); |
109 | 91 | // generate the window function (square root of hann, b/c it is applied before and after the transform) |
110 | 92 | wnd.resize(N); |
111 | | // dft normalization included in the window for zero cost scaling |
112 | | // also add a gain factor of *2 due to processing gain in algo (see center_level) |
113 | | surround_gain(1.0); |
| 93 | for (unsigned k=0;k<N;k++) |
| 94 | wnd[k] = sqrt(0.5*(1-cos(2*PI*k/N))/N); |
114 | 95 | current_buf = 0; |
115 | 96 | // set the default coefficients |
116 | 97 | surround_coefficients(0.8165,0.5774); |
… |
… |
public: |
192 | 173 | // set lfe filter params |
193 | 174 | void sample_rate(unsigned int srate) { |
194 | 175 | // lfe filter is just straight through band limited |
195 | | unsigned int cutoff = (250*N)/srate; |
| 176 | unsigned int cutoff = (30*N)/srate; |
196 | 177 | for (unsigned f=0;f<=halfN;f++) { |
197 | | if ((f>=2) && (f<cutoff)) |
198 | | filter[5][f] = 1.0; |
| 178 | if (f<cutoff) |
| 179 | filter[5][f] = 0.5*sqrt(0.5); |
199 | 180 | else |
200 | 181 | filter[5][f] = 0.0; |
201 | 182 | } |
… |
… |
public: |
214 | 195 | E = (o+v)*n; F = (o+u)*n; G = (o-v)*n; H = (o-u)*n; |
215 | 196 | } |
216 | 197 | |
217 | | void surround_gain(float gain) { |
218 | | master_gain = gain * window_gain * 0.5 * 0.25; |
219 | | for (unsigned k=0;k<N;k++) |
220 | | wnd[k] = sqrt(master_gain*(1-cos(2*PI*k/N))/N); |
221 | | } |
222 | | |
223 | 198 | // set the phase shifting mode |
224 | 199 | void phase_mode(unsigned mode) { |
225 | 200 | const float modes[4][2] = {{0,0},{0,PI},{PI,0},{-PI/2,PI/2}}; |
… |
… |
private: |
290 | 265 | |
291 | 266 | // 2. compare amplitude and phase of each DFT bin and produce the X/Y coordinates in the sound field |
292 | 267 | // but dont do DC or N/2 component |
293 | | for (unsigned f=2;f<halfN;f++) { |
| 268 | for (unsigned f=0;f<halfN;f++) { |
294 | 269 | // get left/right amplitudes/phases |
295 | 270 | float ampL = amplitude(dftL[f]), ampR = amplitude(dftR[f]); |
296 | 271 | float phaseL = phase(dftL[f]), phaseR = phase(dftR[f]); |
… |
… |
private: |
305 | 280 | phaseDiff = abs(phaseDiff); |
306 | 281 | |
307 | 282 | if (linear_steering) { |
308 | | /* cfloat w = polar(sqrt(ampL*ampL+ampR*ampR), (phaseL+phaseR)/2); |
309 | | cfloat lt = cfloat(dftL[f][0],dftL[f][1])/w, rt = cfloat(dftR[f][0],dftR[f][1])/w; */ |
310 | | // xfs[f] = -(C*(rt-H) - B*E + F*A + G*(D-lt)) / (G*A - C*E).real(); |
311 | | // yfs[f] = (rt - (xfs[f]*E+H))/(F+xfs[f]*G); |
312 | | |
313 | | /* |
314 | | Problem: |
315 | | This assumes that the values are interpolated linearly between the cardinal points. |
316 | | But this way we have no chance of knowing the average volume... |
317 | | - Can we solve that computing everything under the assumption of normalized volume? |
318 | | No. Seemingly not. |
319 | | - Maybe we should add w explitcitly into the equation and see if we can solve it... |
320 | | */ |
321 | | |
322 | | |
323 | | //cfloat lt(0.5,0),rt(0.5,0); |
324 | | //cfloat x(0,0), y(1,0); |
325 | | /*cfloat p = (C*(rt-H) - B*E + F*A + G*(D-lt)) / (G*A - C*E); |
326 | | cfloat q = B*(rt+H) + F*(D-lt) / (G*A - C*E); |
327 | | cfloat s = sqrt(p*p/4.0f - q); |
328 | | cfloat x = -p; |
329 | | cfloat x1 = -p/2.0f + s; |
330 | | cfloat x2 = -p/2.0f - s; |
331 | | float x = 0; |
332 | | if (x1.real() >= -1 && x1.real() <= 1) |
333 | | x = x1.real(); |
334 | | else if (x2.real() >= -1 && x2.real() <= 1) |
335 | | x = x2.real();*/ |
336 | | |
337 | | //cfloat yp = (rt - (x*E+H))/(F+x*G); |
338 | | //cfloat xp = (lt - (y*B+D))/(A+y*C); |
339 | | |
340 | | /*xfs[f] = x; |
341 | | yfs[f] = y.real();*/ |
342 | | |
343 | 283 | // --- this is the fancy new linear mode --- |
344 | 284 | |
345 | 285 | // get sound field x/y position |
… |
… |
private: |
597 | 537 | float surround_high,surround_low; // high and low surround mixing coefficient (e.g. 0.8165/0.5774) |
598 | 538 | float surround_balance; // the xfs balance that follows from the coeffs |
599 | 539 | float surround_level; // gain for the surround channels (follows from the coeffs |
600 | | float master_gain; // gain for all channels |
601 | 540 | float phase_offsetL, phase_offsetR;// phase shifts to be applied to the rear channels |
602 | 541 | float front_separation; // front stereo separation |
603 | 542 | float rear_separation; // rear stereo separation |
… |
… |
void fsurround_decoder::flush() { impl->flush(); } |
625 | 564 | |
626 | 565 | void fsurround_decoder::surround_coefficients(float a, float b) { impl->surround_coefficients(a,b); } |
627 | 566 | |
628 | | void fsurround_decoder::gain(float gain) { impl->surround_gain(gain); } |
629 | | |
630 | 567 | void fsurround_decoder::phase_mode(unsigned mode) { impl->phase_mode(mode); } |
631 | 568 | |
632 | 569 | void fsurround_decoder::steering_mode(bool mode) { impl->steering_mode(mode); } |
-
diff --git a/mythtv/libs/libmythfreesurround/el_processor.h b/mythtv/libs/libmythfreesurround/el_processor.h
index 021786a..26452f6 100644
a
|
b
|
public: |
47 | 47 | // a is the coefficient of left rear in left total, b is the coefficient of left rear in right total; the same is true for right. |
48 | 48 | void surround_coefficients(float a, float b); |
49 | 49 | |
50 | | // override for master surround gain |
51 | | void gain(float gain); |
52 | | |
53 | 50 | // set the phase shifting mode for decoding |
54 | 51 | // 0 = (+0°,+0°) - music mode |
55 | 52 | // 1 = (+0°,+180°) - PowerDVD compatibility |
-
diff --git a/mythtv/libs/libmythfreesurround/freesurround.cpp b/mythtv/libs/libmythfreesurround/freesurround.cpp
index 07fe0d8..85b4e59 100644
a
|
b
|
using namespace std; |
63 | 63 | const unsigned default_block_size = 8192; |
64 | 64 | // there will be a slider for this in the future |
65 | 65 | //const float master_gain = 1.0; |
66 | | //#define MASTER_GAIN * master_gain |
| 66 | //#define MASTER_GAIN * master_gain |
67 | 67 | #define MASTER_GAIN |
68 | | //const float master_gain = 1.0/(1<<15); |
69 | | //const float inv_master_gain = (1<<15); |
| 68 | //const float inv_master_gain = 1.0; |
70 | 69 | //#define INV_MASTER_GAIN * inv_master_gain |
71 | 70 | #define INV_MASTER_GAIN |
72 | 71 | |
… |
… |
FreeSurround::FreeSurround(uint srate, bool moviemode, SurroundMode smode) : |
191 | 190 | if (moviemode) |
192 | 191 | { |
193 | 192 | params.phasemode = 1; |
194 | | params.center_width = 0; |
195 | | params.gain = 1.0; |
| 193 | params.center_width = 25; |
| 194 | params.dimension = 0.5; |
196 | 195 | } |
197 | 196 | else |
198 | 197 | { |
199 | | params.center_width = 70; |
200 | | // for 50, gain should be about 1.9, c/lr about 2.7 |
201 | | // for 70, gain should be about 3.1, c/lr about 1.5 |
202 | | params.gain = 3.1; |
| 198 | params.center_width = 65; |
| 199 | params.dimension = 0.3; |
203 | 200 | } |
204 | 201 | switch (surround_mode) |
205 | 202 | { |
… |
… |
void FreeSurround::SetParams() |
235 | 232 | decoder->phase_mode(params.phasemode); |
236 | 233 | decoder->surround_coefficients(params.coeff_a, params.coeff_b); |
237 | 234 | decoder->separation(params.front_sep/100.0,params.rear_sep/100.0); |
238 | | decoder->gain(params.gain); |
239 | 235 | } |
240 | 236 | } |
241 | 237 | |
… |
… |
FreeSurround::fsurround_params::fsurround_params( |
249 | 245 | phasemode(0), |
250 | 246 | steering(1), |
251 | 247 | front_sep(100), |
252 | | rear_sep(100), |
253 | | gain(1.0) |
| 248 | rear_sep(100) |
254 | 249 | { |
255 | 250 | } |
256 | 251 | |
… |
… |
void FreeSurround::process_block() |
654 | 649 | { |
655 | 650 | if (decoder) |
656 | 651 | { |
657 | | // actually these params need only be set when they change... but it doesn't hurt |
658 | | #if 0 |
659 | | decoder->steering_mode(params.steering); |
660 | | decoder->phase_mode(params.phasemode); |
661 | | decoder->surround_coefficients(params.coeff_a, params.coeff_b); |
662 | | decoder->separation(params.front_sep/100.0,params.rear_sep/100.0); |
663 | | #endif |
664 | | // decode the bufs->block |
665 | | //decoder->decode(input,output,params.center_width/100.0,params.dimension/100.0); |
666 | | //decoder->decode(output,params.center_width/100.0,params.dimension/100.0); |
667 | 652 | decoder->decode(params.center_width/100.0,params.dimension/100.0); |
668 | 653 | } |
669 | 654 | } |
-
diff --git a/mythtv/libs/libmythfreesurround/freesurround.h b/mythtv/libs/libmythfreesurround/freesurround.h
index 5748864..0f057e3 100644
a
|
b
|
private: |
74 | 74 | fsurround_params(int32_t center_width=100, int32_t dimension=0); |
75 | 75 | } params; |
76 | 76 | |
77 | | // additional settings |
78 | | uint srate; |
79 | | |
80 | | // info about the current setup |
81 | | bool open_; // whether a stream is currently open |
82 | | bool initialized_; // whether the thing is intialized |
83 | | //struct buffers *bufs; // our buffers |
84 | | struct int16buffers *int16bufs; // our buffers |
85 | | class fsurround_decoder *decoder; // the surround decoder |
| 77 | // additional settings |
| 78 | uint srate; |
| 79 | |
| 80 | // info about the current setup |
| 81 | bool open_; // whether a stream is currently open |
| 82 | bool initialized_; // whether the thing is intialized |
| 83 | //struct buffers *bufs; // our buffers |
| 84 | struct int16buffers *int16bufs; // our buffers |
| 85 | class fsurround_decoder *decoder; // the surround decoder |
86 | 86 | int in_count; // amount in lt,rt |
87 | 87 | int out_count; // amount in output bufs |
88 | 88 | bool processed; // whether processing is enabled or not for latency calc |
-
diff --git a/mythtv/libs/libmythsamplerate/samplerate.c b/mythtv/libs/libmythsamplerate/samplerate.c
index d5a5abc..4d74640 100644
a
|
b
|
src_float_to_short_array (const float *in, short *out, int len) |
452 | 452 | { len -- ; |
453 | 453 | |
454 | 454 | scaled_value = in [len] * (8.0 * 0x10000000) ; |
455 | | if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) |
| 455 | if (scaled_value >= (1.0 * 0x7FFFFFFF)) |
456 | 456 | { out [len] = 32767 ; |
457 | 457 | continue ; |
458 | 458 | } ; |
459 | | if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) |
| 459 | if (scaled_value <= (-8.0 * 0x10000000)) |
460 | 460 | { out [len] = -32768 ; |
461 | 461 | continue ; |
462 | 462 | } ; |
-
diff --git a/mythtv/libs/libmythtv/NuppelVideoPlayer.cpp b/mythtv/libs/libmythtv/NuppelVideoPlayer.cpp
index cb660af..a512c26 100644
a
|
b
|
NuppelVideoPlayer::NuppelVideoPlayer(QString inUseID, const ProgramInfo *info) |
207 | 207 | audioOutput(NULL), |
208 | 208 | audio_main_device(QString::null), |
209 | 209 | audio_passthru_device(QString::null), |
210 | | audio_channels(2), audio_bits(-1), |
211 | | audio_samplerate(44100), audio_stretchfactor(1.0f), |
212 | | audio_codec(NULL), |
| 210 | audio_channels(2), audio_codec(0), |
| 211 | audio_bits(-1), audio_samplerate(44100), |
| 212 | audio_stretchfactor(1.0f), |
213 | 213 | // Picture-in-Picture |
214 | 214 | pipplayer(NULL), setpipplayer(NULL), needsetpipplayer(false), |
215 | 215 | // Preview window support |
… |
… |
QString NuppelVideoPlayer::ReinitAudio(void) |
775 | 775 | audioOutput = AudioOutput::OpenAudio(audio_main_device, |
776 | 776 | audio_passthru_device, |
777 | 777 | audio_bits, audio_channels, |
| 778 | audio_codec, |
778 | 779 | audio_samplerate, |
779 | 780 | AUDIOOUTPUT_VIDEO, |
780 | 781 | setVolume, audio_passthru); |
… |
… |
QString NuppelVideoPlayer::ReinitAudio(void) |
803 | 804 | |
804 | 805 | if (audioOutput) |
805 | 806 | { |
806 | | audioOutput->Reconfigure(audio_bits, audio_channels, |
807 | | audio_samplerate, audio_passthru, |
808 | | audio_codec); |
| 807 | audioOutput->Reconfigure(audio_bits, audio_channels, audio_codec, |
| 808 | audio_samplerate, audio_passthru); |
| 809 | if (audio_passthru) |
| 810 | audio_channels = 2; |
809 | 811 | errMsg = audioOutput->GetError(); |
810 | 812 | if (!errMsg.isEmpty()) |
811 | 813 | audioOutput->SetStretchFactor(audio_stretchfactor); |
… |
… |
void NuppelVideoPlayer::StartPlaying(void) |
3709 | 3711 | } |
3710 | 3712 | } |
3711 | 3713 | |
3712 | | void NuppelVideoPlayer::SetAudioParams(int bps, int channels, |
| 3714 | void NuppelVideoPlayer::SetAudioParams(int bps, int channels, int codec, |
3713 | 3715 | int samplerate, bool passthru) |
3714 | 3716 | { |
3715 | 3717 | audio_bits = bps; |
3716 | 3718 | audio_channels = channels; |
| 3719 | audio_codec = codec; |
3717 | 3720 | audio_samplerate = samplerate; |
3718 | 3721 | audio_passthru = passthru; |
3719 | 3722 | } |
3720 | 3723 | |
3721 | | void NuppelVideoPlayer::SetAudioCodec(void *ac) |
3722 | | { |
3723 | | audio_codec = ac; |
3724 | | } |
3725 | | |
3726 | 3724 | void NuppelVideoPlayer::SetEffDsp(int dsprate) |
3727 | 3725 | { |
3728 | 3726 | if (audioOutput) |
-
diff --git a/mythtv/libs/libmythtv/NuppelVideoPlayer.h b/mythtv/libs/libmythtv/NuppelVideoPlayer.h
index 5f3d2ac..58e4695 100644
a
|
b
|
class MPUBLIC NuppelVideoPlayer : public CC608Reader, public CC708Reader |
125 | 125 | void SetAudioStretchFactor(float factor) { audio_stretchfactor = factor; } |
126 | 126 | void SetAudioOutput(AudioOutput *ao) { audioOutput = ao; } |
127 | 127 | void SetAudioInfo(const QString &main, const QString &passthru, uint rate); |
128 | | void SetAudioParams(int bits, int channels, int samplerate, bool passthru); |
| 128 | void SetAudioParams(int bits, int channels, int codec, int samplerate, |
| 129 | bool passthru); |
129 | 130 | void SetEffDsp(int dsprate); |
130 | 131 | void SetAudioCodec(void *ac); |
131 | 132 | |
… |
… |
class MPUBLIC NuppelVideoPlayer : public CC608Reader, public CC708Reader |
682 | 683 | QString audio_main_device; |
683 | 684 | QString audio_passthru_device; |
684 | 685 | int audio_channels; |
| 686 | int audio_codec; |
685 | 687 | int audio_bits; |
686 | 688 | int audio_samplerate; |
687 | 689 | float audio_stretchfactor; |
688 | | void *audio_codec; |
689 | 690 | bool audio_passthru; |
690 | 691 | |
691 | 692 | // Picture-in-Picture |
-
diff --git a/mythtv/libs/libmythtv/avformatdecoder.cpp b/mythtv/libs/libmythtv/avformatdecoder.cpp
index f574bca..972f0fd 100644
a
|
b
|
AvFormatDecoder::AvFormatDecoder(NuppelVideoPlayer *parent, |
411 | 411 | audioSamples(new short int[AVCODEC_MAX_AUDIO_FRAME_SIZE]), |
412 | 412 | allow_ac3_passthru(false), allow_dts_passthru(false), |
413 | 413 | disable_passthru(false), max_channels(2), |
414 | | dummy_frame(NULL), |
| 414 | last_ac3_channels(0), dummy_frame(NULL), |
415 | 415 | // DVD |
416 | 416 | lastdvdtitle(-1), |
417 | 417 | decodeStillFrame(false), |
… |
… |
int AvFormatDecoder::ScanStreams(bool novideo) |
1874 | 1874 | // waiting on audio. |
1875 | 1875 | if (GetNVP()->HasAudioIn() && tracks[kTrackTypeAudio].empty()) |
1876 | 1876 | { |
1877 | | GetNVP()->SetAudioParams(-1, -1, -1, false /* AC3/DTS pass-through */); |
| 1877 | GetNVP()->SetAudioParams(-1, -1, CODEC_ID_NONE, -1, false /* AC3/DTS pass-through */); |
1878 | 1878 | GetNVP()->ReinitAudio(); |
1879 | 1879 | if (ringBuffer && ringBuffer->isDVD()) |
1880 | 1880 | audioIn = AudioInfo(); |
… |
… |
int AvFormatDecoder::AutoSelectAudioTrack(void) |
2839 | 2839 | { |
2840 | 2840 | int idx = atracks[i].av_stream_index; |
2841 | 2841 | AVCodecContext *codec_ctx = ic->streams[idx]->codec; |
2842 | | bool do_ac3_passthru = (allow_ac3_passthru && !transcoding && |
2843 | | !disable_passthru && |
2844 | | (codec_ctx->codec_id == CODEC_ID_AC3)); |
2845 | | bool do_dts_passthru = (allow_dts_passthru && !transcoding && |
2846 | | !disable_passthru && |
2847 | | (codec_ctx->codec_id == CODEC_ID_DTS)); |
2848 | 2842 | AudioInfo item(codec_ctx->codec_id, |
2849 | 2843 | codec_ctx->sample_rate, codec_ctx->channels, |
2850 | | do_ac3_passthru || do_dts_passthru); |
| 2844 | DoPassThrough(codec_ctx)); |
2851 | 2845 | VERBOSE(VB_AUDIO, LOC + " * " + item.toString()); |
2852 | 2846 | } |
2853 | 2847 | #endif |
… |
… |
static void extract_mono_channel(uint channel, AudioInfo *audioInfo, |
2981 | 2975 | bool AvFormatDecoder::GetFrame(int onlyvideo) |
2982 | 2976 | { |
2983 | 2977 | AVPacket *pkt = NULL; |
| 2978 | AC3HeaderInfo hdr; |
2984 | 2979 | int len; |
2985 | 2980 | unsigned char *ptr; |
2986 | 2981 | int data_size = 0; |
… |
… |
bool AvFormatDecoder::GetFrame(int onlyvideo) |
3167 | 3162 | pts = 0; |
3168 | 3163 | |
3169 | 3164 | AVStream *curstream = ic->streams[pkt->stream_index]; |
| 3165 | AVCodecContext *ctx = curstream->codec; |
3170 | 3166 | |
3171 | 3167 | if (pkt->dts != (int64_t)AV_NOPTS_VALUE) |
3172 | 3168 | pts = (long long)(av_q2d(curstream->time_base) * pkt->dts * 1000); |
3173 | 3169 | |
3174 | 3170 | if (ringBuffer->isDVD() && |
3175 | | curstream->codec->codec_type == CODEC_TYPE_VIDEO) |
| 3171 | ctx->codec_type == CODEC_TYPE_VIDEO) |
3176 | 3172 | { |
3177 | 3173 | MpegPreProcessPkt(curstream, pkt); |
3178 | 3174 | |
… |
… |
bool AvFormatDecoder::GetFrame(int onlyvideo) |
3200 | 3196 | |
3201 | 3197 | if (!d->HasMPEG2Dec()) |
3202 | 3198 | { |
3203 | | int current_width = curstream->codec->width; |
| 3199 | int current_width = ctx->width; |
3204 | 3200 | int video_width = GetNVP()->GetVideoSize().width(); |
3205 | 3201 | if (dvd_xvmc_enabled && GetNVP() && GetNVP()->getVideoOutput()) |
3206 | 3202 | { |
… |
… |
bool AvFormatDecoder::GetFrame(int onlyvideo) |
3241 | 3237 | } |
3242 | 3238 | |
3243 | 3239 | if (storevideoframes && |
3244 | | curstream->codec->codec_type == CODEC_TYPE_VIDEO) |
| 3240 | ctx->codec_type == CODEC_TYPE_VIDEO) |
3245 | 3241 | { |
3246 | 3242 | av_dup_packet(pkt); |
3247 | 3243 | storedPackets.append(pkt); |
… |
… |
bool AvFormatDecoder::GetFrame(int onlyvideo) |
3249 | 3245 | continue; |
3250 | 3246 | } |
3251 | 3247 | |
3252 | | if (len > 0 && curstream->codec->codec_type == CODEC_TYPE_VIDEO && |
| 3248 | if (len > 0 && ctx->codec_type == CODEC_TYPE_VIDEO && |
3253 | 3249 | pkt->stream_index == selectedVideoIndex) |
3254 | 3250 | { |
3255 | | AVCodecContext *context = curstream->codec; |
3256 | 3251 | |
3257 | | if (context->codec_id == CODEC_ID_MPEG1VIDEO || |
3258 | | context->codec_id == CODEC_ID_MPEG2VIDEO || |
3259 | | context->codec_id == CODEC_ID_MPEG2VIDEO_XVMC || |
3260 | | context->codec_id == CODEC_ID_MPEG2VIDEO_XVMC_VLD) |
| 3252 | if (ctx->codec_id == CODEC_ID_MPEG1VIDEO || |
| 3253 | ctx->codec_id == CODEC_ID_MPEG2VIDEO || |
| 3254 | ctx->codec_id == CODEC_ID_MPEG2VIDEO_XVMC || |
| 3255 | ctx->codec_id == CODEC_ID_MPEG2VIDEO_XVMC_VLD) |
3261 | 3256 | { |
3262 | 3257 | if (!ringBuffer->isDVD()) |
3263 | 3258 | MpegPreProcessPkt(curstream, pkt); |
3264 | 3259 | } |
3265 | | else if (context->codec_id == CODEC_ID_H264) |
| 3260 | else if (ctx->codec_id == CODEC_ID_H264) |
3266 | 3261 | { |
3267 | 3262 | H264PreProcessPkt(curstream, pkt); |
3268 | 3263 | } |
… |
… |
bool AvFormatDecoder::GetFrame(int onlyvideo) |
3308 | 3303 | } |
3309 | 3304 | |
3310 | 3305 | if (len > 0 && |
3311 | | curstream->codec->codec_type == CODEC_TYPE_DATA && |
3312 | | curstream->codec->codec_id == CODEC_ID_MPEG2VBI) |
| 3306 | ctx->codec_type == CODEC_TYPE_DATA && |
| 3307 | ctx->codec_id == CODEC_ID_MPEG2VBI) |
3313 | 3308 | { |
3314 | 3309 | ProcessVBIDataPacket(curstream, pkt); |
3315 | 3310 | |
… |
… |
bool AvFormatDecoder::GetFrame(int onlyvideo) |
3318 | 3313 | } |
3319 | 3314 | |
3320 | 3315 | if (len > 0 && |
3321 | | curstream->codec->codec_type == CODEC_TYPE_DATA && |
3322 | | curstream->codec->codec_id == CODEC_ID_DVB_VBI) |
| 3316 | ctx->codec_type == CODEC_TYPE_DATA && |
| 3317 | ctx->codec_id == CODEC_ID_DVB_VBI) |
3323 | 3318 | { |
3324 | 3319 | ProcessDVBDataPacket(curstream, pkt); |
3325 | 3320 | |
… |
… |
bool AvFormatDecoder::GetFrame(int onlyvideo) |
3328 | 3323 | } |
3329 | 3324 | |
3330 | 3325 | if (len > 0 && |
3331 | | curstream->codec->codec_type == CODEC_TYPE_DATA && |
3332 | | curstream->codec->codec_id == CODEC_ID_DSMCC_B) |
| 3326 | ctx->codec_type == CODEC_TYPE_DATA && |
| 3327 | ctx->codec_id == CODEC_ID_DSMCC_B) |
3333 | 3328 | { |
3334 | 3329 | ProcessDSMCCPacket(curstream, pkt); |
3335 | 3330 | |
… |
… |
bool AvFormatDecoder::GetFrame(int onlyvideo) |
3349 | 3344 | } |
3350 | 3345 | |
3351 | 3346 | // we don't care about other data streams |
3352 | | if (curstream->codec->codec_type == CODEC_TYPE_DATA) |
| 3347 | if (ctx->codec_type == CODEC_TYPE_DATA) |
3353 | 3348 | { |
3354 | 3349 | av_free_packet(pkt); |
3355 | 3350 | continue; |
3356 | 3351 | } |
3357 | 3352 | |
3358 | | if (!curstream->codec->codec) |
| 3353 | if (!ctx->codec) |
3359 | 3354 | { |
3360 | 3355 | VERBOSE(VB_PLAYBACK, LOC + |
3361 | 3356 | QString("No codec for stream index %1, type(%2) id(%3:%4)") |
3362 | 3357 | .arg(pkt->stream_index) |
3363 | | .arg(codec_type_string(curstream->codec->codec_type)) |
3364 | | .arg(codec_id_string(curstream->codec->codec_id)) |
3365 | | .arg(curstream->codec->codec_id)); |
| 3358 | .arg(codec_type_string(ctx->codec_type)) |
| 3359 | .arg(codec_id_string(ctx->codec_id)) |
| 3360 | .arg(ctx->codec_id)); |
3366 | 3361 | av_free_packet(pkt); |
3367 | 3362 | continue; |
3368 | 3363 | } |
… |
… |
bool AvFormatDecoder::GetFrame(int onlyvideo) |
3371 | 3366 | have_err = false; |
3372 | 3367 | |
3373 | 3368 | avcodeclock.lock(); |
3374 | | int ctype = curstream->codec->codec_type; |
| 3369 | int ctype = ctx->codec_type; |
3375 | 3370 | int audIdx = selectedTrack[kTrackTypeAudio].av_stream_index; |
3376 | 3371 | int audSubIdx = selectedTrack[kTrackTypeAudio].av_substream_index; |
3377 | 3372 | int subIdx = selectedTrack[kTrackTypeSubtitle].av_stream_index; |
… |
… |
bool AvFormatDecoder::GetFrame(int onlyvideo) |
3396 | 3391 | |
3397 | 3392 | // detect switches between stereo and dual languages |
3398 | 3393 | bool wasDual = audSubIdx != -1; |
3399 | | bool isDual = curstream->codec->avcodec_dual_language; |
| 3394 | bool isDual = ctx->avcodec_dual_language; |
3400 | 3395 | if ((wasDual && !isDual) || (!wasDual && isDual)) |
3401 | 3396 | { |
3402 | 3397 | SetupAudioStreamSubIndexes(audIdx); |
3403 | 3398 | reselectAudioTrack = true; |
3404 | 3399 | } |
3405 | 3400 | |
3406 | | bool do_ac3_passthru = |
3407 | | (allow_ac3_passthru && !transcoding && |
3408 | | (curstream->codec->codec_id == CODEC_ID_AC3)); |
3409 | | bool do_dts_passthru = |
3410 | | (allow_dts_passthru && !transcoding && |
3411 | | (curstream->codec->codec_id == CODEC_ID_DTS)); |
3412 | | bool using_passthru = do_ac3_passthru || do_dts_passthru; |
3413 | | |
3414 | 3401 | // detect channels on streams that need |
3415 | 3402 | // to be decoded before we can know this |
3416 | 3403 | bool already_decoded = false; |
3417 | | if (!curstream->codec->channels) |
| 3404 | if (!ctx->channels) |
3418 | 3405 | { |
3419 | 3406 | QMutexLocker locker(&avcodeclock); |
3420 | 3407 | VERBOSE(VB_IMPORTANT, LOC + |
3421 | 3408 | QString("Setting channels to %1") |
3422 | 3409 | .arg(audioOut.channels)); |
3423 | 3410 | |
3424 | | if (using_passthru) |
| 3411 | if (DoPassThrough(ctx)) |
3425 | 3412 | { |
3426 | 3413 | // for passthru let it select the max number |
3427 | 3414 | // of channels |
3428 | | curstream->codec->channels = 0; |
3429 | | curstream->codec->request_channels = 0; |
| 3415 | ctx->channels = 0; |
| 3416 | ctx->request_channels = 0; |
3430 | 3417 | } |
3431 | 3418 | else |
3432 | 3419 | { |
3433 | | curstream->codec->channels = audioOut.channels; |
3434 | | curstream->codec->request_channels = |
| 3420 | ctx->channels = audioOut.channels; |
| 3421 | ctx->request_channels = |
3435 | 3422 | audioOut.channels; |
3436 | 3423 | } |
3437 | 3424 | ret = avcodec_decode_audio( |
3438 | | curstream->codec, audioSamples, |
| 3425 | ctx, audioSamples, |
3439 | 3426 | &data_size, ptr, len); |
3440 | 3427 | already_decoded = true; |
3441 | 3428 | |
3442 | | reselectAudioTrack |= curstream->codec->channels; |
| 3429 | reselectAudioTrack |= ctx->channels; |
| 3430 | } |
| 3431 | |
| 3432 | if (ctx->codec_id == CODEC_ID_AC3 && |
| 3433 | !ff_ac3_parse_header(ptr, &hdr)) |
| 3434 | { |
| 3435 | if (hdr.channels != last_ac3_channels) |
| 3436 | { |
| 3437 | last_ac3_channels = ctx->channels = hdr.channels; |
| 3438 | SetupAudioStream(); |
| 3439 | } |
3443 | 3440 | } |
3444 | 3441 | |
3445 | 3442 | if (reselectAudioTrack) |
… |
… |
bool AvFormatDecoder::GetFrame(int onlyvideo) |
3455 | 3452 | .av_stream_index; |
3456 | 3453 | audSubIdx = selectedTrack[kTrackTypeAudio] |
3457 | 3454 | .av_substream_index; |
| 3455 | ctx = curstream->codec; |
3458 | 3456 | } |
3459 | 3457 | |
3460 | 3458 | if ((onlyvideo > 0) || (pkt->stream_index != audIdx)) |
… |
… |
bool AvFormatDecoder::GetFrame(int onlyvideo) |
3486 | 3484 | if (audioOut.do_passthru) |
3487 | 3485 | { |
3488 | 3486 | data_size = pkt->size; |
3489 | | bool dts = CODEC_ID_DTS == curstream->codec->codec_id; |
| 3487 | bool dts = CODEC_ID_DTS == ctx->codec_id; |
3490 | 3488 | ret = encode_frame(dts, ptr, len, |
3491 | 3489 | audioSamples, data_size); |
3492 | 3490 | } |
3493 | 3491 | else |
3494 | 3492 | { |
3495 | | AVCodecContext *ctx = curstream->codec; |
3496 | | |
3497 | 3493 | if ((ctx->channels == 0) || |
3498 | 3494 | (ctx->channels > audioOut.channels)) |
3499 | 3495 | { |
… |
… |
bool AvFormatDecoder::GetFrame(int onlyvideo) |
3502 | 3498 | |
3503 | 3499 | if (!already_decoded) |
3504 | 3500 | { |
3505 | | curstream->codec->request_channels = |
3506 | | audioOut.channels; |
| 3501 | ctx->request_channels = audioOut.channels; |
3507 | 3502 | ret = avcodec_decode_audio( |
3508 | 3503 | ctx, audioSamples, &data_size, ptr, len); |
3509 | 3504 | } |
… |
… |
bool AvFormatDecoder::GetFrame(int onlyvideo) |
3520 | 3515 | audIdx = -1; |
3521 | 3516 | AutoSelectAudioTrack(); |
3522 | 3517 | data_size = 0; |
| 3518 | ctx = curstream->codec; |
3523 | 3519 | } |
3524 | 3520 | } |
3525 | 3521 | avcodeclock.unlock(); |
… |
… |
bool AvFormatDecoder::GetFrame(int onlyvideo) |
3537 | 3533 | |
3538 | 3534 | // calc for next frame |
3539 | 3535 | lastapts += (long long)((double)(data_size * 1000) / |
3540 | | (curstream->codec->channels * 2) / |
3541 | | curstream->codec->sample_rate); |
| 3536 | (ctx->channels * 2) / ctx->sample_rate); |
3542 | 3537 | |
3543 | 3538 | VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, |
3544 | 3539 | LOC + QString("audio timecode %1 %2 %3 %4") |
… |
… |
bool AvFormatDecoder::GetFrame(int onlyvideo) |
3598 | 3593 | continue; |
3599 | 3594 | } |
3600 | 3595 | |
3601 | | AVCodecContext *context = curstream->codec; |
3602 | 3596 | AVFrame mpa_pic; |
3603 | 3597 | bzero(&mpa_pic, sizeof(AVFrame)); |
3604 | 3598 | |
… |
… |
bool AvFormatDecoder::GetFrame(int onlyvideo) |
3613 | 3607 | // HACK |
3614 | 3608 | while (!gotpicture && count < 5) |
3615 | 3609 | { |
3616 | | ret = d->DecodeMPEG2Video(context, &mpa_pic, |
| 3610 | ret = d->DecodeMPEG2Video(ctx, &mpa_pic, |
3617 | 3611 | &gotpicture, ptr, len); |
3618 | 3612 | count++; |
3619 | 3613 | } |
3620 | 3614 | } |
3621 | 3615 | else |
3622 | 3616 | { |
3623 | | ret = d->DecodeMPEG2Video(context, &mpa_pic, |
| 3617 | ret = d->DecodeMPEG2Video(ctx, &mpa_pic, |
3624 | 3618 | &gotpicture, ptr, len); |
3625 | 3619 | } |
3626 | 3620 | } |
3627 | 3621 | else |
3628 | 3622 | { |
3629 | | ret = avcodec_decode_video(context, &mpa_pic, |
| 3623 | ret = avcodec_decode_video(ctx, &mpa_pic, |
3630 | 3624 | &gotpicture, ptr, len); |
3631 | 3625 | // Reparse it to not drop the DVD still frame |
3632 | 3626 | if (decodeStillFrame) |
3633 | | ret = avcodec_decode_video(context, &mpa_pic, |
| 3627 | ret = avcodec_decode_video(ctx, &mpa_pic, |
3634 | 3628 | &gotpicture, ptr, len); |
3635 | 3629 | } |
3636 | 3630 | avcodeclock.unlock(); |
… |
… |
bool AvFormatDecoder::GetFrame(int onlyvideo) |
3697 | 3691 | |
3698 | 3692 | img_convert(&tmppicture, PIX_FMT_YUV420P, |
3699 | 3693 | (AVPicture *)&mpa_pic, |
3700 | | context->pix_fmt, |
3701 | | context->width, |
3702 | | context->height); |
| 3694 | ctx->pix_fmt, |
| 3695 | ctx->width, |
| 3696 | ctx->height); |
3703 | 3697 | |
3704 | 3698 | if (xf) |
3705 | 3699 | { |
… |
… |
bool AvFormatDecoder::GetFrame(int onlyvideo) |
3722 | 3716 | (temppts + 10000 > lastvpts || temppts < 0)) |
3723 | 3717 | { |
3724 | 3718 | temppts = lastvpts; |
3725 | | temppts += (long long)(1000 * av_q2d(context->time_base)); |
| 3719 | temppts += (long long)(1000 * av_q2d(ctx->time_base)); |
3726 | 3720 | // MPEG2 frames can be repeated, update pts accordingly |
3727 | 3721 | temppts += (long long)(mpa_pic.repeat_pict * 500 |
3728 | | * av_q2d(curstream->codec->time_base)); |
| 3722 | * av_q2d(ctx->time_base)); |
3729 | 3723 | } |
3730 | 3724 | |
3731 | 3725 | VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, LOC + |
… |
… |
bool AvFormatDecoder::GetFrame(int onlyvideo) |
3761 | 3755 | picframe->frameNumber = framesPlayed; |
3762 | 3756 | GetNVP()->ReleaseNextVideoFrame(picframe, temppts); |
3763 | 3757 | if (d->HasMPEG2Dec() && mpa_pic.data[3]) |
3764 | | context->release_buffer(context, &mpa_pic); |
| 3758 | ctx->release_buffer(ctx, &mpa_pic); |
3765 | 3759 | |
3766 | 3760 | decoded_video_frame = picframe; |
3767 | 3761 | gotvideo = 1; |
… |
… |
bool AvFormatDecoder::GetFrame(int onlyvideo) |
3820 | 3814 | } |
3821 | 3815 | default: |
3822 | 3816 | { |
3823 | | AVCodecContext *enc = curstream->codec; |
3824 | 3817 | VERBOSE(VB_IMPORTANT, LOC_ERR + |
3825 | 3818 | QString("Decoding - id(%1) type(%2)") |
3826 | | .arg(codec_id_string(enc->codec_id)) |
3827 | | .arg(codec_type_string(enc->codec_type))); |
| 3819 | .arg(codec_id_string(ctx->codec_id)) |
| 3820 | .arg(codec_type_string(ctx->codec_type))); |
3828 | 3821 | have_err = true; |
3829 | 3822 | break; |
3830 | 3823 | } |
… |
… |
void AvFormatDecoder::SetDisablePassThrough(bool disable) |
3969 | 3962 | } |
3970 | 3963 | } |
3971 | 3964 | |
| 3965 | bool AvFormatDecoder::DoPassThrough(const AVCodecContext *ctx) |
| 3966 | { |
| 3967 | bool passthru = false; |
| 3968 | |
| 3969 | if (ctx->codec_id == CODEC_ID_AC3) |
| 3970 | passthru = allow_ac3_passthru && |
| 3971 | ctx->channels >= (int)max_channels; |
| 3972 | else if (ctx->codec_id == CODEC_ID_DTS) |
| 3973 | passthru = allow_dts_passthru; |
| 3974 | |
| 3975 | passthru &= !transcoding && !disable_passthru; |
| 3976 | // Don't know any cards that support spdif clocked at < 44100 |
| 3977 | // Some US cable transmissions have 2ch 32k AC-3 streams |
| 3978 | passthru &= ctx->sample_rate >= 44100; |
| 3979 | |
| 3980 | return passthru; |
| 3981 | } |
| 3982 | |
| 3983 | |
3972 | 3984 | /** \fn AvFormatDecoder::SetupAudioStream(void) |
3973 | 3985 | * \brief Reinitializes audio if it needs to be reinitialized. |
3974 | 3986 | * |
… |
… |
bool AvFormatDecoder::SetupAudioStream(void) |
3982 | 3994 | AVStream *curstream = NULL; |
3983 | 3995 | AVCodecContext *codec_ctx = NULL; |
3984 | 3996 | AudioInfo old_in = audioIn; |
3985 | | AudioInfo old_out = audioOut; |
3986 | 3997 | bool using_passthru = false; |
3987 | 3998 | |
3988 | 3999 | if ((currentTrack[kTrackTypeAudio] >= 0) && |
… |
… |
bool AvFormatDecoder::SetupAudioStream(void) |
3994 | 4005 | assert(curstream); |
3995 | 4006 | assert(curstream->codec); |
3996 | 4007 | codec_ctx = curstream->codec; |
3997 | | bool do_ac3_passthru = (allow_ac3_passthru && !transcoding && |
3998 | | (codec_ctx->codec_id == CODEC_ID_AC3)); |
3999 | | bool do_dts_passthru = (allow_dts_passthru && !transcoding && |
4000 | | (codec_ctx->codec_id == CODEC_ID_DTS)); |
4001 | | using_passthru = do_ac3_passthru || do_dts_passthru; |
4002 | | info = AudioInfo(codec_ctx->codec_id, |
4003 | | codec_ctx->sample_rate, codec_ctx->channels, |
4004 | | using_passthru && !disable_passthru); |
| 4008 | using_passthru = DoPassThrough(codec_ctx); |
| 4009 | info = AudioInfo(codec_ctx->codec_id, codec_ctx->sample_rate, |
| 4010 | codec_ctx->channels, using_passthru); |
4005 | 4011 | } |
4006 | 4012 | |
4007 | 4013 | if (info == audioIn) |
… |
… |
bool AvFormatDecoder::SetupAudioStream(void) |
4012 | 4018 | QString("audio track #%1").arg(currentTrack[kTrackTypeAudio]+1)); |
4013 | 4019 | |
4014 | 4020 | audioOut = audioIn = info; |
4015 | | if (using_passthru) |
4016 | | { |
4017 | | // A passthru stream looks like a 48KHz 2ch (@ 16bit) to the sound card |
4018 | | AudioInfo digInfo = audioOut; |
4019 | | if (!disable_passthru) |
4020 | | { |
4021 | | digInfo.channels = 2; |
4022 | | digInfo.sample_rate = 48000; |
4023 | | digInfo.sample_size = 4; |
4024 | | } |
4025 | | if (audioOut.channels > (int) max_channels) |
4026 | | { |
4027 | | audioOut.channels = (int) max_channels; |
4028 | | audioOut.sample_size = audioOut.channels * 2; |
4029 | | codec_ctx->channels = audioOut.channels; |
4030 | | } |
4031 | | VERBOSE(VB_AUDIO, LOC + "Audio format changed digital passthrough " + |
4032 | | QString("%1\n\t\t\tfrom %2 ; %3\n\t\t\tto %4 ; %5") |
4033 | | .arg(digInfo.toString()) |
4034 | | .arg(old_in.toString()).arg(old_out.toString()) |
4035 | | .arg(audioIn.toString()).arg(audioOut.toString())); |
4036 | | |
4037 | | if (digInfo.sample_rate > 0) |
4038 | | GetNVP()->SetEffDsp(digInfo.sample_rate * 100); |
4039 | | |
4040 | | GetNVP()->SetAudioParams(digInfo.bps(), digInfo.channels, |
4041 | | digInfo.sample_rate, audioIn.do_passthru); |
4042 | | // allow the audio stuff to reencode |
4043 | | GetNVP()->SetAudioCodec(codec_ctx); |
4044 | | GetNVP()->ReinitAudio(); |
4045 | | return true; |
4046 | | } |
4047 | | else |
| 4021 | |
| 4022 | if (!using_passthru && audioOut.channels > (int)max_channels) |
4048 | 4023 | { |
4049 | | if (audioOut.channels > (int) max_channels) |
4050 | | { |
4051 | | audioOut.channels = (int) max_channels; |
4052 | | audioOut.sample_size = audioOut.channels * 2; |
4053 | | codec_ctx->channels = audioOut.channels; |
4054 | | } |
| 4024 | audioOut.channels = (int)max_channels; |
| 4025 | audioOut.sample_size = audioOut.channels * 2; |
| 4026 | codec_ctx->channels = audioOut.channels; |
4055 | 4027 | } |
4056 | | |
| 4028 | |
4057 | 4029 | VERBOSE(VB_AUDIO, LOC + "Audio format changed " + |
4058 | | QString("\n\t\t\tfrom %1 ; %2\n\t\t\tto %3 ; %4") |
4059 | | .arg(old_in.toString()).arg(old_out.toString()) |
4060 | | .arg(audioIn.toString()).arg(audioOut.toString())); |
| 4030 | QString("\n\t\t\tfrom %1 to %2") |
| 4031 | .arg(old_in.toString()).arg(audioOut.toString())); |
4061 | 4032 | |
4062 | 4033 | if (audioOut.sample_rate > 0) |
4063 | 4034 | GetNVP()->SetEffDsp(audioOut.sample_rate * 100); |
4064 | 4035 | |
4065 | | GetNVP()->SetAudioParams(audioOut.bps(), audioOut.channels, |
4066 | | audioOut.sample_rate, |
4067 | | audioIn.do_passthru); |
| 4036 | GetNVP()->SetAudioParams(audioOut.bps(), audioOut.channels, |
| 4037 | audioOut.codec_id, audioOut.sample_rate, |
| 4038 | audioOut.do_passthru); |
4068 | 4039 | |
4069 | | // allow the audio stuff to reencode |
4070 | | GetNVP()->SetAudioCodec(using_passthru?codec_ctx:NULL); |
4071 | 4040 | QString errMsg = GetNVP()->ReinitAudio(); |
4072 | | bool audiook = errMsg.isEmpty(); |
4073 | 4041 | |
4074 | 4042 | return true; |
4075 | 4043 | } |
-
diff --git a/mythtv/libs/libmythtv/avformatdecoder.h b/mythtv/libs/libmythtv/avformatdecoder.h
index 2f4fb43..f008136 100644
a
|
b
|
class AvFormatDecoder : public DecoderBase |
196 | 196 | |
197 | 197 | void SeekReset(long long, uint skipFrames, bool doFlush, bool discardFrames); |
198 | 198 | |
| 199 | bool DoPassThrough(const AVCodecContext *ctx); |
199 | 200 | bool SetupAudioStream(void); |
200 | 201 | void SetupAudioStreamSubIndexes(int streamIndex); |
201 | 202 | void RemoveAudioStreams(); |
… |
… |
class AvFormatDecoder : public DecoderBase |
264 | 265 | bool allow_dts_passthru; |
265 | 266 | bool disable_passthru; |
266 | 267 | uint max_channels; |
| 268 | uint last_ac3_channels; |
267 | 269 | |
268 | 270 | VideoFrame *dummy_frame; |
269 | 271 | |
-
diff --git a/mythtv/libs/libmythtv/nuppeldecoder.cpp b/mythtv/libs/libmythtv/nuppeldecoder.cpp
index aae2f26..80a5b89 100644
a
|
b
|
int NuppelDecoder::OpenFile(RingBuffer *rbuffer, bool novideo, |
479 | 479 | #endif |
480 | 480 | GetNVP()->SetAudioParams(extradata.audio_bits_per_sample, |
481 | 481 | extradata.audio_channels, |
| 482 | CODEC_ID_NONE, |
482 | 483 | extradata.audio_sample_rate, |
483 | 484 | false /* AC3/DTS pass through */); |
484 | 485 | GetNVP()->ReinitAudio(); |
-
diff --git a/mythtv/libs/libmythtv/tv_play.cpp b/mythtv/libs/libmythtv/tv_play.cpp
index e56fbae..5fc504d 100644
a
|
b
|
void TV::InitKeys(void) |
348 | 348 | REG_KEY("TV Playback", "VOLUMEDOWN", "Volume down", "[,{,F10,Volume Down"); |
349 | 349 | REG_KEY("TV Playback", "VOLUMEUP", "Volume up", "],},F11,Volume Up"); |
350 | 350 | REG_KEY("TV Playback", "MUTE", "Mute", "|,\\,F9,Volume Mute"); |
| 351 | REG_KEY("TV Playback", "TOGGLEUPMIX", "Toggle upmixer", "Ctrl+U"); |
351 | 352 | REG_KEY("TV Playback", "TOGGLEPIPMODE", "Toggle Picture-in-Picture mode", |
352 | 353 | "V"); |
353 | 354 | REG_KEY("TV Playback", "TOGGLEPIPWINDOW", "Toggle active PiP window", "B"); |
… |
… |
void TV::InitKeys(void) |
480 | 481 | Teletext F2,F3,F4,F5,F6,F7,F8 |
481 | 482 | ITV F2,F3,F4,F5,F6,F7,F12 |
482 | 483 | |
483 | | Playback: Ctrl-B,Ctrl-G,Ctrl-Y |
| 484 | Playback: Ctrl-B,Ctrl-G,Ctrl-Y,Ctrl-U |
484 | 485 | */ |
485 | 486 | } |
486 | 487 | |
… |
… |
void TV::ProcessKeypress(QKeyEvent *e) |
2710 | 2711 | else if (action == "VOLUMEDOWN" || action == "VOLUMEUP" || |
2711 | 2712 | action == "STRETCHINC" || action == "STRETCHDEC" || |
2712 | 2713 | action == "MUTE" || action == "TOGGLEASPECT" || |
2713 | | action == "TOGGLEFILL" ) |
| 2714 | action == "TOGGLEFILL" || action == "TOGGLEUPMIX") |
2714 | 2715 | { |
2715 | 2716 | passThru = 1; |
2716 | 2717 | handled = false; |
… |
… |
void TV::ProcessKeypress(QKeyEvent *e) |
2725 | 2726 | else |
2726 | 2727 | handled = false; |
2727 | 2728 | } |
2728 | | |
| 2729 | |
2729 | 2730 | if (!passThru) |
2730 | 2731 | return; |
2731 | 2732 | } |
2732 | | |
| 2733 | |
2733 | 2734 | if (zoomMode) |
2734 | 2735 | { |
2735 | 2736 | int passThru = 0; |
… |
… |
void TV::ProcessKeypress(QKeyEvent *e) |
2765 | 2766 | else if (action == "VOLUMEDOWN" || action == "VOLUMEUP" || |
2766 | 2767 | action == "STRETCHINC" || action == "STRETCHDEC" || |
2767 | 2768 | action == "MUTE" || action == "PAUSE" || |
2768 | | action == "CLEAROSD") |
| 2769 | action == "CLEAROSD" || action == "TOGGLEUPMIX") |
2769 | 2770 | { |
2770 | 2771 | passThru = 1; |
2771 | 2772 | handled = false; |
… |
… |
void TV::ProcessKeypress(QKeyEvent *e) |
2777 | 2778 | if (!passThru) |
2778 | 2779 | return; |
2779 | 2780 | } |
2780 | | |
| 2781 | |
2781 | 2782 | if (dialogname != "" && GetOSD() && GetOSD()->DialogShowing(dialogname)) |
2782 | 2783 | { |
2783 | 2784 | for (unsigned int i = 0; i < actions.size() && !handled; i++) |
… |
… |
void TV::ProcessKeypress(QKeyEvent *e) |
3036 | 3037 | return; |
3037 | 3038 | } |
3038 | 3039 | } |
3039 | | |
| 3040 | |
3040 | 3041 | for (unsigned int i = 0; i < actions.size() && !handled; i++) |
3041 | 3042 | { |
3042 | 3043 | QString action = actions[i]; |
… |
… |
void TV::ProcessKeypress(QKeyEvent *e) |
3070 | 3071 | ChangeTimeStretch(0); // just display |
3071 | 3072 | else if (action == "TOGGLESTRETCH") |
3072 | 3073 | ToggleTimeStretch(); |
| 3074 | else if (action == "TOGGLEUPMIX") |
| 3075 | ToggleUpmix(); |
3073 | 3076 | else if (action == "CYCLECOMMSKIPMODE") { |
3074 | 3077 | SetAutoCommercialSkip((enum commSkipMode) |
3075 | 3078 | ((autoCommercialSkip + 1) % CommSkipModes)); |
… |
… |
void TV::ChangeTimeStretch(int dir, bool allowEdit) |
6054 | 6057 | } |
6055 | 6058 | } |
6056 | 6059 | |
| 6060 | void TV::ToggleUpmix() |
| 6061 | { |
| 6062 | AudioOutput *aud = nvp->getAudioOutput(); |
| 6063 | if (!aud) |
| 6064 | return; |
| 6065 | QString text; |
| 6066 | if (aud->ToggleUpmix()) |
| 6067 | text = tr("Upmixer On"); |
| 6068 | else |
| 6069 | text = tr("Upmixer Off"); |
| 6070 | |
| 6071 | if (GetOSD() && !browsemode) |
| 6072 | GetOSD()->SetSettingsText(text, 5); |
| 6073 | } |
| 6074 | |
| 6075 | |
6057 | 6076 | // dir in 10ms jumps |
6058 | 6077 | void TV::ChangeAudioSync(int dir, bool allowEdit) |
6059 | 6078 | { |
… |
… |
void TV::TreeMenuSelected(OSDListTreeType *tree, OSDGenericTree *item) |
7302 | 7321 | |
7303 | 7322 | ChangeTimeStretch(0, !floatRead); // just display |
7304 | 7323 | } |
| 7324 | else if (action == "TOGGLEUPMIX") |
| 7325 | ToggleUpmix(); |
7305 | 7326 | else if (action.left(11) == "SELECTSCAN_") |
7306 | 7327 | activenvp->SetScanType((FrameScanType) action.right(1).toInt()); |
7307 | 7328 | else if (action.left(15) == "TOGGLEAUDIOSYNC") |
… |
… |
void TV::BuildOSDTreeMenu(void) |
7549 | 7570 | subitem = new OSDGenericTree(item, tr("1.5X"), "ADJUSTSTRETCH1.5", |
7550 | 7571 | (speedX100 == 150) ? 1 : 0, NULL, |
7551 | 7572 | "STRETCHGROUP"); |
| 7573 | |
| 7574 | item = new OSDGenericTree(treeMenu, tr("Toggle Upmixer"), "TOGGLEUPMIX"); |
7552 | 7575 | |
7553 | 7576 | // add scan mode override settings to menu |
7554 | 7577 | FrameScanType scan_type = kScan_Ignore; |
-
diff --git a/mythtv/libs/libmythtv/tv_play.h b/mythtv/libs/libmythtv/tv_play.h
index 8aa048b..873da6f 100644
a
|
b
|
class MPUBLIC TV : public QObject |
314 | 314 | void ChangeSpeed(int direction); |
315 | 315 | void ToggleTimeStretch(void); |
316 | 316 | void ChangeTimeStretch(int dir, bool allowEdit = true); |
| 317 | void ToggleUpmix(void); |
317 | 318 | void ChangeAudioSync(int dir, bool allowEdit = true); |
318 | 319 | float StopFFRew(void); |
319 | 320 | void ChangeFFRew(int direction); |
-
diff --git a/mythtv/programs/mythfrontend/globalsettings.cpp b/mythtv/programs/mythfrontend/globalsettings.cpp
index b1012d1..19ecd0e 100644
a
|
b
|
static HostComboBox *AudioUpmixType() |
116 | 116 | return gc; |
117 | 117 | } |
118 | 118 | |
| 119 | static HostComboBox *SRCQuality() |
| 120 | { |
| 121 | HostComboBox *gc = new HostComboBox("SRCQuality", false); |
| 122 | gc->setLabel(QObject::tr("Sample Rate Conversion")); |
| 123 | gc->addSelection(QObject::tr("Best"), "3", true); // default |
| 124 | gc->addSelection(QObject::tr("Medium"), "2"); |
| 125 | gc->addSelection(QObject::tr("Fastest"), "1"); |
| 126 | gc->setHelpText( |
| 127 | QObject::tr( |
| 128 | "Set the quality of audio sample rate conversion. " |
| 129 | "All three options offer a worst-case SNR of 97dB. " |
| 130 | "'Best' at a bandwidth of 97%. " |
| 131 | "'Medium' at a bandwidth of 90%. " |
| 132 | "'Fastest' at a bandwidth of 80%. ")); |
| 133 | return gc; |
| 134 | } |
| 135 | |
119 | 136 | static HostComboBox *PassThroughOutputDevice() |
120 | 137 | { |
121 | 138 | HostComboBox *gc = new HostComboBox("PassThruOutputDevice", true); |
… |
… |
class AudioSettings : public TriggeredConfigurationGroup |
3307 | 3324 | agrp->addChild(MaxAudioChannels()); |
3308 | 3325 | agrp->addChild(AudioUpmixType()); |
3309 | 3326 | addChild(agrp); |
| 3327 | |
| 3328 | HorizontalConfigurationGroup *agrp1 = |
| 3329 | new HorizontalConfigurationGroup(false, false, true, true); |
| 3330 | agrp1->addChild(SRCQuality()); |
| 3331 | addChild(agrp1); |
3310 | 3332 | |
3311 | 3333 | VerticalConfigurationGroup *vgrp1 = |
3312 | 3334 | new VerticalConfigurationGroup(false, false, true, true); |
-
diff --git a/mythtv/programs/mythtranscode/transcode.cpp b/mythtv/programs/mythtranscode/transcode.cpp
index dde8b09..653f9d4 100644
a
|
b
|
class AudioReencodeBuffer : public AudioOutput |
38 | 38 | AudioReencodeBuffer(int audio_bits, int audio_channels) |
39 | 39 | { |
40 | 40 | Reset(); |
41 | | Reconfigure(audio_bits, audio_channels, 0, 0); |
| 41 | Reconfigure(audio_bits, audio_channels, CODEC_ID_NONE, 0, 0); |
42 | 42 | bufsize = 512000; |
43 | 43 | audiobuffer = new unsigned char[bufsize]; |
44 | 44 | |
… |
… |
class AudioReencodeBuffer : public AudioOutput |
54 | 54 | } |
55 | 55 | |
56 | 56 | // reconfigure sound out for new params |
57 | | virtual void Reconfigure(int audio_bits, int audio_channels, |
58 | | int audio_samplerate, bool audio_passthru, |
59 | | void *audio_codec = NULL) |
| 57 | virtual void Reconfigure(int audio_bits, int audio_channels, |
| 58 | int audio_codec, int audio_samplerate, |
| 59 | bool audio_passthru) |
60 | 60 | { |
61 | 61 | (void)audio_samplerate; |
62 | 62 | (void)audio_passthru; |
63 | | (void)audio_codec; |
64 | 63 | |
65 | 64 | ClearError(); |
66 | 65 | bits = audio_bits; |
… |
… |
class AudioReencodeBuffer : public AudioOutput |
218 | 217 | // Do nothing |
219 | 218 | return MUTE_OFF; |
220 | 219 | } |
| 220 | virtual bool ToggleUpmix(void) |
| 221 | { |
| 222 | // Do nothing |
| 223 | return false; |
| 224 | } |
221 | 225 | |
222 | 226 | // These are pure virtual in AudioOutput, but we don't need them here |
223 | 227 | virtual void bufferOutputData(bool){ return; } |