Merge pull request #26287 from CrystalP/ref-savefilestatejob
[xbmc.git] / xbmc / cores / RetroPlayer / streams / RetroPlayerAudio.cpp
blob3bad9d60ad280f44c2c2a54d58c49cf73a4a4732
1 /*
2 * Copyright (C) 2012-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
9 #include "RetroPlayerAudio.h"
11 #include "ServiceBroker.h"
12 #include "cores/AudioEngine/Interfaces/AE.h"
13 #include "cores/AudioEngine/Interfaces/AEStream.h"
14 #include "cores/AudioEngine/Utils/AEChannelInfo.h"
15 #include "cores/AudioEngine/Utils/AEUtil.h"
16 #include "cores/RetroPlayer/audio/AudioTranslator.h"
17 #include "cores/RetroPlayer/process/RPProcessInfo.h"
18 #include "utils/log.h"
20 #include <cmath>
22 using namespace KODI;
23 using namespace RETRO;
25 const double MAX_DELAY = 0.3; // seconds
27 CRetroPlayerAudio::CRetroPlayerAudio(CRPProcessInfo& processInfo)
28 : m_processInfo(processInfo), m_pAudioStream(nullptr)
30 CLog::Log(LOGDEBUG, "RetroPlayer[AUDIO]: Initializing audio");
33 CRetroPlayerAudio::~CRetroPlayerAudio()
35 CLog::Log(LOGDEBUG, "RetroPlayer[AUDIO]: Deinitializing audio");
37 CloseStream();
40 bool CRetroPlayerAudio::OpenStream(const StreamProperties& properties)
42 const AudioStreamProperties& audioProperties =
43 static_cast<const AudioStreamProperties&>(properties);
45 const AEDataFormat pcmFormat = CAudioTranslator::TranslatePCMFormat(audioProperties.format);
46 if (pcmFormat == AE_FMT_INVALID)
48 CLog::Log(LOGERROR, "RetroPlayer[AUDIO]: Unknown PCM format: {}",
49 static_cast<int>(audioProperties.format));
50 return false;
53 unsigned int iSampleRate = static_cast<unsigned int>(std::round(audioProperties.sampleRate));
54 if (iSampleRate == 0)
56 CLog::Log(LOGERROR, "RetroPlayer[AUDIO]: Invalid samplerate: {:f}", audioProperties.sampleRate);
57 return false;
60 CAEChannelInfo channelLayout;
61 for (auto it = audioProperties.channelMap.begin(); it != audioProperties.channelMap.end(); ++it)
63 AEChannel channel = CAudioTranslator::TranslateAudioChannel(*it);
64 if (channel == AE_CH_NULL)
65 break;
67 channelLayout += channel;
70 if (!channelLayout.IsLayoutValid())
72 CLog::Log(LOGERROR, "RetroPlayer[AUDIO]: Empty channel layout");
73 return false;
76 if (m_pAudioStream != nullptr)
77 CloseStream();
79 IAE* audioEngine = CServiceBroker::GetActiveAE();
80 if (audioEngine == nullptr)
81 return false;
83 CLog::Log(
84 LOGINFO,
85 "RetroPlayer[AUDIO]: Creating audio stream, format = {}, sample rate = {}, channels = {}",
86 CAEUtil::DataFormatToStr(pcmFormat), iSampleRate, channelLayout.Count());
88 AEAudioFormat audioFormat;
89 audioFormat.m_dataFormat = pcmFormat;
90 audioFormat.m_sampleRate = iSampleRate;
91 audioFormat.m_channelLayout = channelLayout;
92 m_pAudioStream = audioEngine->MakeStream(audioFormat);
94 if (m_pAudioStream == nullptr)
96 CLog::Log(LOGERROR, "RetroPlayer[AUDIO]: Failed to create audio stream");
97 return false;
100 m_processInfo.SetAudioChannels(audioFormat.m_channelLayout);
101 m_processInfo.SetAudioSampleRate(audioFormat.m_sampleRate);
102 m_processInfo.SetAudioBitsPerSample(CAEUtil::DataFormatToUsedBits(audioFormat.m_dataFormat));
104 return true;
107 void CRetroPlayerAudio::AddStreamData(const StreamPacket& packet)
109 const AudioStreamPacket& audioPacket = static_cast<const AudioStreamPacket&>(packet);
111 if (m_bAudioEnabled)
113 if (m_pAudioStream)
115 const double delaySecs = m_pAudioStream->GetDelay();
117 const size_t frameSize = m_pAudioStream->GetChannelCount() *
118 (CAEUtil::DataFormatToBits(m_pAudioStream->GetDataFormat()) >> 3);
120 const unsigned int frameCount = static_cast<unsigned int>(audioPacket.size / frameSize);
122 if (delaySecs > MAX_DELAY)
124 m_pAudioStream->Flush();
125 CLog::Log(LOGDEBUG, "RetroPlayer[AUDIO]: Audio delay ({:0.2f} ms) is too high - flushing",
126 delaySecs * 1000);
129 m_pAudioStream->AddData(&audioPacket.data, 0, frameCount, nullptr);
134 void CRetroPlayerAudio::CloseStream()
136 if (m_pAudioStream)
138 CLog::Log(LOGDEBUG, "RetroPlayer[AUDIO]: Closing audio stream");
140 m_pAudioStream.reset();