MythTV  0.26-pre
audioplayer.cpp
Go to the documentation of this file.
00001 #include "mythplayer.h"
00002 #include "audiooutput.h"
00003 #include "audioplayer.h"
00004 
00005 #define LOC QString("AudioPlayer: ")
00006 
00007 AudioPlayer::AudioPlayer(MythPlayer *parent, bool muted)
00008   : m_parent(parent),     m_audioOutput(NULL),   m_channels(-1),
00009     m_orig_channels(-1),  m_codec(0),            m_format(FORMAT_NONE),
00010     m_samplerate(44100),  m_codec_profile(0),
00011     m_stretchfactor(1.0f),m_passthru(false),
00012     m_lock(QMutex::Recursive), m_muted_on_creation(muted),
00013     m_main_device(QString::null), m_passthru_device(QString::null),
00014     m_no_audio_in(false), m_no_audio_out(false), m_controls_volume(true)
00015 {
00016     m_controls_volume = gCoreContext->GetNumSetting("MythControlsVolume", 1);
00017 }
00018 
00019 AudioPlayer::~AudioPlayer()
00020 {
00021     DeleteOutput();
00022     m_visuals.clear();
00023 }
00024 
00025 void AudioPlayer::addVisual(MythTV::Visual *vis)
00026 {
00027     if (!m_audioOutput)
00028         return;
00029 
00030     QMutexLocker lock(&m_lock);
00031     Visuals::iterator it = std::find(m_visuals.begin(), m_visuals.end(), vis);
00032     if (it == m_visuals.end())
00033     {
00034         m_visuals.push_back(vis);
00035         m_audioOutput->addVisual(vis);
00036     }
00037 }
00038 
00039 void AudioPlayer::removeVisual(MythTV::Visual *vis)
00040 {
00041     if (!m_audioOutput)
00042         return;
00043 
00044     QMutexLocker lock(&m_lock);
00045     Visuals::iterator it = std::find(m_visuals.begin(), m_visuals.end(), vis);
00046     if (it != m_visuals.end())
00047     {
00048         m_visuals.erase(it);
00049         m_audioOutput->removeVisual(vis);
00050     }
00051 }
00052 
00053 void AudioPlayer::AddVisuals(void)
00054 {
00055     if (!m_audioOutput)
00056         return;
00057 
00058     QMutexLocker lock(&m_lock);
00059     for (uint i = 0; i < m_visuals.size(); i++)
00060         m_audioOutput->addVisual(m_visuals[i]);
00061 }
00062 
00063 void AudioPlayer::RemoveVisuals(void)
00064 {
00065     if (!m_audioOutput)
00066         return;
00067 
00068     QMutexLocker lock(&m_lock);
00069     for (uint i = 0; i < m_visuals.size(); i++)
00070         m_audioOutput->removeVisual(m_visuals[i]);
00071 }
00072 
00073 void AudioPlayer::ResetVisuals(void)
00074 {
00075     if (!m_audioOutput)
00076         return;
00077 
00078     QMutexLocker lock(&m_lock);
00079     for (uint i = 0; i < m_visuals.size(); i++)
00080         m_visuals[i]->prepare();
00081 }
00082 
00083 void AudioPlayer::Reset(void)
00084 {
00085     if (!m_audioOutput)
00086         return;
00087 
00088     QMutexLocker lock(&m_lock);
00089     m_audioOutput->Reset();
00090 }
00091 
00092 void AudioPlayer::DeleteOutput(void)
00093 {
00094     RemoveVisuals();
00095     QMutexLocker locker(&m_lock);
00096     if (m_audioOutput)
00097     {
00098         delete m_audioOutput;
00099         m_audioOutput = NULL;
00100     }
00101     m_no_audio_out = true;
00102 }
00103 
00104 QString AudioPlayer::ReinitAudio(void)
00105 {
00106     bool want_audio = m_parent->IsAudioNeeded();
00107     QString errMsg = QString::null;
00108     QMutexLocker lock(&m_lock);
00109 
00110     bool firstinit = (m_format == FORMAT_NONE &&
00111                       m_channels < 0 &&
00112                       m_samplerate == 44100);
00113 
00114     if ((m_format == FORMAT_NONE) ||
00115         (m_channels <= 0) ||
00116         (m_samplerate <= 0))
00117     {
00118         m_no_audio_in = m_no_audio_out = true;
00119     }
00120     else
00121         m_no_audio_in = false;
00122 
00123     if (want_audio && !m_audioOutput)
00124     {
00125         // AudioOutput has never been created and we will want audio
00126         AudioSettings aos = AudioSettings(m_main_device,
00127                                           m_passthru_device,
00128                                           m_format, m_channels,
00129                                           m_codec, m_samplerate,
00130                                           AUDIOOUTPUT_VIDEO,
00131                                           m_controls_volume, m_passthru);
00132         if (m_no_audio_in)
00133             aos.init = false;
00134 
00135         m_audioOutput = AudioOutput::OpenAudio(aos);
00136         if (!m_audioOutput)
00137         {
00138             errMsg = QObject::tr("Unable to create AudioOutput.");
00139         }
00140         else
00141         {
00142             errMsg = m_audioOutput->GetError();
00143         }
00144         AddVisuals();
00145     }
00146     else if (!m_no_audio_in && m_audioOutput)
00147     {
00148         const AudioSettings settings(m_format, m_channels, m_codec,
00149                                      m_samplerate, m_passthru, 0,
00150                                      m_codec_profile);
00151         m_audioOutput->Reconfigure(settings);
00152         errMsg = m_audioOutput->GetError();
00153         SetStretchFactor(m_stretchfactor);
00154     }
00155 
00156     if (!errMsg.isEmpty())
00157     {
00158         if (!firstinit)
00159         {
00160             LOG(VB_GENERAL, LOG_NOTICE, LOC + "Disabling Audio" +
00161                     QString(", reason is: %1").arg(errMsg));
00162         }
00163         m_no_audio_out = true;
00164     }
00165     else if (m_no_audio_out && m_audioOutput)
00166     {
00167         LOG(VB_GENERAL, LOG_NOTICE, LOC + "Enabling Audio");
00168         m_no_audio_out = false;
00169     }
00170 
00171     if (m_muted_on_creation)
00172     {
00173         SetMuteState(kMuteAll);
00174         m_muted_on_creation = false;
00175     }
00176 
00177     ResetVisuals();
00178 
00179     return errMsg;
00180 }
00181 
00182 void AudioPlayer::CheckFormat(void)
00183 {
00184     if (m_format == FORMAT_NONE)
00185         m_no_audio_in = m_no_audio_out = true;
00186 }
00187 
00188 bool AudioPlayer::Pause(bool pause)
00189 {
00190     if (!m_audioOutput || m_no_audio_out)
00191         return false;
00192 
00193     QMutexLocker lock(&m_lock);
00194     m_audioOutput->Pause(pause);
00195     return true;
00196 }
00197 
00198 bool AudioPlayer::IsPaused(void)
00199 {
00200     if (!m_audioOutput || m_no_audio_out)
00201         return false;
00202     QMutexLocker lock(&m_lock);
00203     return m_audioOutput->IsPaused();
00204 }
00205 
00206 void AudioPlayer::PauseAudioUntilBuffered()
00207 {
00208     if (!m_audioOutput || m_no_audio_out)
00209         return;
00210     QMutexLocker lock(&m_lock);
00211     m_audioOutput->PauseUntilBuffered();
00212 }
00213 
00214 void AudioPlayer::SetAudioOutput(AudioOutput *ao)
00215 {
00216     // delete current audio class if any
00217     DeleteOutput();
00218     m_lock.lock();
00219     m_audioOutput = ao;
00220     AddVisuals();
00221     m_lock.unlock();
00222 }
00223 
00224 uint AudioPlayer::GetVolume(void)
00225 {
00226     if (!m_audioOutput || m_no_audio_out)
00227         return 0;
00228     QMutexLocker lock(&m_lock);
00229     return m_audioOutput->GetCurrentVolume();
00230 }
00231 
00236 void AudioPlayer::SetAudioInfo(const QString &main_device,
00237                                const QString &passthru_device,
00238                                uint           samplerate,
00239                                int            codec_profile)
00240 {
00241     m_main_device = m_passthru_device = QString::null;
00242     if (!main_device.isEmpty())
00243     {
00244         m_main_device = main_device;
00245         m_main_device.detach();
00246     }
00247     if (!passthru_device.isEmpty())
00248     {
00249         m_passthru_device = passthru_device;
00250         m_passthru_device.detach();
00251     }
00252     m_samplerate = (int)samplerate;
00253     m_codec_profile    = codec_profile;
00254 }
00255 
00260 void AudioPlayer::SetAudioParams(AudioFormat format, int orig_channels,
00261                                  int channels, int codec,
00262                                  int samplerate, bool passthru,
00263                                  int codec_profile)
00264 {
00265     m_format        = format;
00266     m_orig_channels = orig_channels;
00267     m_channels      = channels;
00268     m_codec         = codec;
00269     m_samplerate    = samplerate;
00270     m_passthru      = passthru;
00271     m_codec_profile = codec_profile;
00272 
00273     ResetVisuals();
00274 }
00275 
00276 void AudioPlayer::SetEffDsp(int dsprate)
00277 {
00278     if (!m_audioOutput || !m_no_audio_out)
00279         return;
00280     QMutexLocker lock(&m_lock);
00281     m_audioOutput->SetEffDsp(dsprate);
00282 }
00283 
00284 bool AudioPlayer::SetMuted(bool mute)
00285 {
00286     bool is_muted = IsMuted();
00287     QMutexLocker lock(&m_lock);
00288 
00289     if (m_audioOutput && !m_no_audio_out && !is_muted && mute &&
00290         (kMuteAll == SetMuteState(kMuteAll)))
00291     {
00292         LOG(VB_AUDIO, LOG_INFO, QString("muting sound %1").arg(IsMuted()));
00293         return true;
00294     }
00295     else if (m_audioOutput && !m_no_audio_out && is_muted && !mute &&
00296              (kMuteOff == SetMuteState(kMuteOff)))
00297     {
00298         LOG(VB_AUDIO, LOG_INFO, QString("unmuting sound %1").arg(IsMuted()));
00299         return true;
00300     }
00301 
00302     LOG(VB_AUDIO, LOG_ERR,
00303         QString("not changing sound mute state %1").arg(IsMuted()));
00304 
00305     return false;
00306 }
00307 
00308 MuteState AudioPlayer::SetMuteState(MuteState mstate)
00309 {
00310     if (!m_audioOutput || m_no_audio_out)
00311         return kMuteAll;
00312     QMutexLocker lock(&m_lock);
00313     return m_audioOutput->SetMuteState(mstate);
00314 }
00315 
00316 MuteState AudioPlayer::IncrMuteState(void)
00317 {
00318     if (!m_audioOutput || m_no_audio_out)
00319         return kMuteAll;
00320     return SetMuteState(VolumeBase::NextMuteState(GetMuteState()));
00321 }
00322 
00323 MuteState AudioPlayer::GetMuteState(void)
00324 {
00325     if (!m_audioOutput || m_no_audio_out)
00326         return kMuteAll;
00327     QMutexLocker lock(&m_lock);
00328     return m_audioOutput->GetMuteState();
00329 }
00330 
00331 uint AudioPlayer::AdjustVolume(int change)
00332 {
00333     if (!m_audioOutput || m_no_audio_out)
00334         return GetVolume();
00335     QMutexLocker lock(&m_lock);
00336     m_audioOutput->AdjustCurrentVolume(change);
00337     return GetVolume();
00338 }
00339 
00340 uint AudioPlayer::SetVolume(int newvolume)
00341 {
00342     if (!m_audioOutput || m_no_audio_out)
00343         return GetVolume();
00344     QMutexLocker lock(&m_lock);
00345     m_audioOutput->SetCurrentVolume(newvolume);
00346     return GetVolume();
00347 }
00348 
00349 int64_t AudioPlayer::GetAudioTime(void)
00350 {
00351     if (!m_audioOutput || m_no_audio_out)
00352         return 0LL;
00353     QMutexLocker lock(&m_lock);
00354     return m_audioOutput->GetAudiotime();
00355 }
00356 
00357 bool AudioPlayer::IsUpmixing(void)
00358 {
00359     if (!m_audioOutput)
00360         return false;
00361     QMutexLocker lock(&m_lock);
00362     return m_audioOutput->IsUpmixing();
00363 }
00364 
00365 bool AudioPlayer::EnableUpmix(bool enable, bool toggle)
00366 {
00367     if (!m_audioOutput)
00368         return false;
00369     QMutexLocker lock(&m_lock);
00370     if (toggle || (enable != IsUpmixing()))
00371         return m_audioOutput->ToggleUpmix();
00372     return enable;
00373 }
00374 
00375 bool AudioPlayer::CanUpmix(void)
00376 {
00377     if (!m_audioOutput)
00378         return false;
00379     QMutexLocker lock(&m_lock);
00380     return m_audioOutput->CanUpmix();
00381 }
00382 
00383 void AudioPlayer::SetStretchFactor(float factor)
00384 {
00385     m_stretchfactor = factor;
00386     if (!m_audioOutput)
00387         return;
00388     QMutexLocker lock(&m_lock);
00389     m_audioOutput->SetStretchFactor(m_stretchfactor);
00390 }
00391 
00392 // The following methods are not locked as this hinders performance.
00393 // They are however only called from the Decoder and only the decode
00394 // thread will trigger a deletion/recreation of the AudioOutput device, hence
00395 // they should be safe.
00396 
00397 inline bool TestDigitalFeature(AudioOutput *ao, DigitalFeature feature)
00398 {
00399     if (!ao)
00400         return false;
00401 
00402     return ao->GetOutputSettingsUsers(true)->canFeature(feature);
00403 }
00404 
00405 bool AudioPlayer::CanAC3(void)
00406 {
00407     return TestDigitalFeature(m_audioOutput, FEATURE_AC3);
00408 }
00409 
00410 bool AudioPlayer::CanDTS(void)
00411 {
00412     return TestDigitalFeature(m_audioOutput, FEATURE_DTS);
00413 }
00414 
00415 bool AudioPlayer::CanEAC3(void)
00416 {
00417     return TestDigitalFeature(m_audioOutput, FEATURE_EAC3);
00418 }
00419 
00420 bool AudioPlayer::CanTrueHD(void)
00421 {
00422     return TestDigitalFeature(m_audioOutput, FEATURE_TRUEHD);
00423 }
00424 
00425 bool AudioPlayer::CanDTSHD(void)
00426 {
00427     return TestDigitalFeature(m_audioOutput, FEATURE_DTSHD);
00428 }
00429 
00430 uint AudioPlayer::GetMaxChannels(void)
00431 {
00432     if (!m_audioOutput)
00433         return 2;
00434     return m_audioOutput->GetOutputSettingsUsers(false)->BestSupportedChannels();
00435 }
00436 
00437 int AudioPlayer::GetMaxHDRate()
00438 {
00439     if (!m_audioOutput)
00440         return 0;
00441     return m_audioOutput->GetOutputSettingsUsers(true)->GetMaxHDRate();
00442 }
00443 
00444 bool AudioPlayer::CanPassthrough(int samplerate, int channels,
00445                                  int codec, int profile)
00446 {
00447     if (!m_audioOutput)
00448         return false;
00449     return m_audioOutput->CanPassthrough(samplerate, channels, codec, profile);
00450 }
00451 
00452 bool AudioPlayer::CanDownmix(void)
00453 {
00454     if (!m_audioOutput)
00455         return false;
00456     return m_audioOutput->CanDownmix();
00457 }
00458 
00459 /*
00460  * if frames = -1 : let AudioOuput calculate value
00461  * if frames = 0 && len > 0: will calculate according to len
00462  */
00463 void AudioPlayer::AddAudioData(char *buffer, int len,
00464                                int64_t timecode, int frames)
00465 {
00466     if (!m_audioOutput || m_no_audio_out)
00467         return;
00468 
00469     if (m_parent->PrepareAudioSample(timecode) && !m_no_audio_out)
00470         m_audioOutput->Drain();
00471     int samplesize = m_audioOutput->GetBytesPerFrame();
00472 
00473     if (samplesize <= 0)
00474         return;
00475 
00476     if (frames == 0 && len > 0)
00477         frames = len / samplesize;
00478 
00479     if (!m_audioOutput->AddData(buffer, len, timecode, frames))
00480         LOG(VB_PLAYBACK, LOG_ERR, LOC + "AddAudioData(): "
00481                 "Audio buffer overflow, audio data lost!");
00482 }
00483 
00484 bool AudioPlayer::NeedDecodingBeforePassthrough(void)
00485 {
00486     if (!m_audioOutput)
00487         return true;
00488     else
00489         return m_audioOutput->NeedDecodingBeforePassthrough();
00490 }
00491 
00492 int64_t AudioPlayer::LengthLastData(void)
00493 {
00494     if (!m_audioOutput)
00495         return 0;
00496     else
00497         return m_audioOutput->LengthLastData();
00498 }
00499 
00500 bool AudioPlayer::GetBufferStatus(uint &fill, uint &total)
00501 {
00502     fill = total = 0;
00503     if (!m_audioOutput || m_no_audio_out)
00504         return false;
00505     m_audioOutput->GetBufferStatus(fill, total);
00506     return true;
00507 }
00508 
00509 bool AudioPlayer::IsBufferAlmostFull(void)
00510 {
00511     uint ofill = 0, ototal = 0, othresh = 0;
00512     if (GetBufferStatus(ofill, ototal))
00513     {
00514         othresh =  ((ototal>>1) + (ototal>>2));
00515         return ofill > othresh;
00516     }
00517     return false;
00518 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends