2 * Copyright (C) 2010-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
23 using namespace ActiveAE;
24 #include "ActiveAESound.h"
25 #include "ActiveAEStream.h"
26 #include "Utils/AEUtil.h"
27 #include "Encoders/AEEncoderFFmpeg.h"
29 #include "settings/Settings.h"
30 #include "settings/AdvancedSettings.h"
31 #include "windowing/WindowingFactory.h"
33 #define MAX_CACHE_LEVEL 0.5 // total cache time of stream in seconds
34 #define MAX_WATER_LEVEL 0.25 // buffered time after stream stages in seconds
36 void CEngineStats::Reset(unsigned int sampleRate)
38 CSingleLock lock(m_lock);
39 m_sinkUpdate = XbmcThreads::SystemClockMillis();
41 m_sinkSampleRate = sampleRate;
42 m_bufferedSamples = 0;
46 void CEngineStats::UpdateSinkDelay(double delay, int samples)
48 CSingleLock lock(m_lock);
49 m_sinkUpdate = XbmcThreads::SystemClockMillis();
51 if (samples > m_bufferedSamples)
53 CLog::Log(LOGERROR, "CEngineStats::UpdateSinkDelay - inconsistency in buffer time");
56 m_bufferedSamples -= samples;
59 void CEngineStats::AddSamples(int samples, std::list<CActiveAEStream*> &streams)
61 CSingleLock lock(m_lock);
62 m_bufferedSamples += samples;
64 //update buffered time of streams
65 std::list<CActiveAEStream*>::iterator it;
66 for(it=streams.begin(); it!=streams.end(); ++it)
69 std::deque<CSampleBuffer*>::iterator itBuf;
70 for(itBuf=(*it)->m_processingSamples.begin(); itBuf!=(*it)->m_processingSamples.end(); ++itBuf)
72 delay += (float)(*itBuf)->pkt->nb_samples / (*itBuf)->pkt->config.sample_rate;
74 delay += (*it)->m_resampleBuffers->GetDelay();
75 (*it)->m_bufferedTime = delay;
79 float CEngineStats::GetDelay()
81 CSingleLock lock(m_lock);
82 unsigned int now = XbmcThreads::SystemClockMillis();
83 float delay = m_sinkDelay - (double)(now-m_sinkUpdate) / 1000;
84 delay += (float)m_bufferedSamples / m_sinkSampleRate;
92 float CEngineStats::GetDelay(CActiveAEStream *stream)
94 CSingleLock lock(m_lock);
95 unsigned int now = XbmcThreads::SystemClockMillis();
96 float delay = m_sinkDelay - (double)(now-m_sinkUpdate) / 1000;
97 delay += (float)m_bufferedSamples / m_sinkSampleRate;
102 delay += stream->m_bufferedTime;
106 float CEngineStats::GetCacheTime(CActiveAEStream *stream)
108 CSingleLock lock(m_lock);
109 float delay = (float)m_bufferedSamples / m_sinkSampleRate;
111 delay += stream->m_bufferedTime;
115 float CEngineStats::GetCacheTotal(CActiveAEStream *stream)
117 return MAX_CACHE_LEVEL + m_sinkCacheTotal;
120 float CEngineStats::GetWaterLevel()
122 return (float)m_bufferedSamples / m_sinkSampleRate;
125 void CEngineStats::SetSuspended(bool state)
127 CSingleLock lock(m_lock);
131 bool CEngineStats::IsSuspended()
133 CSingleLock lock(m_lock);
137 CActiveAE::CActiveAE() :
139 m_controlPort("OutputControlPort", &m_inMsgEvent, &m_outMsgEvent),
140 m_dataPort("OutputDataPort", &m_inMsgEvent, &m_outMsgEvent),
141 m_sink(&m_outMsgEvent)
143 m_sinkBuffers = NULL;
144 m_silenceBuffers = NULL;
145 m_encoderBuffers = NULL;
153 m_audioCallback = NULL;
154 m_vizInitialized = false;
155 m_sinkHasVolume = false;
158 CActiveAE::~CActiveAE()
163 void CActiveAE::Dispose()
165 #if defined(HAS_GLX) || defined(TARGET_DARWIN_OSX)
166 g_Windowing.Unregister(this);
172 m_controlPort.Purge();
176 m_dllAvFormat.Unload();
177 m_dllAvCodec.Unload();
178 m_dllAvUtil.Unload();
181 //-----------------------------------------------------------------------------
183 //-----------------------------------------------------------------------------
189 AE_TOP_UNCONFIGURED, // 2
190 AE_TOP_RECONFIGURING, // 3
191 AE_TOP_CONFIGURED, // 4
192 AE_TOP_CONFIGURED_SUSPEND, // 5
193 AE_TOP_CONFIGURED_IDLE, // 6
194 AE_TOP_CONFIGURED_PLAY, // 7
197 int AE_parentStates[] = {
200 0, //TOP_UNCONFIGURED
202 0, //TOP_RECONFIGURING
203 4, //TOP_CONFIGURED_SUSPEND
204 4, //TOP_CONFIGURED_IDLE
205 4, //TOP_CONFIGURED_PLAY
208 void CActiveAE::StateMachine(int signal, Protocol *port, Message *msg)
210 for (int state = m_state; ; state = AE_parentStates[state])
215 if (port == &m_controlPort)
219 case CActiveAEControlProtocol::GETSTATE:
220 msg->Reply(CActiveAEControlProtocol::ACC, &m_state, sizeof(m_state));
222 case CActiveAEControlProtocol::SOUNDMODE:
223 m_soundMode = *(int*)msg->data;
225 case CActiveAEControlProtocol::VOLUME:
226 m_volume = *(float*)msg->data;
228 m_sink.m_controlPort.SendOutMessage(CSinkControlProtocol::VOLUME, &m_volume, sizeof(float));
230 case CActiveAEControlProtocol::MUTE:
231 m_muted = *(bool*)msg->data;
237 else if (port == &m_dataPort)
241 case CActiveAEDataProtocol::NEWSOUND:
242 CActiveAESound *sound;
243 sound = *(CActiveAESound**)msg->data;
246 m_sounds.push_back(sound);
250 case CActiveAEDataProtocol::FREESTREAM:
251 CActiveAEStream *stream;
252 stream = *(CActiveAEStream**)msg->data;
253 DiscardStream(stream);
255 case CActiveAEDataProtocol::FREESOUND:
256 sound = *(CActiveAESound**)msg->data;
259 case CActiveAEDataProtocol::DRAINSTREAM:
260 stream = *(CActiveAEStream**)msg->data;
261 stream->m_drain = true;
262 stream->m_resampleBuffers->m_drain = true;
263 msg->Reply(CActiveAEDataProtocol::ACC);
264 stream->m_streamPort->SendInMessage(CActiveAEDataProtocol::STREAMDRAINED);
270 else if (&m_sink.m_dataPort)
274 case CSinkDataProtocol::RETURNSAMPLE:
275 CSampleBuffer **buffer;
276 buffer = (CSampleBuffer**)msg->data;
287 std::string portName = port == NULL ? "timer" : port->portName;
288 CLog::Log(LOGWARNING, "CActiveAE::%s - signal: %d from port: %s not handled for state: %d", __FUNCTION__, signal, portName.c_str(), m_state);
293 if (port == NULL) // timeout
297 case CActiveAEControlProtocol::TIMEOUT:
303 m_state = AE_TOP_CONFIGURED_IDLE;
308 m_state = AE_TOP_ERROR;
318 case AE_TOP_UNCONFIGURED:
319 if (port == &m_controlPort)
323 case CActiveAEControlProtocol::INIT:
325 m_sink.EnumerateSinkList(false);
328 msg->Reply(CActiveAEControlProtocol::ACC);
331 m_state = AE_TOP_CONFIGURED_IDLE;
336 m_state = AE_TOP_ERROR;
347 case AE_TOP_RECONFIGURING:
348 if (port == NULL) // timeout
352 case CActiveAEControlProtocol::TIMEOUT:
359 if (!m_sinkBuffers->m_inputSamples.empty() || !m_sinkBuffers->m_outputSamples.empty())
364 if (NeedReconfigureSink())
371 m_state = AE_TOP_CONFIGURED_PLAY;
376 m_state = AE_TOP_ERROR;
379 m_extDeferData = false;
387 case AE_TOP_CONFIGURED:
388 if (port == &m_controlPort)
392 case CActiveAEControlProtocol::RECONFIGURE:
393 if (m_streams.empty())
395 bool silence = false;
396 m_sink.m_controlPort.SendOutMessage(CSinkControlProtocol::SILENCEMODE, &silence, sizeof(bool));
400 if (!NeedReconfigureBuffers() && !NeedReconfigureSink())
402 m_state = AE_TOP_RECONFIGURING;
404 // don't accept any data until we are reconfigured
405 m_extDeferData = true;
407 case CActiveAEControlProtocol::SUSPEND:
409 m_stats.SetSuspended(true);
410 m_state = AE_TOP_CONFIGURED_SUSPEND;
411 m_extDeferData = true;
413 case CActiveAEControlProtocol::DISPLAYLOST:
414 if (m_settings.mode == AUDIO_HDMI)
417 m_stats.SetSuspended(true);
418 m_state = AE_TOP_CONFIGURED_SUSPEND;
419 m_extDeferData = true;
422 case CActiveAEControlProtocol::PAUSESTREAM:
423 CActiveAEStream *stream;
424 stream = *(CActiveAEStream**)msg->data;
425 if (stream->m_paused != true && m_streams.size() == 1)
427 stream->m_paused = true;
429 case CActiveAEControlProtocol::RESUMESTREAM:
430 stream = *(CActiveAEStream**)msg->data;
431 stream->m_paused = false;
432 m_state = AE_TOP_CONFIGURED_PLAY;
435 case CActiveAEControlProtocol::FLUSHSTREAM:
436 stream = *(CActiveAEStream**)msg->data;
437 SFlushStream(stream);
438 msg->Reply(CActiveAEControlProtocol::ACC);
439 m_state = AE_TOP_CONFIGURED_PLAY;
442 case CActiveAEControlProtocol::STREAMAMP:
443 MsgStreamParameter *par;
444 par = (MsgStreamParameter*)msg->data;
445 par->stream->m_limiter.SetAmplification(par->parameter.float_par);
446 par->stream->m_amplify = par->parameter.float_par;
448 case CActiveAEControlProtocol::STREAMVOLUME:
449 par = (MsgStreamParameter*)msg->data;
450 par->stream->m_volume = par->parameter.float_par;
452 case CActiveAEControlProtocol::STREAMRGAIN:
453 par = (MsgStreamParameter*)msg->data;
454 par->stream->m_rgain = par->parameter.float_par;
456 case CActiveAEControlProtocol::STREAMRESAMPLERATIO:
457 par = (MsgStreamParameter*)msg->data;
458 if (par->stream->m_resampleBuffers)
460 par->stream->m_resampleBuffers->m_resampleRatio = par->parameter.double_par;
463 case CActiveAEControlProtocol::STREAMFADE:
465 fade = (MsgStreamFade*)msg->data;
466 fade->stream->m_fadingBase = fade->from;
467 fade->stream->m_fadingTarget = fade->target;
468 fade->stream->m_fadingTime = fade->millis;
469 fade->stream->m_fadingSamples = -1;
471 case CActiveAEControlProtocol::STOPSOUND:
472 CActiveAESound *sound;
473 sound = *(CActiveAESound**)msg->data;
480 else if (port == &m_dataPort)
484 case CActiveAEDataProtocol::PLAYSOUND:
485 CActiveAESound *sound;
486 sound = *(CActiveAESound**)msg->data;
487 if (m_soundMode == AE_SOUND_OFF ||
488 (m_soundMode == AE_SOUND_IDLE && !m_streams.empty()))
492 SoundState st = {sound, 0};
493 m_sounds_playing.push_back(st);
495 m_state = AE_TOP_CONFIGURED_PLAY;
498 case CActiveAEDataProtocol::NEWSTREAM:
499 MsgStreamNew *streamMsg;
500 CActiveAEStream *stream;
501 streamMsg = (MsgStreamNew*)msg->data;
502 stream = CreateStream(streamMsg);
505 msg->Reply(CActiveAEDataProtocol::ACC, &stream, sizeof(CActiveAEStream*));
510 m_state = AE_TOP_CONFIGURED_PLAY;
515 m_state = AE_TOP_ERROR;
520 msg->Reply(CActiveAEDataProtocol::ERR);
522 case CActiveAEDataProtocol::STREAMSAMPLE:
523 MsgStreamSample *msgData;
524 CSampleBuffer *samples;
525 msgData = (MsgStreamSample*)msg->data;
526 samples = msgData->stream->m_processingSamples.front();
527 msgData->stream->m_processingSamples.pop_front();
528 if (samples != msgData->buffer)
529 CLog::Log(LOGERROR, "CActiveAE - inconsistency in stream sample message");
530 if (msgData->buffer->pkt->nb_samples == 0)
531 msgData->buffer->Return();
533 msgData->stream->m_resampleBuffers->m_inputSamples.push_back(msgData->buffer);
535 m_state = AE_TOP_CONFIGURED_PLAY;
537 case CActiveAEDataProtocol::FREESTREAM:
538 stream = *(CActiveAEStream**)msg->data;
539 DiscardStream(stream);
540 if (m_streams.empty())
542 m_extDrainTimer.Set(m_stats.GetDelay() * 1000);
546 m_state = AE_TOP_CONFIGURED_PLAY;
548 case CActiveAEDataProtocol::DRAINSTREAM:
549 stream = *(CActiveAEStream**)msg->data;
550 stream->m_drain = true;
551 stream->m_resampleBuffers->m_drain = true;
553 m_state = AE_TOP_CONFIGURED_PLAY;
554 msg->Reply(CActiveAEDataProtocol::ACC);
560 else if (&m_sink.m_dataPort)
564 case CSinkDataProtocol::RETURNSAMPLE:
565 CSampleBuffer **buffer;
566 buffer = (CSampleBuffer**)msg->data;
572 m_state = AE_TOP_CONFIGURED_PLAY;
580 case AE_TOP_CONFIGURED_SUSPEND:
581 if (port == &m_controlPort)
583 bool displayReset = false;
586 case CActiveAEControlProtocol::DISPLAYRESET:
588 case CActiveAEControlProtocol::INIT:
592 m_sink.EnumerateSinkList(true);
597 msg->Reply(CActiveAEControlProtocol::ACC);
600 m_state = AE_TOP_CONFIGURED_PLAY;
605 m_state = AE_TOP_ERROR;
608 m_stats.SetSuspended(false);
609 m_extDeferData = false;
615 else if (&m_sink.m_dataPort)
619 case CSinkDataProtocol::RETURNSAMPLE:
620 CSampleBuffer **buffer;
621 buffer = (CSampleBuffer**)msg->data;
633 case AE_TOP_CONFIGURED_IDLE:
634 if (port == NULL) // timeout
638 case CActiveAEControlProtocol::TIMEOUT:
640 ClearDiscardedBuffers();
643 if (m_extDrainTimer.IsTimePast())
648 m_state = AE_TOP_CONFIGURED_PLAY;
653 m_state = AE_TOP_ERROR;
658 m_extTimeout = m_extDrainTimer.MillisLeft();
669 case AE_TOP_CONFIGURED_PLAY:
670 if (port == NULL) // timeout
674 case CActiveAEControlProtocol::TIMEOUT:
677 m_state = AE_TOP_ERROR;
686 if (!m_extDrain && HasWork())
689 ClearDiscardedBuffers();
694 m_state = AE_TOP_CONFIGURED_IDLE;
702 default: // we are in no state, should not happen
703 CLog::Log(LOGERROR, "CActiveAE::%s - no valid state: %d", __FUNCTION__, m_state);
709 void CActiveAE::Process()
712 Protocol *port = NULL;
715 m_state = AE_TOP_UNCONFIGURED;
717 m_bStateMachineSelfTrigger = false;
719 m_extDeferData = false;
728 if (m_bStateMachineSelfTrigger)
730 m_bStateMachineSelfTrigger = false;
731 // self trigger state machine
732 StateMachine(msg->signal, port, msg);
733 if (!m_bStateMachineSelfTrigger)
740 // check control port
741 else if (m_controlPort.ReceiveOutMessage(&msg))
744 port = &m_controlPort;
746 // check sink data port
747 else if (m_sink.m_dataPort.ReceiveInMessage(&msg))
750 port = &m_sink.m_dataPort;
752 else if (!m_extDeferData)
755 if (m_dataPort.ReceiveOutMessage(&msg))
763 std::list<CActiveAEStream*>::iterator it;
764 for(it=m_streams.begin(); it!=m_streams.end(); ++it)
766 if((*it)->m_streamPort->ReceiveOutMessage(&msg))
778 StateMachine(msg->signal, port, msg);
779 if (!m_bStateMachineSelfTrigger)
788 else if (m_outMsgEvent.WaitMSec(m_extTimeout))
795 msg = m_controlPort.GetMessage();
796 msg->signal = CActiveAEControlProtocol::TIMEOUT;
798 // signal timeout to state machine
799 StateMachine(msg->signal, port, msg);
800 if (!m_bStateMachineSelfTrigger)
809 AEAudioFormat CActiveAE::GetInputFormat(AEAudioFormat *desiredFmt)
811 AEAudioFormat inputFormat;
813 if (m_streams.empty())
815 inputFormat.m_dataFormat = AE_FMT_FLOAT;
816 inputFormat.m_sampleRate = 44100;
817 inputFormat.m_encodedRate = 0;
818 inputFormat.m_channelLayout = AE_CH_LAYOUT_2_0;
819 inputFormat.m_frames = 0;
820 inputFormat.m_frameSamples = 0;
821 inputFormat.m_frameSize = 0;
823 // force input format after unpausing slave
824 else if (desiredFmt != NULL)
826 inputFormat = *desiredFmt;
828 // keep format when having multiple streams
829 else if (m_streams.size() > 1 && m_silenceBuffers == NULL)
831 inputFormat = m_inputFormat;
835 inputFormat = m_streams.front()->m_format;
836 m_inputFormat = inputFormat;
842 void CActiveAE::Configure(AEAudioFormat *desiredFmt)
844 bool initSink = false;
846 AEAudioFormat sinkInputFormat, inputFormat;
847 AEAudioFormat oldInternalFormat = m_internalFormat;
849 inputFormat = GetInputFormat(desiredFmt);
851 m_sinkRequestFormat = inputFormat;
852 ApplySettingsToFormat(m_sinkRequestFormat, m_settings, (int*)&m_mode);
853 std::string device = AE_IS_RAW(m_sinkRequestFormat.m_dataFormat) ? m_settings.passthoughdevice : m_settings.device;
855 CAESinkFactory::ParseDevice(device, driver);
856 if (!IsSinkCompatible(m_sinkRequestFormat, device) || m_settings.driver.compare(driver) != 0)
860 m_settings.driver = driver;
862 m_stats.Reset(m_sinkFormat.m_sampleRate);
863 m_sink.m_controlPort.SendOutMessage(CSinkControlProtocol::VOLUME, &m_volume, sizeof(float));
866 if (m_silenceBuffers)
868 m_discardBufferPools.push_back(m_silenceBuffers);
869 m_silenceBuffers = NULL;
872 // buffers for driving gui sounds if no streams are active
873 if (m_streams.empty())
875 inputFormat = m_sinkFormat;
876 inputFormat.m_channelLayout = m_sinkRequestFormat.m_channelLayout;
877 inputFormat.m_channelLayout.ResolveChannels(m_sinkFormat.m_channelLayout);
878 inputFormat.m_dataFormat = AE_FMT_FLOAT;
879 inputFormat.m_frameSize = inputFormat.m_channelLayout.Count() *
880 (CAEUtil::DataFormatToBits(inputFormat.m_dataFormat) >> 3);
881 m_silenceBuffers = new CActiveAEBufferPool(inputFormat);
882 m_silenceBuffers->Create(MAX_WATER_LEVEL*1000);
883 sinkInputFormat = inputFormat;
884 m_internalFormat = inputFormat;
886 bool silence = false;
887 m_sink.m_controlPort.SendOutMessage(CSinkControlProtocol::SILENCEMODE, &silence, sizeof(bool));
892 if (m_encoderBuffers)
894 m_discardBufferPools.push_back(m_encoderBuffers);
895 m_encoderBuffers = NULL;
899 m_discardBufferPools.push_back(m_vizBuffers);
903 // resample buffers for streams
907 m_sink.m_controlPort.SendOutMessage(CSinkControlProtocol::SILENCEMODE, &silence, sizeof(bool));
909 AEAudioFormat outputFormat;
910 if (m_mode == MODE_RAW)
912 outputFormat = inputFormat;
913 sinkInputFormat = m_sinkFormat;
915 // transcode everything with more than 2 channels
916 else if (m_mode == MODE_TRANSCODE)
918 outputFormat = inputFormat;
919 outputFormat.m_dataFormat = AE_FMT_FLOATP;
920 outputFormat.m_sampleRate = 48000;
925 m_encoder = new CAEEncoderFFmpeg();
926 m_encoder->Initialize(outputFormat, true);
927 m_encoderFormat = outputFormat;
930 outputFormat = m_encoderFormat;
932 outputFormat.m_channelLayout = m_encoderFormat.m_channelLayout;
933 outputFormat.m_frames = m_encoderFormat.m_frames;
936 if (m_encoder->GetCodecID() == AV_CODEC_ID_AC3)
938 AEAudioFormat format;
939 format.m_channelLayout = AE_CH_LAYOUT_2_0;
940 format.m_dataFormat = AE_FMT_S16NE;
941 format.m_frameSize = 2* (CAEUtil::DataFormatToBits(format.m_dataFormat) >> 3);
942 format.m_frames = AC3_FRAME_SIZE;
943 format.m_sampleRate = 48000;
944 if (m_encoderBuffers && initSink)
946 m_discardBufferPools.push_back(m_encoderBuffers);
947 m_encoderBuffers = NULL;
949 if (!m_encoderBuffers)
951 m_encoderBuffers = new CActiveAEBufferPool(format);
952 m_encoderBuffers->Create(MAX_WATER_LEVEL*1000);
956 sinkInputFormat = m_sinkFormat;
960 outputFormat = m_sinkFormat;
961 outputFormat.m_channelLayout = m_sinkRequestFormat.m_channelLayout;
962 outputFormat.m_channelLayout.ResolveChannels(m_sinkFormat.m_channelLayout);
963 outputFormat.m_dataFormat = AE_FMT_FLOAT;
964 outputFormat.m_frameSize = outputFormat.m_channelLayout.Count() *
965 (CAEUtil::DataFormatToBits(outputFormat.m_dataFormat) >> 3);
966 // TODO: adjust to decoder
967 sinkInputFormat = outputFormat;
969 m_internalFormat = outputFormat;
971 std::list<CActiveAEStream*>::iterator it;
972 for(it=m_streams.begin(); it!=m_streams.end(); ++it)
974 // check if we support input format of stream
975 if (!AE_IS_RAW((*it)->m_format.m_dataFormat) &&
976 CActiveAEResample::GetAVSampleFormat((*it)->m_format.m_dataFormat) == AV_SAMPLE_FMT_FLT &&
977 (*it)->m_format.m_dataFormat != AE_FMT_FLOAT)
979 (*it)->m_convertFn = CAEConvert::ToFloat((*it)->m_format.m_dataFormat);
980 (*it)->m_format.m_dataFormat = AE_FMT_FLOAT;
983 if (!(*it)->m_inputBuffers)
985 // align input buffers with period of sink or encoder
986 (*it)->m_format.m_frames = m_internalFormat.m_frames * ((float)(*it)->m_format.m_sampleRate / m_internalFormat.m_sampleRate);
988 // create buffer pool
989 (*it)->m_inputBuffers = new CActiveAEBufferPool((*it)->m_format);
990 (*it)->m_inputBuffers->Create(MAX_CACHE_LEVEL*1000);
992 if (initSink && (*it)->m_resampleBuffers)
994 m_discardBufferPools.push_back((*it)->m_resampleBuffers);
995 (*it)->m_resampleBuffers = NULL;
997 if (!(*it)->m_resampleBuffers)
999 (*it)->m_resampleBuffers = new CActiveAEBufferPoolResample((*it)->m_inputBuffers->m_format, outputFormat, m_settings.resampleQuality);
1000 (*it)->m_resampleBuffers->m_changeResampler = (*it)->m_forceResampler;
1001 (*it)->m_resampleBuffers->Create(MAX_CACHE_LEVEL*1000, false, m_settings.stereoupmix);
1003 if (m_mode == MODE_TRANSCODE || m_streams.size() > 1)
1004 (*it)->m_resampleBuffers->m_fillPackets = true;
1007 (*it)->m_limiter.SetSamplerate(outputFormat.m_sampleRate);
1011 if (!AE_IS_RAW(inputFormat.m_dataFormat))
1013 if (initSink && m_vizBuffers)
1015 m_discardBufferPools.push_back(m_vizBuffers);
1016 m_vizBuffers = NULL;
1020 AEAudioFormat vizFormat = m_internalFormat;
1021 vizFormat.m_channelLayout = AE_CH_LAYOUT_2_0;
1022 vizFormat.m_dataFormat = AE_FMT_FLOAT;
1023 m_vizBuffers = new CActiveAEBufferPoolResample(m_internalFormat, vizFormat, m_settings.resampleQuality);
1024 // TODO use cache of sync + water level
1025 m_vizBuffers->Create(2000, false, false);
1026 m_vizInitialized = false;
1031 // resample buffers for sink
1032 if (m_sinkBuffers &&
1033 (!CompareFormat(m_sinkBuffers->m_format,m_sinkFormat) || !CompareFormat(m_sinkBuffers->m_inputFormat, sinkInputFormat)))
1035 m_discardBufferPools.push_back(m_sinkBuffers);
1036 m_sinkBuffers = NULL;
1040 m_sinkBuffers = new CActiveAEBufferPoolResample(sinkInputFormat, m_sinkFormat, m_settings.resampleQuality);
1041 m_sinkBuffers->Create(MAX_WATER_LEVEL*1000, true, false);
1045 if (!CompareFormat(oldInternalFormat, m_internalFormat))
1047 std::vector<CActiveAESound*>::iterator it;
1048 for (it = m_sounds.begin(); it != m_sounds.end(); ++it)
1050 (*it)->SetConverted(false);
1054 ClearDiscardedBuffers();
1058 CActiveAEStream* CActiveAE::CreateStream(MsgStreamNew *streamMsg)
1060 // we only can handle a single pass through stream
1061 bool hasRawStream = false;
1062 bool hasStream = false;
1063 std::list<CActiveAEStream*>::iterator it;
1064 for(it = m_streams.begin(); it != m_streams.end(); ++it)
1066 if((*it)->IsDrained())
1068 if(AE_IS_RAW((*it)->m_format.m_dataFormat))
1069 hasRawStream = true;
1072 if (hasRawStream || (hasStream && AE_IS_RAW(streamMsg->format.m_dataFormat)))
1077 // create the stream
1078 CActiveAEStream *stream;
1079 stream = new CActiveAEStream(&streamMsg->format);
1080 stream->m_streamPort = new CActiveAEDataProtocol("stream",
1081 &stream->m_inMsgEvent, &m_outMsgEvent);
1083 // create buffer pool
1084 stream->m_inputBuffers = NULL; // create in Configure when we know the sink format
1085 stream->m_resampleBuffers = NULL; // create in Configure when we know the sink format
1086 stream->m_statsLock = m_stats.GetLock();
1087 stream->m_fadingSamples = 0;
1088 stream->m_started = false;
1090 if (streamMsg->options & AESTREAM_PAUSED)
1091 stream->m_paused = true;
1093 if (streamMsg->options & AESTREAM_FORCE_RESAMPLE)
1094 stream->m_forceResampler = true;
1096 m_streams.push_back(stream);
1101 void CActiveAE::DiscardStream(CActiveAEStream *stream)
1103 std::list<CActiveAEStream*>::iterator it;
1104 for (it=m_streams.begin(); it!=m_streams.end(); )
1106 if (stream == (*it))
1108 while (!(*it)->m_processingSamples.empty())
1110 (*it)->m_processingSamples.front()->Return();
1111 (*it)->m_processingSamples.pop_front();
1113 m_discardBufferPools.push_back((*it)->m_inputBuffers);
1114 m_discardBufferPools.push_back((*it)->m_resampleBuffers);
1115 CLog::Log(LOGDEBUG, "CActiveAE::DiscardStream - audio stream deleted");
1116 delete (*it)->m_streamPort;
1118 it = m_streams.erase(it);
1124 ClearDiscardedBuffers();
1127 void CActiveAE::SFlushStream(CActiveAEStream *stream)
1129 while (!stream->m_processingSamples.empty())
1131 stream->m_processingSamples.front()->Return();
1132 stream->m_processingSamples.pop_front();
1134 stream->m_resampleBuffers->Flush();
1135 stream->m_streamPort->Purge();
1136 stream->m_bufferedTime = 0.0;
1137 stream->m_paused = false;
1139 // flush the engine if we only have a single stream
1140 if (m_streams.size() == 1)
1146 void CActiveAE::FlushEngine()
1149 m_sinkBuffers->Flush();
1151 m_vizBuffers->Flush();
1153 // send message to sink
1155 if (m_sink.m_controlPort.SendOutMessageSync(CSinkControlProtocol::FLUSH,
1158 bool success = reply->signal == CSinkControlProtocol::ACC ? true : false;
1161 CLog::Log(LOGERROR, "ActiveAE::%s - returned error on flush", __FUNCTION__);
1168 CLog::Log(LOGERROR, "ActiveAE::%s - failed to flush", __FUNCTION__);
1171 m_stats.Reset(m_sinkFormat.m_sampleRate);
1174 void CActiveAE::ClearDiscardedBuffers()
1176 std::list<CActiveAEBufferPool*>::iterator it;
1177 for (it=m_discardBufferPools.begin(); it!=m_discardBufferPools.end(); ++it)
1179 CActiveAEBufferPoolResample *rbuf = dynamic_cast<CActiveAEBufferPoolResample*>(*it);
1184 // if all buffers have returned, we can delete the buffer pool
1185 if ((*it)->m_allSamples.size() == (*it)->m_freeSamples.size())
1188 CLog::Log(LOGDEBUG, "CActiveAE::ClearDiscardedBuffers - buffer pool deleted");
1189 m_discardBufferPools.erase(it);
1195 void CActiveAE::SStopSound(CActiveAESound *sound)
1197 std::list<SoundState>::iterator it;
1198 for (it=m_sounds_playing.begin(); it!=m_sounds_playing.end(); ++it)
1200 if (it->sound == sound)
1202 m_sounds_playing.erase(it);
1208 void CActiveAE::DiscardSound(CActiveAESound *sound)
1212 std::vector<CActiveAESound*>::iterator it;
1213 for (it=m_sounds.begin(); it!=m_sounds.end(); ++it)
1223 void CActiveAE::ChangeResamplers()
1225 std::list<CActiveAEStream*>::iterator it;
1226 for(it=m_streams.begin(); it!=m_streams.end(); ++it)
1228 if ((*it)->m_resampleBuffers && (*it)->m_resampleBuffers->m_resampler &&
1229 (((*it)->m_resampleBuffers->m_resampleQuality != m_settings.resampleQuality) ||
1230 ((*it)->m_resampleBuffers->m_stereoUpmix != m_settings.stereoupmix)))
1232 (*it)->m_resampleBuffers->m_changeResampler = true;
1234 (*it)->m_resampleBuffers->m_resampleQuality = m_settings.resampleQuality;
1235 (*it)->m_resampleBuffers->m_stereoUpmix = m_settings.stereoupmix;
1239 void CActiveAE::ApplySettingsToFormat(AEAudioFormat &format, AudioSettings &settings, int *mode)
1245 if (m_settings.mode != AUDIO_ANALOG && AE_IS_RAW(format.m_dataFormat))
1247 if ((format.m_dataFormat == AE_FMT_AC3 && !settings.ac3passthrough) ||
1248 (format.m_dataFormat == AE_FMT_EAC3 && !settings.eac3passthrough) ||
1249 (format.m_dataFormat == AE_FMT_TRUEHD && !settings.truehdpassthrough) ||
1250 (format.m_dataFormat == AE_FMT_DTS && !settings.dtspassthrough) ||
1251 (format.m_dataFormat == AE_FMT_DTSHD && !settings.dtshdpassthrough))
1253 CLog::Log(LOGERROR, "CActiveAE::ApplySettingsToFormat - input audio format is wrong");
1259 else if (m_settings.mode != AUDIO_ANALOG &&
1260 settings.ac3passthrough &&
1261 (!settings.multichannellpcm || (m_settings.mode != AUDIO_HDMI)) &&
1262 !m_streams.empty() &&
1263 (format.m_channelLayout.Count() > 2 || settings.stereoupmix))
1265 format.m_dataFormat = AE_FMT_AC3;
1266 format.m_sampleRate = 48000;
1267 format.m_channelLayout = AE_CH_LAYOUT_2_0;
1269 *mode = MODE_TRANSCODE;
1273 format.m_dataFormat = AE_FMT_FLOAT;
1274 // consider user channel layout for those cases
1275 // 1. input stream is multichannel
1276 // 2. stereo upmix is selected
1277 // 3. already playing > 2 channels and "audiophile" is not set
1278 // this is the case if e.g. a stream changes config from 5.1 to 2.0
1279 // which would cause a short audio drop-out if we changed the sink
1280 if ((format.m_channelLayout.Count() > 2) ||
1281 settings.stereoupmix ||
1282 (m_stats.GetWaterLevel() > 0 && m_internalFormat.m_channelLayout.Count() > 2 && !g_advancedSettings.m_audioAudiophile))
1284 CAEChannelInfo stdLayout;
1285 switch (settings.channels)
1288 case 0: stdLayout = AE_CH_LAYOUT_2_0; break;
1289 case 1: stdLayout = AE_CH_LAYOUT_2_0; break;
1290 case 2: stdLayout = AE_CH_LAYOUT_2_1; break;
1291 case 3: stdLayout = AE_CH_LAYOUT_3_0; break;
1292 case 4: stdLayout = AE_CH_LAYOUT_3_1; break;
1293 case 5: stdLayout = AE_CH_LAYOUT_4_0; break;
1294 case 6: stdLayout = AE_CH_LAYOUT_4_1; break;
1295 case 7: stdLayout = AE_CH_LAYOUT_5_0; break;
1296 case 8: stdLayout = AE_CH_LAYOUT_5_1; break;
1297 case 9: stdLayout = AE_CH_LAYOUT_7_0; break;
1298 case 10: stdLayout = AE_CH_LAYOUT_7_1; break;
1301 if (g_advancedSettings.m_audioAudiophile)
1302 format.m_channelLayout.ResolveChannels(stdLayout);
1304 format.m_channelLayout = stdLayout;
1307 if (m_settings.mode == AUDIO_IEC958 && format.m_sampleRate > 48000)
1309 format.m_sampleRate = 48000;
1310 CLog::Log(LOGINFO, "CActiveAE::ApplySettings - limit samplerate for SPDIF to %d", format.m_sampleRate);
1313 if (g_advancedSettings.m_audioResample)
1315 format.m_sampleRate = g_advancedSettings.m_audioResample;
1316 CLog::Log(LOGINFO, "CActiveAE::ApplySettings - Forcing samplerate to %d", format.m_sampleRate);
1319 // for IEC958 limit to 2 channels
1320 if (m_settings.mode == AUDIO_IEC958)
1322 format.m_channelLayout = AE_CH_LAYOUT_2_0;
1325 // sinks may not support mono
1326 if (format.m_channelLayout.Count() == 1)
1328 format.m_channelLayout = AE_CH_LAYOUT_2_0;
1333 bool CActiveAE::NeedReconfigureBuffers()
1335 AEAudioFormat newFormat = GetInputFormat();
1336 ApplySettingsToFormat(newFormat, m_settings);
1338 if (newFormat.m_dataFormat != m_sinkRequestFormat.m_dataFormat ||
1339 newFormat.m_channelLayout != m_sinkRequestFormat.m_channelLayout ||
1340 newFormat.m_sampleRate != m_sinkRequestFormat.m_sampleRate)
1346 bool CActiveAE::NeedReconfigureSink()
1348 AEAudioFormat newFormat = GetInputFormat();
1349 ApplySettingsToFormat(newFormat, m_settings);
1351 std::string device = AE_IS_RAW(newFormat.m_dataFormat) ? m_settings.passthoughdevice : m_settings.device;
1353 CAESinkFactory::ParseDevice(device, driver);
1354 if (m_settings.driver.compare(driver) != 0)
1357 if (!IsSinkCompatible(newFormat, device))
1363 bool CActiveAE::InitSink()
1366 config.format = m_sinkRequestFormat;
1367 config.stats = &m_stats;
1368 config.device = AE_IS_RAW(m_sinkRequestFormat.m_dataFormat) ? &m_settings.passthoughdevice :
1371 // send message to sink
1373 if (m_sink.m_controlPort.SendOutMessageSync(CSinkControlProtocol::CONFIGURE,
1376 &config, sizeof(config)))
1378 bool success = reply->signal == CSinkControlProtocol::ACC ? true : false;
1382 CLog::Log(LOGERROR, "ActiveAE::%s - returned error", __FUNCTION__);
1386 AEAudioFormat *data;
1387 data = (AEAudioFormat*)reply->data;
1390 m_sinkFormat = *data;
1392 m_sinkHasVolume = m_sink.HasVolume();
1397 CLog::Log(LOGERROR, "ActiveAE::%s - failed to init", __FUNCTION__);
1402 m_inMsgEvent.Reset();
1406 void CActiveAE::DrainSink()
1408 // send message to sink
1410 if (m_sink.m_dataPort.SendOutMessageSync(CSinkDataProtocol::DRAIN,
1414 bool success = reply->signal == CSinkDataProtocol::ACC ? true : false;
1418 CLog::Log(LOGERROR, "ActiveAE::%s - returned error on drain", __FUNCTION__);
1426 CLog::Log(LOGERROR, "ActiveAE::%s - failed to drain", __FUNCTION__);
1432 bool CActiveAE::IsSinkCompatible(const AEAudioFormat format, const std::string &device)
1434 bool compatible = false;
1436 config.format = format;
1437 config.device = &device;
1439 // send message to sink
1441 if (m_sink.m_controlPort.SendOutMessageSync(CSinkControlProtocol::ISCOMPATIBLE,
1444 &config, sizeof(config)))
1446 bool success = reply->signal == CSinkControlProtocol::ACC ? true : false;
1450 CLog::Log(LOGERROR, "ActiveAE::%s - returned error", __FUNCTION__);
1454 compatible = *(bool*)reply->data;
1459 CLog::Log(LOGERROR, "ActiveAE::%s - failed to query compatibility", __FUNCTION__);
1466 void CActiveAE::UnconfigureSink()
1468 // send message to sink
1470 if (m_sink.m_controlPort.SendOutMessageSync(CSinkControlProtocol::UNCONFIGURE,
1474 bool success = reply->signal == CSinkControlProtocol::ACC ? true : false;
1477 CLog::Log(LOGERROR, "ActiveAE::%s - returned error", __FUNCTION__);
1484 CLog::Log(LOGERROR, "ActiveAE::%s - failed to unconfigure", __FUNCTION__);
1488 m_inMsgEvent.Reset();
1492 bool CActiveAE::RunStages()
1496 // serve input streams
1497 std::list<CActiveAEStream*>::iterator it;
1498 for (it = m_streams.begin(); it != m_streams.end(); ++it)
1500 if ((*it)->m_resampleBuffers && !(*it)->m_paused)
1501 busy = (*it)->m_resampleBuffers->ResampleBuffers();
1502 else if ((*it)->m_resampleBuffers &&
1503 ((*it)->m_resampleBuffers->m_inputSamples.size() > (*it)->m_resampleBuffers->m_allSamples.size() * 0.5))
1505 CSingleLock lock((*it)->m_streamLock);
1506 (*it)->m_streamIsBuffering = false;
1509 // provide buffers to stream
1510 float time = m_stats.GetCacheTime((*it));
1511 CSampleBuffer *buffer;
1512 if (!(*it)->m_drain)
1514 while (time < MAX_CACHE_LEVEL && !(*it)->m_inputBuffers->m_freeSamples.empty())
1516 buffer = (*it)->m_inputBuffers->GetFreeBuffer();
1517 (*it)->m_processingSamples.push_back(buffer);
1518 (*it)->m_streamPort->SendInMessage(CActiveAEDataProtocol::STREAMBUFFER, &buffer, sizeof(CSampleBuffer*));
1519 (*it)->IncFreeBuffers();
1520 time += (float)buffer->pkt->max_nb_samples / buffer->pkt->config.sample_rate;
1525 if ((*it)->m_resampleBuffers->m_inputSamples.empty() &&
1526 (*it)->m_resampleBuffers->m_outputSamples.empty() &&
1527 (*it)->m_processingSamples.empty())
1529 (*it)->m_streamPort->SendInMessage(CActiveAEDataProtocol::STREAMDRAINED);
1530 (*it)->m_drain = false;
1531 (*it)->m_resampleBuffers->m_drain = false;
1532 (*it)->m_started = false;
1534 // set variables being polled via stream interface
1535 CSingleLock lock((*it)->m_streamLock);
1536 if ((*it)->m_streamSlave)
1538 CActiveAEStream *slave = (CActiveAEStream*)((*it)->m_streamSlave);
1539 slave->m_paused = false;
1541 // TODO: find better solution for this
1542 // gapless bites audiophile
1543 if (g_advancedSettings.m_audioAudiophile)
1544 Configure(&slave->m_format);
1546 (*it)->m_streamSlave = NULL;
1548 (*it)->m_streamDrained = true;
1549 (*it)->m_streamDraining = false;
1550 (*it)->m_streamFading = false;
1555 if (m_stats.GetWaterLevel() < MAX_WATER_LEVEL &&
1556 (m_mode != MODE_TRANSCODE || (m_encoderBuffers && !m_encoderBuffers->m_freeSamples.empty())))
1558 // mix streams and sounds sounds
1559 if (m_mode != MODE_RAW)
1561 CSampleBuffer *out = NULL;
1562 if (!m_sounds_playing.empty() && m_streams.empty())
1564 if (m_silenceBuffers && !m_silenceBuffers->m_freeSamples.empty())
1566 out = m_silenceBuffers->GetFreeBuffer();
1567 for (int i=0; i<out->pkt->planes; i++)
1569 memset(out->pkt->data[i], 0, out->pkt->linesize);
1571 out->pkt->nb_samples = out->pkt->max_nb_samples;
1576 std::list<CActiveAEStream*>::iterator it;
1578 // if we deal with more than a single stream, all streams
1579 // must provide samples for mixing
1580 bool allStreamsReady = true;
1581 for (it = m_streams.begin(); it != m_streams.end(); ++it)
1583 if ((*it)->m_paused || !(*it)->m_started || !(*it)->m_resampleBuffers)
1586 if ((*it)->m_resampleBuffers->m_outputSamples.empty())
1587 allStreamsReady = false;
1590 bool needClamp = false;
1591 for (it = m_streams.begin(); it != m_streams.end() && allStreamsReady; ++it)
1593 if ((*it)->m_paused || !(*it)->m_resampleBuffers)
1596 if (!(*it)->m_resampleBuffers->m_outputSamples.empty())
1598 (*it)->m_started = true;
1602 out = (*it)->m_resampleBuffers->m_outputSamples.front();
1603 (*it)->m_resampleBuffers->m_outputSamples.pop_front();
1605 int nb_floats = out->pkt->nb_samples * out->pkt->config.channels / out->pkt->planes;
1607 float fadingStep = 0.0f;
1610 if ((*it)->m_fadingSamples == -1)
1612 (*it)->m_fadingSamples = m_internalFormat.m_sampleRate * (float)(*it)->m_fadingTime / 1000.0f;
1613 (*it)->m_volume = (*it)->m_fadingBase;
1615 if ((*it)->m_fadingSamples > 0)
1617 nb_floats = out->pkt->config.channels / out->pkt->planes;
1618 nb_loops = out->pkt->nb_samples;
1619 float delta = (*it)->m_fadingTarget - (*it)->m_fadingBase;
1620 int samples = m_internalFormat.m_sampleRate * (float)(*it)->m_fadingTime / 1000.0f;
1621 fadingStep = delta / samples;
1624 // for stream amplification we need to run on a per sample basis
1625 if ((*it)->m_amplify != 1.0)
1627 nb_floats = out->pkt->config.channels / out->pkt->planes;
1628 nb_loops = out->pkt->nb_samples;
1631 for(int i=0; i<nb_loops; i++)
1633 if ((*it)->m_fadingSamples > 0)
1635 (*it)->m_volume += fadingStep;
1636 (*it)->m_fadingSamples--;
1638 if ((*it)->m_fadingSamples == 0)
1640 // set variables being polled via stream interface
1641 CSingleLock lock((*it)->m_streamLock);
1642 (*it)->m_streamFading = false;
1646 // volume for stream
1647 float volume = (*it)->m_volume * (*it)->m_rgain;
1649 volume *= (*it)->m_limiter.Run((float**)out->pkt->data, out->pkt->config.channels, i*nb_floats, out->pkt->planes > 1);
1651 for(int j=0; j<out->pkt->planes; j++)
1654 CAEUtil::SSEMulArray((float*)out->pkt->data[j]+i*nb_floats, m_muted ? 0.0 : volume, nb_floats);
1656 float* fbuffer = (float*) out->pkt->data[j]+i*nb_floats;
1657 for (int k = 0; k < nb_floats; ++k)
1659 fbuffer[k] *= m_muted ? 0.0 : volume;
1667 CSampleBuffer *mix = NULL;
1668 mix = (*it)->m_resampleBuffers->m_outputSamples.front();
1669 (*it)->m_resampleBuffers->m_outputSamples.pop_front();
1671 int nb_floats = mix->pkt->nb_samples * mix->pkt->config.channels / mix->pkt->planes;
1673 float fadingStep = 0.0f;
1676 if ((*it)->m_fadingSamples == -1)
1678 (*it)->m_fadingSamples = m_internalFormat.m_sampleRate * (float)(*it)->m_fadingTime / 1000.0f;
1679 (*it)->m_volume = (*it)->m_fadingBase;
1681 if ((*it)->m_fadingSamples > 0)
1683 nb_floats = mix->pkt->config.channels / mix->pkt->planes;
1684 nb_loops = mix->pkt->nb_samples;
1685 float delta = (*it)->m_fadingTarget - (*it)->m_fadingBase;
1686 int samples = m_internalFormat.m_sampleRate * (float)(*it)->m_fadingTime / 1000.0f;
1687 fadingStep = delta / samples;
1690 // for stream amplification we need to run on a per sample basis
1691 if ((*it)->m_amplify != 1.0)
1693 nb_floats = out->pkt->config.channels / out->pkt->planes;
1694 nb_loops = out->pkt->nb_samples;
1697 for(int i=0; i<nb_loops; i++)
1699 if ((*it)->m_fadingSamples > 0)
1701 (*it)->m_volume += fadingStep;
1702 (*it)->m_fadingSamples--;
1704 if ((*it)->m_fadingSamples == 0)
1706 // set variables being polled via stream interface
1707 CSingleLock lock((*it)->m_streamLock);
1708 (*it)->m_streamFading = false;
1712 // volume for stream
1713 float volume = (*it)->m_volume * (*it)->m_rgain;
1715 volume *= (*it)->m_limiter.Run((float**)mix->pkt->data, mix->pkt->config.channels, i*nb_floats, mix->pkt->planes > 1);
1717 for(int j=0; j<out->pkt->planes && j<mix->pkt->planes; j++)
1719 float *dst = (float*)out->pkt->data[j]+i*nb_floats;
1720 float *src = (float*)mix->pkt->data[j]+i*nb_floats;
1722 CAEUtil::SSEMulAddArray(dst, src, m_muted ? 0.0 : volume, nb_floats);
1723 for (int k = 0; k < nb_floats; ++k)
1725 if (fabs(dst[k]) > 1.0f)
1732 for (int k = 0; k < nb_floats; ++k)
1734 dst[k] += src[k] * (m_muted ? 0.0 : volume);
1735 if (fabs(dst[k]) > 1.0f)
1747 // finally clamp samples
1748 if(out && needClamp)
1750 int nb_floats = out->pkt->nb_samples * out->pkt->config.channels / out->pkt->planes;
1751 for(int i=0; i<out->pkt->planes; i++)
1753 CAEUtil::ClampArray((float*)out->pkt->data[i], nb_floats);
1757 // process output buffer, gui sounds, encode, viz
1758 CSampleBuffer *viz = NULL;
1762 MixSounds(*(out->pkt));
1763 if (!m_sinkHasVolume)
1764 Deamplify(*(out->pkt));
1766 // encode and backup out buffer for viz
1768 if (m_mode == MODE_TRANSCODE && m_encoder)
1770 CSampleBuffer *buf = m_encoderBuffers->GetFreeBuffer();
1771 m_encoder->Encode(out->pkt->data[0], out->pkt->planes*out->pkt->linesize,
1772 buf->pkt->data[0], buf->pkt->planes*buf->pkt->linesize);
1773 buf->pkt->nb_samples = buf->pkt->max_nb_samples;
1782 CSingleLock lock(m_vizLock);
1783 if (m_audioCallback && m_vizBuffers && !m_streams.empty())
1785 if (!m_vizInitialized)
1787 m_audioCallback->OnInitialize(2, m_vizBuffers->m_format.m_sampleRate, 32);
1788 m_vizInitialized = true;
1791 // if viz has no free buffer, it won't return current buffer "viz"
1792 if (!m_vizBuffers->m_freeSamples.empty())
1797 m_vizBuffers->m_inputSamples.push_back(viz);
1801 CLog::Log(LOGWARNING,"ActiveAE::%s - viz ran out of free buffers", __FUNCTION__);
1802 unsigned int now = XbmcThreads::SystemClockMillis();
1803 unsigned int timestamp = now + m_stats.GetDelay() * 1000;
1804 busy |= m_vizBuffers->ResampleBuffers(timestamp);
1805 while(!m_vizBuffers->m_outputSamples.empty())
1807 CSampleBuffer *buf = m_vizBuffers->m_outputSamples.front();
1808 if ((now - buf->timestamp) & 0x80000000)
1814 while(submitted < buf->pkt->nb_samples)
1816 samples = std::min(512, buf->pkt->nb_samples-submitted);
1817 m_audioCallback->OnAudioData((float*)(buf->pkt->data[0]+2*submitted), samples);
1818 submitted += samples;
1821 m_vizBuffers->m_outputSamples.pop_front();
1825 else if (m_vizBuffers)
1826 m_vizBuffers->Flush();
1831 m_stats.AddSamples(out->pkt->nb_samples, m_streams);
1832 m_sinkBuffers->m_inputSamples.push_back(out);
1833 if(viz && (viz != out))
1840 std::list<CActiveAEStream*>::iterator it;
1841 CSampleBuffer *buffer;
1842 for (it = m_streams.begin(); it != m_streams.end(); ++it)
1844 if (!(*it)->m_resampleBuffers->m_outputSamples.empty())
1846 buffer = (*it)->m_resampleBuffers->m_outputSamples.front();
1847 (*it)->m_resampleBuffers->m_outputSamples.pop_front();
1848 m_stats.AddSamples(buffer->pkt->nb_samples, m_streams);
1849 m_sinkBuffers->m_inputSamples.push_back(buffer);
1854 // serve sink buffers
1855 busy = m_sinkBuffers->ResampleBuffers();
1856 while(!m_sinkBuffers->m_outputSamples.empty())
1858 CSampleBuffer *out = NULL;
1859 out = m_sinkBuffers->m_outputSamples.front();
1860 m_sinkBuffers->m_outputSamples.pop_front();
1861 m_sink.m_dataPort.SendOutMessage(CSinkDataProtocol::SAMPLE,
1862 &out, sizeof(CSampleBuffer*));
1870 bool CActiveAE::HasWork()
1872 if (!m_sounds_playing.empty())
1874 if (!m_sinkBuffers->m_inputSamples.empty())
1876 if (!m_sinkBuffers->m_outputSamples.empty())
1879 std::list<CActiveAEStream*>::iterator it;
1880 for (it = m_streams.begin(); it != m_streams.end(); ++it)
1882 if (!(*it)->m_resampleBuffers->m_inputSamples.empty())
1884 if (!(*it)->m_resampleBuffers->m_outputSamples.empty())
1886 if (!(*it)->m_processingSamples.empty())
1893 void CActiveAE::MixSounds(CSoundPacket &dstSample)
1895 if (m_sounds_playing.empty())
1900 float *sample_buffer;
1901 int max_samples = dstSample.nb_samples;
1903 std::list<SoundState>::iterator it;
1904 for (it = m_sounds_playing.begin(); it != m_sounds_playing.end(); )
1906 if (!it->sound->IsConverted())
1907 ResampleSound(it->sound);
1908 int available_samples = it->sound->GetSound(false)->nb_samples - it->samples_played;
1909 int mix_samples = std::min(max_samples, available_samples);
1910 int start = it->samples_played *
1911 m_dllAvUtil.av_get_bytes_per_sample(it->sound->GetSound(false)->config.fmt) *
1912 it->sound->GetSound(false)->config.channels /
1913 it->sound->GetSound(false)->planes;
1915 for(int j=0; j<dstSample.planes; j++)
1917 volume = it->sound->GetVolume();
1918 out = (float*)dstSample.data[j];
1919 sample_buffer = (float*)(it->sound->GetSound(false)->data[j]+start);
1920 int nb_floats = mix_samples * dstSample.config.channels / dstSample.planes;
1922 CAEUtil::SSEMulAddArray(out, sample_buffer, volume, nb_floats);
1924 for (int k = 0; k < nb_floats; ++k)
1925 *out++ += *sample_buffer++ * volume;
1929 it->samples_played += mix_samples;
1931 // no more frames, so remove it from the list
1932 if (it->samples_played >= it->sound->GetSound(false)->nb_samples)
1934 it = m_sounds_playing.erase(it);
1941 void CActiveAE::Deamplify(CSoundPacket &dstSample)
1946 int nb_floats = dstSample.nb_samples * dstSample.config.channels / dstSample.planes;
1948 for(int j=0; j<dstSample.planes; j++)
1950 buffer = (float*)dstSample.data[j];
1952 CAEUtil::SSEMulArray(buffer, m_muted ? 0.0 : m_volume, nb_floats);
1954 float *fbuffer = buffer;
1955 for (int i = 0; i < nb_floats; i++)
1956 *fbuffer++ *= m_volume;
1962 //-----------------------------------------------------------------------------
1964 //-----------------------------------------------------------------------------
1966 void CActiveAE::LoadSettings()
1968 m_settings.device = CSettings::Get().GetString("audiooutput.audiodevice");
1969 m_settings.passthoughdevice = CSettings::Get().GetString("audiooutput.passthroughdevice");
1971 m_settings.mode = CSettings::Get().GetInt("audiooutput.mode");
1972 m_settings.channels = CSettings::Get().GetInt("audiooutput.channels");
1974 m_settings.stereoupmix = CSettings::Get().GetBool("audiooutput.stereoupmix");
1975 m_settings.ac3passthrough = CSettings::Get().GetBool("audiooutput.ac3passthrough");
1976 m_settings.eac3passthrough = CSettings::Get().GetBool("audiooutput.eac3passthrough");
1977 m_settings.truehdpassthrough = CSettings::Get().GetBool("audiooutput.truehdpassthrough");
1978 m_settings.dtspassthrough = CSettings::Get().GetBool("audiooutput.dtspassthrough");
1979 m_settings.dtshdpassthrough = CSettings::Get().GetBool("audiooutput.dtshdpassthrough");
1980 m_settings.aacpassthrough = CSettings::Get().GetBool("audiooutput.passthroughaac");
1981 m_settings.multichannellpcm = CSettings::Get().GetBool("audiooutput.multichannellpcm");
1983 m_settings.resampleQuality = static_cast<AEQuality>(CSettings::Get().GetInt("audiooutput.processquality"));
1986 bool CActiveAE::Initialize()
1988 if (!m_dllAvUtil.Load() || !m_dllAvCodec.Load() || !m_dllAvFormat.Load())
1990 CLog::Log(LOGERROR,"CActiveAE::Initialize - failed to load ffmpeg libraries");
1993 m_dllAvFormat.av_register_all();
1997 if (m_controlPort.SendOutMessageSync(CActiveAEControlProtocol::INIT,
2001 bool success = reply->signal == CActiveAEControlProtocol::ACC ? true : false;
2005 CLog::Log(LOGERROR, "ActiveAE::%s - returned error", __FUNCTION__);
2012 CLog::Log(LOGERROR, "ActiveAE::%s - failed to init", __FUNCTION__);
2017 // hook into windowing for receiving display reset events
2018 #if defined(HAS_GLX) || defined(TARGET_DARWIN_OSX)
2019 g_Windowing.Register(this);
2022 m_inMsgEvent.Reset();
2026 void CActiveAE::EnumerateOutputDevices(AEDeviceList &devices, bool passthrough)
2028 m_sink.EnumerateOutputDevices(devices, passthrough);
2031 std::string CActiveAE::GetDefaultDevice(bool passthrough)
2033 return m_sink.GetDefaultDevice(passthrough);
2036 void CActiveAE::OnSettingsChange(const std::string& setting)
2038 if (setting == "audiooutput.passthroughdevice" ||
2039 setting == "audiooutput.audiodevice" ||
2040 setting == "audiooutput.mode" ||
2041 setting == "audiooutput.ac3passthrough" ||
2042 setting == "audiooutput.eac3passthrough" ||
2043 setting == "audiooutput.dtspassthrough" ||
2044 setting == "audiooutput.passthroughaac" ||
2045 setting == "audiooutput.truehdpassthrough" ||
2046 setting == "audiooutput.dtshdpassthrough" ||
2047 setting == "audiooutput.channels" ||
2048 setting == "audiooutput.multichannellpcm" ||
2049 setting == "audiooutput.stereoupmix" ||
2050 setting == "audiooutput.streamsilence" ||
2051 setting == "audiooutput.processquality")
2053 m_controlPort.SendOutMessage(CActiveAEControlProtocol::RECONFIGURE);
2057 bool CActiveAE::SupportsRaw()
2062 bool CActiveAE::SupportsDrain()
2067 bool CActiveAE::SupportsQualityLevel(enum AEQuality level)
2069 if (level == AE_QUALITY_LOW || level == AE_QUALITY_MID || level == AE_QUALITY_HIGH)
2075 void CActiveAE::Shutdown()
2080 bool CActiveAE::Suspend()
2082 return m_controlPort.SendOutMessage(CActiveAEControlProtocol::SUSPEND);
2085 bool CActiveAE::Resume()
2088 if (m_controlPort.SendOutMessageSync(CActiveAEControlProtocol::INIT,
2092 bool success = reply->signal == CActiveAEControlProtocol::ACC ? true : false;
2096 CLog::Log(LOGERROR, "ActiveAE::%s - returned error", __FUNCTION__);
2102 CLog::Log(LOGERROR, "ActiveAE::%s - failed to init", __FUNCTION__);
2106 m_inMsgEvent.Reset();
2110 bool CActiveAE::IsSuspended()
2112 return m_stats.IsSuspended();
2115 float CActiveAE::GetVolume()
2120 void CActiveAE::SetVolume(const float volume)
2122 m_aeVolume = std::max( 0.0f, std::min(1.0f, volume));
2123 m_controlPort.SendOutMessage(CActiveAEControlProtocol::VOLUME, &m_aeVolume, sizeof(float));
2126 void CActiveAE::SetMute(const bool enabled)
2128 m_aeMuted = enabled;
2129 m_controlPort.SendOutMessage(CActiveAEControlProtocol::MUTE, &m_aeMuted, sizeof(bool));
2132 bool CActiveAE::IsMuted()
2137 void CActiveAE::SetSoundMode(const int mode)
2139 int soundmode = mode;
2140 m_controlPort.SendOutMessage(CActiveAEControlProtocol::SOUNDMODE, &soundmode, sizeof(int));
2144 void CActiveAE::OnLostDevice()
2146 // m_controlPort.SendOutMessage(CActiveAEControlProtocol::DISPLAYLOST);
2149 void CActiveAE::OnResetDevice()
2151 // m_controlPort.SendOutMessage(CActiveAEControlProtocol::DISPLAYRESET);
2154 //-----------------------------------------------------------------------------
2156 //-----------------------------------------------------------------------------
2158 uint8_t **CActiveAE::AllocSoundSample(SampleConfig &config, int &samples, int &bytes_per_sample, int &planes, int &linesize)
2161 planes = m_dllAvUtil.av_sample_fmt_is_planar(config.fmt) ? config.channels : 1;
2162 buffer = new uint8_t*[planes];
2164 // align buffer to 16 in order to be compatible with sse in CAEConvert
2165 m_dllAvUtil.av_samples_alloc(buffer, &linesize, config.channels,
2166 samples, config.fmt, 16);
2167 bytes_per_sample = m_dllAvUtil.av_get_bytes_per_sample(config.fmt);
2171 void CActiveAE::FreeSoundSample(uint8_t **data)
2173 m_dllAvUtil.av_freep(data);
2177 bool CActiveAE::CompareFormat(AEAudioFormat &lhs, AEAudioFormat &rhs)
2179 if (lhs.m_channelLayout != rhs.m_channelLayout ||
2180 lhs.m_dataFormat != rhs.m_dataFormat ||
2181 lhs.m_sampleRate != rhs.m_sampleRate ||
2182 lhs.m_frames != rhs.m_frames)
2188 //-----------------------------------------------------------------------------
2190 //-----------------------------------------------------------------------------
2193 * load sound from an audio file and store original format
2194 * register the sound in ActiveAE
2195 * later when the engine is idle it will convert the sound to sink format
2198 #define SOUNDBUFFER_SIZE 20480
2200 IAESound *CActiveAE::MakeSound(const std::string& file)
2202 AVFormatContext *fmt_ctx = NULL;
2203 AVCodecContext *dec_ctx = NULL;
2204 AVIOContext *io_ctx;
2205 AVInputFormat *io_fmt;
2206 AVCodec *dec = NULL;
2207 CActiveAESound *sound = NULL;
2208 SampleConfig config;
2210 sound = new CActiveAESound(file);
2211 if (!sound->Prepare())
2216 int fileSize = sound->GetFileSize();
2218 fmt_ctx = m_dllAvFormat.avformat_alloc_context();
2219 unsigned char* buffer = (unsigned char*)m_dllAvUtil.av_malloc(SOUNDBUFFER_SIZE+FF_INPUT_BUFFER_PADDING_SIZE);
2220 io_ctx = m_dllAvFormat.avio_alloc_context(buffer, SOUNDBUFFER_SIZE, 0,
2221 sound, CActiveAESound::Read, NULL, CActiveAESound::Seek);
2222 io_ctx->max_packet_size = sound->GetChunkSize();
2223 if(io_ctx->max_packet_size)
2224 io_ctx->max_packet_size *= SOUNDBUFFER_SIZE / io_ctx->max_packet_size;
2226 if(!sound->IsSeekPosible())
2227 io_ctx->seekable = 0;
2229 fmt_ctx->pb = io_ctx;
2231 m_dllAvFormat.av_probe_input_buffer(io_ctx, &io_fmt, file.c_str(), NULL, 0, 0);
2234 m_dllAvFormat.avformat_close_input(&fmt_ctx);
2240 if (m_dllAvFormat.avformat_open_input(&fmt_ctx, file.c_str(), NULL, NULL) == 0)
2242 fmt_ctx->flags |= AVFMT_FLAG_NOPARSE;
2243 if (m_dllAvFormat.avformat_find_stream_info(fmt_ctx, NULL) >= 0)
2245 dec_ctx = fmt_ctx->streams[0]->codec;
2246 dec = m_dllAvCodec.avcodec_find_decoder(dec_ctx->codec_id);
2247 config.sample_rate = dec_ctx->sample_rate;
2248 config.channels = dec_ctx->channels;
2249 config.channel_layout = dec_ctx->channel_layout;
2254 m_dllAvFormat.avformat_close_input(&fmt_ctx);
2259 dec_ctx = m_dllAvCodec.avcodec_alloc_context3(dec);
2260 dec_ctx->sample_rate = config.sample_rate;
2261 dec_ctx->channels = config.channels;
2262 if (!config.channel_layout)
2263 config.channel_layout = m_dllAvUtil.av_get_default_channel_layout(config.channels);
2264 dec_ctx->channel_layout = config.channel_layout;
2267 AVFrame *decoded_frame = NULL;
2268 decoded_frame = m_dllAvCodec.avcodec_alloc_frame();
2270 if (m_dllAvCodec.avcodec_open2(dec_ctx, dec, NULL) >= 0)
2275 m_dllAvCodec.av_init_packet(&avpkt);
2277 while (m_dllAvFormat.av_read_frame(fmt_ctx, &avpkt) >= 0)
2280 len = m_dllAvCodec.avcodec_decode_audio4(dec_ctx, decoded_frame, &got_frame, &avpkt);
2283 m_dllAvCodec.avcodec_close(dec_ctx);
2284 m_dllAvUtil.av_free(dec_ctx);
2285 m_dllAvUtil.av_free(&decoded_frame);
2286 m_dllAvFormat.avformat_close_input(&fmt_ctx);
2294 int samples = fileSize / m_dllAvUtil.av_get_bytes_per_sample(dec_ctx->sample_fmt) / config.channels;
2295 config.fmt = dec_ctx->sample_fmt;
2296 config.bits_per_sample = dec_ctx->bits_per_coded_sample;
2297 sound->InitSound(true, config, samples);
2300 sound->StoreSound(true, decoded_frame->extended_data,
2301 decoded_frame->nb_samples, decoded_frame->linesize[0]);
2304 m_dllAvCodec.avcodec_close(dec_ctx);
2307 m_dllAvUtil.av_free(dec_ctx);
2308 m_dllAvUtil.av_free(decoded_frame);
2309 m_dllAvFormat.avformat_close_input(&fmt_ctx);
2314 m_dataPort.SendOutMessage(CActiveAEDataProtocol::NEWSOUND, &sound, sizeof(CActiveAESound*));
2319 void CActiveAE::FreeSound(IAESound *sound)
2321 m_dataPort.SendOutMessage(CActiveAEDataProtocol::FREESOUND, &sound, sizeof(CActiveAESound*));
2324 void CActiveAE::PlaySound(CActiveAESound *sound)
2326 m_dataPort.SendOutMessage(CActiveAEDataProtocol::PLAYSOUND, &sound, sizeof(CActiveAESound*));
2329 void CActiveAE::StopSound(CActiveAESound *sound)
2331 m_controlPort.SendOutMessage(CActiveAEControlProtocol::STOPSOUND, &sound, sizeof(CActiveAESound*));
2335 * resample sounds to destination format for mixing
2336 * destination format is either format of stream or
2337 * default sink format when no stream is playing
2339 void CActiveAE::ResampleSounds()
2341 std::vector<CActiveAESound*>::iterator it;
2342 for (it = m_sounds.begin(); it != m_sounds.end(); ++it)
2344 if (!(*it)->IsConverted())
2347 // only do one sound, then yield to main loop
2353 bool CActiveAE::ResampleSound(CActiveAESound *sound)
2355 SampleConfig orig_config, dst_config;
2356 uint8_t **dst_buffer;
2359 if (m_mode == MODE_RAW || m_internalFormat.m_dataFormat == AE_FMT_INVALID)
2362 if (!sound->GetSound(true))
2365 orig_config = sound->GetSound(true)->config;
2367 dst_config.channel_layout = CActiveAEResample::GetAVChannelLayout(m_internalFormat.m_channelLayout);
2368 dst_config.channels = m_internalFormat.m_channelLayout.Count();
2369 dst_config.sample_rate = m_internalFormat.m_sampleRate;
2370 dst_config.fmt = CActiveAEResample::GetAVSampleFormat(m_internalFormat.m_dataFormat);
2371 dst_config.bits_per_sample = CAEUtil::DataFormatToUsedBits(m_internalFormat.m_dataFormat);
2373 CActiveAEResample *resampler = new CActiveAEResample();
2374 resampler->Init(dst_config.channel_layout,
2375 dst_config.channels,
2376 dst_config.sample_rate,
2378 dst_config.bits_per_sample,
2379 orig_config.channel_layout,
2380 orig_config.channels,
2381 orig_config.sample_rate,
2383 orig_config.bits_per_sample,
2388 dst_samples = resampler->CalcDstSampleCount(sound->GetSound(true)->nb_samples,
2389 m_internalFormat.m_sampleRate,
2390 orig_config.sample_rate);
2392 dst_buffer = sound->InitSound(false, dst_config, dst_samples);
2398 int samples = resampler->Resample(dst_buffer, dst_samples,
2399 sound->GetSound(true)->data,
2400 sound->GetSound(true)->nb_samples,
2403 sound->GetSound(false)->nb_samples = samples;
2406 sound->SetConverted(true);
2410 //-----------------------------------------------------------------------------
2412 //-----------------------------------------------------------------------------
2414 IAEStream *CActiveAE::MakeStream(enum AEDataFormat dataFormat, unsigned int sampleRate, unsigned int encodedSampleRate, CAEChannelInfo channelLayout, unsigned int options)
2416 //TODO: pass number of samples in audio packet
2418 AEAudioFormat format;
2419 format.m_dataFormat = dataFormat;
2420 format.m_sampleRate = sampleRate;
2421 format.m_encodedRate = encodedSampleRate;
2422 format.m_channelLayout = channelLayout;
2423 format.m_frames = format.m_sampleRate / 10;
2424 format.m_frameSize = format.m_channelLayout.Count() *
2425 (CAEUtil::DataFormatToBits(format.m_dataFormat) >> 3);
2428 msg.format = format;
2429 msg.options = options;
2432 if (m_dataPort.SendOutMessageSync(CActiveAEDataProtocol::NEWSTREAM,
2434 &msg, sizeof(MsgStreamNew)))
2436 bool success = reply->signal == CActiveAEControlProtocol::ACC ? true : false;
2439 CActiveAEStream *stream = *(CActiveAEStream**)reply->data;
2446 CLog::Log(LOGERROR, "ActiveAE::%s - could not create stream", __FUNCTION__);
2450 IAEStream *CActiveAE::FreeStream(IAEStream *stream)
2452 m_dataPort.SendOutMessage(CActiveAEDataProtocol::FREESTREAM, &stream, sizeof(IAEStream*));
2456 void CActiveAE::FlushStream(CActiveAEStream *stream)
2459 if (m_controlPort.SendOutMessageSync(CActiveAEControlProtocol::FLUSHSTREAM,
2461 &stream, sizeof(CActiveAEStream*)))
2463 bool success = reply->signal == CActiveAEControlProtocol::ACC ? true : false;
2467 CLog::Log(LOGERROR, "CActiveAE::FlushStream - failed");
2472 void CActiveAE::PauseStream(CActiveAEStream *stream, bool pause)
2474 // TODO pause sink, needs api change
2476 m_controlPort.SendOutMessage(CActiveAEControlProtocol::PAUSESTREAM,
2477 &stream, sizeof(CActiveAEStream*));
2479 m_controlPort.SendOutMessage(CActiveAEControlProtocol::RESUMESTREAM,
2480 &stream, sizeof(CActiveAEStream*));
2483 void CActiveAE::SetStreamAmplification(CActiveAEStream *stream, float amplify)
2485 MsgStreamParameter msg;
2486 msg.stream = stream;
2487 msg.parameter.float_par = amplify;
2488 m_controlPort.SendOutMessage(CActiveAEControlProtocol::STREAMAMP,
2489 &msg, sizeof(MsgStreamParameter));
2492 void CActiveAE::SetStreamReplaygain(CActiveAEStream *stream, float rgain)
2494 MsgStreamParameter msg;
2495 msg.stream = stream;
2496 msg.parameter.float_par = rgain;
2497 m_controlPort.SendOutMessage(CActiveAEControlProtocol::STREAMRGAIN,
2498 &msg, sizeof(MsgStreamParameter));
2501 void CActiveAE::SetStreamVolume(CActiveAEStream *stream, float volume)
2503 MsgStreamParameter msg;
2504 msg.stream = stream;
2505 msg.parameter.float_par = volume;
2506 m_controlPort.SendOutMessage(CActiveAEControlProtocol::STREAMVOLUME,
2507 &msg, sizeof(MsgStreamParameter));
2510 void CActiveAE::SetStreamResampleRatio(CActiveAEStream *stream, double ratio)
2512 MsgStreamParameter msg;
2513 msg.stream = stream;
2514 msg.parameter.double_par = ratio;
2515 m_controlPort.SendOutMessage(CActiveAEControlProtocol::STREAMRESAMPLERATIO,
2516 &msg, sizeof(MsgStreamParameter));
2519 void CActiveAE::SetStreamFade(CActiveAEStream *stream, float from, float target, unsigned int millis)
2522 msg.stream = stream;
2524 msg.target = target;
2525 msg.millis = millis;
2526 m_controlPort.SendOutMessage(CActiveAEControlProtocol::STREAMFADE,
2527 &msg, sizeof(MsgStreamFade));
2530 void CActiveAE::RegisterAudioCallback(IAudioCallback* pCallback)
2532 CSingleLock lock(m_vizLock);
2533 m_audioCallback = pCallback;
2534 m_vizInitialized = false;
2537 void CActiveAE::UnregisterAudioCallback()
2539 CSingleLock lock(m_vizLock);
2540 m_audioCallback = NULL;