1 #include "FakeAudioDeviceModule.h"
2 
3 #include "modules/audio_device/include/audio_device_default.h"
4 #include "rtc_base/ref_counted_object.h"
5 #include "rtc_base/platform_thread.h"
6 #include "rtc_base/time_utils.h"
7 
8 #include <thread>
9 #include <mutex>
10 #include <condition_variable>
11 
12 namespace tgcalls {
13 class FakeAudioDeviceModuleImpl : public webrtc::webrtc_impl::AudioDeviceModuleDefault<webrtc::AudioDeviceModule> {
14  public:
Create(webrtc::TaskQueueFactory * taskQueueFactory,std::shared_ptr<FakeAudioDeviceModule::Renderer> renderer,std::shared_ptr<FakeAudioDeviceModule::Recorder> recorder,FakeAudioDeviceModule::Options options)15   static rtc::scoped_refptr<webrtc::AudioDeviceModule> Create(webrtc::TaskQueueFactory* taskQueueFactory,
16                                                               std::shared_ptr<FakeAudioDeviceModule::Renderer> renderer,
17                                                               std::shared_ptr<FakeAudioDeviceModule::Recorder> recorder,
18                                                               FakeAudioDeviceModule::Options options) {
19     return rtc::scoped_refptr<webrtc::AudioDeviceModule>(
20         new rtc::RefCountedObject<FakeAudioDeviceModuleImpl>(taskQueueFactory, options, std::move(renderer), std::move(recorder)));
21   }
22 
FakeAudioDeviceModuleImpl(webrtc::TaskQueueFactory *,FakeAudioDeviceModule::Options options,std::shared_ptr<FakeAudioDeviceModule::Renderer> renderer,std::shared_ptr<FakeAudioDeviceModule::Recorder> recorder)23   FakeAudioDeviceModuleImpl(webrtc::TaskQueueFactory*, FakeAudioDeviceModule::Options options,
24                             std::shared_ptr<FakeAudioDeviceModule::Renderer> renderer,
25                             std::shared_ptr<FakeAudioDeviceModule::Recorder> recorder)
26       : num_channels_{options.num_channels}, samples_per_sec_{options.samples_per_sec}, scheduler_(options.scheduler_),
27         renderer_(std::move(renderer)), recorder_(std::move(recorder)) {
28     if (!scheduler_) {
__anon7545dce60102(auto f) 29       scheduler_ = [](auto f)  {
30         std::thread([f = std::move(f)]() {
31           while (true)  {
32             double wait = f();
33             if (wait < 0) {
34               return;
35             }
36             std::this_thread::sleep_for(std::chrono::microseconds (static_cast<int64_t>(wait * 1000000)));
37           }
38         }).detach();
39       };
40     }
41     RTC_CHECK(num_channels_ == 1 || num_channels_ == 2);
__anon7545dce60302(size_t sr) 42     auto good_sample_rate = [](size_t sr) {
43       return sr == 8000 || sr == 16000 || sr == 32000 || sr == 44100 || sr == 48000;
44     };
45     RTC_CHECK(good_sample_rate(samples_per_sec_));
46     samples_per_frame_ = samples_per_sec_ / 100;
47     playout_buffer_.resize(samples_per_frame_ * 2 /* 2 in case stereo will be turned on later */, 0);
48   }
49 
~FakeAudioDeviceModuleImpl()50   ~FakeAudioDeviceModuleImpl() override {
51     StopPlayout();
52   }
53 
PlayoutIsAvailable(bool * available)54   int32_t PlayoutIsAvailable(bool* available) override {
55     if (available) {
56       *available = true;
57     }
58     return 0;
59   }
60 
StereoPlayoutIsAvailable(bool * available) const61   int32_t StereoPlayoutIsAvailable(bool* available) const override {
62     if (available) {
63       *available = true;
64     }
65     return 0;
66   }
StereoPlayout(bool * enabled) const67   int32_t StereoPlayout(bool* enabled) const override {
68     if (enabled) {
69       *enabled = num_channels_ == 2;
70     }
71     return 0;
72   }
SetStereoPlayout(bool enable)73   int32_t SetStereoPlayout(bool enable) override {
74     size_t new_num_channels = enable ? 2 : 1;
75     if (new_num_channels != num_channels_) {
76       return -1;
77     }
78     return 0;
79   }
80 
Init()81   int32_t Init() override {
82     return 0;
83   }
84 
RegisterAudioCallback(webrtc::AudioTransport * callback)85   int32_t RegisterAudioCallback(webrtc::AudioTransport* callback) override {
86     std::unique_lock<std::mutex> lock(render_mutex_);
87     audio_callback_ = callback;
88     return 0;
89   }
90 
StartPlayout()91   int32_t StartPlayout() override {
92     std::unique_lock<std::mutex> lock(render_mutex_);
93     if (!renderer_) {
94       return 0;
95     }
96     if (rendering_) {
97       return 0;
98     }
99     need_rendering_ = true;
100     rendering_ = true;
101     scheduler_([this]{
102       return Render() / 1000000.0;
103     });
104     return 0;
105   }
106 
StopPlayout()107   int32_t StopPlayout() override {
108     if (!rendering_) {
109       return 0;
110     }
111 
112     need_rendering_ = false;
113     std::unique_lock<std::mutex> lock(render_mutex_);
114     render_cond_.wait(lock, [this]{ return !rendering_; });
115 
116     return 0;
117   }
118 
Playing() const119   bool Playing() const override {
120     return rendering_;
121   }
122 
StartRecording()123   int32_t StartRecording() override {
124     std::unique_lock<std::mutex> lock(record_mutex_);
125     if (!recorder_) {
126       return 0;
127     }
128     if (recording_) {
129       return 0;
130     }
131     need_recording_ = true;
132     recording_ = true;
133     scheduler_([this]{
134       return Record() / 1000000.0;
135     });
136     return 0;
137   }
StopRecording()138  int32_t StopRecording() override {
139    if (!recording_) {
140      return 0;
141    }
142 
143    need_recording_ = false;
144    std::unique_lock<std::mutex> lock(record_mutex_);
145    record_cond_.wait(lock, [this]{ return !recording_; });
146 
147    return 0;
148  }
Recording() const149   bool Recording() const override {
150     return recording_;
151   }
152 
153 private:
154 
Render()155   int32_t Render() {
156     std::unique_lock<std::mutex> lock(render_mutex_);
157     if (!need_rendering_) {
158       rendering_ = false;
159       render_cond_.notify_all();
160       return -1;
161     }
162 
163     size_t samples_out = 0;
164     int64_t elapsed_time_ms = -1;
165     int64_t ntp_time_ms = -1;
166     size_t bytes_per_sample = 2 * num_channels_;
167 
168     RTC_CHECK(audio_callback_);
169     if (renderer_) {
170       renderer_->BeginFrame(0);
171     }
172     audio_callback_->NeedMorePlayData(samples_per_frame_, bytes_per_sample, num_channels_, samples_per_sec_,
173                                       playout_buffer_.data(), samples_out, &elapsed_time_ms, &ntp_time_ms);
174     if (renderer_) {
175       renderer_->EndFrame();
176     }
177     if (samples_out != 0 && renderer_) {
178       AudioFrame frame;
179       frame.audio_samples = playout_buffer_.data();
180       frame.num_samples = samples_out;
181       frame.bytes_per_sample = bytes_per_sample;
182       frame.num_channels = num_channels_;
183       frame.samples_per_sec = samples_per_sec_;
184       frame.elapsed_time_ms = elapsed_time_ms;
185       frame.ntp_time_ms = ntp_time_ms;
186       renderer_->Render(frame);
187     }
188     int32_t wait_for_us = -1;
189     if (renderer_) {
190       wait_for_us = renderer_->WaitForUs();
191     }
192     return wait_for_us;
193   }
194 
Record()195   int32_t Record() {
196     std::unique_lock<std::mutex> lock(record_mutex_);
197     if (!need_recording_) {
198       recording_ = false;
199       record_cond_.notify_all();
200       return -1;
201     }
202 
203     auto frame = recorder_->Record();
204     if (frame.num_samples != 0) {
205        uint32_t new_mic_level;
206        audio_callback_->RecordedDataIsAvailable(frame.audio_samples,
207          frame.num_samples, frame.bytes_per_sample, frame.num_channels,
208          frame.samples_per_sec, 0, 0, 0, false, new_mic_level);
209     }
210 
211     int32_t wait_for_us = -1;
212     if (recorder_) {
213       wait_for_us = recorder_->WaitForUs();
214     }
215     return wait_for_us;
216   }
217 
218   size_t num_channels_;
219   const uint32_t samples_per_sec_;
220   size_t samples_per_frame_{0};
221 
222   std::function<void(FakeAudioDeviceModule::Task)> scheduler_;
223 
224   mutable std::mutex render_mutex_;
225   std::atomic<bool> need_rendering_{false};
226   std::atomic<bool> rendering_{false};
227   std::condition_variable render_cond_;
228   std::unique_ptr<rtc::PlatformThread> renderThread_;
229 
230   mutable std::mutex record_mutex_;
231   std::atomic<bool> need_recording_{false};
232   std::atomic<bool> recording_{false};
233   std::condition_variable record_cond_;
234   std::unique_ptr<rtc::PlatformThread> recordThread_;
235 
236 
237   webrtc::AudioTransport* audio_callback_{nullptr};
238   const std::shared_ptr<FakeAudioDeviceModule::Renderer> renderer_;
239   const std::shared_ptr<FakeAudioDeviceModule::Recorder> recorder_;
240   std::vector<int16_t> playout_buffer_;
241 };
242 
Creator(std::shared_ptr<Renderer> renderer,std::shared_ptr<Recorder> recorder,Options options)243 std::function<rtc::scoped_refptr<webrtc::AudioDeviceModule>(webrtc::TaskQueueFactory*)> FakeAudioDeviceModule::Creator(
244     std::shared_ptr<Renderer> renderer, std::shared_ptr<Recorder> recorder, Options options) {
245   bool is_renderer_empty = bool(renderer);
246   auto boxed_renderer = std::make_shared<std::shared_ptr<Renderer>>(std::move(renderer));
247   bool is_recorder_empty = bool(recorder);
248   auto boxed_recorder = std::make_shared<std::shared_ptr<Recorder>>(std::move(recorder));
249   return
250       [boxed_renderer = std::move(boxed_renderer), is_renderer_empty,
251        boxed_recorder = std::move(boxed_recorder), is_recorder_empty, options](webrtc::TaskQueueFactory* task_factory) {
252         RTC_CHECK(is_renderer_empty == bool(*boxed_renderer));  // call only once if renderer exists
253         RTC_CHECK(is_recorder_empty == bool(*boxed_recorder));  // call only once if recorder exists
254         return FakeAudioDeviceModuleImpl::Create(task_factory, std::move(*boxed_renderer), std::move(*boxed_recorder), options);
255       };
256 }
257 }  // namespace tgcalls
258