diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/AudioDSPAddons/ActiveAEDSPProcess.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/AudioDSPAddons/ActiveAEDSPProcess.cpp index 2128cbd6279e5..f459a0cc1aa9d 100644 --- a/xbmc/cores/AudioEngine/Engines/ActiveAE/AudioDSPAddons/ActiveAEDSPProcess.cpp +++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/AudioDSPAddons/ActiveAEDSPProcess.cpp @@ -34,13 +34,15 @@ extern "C" { #include "cores/AudioEngine/Utils/AEUtil.h" #include "cores/IPlayer.h" #include "settings/MediaSettings.h" -#include "utils/log.h" #include "utils/TimeUtils.h" using namespace ADDON; using namespace ActiveAE; #define MIN_DSP_ARRAY_SIZE 4096 +#define FFMPEG_PROC_ARRAY_IN 0 +#define FFMPEG_PROC_ARRAY_OUT 1 + CActiveAEDSPProcess::CActiveAEDSPProcess(AE_DSP_STREAM_ID streamId) : m_streamId(streamId) @@ -60,7 +62,7 @@ CActiveAEDSPProcess::CActiveAEDSPProcess(AE_DSP_STREAM_ID streamId) * Create predefined process arrays on every supported channel for audio dsp's. * All are set if used or not for safety reason and unsued ones can be used from * dsp addons as buffer arrays. - * If a bigger size is needed it becomes reallocated during DSP processing. + * If a bigger size is neeeded it becomes reallocated during DSP processing. */ m_processArraySize = MIN_DSP_ARRAY_SIZE; for (int i = 0; i < AE_DSP_CH_MAX; ++i) @@ -74,11 +76,8 @@ CActiveAEDSPProcess::~CActiveAEDSPProcess() { ResetStreamFunctionsSelection(); - if (m_resamplerDSPProcessor) - { - delete m_resamplerDSPProcessor; - m_resamplerDSPProcessor = NULL; - } + delete m_resamplerDSPProcessor; + m_resamplerDSPProcessor = NULL; /* Clear the buffer arrays */ for (int i = 0; i < AE_DSP_CH_MAX; ++i) @@ -107,19 +106,19 @@ void CActiveAEDSPProcess::ResetStreamFunctionsSelection() m_usedMap.clear(); } -bool CActiveAEDSPProcess::Create(const AEAudioFormat &inputFormat, const AEAudioFormat &outputFormat, bool upmix, AEQuality quality, AE_DSP_STREAMTYPE iStreamType, +bool CActiveAEDSPProcess::Create(const AEAudioFormat &inputFormat, const AEAudioFormat &outputFormat, bool upmix, bool bypassDSP, AEQuality quality, AE_DSP_STREAMTYPE iStreamType, enum AVMatrixEncoding matrix_encoding, enum AVAudioServiceType audio_service_type, int profile) { m_inputFormat = inputFormat; /*!< Input format of processed stream */ m_outputFormat = outputFormat; /*!< Output format of required stream (set from ADSP system on startup, to have ffmpeg compatible format */ - m_outputSamplerate = m_inputFormat.m_sampleRate; /*!< If no resampler addon is present output samplerate is the same as input */ - m_outputFrames = m_inputFormat.m_frames; + m_outputFormat.m_sampleRate = m_inputFormat.m_sampleRate; /*!< If no resampler addon is present output samplerate is the same as input */ + m_outputFormat.m_frames = m_inputFormat.m_frames; m_streamQuality = quality; /*!< from KODI on settings selected resample quality, also passed to addons to support different quality */ - m_dataFormat = AE_FMT_FLOAT; /*!< the base stream format, hard set to float */ m_activeMode = AE_DSP_MASTER_MODE_ID_PASSOVER; /*!< Reset the pointer for m_MasterModes about active master process, set here during mode selection */ m_ffMpegMatrixEncoding = matrix_encoding; m_ffMpegAudioServiceType= audio_service_type; m_ffMpegProfile = profile; + m_bypassDSP = bypassDSP; CSingleLock lock(m_restartSection); @@ -184,7 +183,6 @@ bool CActiveAEDSPProcess::Create(const AEAudioFormat &inputFormat, const AEAudio /*! * Set general stream information about the processed stream */ - if (g_application.m_pPlayer->GetAudioStreamCount() > 0) { int identifier = CMediaSettings::GetInstance().GetCurrentVideoSettings().m_AudioStream; @@ -241,353 +239,27 @@ bool CActiveAEDSPProcess::Create(const AEAudioFormat &inputFormat, const AEAudio m_addonSettings.bInputResamplingActive = false; /*! Becomes true if input resampling is in use */ m_addonSettings.iQualityLevel = m_streamQuality; /*! Requested stream processing quality, is optional and can be from addon ignored */ - if (m_inputFormat.m_channelLayout.HasChannel(AE_CH_FL)) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_FL; - if (m_inputFormat.m_channelLayout.HasChannel(AE_CH_FR)) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_FR; - if (m_inputFormat.m_channelLayout.HasChannel(AE_CH_FC)) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_FC; - if (m_inputFormat.m_channelLayout.HasChannel(AE_CH_LFE)) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_LFE; - if (m_inputFormat.m_channelLayout.HasChannel(AE_CH_BL)) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_BL; - if (m_inputFormat.m_channelLayout.HasChannel(AE_CH_BR)) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_BR; - if (m_inputFormat.m_channelLayout.HasChannel(AE_CH_FLOC)) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_FLOC; - if (m_inputFormat.m_channelLayout.HasChannel(AE_CH_FROC)) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_FROC; - if (m_inputFormat.m_channelLayout.HasChannel(AE_CH_BC)) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_BC; - if (m_inputFormat.m_channelLayout.HasChannel(AE_CH_SL)) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_SL; - if (m_inputFormat.m_channelLayout.HasChannel(AE_CH_SR)) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_SR; - if (m_inputFormat.m_channelLayout.HasChannel(AE_CH_TFL)) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_TFL; - if (m_inputFormat.m_channelLayout.HasChannel(AE_CH_TFR)) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_TFR; - if (m_inputFormat.m_channelLayout.HasChannel(AE_CH_TFC)) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_TFC; - if (m_inputFormat.m_channelLayout.HasChannel(AE_CH_TC)) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_TC; - if (m_inputFormat.m_channelLayout.HasChannel(AE_CH_TBL)) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_TBL; - if (m_inputFormat.m_channelLayout.HasChannel(AE_CH_TBR)) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_TBR; - if (m_inputFormat.m_channelLayout.HasChannel(AE_CH_TBC)) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_TBC; - if (m_inputFormat.m_channelLayout.HasChannel(AE_CH_BLOC)) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_BLOC; - if (m_inputFormat.m_channelLayout.HasChannel(AE_CH_BROC)) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_BROC; - - if (m_outputFormat.m_channelLayout.HasChannel(AE_CH_FL)) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_FL; - if (m_outputFormat.m_channelLayout.HasChannel(AE_CH_FR)) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_FR; - if (m_outputFormat.m_channelLayout.HasChannel(AE_CH_FC)) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_FC; - if (m_outputFormat.m_channelLayout.HasChannel(AE_CH_LFE)) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_LFE; - if (m_outputFormat.m_channelLayout.HasChannel(AE_CH_BL)) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_BL; - if (m_outputFormat.m_channelLayout.HasChannel(AE_CH_BR)) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_BR; - if (m_outputFormat.m_channelLayout.HasChannel(AE_CH_FLOC)) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_FLOC; - if (m_outputFormat.m_channelLayout.HasChannel(AE_CH_FROC)) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_FROC; - if (m_outputFormat.m_channelLayout.HasChannel(AE_CH_BC)) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_BC; - if (m_outputFormat.m_channelLayout.HasChannel(AE_CH_SL)) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_SL; - if (m_outputFormat.m_channelLayout.HasChannel(AE_CH_SR)) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_SR; - if (m_outputFormat.m_channelLayout.HasChannel(AE_CH_TFL)) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_TFL; - if (m_outputFormat.m_channelLayout.HasChannel(AE_CH_TFR)) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_TFR; - if (m_outputFormat.m_channelLayout.HasChannel(AE_CH_TFC)) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_TFC; - if (m_outputFormat.m_channelLayout.HasChannel(AE_CH_TC)) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_TC; - if (m_outputFormat.m_channelLayout.HasChannel(AE_CH_TBL)) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_TBL; - if (m_outputFormat.m_channelLayout.HasChannel(AE_CH_TBR)) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_TBR; - if (m_outputFormat.m_channelLayout.HasChannel(AE_CH_TBC)) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_TBC; - if (m_outputFormat.m_channelLayout.HasChannel(AE_CH_BLOC)) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_BLOC; - if (m_outputFormat.m_channelLayout.HasChannel(AE_CH_BROC)) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_BROC; - - /*! - * Setup off mode, used if dsp master processing is set off, required to have data - * for stream information functions. - */ - sDSPProcessHandle internalMode; - internalMode.Clear(); - internalMode.iAddonModeNumber = AE_DSP_MASTER_MODE_ID_PASSOVER; - internalMode.pMode = CActiveAEDSPModePtr(new CActiveAEDSPMode(internalMode.iAddonModeNumber, (AE_DSP_BASETYPE)m_addonStreamProperties.iBaseType)); - internalMode.iLastTime = 0; - m_addons_MasterProc.push_back(internalMode); - m_activeMode = AE_DSP_MASTER_MODE_ID_PASSOVER; - - if (upmix && m_addonSettings.iInChannels <= 2) - { - internalMode.Clear(); - internalMode.iAddonModeNumber = AE_DSP_MASTER_MODE_ID_INTERNAL_STEREO_UPMIX; - internalMode.pMode = CActiveAEDSPModePtr(new CActiveAEDSPMode(internalMode.iAddonModeNumber, (AE_DSP_BASETYPE)m_addonStreamProperties.iBaseType)); - internalMode.iLastTime = 0; - m_addons_MasterProc.push_back(internalMode); - } - - /*! - * Load all selected processing types, stored in a database and available from addons + /*! @warning If you change or add new channel enums to AEChannel in + * xbmc/cores/AudioEngine/Utils/AEChannelData.h you have to adapt this loop */ - AE_DSP_ADDONMAP addonMap; - if (CServiceBroker::GetADSP().GetEnabledAudioDSPAddons(addonMap) > 0) + for (int ii = 0; ii < AE_DSP_CH_MAX; ii++) { - int foundInputResamplerId = -1; /*!< Used to prevent double call of StreamCreate if input stream resampling is together with outer processing types */ - - /*! - * First find input resample addon to become information about processing sample rate and - * load one allowed before master processing & final resample addon - */ - CLog::Log(LOGDEBUG, " ---- DSP input resample addon ---"); - const AE_DSP_MODELIST listInputResample = CServiceBroker::GetADSP().GetAvailableModes(AE_DSP_MODE_TYPE_INPUT_RESAMPLE); - if (listInputResample.empty()) - CLog::Log(LOGDEBUG, " | - no input resample addon present or enabled"); - for (unsigned int i = 0; i < listInputResample.size(); ++i) - { - /// For resample only one call is allowed. Use first one and ignore everything else. - CActiveAEDSPModePtr pMode = listInputResample[i].first; - AE_DSP_ADDON addon = listInputResample[i].second; - if (!CAddonMgr::GetInstance().IsAddonDisabled(addon->ID()) && addon->SupportsInputResample() && pMode->IsEnabled()) - { - ADDON_HANDLE_STRUCT handle; - AE_DSP_ERROR err = addon->StreamCreate(&m_addonSettings, &m_addonStreamProperties, &handle); - if (err == AE_DSP_ERROR_NO_ERROR) - { - if (addon->StreamIsModeSupported(&handle, pMode->ModeType(), pMode->AddonModeNumber(), pMode->ModeID())) - { - int processSamplerate = addon->InputResampleSampleRate(&handle); - if (processSamplerate == (int)m_inputFormat.m_sampleRate) - { - CLog::Log(LOGDEBUG, " | - input resample addon %s ignored, input sample rate %i the same as process rate", addon->GetFriendlyName().c_str(), m_inputFormat.m_sampleRate); - } - else if (processSamplerate > 0) - { - CLog::Log(LOGDEBUG, " | - %s with resampling from %i to %i", addon->GetAudioDSPName().c_str(), m_inputFormat.m_sampleRate, processSamplerate); - - m_outputSamplerate = processSamplerate; /*!< overwrite output sample rate with the new rate */ - m_outputFrames = (int) ceil((1.0 * processSamplerate) / m_addonSettings.iInSamplerate * m_addonSettings.iInFrames); - m_addonSettings.iProcessSamplerate = m_outputSamplerate; /*!< the processing sample rate required for all behind called processes */ - m_addonSettings.iProcessFrames = m_outputFrames; - m_addonSettings.bInputResamplingActive = true; - - m_addon_InputResample.iAddonModeNumber = pMode->AddonModeNumber(); - m_addon_InputResample.pMode = pMode; - m_addon_InputResample.pAddon = addon; - m_addon_InputResample.iLastTime = 0; - } - else - { - CLog::Log(LOGERROR, "ActiveAE DSP - %s - input resample addon %s return invalid samplerate and becomes disabled", __FUNCTION__, addon->GetFriendlyName().c_str()); - } - - unsigned int id = addon->GetID(); - m_addon_Handles[id] = handle; - foundInputResamplerId = id; - m_usedMap.insert(std::make_pair(id, addon)); - } - } - else if (err != AE_DSP_ERROR_IGNORE_ME) - CLog::Log(LOGERROR, "ActiveAE DSP - %s - input resample addon creation failed on %s with %s", __FUNCTION__, addon->GetAudioDSPName().c_str(), CActiveAEDSPAddon::ToString(err)); - break; - } - } - - /*! - * Now init all other dsp relevant addons - */ - for (AE_DSP_ADDONMAP_ITR itr = addonMap.begin(); itr != addonMap.end(); ++itr) - { - AE_DSP_ADDON addon = itr->second; - int id = addon->GetID(); - if (!CAddonMgr::GetInstance().IsAddonDisabled(addon->ID()) && id != foundInputResamplerId) - { - ADDON_HANDLE_STRUCT handle; - AE_DSP_ERROR err = addon->StreamCreate(&m_addonSettings, &m_addonStreamProperties, &handle); - if (err == AE_DSP_ERROR_NO_ERROR) - { - m_addon_Handles[id] = handle; - m_usedMap.insert(std::make_pair(id, addon)); - } - else if (err == AE_DSP_ERROR_IGNORE_ME) - continue; - else - CLog::Log(LOGERROR, "ActiveAE DSP - %s - addon creation failed on %s with %s", __FUNCTION__, addon->GetAudioDSPName().c_str(), CActiveAEDSPAddon::ToString(err)); - } - } - - for (AE_DSP_ADDONMAP_ITR itr = m_usedMap.begin(); itr != m_usedMap.end(); ++itr) - { - AE_DSP_ADDON addon = itr->second; - if (addon->SupportsInputInfoProcess()) - { - sDSPProcessHandle modeHandle; - modeHandle.pAddon = addon; - modeHandle.handle = m_addon_Handles[addon->GetID()]; - m_addons_InputProc.push_back(modeHandle); - } - } - - /*! - * Load all required pre process dsp addon functions - */ - CLog::Log(LOGDEBUG, " ---- DSP active pre process modes ---"); - const AE_DSP_MODELIST listPreProcess = CServiceBroker::GetADSP().GetAvailableModes(AE_DSP_MODE_TYPE_PRE_PROCESS); - for (unsigned int i = 0; i < listPreProcess.size(); ++i) - { - CActiveAEDSPModePtr pMode = listPreProcess[i].first; - AE_DSP_ADDON addon = listPreProcess[i].second; - int id = addon->GetID(); - - if (m_usedMap.find(id) == m_usedMap.end()) - continue; - if (!CAddonMgr::GetInstance().IsAddonDisabled(addon->ID()) && addon->SupportsPreProcess() && pMode->IsEnabled() && - addon->StreamIsModeSupported(&m_addon_Handles[id], pMode->ModeType(), pMode->AddonModeNumber(), pMode->ModeID())) - { - CLog::Log(LOGDEBUG, " | - %i - %s (%s)", i, pMode->AddonModeName().c_str(), addon->GetAudioDSPName().c_str()); - - sDSPProcessHandle modeHandle; - modeHandle.iAddonModeNumber = pMode->AddonModeNumber(); - modeHandle.pMode = pMode; - modeHandle.pAddon = addon; - modeHandle.iLastTime = 0; - modeHandle.handle = m_addon_Handles[id]; - m_addons_PreProc.push_back(modeHandle); - } - } - if (m_addons_PreProc.empty()) - CLog::Log(LOGDEBUG, " | - no pre processing addon's present or enabled"); - - /*! - * Load all available master modes from addons and put together with database - */ - CLog::Log(LOGDEBUG, " ---- DSP active master process modes ---"); - const AE_DSP_MODELIST listMasterProcess = CServiceBroker::GetADSP().GetAvailableModes(AE_DSP_MODE_TYPE_MASTER_PROCESS); - for (unsigned int i = 0; i < listMasterProcess.size(); ++i) - { - CActiveAEDSPModePtr pMode = listMasterProcess[i].first; - AE_DSP_ADDON addon = listMasterProcess[i].second; - int id = addon->GetID(); - - if (m_usedMap.find(id) == m_usedMap.end()) - continue; - if (!CAddonMgr::GetInstance().IsAddonDisabled(addon->ID()) && addon->SupportsMasterProcess() && pMode->IsEnabled() && - addon->StreamIsModeSupported(&m_addon_Handles[id], pMode->ModeType(), pMode->AddonModeNumber(), pMode->ModeID())) - { - CLog::Log(LOGDEBUG, " | - %i - %s (%s)", i, pMode->AddonModeName().c_str(), addon->GetAudioDSPName().c_str()); - - sDSPProcessHandle modeHandle; - modeHandle.iAddonModeNumber = pMode->AddonModeNumber(); - modeHandle.pMode = pMode; - modeHandle.pAddon = addon; - modeHandle.iLastTime = 0; - modeHandle.handle = m_addon_Handles[id]; - modeHandle.pMode->SetBaseType((AE_DSP_BASETYPE)m_addonStreamProperties.iBaseType); - m_addons_MasterProc.push_back(modeHandle); - } - } - if (m_addons_MasterProc.empty()) - CLog::Log(LOGDEBUG, " | - no master processing addon's present or enabled"); - - /*! - * Get selected source for current input - */ - int modeID = CMediaSettings::GetInstance().GetCurrentAudioSettings().m_MasterModes[m_addonStreamProperties.iStreamType][m_addonStreamProperties.iBaseType]; - if (modeID == AE_DSP_MASTER_MODE_ID_INVALID) - modeID = AE_DSP_MASTER_MODE_ID_PASSOVER; - - for (unsigned int ptr = 0; ptr < m_addons_MasterProc.size(); ++ptr) - { - CActiveAEDSPModePtr mode = m_addons_MasterProc.at(ptr).pMode; - if (mode->ModeID() == modeID) - { - m_activeMode = (int)ptr; - CLog::Log(LOGDEBUG, " | -- %s (selected)", mode->AddonModeName().c_str()); - break; - } - } - - /*! - * Setup the one allowed master processing addon and inform about selected mode - */ - m_activeModeOutChannels = -1; - if (m_addons_MasterProc[m_activeMode].pAddon) - { - AE_DSP_ERROR err = m_addons_MasterProc[m_activeMode].pAddon->MasterProcessSetMode(&m_addons_MasterProc[m_activeMode].handle, m_addonStreamProperties.iStreamType, m_addons_MasterProc[m_activeMode].pMode->AddonModeNumber(), m_addons_MasterProc[m_activeMode].pMode->ModeID()); - if (err != AE_DSP_ERROR_NO_ERROR) - { - CLog::Log(LOGERROR, "ActiveAE DSP - %s - addon master mode selection failed on %s with Mode '%s' with %s", - __FUNCTION__, - m_addons_MasterProc[m_activeMode].pAddon->GetAudioDSPName().c_str(), - m_addons_MasterProc[m_activeMode].pMode->AddonModeName().c_str(), - CActiveAEDSPAddon::ToString(err)); - m_addons_MasterProc.erase(m_addons_MasterProc.begin()+m_activeMode); - m_activeMode = AE_DSP_MASTER_MODE_ID_PASSOVER; - } - else - m_activeModeOutChannels = m_addons_MasterProc[m_activeMode].pAddon->MasterProcessGetOutChannels(&m_addons_MasterProc[m_activeMode].handle, m_activeModeOutChannelsPresent); - } - else - { - CLog::Log(LOGDEBUG, " | -- No master process selected!"); - } - - /*! - * Load all required post process dsp addon functions - */ - CLog::Log(LOGDEBUG, " ---- DSP active post process modes ---"); - const AE_DSP_MODELIST listPostProcess = CServiceBroker::GetADSP().GetAvailableModes(AE_DSP_MODE_TYPE_POST_PROCESS); - for (unsigned int i = 0; i < listPostProcess.size(); ++i) + if (m_inputFormat.m_channelLayout.HasChannel((AEChannel)(ii + 1))) { - CActiveAEDSPModePtr pMode = listPostProcess[i].first; - AE_DSP_ADDON addon = listPostProcess[i].second; - int id = addon->GetID(); - - if (m_usedMap.find(id) == m_usedMap.end()) - continue; - - if (!CAddonMgr::GetInstance().IsAddonDisabled(addon->ID()) && addon->SupportsPostProcess() && pMode->IsEnabled() && - addon->StreamIsModeSupported(&m_addon_Handles[id], pMode->ModeType(), pMode->AddonModeNumber(), pMode->ModeID())) - { - CLog::Log(LOGDEBUG, " | - %i - %s (%s)", i, pMode->AddonModeName().c_str(), addon->GetAudioDSPName().c_str()); - - sDSPProcessHandle modeHandle; - modeHandle.iAddonModeNumber = pMode->AddonModeNumber(); - modeHandle.pMode = pMode; - modeHandle.pAddon = addon; - modeHandle.iLastTime = 0; - modeHandle.handle = m_addon_Handles[id]; - m_addons_PostProc.push_back(modeHandle); - } + m_addonSettings.lInChannelPresentFlags |= 1 << ii; } - if (m_addons_PostProc.empty()) - CLog::Log(LOGDEBUG, " | - no post processing addon's present or enabled"); - - /*! - * Load one allowed addon for resampling after final post processing - */ - CLog::Log(LOGDEBUG, " ---- DSP post resample addon ---"); - if (m_addonSettings.iProcessSamplerate != m_outputFormat.m_sampleRate) - { - const AE_DSP_MODELIST listOutputResample = CServiceBroker::GetADSP().GetAvailableModes(AE_DSP_MODE_TYPE_OUTPUT_RESAMPLE); - if (listOutputResample.empty()) - CLog::Log(LOGDEBUG, " | - no final post resample addon present or enabled, becomes performed by KODI"); - for (unsigned int i = 0; i < listOutputResample.size(); ++i) - { - /// For resample only one call is allowed. Use first one and ignore everything else. - CActiveAEDSPModePtr pMode = listOutputResample[i].first; - AE_DSP_ADDON addon = listOutputResample[i].second; - int id = addon->GetID(); - - if (m_usedMap.find(id) != m_usedMap.end() && - !CAddonMgr::GetInstance().IsAddonDisabled(addon->ID()) && addon->SupportsOutputResample() && pMode->IsEnabled() && - addon->StreamIsModeSupported(&m_addon_Handles[id], pMode->ModeType(), pMode->AddonModeNumber(), pMode->ModeID())) - { - int outSamplerate = addon->OutputResampleSampleRate(&m_addon_Handles[id]); - if (outSamplerate > 0) - { - CLog::Log(LOGDEBUG, " | - %s with resampling to %i", addon->GetAudioDSPName().c_str(), outSamplerate); - - m_outputSamplerate = outSamplerate; - m_outputFrames = (int) ceil((1.0 * outSamplerate) / m_addonSettings.iProcessSamplerate * m_addonSettings.iProcessFrames); + } - m_addon_OutputResample.iAddonModeNumber = pMode->AddonModeNumber(); - m_addon_OutputResample.pMode = pMode; - m_addon_OutputResample.pAddon = addon; - m_addon_OutputResample.iLastTime = 0; - m_addon_OutputResample.handle = m_addon_Handles[id]; - } - else - { - CLog::Log(LOGERROR, "ActiveAE DSP - %s - post resample addon %s return invalid samplerate and becomes disabled", __FUNCTION__, addon->GetFriendlyName().c_str()); - } - break; - } - } - } - else + for (int ii = 0; ii < AE_DSP_CH_MAX; ii++) + { + if (m_outputFormat.m_channelLayout.HasChannel((AEChannel)(ii + 1))) { - CLog::Log(LOGDEBUG, " | - no final resampling needed, process and final samplerate the same"); + m_addonSettings.lOutChannelPresentFlags |= 1 << ii; } } + UpdateActiveModes(); + /*! * Initialize fallback matrix mixer */ @@ -622,11 +294,11 @@ bool CActiveAEDSPProcess::Create(const AEAudioFormat &inputFormat, const AEAudio CLog::Log(LOGDEBUG, " | Frames : %d", m_addonSettings.iProcessFrames); CLog::Log(LOGDEBUG, " | Internal processing : %s", m_resamplerDSPProcessor ? "yes" : "no"); CLog::Log(LOGDEBUG, " ---- Output format ----"); - CLog::Log(LOGDEBUG, " | Sample Rate : %d", m_outputSamplerate); + CLog::Log(LOGDEBUG, " | Sample Rate : %d", m_outputFormat.m_sampleRate); CLog::Log(LOGDEBUG, " | Sample Format : %s", CAEUtil::DataFormatToStr(m_outputFormat.m_dataFormat)); CLog::Log(LOGDEBUG, " | Channel Count : %d", m_outputFormat.m_channelLayout.Count()); CLog::Log(LOGDEBUG, " | Channel Layout : %s", ((std::string)m_outputFormat.m_channelLayout).c_str()); - CLog::Log(LOGDEBUG, " | Frames : %d", m_outputFrames); + CLog::Log(LOGDEBUG, " | Frames : %d", m_outputFormat.m_frames); } m_forceInit = true; @@ -866,61 +538,21 @@ AE_DSP_STREAM_ID CActiveAEDSPProcess::GetStreamId() const return m_streamId; } -unsigned int CActiveAEDSPProcess::GetInputChannels() +AEAudioFormat ActiveAE::CActiveAEDSPProcess::GetOutputFormat() { - return m_inputFormat.m_channelLayout.Count(); + return m_outputFormat; } -std::string CActiveAEDSPProcess::GetInputChannelNames() -{ - return m_inputFormat.m_channelLayout; -} - -unsigned int CActiveAEDSPProcess::GetInputSamplerate() -{ - return m_inputFormat.m_sampleRate; -} - -unsigned int CActiveAEDSPProcess::GetProcessSamplerate() +unsigned int CActiveAEDSPProcess::GetProcessSamplerate() { return m_addonSettings.iProcessSamplerate; } -unsigned int CActiveAEDSPProcess::GetOutputChannels() -{ - return m_outputFormat.m_channelLayout.Count(); -} - -std::string CActiveAEDSPProcess::GetOutputChannelNames() -{ - return m_outputFormat.m_channelLayout; -} - -unsigned int CActiveAEDSPProcess::GetOutputSamplerate() -{ - return m_outputSamplerate; -} - -unsigned int CActiveAEDSPProcess::GetOutputFrames() -{ - return m_outputFrames; -} - float CActiveAEDSPProcess::GetCPUUsage(void) const { return m_fLastProcessUsage; } -CAEChannelInfo CActiveAEDSPProcess::GetChannelLayout() -{ - return m_outputFormat.m_channelLayout; -} - -AEDataFormat CActiveAEDSPProcess::GetDataFormat() -{ - return m_dataFormat; -} - AEAudioFormat CActiveAEDSPProcess::GetInputFormat() { return m_inputFormat; @@ -1119,6 +751,11 @@ void CActiveAEDSPProcess::ClearArray(float **array, unsigned int samples) bool CActiveAEDSPProcess::Process(CSampleBuffer *in, CSampleBuffer *out) { + if (!in || !out) + { + return false; + } + CSingleLock lock(m_restartSection); bool needDSPAddonsReinit = m_forceInit; @@ -1131,6 +768,7 @@ bool CActiveAEDSPProcess::Process(CSampleBuffer *in, CSampleBuffer *out) { m_channelLayoutIn = in->pkt->config.channel_layout; + memset(m_idx_in, -1, sizeof(m_idx_in)); m_idx_in[AE_CH_FL] = av_get_channel_layout_channel_index(m_channelLayoutIn, AV_CH_FRONT_LEFT); m_idx_in[AE_CH_FR] = av_get_channel_layout_channel_index(m_channelLayoutIn, AV_CH_FRONT_RIGHT); m_idx_in[AE_CH_FC] = av_get_channel_layout_channel_index(m_channelLayoutIn, AV_CH_FRONT_CENTER); @@ -1160,6 +798,7 @@ bool CActiveAEDSPProcess::Process(CSampleBuffer *in, CSampleBuffer *out) { m_channelLayoutOut = out->pkt->config.channel_layout; + memset(m_idx_out, -1, sizeof(m_idx_out)); m_idx_out[AE_CH_FL] = av_get_channel_layout_channel_index(m_channelLayoutOut, AV_CH_FRONT_LEFT); m_idx_out[AE_CH_FR] = av_get_channel_layout_channel_index(m_channelLayoutOut, AV_CH_FRONT_RIGHT); m_idx_out[AE_CH_FC] = av_get_channel_layout_channel_index(m_channelLayoutOut, AV_CH_FRONT_CENTER); @@ -1186,50 +825,29 @@ bool CActiveAEDSPProcess::Process(CSampleBuffer *in, CSampleBuffer *out) if (needDSPAddonsReinit) { + /*! @warning If you change or add new channel enums to AEChannel in + * xbmc/cores/AudioEngine/Utils/AEChannelData.h you have to adapt this loop + */ m_addonSettings.lInChannelPresentFlags = 0; - if (m_idx_in[AE_CH_FL] >= 0) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_FL; - if (m_idx_in[AE_CH_FR] >= 0) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_FR; - if (m_idx_in[AE_CH_FC] >= 0) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_FC; - if (m_idx_in[AE_CH_LFE] >= 0) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_LFE; - if (m_idx_in[AE_CH_BL] >= 0) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_BL; - if (m_idx_in[AE_CH_BR] >= 0) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_BR; - if (m_idx_in[AE_CH_FLOC] >= 0) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_FLOC; - if (m_idx_in[AE_CH_FROC] >= 0) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_FROC; - if (m_idx_in[AE_CH_BC] >= 0) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_BC; - if (m_idx_in[AE_CH_SL] >= 0) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_SL; - if (m_idx_in[AE_CH_SR] >= 0) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_SR; - if (m_idx_in[AE_CH_TFL] >= 0) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_TFL; - if (m_idx_in[AE_CH_TFR] >= 0) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_TFR; - if (m_idx_in[AE_CH_TFC] >= 0) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_TFC; - if (m_idx_in[AE_CH_TC] >= 0) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_TC; - if (m_idx_in[AE_CH_TBL] >= 0) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_TBL; - if (m_idx_in[AE_CH_TBR] >= 0) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_TBR; - if (m_idx_in[AE_CH_TBC] >= 0) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_TBC; - if (m_idx_in[AE_CH_TBR] >= 0) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_TBR; - if (m_idx_in[AE_CH_BLOC] >= 0) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_BLOC; - if (m_idx_in[AE_CH_BROC] >= 0) m_addonSettings.lInChannelPresentFlags |= AE_DSP_PRSNT_CH_BROC; + for (int ii = 0; ii < AE_DSP_CH_MAX; ii++) + { + if (m_idx_in[ii+1] >= 0) + { + m_addonSettings.lInChannelPresentFlags |= 1 << ii; + } + } + /*! @warning If you change or add new channel enums to AEChannel in + * xbmc/cores/AudioEngine/Utils/AEChannelData.h you have to adapt this loop + */ m_addonSettings.lOutChannelPresentFlags = 0; - if (m_idx_out[AE_CH_FL] >= 0) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_FL; - if (m_idx_out[AE_CH_FR] >= 0) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_FR; - if (m_idx_out[AE_CH_FC] >= 0) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_FC; - if (m_idx_out[AE_CH_LFE] >= 0) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_LFE; - if (m_idx_out[AE_CH_BL] >= 0) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_BL; - if (m_idx_out[AE_CH_BR] >= 0) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_BR; - if (m_idx_out[AE_CH_FLOC] >= 0) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_FLOC; - if (m_idx_out[AE_CH_FROC] >= 0) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_FROC; - if (m_idx_out[AE_CH_BC] >= 0) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_BC; - if (m_idx_out[AE_CH_SL] >= 0) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_SL; - if (m_idx_out[AE_CH_SR] >= 0) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_SR; - if (m_idx_out[AE_CH_TFL] >= 0) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_TFL; - if (m_idx_out[AE_CH_TFR] >= 0) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_TFR; - if (m_idx_out[AE_CH_TFC] >= 0) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_TFC; - if (m_idx_out[AE_CH_TC] >= 0) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_TC; - if (m_idx_out[AE_CH_TBL] >= 0) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_TBL; - if (m_idx_out[AE_CH_TBR] >= 0) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_TBR; - if (m_idx_out[AE_CH_TBC] >= 0) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_TBC; - if (m_idx_out[AE_CH_BLOC] >= 0) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_BLOC; - if (m_idx_out[AE_CH_BROC] >= 0) m_addonSettings.lOutChannelPresentFlags |= AE_DSP_PRSNT_CH_BROC; + for (int ii = 0; ii < AE_DSP_CH_MAX; ii++) + { + if (m_idx_out[ii + 1] >= 0) + { + m_addonSettings.lOutChannelPresentFlags |= 1 << ii; + } + } m_addonSettings.iStreamID = m_streamId; m_addonSettings.iInChannels = in->pkt->config.channels; @@ -1245,6 +863,7 @@ bool CActiveAEDSPProcess::Process(CSampleBuffer *in, CSampleBuffer *out) m_NewStreamType = AE_DSP_ASTREAM_INVALID; } + UpdateActiveModes(); for (AE_DSP_ADDONMAP_ITR itr = m_usedMap.begin(); itr != m_usedMap.end(); ++itr) { AE_DSP_ERROR err = itr->second->StreamInitialize(&m_addon_Handles[itr->first], &m_addonSettings); @@ -1266,7 +885,7 @@ bool CActiveAEDSPProcess::Process(CSampleBuffer *in, CSampleBuffer *out) /** * Setup ffmpeg convert array for input stream */ - SetFFMpegDSPProcessorArray(m_ffMpegConvertArray, m_processArray[0], NULL); + SetFFMpegDSPProcessorArray(m_ffMpegConvertArray[FFMPEG_PROC_ARRAY_IN], m_processArray[0], m_idx_in, m_addonSettings.lInChannelPresentFlags); } int64_t startTime; @@ -1276,7 +895,7 @@ bool CActiveAEDSPProcess::Process(CSampleBuffer *in, CSampleBuffer *out) /** * Convert to required planar float format inside dsp system */ - if (swr_convert(m_convertInput, (uint8_t **)m_ffMpegConvertArray[0], m_processArraySize, (const uint8_t **)in->pkt->data , frames) < 0) + if (swr_convert(m_convertInput, (uint8_t **)m_ffMpegConvertArray[FFMPEG_PROC_ARRAY_IN], m_processArraySize, (const uint8_t **)in->pkt->data, in->pkt->nb_samples) < 0) { CLog::Log(LOGERROR, "ActiveAE DSP - %s - input audio convert failed", __FUNCTION__); return false; @@ -1305,7 +924,7 @@ bool CActiveAEDSPProcess::Process(CSampleBuffer *in, CSampleBuffer *out) * Here a high quality resample can be performed. * Only one DSP addon is allowed todo this! */ - if (m_addon_InputResample.pAddon) + if (m_addon_InputResample.pAddon && !m_bypassDSP) { startTime = CurrentHostCounter(); @@ -1323,7 +942,7 @@ bool CActiveAEDSPProcess::Process(CSampleBuffer *in, CSampleBuffer *out) * DSP pre processing * All DSP addons allowed todo this and order of it set on settings. */ - for (unsigned int i = 0; i < m_addons_PreProc.size(); ++i) + for (unsigned int i = 0; i < m_addons_PreProc.size() && !m_bypassDSP; ++i) { startTime = CurrentHostCounter(); @@ -1342,7 +961,7 @@ bool CActiveAEDSPProcess::Process(CSampleBuffer *in, CSampleBuffer *out) * Here a channel upmix/downmix for stereo surround sound can be performed * Only one DSP addon is allowed todo this! */ - if (m_addons_MasterProc[m_activeMode].pAddon) + if (m_addons_MasterProc[m_activeMode].pAddon && !m_bypassDSP) { startTime = CurrentHostCounter(); @@ -1366,7 +985,11 @@ bool CActiveAEDSPProcess::Process(CSampleBuffer *in, CSampleBuffer *out) startTime = CurrentHostCounter(); if (needDSPAddonsReinit) - SetFFMpegDSPProcessorArray(m_ffMpegProcessArray, lastOutArray, m_processArray[togglePtr]); + { + /*! @todo: test with an resampler add-on */ + SetFFMpegDSPProcessorArray(m_ffMpegProcessArray[FFMPEG_PROC_ARRAY_IN], lastOutArray, m_idx_in, m_addonSettings.lInChannelPresentFlags); + SetFFMpegDSPProcessorArray(m_ffMpegProcessArray[FFMPEG_PROC_ARRAY_OUT], m_processArray[togglePtr], m_idx_out, m_addonSettings.lOutChannelPresentFlags); + } frames = m_resamplerDSPProcessor->Resample((uint8_t**)m_ffMpegProcessArray[FFMPEG_PROC_ARRAY_OUT], frames, (uint8_t**)m_ffMpegProcessArray[FFMPEG_PROC_ARRAY_IN], frames, 1.0); if (frames <= 0) @@ -1387,7 +1010,7 @@ bool CActiveAEDSPProcess::Process(CSampleBuffer *in, CSampleBuffer *out) * or frequency/volume corrections, speaker distance handling, equalizer... . * All DSP addons allowed todo this and order of it set on settings. */ - for (unsigned int i = 0; i < m_addons_PostProc.size(); ++i) + for (unsigned int i = 0; i < m_addons_PostProc.size() && !m_bypassDSP; ++i) { startTime = CurrentHostCounter(); @@ -1406,7 +1029,7 @@ bool CActiveAEDSPProcess::Process(CSampleBuffer *in, CSampleBuffer *out) * Here a high quality resample can be performed. * Only one DSP addon is allowed todo this! */ - if (m_addon_OutputResample.pAddon) + if (m_addon_OutputResample.pAddon && !m_bypassDSP) { startTime = CurrentHostCounter(); @@ -1424,17 +1047,18 @@ bool CActiveAEDSPProcess::Process(CSampleBuffer *in, CSampleBuffer *out) * Setup ffmpeg convert array for output stream, performed here to now last array */ if (needDSPAddonsReinit) - SetFFMpegDSPProcessorArray(m_ffMpegConvertArray, NULL, lastOutArray); + SetFFMpegDSPProcessorArray(m_ffMpegConvertArray[FFMPEG_PROC_ARRAY_OUT], lastOutArray, m_idx_out, m_addonSettings.lOutChannelPresentFlags); /** * Convert back to required output format */ - if (swr_convert(m_convertOutput, (uint8_t **)out->pkt->data, m_processArraySize, (const uint8_t **)m_ffMpegConvertArray[1], frames) < 0) + if (swr_convert(m_convertOutput, (uint8_t **)out->pkt->data, out->pkt->max_nb_samples, (const uint8_t **)m_ffMpegConvertArray[FFMPEG_PROC_ARRAY_OUT], frames) < 0) { CLog::Log(LOGERROR, "ActiveAE DSP - %s - output audio convert failed", __FUNCTION__); return false; } out->pkt->nb_samples = frames; + out->pkt_start_offset = out->pkt->nb_samples; /** * Update cpu process percent usage values for modes and total (every second) @@ -1565,7 +1189,7 @@ void CActiveAEDSPProcess::CalculateCPUUsage(uint64_t iTime) m_iLastProcessTime = iTime; } -void CActiveAEDSPProcess::SetFFMpegDSPProcessorArray(float *array_ffmpeg[2][AE_DSP_CH_MAX], float **array_in, float **array_out) +void CActiveAEDSPProcess::SetFFMpegDSPProcessorArray(float *array_ffmpeg[AE_DSP_CH_MAX], float *array_dsp[AE_DSP_CH_MAX], int idx[AE_CH_MAX], unsigned long ChannelFlags) { /*! * Setup ffmpeg resampler channel setup, this way is not my favorite but it works to become @@ -1576,54 +1200,17 @@ void CActiveAEDSPProcess::SetFFMpegDSPProcessorArray(float *array_ffmpeg[2][AE_D * already present channel memory storage. */ - //! Initialize input channel alignment for ffmpeg process array - if (array_in) + /*! @warning If you change or add new channel enums to AEChannel in + * xbmc/cores/AudioEngine/Utils/AEChannelData.h you have to adapt this loop + */ + memset(array_ffmpeg, 0, sizeof(float*)*AE_DSP_CH_MAX); + for (int ii = 0; ii < AE_DSP_CH_MAX; ii++) { - if (m_addonSettings.lInChannelPresentFlags & AE_DSP_PRSNT_CH_FL) array_ffmpeg[FFMPEG_PROC_ARRAY_IN][m_idx_in[AE_CH_FL]] = array_in[AE_DSP_CH_FL]; - if (m_addonSettings.lInChannelPresentFlags & AE_DSP_PRSNT_CH_FR) array_ffmpeg[FFMPEG_PROC_ARRAY_IN][m_idx_in[AE_CH_FR]] = array_in[AE_DSP_CH_FR]; - if (m_addonSettings.lInChannelPresentFlags & AE_DSP_PRSNT_CH_FC) array_ffmpeg[FFMPEG_PROC_ARRAY_IN][m_idx_in[AE_CH_FC]] = array_in[AE_DSP_CH_FC]; - if (m_addonSettings.lInChannelPresentFlags & AE_DSP_PRSNT_CH_LFE) array_ffmpeg[FFMPEG_PROC_ARRAY_IN][m_idx_in[AE_CH_LFE]] = array_in[AE_DSP_CH_LFE]; - if (m_addonSettings.lInChannelPresentFlags & AE_DSP_PRSNT_CH_BL) array_ffmpeg[FFMPEG_PROC_ARRAY_IN][m_idx_in[AE_CH_BL]] = array_in[AE_DSP_CH_BL]; - if (m_addonSettings.lInChannelPresentFlags & AE_DSP_PRSNT_CH_BR) array_ffmpeg[FFMPEG_PROC_ARRAY_IN][m_idx_in[AE_CH_BR]] = array_in[AE_DSP_CH_BR]; - if (m_addonSettings.lInChannelPresentFlags & AE_DSP_PRSNT_CH_FLOC) array_ffmpeg[FFMPEG_PROC_ARRAY_IN][m_idx_in[AE_CH_FLOC]] = array_in[AE_DSP_CH_FLOC]; - if (m_addonSettings.lInChannelPresentFlags & AE_DSP_PRSNT_CH_FROC) array_ffmpeg[FFMPEG_PROC_ARRAY_IN][m_idx_in[AE_CH_FROC]] = array_in[AE_DSP_CH_FROC]; - if (m_addonSettings.lInChannelPresentFlags & AE_DSP_PRSNT_CH_BC) array_ffmpeg[FFMPEG_PROC_ARRAY_IN][m_idx_in[AE_CH_BC]] = array_in[AE_DSP_CH_BC]; - if (m_addonSettings.lInChannelPresentFlags & AE_DSP_PRSNT_CH_SL) array_ffmpeg[FFMPEG_PROC_ARRAY_IN][m_idx_in[AE_CH_SL]] = array_in[AE_DSP_CH_SL]; - if (m_addonSettings.lInChannelPresentFlags & AE_DSP_PRSNT_CH_SR) array_ffmpeg[FFMPEG_PROC_ARRAY_IN][m_idx_in[AE_CH_SR]] = array_in[AE_DSP_CH_SR]; - if (m_addonSettings.lInChannelPresentFlags & AE_DSP_PRSNT_CH_TFL) array_ffmpeg[FFMPEG_PROC_ARRAY_IN][m_idx_in[AE_CH_TFL]] = array_in[AE_DSP_CH_TFL]; - if (m_addonSettings.lInChannelPresentFlags & AE_DSP_PRSNT_CH_TFR) array_ffmpeg[FFMPEG_PROC_ARRAY_IN][m_idx_in[AE_CH_TFR]] = array_in[AE_DSP_CH_TFR]; - if (m_addonSettings.lInChannelPresentFlags & AE_DSP_PRSNT_CH_TFC) array_ffmpeg[FFMPEG_PROC_ARRAY_IN][m_idx_in[AE_CH_TFC]] = array_in[AE_DSP_CH_TFC]; - if (m_addonSettings.lInChannelPresentFlags & AE_DSP_PRSNT_CH_TC) array_ffmpeg[FFMPEG_PROC_ARRAY_IN][m_idx_in[AE_CH_TC]] = array_in[AE_DSP_CH_TC]; - if (m_addonSettings.lInChannelPresentFlags & AE_DSP_PRSNT_CH_TBL) array_ffmpeg[FFMPEG_PROC_ARRAY_IN][m_idx_in[AE_CH_TBL]] = array_in[AE_DSP_CH_TBL]; - if (m_addonSettings.lInChannelPresentFlags & AE_DSP_PRSNT_CH_TBR) array_ffmpeg[FFMPEG_PROC_ARRAY_IN][m_idx_in[AE_CH_TBR]] = array_in[AE_DSP_CH_TBR]; - if (m_addonSettings.lInChannelPresentFlags & AE_DSP_PRSNT_CH_TBC) array_ffmpeg[FFMPEG_PROC_ARRAY_IN][m_idx_in[AE_CH_TBC]] = array_in[AE_DSP_CH_TBC]; - if (m_addonSettings.lInChannelPresentFlags & AE_DSP_PRSNT_CH_BLOC) array_ffmpeg[FFMPEG_PROC_ARRAY_IN][m_idx_in[AE_CH_BLOC]] = array_in[AE_DSP_CH_BLOC]; - if (m_addonSettings.lInChannelPresentFlags & AE_DSP_PRSNT_CH_BROC) array_ffmpeg[FFMPEG_PROC_ARRAY_IN][m_idx_in[AE_CH_BROC]] = array_in[AE_DSP_CH_BROC]; - } + if (ChannelFlags & 1 << ii) + { + array_ffmpeg[idx[ii + 1]] = array_dsp[ii]; + } - //! Initialize output channel alignment for ffmpeg process array - if (array_out) - { - if (m_addonSettings.lOutChannelPresentFlags & AE_DSP_PRSNT_CH_FL) array_ffmpeg[FFMPEG_PROC_ARRAY_OUT][m_idx_out[AE_CH_FL]] = array_out[AE_DSP_CH_FL]; - if (m_addonSettings.lOutChannelPresentFlags & AE_DSP_PRSNT_CH_FR) array_ffmpeg[FFMPEG_PROC_ARRAY_OUT][m_idx_out[AE_CH_FR]] = array_out[AE_DSP_CH_FR]; - if (m_addonSettings.lOutChannelPresentFlags & AE_DSP_PRSNT_CH_FC) array_ffmpeg[FFMPEG_PROC_ARRAY_OUT][m_idx_out[AE_CH_FC]] = array_out[AE_DSP_CH_FC]; - if (m_addonSettings.lOutChannelPresentFlags & AE_DSP_PRSNT_CH_LFE) array_ffmpeg[FFMPEG_PROC_ARRAY_OUT][m_idx_out[AE_CH_LFE]] = array_out[AE_DSP_CH_LFE]; - if (m_addonSettings.lOutChannelPresentFlags & AE_DSP_PRSNT_CH_BL) array_ffmpeg[FFMPEG_PROC_ARRAY_OUT][m_idx_out[AE_CH_BL]] = array_out[AE_DSP_CH_BL]; - if (m_addonSettings.lOutChannelPresentFlags & AE_DSP_PRSNT_CH_BR) array_ffmpeg[FFMPEG_PROC_ARRAY_OUT][m_idx_out[AE_CH_BR]] = array_out[AE_DSP_CH_BR]; - if (m_addonSettings.lOutChannelPresentFlags & AE_DSP_PRSNT_CH_FLOC) array_ffmpeg[FFMPEG_PROC_ARRAY_OUT][m_idx_out[AE_CH_FLOC]] = array_out[AE_DSP_CH_FLOC]; - if (m_addonSettings.lOutChannelPresentFlags & AE_DSP_PRSNT_CH_FROC) array_ffmpeg[FFMPEG_PROC_ARRAY_OUT][m_idx_out[AE_CH_FROC]] = array_out[AE_DSP_CH_FROC]; - if (m_addonSettings.lOutChannelPresentFlags & AE_DSP_PRSNT_CH_BC) array_ffmpeg[FFMPEG_PROC_ARRAY_OUT][m_idx_out[AE_CH_BC]] = array_out[AE_DSP_CH_BC]; - if (m_addonSettings.lOutChannelPresentFlags & AE_DSP_PRSNT_CH_SL) array_ffmpeg[FFMPEG_PROC_ARRAY_OUT][m_idx_out[AE_CH_SL]] = array_out[AE_DSP_CH_SL]; - if (m_addonSettings.lOutChannelPresentFlags & AE_DSP_PRSNT_CH_SR) array_ffmpeg[FFMPEG_PROC_ARRAY_OUT][m_idx_out[AE_CH_SR]] = array_out[AE_DSP_CH_SR]; - if (m_addonSettings.lOutChannelPresentFlags & AE_DSP_PRSNT_CH_TFL) array_ffmpeg[FFMPEG_PROC_ARRAY_OUT][m_idx_out[AE_CH_TFL]] = array_out[AE_DSP_CH_TFL]; - if (m_addonSettings.lOutChannelPresentFlags & AE_DSP_PRSNT_CH_TFR) array_ffmpeg[FFMPEG_PROC_ARRAY_OUT][m_idx_out[AE_CH_TFR]] = array_out[AE_DSP_CH_TFR]; - if (m_addonSettings.lOutChannelPresentFlags & AE_DSP_PRSNT_CH_TFC) array_ffmpeg[FFMPEG_PROC_ARRAY_OUT][m_idx_out[AE_CH_TFC]] = array_out[AE_DSP_CH_TFC]; - if (m_addonSettings.lOutChannelPresentFlags & AE_DSP_PRSNT_CH_TC) array_ffmpeg[FFMPEG_PROC_ARRAY_OUT][m_idx_out[AE_CH_TC]] = array_out[AE_DSP_CH_TC]; - if (m_addonSettings.lOutChannelPresentFlags & AE_DSP_PRSNT_CH_TBL) array_ffmpeg[FFMPEG_PROC_ARRAY_OUT][m_idx_out[AE_CH_TBL]] = array_out[AE_DSP_CH_TBL]; - if (m_addonSettings.lOutChannelPresentFlags & AE_DSP_PRSNT_CH_TBR) array_ffmpeg[FFMPEG_PROC_ARRAY_OUT][m_idx_out[AE_CH_TBR]] = array_out[AE_DSP_CH_TBR]; - if (m_addonSettings.lOutChannelPresentFlags & AE_DSP_PRSNT_CH_TBC) array_ffmpeg[FFMPEG_PROC_ARRAY_OUT][m_idx_out[AE_CH_TBC]] = array_out[AE_DSP_CH_TBC]; - if (m_addonSettings.lOutChannelPresentFlags & AE_DSP_PRSNT_CH_BLOC) array_ffmpeg[FFMPEG_PROC_ARRAY_OUT][m_idx_out[AE_CH_BLOC]] = array_out[AE_DSP_CH_BLOC]; - if (m_addonSettings.lOutChannelPresentFlags & AE_DSP_PRSNT_CH_BROC) array_ffmpeg[FFMPEG_PROC_ARRAY_OUT][m_idx_out[AE_CH_BROC]] = array_out[AE_DSP_CH_BROC]; } } @@ -1651,6 +1238,322 @@ float CActiveAEDSPProcess::GetDelay() return delay; } +void CActiveAEDSPProcess::UpdateActiveModes() +{ + m_addon_InputResample.Clear(); + m_addon_OutputResample.Clear(); + + m_addons_InputProc.clear(); + m_addons_PreProc.clear(); + m_addons_MasterProc.clear(); + m_addons_PostProc.clear(); + + /*! + * Setup off mode, used if dsp master processing is set off, required to have data + * for stream information functions. + */ + sDSPProcessHandle internalMode; + internalMode.Clear(); + internalMode.iAddonModeNumber = AE_DSP_MASTER_MODE_ID_PASSOVER; + internalMode.pMode = CActiveAEDSPModePtr(new CActiveAEDSPMode(internalMode.iAddonModeNumber, (AE_DSP_BASETYPE)m_addonStreamProperties.iBaseType)); + internalMode.iLastTime = 0; + m_addons_MasterProc.push_back(internalMode); + m_activeMode = AE_DSP_MASTER_MODE_ID_PASSOVER; + + if (m_addonSettings.bStereoUpmix && m_addonSettings.iInChannels <= 2) + { + internalMode.Clear(); + internalMode.iAddonModeNumber = AE_DSP_MASTER_MODE_ID_INTERNAL_STEREO_UPMIX; + internalMode.pMode = CActiveAEDSPModePtr(new CActiveAEDSPMode(internalMode.iAddonModeNumber, (AE_DSP_BASETYPE)m_addonStreamProperties.iBaseType)); + internalMode.iLastTime = 0; + m_addons_MasterProc.push_back(internalMode); + } + + /*! + * Load all selected processing types, stored in a database and available from addons + */ + AE_DSP_ADDONMAP addonMap; + if (CServiceBroker::GetADSP().GetEnabledAudioDSPAddons(addonMap) > 0) + { + int foundInputResamplerId = -1; /*!< Used to prevent double call of StreamCreate if input stream resampling is together with outer processing types */ + + /*! + * First find input resample addon to become information about processing sample rate and + * load one allowed before master processing & final resample addon + */ + CLog::Log(LOGDEBUG, " ---- DSP input resample addon ---"); + const AE_DSP_MODELIST listInputResample = CServiceBroker::GetADSP().GetAvailableModes(AE_DSP_MODE_TYPE_INPUT_RESAMPLE); + if (listInputResample.empty()) + CLog::Log(LOGDEBUG, " | - no input resample addon present or enabled"); + for (unsigned int i = 0; i < listInputResample.size(); ++i) + { + /// For resample only one call is allowed. Use first one and ignore everything else. + CActiveAEDSPModePtr pMode = listInputResample[i].first; + AE_DSP_ADDON addon = listInputResample[i].second; + if (!CAddonMgr::GetInstance().IsAddonDisabled(addon->ID()) && addon->SupportsInputResample() && pMode->IsEnabled()) + { + ADDON_HANDLE_STRUCT handle; + AE_DSP_ERROR err = addon->StreamCreate(&m_addonSettings, &m_addonStreamProperties, &handle); + if (err == AE_DSP_ERROR_NO_ERROR) + { + if (addon->StreamIsModeSupported(&handle, pMode->ModeType(), pMode->AddonModeNumber(), pMode->ModeID())) + { + int processSamplerate = addon->InputResampleSampleRate(&handle); + if (processSamplerate == (int)m_inputFormat.m_sampleRate) + { + CLog::Log(LOGDEBUG, " | - input resample addon %s ignored, input sample rate %i the same as process rate", addon->GetFriendlyName().c_str(), m_inputFormat.m_sampleRate); + } + else if (processSamplerate > 0) + { + CLog::Log(LOGDEBUG, " | - %s with resampling from %i to %i", addon->GetAudioDSPName().c_str(), m_inputFormat.m_sampleRate, processSamplerate); + + m_outputFormat.m_sampleRate = processSamplerate; /*!< overwrite output sample rate with the new rate */ + m_outputFormat.m_frames = (int)ceil((1.0 * processSamplerate) / m_addonSettings.iInSamplerate * m_addonSettings.iInFrames); + m_addonSettings.iProcessSamplerate = processSamplerate; /*!< the processing sample rate required for all behind called processes */ + m_addonSettings.iProcessFrames = m_outputFormat.m_frames; + m_addonSettings.bInputResamplingActive = true; + + m_addon_InputResample.iAddonModeNumber = pMode->AddonModeNumber(); + m_addon_InputResample.pMode = pMode; + m_addon_InputResample.pAddon = addon; + m_addon_InputResample.iLastTime = 0; + } + else + { + CLog::Log(LOGERROR, "ActiveAE DSP - %s - input resample addon %s return invalid samplerate and becomes disabled", __FUNCTION__, addon->GetFriendlyName().c_str()); + } + + unsigned int id = addon->GetID(); + m_addon_Handles[id] = handle; + foundInputResamplerId = id; + m_usedMap.insert(std::make_pair(id, addon)); + } + } + else if (err != AE_DSP_ERROR_IGNORE_ME) + CLog::Log(LOGERROR, "ActiveAE DSP - %s - input resample addon creation failed on %s with %s", __FUNCTION__, addon->GetAudioDSPName().c_str(), CActiveAEDSPAddon::ToString(err)); + break; + } + } + + /*! + * Now init all other dsp relavant addons + */ + for (AE_DSP_ADDONMAP_ITR itr = addonMap.begin(); itr != addonMap.end(); ++itr) + { + AE_DSP_ADDON addon = itr->second; + int id = addon->GetID(); + if (!CAddonMgr::GetInstance().IsAddonDisabled(addon->ID()) && id != foundInputResamplerId) + { + ADDON_HANDLE_STRUCT handle; + AE_DSP_ERROR err = addon->StreamCreate(&m_addonSettings, &m_addonStreamProperties, &handle); + if (err == AE_DSP_ERROR_NO_ERROR) + { + m_addon_Handles[id] = handle; + m_usedMap.insert(std::make_pair(id, addon)); + } + else if (err == AE_DSP_ERROR_IGNORE_ME) + continue; + else + CLog::Log(LOGERROR, "ActiveAE DSP - %s - addon creation failed on %s with %s", __FUNCTION__, addon->GetAudioDSPName().c_str(), CActiveAEDSPAddon::ToString(err)); + } + } + + for (AE_DSP_ADDONMAP_ITR itr = m_usedMap.begin(); itr != m_usedMap.end(); ++itr) + { + AE_DSP_ADDON addon = itr->second; + if (addon->SupportsInputInfoProcess()) + { + sDSPProcessHandle modeHandle; + modeHandle.pAddon = addon; + modeHandle.handle = m_addon_Handles[addon->GetID()]; + m_addons_InputProc.push_back(modeHandle); + } + } + + /*! + * Load all required pre process dsp addon functions + */ + CLog::Log(LOGDEBUG, " ---- DSP active pre process modes ---"); + const AE_DSP_MODELIST listPreProcess = CServiceBroker::GetADSP().GetAvailableModes(AE_DSP_MODE_TYPE_PRE_PROCESS); + for (unsigned int i = 0; i < listPreProcess.size(); ++i) + { + CActiveAEDSPModePtr pMode = listPreProcess[i].first; + AE_DSP_ADDON addon = listPreProcess[i].second; + int id = addon->GetID(); + + if (m_usedMap.find(id) == m_usedMap.end()) + continue; + if (!CAddonMgr::GetInstance().IsAddonDisabled(addon->ID()) && addon->SupportsPreProcess() && pMode->IsEnabled() && + addon->StreamIsModeSupported(&m_addon_Handles[id], pMode->ModeType(), pMode->AddonModeNumber(), pMode->ModeID())) + { + CLog::Log(LOGDEBUG, " | - %i - %s (%s)", i, pMode->AddonModeName().c_str(), addon->GetAudioDSPName().c_str()); + + sDSPProcessHandle modeHandle; + modeHandle.iAddonModeNumber = pMode->AddonModeNumber(); + modeHandle.pMode = pMode; + modeHandle.pAddon = addon; + modeHandle.iLastTime = 0; + modeHandle.handle = m_addon_Handles[id]; + m_addons_PreProc.push_back(modeHandle); + } + } + if (m_addons_PreProc.empty()) + CLog::Log(LOGDEBUG, " | - no pre processing addon's present or enabled"); + + /*! + * Load all available master modes from addons and put together with database + */ + CLog::Log(LOGDEBUG, " ---- DSP active master process modes ---"); + const AE_DSP_MODELIST listMasterProcess = CServiceBroker::GetADSP().GetAvailableModes(AE_DSP_MODE_TYPE_MASTER_PROCESS); + for (unsigned int i = 0; i < listMasterProcess.size(); ++i) + { + CActiveAEDSPModePtr pMode = listMasterProcess[i].first; + AE_DSP_ADDON addon = listMasterProcess[i].second; + int id = addon->GetID(); + + if (m_usedMap.find(id) == m_usedMap.end()) + continue; + if (!CAddonMgr::GetInstance().IsAddonDisabled(addon->ID()) && addon->SupportsMasterProcess() && pMode->IsEnabled() && + addon->StreamIsModeSupported(&m_addon_Handles[id], pMode->ModeType(), pMode->AddonModeNumber(), pMode->ModeID())) + { + CLog::Log(LOGDEBUG, " | - %i - %s (%s)", i, pMode->AddonModeName().c_str(), addon->GetAudioDSPName().c_str()); + + sDSPProcessHandle modeHandle; + modeHandle.iAddonModeNumber = pMode->AddonModeNumber(); + modeHandle.pMode = pMode; + modeHandle.pAddon = addon; + modeHandle.iLastTime = 0; + modeHandle.handle = m_addon_Handles[id]; + modeHandle.pMode->SetBaseType((AE_DSP_BASETYPE)m_addonStreamProperties.iBaseType); + m_addons_MasterProc.push_back(modeHandle); + } + } + if (m_addons_MasterProc.empty()) + CLog::Log(LOGDEBUG, " | - no master processing addon's present or enabled"); + + /*! + * Get selected source for current input + */ + int modeID = CMediaSettings::GetInstance().GetCurrentAudioSettings().m_MasterModes[m_addonStreamProperties.iStreamType][m_addonStreamProperties.iBaseType]; + if (modeID == AE_DSP_MASTER_MODE_ID_INVALID) + modeID = AE_DSP_MASTER_MODE_ID_PASSOVER; + + for (unsigned int ptr = 0; ptr < m_addons_MasterProc.size(); ++ptr) + { + CActiveAEDSPModePtr mode = m_addons_MasterProc.at(ptr).pMode; + if (mode->ModeID() == modeID) + { + m_activeMode = (int)ptr; + CLog::Log(LOGDEBUG, " | -- %s (selected)", mode->AddonModeName().c_str()); + break; + } + } + + /*! + * Setup the one allowed master processing addon and inform about selected mode + */ + m_activeModeOutChannels = -1; + if (m_addons_MasterProc[m_activeMode].pAddon) + { + AE_DSP_ERROR err = m_addons_MasterProc[m_activeMode].pAddon->MasterProcessSetMode(&m_addons_MasterProc[m_activeMode].handle, m_addonStreamProperties.iStreamType, m_addons_MasterProc[m_activeMode].pMode->AddonModeNumber(), m_addons_MasterProc[m_activeMode].pMode->ModeID()); + if (err != AE_DSP_ERROR_NO_ERROR) + { + CLog::Log(LOGERROR, "ActiveAE DSP - %s - addon master mode selection failed on %s with Mode '%s' with %s", + __FUNCTION__, + m_addons_MasterProc[m_activeMode].pAddon->GetAudioDSPName().c_str(), + m_addons_MasterProc[m_activeMode].pMode->AddonModeName().c_str(), + CActiveAEDSPAddon::ToString(err)); + m_addons_MasterProc.erase(m_addons_MasterProc.begin() + m_activeMode); + m_activeMode = AE_DSP_MASTER_MODE_ID_PASSOVER; + } + else + m_activeModeOutChannels = m_addons_MasterProc[m_activeMode].pAddon->MasterProcessGetOutChannels(&m_addons_MasterProc[m_activeMode].handle, m_activeModeOutChannelsPresent); + } + else + { + CLog::Log(LOGDEBUG, " | -- No master process selected!"); + } + + /*! + * Load all required post process dsp addon functions + */ + CLog::Log(LOGDEBUG, " ---- DSP active post process modes ---"); + const AE_DSP_MODELIST listPostProcess = CServiceBroker::GetADSP().GetAvailableModes(AE_DSP_MODE_TYPE_POST_PROCESS); + for (unsigned int i = 0; i < listPostProcess.size(); ++i) + { + CActiveAEDSPModePtr pMode = listPostProcess[i].first; + AE_DSP_ADDON addon = listPostProcess[i].second; + int id = addon->GetID(); + + if (m_usedMap.find(id) == m_usedMap.end()) + continue; + + if (!CAddonMgr::GetInstance().IsAddonDisabled(addon->ID()) && addon->SupportsPostProcess() && pMode->IsEnabled() && + addon->StreamIsModeSupported(&m_addon_Handles[id], pMode->ModeType(), pMode->AddonModeNumber(), pMode->ModeID())) + { + CLog::Log(LOGDEBUG, " | - %i - %s (%s)", i, pMode->AddonModeName().c_str(), addon->GetAudioDSPName().c_str()); + + sDSPProcessHandle modeHandle; + modeHandle.iAddonModeNumber = pMode->AddonModeNumber(); + modeHandle.pMode = pMode; + modeHandle.pAddon = addon; + modeHandle.iLastTime = 0; + modeHandle.handle = m_addon_Handles[id]; + m_addons_PostProc.push_back(modeHandle); + } + } + if (m_addons_PostProc.empty()) + CLog::Log(LOGDEBUG, " | - no post processing addon's present or enabled"); + + /*! + * Load one allowed addon for resampling after final post processing + */ + CLog::Log(LOGDEBUG, " ---- DSP post resample addon ---"); + if (m_addonSettings.iProcessSamplerate != m_outputFormat.m_sampleRate) + { + const AE_DSP_MODELIST listOutputResample = CServiceBroker::GetADSP().GetAvailableModes(AE_DSP_MODE_TYPE_OUTPUT_RESAMPLE); + if (listOutputResample.empty()) + CLog::Log(LOGDEBUG, " | - no final post resample addon present or enabled, becomes performed by KODI"); + for (unsigned int i = 0; i < listOutputResample.size(); ++i) + { + /// For resample only one call is allowed. Use first one and ignore everything else. + CActiveAEDSPModePtr pMode = listOutputResample[i].first; + AE_DSP_ADDON addon = listOutputResample[i].second; + int id = addon->GetID(); + + if (m_usedMap.find(id) != m_usedMap.end() && + !CAddonMgr::GetInstance().IsAddonDisabled(addon->ID()) && addon->SupportsOutputResample() && pMode->IsEnabled() && + addon->StreamIsModeSupported(&m_addon_Handles[id], pMode->ModeType(), pMode->AddonModeNumber(), pMode->ModeID())) + { + int outSamplerate = addon->OutputResampleSampleRate(&m_addon_Handles[id]); + if (outSamplerate > 0) + { + CLog::Log(LOGDEBUG, " | - %s with resampling to %i", addon->GetAudioDSPName().c_str(), outSamplerate); + + m_outputFormat.m_sampleRate = outSamplerate; + m_outputFormat.m_frames = (int)ceil((1.0 * outSamplerate) / m_addonSettings.iProcessSamplerate * m_addonSettings.iProcessFrames); + + m_addon_OutputResample.iAddonModeNumber = pMode->AddonModeNumber(); + m_addon_OutputResample.pMode = pMode; + m_addon_OutputResample.pAddon = addon; + m_addon_OutputResample.iLastTime = 0; + m_addon_OutputResample.handle = m_addon_Handles[id]; + } + else + { + CLog::Log(LOGERROR, "ActiveAE DSP - %s - post resample addon %s return invalid samplerate and becomes disabled", __FUNCTION__, addon->GetFriendlyName().c_str()); + } + break; + } + } + } + else + { + CLog::Log(LOGDEBUG, " | - no final resampling needed, process and final samplerate the same"); + } + } +} + bool CActiveAEDSPProcess::HasActiveModes(AE_DSP_MODE_TYPE type) { bool bReturn(false); @@ -1741,6 +1644,7 @@ CActiveAEDSPModePtr CActiveAEDSPProcess::GetActiveMasterMode() const bool CActiveAEDSPProcess::SetMasterMode(AE_DSP_STREAMTYPE streamType, int iModeID, bool bSwitchStreamType) { + CSingleLock lockMasterModes(m_critSection); /*! * if the unique master mode id is already used a reinit is not needed */ diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/AudioDSPAddons/ActiveAEDSPProcess.h b/xbmc/cores/AudioEngine/Engines/ActiveAE/AudioDSPAddons/ActiveAEDSPProcess.h index 665cf5886ce16..c0e3dd5ee85bd 100644 --- a/xbmc/cores/AudioEngine/Engines/ActiveAE/AudioDSPAddons/ActiveAEDSPProcess.h +++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/AudioDSPAddons/ActiveAEDSPProcess.h @@ -32,7 +32,7 @@ namespace ActiveAE { class CSampleBuffer; class IAEResample; - class CActiveAEResample; + class CActiveAEBufferPoolADSP; //@{ /*! @@ -54,7 +54,7 @@ namespace ActiveAE * @param streamType The input stream type to find allowed master process dsp addons for it, e.g. AE_DSP_ASTREAM_MUSIC * @return True if the dsp processing becomes available */ - bool Create(const AEAudioFormat &inputFormat, const AEAudioFormat &outputFormat, bool upmix, AEQuality quality, AE_DSP_STREAMTYPE streamType, + bool Create(const AEAudioFormat &inputFormat, const AEAudioFormat &outputFormat, bool upmix, bool bypassDSP, AEQuality quality, AE_DSP_STREAMTYPE streamType, enum AVMatrixEncoding matrix_encoding, enum AVAudioServiceType audio_service_type, int profile); /*!> @@ -72,70 +72,29 @@ namespace ActiveAE */ AE_DSP_STREAM_ID GetStreamId() const; + /*!> + * Get the currently used input stream format + * @note used to have a fallback to normal operation without dsp + */ + AEAudioFormat GetOutputFormat(); + /*!> * Get the currently used input stream format * @note used to have a fallback to normal operation without dsp */ AEAudioFormat GetInputFormat(); - /*!> - * Get the incoming channels amount for this class - */ - unsigned int GetInputChannels(); - - /*!> - * Get the incoming sample rate for this class - */ - unsigned int GetInputSamplerate(); - - /*!> - * Get the incoming channel names as string - */ - std::string GetInputChannelNames(); - /*!> * Get the inside addons used samplerate for this class */ unsigned int GetProcessSamplerate(); - /*!> - * Get the outgoing channels amount for this class - */ - unsigned int GetOutputChannels(); - - /*!> - * Get the outgoing channel names - */ - std::string GetOutputChannelNames(); - - /*!> - * Get the used output samplerate for this class - */ - unsigned int GetOutputSamplerate(); - - /*!> - * Get the used output frames for this class - */ - unsigned int GetOutputFrames(); - /*!> * Get the amount of percent what the cpu need to process complete dsp stream * @return The current cpu usage */ float GetCPUUsage(void) const; - /*!> - * Get the channel layout which is passed out from it - * @return Channel information class - */ - CAEChannelInfo GetChannelLayout(); - - /*!> - * Get the currently used output data format - * @note Is normally float - */ - AEDataFormat GetDataFormat(); - /*!> * It returns the on input source detected stream type, not always the active one. */ @@ -185,7 +144,7 @@ namespace ActiveAE /*!> * Returns the information class from the currently used dsp addon - * @return pointer to the info class, or uninitialized class if no master processing present + * @return pointer to the info class, or unitialized class if no master processing present */ CActiveAEDSPModePtr GetActiveMasterMode() const; @@ -210,7 +169,7 @@ namespace ActiveAE bool GetMasterModeStreamInfoString(std::string &strInfo); /*!> - * Get all dsp addon relevant information to detect processing mode type and base values. + * Get all dsp addon relavant information to detect processing mode type and base values. * @retval streamTypeUsed The current stream type processed by addon * @retval baseType The current base type type processed by addon * @retval iModeID The database identification code of the mode @@ -228,7 +187,7 @@ namespace ActiveAE bool IsMenuHookModeActive(AE_DSP_MENUHOOK_CAT category, int iAddonId, unsigned int iModeNumber); protected: - friend class CActiveAEBufferPoolResample; + friend class CActiveAEBufferPoolADSP; /*!> * Master processing @@ -244,6 +203,11 @@ namespace ActiveAE * @return seconds */ float GetDelay(); + + /*!> + * Update the state all AudioDSP modes. + */ + void UpdateActiveModes(); //@} private: //@{ @@ -261,7 +225,7 @@ namespace ActiveAE bool RecheckProcessArray(unsigned int inputFrames); bool ReallocProcessArray(unsigned int requestSize); void CalculateCPUUsage(uint64_t iTime); - void SetFFMpegDSPProcessorArray(float *array_ffmpeg[2][AE_DSP_CH_MAX], float **array_in, float **array_out); + void SetFFMpegDSPProcessorArray(float *array_ffmpeg[AE_DSP_CH_MAX], float *array_dsp[AE_DSP_CH_MAX], int idx[AE_CH_MAX], unsigned long ChannelFlags); //@} //@{ /*! @@ -273,11 +237,9 @@ namespace ActiveAE bool m_forceInit; /*!< if set to true the process function perform a reinitialization of addons and data */ AE_DSP_ADDONMAP m_usedMap; /*!< a map of all currently used audio dsp add-on's */ AEAudioFormat m_inputFormat; /*!< the used input stream format */ - AEAudioFormat m_outputFormat; /*!< the from XBMX requested output format */ - unsigned int m_outputSamplerate; /*!< the currently active output samplerate can be become changed from addon resamplers */ - unsigned int m_outputFrames; /*!< the maximum present output frames */ + AEAudioFormat m_outputFormat; /*!< the from Kodi requested output format */ AEQuality m_streamQuality; /*!< from KODI requested stream quality, based also to addons */ - enum AEDataFormat m_dataFormat; /*!< The inside addon system used data format, currently fixed to float */ + bool m_bypassDSP; /*!< if true, all AudioDSP modes are skipped */ AE_DSP_SETTINGS m_addonSettings; /*!< the current stream's settings passed to dsp add-ons */ AE_DSP_STREAM_PROPERTIES m_addonStreamProperties; /*!< the current stream's properties (eg. stream type) passed to dsp add-ons */ int m_NewMasterMode; /*!< if master mode is changed it set here and handled by process function */ @@ -334,8 +296,6 @@ namespace ActiveAE /*!> * Internal ffmpeg process data */ - #define FFMPEG_PROC_ARRAY_IN 0 - #define FFMPEG_PROC_ARRAY_OUT 1 IAEResample *m_resamplerDSPProcessor; /*!< ffmpeg resampler usage for down mix of input stream to required output channel alignment or internal processing*/ float *m_ffMpegConvertArray[2][AE_DSP_CH_MAX]; /*!< the process array memory pointers for ffmpeg used for format convert. No own memory only addresses taken from m_processArray in correct ffmpeg channel alignment */ float *m_ffMpegProcessArray[2][AE_DSP_CH_MAX]; /*!< the process array memory pointers for ffmpeg. No own memory only addresses taken from m_processArray in correct ffmpeg channel alignment */