blob: 194f09cf6c786b9fa47c403873e0bde2f40e7cb0 [file] [log] [blame]
Fredrik Solenberg2a877972017-12-15 16:42:15 +01001/*
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "audio/audio_transport_impl.h"
12
13#include <algorithm>
14#include <memory>
15#include <utility>
16
Fredrik Solenberga8b7c7f2018-01-17 11:18:31 +010017#include "audio/remix_resample.h"
Fredrik Solenberg2a877972017-12-15 16:42:15 +010018#include "audio/utility/audio_frame_operations.h"
Tim Nab8c775a2020-01-10 10:33:05 -080019#include "call/audio_sender.h"
Olga Sharonova09ceed22020-09-30 18:27:39 +020020#include "modules/async_audio_processing/async_audio_processing.h"
Per Åhgren71652f42020-03-17 13:23:58 +010021#include "modules/audio_processing/include/audio_frame_proxies.h"
Yves Gerey988cc082018-10-23 12:03:01 +020022#include "rtc_base/checks.h"
Fredrik Solenberg2a877972017-12-15 16:42:15 +010023
24namespace webrtc {
25
26namespace {
27
28// We want to process at the lowest sample rate and channel count possible
29// without losing information. Choose the lowest native rate at least equal to
30// the minimum of input and codec rates, choose lowest channel count, and
31// configure the audio frame.
32void InitializeCaptureFrame(int input_sample_rate,
33 int send_sample_rate_hz,
34 size_t input_num_channels,
35 size_t send_num_channels,
36 AudioFrame* audio_frame) {
37 RTC_DCHECK(audio_frame);
38 int min_processing_rate_hz = std::min(input_sample_rate, send_sample_rate_hz);
39 for (int native_rate_hz : AudioProcessing::kNativeSampleRatesHz) {
40 audio_frame->sample_rate_hz_ = native_rate_hz;
41 if (audio_frame->sample_rate_hz_ >= min_processing_rate_hz) {
42 break;
43 }
44 }
45 audio_frame->num_channels_ = std::min(input_num_channels, send_num_channels);
46}
47
henrika649a3852017-12-22 13:58:29 +010048void ProcessCaptureFrame(uint32_t delay_ms,
Fredrik Solenberg2a877972017-12-15 16:42:15 +010049 bool key_pressed,
50 bool swap_stereo_channels,
51 AudioProcessing* audio_processing,
52 AudioFrame* audio_frame) {
Fredrik Solenberg2a877972017-12-15 16:42:15 +010053 RTC_DCHECK(audio_frame);
Per Åhgrencc73ed32020-04-26 23:56:17 +020054 if (audio_processing) {
55 audio_processing->set_stream_delay_ms(delay_ms);
56 audio_processing->set_stream_key_pressed(key_pressed);
57 int error = ProcessAudioFrame(audio_processing, audio_frame);
Per Åhgren71652f42020-03-17 13:23:58 +010058
Per Åhgrencc73ed32020-04-26 23:56:17 +020059 RTC_DCHECK_EQ(0, error) << "ProcessStream() error: " << error;
60 }
61
Fredrik Solenberg2a877972017-12-15 16:42:15 +010062 if (swap_stereo_channels) {
63 AudioFrameOperations::SwapStereoChannels(audio_frame);
64 }
65}
66
Artem Titovb0ea6372021-07-26 11:47:07 +020067// Resample audio in `frame` to given sample rate preserving the
68// channel count and place the result in `destination`.
Fredrik Solenberg2a877972017-12-15 16:42:15 +010069int Resample(const AudioFrame& frame,
70 const int destination_sample_rate,
71 PushResampler<int16_t>* resampler,
72 int16_t* destination) {
73 const int number_of_channels = static_cast<int>(frame.num_channels_);
74 const int target_number_of_samples_per_channel =
75 destination_sample_rate / 100;
76 resampler->InitializeIfNeeded(frame.sample_rate_hz_, destination_sample_rate,
77 number_of_channels);
78
79 // TODO(yujo): make resampler take an AudioFrame, and add special case
80 // handling of muted frames.
81 return resampler->Resample(
82 frame.data(), frame.samples_per_channel_ * number_of_channels,
83 destination, number_of_channels * target_number_of_samples_per_channel);
84}
85} // namespace
86
Olga Sharonova09ceed22020-09-30 18:27:39 +020087AudioTransportImpl::AudioTransportImpl(
88 AudioMixer* mixer,
89 AudioProcessing* audio_processing,
90 AsyncAudioProcessing::Factory* async_audio_processing_factory)
91 : audio_processing_(audio_processing),
92 async_audio_processing_(
93 async_audio_processing_factory
94 ? async_audio_processing_factory->CreateAsyncAudioProcessing(
95 [this](std::unique_ptr<AudioFrame> frame) {
96 this->SendProcessedData(std::move(frame));
97 })
98 : nullptr),
99 mixer_(mixer) {
Fredrik Solenberg2a877972017-12-15 16:42:15 +0100100 RTC_DCHECK(mixer);
Fredrik Solenberg2a877972017-12-15 16:42:15 +0100101}
102
103AudioTransportImpl::~AudioTransportImpl() {}
104
Olov Brändströmb732bd52022-01-28 15:07:39 +0100105int32_t AudioTransportImpl::RecordedDataIsAvailable(
106 const void* audio_data,
107 const size_t number_of_frames,
108 const size_t bytes_per_sample,
109 const size_t number_of_channels,
110 const uint32_t sample_rate,
111 const uint32_t audio_delay_milliseconds,
112 const int32_t clock_drift,
113 const uint32_t volume,
114 const bool key_pressed,
115 uint32_t& new_mic_volume) { // NOLINT: to avoid changing APIs
116 return RecordedDataIsAvailable(
117 audio_data, number_of_frames, bytes_per_sample, number_of_channels,
118 sample_rate, audio_delay_milliseconds, clock_drift, volume, key_pressed,
119 new_mic_volume, /* estimated_capture_time_ns */ 0);
120}
121
Fredrik Solenberg2a877972017-12-15 16:42:15 +0100122// Not used in Chromium. Process captured audio and distribute to all sending
123// streams, and try to do this at the lowest possible sample rate.
124int32_t AudioTransportImpl::RecordedDataIsAvailable(
125 const void* audio_data,
126 const size_t number_of_frames,
127 const size_t bytes_per_sample,
128 const size_t number_of_channels,
129 const uint32_t sample_rate,
130 const uint32_t audio_delay_milliseconds,
131 const int32_t /*clock_drift*/,
henrika649a3852017-12-22 13:58:29 +0100132 const uint32_t /*volume*/,
Fredrik Solenberg2a877972017-12-15 16:42:15 +0100133 const bool key_pressed,
Olov Brändströmb732bd52022-01-28 15:07:39 +0100134 uint32_t& /*new_mic_volume*/,
135 const int64_t
136 estimated_capture_time_ns) { // NOLINT: to avoid changing APIs
Fredrik Solenberg2a877972017-12-15 16:42:15 +0100137 RTC_DCHECK(audio_data);
138 RTC_DCHECK_GE(number_of_channels, 1);
139 RTC_DCHECK_LE(number_of_channels, 2);
140 RTC_DCHECK_EQ(2 * number_of_channels, bytes_per_sample);
141 RTC_DCHECK_GE(sample_rate, AudioProcessing::NativeRate::kSampleRate8kHz);
142 // 100 = 1 second / data duration (10 ms).
143 RTC_DCHECK_EQ(number_of_frames * 100, sample_rate);
144 RTC_DCHECK_LE(bytes_per_sample * number_of_frames * number_of_channels,
145 AudioFrame::kMaxDataSizeBytes);
146
Fredrik Solenberg2a877972017-12-15 16:42:15 +0100147 int send_sample_rate_hz = 0;
148 size_t send_num_channels = 0;
149 bool swap_stereo_channels = false;
150 {
Markus Handell62872802020-07-06 15:15:07 +0200151 MutexLock lock(&capture_lock_);
Fredrik Solenberg2a877972017-12-15 16:42:15 +0100152 send_sample_rate_hz = send_sample_rate_hz_;
153 send_num_channels = send_num_channels_;
154 swap_stereo_channels = swap_stereo_channels_;
155 }
156
157 std::unique_ptr<AudioFrame> audio_frame(new AudioFrame());
Yves Gerey665174f2018-06-19 15:03:05 +0200158 InitializeCaptureFrame(sample_rate, send_sample_rate_hz, number_of_channels,
159 send_num_channels, audio_frame.get());
Fredrik Solenberg2a877972017-12-15 16:42:15 +0100160 voe::RemixAndResample(static_cast<const int16_t*>(audio_data),
161 number_of_frames, number_of_channels, sample_rate,
162 &capture_resampler_, audio_frame.get());
henrika649a3852017-12-22 13:58:29 +0100163 ProcessCaptureFrame(audio_delay_milliseconds, key_pressed,
Fredrik Solenberg2a877972017-12-15 16:42:15 +0100164 swap_stereo_channels, audio_processing_,
165 audio_frame.get());
Olov Brändströmb732bd52022-01-28 15:07:39 +0100166 audio_frame->set_absolute_capture_timestamp_ms(estimated_capture_time_ns /
167 1000000);
Fredrik Solenberg2a877972017-12-15 16:42:15 +0100168
Olga Sharonova09ceed22020-09-30 18:27:39 +0200169 RTC_DCHECK_GT(audio_frame->samples_per_channel_, 0);
170 if (async_audio_processing_)
171 async_audio_processing_->Process(std::move(audio_frame));
172 else
173 SendProcessedData(std::move(audio_frame));
174
Fredrik Solenberg2a877972017-12-15 16:42:15 +0100175 return 0;
176}
177
Olga Sharonova09ceed22020-09-30 18:27:39 +0200178void AudioTransportImpl::SendProcessedData(
179 std::unique_ptr<AudioFrame> audio_frame) {
180 RTC_DCHECK_GT(audio_frame->samples_per_channel_, 0);
181 MutexLock lock(&capture_lock_);
182 if (audio_senders_.empty())
183 return;
184
185 auto it = audio_senders_.begin();
186 while (++it != audio_senders_.end()) {
187 auto audio_frame_copy = std::make_unique<AudioFrame>();
188 audio_frame_copy->CopyFrom(*audio_frame);
189 (*it)->SendAudioData(std::move(audio_frame_copy));
190 }
191 // Send the original frame to the first stream w/o copying.
192 (*audio_senders_.begin())->SendAudioData(std::move(audio_frame));
193}
194
Fredrik Solenberg2a877972017-12-15 16:42:15 +0100195// Mix all received streams, feed the result to the AudioProcessing module, then
196// resample the result to the requested output rate.
197int32_t AudioTransportImpl::NeedMorePlayData(const size_t nSamples,
Yves Gerey665174f2018-06-19 15:03:05 +0200198 const size_t nBytesPerSample,
199 const size_t nChannels,
200 const uint32_t samplesPerSec,
201 void* audioSamples,
202 size_t& nSamplesOut,
203 int64_t* elapsed_time_ms,
204 int64_t* ntp_time_ms) {
Fredrik Solenberg2a877972017-12-15 16:42:15 +0100205 RTC_DCHECK_EQ(sizeof(int16_t) * nChannels, nBytesPerSample);
206 RTC_DCHECK_GE(nChannels, 1);
207 RTC_DCHECK_LE(nChannels, 2);
208 RTC_DCHECK_GE(
209 samplesPerSec,
210 static_cast<uint32_t>(AudioProcessing::NativeRate::kSampleRate8kHz));
211
212 // 100 = 1 second / data duration (10 ms).
213 RTC_DCHECK_EQ(nSamples * 100, samplesPerSec);
214 RTC_DCHECK_LE(nBytesPerSample * nSamples * nChannels,
215 AudioFrame::kMaxDataSizeBytes);
216
217 mixer_->Mix(nChannels, &mixed_frame_);
218 *elapsed_time_ms = mixed_frame_.elapsed_time_ms_;
219 *ntp_time_ms = mixed_frame_.ntp_time_ms_;
220
Per Åhgrencc73ed32020-04-26 23:56:17 +0200221 if (audio_processing_) {
222 const auto error =
223 ProcessReverseAudioFrame(audio_processing_, &mixed_frame_);
224 RTC_DCHECK_EQ(error, AudioProcessing::kNoError);
225 }
Fredrik Solenberg2a877972017-12-15 16:42:15 +0100226
227 nSamplesOut = Resample(mixed_frame_, samplesPerSec, &render_resampler_,
228 static_cast<int16_t*>(audioSamples));
229 RTC_DCHECK_EQ(nSamplesOut, nChannels * nSamples);
230 return 0;
231}
232
233// Used by Chromium - same as NeedMorePlayData() but because Chrome has its
234// own APM instance, does not call audio_processing_->ProcessReverseStream().
235void AudioTransportImpl::PullRenderData(int bits_per_sample,
Yves Gerey665174f2018-06-19 15:03:05 +0200236 int sample_rate,
237 size_t number_of_channels,
238 size_t number_of_frames,
239 void* audio_data,
240 int64_t* elapsed_time_ms,
241 int64_t* ntp_time_ms) {
Fredrik Solenberg2a877972017-12-15 16:42:15 +0100242 RTC_DCHECK_EQ(bits_per_sample, 16);
243 RTC_DCHECK_GE(number_of_channels, 1);
Fredrik Solenberg2a877972017-12-15 16:42:15 +0100244 RTC_DCHECK_GE(sample_rate, AudioProcessing::NativeRate::kSampleRate8kHz);
245
246 // 100 = 1 second / data duration (10 ms).
247 RTC_DCHECK_EQ(number_of_frames * 100, sample_rate);
248
249 // 8 = bits per byte.
250 RTC_DCHECK_LE(bits_per_sample / 8 * number_of_frames * number_of_channels,
251 AudioFrame::kMaxDataSizeBytes);
252 mixer_->Mix(number_of_channels, &mixed_frame_);
253 *elapsed_time_ms = mixed_frame_.elapsed_time_ms_;
254 *ntp_time_ms = mixed_frame_.ntp_time_ms_;
255
256 auto output_samples = Resample(mixed_frame_, sample_rate, &render_resampler_,
257 static_cast<int16_t*>(audio_data));
258 RTC_DCHECK_EQ(output_samples, number_of_channels * number_of_frames);
259}
260
Tim Nab8c775a2020-01-10 10:33:05 -0800261void AudioTransportImpl::UpdateAudioSenders(std::vector<AudioSender*> senders,
262 int send_sample_rate_hz,
263 size_t send_num_channels) {
Markus Handell62872802020-07-06 15:15:07 +0200264 MutexLock lock(&capture_lock_);
Tim Nab8c775a2020-01-10 10:33:05 -0800265 audio_senders_ = std::move(senders);
Fredrik Solenberg2a877972017-12-15 16:42:15 +0100266 send_sample_rate_hz_ = send_sample_rate_hz;
267 send_num_channels_ = send_num_channels;
268}
269
270void AudioTransportImpl::SetStereoChannelSwapping(bool enable) {
Markus Handell62872802020-07-06 15:15:07 +0200271 MutexLock lock(&capture_lock_);
Fredrik Solenberg2a877972017-12-15 16:42:15 +0100272 swap_stereo_channels_ = enable;
273}
274
Fredrik Solenberg2a877972017-12-15 16:42:15 +0100275} // namespace webrtc