OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
130 AudioMixerImpl::Source const* audio_source, | 130 AudioMixerImpl::Source const* audio_source, |
131 AudioMixerImpl::SourceStatusList* audio_source_list) { | 131 AudioMixerImpl::SourceStatusList* audio_source_list) { |
132 return std::find_if(audio_source_list->begin(), audio_source_list->end(), | 132 return std::find_if(audio_source_list->begin(), audio_source_list->end(), |
133 [audio_source](const AudioMixerImpl::SourceStatus& p) { | 133 [audio_source](const AudioMixerImpl::SourceStatus& p) { |
134 return p.audio_source == audio_source; | 134 return p.audio_source == audio_source; |
135 }); | 135 }); |
136 } | 136 } |
137 | 137 |
138 } // namespace | 138 } // namespace |
139 | 139 |
140 std::unique_ptr<AudioMixer> AudioMixer::Create() { | |
141 return AudioMixerImpl::Create(); | |
142 } | |
143 | |
144 AudioMixerImpl::AudioMixerImpl(std::unique_ptr<AudioProcessing> limiter) | 140 AudioMixerImpl::AudioMixerImpl(std::unique_ptr<AudioProcessing> limiter) |
145 : audio_source_list_(), | 141 : audio_source_list_(), |
146 num_mixed_audio_sources_(0), | |
147 use_limiter_(true), | 142 use_limiter_(true), |
148 time_stamp_(0), | 143 time_stamp_(0), |
149 limiter_(std::move(limiter)) { | 144 limiter_(std::move(limiter)) { |
150 SetOutputFrequency(kDefaultFrequency); | 145 SetOutputFrequency(kDefaultFrequency); |
151 thread_checker_.DetachFromThread(); | 146 thread_checker_.DetachFromThread(); |
152 } | 147 } |
153 | 148 |
154 AudioMixerImpl::~AudioMixerImpl() {} | 149 AudioMixerImpl::~AudioMixerImpl() {} |
155 | 150 |
156 std::unique_ptr<AudioMixerImpl> AudioMixerImpl::Create() { | 151 rtc::scoped_refptr<AudioMixerImpl> AudioMixerImpl::Create() { |
157 Config config; | 152 Config config; |
158 config.Set<ExperimentalAgc>(new ExperimentalAgc(false)); | 153 config.Set<ExperimentalAgc>(new ExperimentalAgc(false)); |
159 std::unique_ptr<AudioProcessing> limiter(AudioProcessing::Create(config)); | 154 std::unique_ptr<AudioProcessing> limiter(AudioProcessing::Create(config)); |
160 if (!limiter.get()) { | 155 if (!limiter.get()) { |
161 return nullptr; | 156 return nullptr; |
162 } | 157 } |
163 | 158 |
164 if (limiter->gain_control()->set_mode(GainControl::kFixedDigital) != | 159 if (limiter->gain_control()->set_mode(GainControl::kFixedDigital) != |
165 limiter->kNoError) { | 160 limiter->kNoError) { |
166 return nullptr; | 161 return nullptr; |
(...skipping 12 matching lines...) Expand all Loading... | |
179 } | 174 } |
180 | 175 |
181 if (limiter->gain_control()->enable_limiter(true) != limiter->kNoError) { | 176 if (limiter->gain_control()->enable_limiter(true) != limiter->kNoError) { |
182 return nullptr; | 177 return nullptr; |
183 } | 178 } |
184 | 179 |
185 if (limiter->gain_control()->Enable(true) != limiter->kNoError) { | 180 if (limiter->gain_control()->Enable(true) != limiter->kNoError) { |
186 return nullptr; | 181 return nullptr; |
187 } | 182 } |
188 | 183 |
189 return std::unique_ptr<AudioMixerImpl>( | 184 return rtc::scoped_refptr<AudioMixerImpl>( |
190 new AudioMixerImpl(std::move(limiter))); | 185 new rtc::RefCountedObject<AudioMixerImpl>(std::move(limiter))); |
191 } | 186 } |
192 | 187 |
193 void AudioMixerImpl::Mix(int sample_rate, | 188 void AudioMixerImpl::Mix(int sample_rate, |
194 size_t number_of_channels, | 189 size_t number_of_channels, |
195 AudioFrame* audio_frame_for_mixing) { | 190 AudioFrame* audio_frame_for_mixing) { |
196 RTC_DCHECK(number_of_channels == 1 || number_of_channels == 2); | 191 RTC_DCHECK(number_of_channels == 1 || number_of_channels == 2); |
197 RTC_DCHECK_RUN_ON(&thread_checker_); | 192 RTC_DCHECK_RUN_ON(&thread_checker_); |
198 | 193 |
199 | 194 |
200 if (OutputFrequency() != sample_rate) { | 195 if (OutputFrequency() != sample_rate) { |
201 SetOutputFrequency(sample_rate); | 196 SetOutputFrequency(sample_rate); |
202 } | 197 } |
203 | 198 |
204 AudioFrameList mix_list; | 199 AudioFrameList mix_list; |
205 size_t num_mixed_audio_sources; | |
206 { | 200 { |
207 rtc::CritScope lock(&crit_); | 201 rtc::CritScope lock(&crit_); |
208 mix_list = GetNonAnonymousAudio(); | 202 mix_list = GetAudioFromSources(); |
209 num_mixed_audio_sources = num_mixed_audio_sources_; | |
210 } | 203 } |
211 | 204 |
212 for (const auto& frame : mix_list) { | 205 for (const auto& frame : mix_list) { |
213 RemixFrame(frame, number_of_channels); | 206 RemixFrame(frame, number_of_channels); |
214 } | 207 } |
215 | 208 |
216 audio_frame_for_mixing->UpdateFrame( | 209 audio_frame_for_mixing->UpdateFrame( |
217 -1, time_stamp_, NULL, 0, OutputFrequency(), AudioFrame::kNormalSpeech, | 210 -1, time_stamp_, NULL, 0, OutputFrequency(), AudioFrame::kNormalSpeech, |
218 AudioFrame::kVadPassive, number_of_channels); | 211 AudioFrame::kVadPassive, number_of_channels); |
219 | 212 |
220 time_stamp_ += static_cast<uint32_t>(sample_size_); | 213 time_stamp_ += static_cast<uint32_t>(sample_size_); |
221 | 214 |
222 use_limiter_ = num_mixed_audio_sources > 1; | 215 use_limiter_ = mix_list.size() > 1; |
223 | 216 |
224 // We only use the limiter if we're actually mixing multiple streams. | 217 // We only use the limiter if we're actually mixing multiple streams. |
225 MixFromList(audio_frame_for_mixing, mix_list, use_limiter_); | 218 MixFromList(audio_frame_for_mixing, mix_list, use_limiter_); |
226 | 219 |
227 if (audio_frame_for_mixing->samples_per_channel_ == 0) { | 220 if (audio_frame_for_mixing->samples_per_channel_ == 0) { |
228 // Nothing was mixed, set the audio samples to silence. | 221 // Nothing was mixed, set the audio samples to silence. |
229 audio_frame_for_mixing->samples_per_channel_ = sample_size_; | 222 audio_frame_for_mixing->samples_per_channel_ = sample_size_; |
230 audio_frame_for_mixing->Mute(); | 223 audio_frame_for_mixing->Mute(); |
231 } else { | 224 } else { |
232 // Only call the limiter if we have something to mix. | 225 // Only call the limiter if we have something to mix. |
233 LimitMixedAudio(audio_frame_for_mixing); | 226 LimitMixedAudio(audio_frame_for_mixing); |
234 } | 227 } |
235 | 228 |
236 return; | 229 return; |
237 } | 230 } |
238 | 231 |
239 void AudioMixerImpl::SetOutputFrequency(int frequency) { | 232 void AudioMixerImpl::SetOutputFrequency(int frequency) { |
240 RTC_DCHECK_RUN_ON(&thread_checker_); | 233 RTC_DCHECK_RUN_ON(&thread_checker_); |
241 output_frequency_ = frequency; | 234 output_frequency_ = frequency; |
242 sample_size_ = (output_frequency_ * kFrameDurationInMs) / 1000; | 235 sample_size_ = (output_frequency_ * kFrameDurationInMs) / 1000; |
243 } | 236 } |
244 | 237 |
245 int AudioMixerImpl::OutputFrequency() const { | 238 int AudioMixerImpl::OutputFrequency() const { |
246 RTC_DCHECK_RUN_ON(&thread_checker_); | 239 RTC_DCHECK_RUN_ON(&thread_checker_); |
247 return output_frequency_; | 240 return output_frequency_; |
248 } | 241 } |
249 | 242 |
250 int32_t AudioMixerImpl::SetMixabilityStatus(Source* audio_source, | 243 bool AudioMixerImpl::AddSource(Source* audio_source) { |
251 bool mixable) { | 244 RTC_DCHECK(audio_source); |
252 { | 245 rtc::CritScope lock(&crit_); |
253 rtc::CritScope lock(&crit_); | 246 RTC_DCHECK(FindSourceInList(audio_source, &audio_source_list_) == |
hlundin-webrtc
2016/10/11 11:50:21
The argument of DCHECK is not evaluated in release
the sun
2016/10/11 12:10:56
That's exactly the point. Don't evaluate since it
| |
254 const bool is_mixed = FindSourceInList(audio_source, &audio_source_list_) != | 247 audio_source_list_.end()) |
255 audio_source_list_.end(); | 248 << "Source already added to mixer"; |
256 // API must be called with a new state. | 249 audio_source_list_.emplace_back(audio_source, false, 0); |
257 if (!(mixable ^ is_mixed)) { | 250 return true; |
258 return -1; | |
259 } | |
260 bool success = false; | |
261 if (mixable) { | |
262 success = AddAudioSourceToList(audio_source, &audio_source_list_); | |
263 } else { | |
264 success = RemoveAudioSourceFromList(audio_source, &audio_source_list_); | |
265 } | |
266 if (!success) { | |
267 RTC_NOTREACHED(); | |
268 return -1; | |
269 } | |
270 | |
271 size_t num_mixed_non_anonymous = audio_source_list_.size(); | |
272 if (num_mixed_non_anonymous > kMaximumAmountOfMixedAudioSources) { | |
273 num_mixed_non_anonymous = kMaximumAmountOfMixedAudioSources; | |
274 } | |
275 num_mixed_audio_sources_ = num_mixed_non_anonymous; | |
276 } | |
277 return 0; | |
278 } | 251 } |
279 | 252 |
253 bool AudioMixerImpl::RemoveSource(Source* audio_source) { | |
254 RTC_DCHECK(audio_source); | |
255 rtc::CritScope lock(&crit_); | |
256 const auto iter = FindSourceInList(audio_source, &audio_source_list_); | |
257 RTC_DCHECK(iter != audio_source_list_.end()) << "Source not present in mixer"; | |
hlundin-webrtc
2016/10/11 11:50:21
Same here.
the sun
2016/10/11 12:10:56
But here "iter" is used for the deletion.
hlundin-webrtc
2016/10/11 12:49:54
Yes, iter is needed in any case. I was referring t
| |
258 audio_source_list_.erase(iter); | |
259 return true; | |
260 } | |
280 | 261 |
281 | 262 AudioFrameList AudioMixerImpl::GetAudioFromSources() { |
282 AudioFrameList AudioMixerImpl::GetNonAnonymousAudio() { | |
283 RTC_DCHECK_RUN_ON(&thread_checker_); | 263 RTC_DCHECK_RUN_ON(&thread_checker_); |
284 AudioFrameList result; | 264 AudioFrameList result; |
285 std::vector<SourceFrame> audio_source_mixing_data_list; | 265 std::vector<SourceFrame> audio_source_mixing_data_list; |
286 std::vector<SourceFrame> ramp_list; | 266 std::vector<SourceFrame> ramp_list; |
287 | 267 |
288 // Get audio source audio and put it in the struct vector. | 268 // Get audio source audio and put it in the struct vector. |
289 for (auto& source_and_status : audio_source_list_) { | 269 for (auto& source_and_status : audio_source_list_) { |
290 auto audio_frame_with_info = | 270 auto audio_frame_with_info = |
291 source_and_status.audio_source->GetAudioFrameWithMuted( | 271 source_and_status.audio_source->GetAudioFrameWithMuted( |
292 static_cast<int>(OutputFrequency())); | 272 static_cast<int>(OutputFrequency())); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
324 result.push_back(p.audio_frame); | 304 result.push_back(p.audio_frame); |
325 ramp_list.emplace_back(p.source_status, p.audio_frame, false, -1); | 305 ramp_list.emplace_back(p.source_status, p.audio_frame, false, -1); |
326 is_mixed = true; | 306 is_mixed = true; |
327 } | 307 } |
328 p.source_status->is_mixed = is_mixed; | 308 p.source_status->is_mixed = is_mixed; |
329 } | 309 } |
330 RampAndUpdateGain(ramp_list); | 310 RampAndUpdateGain(ramp_list); |
331 return result; | 311 return result; |
332 } | 312 } |
333 | 313 |
334 bool AudioMixerImpl::AddAudioSourceToList( | |
335 Source* audio_source, | |
336 SourceStatusList* audio_source_list) const { | |
337 audio_source_list->emplace_back(audio_source, false, 0); | |
338 return true; | |
339 } | |
340 | |
341 bool AudioMixerImpl::RemoveAudioSourceFromList( | |
342 Source* audio_source, | |
343 SourceStatusList* audio_source_list) const { | |
344 const auto iter = FindSourceInList(audio_source, audio_source_list); | |
345 if (iter != audio_source_list->end()) { | |
346 audio_source_list->erase(iter); | |
347 return true; | |
348 } else { | |
349 return false; | |
350 } | |
351 } | |
352 | 314 |
353 bool AudioMixerImpl::LimitMixedAudio(AudioFrame* mixed_audio) const { | 315 bool AudioMixerImpl::LimitMixedAudio(AudioFrame* mixed_audio) const { |
354 RTC_DCHECK_RUN_ON(&thread_checker_); | 316 RTC_DCHECK_RUN_ON(&thread_checker_); |
355 if (!use_limiter_) { | 317 if (!use_limiter_) { |
356 return true; | 318 return true; |
357 } | 319 } |
358 | 320 |
359 // Smoothly limit the mixed frame. | 321 // Smoothly limit the mixed frame. |
360 const int error = limiter_->ProcessStream(mixed_audio); | 322 const int error = limiter_->ProcessStream(mixed_audio); |
361 | 323 |
(...skipping 25 matching lines...) Expand all Loading... | |
387 const auto non_anonymous_iter = | 349 const auto non_anonymous_iter = |
388 FindSourceInList(audio_source, &audio_source_list_); | 350 FindSourceInList(audio_source, &audio_source_list_); |
389 if (non_anonymous_iter != audio_source_list_.end()) { | 351 if (non_anonymous_iter != audio_source_list_.end()) { |
390 return non_anonymous_iter->is_mixed; | 352 return non_anonymous_iter->is_mixed; |
391 } | 353 } |
392 | 354 |
393 LOG(LS_ERROR) << "Audio source unknown"; | 355 LOG(LS_ERROR) << "Audio source unknown"; |
394 return false; | 356 return false; |
395 } | 357 } |
396 } // namespace webrtc | 358 } // namespace webrtc |
OLD | NEW |