MythTV  master
audioplayer.cpp
Go to the documentation of this file.
1 
2 #include "audioplayer.h"
3 
4 #include "mythplayer.h"
5 #include "audiooutput.h"
7 
8 #define LOC QString("AudioPlayer: ")
9 
10 //static const QString _Location = AudioPlayer::tr("Audio Player");
11 
13  : m_parent(parent),
14  m_muted_on_creation(muted)
15 {
16  m_controls_volume = gCoreContext->GetBoolSetting("MythControlsVolume", true);
17 }
18 
20 {
21  DeleteOutput();
22  m_visuals.clear();
23 }
24 
26 {
27  if (!m_audioOutput)
28  return;
29 
30  QMutexLocker lock(&m_lock);
31  Visuals::iterator it = std::find(m_visuals.begin(), m_visuals.end(), vis);
32  if (it == m_visuals.end())
33  {
34  m_visuals.push_back(vis);
36  }
37 }
38 
40 {
41  if (!m_audioOutput)
42  return;
43 
44  QMutexLocker lock(&m_lock);
45  Visuals::iterator it = std::find(m_visuals.begin(), m_visuals.end(), vis);
46  if (it != m_visuals.end())
47  {
48  m_visuals.erase(it);
50  }
51 }
52 
54 {
55  if (!m_audioOutput)
56  return;
57 
58  QMutexLocker lock(&m_lock);
59  for (size_t i = 0; i < m_visuals.size(); i++)
61 }
62 
64 {
65  if (!m_audioOutput)
66  return;
67 
68  QMutexLocker lock(&m_lock);
69  for (size_t i = 0; i < m_visuals.size(); i++)
71 }
72 
74 {
75  if (!m_audioOutput)
76  return;
77 
78  QMutexLocker lock(&m_lock);
79  for (size_t i = 0; i < m_visuals.size(); i++)
80  m_visuals[i]->prepare();
81 }
82 
84 {
85  if (!m_audioOutput)
86  return;
87 
88  QMutexLocker lock(&m_lock);
90 }
91 
93 {
94  RemoveVisuals();
95  QMutexLocker locker(&m_lock);
96  if (m_audioOutput)
97  {
98  delete m_audioOutput;
99  m_audioOutput = nullptr;
100  }
101  m_no_audio_out = true;
102 }
103 
105 {
106  bool want_audio = m_parent->IsAudioNeeded();
107  QString errMsg;
108  QMutexLocker lock(&m_lock);
109 
110  if ((m_format == FORMAT_NONE) ||
111  (m_channels <= 0) ||
112  (m_samplerate <= 0))
113  {
114  m_no_audio_in = m_no_audio_out = true;
115  }
116  else
117  m_no_audio_in = false;
118 
119  if (want_audio && !m_audioOutput)
120  {
121  // AudioOutput has never been created and we will want audio
128  if (m_no_audio_in)
129  aos.m_init = false;
130 
132  if (!m_audioOutput)
133  {
134  errMsg = tr("Unable to create AudioOutput.");
135  }
136  else
137  {
138  errMsg = m_audioOutput->GetError();
139  }
140  AddVisuals();
141  }
142  else if (!m_no_audio_in && m_audioOutput)
143  {
144  const AudioSettings settings(m_format, m_channels, m_codec,
147  m_audioOutput->Reconfigure(settings);
148  errMsg = m_audioOutput->GetError();
150  }
151 
152  if (!errMsg.isEmpty())
153  {
154  LOG(VB_GENERAL, LOG_NOTICE, LOC + "Disabling Audio" +
155  QString(", reason is: %1").arg(errMsg));
156  ShowNotificationError(tr("Disabling Audio"),
157  AudioPlayer::tr( "Audio Player" ), errMsg);
158  m_no_audio_out = true;
159  }
160  else if (m_no_audio_out && m_audioOutput)
161  {
162  LOG(VB_GENERAL, LOG_NOTICE, LOC + "Enabling Audio");
163  m_no_audio_out = false;
164  }
165 
167  {
169  m_muted_on_creation = false;
170  }
171 
172  ResetVisuals();
173 
174  return errMsg;
175 }
176 
178 {
179  if (m_format == FORMAT_NONE)
180  m_no_audio_in = m_no_audio_out = true;
181 }
182 
183 bool AudioPlayer::Pause(bool pause)
184 {
186  return false;
187 
188  QMutexLocker lock(&m_lock);
189  m_audioOutput->Pause(pause);
190  return true;
191 }
192 
194 {
196  return false;
197  QMutexLocker lock(&m_lock);
198  return m_audioOutput->IsPaused();
199 }
200 
202 {
204  return;
205  QMutexLocker lock(&m_lock);
207 }
208 
210 {
211  // delete current audio class if any
212  DeleteOutput();
213  m_lock.lock();
214  m_audioOutput = ao;
215  AddVisuals();
216  m_lock.unlock();
217 }
218 
220 {
222  return 0;
223  QMutexLocker lock(&m_lock);
225 }
226 
231 void AudioPlayer::SetAudioInfo(const QString &main_device,
232  const QString &passthru_device,
233  uint samplerate,
234  int codec_profile)
235 {
236  m_main_device.clear();
237  m_passthru_device.clear();
238  if (!main_device.isEmpty())
239  m_main_device = main_device;
240  if (!passthru_device.isEmpty())
241  m_passthru_device = passthru_device;
242  m_samplerate = (int)samplerate;
243  m_codec_profile = codec_profile;
244 }
245 
250 void AudioPlayer::SetAudioParams(AudioFormat format, int orig_channels,
251  int channels, AVCodecID codec,
252  int samplerate, bool passthru,
253  int codec_profile)
254 {
255  m_format = CanProcess(format) ? format : FORMAT_S16;
256  m_orig_channels = orig_channels;
257  m_channels = channels;
258  m_codec = codec;
259  m_samplerate = samplerate;
260  m_passthru = passthru;
261  m_codec_profile = codec_profile;
262 
263  ResetVisuals();
264 }
265 
266 void AudioPlayer::SetEffDsp(int dsprate)
267 {
268  if (!m_audioOutput || !m_no_audio_out)
269  return;
270  QMutexLocker lock(&m_lock);
271  m_audioOutput->SetEffDsp(dsprate);
272 }
273 
274 bool AudioPlayer::SetMuted(bool mute)
275 {
276  bool is_muted = IsMuted();
277  QMutexLocker lock(&m_lock);
278 
279  if (m_audioOutput && !m_no_audio_out && !is_muted && mute &&
281  {
282  LOG(VB_AUDIO, LOG_INFO, QString("muting sound %1").arg(IsMuted()));
283  return true;
284  }
285  if (m_audioOutput && !m_no_audio_out && is_muted && !mute &&
287  {
288  LOG(VB_AUDIO, LOG_INFO, QString("unmuting sound %1").arg(IsMuted()));
289  return true;
290  }
291 
292  LOG(VB_AUDIO, LOG_ERR,
293  QString("not changing sound mute state %1").arg(IsMuted()));
294 
295  return false;
296 }
297 
299 {
301  return kMuteAll;
302  QMutexLocker lock(&m_lock);
303  return m_audioOutput->SetMuteState(mstate);
304 }
305 
307 {
309  return kMuteAll;
311 }
312 
314 {
316  return kMuteAll;
317  QMutexLocker lock(&m_lock);
318  return m_audioOutput->GetMuteState();
319 }
320 
322 {
324  return GetVolume();
325  QMutexLocker lock(&m_lock);
327  return GetVolume();
328 }
329 
331 {
333  return GetVolume();
334  QMutexLocker lock(&m_lock);
335  m_audioOutput->SetCurrentVolume(newvolume);
336  return GetVolume();
337 }
338 
340 {
342  return 0LL;
343  QMutexLocker lock(&m_lock);
344  return m_audioOutput->GetAudiotime();
345 }
346 
348 {
349  if (!m_audioOutput)
350  return false;
351  QMutexLocker lock(&m_lock);
352  return m_audioOutput->IsUpmixing();
353 }
354 
355 bool AudioPlayer::EnableUpmix(bool enable, bool toggle)
356 {
357  if (!m_audioOutput)
358  return false;
359  QMutexLocker lock(&m_lock);
360  if (toggle || (enable != IsUpmixing()))
361  return m_audioOutput->ToggleUpmix();
362  return enable;
363 }
364 
366 {
367  if (!m_audioOutput)
368  return false;
369  QMutexLocker lock(&m_lock);
370  return m_audioOutput->CanUpmix();
371 }
372 
374 {
375  m_stretchfactor = factor;
376  if (!m_audioOutput)
377  return;
378  QMutexLocker lock(&m_lock);
380 }
381 
382 // The following methods are not locked as this hinders performance.
383 // They are however only called from the Decoder and only the decode
384 // thread will trigger a deletion/recreation of the AudioOutput device, hence
385 // they should be safe.
386 
388 {
389  if (!ao)
390  return false;
391 
392  return ao->GetOutputSettingsUsers(true)->canFeature(feature);
393 }
394 
396 {
398 }
399 
401 {
403 }
404 
406 {
408 }
409 
411 {
413 }
414 
416 {
418 }
419 
421 {
422  if (!m_audioOutput)
423  return 2;
425 }
426 
428 {
429  if (!m_audioOutput)
430  return 0;
432 }
433 
434 bool AudioPlayer::CanPassthrough(int samplerate, int channels,
435  AVCodecID codec, int profile)
436 {
437  if (!m_audioOutput)
438  return false;
439  return m_audioOutput->CanPassthrough(samplerate, channels, codec, profile);
440 }
441 
443 {
444  if (!m_audioOutput)
445  return false;
446  return m_audioOutput->CanDownmix();
447 }
448 
449 /*
450  * if frames = -1 : let AudioOuput calculate value
451  * if frames = 0 && len > 0: will calculate according to len
452  */
453 void AudioPlayer::AddAudioData(char *buffer, int len,
454  int64_t timecode, int frames)
455 {
457  return;
458 
459  if (m_parent->PrepareAudioSample(timecode) && !m_no_audio_out)
460  m_audioOutput->Drain();
461  int samplesize = m_audioOutput->GetBytesPerFrame();
462 
463  if (samplesize <= 0)
464  return;
465 
466  if (frames == 0 && len > 0)
467  frames = len / samplesize;
468 
469  if (!m_audioOutput->AddData(buffer, len, timecode, frames))
470  LOG(VB_PLAYBACK, LOG_ERR, LOC + "AddAudioData(): "
471  "Audio buffer overflow, audio data lost!");
472 }
473 
475 {
476  if (!m_audioOutput)
477  return true;
479 }
480 
482 {
483  if (!m_audioOutput)
484  return 0;
485  return m_audioOutput->LengthLastData();
486 }
487 
489 {
490  fill = total = 0;
492  return false;
493  m_audioOutput->GetBufferStatus(fill, total);
494  return true;
495 }
496 
498 {
499  uint ofill = 0, 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() > 8000;
506  }
507  return false;
508 }
509 
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 
540 int 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 }
virtual bool IsPaused(void) const =0
bool SetMuted(bool mute)
uint32_t CanProcess(void)
MuteState GetMuteState(void)
virtual int GetBytesPerFrame(void) const
Definition: audiooutput.h:75
virtual uint GetCurrentVolume(void) const
Definition: volumebase.cpp:118
uint GetVolume(void)
void SetStretchFactor(float factor)
virtual bool NeedDecodingBeforePassthrough(void) const
Definition: audiooutput.h:119
int64_t LengthLastData(void)
virtual AudioOutputSettings * GetOutputSettingsUsers(bool digital=true)
virtual void SetCurrentVolume(int value)
Definition: volumebase.cpp:123
bool Pause(bool pause)
int m_samplerate
Definition: audioplayer.h:118
virtual bool ToggleUpmix(void)
Definition: audiooutput.h:155
int m_orig_channels
Definition: audioplayer.h:115
QString m_passthru_device
Definition: audioplayer.h:125
void addVisual(MythTV::Visual *vis)
Definition: audioplayer.cpp:25
virtual void Reset(void)=0
AudioPlayer(MythPlayer *parent, bool muted)
Definition: audioplayer.cpp:12
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:61
virtual bool CanUpmix(void)
Definition: audiooutput.h:156
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)
virtual int64_t LengthLastData(void) const
Definition: audiooutput.h:126
virtual void Drain(void)=0
void SetAudioParams(AudioFormat format, int orig_channels, int channels, AVCodecID codec, int samplerate, bool passthru, int codec_profile=-1)
Set audio output parameters.
bool m_muted_on_creation
Definition: audioplayer.h:123
void SetAudioInfo(const QString &main_device, const QString &passthru_device, uint samplerate, int codec_profile=-1)
Set audio output device parameters.
MuteState
Definition: volumebase.h:6
bool CanDTS(void)
AudioOutput * m_audioOutput
Definition: audioplayer.h:113
bool IsAudioNeeded(void)
Definition: mythplayer.h:178
virtual bool CanPassthrough(int samplerate, int channels, AVCodecID codec, int profile) const
unsigned int uint
Definition: compat.h:140
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
QString ReinitAudio(void)
static MuteState NextMuteState(MuteState)
Definition: volumebase.cpp:155
bool CanAC3(void)
virtual bool CanProcess(AudioFormat fmt)
Definition: audiooutput.h:164
void ResetVisuals(void)
Definition: audioplayer.cpp:73
QString m_main_device
Definition: audioplayer.h:124
bool EnableUpmix(bool enable, bool toggle=false)
virtual int64_t GetAudiotime(void)=0
MuteState SetMuteState(MuteState)
virtual MuteState SetMuteState(MuteState)
Definition: volumebase.cpp:137
virtual void AdjustCurrentVolume(int change)
Definition: volumebase.cpp:132
virtual bool PrepareAudioSample(int64_t &timecode)
int GetMaxHDRate(void)
MythPlayer * m_parent
Definition: audioplayer.h:112
void CheckFormat(void)
virtual bool CanDownmix(void) const
Definition: audiooutput.h:81
bool IsBufferAlmostFull(void)
void RemoveVisuals(void)
Definition: audioplayer.cpp:63
int m_codec_profile
Definition: audioplayer.h:119
void SetAudioOutput(AudioOutput *ao)
vector< MythTV::Visual * > m_visuals
Definition: audioplayer.h:129
QMutex m_lock
Definition: audioplayer.h:122
bool CanTrueHD(void)
virtual void Pause(bool paused)=0
uint GetMaxChannels(void)
bool IsPaused(void)
virtual void SetEffDsp(int dsprate)=0
void AddVisuals(void)
Definition: audioplayer.cpp:53
AVCodecID m_codec
Definition: audioplayer.h:116
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
bool canFeature(DigitalFeature arg)
return DigitalFeature mask.
int DecodeAudio(AVCodecContext *ctx, uint8_t *buffer, int &data_size, const AVPacket *pkt)
DecodeAudio Utility routine.
int64_t GetAudioBufferedTime(void)
float m_stretchfactor
Definition: audioplayer.h:120
virtual void GetBufferStatus(uint &fill, uint &total)
Definition: audiooutput.h:146
virtual void SetStretchFactor(float factor)
void addVisual(MythTV::Visual *)
Definition: output.cpp:36
bool CanDownmix(void)
virtual int DecodeAudio(AVCodecContext *ctx, uint8_t *buffer, int &data_size, const AVPacket *pkt)
Utility routine.
void PauseAudioUntilBuffered(void)
int64_t GetAudioTime(void)
bool CanEAC3(void)
bool IsUpmixing(void)
uint SetVolume(int newvolume)
virtual void Reconfigure(const AudioSettings &settings)=0
bool TestDigitalFeature(AudioOutput *ao, DigitalFeature feature)
MuteState IncrMuteState(void)
void DeleteOutput(void)
Definition: audioplayer.cpp:92
virtual bool AddData(void *buffer, int len, int64_t timecode, int frames)=0
Add data to the audiobuffer for playback.
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
virtual bool IsUpmixing(void)
Definition: audiooutput.h:154
uint AdjustVolume(int change)
bool GetBoolSetting(const QString &key, bool defaultval=false)
bool CanPassthrough(int samplerate, int channels, AVCodecID codec, int profile)
int GetMaxHDRate()
return the highest iec958 rate supported.
void removeVisual(MythTV::Visual *)
Definition: output.cpp:43
void SetEffDsp(int dsprate)
bool GetBufferStatus(uint &fill, uint &total)
bool CanDTSHD(void)
bool IsMuted(void)
Definition: audioplayer.h:88
DigitalFeature
const char * frames[3]
Definition: element.c:46
bool m_passthru
Definition: audioplayer.h:121
bool m_controls_volume
Definition: audioplayer.h:128
bool NeedDecodingBeforePassthrough(void)
bool m_no_audio_out
Definition: audioplayer.h:127
void AddAudioData(char *buffer, int len, int64_t timecode, int frames)
virtual void PauseUntilBuffered(void)=0
#define LOC
Definition: audioplayer.cpp:8
void removeVisual(MythTV::Visual *vis)
Definition: audioplayer.cpp:39
bool m_init
If set to false, AudioOutput instance will not try to initially open the audio device.
Definition: audiosettings.h:80
void Reset(void)
Definition: audioplayer.cpp:83
bool CanUpmix(void)
AudioFormat m_format
Definition: audioplayer.h:117
bool m_no_audio_in
Definition: audioplayer.h:126
QString GetError(void) const
Definition: audiooutput.h:143
virtual MuteState GetMuteState(void) const
Definition: volumebase.cpp:150
virtual int64_t GetAudioBufferedTime(void)
report amount of audio buffered in milliseconds.
Definition: audiooutput.h:139