kodi
ActiveAE.h
1 /*
2  * Copyright (C) 2010-2018 Team Kodi
3  * This file is part of Kodi - https://kodi.tv
4  *
5  * SPDX-License-Identifier: GPL-2.0-or-later
6  * See LICENSES/README.md for more information.
7  */
8 
9 #pragma once
10 
11 #include "ActiveAESink.h"
12 #include "cores/AudioEngine/Engines/ActiveAE/ActiveAEBuffer.h"
13 #include "cores/AudioEngine/Interfaces/AESound.h"
14 #include "cores/AudioEngine/Interfaces/AEStream.h"
15 #include "guilib/DispResource.h"
16 #include "threads/SystemClock.h"
17 #include "threads/Thread.h"
18 
19 #include <list>
20 #include <memory>
21 #include <queue>
22 #include <string>
23 #include <utility>
24 #include <vector>
25 
26 // ffmpeg
27 extern "C" {
28 #include <libavformat/avformat.h>
29 #include <libavcodec/avcodec.h>
30 #include <libavutil/avutil.h>
31 }
32 
33 class IAESink;
34 class IAEEncoder;
35 
36 namespace ActiveAE
37 {
38 
39 class CActiveAESound;
40 class CActiveAEStream;
41 class CActiveAESettings;
42 
44 {
45  std::string device;
46  std::string driver;
47  std::string passthroughdevice;
48  int channels;
49  bool ac3passthrough;
50  bool ac3transcode;
51  bool eac3passthrough;
52  bool dtspassthrough;
53  bool truehdpassthrough;
54  bool dtshdpassthrough;
55  bool usesdtscorefallback;
56  bool stereoupmix;
57  bool normalizelevels;
58  bool passthrough;
59  int config;
60  int guisoundmode;
61  unsigned int samplerate;
62  AEQuality resampleQuality;
63  double atempoThreshold;
64  bool streamNoise;
65  int silenceTimeoutMinutes;
66 };
67 
69 {
70 public:
71  CActiveAEControlProtocol(std::string name, CEvent* inEvent, CEvent* outEvent)
72  : Protocol(std::move(name), inEvent, outEvent)
73  {
74  }
75  enum OutSignal
76  {
77  INIT = 0,
78  RECONFIGURE,
79  SUSPEND,
80  DEVICECHANGE,
81  DEVICECOUNTCHANGE,
82  MUTE,
83  VOLUME,
84  PAUSESTREAM,
85  RESUMESTREAM,
86  FLUSHSTREAM,
87  STREAMRGAIN,
88  STREAMVOLUME,
89  STREAMAMP,
90  STREAMRESAMPLERATIO,
91  STREAMRESAMPLEMODE,
92  STREAMFADE,
93  STREAMFFMPEGINFO,
94  STOPSOUND,
95  GETSTATE,
96  DISPLAYLOST,
97  DISPLAYRESET,
98  APPFOCUSED,
99  KEEPCONFIG,
100  TIMEOUT,
101  };
102  enum InSignal
103  {
104  ACC,
105  ERR,
106  STATS,
107  };
108 };
109 
111 {
112 public:
113  CActiveAEDataProtocol(std::string name, CEvent* inEvent, CEvent* outEvent)
114  : Protocol(std::move(name), inEvent, outEvent)
115  {
116  }
117  enum OutSignal
118  {
119  NEWSOUND = 0,
120  PLAYSOUND,
121  FREESOUND,
122  NEWSTREAM,
123  FREESTREAM,
124  STREAMSAMPLE,
125  DRAINSTREAM,
126  };
127  enum InSignal
128  {
129  ACC,
130  ERR,
131  STREAMBUFFER,
132  STREAMDRAINED,
133  };
134 };
135 
137 {
138  AEAudioFormat format;
139  unsigned int options;
140  IAEClockCallback *clock;
141 };
142 
144 {
145  CActiveAEStream *stream;
146  bool finish; // if true switch back to gui sound mode
147 };
148 
150 {
151  CSampleBuffer *buffer;
152  CActiveAEStream *stream;
153 };
154 
156 {
157  CActiveAEStream *stream;
158  union
159  {
160  float float_par;
161  double double_par;
162  int int_par;
163  } parameter;
164 };
165 
167 {
168  CActiveAEStream *stream;
169  float from;
170  float target;
171  unsigned int millis;
172 };
173 
175 {
176  CActiveAEStream *stream;
177  int profile;
178  enum AVMatrixEncoding matrix_encoding;
179  enum AVAudioServiceType audio_service_type;
180 };
181 
183 {
184 public:
185  void Reset(unsigned int sampleRate, bool pcm);
186  void UpdateSinkDelay(const AEDelayStatus& status, int samples);
187  void AddSamples(int samples, const std::list<CActiveAEStream*>& streams);
188  void GetDelay(AEDelayStatus& status);
189  void AddStream(unsigned int streamid);
190  void RemoveStream(unsigned int streamid);
191  void UpdateStream(CActiveAEStream *stream);
192  void GetDelay(AEDelayStatus& status, CActiveAEStream *stream);
193  void GetSyncInfo(CAESyncInfo& info, CActiveAEStream *stream);
194  float GetCacheTime(CActiveAEStream *stream);
195  float GetCacheTotal();
196  float GetMaxDelay() const;
197  float GetWaterLevel();
198  void SetSuspended(bool state);
199  void SetCurrentSinkFormat(const AEAudioFormat& SinkFormat);
200  void SetSinkCacheTotal(float time) { m_sinkCacheTotal = time; }
201  void SetSinkLatency(float time) { m_sinkLatency = time; }
202  void SetSinkNeedIec(bool needIEC) { m_sinkNeedIecPack = needIEC; }
203  bool IsSuspended();
204  AEAudioFormat GetCurrentSinkFormat();
205 protected:
206  float m_sinkCacheTotal;
207  float m_sinkLatency;
208  int m_bufferedSamples;
209  unsigned int m_sinkSampleRate;
210  AEDelayStatus m_sinkDelay;
211  bool m_suspended;
212  AEAudioFormat m_sinkFormat;
213  bool m_pcmOutput;
214  bool m_sinkNeedIecPack{false};
215  CCriticalSection m_lock;
216  struct StreamStats
217  {
218  unsigned int m_streamId;
219  double m_bufferedTime;
220  double m_resampleRatio;
221  double m_syncError;
222  unsigned int m_errorTime;
223  CAESyncInfo::AESyncState m_syncState;
224  };
225  std::vector<StreamStats> m_streamStats;
226 };
227 
228 class CActiveAE : public IAE, public IDispResource, private CThread
229 {
230 protected:
231  friend class CActiveAESound;
232  friend class CActiveAEStream;
233  friend class CSoundPacket;
234  friend class CActiveAEBufferPoolResample;
235 
236 public:
237  CActiveAE();
238  ~CActiveAE() override;
239  void Start() override;
240  void Shutdown() override;
241  bool Suspend() override;
242  bool Resume() override;
243  bool IsSuspended() override;
244  void OnSettingsChange();
245 
246  float GetVolume() override;
247  void SetVolume(const float volume) override;
248  void SetMute(const bool enabled) override;
249  bool IsMuted() override;
250 
251  /* returns a new stream for data in the specified format */
252  IAE::StreamPtr MakeStream(AEAudioFormat& audioFormat,
253  unsigned int options = 0,
254  IAEClockCallback* clock = NULL) override;
255 
256  /* returns a new sound object */
257  IAE::SoundPtr MakeSound(const std::string& file) override;
258 
259  void EnumerateOutputDevices(AEDeviceList &devices, bool passthrough) override;
260  bool SupportsRaw(AEAudioFormat &format) override;
261  bool SupportsSilenceTimeout() override;
262  bool UsesDtsCoreFallback() override;
263  bool HasStereoAudioChannelCount() override;
264  bool HasHDAudioChannelCount() override;
265  bool SupportsQualityLevel(enum AEQuality level) override;
266  bool IsSettingVisible(const std::string &settingId) override;
267  void KeepConfiguration(unsigned int millis) override;
268  void DeviceChange() override;
269  void DeviceCountChange(const std::string& driver) override;
270  bool GetCurrentSinkFormat(AEAudioFormat &SinkFormat) override;
271 
272  void RegisterAudioCallback(IAudioCallback* pCallback) override;
273  void UnregisterAudioCallback(IAudioCallback* pCallback) override;
274 
275  void OnLostDisplay() override;
276  void OnResetDisplay() override;
277  void OnAppFocusChange(bool focus) override;
278 
279 private:
280  bool FreeStream(IAEStream* stream, bool finish) override;
281  void FreeSound(IAESound* sound) override;
282 
283 protected:
284  void PlaySound(CActiveAESound *sound);
285  static uint8_t **AllocSoundSample(SampleConfig &config, int &samples, int &bytes_per_sample, int &planes, int &linesize);
286  static void FreeSoundSample(uint8_t **data);
287  void GetDelay(AEDelayStatus& status, CActiveAEStream *stream) { m_stats.GetDelay(status, stream); }
288  void GetSyncInfo(CAESyncInfo& info, CActiveAEStream *stream) { m_stats.GetSyncInfo(info, stream); }
289  float GetCacheTime(CActiveAEStream *stream) { return m_stats.GetCacheTime(stream); }
290  float GetCacheTotal() { return m_stats.GetCacheTotal(); }
291  float GetMaxDelay() { return m_stats.GetMaxDelay(); }
292  void FlushStream(CActiveAEStream *stream);
293  void PauseStream(CActiveAEStream *stream, bool pause);
294  void StopSound(CActiveAESound *sound);
295  void SetStreamAmplification(CActiveAEStream *stream, float amplify);
296  void SetStreamReplaygain(CActiveAEStream *stream, float rgain);
297  void SetStreamVolume(CActiveAEStream *stream, float volume);
298  void SetStreamResampleRatio(CActiveAEStream *stream, double ratio);
299  void SetStreamResampleMode(CActiveAEStream *stream, int mode);
300  void SetStreamFFmpegInfo(CActiveAEStream *stream, int profile, enum AVMatrixEncoding matrix_encoding, enum AVAudioServiceType audio_service_type);
301  void SetStreamFade(CActiveAEStream *stream, float from, float target, unsigned int millis);
302 
303 protected:
304  void Process() override;
305  void StateMachine(int signal, Protocol *port, Message *msg);
306  bool InitSink();
307  void DrainSink();
308  void UnconfigureSink();
309  void Dispose();
310  void LoadSettings();
311  void ValidateOutputDevices(bool saveChanges);
312  bool NeedReconfigureBuffers();
313  bool NeedReconfigureSink();
314  void ApplySettingsToFormat(AEAudioFormat& format,
315  const AudioSettings& settings,
316  int* mode = NULL);
317  void Configure(AEAudioFormat *desiredFmt = NULL);
318  AEAudioFormat GetInputFormat(AEAudioFormat *desiredFmt = NULL);
319  CActiveAEStream* CreateStream(MsgStreamNew *streamMsg);
320  void DiscardStream(CActiveAEStream *stream);
321  void SFlushStream(CActiveAEStream *stream);
322  void FlushEngine();
323  void ClearDiscardedBuffers();
324  void SStopSound(CActiveAESound *sound);
325  void DiscardSound(CActiveAESound *sound);
326  void ChangeResamplers();
327 
328  bool RunStages();
329  bool HasWork();
330  CSampleBuffer* SyncStream(CActiveAEStream *stream);
331 
332  void ResampleSounds();
333  bool ResampleSound(CActiveAESound *sound);
334  void MixSounds(CSoundPacket &dstSample);
335  void Deamplify(CSoundPacket &dstSample);
336 
337  bool CompareFormat(const AEAudioFormat& lhs, const AEAudioFormat& rhs);
338 
339  CEvent m_inMsgEvent;
340  CEvent m_outMsgEvent;
341  CActiveAEControlProtocol m_controlPort;
342  CActiveAEDataProtocol m_dataPort;
343  int m_state;
344  bool m_bStateMachineSelfTrigger;
345  std::chrono::milliseconds m_extTimeout;
346  bool m_extError;
347  bool m_extDrain;
348  XbmcThreads::EndTime<> m_extDrainTimer;
349  std::chrono::milliseconds m_extKeepConfig;
350  bool m_extDeferData;
351  std::queue<time_t> m_extLastDeviceChange;
352  bool m_extSuspended = false;
353  bool m_isWinSysReg = false;
354 
355  enum
356  {
357  MODE_RAW,
358  MODE_TRANSCODE,
359  MODE_PCM
360  }m_mode;
361 
362  CActiveAESink m_sink;
363  AEAudioFormat m_sinkFormat;
364  AEAudioFormat m_sinkRequestFormat;
365  AEAudioFormat m_encoderFormat;
366  AEAudioFormat m_internalFormat;
367  AEAudioFormat m_inputFormat;
368  AudioSettings m_settings;
369  CEngineStats m_stats;
370  IAEEncoder *m_encoder;
371  std::string m_currDevice;
372  std::unique_ptr<CActiveAESettings> m_settingsHandler;
373 
374  // buffers
375  std::unique_ptr<CActiveAEBufferPoolResample> m_sinkBuffers;
376  std::unique_ptr<CActiveAEBufferPoolResample> m_vizBuffers;
377  std::unique_ptr<CActiveAEBufferPool> m_vizBuffersInput;
378  std::unique_ptr<CActiveAEBufferPool>
379  m_silenceBuffers; // needed to drive gui sounds if we have no streams
380  std::unique_ptr<CActiveAEBufferPool> m_encoderBuffers;
381 
382  // streams
383  std::list<CActiveAEStream*> m_streams;
384  std::list<std::unique_ptr<CActiveAEBufferPool>> m_discardBufferPools;
385  unsigned int m_streamIdGen;
386 
387  // gui sounds
388  struct SoundState
389  {
390  CActiveAESound *sound;
391  int samples_played;
392  };
393  std::list<SoundState> m_sounds_playing;
394  std::vector<CActiveAESound*> m_sounds;
395 
396  float m_volume; // volume on a 0..1 scale corresponding to a proportion along the dB scale
397  float m_volumeScaled; // multiplier to scale samples in order to achieve the volume specified in m_volume
398  bool m_muted;
399  bool m_sinkHasVolume;
400 
401  // viz
402  std::vector<IAudioCallback*> m_audioCallback;
403  bool m_vizInitialized;
404  CCriticalSection m_vizLock;
405 
406  // polled via the interface
407  float m_aeVolume;
408  bool m_aeMuted;
409  bool m_aeGUISoundForce;
410 };
411 };
This is an Event class built from a ConditionVariable.
Definition: Event.h:35
Definition: deflate.c:123
Definition: Thread.h:44
the variables here follow ffmpeg naming
Definition: ActiveAEBuffer.h:28
IAEEncoder interface for on the fly audio compression.
Definition: AEEncoder.h:20
Definition: ActiveAEStream.h:130
Callback interface for VideoPlayer clock needed by AE for sync.
Definition: AEStream.h:23
Definition: ActorProtocol.h:73
Definition: ActiveAESink.h:92
Definition: ActiveAEBuffer.h:75
Definition: SystemClock.h:31
Definition: AESink.h:18
Definition: IAudioCallback.h:15
IAEStream Stream Interface for streaming audio.
Definition: AEStream.h:52
Definition: ActiveAE.h:166
Definition: Application.h:67
Definition: AESound.h:15
Definition: ActorProtocol.h:45
Definition: DispResource.h:14
Definition: AE.h:68
The audio format structure that fully defines a stream&#39;s audio information.
Definition: AEAudioFormat.h:19
Definition: AEUtil.h:27
Definition: ActiveAE.h:136
Definition: settings.py:1
Definition: ActiveAE.h:388
Definition: ActiveAE.h:182
Definition: ActiveAESound.h:26
Definition: ActiveAE.h:68
Definition: ActiveAE.h:149
IAE Interface.
Definition: AE.h:81
Definition: ActiveAEBuffer.h:45
Definition: ActiveAE.h:143
Definition: ActiveAE.h:228
Definition: ActiveAE.h:43
Definition: AEStream.h:31
Definition: ActiveAE.h:216
Definition: ActiveAE.h:155
Definition: ActiveAE.h:110
Definition: ActiveAE.h:174