Implemented further mixer interface change suggestions from https://codereview.webrtc.org/2386383003/
Changed mixability status into AddSource/RemoveSource. Added 'ssrc()' method to the MixerSource interface. Removed unnecessary member 'num_audio_sources_' and made the mixer be refcounted. BUG=webrtc:6346 NOTRY=True Review-Url: https://codereview.webrtc.org/2408683002 Cr-Commit-Position: refs/heads/master@{#14612}
This commit is contained in:
parent
7e30432b36
commit
116ec6da50
@ -337,7 +337,7 @@ if (rtc_include_tests) {
|
|||||||
"audio_conference_mixer/test/audio_conference_mixer_unittest.cc",
|
"audio_conference_mixer/test/audio_conference_mixer_unittest.cc",
|
||||||
"audio_device/fine_audio_buffer_unittest.cc",
|
"audio_device/fine_audio_buffer_unittest.cc",
|
||||||
"audio_mixer/audio_frame_manipulator_unittest.cc",
|
"audio_mixer/audio_frame_manipulator_unittest.cc",
|
||||||
"audio_mixer/test/audio_mixer_unittest.cc",
|
"audio_mixer/audio_mixer_impl_unittest.cc",
|
||||||
"audio_processing/aec/echo_cancellation_unittest.cc",
|
"audio_processing/aec/echo_cancellation_unittest.cc",
|
||||||
"audio_processing/aec/system_delay_unittest.cc",
|
"audio_processing/aec/system_delay_unittest.cc",
|
||||||
"audio_processing/agc/agc_manager_direct_unittest.cc",
|
"audio_processing/agc/agc_manager_direct_unittest.cc",
|
||||||
|
|||||||
@ -13,13 +13,13 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
#include "webrtc/base/refcount.h"
|
||||||
#include "webrtc/modules/include/module_common_types.h"
|
#include "webrtc/modules/include/module_common_types.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
class AudioMixer {
|
class AudioMixer : public rtc::RefCountInterface {
|
||||||
public:
|
public:
|
||||||
static const int kMaximumAmountOfMixedAudioSources = 3;
|
|
||||||
// A callback class that all mixer participants must inherit from/implement.
|
// A callback class that all mixer participants must inherit from/implement.
|
||||||
class Source {
|
class Source {
|
||||||
public:
|
public:
|
||||||
@ -47,16 +47,23 @@ class AudioMixer {
|
|||||||
// mixer.
|
// mixer.
|
||||||
virtual AudioFrameWithInfo GetAudioFrameWithInfo(int sample_rate_hz) = 0;
|
virtual AudioFrameWithInfo GetAudioFrameWithInfo(int sample_rate_hz) = 0;
|
||||||
|
|
||||||
|
// A way for a mixer implementation do distinguish participants.
|
||||||
|
virtual int ssrc() = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~Source() {}
|
virtual ~Source() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Factory method. Constructor disabled.
|
// Since the mixer is reference counted, the destructor may be
|
||||||
static std::unique_ptr<AudioMixer> Create();
|
// called from any thread.
|
||||||
virtual ~AudioMixer() {}
|
~AudioMixer() override {}
|
||||||
|
|
||||||
// Add/remove audio sources as candidates for mixing.
|
// Returns true if adding/removing was successful. A source is never
|
||||||
virtual int32_t SetMixabilityStatus(Source* audio_source, bool mixable) = 0;
|
// added twice and removal is never attempted if a source has not
|
||||||
|
// been successfully added to the mixer. Addition and removal can
|
||||||
|
// happen on different threads.
|
||||||
|
virtual bool AddSource(Source* audio_source) = 0;
|
||||||
|
virtual bool RemoveSource(Source* audio_source) = 0;
|
||||||
|
|
||||||
// Performs mixing by asking registered audio sources for audio. The
|
// Performs mixing by asking registered audio sources for audio. The
|
||||||
// mixed result is placed in the provided AudioFrame. Will only be
|
// mixed result is placed in the provided AudioFrame. Will only be
|
||||||
|
|||||||
@ -137,13 +137,8 @@ AudioMixerImpl::SourceStatusList::iterator FindSourceInList(
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
std::unique_ptr<AudioMixer> AudioMixer::Create() {
|
|
||||||
return AudioMixerImpl::Create();
|
|
||||||
}
|
|
||||||
|
|
||||||
AudioMixerImpl::AudioMixerImpl(std::unique_ptr<AudioProcessing> limiter)
|
AudioMixerImpl::AudioMixerImpl(std::unique_ptr<AudioProcessing> limiter)
|
||||||
: audio_source_list_(),
|
: audio_source_list_(),
|
||||||
num_mixed_audio_sources_(0),
|
|
||||||
use_limiter_(true),
|
use_limiter_(true),
|
||||||
time_stamp_(0),
|
time_stamp_(0),
|
||||||
limiter_(std::move(limiter)) {
|
limiter_(std::move(limiter)) {
|
||||||
@ -153,7 +148,7 @@ AudioMixerImpl::AudioMixerImpl(std::unique_ptr<AudioProcessing> limiter)
|
|||||||
|
|
||||||
AudioMixerImpl::~AudioMixerImpl() {}
|
AudioMixerImpl::~AudioMixerImpl() {}
|
||||||
|
|
||||||
std::unique_ptr<AudioMixerImpl> AudioMixerImpl::Create() {
|
rtc::scoped_refptr<AudioMixerImpl> AudioMixerImpl::Create() {
|
||||||
Config config;
|
Config config;
|
||||||
config.Set<ExperimentalAgc>(new ExperimentalAgc(false));
|
config.Set<ExperimentalAgc>(new ExperimentalAgc(false));
|
||||||
std::unique_ptr<AudioProcessing> limiter(AudioProcessing::Create(config));
|
std::unique_ptr<AudioProcessing> limiter(AudioProcessing::Create(config));
|
||||||
@ -186,8 +181,8 @@ std::unique_ptr<AudioMixerImpl> AudioMixerImpl::Create() {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::unique_ptr<AudioMixerImpl>(
|
return rtc::scoped_refptr<AudioMixerImpl>(
|
||||||
new AudioMixerImpl(std::move(limiter)));
|
new rtc::RefCountedObject<AudioMixerImpl>(std::move(limiter)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioMixerImpl::Mix(int sample_rate,
|
void AudioMixerImpl::Mix(int sample_rate,
|
||||||
@ -201,11 +196,9 @@ void AudioMixerImpl::Mix(int sample_rate,
|
|||||||
}
|
}
|
||||||
|
|
||||||
AudioFrameList mix_list;
|
AudioFrameList mix_list;
|
||||||
size_t num_mixed_audio_sources;
|
|
||||||
{
|
{
|
||||||
rtc::CritScope lock(&crit_);
|
rtc::CritScope lock(&crit_);
|
||||||
mix_list = GetNonAnonymousAudio();
|
mix_list = GetAudioFromSources();
|
||||||
num_mixed_audio_sources = num_mixed_audio_sources_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& frame : mix_list) {
|
for (const auto& frame : mix_list) {
|
||||||
@ -218,7 +211,7 @@ void AudioMixerImpl::Mix(int sample_rate,
|
|||||||
|
|
||||||
time_stamp_ += static_cast<uint32_t>(sample_size_);
|
time_stamp_ += static_cast<uint32_t>(sample_size_);
|
||||||
|
|
||||||
use_limiter_ = num_mixed_audio_sources > 1;
|
use_limiter_ = mix_list.size() > 1;
|
||||||
|
|
||||||
// We only use the limiter if we're actually mixing multiple streams.
|
// We only use the limiter if we're actually mixing multiple streams.
|
||||||
MixFromList(audio_frame_for_mixing, mix_list, use_limiter_);
|
MixFromList(audio_frame_for_mixing, mix_list, use_limiter_);
|
||||||
@ -246,39 +239,26 @@ int AudioMixerImpl::OutputFrequency() const {
|
|||||||
return output_frequency_;
|
return output_frequency_;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t AudioMixerImpl::SetMixabilityStatus(Source* audio_source,
|
bool AudioMixerImpl::AddSource(Source* audio_source) {
|
||||||
bool mixable) {
|
RTC_DCHECK(audio_source);
|
||||||
{
|
|
||||||
rtc::CritScope lock(&crit_);
|
rtc::CritScope lock(&crit_);
|
||||||
const bool is_mixed = FindSourceInList(audio_source, &audio_source_list_) !=
|
RTC_DCHECK(FindSourceInList(audio_source, &audio_source_list_) ==
|
||||||
audio_source_list_.end();
|
audio_source_list_.end())
|
||||||
// API must be called with a new state.
|
<< "Source already added to mixer";
|
||||||
if (!(mixable ^ is_mixed)) {
|
audio_source_list_.emplace_back(audio_source, false, 0);
|
||||||
return -1;
|
return true;
|
||||||
}
|
|
||||||
bool success = false;
|
|
||||||
if (mixable) {
|
|
||||||
success = AddAudioSourceToList(audio_source, &audio_source_list_);
|
|
||||||
} else {
|
|
||||||
success = RemoveAudioSourceFromList(audio_source, &audio_source_list_);
|
|
||||||
}
|
|
||||||
if (!success) {
|
|
||||||
RTC_NOTREACHED();
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t num_mixed_non_anonymous = audio_source_list_.size();
|
|
||||||
if (num_mixed_non_anonymous > kMaximumAmountOfMixedAudioSources) {
|
|
||||||
num_mixed_non_anonymous = kMaximumAmountOfMixedAudioSources;
|
|
||||||
}
|
|
||||||
num_mixed_audio_sources_ = num_mixed_non_anonymous;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AudioMixerImpl::RemoveSource(Source* audio_source) {
|
||||||
|
RTC_DCHECK(audio_source);
|
||||||
|
rtc::CritScope lock(&crit_);
|
||||||
|
const auto iter = FindSourceInList(audio_source, &audio_source_list_);
|
||||||
|
RTC_DCHECK(iter != audio_source_list_.end()) << "Source not present in mixer";
|
||||||
|
audio_source_list_.erase(iter);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioFrameList AudioMixerImpl::GetAudioFromSources() {
|
||||||
AudioFrameList AudioMixerImpl::GetNonAnonymousAudio() {
|
|
||||||
RTC_DCHECK_RUN_ON(&thread_checker_);
|
RTC_DCHECK_RUN_ON(&thread_checker_);
|
||||||
AudioFrameList result;
|
AudioFrameList result;
|
||||||
std::vector<SourceFrame> audio_source_mixing_data_list;
|
std::vector<SourceFrame> audio_source_mixing_data_list;
|
||||||
@ -330,24 +310,6 @@ AudioFrameList AudioMixerImpl::GetNonAnonymousAudio() {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AudioMixerImpl::AddAudioSourceToList(
|
|
||||||
Source* audio_source,
|
|
||||||
SourceStatusList* audio_source_list) const {
|
|
||||||
audio_source_list->emplace_back(audio_source, false, 0);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AudioMixerImpl::RemoveAudioSourceFromList(
|
|
||||||
Source* audio_source,
|
|
||||||
SourceStatusList* audio_source_list) const {
|
|
||||||
const auto iter = FindSourceInList(audio_source, audio_source_list);
|
|
||||||
if (iter != audio_source_list->end()) {
|
|
||||||
audio_source_list->erase(iter);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AudioMixerImpl::LimitMixedAudio(AudioFrame* mixed_audio) const {
|
bool AudioMixerImpl::LimitMixedAudio(AudioFrame* mixed_audio) const {
|
||||||
RTC_DCHECK_RUN_ON(&thread_checker_);
|
RTC_DCHECK_RUN_ON(&thread_checker_);
|
||||||
|
|||||||
@ -14,6 +14,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "webrtc/base/scoped_ref_ptr.h"
|
||||||
#include "webrtc/base/thread_annotations.h"
|
#include "webrtc/base/thread_annotations.h"
|
||||||
#include "webrtc/base/thread_checker.h"
|
#include "webrtc/base/thread_checker.h"
|
||||||
#include "webrtc/modules/audio_mixer/audio_mixer.h"
|
#include "webrtc/modules/audio_mixer/audio_mixer.h"
|
||||||
@ -41,15 +42,18 @@ class AudioMixerImpl : public AudioMixer {
|
|||||||
|
|
||||||
// AudioProcessing only accepts 10 ms frames.
|
// AudioProcessing only accepts 10 ms frames.
|
||||||
static const int kFrameDurationInMs = 10;
|
static const int kFrameDurationInMs = 10;
|
||||||
|
static const int kMaximumAmountOfMixedAudioSources = 3;
|
||||||
static const int kDefaultFrequency = 48000;
|
static const int kDefaultFrequency = 48000;
|
||||||
|
|
||||||
static std::unique_ptr<AudioMixerImpl> Create();
|
static rtc::scoped_refptr<AudioMixerImpl> Create();
|
||||||
|
|
||||||
~AudioMixerImpl() override;
|
~AudioMixerImpl() override;
|
||||||
|
|
||||||
// AudioMixer functions
|
// AudioMixer functions
|
||||||
int32_t SetMixabilityStatus(Source* audio_source, bool mixable) override;
|
bool AddSource(Source* audio_source) override;
|
||||||
void Mix(int sample_rate,
|
bool RemoveSource(Source* audio_source) override;
|
||||||
|
|
||||||
|
void Mix(int sample_rate_hz,
|
||||||
size_t number_of_channels,
|
size_t number_of_channels,
|
||||||
AudioFrame* audio_frame_for_mixing) override;
|
AudioFrame* audio_frame_for_mixing) override;
|
||||||
|
|
||||||
@ -58,9 +62,10 @@ class AudioMixerImpl : public AudioMixer {
|
|||||||
// mixer.
|
// mixer.
|
||||||
bool GetAudioSourceMixabilityStatusForTest(Source* audio_source) const;
|
bool GetAudioSourceMixabilityStatusForTest(Source* audio_source) const;
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
explicit AudioMixerImpl(std::unique_ptr<AudioProcessing> limiter);
|
explicit AudioMixerImpl(std::unique_ptr<AudioProcessing> limiter);
|
||||||
|
|
||||||
|
private:
|
||||||
// Set/get mix frequency
|
// Set/get mix frequency
|
||||||
void SetOutputFrequency(int frequency);
|
void SetOutputFrequency(int frequency);
|
||||||
int OutputFrequency() const;
|
int OutputFrequency() const;
|
||||||
@ -68,8 +73,7 @@ class AudioMixerImpl : public AudioMixer {
|
|||||||
// Compute what audio sources to mix from audio_source_list_. Ramp
|
// Compute what audio sources to mix from audio_source_list_. Ramp
|
||||||
// in and out. Update mixed status. Mixes up to
|
// in and out. Update mixed status. Mixes up to
|
||||||
// kMaximumAmountOfMixedAudioSources audio sources.
|
// kMaximumAmountOfMixedAudioSources audio sources.
|
||||||
AudioFrameList GetNonAnonymousAudio() EXCLUSIVE_LOCKS_REQUIRED(crit_);
|
AudioFrameList GetAudioFromSources() EXCLUSIVE_LOCKS_REQUIRED(crit_);
|
||||||
|
|
||||||
|
|
||||||
// Add/remove the MixerAudioSource to the specified
|
// Add/remove the MixerAudioSource to the specified
|
||||||
// MixerAudioSource list.
|
// MixerAudioSource list.
|
||||||
@ -90,7 +94,6 @@ class AudioMixerImpl : public AudioMixer {
|
|||||||
// List of all audio sources. Note all lists are disjunct
|
// List of all audio sources. Note all lists are disjunct
|
||||||
SourceStatusList audio_source_list_ GUARDED_BY(crit_); // May be mixed.
|
SourceStatusList audio_source_list_ GUARDED_BY(crit_); // May be mixed.
|
||||||
|
|
||||||
size_t num_mixed_audio_sources_ GUARDED_BY(crit_);
|
|
||||||
// Determines if we will use a limiter for clipping protection during
|
// Determines if we will use a limiter for clipping protection during
|
||||||
// mixing.
|
// mixing.
|
||||||
bool use_limiter_ ACCESS_ON(&thread_checker_);
|
bool use_limiter_ ACCESS_ON(&thread_checker_);
|
||||||
|
|||||||
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
@ -59,6 +60,8 @@ class MockMixerAudioSource : public AudioMixer::Source {
|
|||||||
|
|
||||||
MOCK_METHOD1(GetAudioFrameWithInfo, AudioFrameWithInfo(int sample_rate_hz));
|
MOCK_METHOD1(GetAudioFrameWithInfo, AudioFrameWithInfo(int sample_rate_hz));
|
||||||
|
|
||||||
|
MOCK_METHOD0(ssrc, int());
|
||||||
|
|
||||||
AudioFrame* fake_frame() { return &fake_frame_; }
|
AudioFrame* fake_frame() { return &fake_frame_; }
|
||||||
AudioFrameInfo fake_info() { return fake_audio_frame_info_; }
|
AudioFrameInfo fake_info() { return fake_audio_frame_info_; }
|
||||||
void set_fake_info(const AudioFrameInfo audio_frame_info) {
|
void set_fake_info(const AudioFrameInfo audio_frame_info) {
|
||||||
@ -87,7 +90,7 @@ void MixAndCompare(
|
|||||||
RTC_DCHECK(frames.size() == frame_info.size());
|
RTC_DCHECK(frames.size() == frame_info.size());
|
||||||
RTC_DCHECK(frame_info.size() == expected_status.size());
|
RTC_DCHECK(frame_info.size() == expected_status.size());
|
||||||
|
|
||||||
const std::unique_ptr<AudioMixerImpl> mixer(AudioMixerImpl::Create());
|
const auto mixer = AudioMixerImpl::Create();
|
||||||
std::vector<MockMixerAudioSource> participants(num_audio_sources);
|
std::vector<MockMixerAudioSource> participants(num_audio_sources);
|
||||||
|
|
||||||
for (int i = 0; i < num_audio_sources; i++) {
|
for (int i = 0; i < num_audio_sources; i++) {
|
||||||
@ -96,7 +99,7 @@ void MixAndCompare(
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < num_audio_sources; i++) {
|
for (int i = 0; i < num_audio_sources; i++) {
|
||||||
EXPECT_EQ(0, mixer->SetMixabilityStatus(&participants[i], true));
|
EXPECT_TRUE(mixer->AddSource(&participants[i]));
|
||||||
EXPECT_CALL(participants[i], GetAudioFrameWithInfo(kDefaultSampleRateHz))
|
EXPECT_CALL(participants[i], GetAudioFrameWithInfo(kDefaultSampleRateHz))
|
||||||
.Times(Exactly(1));
|
.Times(Exactly(1));
|
||||||
}
|
}
|
||||||
@ -112,9 +115,9 @@ void MixAndCompare(
|
|||||||
|
|
||||||
TEST(AudioMixer, LargestEnergyVadActiveMixed) {
|
TEST(AudioMixer, LargestEnergyVadActiveMixed) {
|
||||||
constexpr int kAudioSources =
|
constexpr int kAudioSources =
|
||||||
AudioMixer::kMaximumAmountOfMixedAudioSources + 3;
|
AudioMixerImpl::kMaximumAmountOfMixedAudioSources + 3;
|
||||||
|
|
||||||
const std::unique_ptr<AudioMixerImpl> mixer(AudioMixerImpl::Create());
|
const auto mixer = AudioMixerImpl::Create();
|
||||||
|
|
||||||
MockMixerAudioSource participants[kAudioSources];
|
MockMixerAudioSource participants[kAudioSources];
|
||||||
|
|
||||||
@ -125,7 +128,7 @@ TEST(AudioMixer, LargestEnergyVadActiveMixed) {
|
|||||||
// modified by a ramped-in window.
|
// modified by a ramped-in window.
|
||||||
participants[i].fake_frame()->data_[80] = i;
|
participants[i].fake_frame()->data_[80] = i;
|
||||||
|
|
||||||
EXPECT_EQ(0, mixer->SetMixabilityStatus(&participants[i], true));
|
EXPECT_TRUE(mixer->AddSource(&participants[i]));
|
||||||
EXPECT_CALL(participants[i], GetAudioFrameWithInfo(_)).Times(Exactly(1));
|
EXPECT_CALL(participants[i], GetAudioFrameWithInfo(_)).Times(Exactly(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,7 +146,8 @@ TEST(AudioMixer, LargestEnergyVadActiveMixed) {
|
|||||||
bool is_mixed =
|
bool is_mixed =
|
||||||
mixer->GetAudioSourceMixabilityStatusForTest(&participants[i]);
|
mixer->GetAudioSourceMixabilityStatusForTest(&participants[i]);
|
||||||
if (i == kAudioSources - 1 ||
|
if (i == kAudioSources - 1 ||
|
||||||
i < kAudioSources - 1 - AudioMixer::kMaximumAmountOfMixedAudioSources) {
|
i < kAudioSources - 1 -
|
||||||
|
AudioMixerImpl::kMaximumAmountOfMixedAudioSources) {
|
||||||
EXPECT_FALSE(is_mixed) << "Mixing status of AudioSource #" << i
|
EXPECT_FALSE(is_mixed) << "Mixing status of AudioSource #" << i
|
||||||
<< " wrong.";
|
<< " wrong.";
|
||||||
} else {
|
} else {
|
||||||
@ -154,7 +158,7 @@ TEST(AudioMixer, LargestEnergyVadActiveMixed) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(AudioMixer, FrameNotModifiedForSingleParticipant) {
|
TEST(AudioMixer, FrameNotModifiedForSingleParticipant) {
|
||||||
const std::unique_ptr<AudioMixer> mixer(AudioMixer::Create());
|
const auto mixer = AudioMixerImpl::Create();
|
||||||
|
|
||||||
MockMixerAudioSource participant;
|
MockMixerAudioSource participant;
|
||||||
|
|
||||||
@ -166,7 +170,7 @@ TEST(AudioMixer, FrameNotModifiedForSingleParticipant) {
|
|||||||
participant.fake_frame()->data_[j] = j;
|
participant.fake_frame()->data_[j] = j;
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPECT_EQ(0, mixer->SetMixabilityStatus(&participant, true));
|
EXPECT_TRUE(mixer->AddSource(&participant));
|
||||||
EXPECT_CALL(participant, GetAudioFrameWithInfo(_)).Times(Exactly(2));
|
EXPECT_CALL(participant, GetAudioFrameWithInfo(_)).Times(Exactly(2));
|
||||||
|
|
||||||
AudioFrame audio_frame;
|
AudioFrame audio_frame;
|
||||||
@ -182,12 +186,12 @@ TEST(AudioMixer, FrameNotModifiedForSingleParticipant) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(AudioMixer, ParticipantSampleRate) {
|
TEST(AudioMixer, ParticipantSampleRate) {
|
||||||
const std::unique_ptr<AudioMixer> mixer(AudioMixer::Create());
|
const auto mixer = AudioMixerImpl::Create();
|
||||||
|
|
||||||
MockMixerAudioSource participant;
|
MockMixerAudioSource participant;
|
||||||
ResetFrame(participant.fake_frame());
|
ResetFrame(participant.fake_frame());
|
||||||
|
|
||||||
EXPECT_EQ(0, mixer->SetMixabilityStatus(&participant, true));
|
EXPECT_TRUE(mixer->AddSource(&participant));
|
||||||
for (auto frequency : {8000, 16000, 32000, 48000}) {
|
for (auto frequency : {8000, 16000, 32000, 48000}) {
|
||||||
EXPECT_CALL(participant, GetAudioFrameWithInfo(frequency))
|
EXPECT_CALL(participant, GetAudioFrameWithInfo(frequency))
|
||||||
.Times(Exactly(1));
|
.Times(Exactly(1));
|
||||||
@ -199,12 +203,12 @@ TEST(AudioMixer, ParticipantSampleRate) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(AudioMixer, ParticipantNumberOfChannels) {
|
TEST(AudioMixer, ParticipantNumberOfChannels) {
|
||||||
const std::unique_ptr<AudioMixer> mixer(AudioMixer::Create());
|
const auto mixer = AudioMixerImpl::Create();
|
||||||
|
|
||||||
MockMixerAudioSource participant;
|
MockMixerAudioSource participant;
|
||||||
ResetFrame(participant.fake_frame());
|
ResetFrame(participant.fake_frame());
|
||||||
|
|
||||||
EXPECT_EQ(0, mixer->SetMixabilityStatus(&participant, true));
|
EXPECT_TRUE(mixer->AddSource(&participant));
|
||||||
for (size_t number_of_channels : {1, 2}) {
|
for (size_t number_of_channels : {1, 2}) {
|
||||||
EXPECT_CALL(participant, GetAudioFrameWithInfo(kDefaultSampleRateHz))
|
EXPECT_CALL(participant, GetAudioFrameWithInfo(kDefaultSampleRateHz))
|
||||||
.Times(Exactly(1));
|
.Times(Exactly(1));
|
||||||
@ -217,9 +221,9 @@ TEST(AudioMixer, ParticipantNumberOfChannels) {
|
|||||||
// another participant with higher energy is added.
|
// another participant with higher energy is added.
|
||||||
TEST(AudioMixer, RampedOutSourcesShouldNotBeMarkedMixed) {
|
TEST(AudioMixer, RampedOutSourcesShouldNotBeMarkedMixed) {
|
||||||
constexpr int kAudioSources =
|
constexpr int kAudioSources =
|
||||||
AudioMixer::kMaximumAmountOfMixedAudioSources + 1;
|
AudioMixerImpl::kMaximumAmountOfMixedAudioSources + 1;
|
||||||
|
|
||||||
const std::unique_ptr<AudioMixerImpl> mixer(AudioMixerImpl::Create());
|
const auto mixer = AudioMixerImpl::Create();
|
||||||
MockMixerAudioSource participants[kAudioSources];
|
MockMixerAudioSource participants[kAudioSources];
|
||||||
|
|
||||||
for (int i = 0; i < kAudioSources; i++) {
|
for (int i = 0; i < kAudioSources; i++) {
|
||||||
@ -231,7 +235,7 @@ TEST(AudioMixer, RampedOutSourcesShouldNotBeMarkedMixed) {
|
|||||||
|
|
||||||
// Add all participants but the loudest for mixing.
|
// Add all participants but the loudest for mixing.
|
||||||
for (int i = 0; i < kAudioSources - 1; i++) {
|
for (int i = 0; i < kAudioSources - 1; i++) {
|
||||||
EXPECT_EQ(0, mixer->SetMixabilityStatus(&participants[i], true));
|
EXPECT_TRUE(mixer->AddSource(&participants[i]));
|
||||||
EXPECT_CALL(participants[i], GetAudioFrameWithInfo(kDefaultSampleRateHz))
|
EXPECT_CALL(participants[i], GetAudioFrameWithInfo(kDefaultSampleRateHz))
|
||||||
.Times(Exactly(1));
|
.Times(Exactly(1));
|
||||||
}
|
}
|
||||||
@ -246,8 +250,7 @@ TEST(AudioMixer, RampedOutSourcesShouldNotBeMarkedMixed) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add new participant with higher energy.
|
// Add new participant with higher energy.
|
||||||
EXPECT_EQ(0,
|
EXPECT_TRUE(mixer->AddSource(&participants[kAudioSources - 1]));
|
||||||
mixer->SetMixabilityStatus(&participants[kAudioSources - 1], true));
|
|
||||||
for (int i = 0; i < kAudioSources; i++) {
|
for (int i = 0; i < kAudioSources; i++) {
|
||||||
EXPECT_CALL(participants[i], GetAudioFrameWithInfo(kDefaultSampleRateHz))
|
EXPECT_CALL(participants[i], GetAudioFrameWithInfo(kDefaultSampleRateHz))
|
||||||
.Times(Exactly(1));
|
.Times(Exactly(1));
|
||||||
@ -273,17 +276,16 @@ TEST(AudioMixer, ConstructFromOtherThread) {
|
|||||||
std::unique_ptr<rtc::Thread> init_thread = rtc::Thread::Create();
|
std::unique_ptr<rtc::Thread> init_thread = rtc::Thread::Create();
|
||||||
std::unique_ptr<rtc::Thread> participant_thread = rtc::Thread::Create();
|
std::unique_ptr<rtc::Thread> participant_thread = rtc::Thread::Create();
|
||||||
init_thread->Start();
|
init_thread->Start();
|
||||||
std::unique_ptr<AudioMixer> mixer(
|
const auto mixer = init_thread->Invoke<rtc::scoped_refptr<AudioMixer>>(
|
||||||
init_thread->Invoke<std::unique_ptr<AudioMixer>>(
|
RTC_FROM_HERE, &AudioMixerImpl::Create);
|
||||||
RTC_FROM_HERE, &AudioMixer::Create));
|
|
||||||
MockMixerAudioSource participant;
|
MockMixerAudioSource participant;
|
||||||
|
|
||||||
ResetFrame(participant.fake_frame());
|
ResetFrame(participant.fake_frame());
|
||||||
|
|
||||||
participant_thread->Start();
|
participant_thread->Start();
|
||||||
EXPECT_EQ(0, participant_thread->Invoke<int>(
|
EXPECT_TRUE(participant_thread->Invoke<int>(
|
||||||
RTC_FROM_HERE, rtc::Bind(&AudioMixer::SetMixabilityStatus,
|
RTC_FROM_HERE,
|
||||||
mixer.get(), &participant, true)));
|
rtc::Bind(&AudioMixer::AddSource, mixer.get(), &participant)));
|
||||||
|
|
||||||
EXPECT_CALL(participant, GetAudioFrameWithInfo(kDefaultSampleRateHz))
|
EXPECT_CALL(participant, GetAudioFrameWithInfo(kDefaultSampleRateHz))
|
||||||
.Times(Exactly(1));
|
.Times(Exactly(1));
|
||||||
@ -294,7 +296,7 @@ TEST(AudioMixer, ConstructFromOtherThread) {
|
|||||||
|
|
||||||
TEST(AudioMixer, MutedShouldMixAfterUnmuted) {
|
TEST(AudioMixer, MutedShouldMixAfterUnmuted) {
|
||||||
constexpr int kAudioSources =
|
constexpr int kAudioSources =
|
||||||
AudioMixer::kMaximumAmountOfMixedAudioSources + 1;
|
AudioMixerImpl::kMaximumAmountOfMixedAudioSources + 1;
|
||||||
|
|
||||||
std::vector<AudioFrame> frames(kAudioSources);
|
std::vector<AudioFrame> frames(kAudioSources);
|
||||||
for (auto& frame : frames) {
|
for (auto& frame : frames) {
|
||||||
@ -312,7 +314,7 @@ TEST(AudioMixer, MutedShouldMixAfterUnmuted) {
|
|||||||
|
|
||||||
TEST(AudioMixer, PassiveShouldMixAfterNormal) {
|
TEST(AudioMixer, PassiveShouldMixAfterNormal) {
|
||||||
constexpr int kAudioSources =
|
constexpr int kAudioSources =
|
||||||
AudioMixer::kMaximumAmountOfMixedAudioSources + 1;
|
AudioMixerImpl::kMaximumAmountOfMixedAudioSources + 1;
|
||||||
|
|
||||||
std::vector<AudioFrame> frames(kAudioSources);
|
std::vector<AudioFrame> frames(kAudioSources);
|
||||||
for (auto& frame : frames) {
|
for (auto& frame : frames) {
|
||||||
@ -330,7 +332,7 @@ TEST(AudioMixer, PassiveShouldMixAfterNormal) {
|
|||||||
|
|
||||||
TEST(AudioMixer, ActiveShouldMixBeforeLoud) {
|
TEST(AudioMixer, ActiveShouldMixBeforeLoud) {
|
||||||
constexpr int kAudioSources =
|
constexpr int kAudioSources =
|
||||||
AudioMixer::kMaximumAmountOfMixedAudioSources + 1;
|
AudioMixerImpl::kMaximumAmountOfMixedAudioSources + 1;
|
||||||
|
|
||||||
std::vector<AudioFrame> frames(kAudioSources);
|
std::vector<AudioFrame> frames(kAudioSources);
|
||||||
for (auto& frame : frames) {
|
for (auto& frame : frames) {
|
||||||
@ -350,7 +352,7 @@ TEST(AudioMixer, ActiveShouldMixBeforeLoud) {
|
|||||||
|
|
||||||
TEST(AudioMixer, UnmutedShouldMixBeforeLoud) {
|
TEST(AudioMixer, UnmutedShouldMixBeforeLoud) {
|
||||||
constexpr int kAudioSources =
|
constexpr int kAudioSources =
|
||||||
AudioMixer::kMaximumAmountOfMixedAudioSources + 1;
|
AudioMixerImpl::kMaximumAmountOfMixedAudioSources + 1;
|
||||||
|
|
||||||
std::vector<AudioFrame> frames(kAudioSources);
|
std::vector<AudioFrame> frames(kAudioSources);
|
||||||
for (auto& frame : frames) {
|
for (auto& frame : frames) {
|
||||||
Loading…
x
Reference in New Issue
Block a user