| Index: webrtc/modules/audio_mixer/audio_mixer_impl.cc
|
| diff --git a/webrtc/modules/audio_mixer/audio_mixer_impl.cc b/webrtc/modules/audio_mixer/audio_mixer_impl.cc
|
| index 5a8d1eb7645705113dc3155565668b198a6bbeb3..93b78bd4c34947ec91a514097384e4644e0a6402 100644
|
| --- a/webrtc/modules/audio_mixer/audio_mixer_impl.cc
|
| +++ b/webrtc/modules/audio_mixer/audio_mixer_impl.cc
|
| @@ -12,7 +12,9 @@
|
|
|
| #include <algorithm>
|
| #include <functional>
|
| +#include <utility>
|
|
|
| +#include "webrtc/base/thread_annotations.h"
|
| #include "webrtc/modules/audio_mixer/audio_frame_manipulator.h"
|
| #include "webrtc/modules/audio_mixer/audio_mixer_defines.h"
|
| #include "webrtc/modules/audio_processing/include/audio_processing.h"
|
| @@ -120,105 +122,80 @@ void NewMixHistory::ResetMixedStatus() {
|
| }
|
|
|
| std::unique_ptr<AudioMixer> AudioMixer::Create(int id) {
|
| - AudioMixerImpl* mixer = new AudioMixerImpl(id);
|
| - if (!mixer->Init()) {
|
| - delete mixer;
|
| - return NULL;
|
| - }
|
| - return std::unique_ptr<AudioMixer>(mixer);
|
| + return AudioMixerImpl::Create(id);
|
| }
|
|
|
| -AudioMixerImpl::AudioMixerImpl(int id)
|
| +AudioMixerImpl::AudioMixerImpl(int id, std::unique_ptr<AudioProcessing> limiter)
|
| : id_(id),
|
| - output_frequency_(kDefaultFrequency),
|
| - sample_size_(0),
|
| audio_source_list_(),
|
| additional_audio_source_list_(),
|
| num_mixed_audio_sources_(0),
|
| use_limiter_(true),
|
| - time_stamp_(0) {
|
| + time_stamp_(0),
|
| + limiter_(std::move(limiter)) {
|
| + SetOutputFrequency(kDefaultFrequency);
|
| thread_checker_.DetachFromThread();
|
| }
|
|
|
| AudioMixerImpl::~AudioMixerImpl() {}
|
|
|
| -bool AudioMixerImpl::Init() {
|
| - crit_.reset(CriticalSectionWrapper::CreateCriticalSection());
|
| - if (crit_.get() == NULL)
|
| - return false;
|
| -
|
| - cb_crit_.reset(CriticalSectionWrapper::CreateCriticalSection());
|
| - if (cb_crit_.get() == NULL)
|
| - return false;
|
| -
|
| +std::unique_ptr<AudioMixer> AudioMixerImpl::Create(int id) {
|
| Config config;
|
| config.Set<ExperimentalAgc>(new ExperimentalAgc(false));
|
| - limiter_.reset(AudioProcessing::Create(config));
|
| - if (!limiter_.get())
|
| - return false;
|
| -
|
| - if (SetOutputFrequency(kDefaultFrequency) == -1)
|
| - return false;
|
| + std::unique_ptr<AudioProcessing> limiter(AudioProcessing::Create(config));
|
| + if (!limiter.get())
|
| + return nullptr;
|
|
|
| - if (limiter_->gain_control()->set_mode(GainControl::kFixedDigital) !=
|
| - limiter_->kNoError)
|
| - return false;
|
| + if (limiter->gain_control()->set_mode(GainControl::kFixedDigital) !=
|
| + limiter->kNoError)
|
| + return nullptr;
|
|
|
| // We smoothly limit the mixed frame to -7 dbFS. -6 would correspond to the
|
| // divide-by-2 but -7 is used instead to give a bit of headroom since the
|
| // AGC is not a hard limiter.
|
| - if (limiter_->gain_control()->set_target_level_dbfs(7) != limiter_->kNoError)
|
| - return false;
|
| + if (limiter->gain_control()->set_target_level_dbfs(7) != limiter->kNoError)
|
| + return nullptr;
|
|
|
| - if (limiter_->gain_control()->set_compression_gain_db(0) !=
|
| - limiter_->kNoError)
|
| - return false;
|
| + if (limiter->gain_control()->set_compression_gain_db(0) != limiter->kNoError)
|
| + return nullptr;
|
|
|
| - if (limiter_->gain_control()->enable_limiter(true) != limiter_->kNoError)
|
| - return false;
|
| + if (limiter->gain_control()->enable_limiter(true) != limiter->kNoError)
|
| + return nullptr;
|
|
|
| - if (limiter_->gain_control()->Enable(true) != limiter_->kNoError)
|
| - return false;
|
| + if (limiter->gain_control()->Enable(true) != limiter->kNoError)
|
| + return nullptr;
|
|
|
| - return true;
|
| + return std::unique_ptr<AudioMixer>(
|
| + new AudioMixerImpl(id, std::move(limiter)));
|
| }
|
|
|
| void AudioMixerImpl::Mix(int sample_rate,
|
| size_t number_of_channels,
|
| AudioFrame* audio_frame_for_mixing) {
|
| RTC_DCHECK(number_of_channels == 1 || number_of_channels == 2);
|
| - RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
| - AudioFrameList mixList;
|
| - AudioFrameList additionalFramesList;
|
| + RTC_DCHECK_RUN_ON(&thread_checker_);
|
| std::map<int, MixerAudioSource*> mixedAudioSourcesMap;
|
| - {
|
| - CriticalSectionScoped cs(cb_crit_.get());
|
| - Frequency mixing_frequency;
|
| -
|
| - switch (sample_rate) {
|
| - case 8000:
|
| - mixing_frequency = kNbInHz;
|
| - break;
|
| - case 16000:
|
| - mixing_frequency = kWbInHz;
|
| - break;
|
| - case 32000:
|
| - mixing_frequency = kSwbInHz;
|
| - break;
|
| - case 48000:
|
| - mixing_frequency = kFbInHz;
|
| - break;
|
| - default:
|
| - RTC_NOTREACHED();
|
| - return;
|
| - }
|
|
|
| - if (OutputFrequency() != mixing_frequency) {
|
| - SetOutputFrequency(mixing_frequency);
|
| - }
|
| + if (sample_rate != kNbInHz && sample_rate != kWbInHz &&
|
| + sample_rate != kSwbInHz && sample_rate != kFbInHz) {
|
| + WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, id_,
|
| + "Invalid frequency: %d", sample_rate);
|
| + RTC_NOTREACHED();
|
| + return;
|
| + }
|
|
|
| + if (OutputFrequency() != sample_rate) {
|
| + SetOutputFrequency(static_cast<Frequency>(sample_rate));
|
| + }
|
| +
|
| + AudioFrameList mixList;
|
| + AudioFrameList additionalFramesList;
|
| + int num_mixed_audio_sources;
|
| + {
|
| + rtc::CritScope lock(&crit_);
|
| mixList = UpdateToMix(kMaximumAmountOfMixedAudioSources);
|
| GetAdditionalAudio(&additionalFramesList);
|
| + num_mixed_audio_sources = static_cast<int>(num_mixed_audio_sources_);
|
| }
|
|
|
| for (FrameAndMuteInfo& frame_and_mute : mixList) {
|
| @@ -234,24 +211,19 @@ void AudioMixerImpl::Mix(int sample_rate,
|
|
|
| time_stamp_ += static_cast<uint32_t>(sample_size_);
|
|
|
| - use_limiter_ = num_mixed_audio_sources_ > 1;
|
| + use_limiter_ = num_mixed_audio_sources > 1;
|
|
|
| // We only use the limiter if it supports the output sample rate and
|
| // we're actually mixing multiple streams.
|
| MixFromList(audio_frame_for_mixing, mixList, id_, use_limiter_);
|
| -
|
| - {
|
| - CriticalSectionScoped cs(crit_.get());
|
| - MixAnonomouslyFromList(audio_frame_for_mixing, additionalFramesList);
|
| -
|
| - if (audio_frame_for_mixing->samples_per_channel_ == 0) {
|
| - // Nothing was mixed, set the audio samples to silence.
|
| - audio_frame_for_mixing->samples_per_channel_ = sample_size_;
|
| - audio_frame_for_mixing->Mute();
|
| - } else {
|
| - // Only call the limiter if we have something to mix.
|
| - LimitMixedAudio(audio_frame_for_mixing);
|
| - }
|
| + MixAnonomouslyFromList(audio_frame_for_mixing, additionalFramesList);
|
| + if (audio_frame_for_mixing->samples_per_channel_ == 0) {
|
| + // Nothing was mixed, set the audio samples to silence.
|
| + audio_frame_for_mixing->samples_per_channel_ = sample_size_;
|
| + audio_frame_for_mixing->Mute();
|
| + } else {
|
| + // Only call the limiter if we have something to mix.
|
| + LimitMixedAudio(audio_frame_for_mixing);
|
| }
|
|
|
| // Pass the final result to the level indicator.
|
| @@ -261,8 +233,7 @@ void AudioMixerImpl::Mix(int sample_rate,
|
| }
|
|
|
| int32_t AudioMixerImpl::SetOutputFrequency(const Frequency& frequency) {
|
| - CriticalSectionScoped cs(crit_.get());
|
| -
|
| + RTC_DCHECK_RUN_ON(&thread_checker_);
|
| output_frequency_ = frequency;
|
| sample_size_ =
|
| static_cast<size_t>((output_frequency_ * kFrameDurationInMs) / 1000);
|
| @@ -271,7 +242,7 @@ int32_t AudioMixerImpl::SetOutputFrequency(const Frequency& frequency) {
|
| }
|
|
|
| AudioMixer::Frequency AudioMixerImpl::OutputFrequency() const {
|
| - CriticalSectionScoped cs(crit_.get());
|
| + RTC_DCHECK_RUN_ON(&thread_checker_);
|
| return output_frequency_;
|
| }
|
|
|
| @@ -282,9 +253,8 @@ int32_t AudioMixerImpl::SetMixabilityStatus(MixerAudioSource* audio_source,
|
| // audio source is in the _audioSourceList if it is being mixed.
|
| SetAnonymousMixabilityStatus(audio_source, false);
|
| }
|
| - size_t numMixedAudioSources;
|
| {
|
| - CriticalSectionScoped cs(cb_crit_.get());
|
| + rtc::CritScope lock(&crit_);
|
| const bool isMixed = IsAudioSourceInList(*audio_source, audio_source_list_);
|
| // API must be called with a new state.
|
| if (!(mixable ^ isMixed)) {
|
| @@ -309,27 +279,22 @@ int32_t AudioMixerImpl::SetMixabilityStatus(MixerAudioSource* audio_source,
|
| if (numMixedNonAnonymous > kMaximumAmountOfMixedAudioSources) {
|
| numMixedNonAnonymous = kMaximumAmountOfMixedAudioSources;
|
| }
|
| - numMixedAudioSources =
|
| + num_mixed_audio_sources_ =
|
| numMixedNonAnonymous + additional_audio_source_list_.size();
|
| }
|
| - // A MixerAudioSource was added or removed. Make sure the scratch
|
| - // buffer is updated if necessary.
|
| - // Note: The scratch buffer may only be updated in Process().
|
| - CriticalSectionScoped cs(crit_.get());
|
| - num_mixed_audio_sources_ = numMixedAudioSources;
|
| return 0;
|
| }
|
|
|
| bool AudioMixerImpl::MixabilityStatus(
|
| const MixerAudioSource& audio_source) const {
|
| - CriticalSectionScoped cs(cb_crit_.get());
|
| + rtc::CritScope lock(&crit_);
|
| return IsAudioSourceInList(audio_source, audio_source_list_);
|
| }
|
|
|
| int32_t AudioMixerImpl::SetAnonymousMixabilityStatus(
|
| MixerAudioSource* audio_source,
|
| bool anonymous) {
|
| - CriticalSectionScoped cs(cb_crit_.get());
|
| + rtc::CritScope lock(&crit_);
|
| if (IsAudioSourceInList(*audio_source, additional_audio_source_list_)) {
|
| if (anonymous) {
|
| return 0;
|
| @@ -363,11 +328,12 @@ int32_t AudioMixerImpl::SetAnonymousMixabilityStatus(
|
|
|
| bool AudioMixerImpl::AnonymousMixabilityStatus(
|
| const MixerAudioSource& audio_source) const {
|
| - CriticalSectionScoped cs(cb_crit_.get());
|
| + rtc::CritScope lock(&crit_);
|
| return IsAudioSourceInList(audio_source, additional_audio_source_list_);
|
| }
|
|
|
| AudioFrameList AudioMixerImpl::UpdateToMix(size_t maxAudioFrameCounter) const {
|
| + RTC_DCHECK_RUN_ON(&thread_checker_);
|
| AudioFrameList result;
|
| std::vector<SourceFrame> audioSourceMixingDataList;
|
|
|
| @@ -426,6 +392,7 @@ AudioFrameList AudioMixerImpl::UpdateToMix(size_t maxAudioFrameCounter) const {
|
|
|
| void AudioMixerImpl::GetAdditionalAudio(
|
| AudioFrameList* additionalFramesList) const {
|
| + RTC_DCHECK_RUN_ON(&thread_checker_);
|
| WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_,
|
| "GetAdditionalAudio(additionalFramesList)");
|
| // The GetAudioFrameWithMuted() callback may result in the audio source being
|
| @@ -533,6 +500,7 @@ int32_t AudioMixerImpl::MixFromList(AudioFrame* mixedAudio,
|
| int32_t AudioMixerImpl::MixAnonomouslyFromList(
|
| AudioFrame* mixedAudio,
|
| const AudioFrameList& audioFrameList) const {
|
| + RTC_DCHECK_RUN_ON(&thread_checker_);
|
| WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_,
|
| "MixAnonomouslyFromList(mixedAudio, audioFrameList)");
|
|
|
| @@ -549,6 +517,7 @@ int32_t AudioMixerImpl::MixAnonomouslyFromList(
|
| }
|
|
|
| bool AudioMixerImpl::LimitMixedAudio(AudioFrame* mixedAudio) const {
|
| + RTC_DCHECK_RUN_ON(&thread_checker_);
|
| if (!use_limiter_) {
|
| return true;
|
| }
|
| @@ -578,6 +547,7 @@ bool AudioMixerImpl::LimitMixedAudio(AudioFrame* mixedAudio) const {
|
| }
|
|
|
| int AudioMixerImpl::GetOutputAudioLevel() {
|
| + RTC_DCHECK_RUN_ON(&thread_checker_);
|
| const int level = audio_level_.Level();
|
| WEBRTC_TRACE(kTraceStateInfo, kTraceAudioMixerServer, id_,
|
| "GetAudioOutputLevel() => level=%d", level);
|
| @@ -585,6 +555,7 @@ int AudioMixerImpl::GetOutputAudioLevel() {
|
| }
|
|
|
| int AudioMixerImpl::GetOutputAudioLevelFullRange() {
|
| + RTC_DCHECK_RUN_ON(&thread_checker_);
|
| const int level = audio_level_.LevelFullRange();
|
| WEBRTC_TRACE(kTraceStateInfo, kTraceAudioMixerServer, id_,
|
| "GetAudioOutputLevelFullRange() => level=%d", level);
|
|
|