xbmc
AESinkXAudio.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 "cores/AudioEngine/Interfaces/AESink.h"
12 #include "cores/AudioEngine/Utils/AEDeviceInfo.h"
13 
14 #include <stdint.h>
15 
16 #include <mmdeviceapi.h>
17 #include <ppltasks.h>
18 #include <wrl/implements.h>
19 #include <x3daudio.h>
20 #include <xapofx.h>
21 #include <xaudio2.h>
22 #include <xaudio2fx.h>
23 #pragma comment(lib,"xaudio2.lib")
24 
25 class CAESinkXAudio : public IAESink
26 {
27 public:
28  virtual const char *GetName() { return "XAudio"; }
29 
30  CAESinkXAudio();
31  virtual ~CAESinkXAudio();
32 
33  static void Register();
34  static IAESink* Create(std::string &device, AEAudioFormat &desiredFormat);
35 
36  bool Initialize (AEAudioFormat &format, std::string &device) override;
37  void Deinitialize() override;
38 
39  void GetDelay(AEDelayStatus& status) override;
40  double GetCacheTotal() override;
41  double GetLatency() override;
42  unsigned int AddPackets(uint8_t **data, unsigned int frames, unsigned int offset) override;
43  void Drain() override;
44 
45  static void EnumerateDevicesEx(AEDeviceInfoList &deviceInfoList, bool force = false);
46 
47 private:
48  struct buffer_ctx
49  {
50  uint8_t *data;
51  uint32_t frames;
52  CAESinkXAudio* sink;
53 
54  ~buffer_ctx()
55  {
56  delete[] data;
57  sink->m_framesInBuffers -= frames;
58  sink = nullptr;
59  }
60  };
61 
62  struct VoiceCallback : public IXAudio2VoiceCallback
63  {
64  VoiceCallback()
65  {
66  mBufferEnd.reset(CreateEventEx(nullptr, nullptr, 0, EVENT_MODIFY_STATE | SYNCHRONIZE));
67  if (!mBufferEnd)
68  {
69  throw std::exception("CreateEvent");
70  }
71  }
72  virtual ~VoiceCallback() { }
73 
74  STDMETHOD_(void, OnVoiceProcessingPassStart) (UINT32) override {}
75  STDMETHOD_(void, OnVoiceProcessingPassEnd)() override {}
76  STDMETHOD_(void, OnStreamEnd)() override {}
77  STDMETHOD_(void, OnBufferStart)(void*) override {}
78  STDMETHOD_(void, OnBufferEnd)(void* context) override
79  {
80  SetEvent(mBufferEnd.get());
81  struct buffer_ctx *ctx = static_cast<struct buffer_ctx*>(context);
82  delete ctx;
83  }
84 
85  STDMETHOD_(void, OnLoopEnd)(void*) override {}
86  STDMETHOD_(void, OnVoiceError)(void*, HRESULT) override {}
87 
88  struct handle_closer
89  {
90  void operator()(HANDLE h) const
91  {
92  assert(h != INVALID_HANDLE_VALUE);
93  if (h)
94  CloseHandle(h);
95  }
96  };
97  std::unique_ptr<void, handle_closer> mBufferEnd;
98  };
99 
100  bool InitializeInternal(std::string deviceId, AEAudioFormat &format);
101  bool IsUSBDevice();
102 
103  Microsoft::WRL::ComPtr<IXAudio2> m_xAudio2;
104  IXAudio2MasteringVoice* m_masterVoice;
105  IXAudio2SourceVoice* m_sourceVoice;
106  VoiceCallback m_voiceCallback;
107 
108  AEAudioFormat m_format;
109  unsigned int m_encodedChannels;
110  unsigned int m_encodedSampleRate;
111  CAEChannelInfo m_channelLayout;
112  std::string m_device;
113 
114  enum AEDataFormat sinkReqFormat;
115  enum AEDataFormat sinkRetFormat;
116 
117  unsigned int m_uiBufferLen; /* xaudio endpoint buffer size, in frames */
118  unsigned int m_AvgBytesPerSec;
119  unsigned int m_dwChunkSize;
120  unsigned int m_dwFrameSize;
121  unsigned int m_dwBufferLen;
122  uint64_t m_sinkFrames;
123  std::atomic<uint16_t> m_framesInBuffers;
124 
125  double m_avgTimeWaiting; /* time between next buffer of data from SoftAE and driver call for data */
126 
127  bool m_running;
128  bool m_initialized;
129  bool m_isSuspended; /* sink is in a suspended state - release audio device */
130  bool m_isDirty; /* sink output failed - needs re-init or new device */
131 };
Definition: XHandle.h:21
unsigned int AddPackets(uint8_t **data, unsigned int frames, unsigned int offset) override
Adds packets to be sent out, this routine MUST block or sleep.
Definition: AESinkXAudio.cpp:230
Definition: AESink.h:18
CAESinkXAudio()
--------------— CAESinkXAudio ---------------------—
Definition: AESinkXAudio.cpp:57
The audio format structure that fully defines a stream&#39;s audio information.
Definition: AEAudioFormat.h:19
Definition: EffectAPI.cpp:20
Definition: AEUtil.h:27
Definition: AEChannelInfo.h:19
Definition: AESinkXAudio.h:25
void GetDelay(AEDelayStatus &status) override
Return a timestamped status structure with delay and sink info.
Definition: AESinkXAudio.cpp:191