MythTV master
audioplayer.cpp
Go to the documentation of this file.
1
6
7#include "audioplayer.h"
8#include "mythplayer.h"
10
11#define LOC QString("AudioPlayer: ")
12
13//static const QString _Location = AudioPlayer::tr("Audio Player");
14
16 : m_parent(parent),
17 m_mutedOnCreation(muted)
18{
19 m_controlsVolume = gCoreContext->GetBoolSetting("MythControlsVolume", true);
20}
21
23{
25 m_visuals.clear();
26}
27
29{
30 if (!m_audioOutput)
31 return;
32
33 QMutexLocker lock(&m_lock);
34 auto it = std::find(m_visuals.begin(), m_visuals.end(), vis);
35 if (it == m_visuals.end())
36 {
37 m_visuals.push_back(vis);
39 }
40}
41
43{
44 if (!m_audioOutput)
45 return;
46
47 QMutexLocker lock(&m_lock);
48 auto it = std::find(m_visuals.begin(), m_visuals.end(), vis);
49 if (it != m_visuals.end())
50 {
51 m_visuals.erase(it);
53 }
54}
55
57{
58 if (!m_audioOutput)
59 return;
60
61 QMutexLocker lock(&m_lock);
62 for (auto & visual : m_visuals)
63 m_audioOutput->addVisual(visual);
64}
65
67{
68 if (!m_audioOutput)
69 return;
70
71 QMutexLocker lock(&m_lock);
72 for (auto & visual : m_visuals)
74}
75
77{
78 if (!m_audioOutput)
79 return;
80
81 QMutexLocker lock(&m_lock);
82 for (auto & visual : m_visuals)
83 visual->prepare();
84}
85
87{
88 if (!m_audioOutput)
89 return;
90
91 QMutexLocker lock(&m_lock);
93}
94
96{
98 QMutexLocker locker(&m_lock);
99 if (m_audioOutput)
100 {
101 delete m_audioOutput;
102 m_audioOutput = nullptr;
103 }
104 m_noAudioOut = true;
105}
106
108{
109 bool want_audio = m_parent->IsAudioNeeded();
110 QString errMsg;
111 QMutexLocker lock(&m_lock);
112
114 m_noAudioIn = m_noAudioOut = true;
115 else
116 m_noAudioIn = false;
117
118 if (want_audio && !m_audioOutput)
119 {
120 // AudioOutput has never been created and we will want audio
126 if (m_noAudioIn)
127 aos.m_init = false;
128
130 if (!m_audioOutput)
131 {
132 errMsg = tr("Unable to create AudioOutput.");
133 }
134 else
135 {
136 errMsg = m_audioOutput->GetError();
137 }
138 AddVisuals();
139 }
140 else if (!m_noAudioIn && m_audioOutput)
141 {
145 m_audioOutput->Reconfigure(settings);
146 errMsg = m_audioOutput->GetError();
148 }
149
150 if (!errMsg.isEmpty())
151 {
152 LOG(VB_GENERAL, LOG_NOTICE, LOC + "Disabling Audio" +
153 QString(", reason is: %1").arg(errMsg));
154 ShowNotificationError(tr("Disabling Audio"),
155 AudioPlayer::tr( "Audio Player" ), errMsg);
156 m_noAudioOut = true;
157 }
158 else if (m_noAudioOut && m_audioOutput)
159 {
160 LOG(VB_GENERAL, LOG_NOTICE, LOC + "Enabling Audio");
161 m_noAudioOut = false;
162 }
163
165 {
167 m_mutedOnCreation = false;
168 }
169
170 ResetVisuals();
171
172 return errMsg;
173}
174
176{
178 m_noAudioIn = m_noAudioOut = true;
179}
180
181bool AudioPlayer::Pause(bool pause)
182{
184 return false;
185
186 QMutexLocker lock(&m_lock);
187 m_audioOutput->Pause(pause);
188 return true;
189}
190
192{
194 return false;
195 QMutexLocker lock(&m_lock);
196 return m_audioOutput->IsPaused();
197}
198
200{
202 return;
203 QMutexLocker lock(&m_lock);
205}
206
208{
209 // delete current audio class if any
210 DeleteOutput();
211 m_lock.lock();
212 m_audioOutput = ao;
213 AddVisuals();
214 m_lock.unlock();
215}
216
218{
220 return 0;
221 QMutexLocker lock(&m_lock);
223}
224
229void AudioPlayer::SetAudioInfo(const QString &main_device,
230 const QString &passthru_device,
231 uint samplerate,
232 int codec_profile)
233{
234 m_mainDevice.clear();
235 m_passthruDevice.clear();
236 if (!main_device.isEmpty())
237 m_mainDevice = main_device;
238 if (!passthru_device.isEmpty())
239 m_passthruDevice = passthru_device;
240 m_state.m_sampleRate = static_cast<int>(samplerate);
241 m_state.m_codecProfile = codec_profile;
243}
244
249void AudioPlayer::SetAudioParams(AudioFormat format, int orig_channels,
250 int channels, AVCodecID codec,
251 int samplerate, bool passthru,
252 int codec_profile)
253{
254 m_state.m_format = CanProcess(format) ? format : FORMAT_S16;
255 m_state.m_origChannels = orig_channels;
256 m_state.m_channels = channels;
257 m_state.m_codec = codec;
258 m_state.m_sampleRate = samplerate;
259 m_state.m_passthru = passthru;
260 m_state.m_codecProfile = codec_profile;
261 ResetVisuals();
263}
264
265void AudioPlayer::SetEffDsp(int dsprate)
266{
268 return;
269 QMutexLocker lock(&m_lock);
270 m_audioOutput->SetEffDsp(dsprate);
271}
272
274{
275 bool is_muted = IsMuted();
276 QMutexLocker lock(&m_lock);
277
278 if (m_audioOutput && !m_noAudioOut && !is_muted && mute &&
280 {
281 LOG(VB_AUDIO, LOG_INFO, QString("muting sound %1").arg(IsMuted()));
282 return true;
283 }
284 if (m_audioOutput && !m_noAudioOut && is_muted && !mute &&
286 {
287 LOG(VB_AUDIO, LOG_INFO, QString("unmuting sound %1").arg(IsMuted()));
288 return true;
289 }
290
291 LOG(VB_AUDIO, LOG_ERR,
292 QString("not changing sound mute state %1").arg(IsMuted()));
293
294 return false;
295}
296
298{
300 return kMuteAll;
301 QMutexLocker lock(&m_lock);
302 return m_audioOutput->SetMuteState(mstate);
303}
304
306{
308 return kMuteAll;
310}
311
313{
315 return kMuteAll;
316 QMutexLocker lock(&m_lock);
317 return m_audioOutput->GetMuteState();
318}
319
321{
323 return GetVolume();
324 QMutexLocker lock(&m_lock);
326 return GetVolume();
327}
328
330{
332 return GetVolume();
333 QMutexLocker lock(&m_lock);
335 return GetVolume();
336}
337
338std::chrono::milliseconds AudioPlayer::GetAudioTime(void)
339{
341 return 0ms;
342 QMutexLocker lock(&m_lock);
343 return m_audioOutput->GetAudiotime();
344}
345
347{
348 if (!m_audioOutput)
349 return false;
350 QMutexLocker lock(&m_lock);
351 return m_audioOutput->IsUpmixing();
352}
353
354bool AudioPlayer::EnableUpmix(bool enable, bool toggle)
355{
356 if (!m_audioOutput)
357 return false;
358 QMutexLocker lock(&m_lock);
359 if (toggle || (enable != IsUpmixing()))
360 return m_audioOutput->ToggleUpmix();
361 return enable;
362}
363
365{
366 if (!m_audioOutput)
367 return false;
368 QMutexLocker lock(&m_lock);
369 return m_audioOutput->CanUpmix();
370}
371
373{
374 m_stretchFactor = factor;
375 if (!m_audioOutput)
376 return;
377 QMutexLocker lock(&m_lock);
379}
380
381// The following methods are not locked as this hinders performance.
382// They are however only called from the Decoder and only the decode
383// thread will trigger a deletion/recreation of the AudioOutput device, hence
384// they should be safe.
385
387{
388 if (!ao)
389 return false;
390
391 return ao->GetOutputSettingsUsers(true)->canFeature(feature);
392}
393
395{
397}
398
400{
402}
403
405{
407}
408
410{
412}
413
415{
417}
418
420{
421 if (!m_audioOutput)
422 return 2;
424}
425
427{
428 if (!m_audioOutput)
429 return 0;
431}
432
433bool AudioPlayer::CanPassthrough(int samplerate, int channels,
434 AVCodecID codec, int profile)
435{
436 if (!m_audioOutput)
437 return false;
438 return m_audioOutput->CanPassthrough(samplerate, channels, codec, profile);
439}
440
442{
443 if (!m_audioOutput)
444 return false;
445 return m_audioOutput->CanDownmix();
446}
447
448/*
449 * if frames = -1 : let AudioOuput calculate value
450 * if frames = 0 && len > 0: will calculate according to len
451 */
452void AudioPlayer::AddAudioData(char *buffer, int len,
453 std::chrono::milliseconds timecode, int frames)
454{
456 return;
457
458 if (m_parent->PrepareAudioSample(timecode))
460 int samplesize = m_audioOutput->GetBytesPerFrame();
461
462 if (samplesize <= 0)
463 return;
464
465 if (frames == 0 && len > 0)
466 frames = len / samplesize;
467
468 if (!m_audioOutput->AddData(buffer, len, timecode, frames))
469 LOG(VB_PLAYBACK, LOG_ERR, LOC + "AddAudioData(): "
470 "Audio buffer overflow, audio data lost!");
471}
472
474{
475 if (!m_audioOutput)
476 return true;
478}
479
480std::chrono::milliseconds AudioPlayer::LengthLastData(void)
481{
482 if (!m_audioOutput)
483 return 0ms;
485}
486
488{
489 fill = total = 0;
491 return false;
492 m_audioOutput->GetBufferStatus(fill, total);
493 return true;
494}
495
497{
498 uint ofill = 0;
499 uint ototal = 0;
500 if (GetBufferStatus(ofill, ototal))
501 {
502 uint othresh = ((ototal>>1) + (ototal>>2));
503 if (ofill > othresh)
504 return true;
505 return GetAudioBufferedTime() > 8s;
506 }
507 return false;
508}
509
510std::chrono::milliseconds AudioPlayer::GetAudioBufferedTime(void)
511{
513}
514
515
517{
518 if (!m_audioOutput)
519 return false;
520 return m_audioOutput->CanProcess(fmt);
521}
522
524{
525 if (!m_audioOutput)
526 return 0;
527 return m_audioOutput->CanProcess();
528}
529
540int AudioPlayer::DecodeAudio(AVCodecContext *ctx,
541 uint8_t *buffer, int &data_size,
542 const AVPacket *pkt)
543{
544 if (!m_audioOutput)
545 {
546 data_size = 0;
547 return 0;
548 }
549 return m_audioOutput->DecodeAudio(ctx, buffer, data_size, pkt);
550}
static const std::array< featureStruct, 7 > feature
@ FORMAT_NONE
@ FORMAT_S16
DigitalFeature
@ FEATURE_DTS
@ FEATURE_AC3
@ FEATURE_DTSHD
@ FEATURE_EAC3
@ FEATURE_TRUEHD
bool TestDigitalFeature(AudioOutput *ao, DigitalFeature feature)
#define LOC
Definition: audioplayer.cpp:11
@ AUDIOOUTPUT_VIDEO
Definition: audiosettings.h:23
bool canFeature(DigitalFeature arg) const
return DigitalFeature mask.
int GetMaxHDRate() const
return the highest iec958 rate supported.
virtual bool AddData(void *buffer, int len, std::chrono::milliseconds timecode, int frames)=0
Add data to the audiobuffer for playback.
virtual bool IsPaused(void) const =0
virtual bool NeedDecodingBeforePassthrough(void) const
Definition: audiooutput.h:122
virtual void Drain(void)=0
static AudioOutput * OpenAudio(const QString &main_device, const QString &passthru_device, AudioFormat format, int channels, AVCodecID codec, int samplerate, AudioOutputSource source, bool set_initial_vol, bool passthru, int upmixer_startup=0, AudioOutputSettings *custom=nullptr)
Definition: audiooutput.cpp:60
virtual std::chrono::milliseconds GetAudioBufferedTime(void)
report amount of audio buffered in milliseconds.
Definition: audiooutput.h:142
virtual bool IsUpmixing(void)
Definition: audiooutput.h:157
virtual void PauseUntilBuffered(void)=0
virtual std::chrono::milliseconds GetAudiotime(void)=0
virtual std::chrono::milliseconds LengthLastData(void) const
Definition: audiooutput.h:129
virtual void SetEffDsp(int dsprate)=0
virtual AudioOutputSettings * GetOutputSettingsUsers(bool digital=true)
virtual bool ToggleUpmix(void)
Definition: audiooutput.h:158
virtual int GetBytesPerFrame(void) const
Definition: audiooutput.h:77
virtual int DecodeAudio(AVCodecContext *ctx, uint8_t *buffer, int &data_size, const AVPacket *pkt)
Utility routine.
virtual bool CanPassthrough(int samplerate, int channels, AVCodecID codec, int profile) const
virtual bool CanDownmix(void) const
Definition: audiooutput.h:83
virtual void Reset(void)=0
virtual bool CanUpmix(void)
Definition: audiooutput.h:159
virtual bool CanProcess(AudioFormat fmt)
Definition: audiooutput.h:167
virtual void Reconfigure(const AudioSettings &settings)=0
virtual void GetBufferStatus(uint &fill, uint &total)
Definition: audiooutput.h:149
virtual void Pause(bool paused)=0
virtual void SetStretchFactor(float factor)
QString GetError(void) const
Definition: audiooutput.h:146
std::vector< MythTV::Visual * > m_visuals
Definition: audioplayer.h:121
void AudioPlayerStateChanged(MythAudioPlayerState State)
std::chrono::milliseconds GetAudioTime(void)
void ResetVisuals(void)
Definition: audioplayer.cpp:76
MuteState IncrMuteState(void)
bool CanAC3(void)
uint GetVolume(void)
bool m_controlsVolume
Definition: audioplayer.h:120
void PauseAudioUntilBuffered(void)
AudioOutput * m_audioOutput
Definition: audioplayer.h:111
bool CanEAC3(void)
bool CanUpmix(void)
bool m_mutedOnCreation
Definition: audioplayer.h:115
uint SetVolume(int newvolume)
float m_stretchFactor
Definition: audioplayer.h:113
bool IsUpmixing(void)
bool IsPaused(void)
QString ReinitAudio(void)
void RemoveVisuals(void)
Definition: audioplayer.cpp:66
bool CanPassthrough(int samplerate, int channels, AVCodecID codec, int profile)
bool CanTrueHD(void)
AudioPlayer(MythPlayer *parent, bool muted)
Definition: audioplayer.cpp:15
uint GetMaxChannels(void)
void addVisual(MythTV::Visual *vis)
Definition: audioplayer.cpp:28
bool GetBufferStatus(uint &fill, uint &total)
void removeVisual(MythTV::Visual *vis)
Definition: audioplayer.cpp:42
bool m_noAudioOut
Definition: audioplayer.h:119
int DecodeAudio(AVCodecContext *ctx, uint8_t *buffer, int &data_size, const AVPacket *pkt)
DecodeAudio Utility routine.
void SetEffDsp(int dsprate)
void AddAudioData(char *buffer, int len, std::chrono::milliseconds timecode, int frames)
void AddVisuals(void)
Definition: audioplayer.cpp:56
MythPlayer * m_parent
Definition: audioplayer.h:110
bool CanDownmix(void)
std::chrono::milliseconds LengthLastData(void)
bool NeedDecodingBeforePassthrough(void)
MythAudioPlayerState m_state
Definition: audioplayer.h:112
void SetAudioParams(AudioFormat format, int orig_channels, int channels, AVCodecID codec, int samplerate, bool passthru, int codec_profile=-1)
Set audio output parameters.
MuteState SetMuteState(MuteState mstate)
void SetAudioOutput(AudioOutput *ao)
QString m_mainDevice
Definition: audioplayer.h:116
bool CanDTSHD(void)
~AudioPlayer() override
Definition: audioplayer.cpp:22
bool IsMuted(void)
Definition: audioplayer.h:86
MuteState GetMuteState(void)
bool Pause(bool pause)
bool m_noAudioIn
Definition: audioplayer.h:118
void CheckFormat(void)
void DeleteOutput(void)
Definition: audioplayer.cpp:95
std::chrono::milliseconds GetAudioBufferedTime(void)
QString m_passthruDevice
Definition: audioplayer.h:117
QRecursiveMutex m_lock
Definition: audioplayer.h:114
bool CanDTS(void)
void Reset(void)
Definition: audioplayer.cpp:86
void SetAudioInfo(const QString &main_device, const QString &passthru_device, uint samplerate, int codec_profile=-1)
Set audio output device parameters.
bool IsBufferAlmostFull(void)
bool EnableUpmix(bool enable, bool toggle=false)
void SetStretchFactor(float factor)
bool SetMuted(bool mute)
int GetMaxHDRate(void)
uint32_t CanProcess(void)
uint AdjustVolume(int change)
bool m_init
If set to false, AudioOutput instance will not try to initially open the audio device.
Definition: audiosettings.h:85
bool GetBoolSetting(const QString &key, bool defaultval=false)
bool IsAudioNeeded(void)
Definition: mythplayer.h:134
virtual bool PrepareAudioSample(std::chrono::milliseconds &timecode)
void removeVisual(MythTV::Visual *v)
Definition: output.cpp:42
void addVisual(MythTV::Visual *v)
Definition: output.cpp:35
static MuteState NextMuteState(MuteState)
Definition: volumebase.cpp:155
virtual MuteState GetMuteState(void) const
Definition: volumebase.cpp:150
virtual void SetCurrentVolume(int value)
Definition: volumebase.cpp:123
virtual uint GetCurrentVolume(void) const
Definition: volumebase.cpp:118
virtual MuteState SetMuteState(MuteState)
Definition: volumebase.cpp:137
virtual void AdjustCurrentVolume(int change)
Definition: volumebase.cpp:132
static pid_list_t::iterator find(const PIDInfoMap &map, pid_list_t &list, pid_list_t::iterator begin, pid_list_t::iterator end, bool find_open)
unsigned int uint
Definition: freesurround.h:24
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
void ShowNotificationError(const QString &msg, const QString &from, const QString &detail, const VNMask visibility, const MythNotification::Priority priority)
convenience utility to display error message as notification
MuteState
Definition: volumebase.h:8
@ kMuteOff
Definition: volumebase.h:9
@ kMuteAll
Definition: volumebase.h:12