Move VoiceEngineObserver into AudioSendStream so that we detect typing noises and return properly in GetStats().

BUG=webrtc:4690

Review URL: https://codereview.webrtc.org/1403363003

Cr-Commit-Position: refs/heads/master@{#10548}
This commit is contained in:
solenberg 2015-11-06 15:34:49 -08:00 committed by Commit bot
parent 19299fb28b
commit 566ef247b9
27 changed files with 701 additions and 398 deletions

View File

@ -47,11 +47,10 @@ class MediaController : public webrtc::MediaControllerInterface,
RTC_DCHECK(nullptr != worker_thread);
worker_thread_->Invoke<void>(
rtc::Bind(&MediaController::Construct_w, this,
channel_manager_->media_engine()->GetVoE()));
channel_manager_->media_engine()));
}
~MediaController() override {
worker_thread_->Invoke<void>(
rtc::Bind(&MediaController::Destruct_w, this));
worker_thread_->Invoke<void>(rtc::Bind(&MediaController::Destruct_w, this));
}
webrtc::Call* call_w() override {
@ -64,10 +63,11 @@ class MediaController : public webrtc::MediaControllerInterface,
}
private:
void Construct_w(webrtc::VoiceEngine* voice_engine) {
void Construct_w(cricket::MediaEngineInterface* media_engine) {
RTC_DCHECK(worker_thread_->IsCurrent());
RTC_DCHECK(media_engine);
webrtc::Call::Config config;
config.voice_engine = voice_engine;
config.audio_state = media_engine->GetAudioState();
config.bitrate_config.min_bitrate_bps = kMinBandwidthBps;
config.bitrate_config.start_bitrate_bps = kStartBandwidthBps;
config.bitrate_config.max_bitrate_bps = kMaxBandwidthBps;
@ -84,7 +84,7 @@ class MediaController : public webrtc::MediaControllerInterface,
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(MediaController);
};
} // namespace {
} // namespace {
namespace webrtc {
@ -93,4 +93,4 @@ MediaControllerInterface* MediaControllerInterface::Create(
cricket::ChannelManager* channel_manager) {
return new MediaController(worker_thread, channel_manager);
}
} // namespace webrtc
} // namespace webrtc

View File

@ -733,7 +733,9 @@ class FakeVoiceEngine : public FakeBaseEngine {
}
bool Init(rtc::Thread* worker_thread) { return true; }
void Terminate() {}
webrtc::VoiceEngine* GetVoE() { return nullptr; }
rtc::scoped_refptr<webrtc::AudioState> GetAudioState() const {
return rtc::scoped_refptr<webrtc::AudioState>();
}
AudioOptions GetOptions() const {
return options_;
}

View File

@ -42,6 +42,7 @@
#include "talk/media/base/videocommon.h"
#include "talk/media/base/voiceprocessor.h"
#include "talk/media/devices/devicemanager.h"
#include "webrtc/audio_state.h"
#include "webrtc/base/fileutils.h"
#include "webrtc/base/sigslotrepeater.h"
@ -51,7 +52,6 @@
namespace webrtc {
class Call;
class VoiceEngine;
}
namespace cricket {
@ -72,7 +72,7 @@ class MediaEngineInterface {
// Shuts down the engine.
virtual void Terminate() = 0;
// TODO(solenberg): Remove once VoE API refactoring is done.
virtual webrtc::VoiceEngine* GetVoE() = 0;
virtual rtc::scoped_refptr<webrtc::AudioState> GetAudioState() const = 0;
// MediaChannel creation
// Creates a voice media channel. Returns NULL on failure.
@ -167,8 +167,8 @@ class CompositeMediaEngine : public MediaEngineInterface {
voice_.Terminate();
}
virtual webrtc::VoiceEngine* GetVoE() {
return voice_.GetVoE();
virtual rtc::scoped_refptr<webrtc::AudioState> GetAudioState() const {
return voice_.GetAudioState();
}
virtual VoiceMediaChannel* CreateChannel(webrtc::Call* call,
const AudioOptions& options) {

View File

@ -47,11 +47,9 @@
#include "webrtc/video_send_stream.h"
namespace cricket {
class FakeAudioSendStream : public webrtc::AudioSendStream {
class FakeAudioSendStream final : public webrtc::AudioSendStream {
public:
explicit FakeAudioSendStream(
const webrtc::AudioSendStream::Config& config);
explicit FakeAudioSendStream(const webrtc::AudioSendStream::Config& config);
const webrtc::AudioSendStream::Config& GetConfig() const;
void SetStats(const webrtc::AudioSendStream::Stats& stats);
@ -72,7 +70,7 @@ class FakeAudioSendStream : public webrtc::AudioSendStream {
webrtc::AudioSendStream::Stats stats_;
};
class FakeAudioReceiveStream : public webrtc::AudioReceiveStream {
class FakeAudioReceiveStream final : public webrtc::AudioReceiveStream {
public:
explicit FakeAudioReceiveStream(
const webrtc::AudioReceiveStream::Config& config);
@ -104,8 +102,8 @@ class FakeAudioReceiveStream : public webrtc::AudioReceiveStream {
int received_packets_;
};
class FakeVideoSendStream : public webrtc::VideoSendStream,
public webrtc::VideoCaptureInput {
class FakeVideoSendStream final : public webrtc::VideoSendStream,
public webrtc::VideoCaptureInput {
public:
FakeVideoSendStream(const webrtc::VideoSendStream::Config& config,
const webrtc::VideoEncoderConfig& encoder_config);
@ -153,7 +151,7 @@ class FakeVideoSendStream : public webrtc::VideoSendStream,
webrtc::VideoSendStream::Stats stats_;
};
class FakeVideoReceiveStream : public webrtc::VideoReceiveStream {
class FakeVideoReceiveStream final : public webrtc::VideoReceiveStream {
public:
explicit FakeVideoReceiveStream(
const webrtc::VideoReceiveStream::Config& config);
@ -188,7 +186,7 @@ class FakeVideoReceiveStream : public webrtc::VideoReceiveStream {
webrtc::VideoReceiveStream::Stats stats_;
};
class FakeCall : public webrtc::Call, public webrtc::PacketReceiver {
class FakeCall final : public webrtc::Call, public webrtc::PacketReceiver {
public:
explicit FakeCall(const webrtc::Call::Config& config);
~FakeCall() override;

View File

@ -388,14 +388,20 @@ AudioOptions GetDefaultEngineOptions() {
std::string GetEnableString(bool enable) {
return enable ? "enable" : "disable";
}
webrtc::AudioState::Config MakeAudioStateConfig(VoEWrapper* voe_wrapper) {
webrtc::AudioState::Config config;
config.voice_engine = voe_wrapper->engine();
return config;
}
} // namespace {
WebRtcVoiceEngine::WebRtcVoiceEngine()
: voe_wrapper_(new VoEWrapper()),
tracing_(new VoETraceWrapper()),
adm_(NULL),
log_filter_(SeverityToFilter(kDefaultLogSeverity)),
is_dumping_aec_(false) {
audio_state_(webrtc::AudioState::Create(MakeAudioStateConfig(voe()))),
log_filter_(SeverityToFilter(kDefaultLogSeverity)) {
Construct();
}
@ -403,25 +409,20 @@ WebRtcVoiceEngine::WebRtcVoiceEngine(VoEWrapper* voe_wrapper,
VoETraceWrapper* tracing)
: voe_wrapper_(voe_wrapper),
tracing_(tracing),
adm_(NULL),
log_filter_(SeverityToFilter(kDefaultLogSeverity)),
is_dumping_aec_(false) {
log_filter_(SeverityToFilter(kDefaultLogSeverity)) {
Construct();
}
void WebRtcVoiceEngine::Construct() {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
signal_thread_checker_.DetachFromThread();
std::memset(&default_agc_config_, 0, sizeof(default_agc_config_));
SetTraceFilter(log_filter_);
initialized_ = false;
LOG(LS_VERBOSE) << "WebRtcVoiceEngine::WebRtcVoiceEngine";
SetTraceOptions("");
if (tracing_->SetTraceCallback(this) == -1) {
LOG_RTCERR0(SetTraceCallback);
}
if (voe_wrapper_->base()->RegisterVoiceEngineObserver(*this) == -1) {
LOG_RTCERR0(RegisterVoiceEngineObserver);
}
// Clear the default agc state.
memset(&default_agc_config_, 0, sizeof(default_agc_config_));
// Load our audio codec list.
ConstructCodecs();
@ -442,6 +443,7 @@ void WebRtcVoiceEngine::Construct() {
}
void WebRtcVoiceEngine::ConstructCodecs() {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
LOG(LS_INFO) << "WebRtc VoiceEngine codecs:";
int ncodecs = voe_wrapper_->codec()->NumOfCodecs();
for (int i = 0; i < ncodecs; ++i) {
@ -499,6 +501,7 @@ void WebRtcVoiceEngine::ConstructCodecs() {
}
bool WebRtcVoiceEngine::GetVoeCodec(int index, webrtc::CodecInst* codec) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
if (voe_wrapper_->codec()->GetCodec(index, *codec) == -1) {
return false;
}
@ -508,10 +511,8 @@ bool WebRtcVoiceEngine::GetVoeCodec(int index, webrtc::CodecInst* codec) {
}
WebRtcVoiceEngine::~WebRtcVoiceEngine() {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
LOG(LS_VERBOSE) << "WebRtcVoiceEngine::~WebRtcVoiceEngine";
if (voe_wrapper_->base()->DeRegisterVoiceEngineObserver() == -1) {
LOG_RTCERR0(DeRegisterVoiceEngineObserver);
}
if (adm_) {
voe_wrapper_.reset();
adm_->Release();
@ -522,6 +523,7 @@ WebRtcVoiceEngine::~WebRtcVoiceEngine() {
}
bool WebRtcVoiceEngine::Init(rtc::Thread* worker_thread) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
RTC_DCHECK(worker_thread == rtc::Thread::Current());
LOG(LS_INFO) << "WebRtcVoiceEngine::Init";
bool res = InitInternal();
@ -535,6 +537,7 @@ bool WebRtcVoiceEngine::Init(rtc::Thread* worker_thread) {
}
bool WebRtcVoiceEngine::InitInternal() {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
// Temporarily turn logging level up for the Init call
int old_filter = log_filter_;
int extended_filter = log_filter_ | SeverityToFilter(rtc::LS_INFO);
@ -588,6 +591,7 @@ bool WebRtcVoiceEngine::InitInternal() {
}
void WebRtcVoiceEngine::Terminate() {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
LOG(LS_INFO) << "WebRtcVoiceEngine::Terminate";
initialized_ = false;
@ -596,12 +600,20 @@ void WebRtcVoiceEngine::Terminate() {
voe_wrapper_->base()->Terminate();
}
rtc::scoped_refptr<webrtc::AudioState>
WebRtcVoiceEngine::GetAudioState() const {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
return audio_state_;
}
VoiceMediaChannel* WebRtcVoiceEngine::CreateChannel(webrtc::Call* call,
const AudioOptions& options) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
return new WebRtcVoiceMediaChannel(this, options, call);
}
bool WebRtcVoiceEngine::SetOptions(const AudioOptions& options) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
if (!ApplyOptions(options)) {
return false;
}
@ -612,6 +624,7 @@ bool WebRtcVoiceEngine::SetOptions(const AudioOptions& options) {
// AudioOptions defaults are set in InitInternal (for options with corresponding
// MediaEngineInterface flags) and in SetOptions(int) for flagless options.
bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
LOG(LS_INFO) << "ApplyOptions: " << options_in.ToString();
AudioOptions options = options_in; // The options are modified below.
// kEcConference is AEC with high suppression.
@ -887,6 +900,7 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
// soundclip device. At that time, reinstate the soundclip pause/resume code.
bool WebRtcVoiceEngine::SetDevices(const Device* in_device,
const Device* out_device) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
#if !defined(IOS)
int in_id = in_device ? rtc::FromString<int>(in_device->id) :
kDefaultAudioDeviceId;
@ -976,6 +990,7 @@ bool WebRtcVoiceEngine::SetDevices(const Device* in_device,
bool WebRtcVoiceEngine::FindWebRtcAudioDeviceId(
bool is_input, const std::string& dev_name, int dev_id, int* rtc_id) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
// In Linux, VoiceEngine uses the same device dev_id as the device manager.
#if defined(LINUX) || defined(ANDROID)
*rtc_id = dev_id;
@ -1025,6 +1040,7 @@ bool WebRtcVoiceEngine::FindWebRtcAudioDeviceId(
}
bool WebRtcVoiceEngine::GetOutputVolume(int* level) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
unsigned int ulevel;
if (voe_wrapper_->volume()->GetSpeakerVolume(ulevel) == -1) {
LOG_RTCERR1(GetSpeakerVolume, level);
@ -1035,6 +1051,7 @@ bool WebRtcVoiceEngine::GetOutputVolume(int* level) {
}
bool WebRtcVoiceEngine::SetOutputVolume(int level) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
RTC_DCHECK(level >= 0 && level <= 255);
if (voe_wrapper_->volume()->SetSpeakerVolume(level) == -1) {
LOG_RTCERR1(SetSpeakerVolume, level);
@ -1044,22 +1061,26 @@ bool WebRtcVoiceEngine::SetOutputVolume(int level) {
}
int WebRtcVoiceEngine::GetInputLevel() {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
unsigned int ulevel;
return (voe_wrapper_->volume()->GetSpeechInputLevel(ulevel) != -1) ?
static_cast<int>(ulevel) : -1;
}
const std::vector<AudioCodec>& WebRtcVoiceEngine::codecs() {
RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
return codecs_;
}
bool WebRtcVoiceEngine::FindCodec(const AudioCodec& in) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
return FindWebRtcCodec(in, NULL);
}
// Get the VoiceEngine codec that matches |in|, with the supplied settings.
bool WebRtcVoiceEngine::FindWebRtcCodec(const AudioCodec& in,
webrtc::CodecInst* out) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
int ncodecs = voe_wrapper_->codec()->NumOfCodecs();
for (int i = 0; i < ncodecs; ++i) {
webrtc::CodecInst voe_codec;
@ -1101,10 +1122,12 @@ bool WebRtcVoiceEngine::FindWebRtcCodec(const AudioCodec& in,
}
const std::vector<RtpHeaderExtension>&
WebRtcVoiceEngine::rtp_header_extensions() const {
RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
return rtp_header_extensions_;
}
void WebRtcVoiceEngine::SetLogging(int min_sev, const char* filter) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
// if min_sev == -1, we keep the current log level.
if (min_sev >= 0) {
SetTraceFilter(SeverityToFilter(min_sev));
@ -1114,10 +1137,12 @@ void WebRtcVoiceEngine::SetLogging(int min_sev, const char* filter) {
}
int WebRtcVoiceEngine::GetLastEngineError() {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
return voe_wrapper_->error();
}
void WebRtcVoiceEngine::SetTraceFilter(int filter) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
log_filter_ = filter;
tracing_->SetTraceFilter(filter);
}
@ -1135,6 +1160,7 @@ void WebRtcVoiceEngine::SetTraceFilter(int filter) {
// For more details see: "https://sites.google.com/a/google.com/wavelet/Home/
// Magic-Flute--RTC-Engine-/Magic-Flute-Command-Line-Parameters"
void WebRtcVoiceEngine::SetTraceOptions(const std::string& options) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
// Set encrypted trace file.
std::vector<std::string> opts;
rtc::tokenize(options, ' ', '"', '"', &opts);
@ -1174,6 +1200,7 @@ void WebRtcVoiceEngine::SetTraceOptions(const std::string& options) {
void WebRtcVoiceEngine::Print(webrtc::TraceLevel level, const char* trace,
int length) {
// Note: This callback can happen on any thread!
rtc::LoggingSeverity sev = rtc::LS_VERBOSE;
if (level == webrtc::kTraceError || level == webrtc::kTraceCritical)
sev = rtc::LS_ERROR;
@ -1195,34 +1222,24 @@ void WebRtcVoiceEngine::Print(webrtc::TraceLevel level, const char* trace,
}
}
void WebRtcVoiceEngine::CallbackOnError(int channel_id, int err_code) {
RTC_DCHECK(channel_id == -1);
LOG(LS_WARNING) << "VoiceEngine error " << err_code << " reported on channel "
<< channel_id << ".";
rtc::CritScope lock(&channels_cs_);
for (WebRtcVoiceMediaChannel* channel : channels_) {
channel->OnError(err_code);
}
}
void WebRtcVoiceEngine::RegisterChannel(WebRtcVoiceMediaChannel* channel) {
RTC_DCHECK(channel != NULL);
rtc::CritScope lock(&channels_cs_);
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
RTC_DCHECK(channel);
channels_.push_back(channel);
}
void WebRtcVoiceEngine::UnregisterChannel(WebRtcVoiceMediaChannel* channel) {
rtc::CritScope lock(&channels_cs_);
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
auto it = std::find(channels_.begin(), channels_.end(), channel);
if (it != channels_.end()) {
channels_.erase(it);
}
RTC_DCHECK(it != channels_.end());
channels_.erase(it);
}
// Adjusts the default AGC target level by the specified delta.
// NB: If we start messing with other config fields, we'll want
// to save the current webrtc::AgcConfig as well.
bool WebRtcVoiceEngine::AdjustAgcLevel(int delta) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
webrtc::AgcConfig config = default_agc_config_;
config.targetLeveldBOv -= delta;
@ -1238,6 +1255,7 @@ bool WebRtcVoiceEngine::AdjustAgcLevel(int delta) {
}
bool WebRtcVoiceEngine::SetAudioDeviceModule(webrtc::AudioDeviceModule* adm) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
if (initialized_) {
LOG(LS_WARNING) << "SetAudioDeviceModule can not be called after Init.";
return false;
@ -1254,6 +1272,7 @@ bool WebRtcVoiceEngine::SetAudioDeviceModule(webrtc::AudioDeviceModule* adm) {
}
bool WebRtcVoiceEngine::StartAecDump(rtc::PlatformFile file) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
FILE* aec_dump_file_stream = rtc::FdopenPlatformFileForWriting(file);
if (!aec_dump_file_stream) {
LOG(LS_ERROR) << "Could not open AEC dump file stream.";
@ -1273,6 +1292,7 @@ bool WebRtcVoiceEngine::StartAecDump(rtc::PlatformFile file) {
}
void WebRtcVoiceEngine::StartAecDump(const std::string& filename) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
if (!is_dumping_aec_) {
// Start dumping AEC when we are not dumping.
if (voe_wrapper_->processing()->StartDebugRecording(
@ -1285,6 +1305,7 @@ void WebRtcVoiceEngine::StartAecDump(const std::string& filename) {
}
void WebRtcVoiceEngine::StopAecDump() {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
if (is_dumping_aec_) {
// Stop dumping AEC when we are dumping.
if (voe_wrapper_->processing()->StopDebugRecording() !=
@ -1296,14 +1317,17 @@ void WebRtcVoiceEngine::StopAecDump() {
}
bool WebRtcVoiceEngine::StartRtcEventLog(rtc::PlatformFile file) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
return voe_wrapper_->codec()->GetEventLog()->StartLogging(file);
}
void WebRtcVoiceEngine::StopRtcEventLog() {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
voe_wrapper_->codec()->GetEventLog()->StopLogging();
}
int WebRtcVoiceEngine::CreateVoEChannel() {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
return voe_wrapper_->base()->CreateChannel(voe_config_);
}
@ -1327,7 +1351,7 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
RTC_DCHECK(stream_);
}
~WebRtcAudioSendStream() override {
RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Stop();
call_->DestroyAudioSendStream(stream_);
}
@ -1337,7 +1361,7 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
// This method is called on the libjingle worker thread.
// TODO(xians): Make sure Start() is called only once.
void Start(AudioRenderer* renderer) {
RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
RTC_DCHECK(renderer);
if (renderer_) {
RTC_DCHECK(renderer_ == renderer);
@ -1348,7 +1372,7 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
}
webrtc::AudioSendStream::Stats GetStats() const {
RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
return stream_->GetStats();
}
@ -1356,7 +1380,7 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
// callback will be received after this method.
// This method is called on the libjingle worker thread.
void Stop() {
RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
if (renderer_) {
renderer_->SetSink(nullptr);
renderer_ = nullptr;
@ -1370,6 +1394,7 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
int sample_rate,
int number_of_channels,
size_t number_of_frames) override {
RTC_DCHECK(!worker_thread_checker_.CalledOnValidThread());
RTC_DCHECK(audio_capture_thread_checker_.CalledOnValidThread());
RTC_DCHECK(voe_audio_transport_);
voe_audio_transport_->OnData(channel_,
@ -1383,7 +1408,7 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
// Callback from the |renderer_| when it is going away. In case Start() has
// never been called, this callback won't be triggered.
void OnClose() override {
RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
// Set |renderer_| to nullptr to make sure no more callback will get into
// the renderer.
renderer_ = nullptr;
@ -1391,12 +1416,12 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
// Accessor to the VoE channel ID.
int channel() const {
RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
return channel_;
}
private:
rtc::ThreadChecker signal_thread_checker_;
rtc::ThreadChecker worker_thread_checker_;
rtc::ThreadChecker audio_capture_thread_checker_;
const int channel_ = -1;
webrtc::AudioTransport* const voe_audio_transport_ = nullptr;
@ -1428,26 +1453,15 @@ class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream {
WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel(WebRtcVoiceEngine* engine,
const AudioOptions& options,
webrtc::Call* call)
: engine_(engine),
send_bitrate_setting_(false),
send_bitrate_bps_(0),
options_(),
dtmf_allowed_(false),
desired_playout_(false),
nack_enabled_(false),
playout_(false),
typing_noise_detected_(false),
desired_send_(SEND_NOTHING),
send_(SEND_NOTHING),
call_(call) {
: engine_(engine), call_(call) {
LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel";
RTC_DCHECK(nullptr != call);
RTC_DCHECK(call);
engine->RegisterChannel(this);
SetOptions(options);
}
WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel() {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel";
// Remove any remaining send streams.
@ -1467,7 +1481,7 @@ WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel() {
bool WebRtcVoiceMediaChannel::SetSendParameters(
const AudioSendParameters& params) {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
// TODO(pthatcher): Refactor this to be more clean now that we have
// all the information at once.
return (SetSendCodecs(params.codecs) &&
@ -1478,7 +1492,7 @@ bool WebRtcVoiceMediaChannel::SetSendParameters(
bool WebRtcVoiceMediaChannel::SetRecvParameters(
const AudioRecvParameters& params) {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
// TODO(pthatcher): Refactor this to be more clean now that we have
// all the information at once.
return (SetRecvCodecs(params.codecs) &&
@ -1486,7 +1500,7 @@ bool WebRtcVoiceMediaChannel::SetRecvParameters(
}
bool WebRtcVoiceMediaChannel::SetOptions(const AudioOptions& options) {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
LOG(LS_INFO) << "Setting voice channel options: "
<< options.ToString();
@ -1525,7 +1539,7 @@ bool WebRtcVoiceMediaChannel::SetOptions(const AudioOptions& options) {
bool WebRtcVoiceMediaChannel::SetRecvCodecs(
const std::vector<AudioCodec>& codecs) {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
// Set the payload types to be used for incoming media.
LOG(LS_INFO) << "Setting receive voice codecs.";
@ -1783,7 +1797,7 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs(
bool WebRtcVoiceMediaChannel::SetSendCodecs(
const std::vector<AudioCodec>& codecs) {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
dtmf_allowed_ = false;
for (const AudioCodec& codec : codecs) {
@ -1840,7 +1854,7 @@ bool WebRtcVoiceMediaChannel::SetSendCodec(
bool WebRtcVoiceMediaChannel::SetRecvRtpHeaderExtensions(
const std::vector<RtpHeaderExtension>& extensions) {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
if (receive_extensions_ == extensions) {
return true;
}
@ -1901,7 +1915,7 @@ bool WebRtcVoiceMediaChannel::SetChannelRecvRtpHeaderExtensions(
bool WebRtcVoiceMediaChannel::SetSendRtpHeaderExtensions(
const std::vector<RtpHeaderExtension>& extensions) {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
if (send_extensions_ == extensions) {
return true;
}
@ -1952,7 +1966,7 @@ bool WebRtcVoiceMediaChannel::ResumePlayout() {
}
bool WebRtcVoiceMediaChannel::ChangePlayout(bool playout) {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
if (playout_ == playout) {
return true;
}
@ -2033,7 +2047,7 @@ bool WebRtcVoiceMediaChannel::SetAudioSend(uint32_t ssrc,
bool enable,
const AudioOptions* options,
AudioRenderer* renderer) {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
// TODO(solenberg): The state change should be fully rolled back if any one of
// these calls fail.
if (!SetLocalRenderer(ssrc, renderer)) {
@ -2074,7 +2088,7 @@ bool WebRtcVoiceMediaChannel::DeleteChannel(int channel) {
}
bool WebRtcVoiceMediaChannel::AddSendStream(const StreamParams& sp) {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
LOG(LS_INFO) << "AddSendStream: " << sp.ToString();
uint32_t ssrc = sp.first_ssrc();
@ -2148,7 +2162,7 @@ bool WebRtcVoiceMediaChannel::AddSendStream(const StreamParams& sp) {
}
bool WebRtcVoiceMediaChannel::RemoveSendStream(uint32_t ssrc) {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
auto it = send_streams_.find(ssrc);
if (it == send_streams_.end()) {
LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc
@ -2177,7 +2191,7 @@ bool WebRtcVoiceMediaChannel::RemoveSendStream(uint32_t ssrc) {
}
bool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
LOG(LS_INFO) << "AddRecvStream: " << sp.ToString();
if (!ValidateStreamParams(sp)) {
@ -2224,7 +2238,7 @@ bool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) {
}
bool WebRtcVoiceMediaChannel::ConfigureRecvChannel(int channel) {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
int send_channel = GetSendChannelId(receiver_reports_ssrc_);
if (send_channel != -1) {
@ -2279,7 +2293,7 @@ bool WebRtcVoiceMediaChannel::ConfigureRecvChannel(int channel) {
}
bool WebRtcVoiceMediaChannel::RemoveRecvStream(uint32_t ssrc) {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
LOG(LS_INFO) << "RemoveRecvStream: " << ssrc;
auto it = receive_channels_.find(ssrc);
@ -2331,7 +2345,7 @@ bool WebRtcVoiceMediaChannel::SetLocalRenderer(uint32_t ssrc,
bool WebRtcVoiceMediaChannel::GetActiveStreams(
AudioInfo::StreamList* actives) {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
actives->clear();
for (const auto& ch : receive_channels_) {
int level = GetOutputLevel(ch.second->channel());
@ -2343,7 +2357,7 @@ bool WebRtcVoiceMediaChannel::GetActiveStreams(
}
int WebRtcVoiceMediaChannel::GetOutputLevel() {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
int highest = 0;
for (const auto& ch : receive_channels_) {
highest = std::max(GetOutputLevel(ch.second->channel()), highest);
@ -2377,7 +2391,7 @@ void WebRtcVoiceMediaChannel::SetTypingDetectionParameters(int time_window,
}
bool WebRtcVoiceMediaChannel::SetOutputVolume(uint32_t ssrc, double volume) {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
if (ssrc == 0) {
default_recv_volume_ = volume;
if (default_recv_ssrc_ == -1) {
@ -2409,7 +2423,7 @@ bool WebRtcVoiceMediaChannel::InsertDtmf(uint32_t ssrc,
int event,
int duration,
int flags) {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
if (!dtmf_allowed_) {
return false;
}
@ -2451,7 +2465,7 @@ bool WebRtcVoiceMediaChannel::InsertDtmf(uint32_t ssrc,
void WebRtcVoiceMediaChannel::OnPacketReceived(
rtc::Buffer* packet, const rtc::PacketTime& packet_time) {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
uint32_t ssrc = 0;
if (!GetRtpSsrc(packet->data(), packet->size(), &ssrc)) {
@ -2494,7 +2508,7 @@ void WebRtcVoiceMediaChannel::OnPacketReceived(
void WebRtcVoiceMediaChannel::OnRtcpReceived(
rtc::Buffer* packet, const rtc::PacketTime& packet_time) {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
// Forward packet to Call as well.
const webrtc::PacketTime webrtc_packet_time(packet_time.timestamp,
@ -2536,7 +2550,7 @@ void WebRtcVoiceMediaChannel::OnRtcpReceived(
}
bool WebRtcVoiceMediaChannel::MuteStream(uint32_t ssrc, bool muted) {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
int channel = GetSendChannelId(ssrc);
if (channel == -1) {
LOG(LS_WARNING) << "The specified ssrc " << ssrc << " is not in use.";
@ -2623,7 +2637,7 @@ bool WebRtcVoiceMediaChannel::SetSendBitrateInternal(int bps) {
}
bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
RTC_DCHECK(info);
// Get SSRC and stats for each sender.
@ -2646,9 +2660,8 @@ bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) {
sinfo.echo_delay_std_ms = stats.echo_delay_std_ms;
sinfo.echo_return_loss = stats.echo_return_loss;
sinfo.echo_return_loss_enhancement = stats.echo_return_loss_enhancement;
sinfo.typing_noise_detected = typing_noise_detected_;
// TODO(solenberg): Move to AudioSendStream.
// sinfo.typing_noise_detected = stats.typing_noise_detected;
sinfo.typing_noise_detected =
(send_ == SEND_NOTHING ? false : stats.typing_noise_detected);
info->senders.push_back(sinfo);
}
@ -2688,17 +2701,6 @@ bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) {
return true;
}
void WebRtcVoiceMediaChannel::OnError(int error) {
if (send_ == SEND_NOTHING) {
return;
}
if (error == VE_TYPING_NOISE_WARNING) {
typing_noise_detected_ = true;
} else if (error == VE_TYPING_NOISE_OFF_WARNING) {
typing_noise_detected_ = false;
}
}
int WebRtcVoiceMediaChannel::GetOutputLevel(int channel) {
unsigned int ulevel = 0;
int ret = engine()->voe()->volume()->GetSpeechOutputLevel(channel, ulevel);
@ -2706,7 +2708,7 @@ int WebRtcVoiceMediaChannel::GetOutputLevel(int channel) {
}
int WebRtcVoiceMediaChannel::GetReceiveChannelId(uint32_t ssrc) const {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
const auto it = receive_channels_.find(ssrc);
if (it != receive_channels_.end()) {
return it->second->channel();
@ -2715,7 +2717,7 @@ int WebRtcVoiceMediaChannel::GetReceiveChannelId(uint32_t ssrc) const {
}
int WebRtcVoiceMediaChannel::GetSendChannelId(uint32_t ssrc) const {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
const auto it = send_streams_.find(ssrc);
if (it != send_streams_.end()) {
return it->second->channel();
@ -2781,39 +2783,6 @@ bool WebRtcVoiceMediaChannel::SetPlayout(int channel, bool playout) {
return true;
}
// Convert VoiceEngine error code into VoiceMediaChannel::Error enum.
VoiceMediaChannel::Error
WebRtcVoiceMediaChannel::WebRtcErrorToChannelError(int err_code) {
switch (err_code) {
case 0:
return ERROR_NONE;
case VE_CANNOT_START_RECORDING:
case VE_MIC_VOL_ERROR:
case VE_GET_MIC_VOL_ERROR:
case VE_CANNOT_ACCESS_MIC_VOL:
return ERROR_REC_DEVICE_OPEN_FAILED;
case VE_SATURATION_WARNING:
return ERROR_REC_DEVICE_SATURATION;
case VE_REC_DEVICE_REMOVED:
return ERROR_REC_DEVICE_REMOVED;
case VE_RUNTIME_REC_WARNING:
case VE_RUNTIME_REC_ERROR:
return ERROR_REC_RUNTIME_ERROR;
case VE_CANNOT_START_PLAYOUT:
case VE_SPEAKER_VOL_ERROR:
case VE_GET_SPEAKER_VOL_ERROR:
case VE_CANNOT_ACCESS_SPEAKER_VOL:
return ERROR_PLAY_DEVICE_OPEN_FAILED;
case VE_RUNTIME_PLAY_WARNING:
case VE_RUNTIME_PLAY_ERROR:
return ERROR_PLAY_RUNTIME_ERROR;
case VE_TYPING_NOISE_WARNING:
return ERROR_REC_TYPING_NOISE_DETECTED;
default:
return VoiceMediaChannel::ERROR_OTHER;
}
}
bool WebRtcVoiceMediaChannel::SetHeaderExtension(ExtensionSetterFunction setter,
int channel_id, const RtpHeaderExtension* extension) {
bool enable = false;
@ -2832,7 +2801,7 @@ bool WebRtcVoiceMediaChannel::SetHeaderExtension(ExtensionSetterFunction setter,
}
void WebRtcVoiceMediaChannel::RecreateAudioReceiveStreams() {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
for (const auto& it : receive_channels_) {
RemoveAudioReceiveStream(it.first);
}
@ -2842,7 +2811,7 @@ void WebRtcVoiceMediaChannel::RecreateAudioReceiveStreams() {
}
void WebRtcVoiceMediaChannel::AddAudioReceiveStream(uint32_t ssrc) {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
WebRtcAudioReceiveStream* stream = receive_channels_[ssrc];
RTC_DCHECK(stream != nullptr);
RTC_DCHECK(receive_streams_.find(ssrc) == receive_streams_.end());
@ -2859,7 +2828,7 @@ void WebRtcVoiceMediaChannel::AddAudioReceiveStream(uint32_t ssrc) {
}
void WebRtcVoiceMediaChannel::RemoveAudioReceiveStream(uint32_t ssrc) {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
auto stream_it = receive_streams_.find(ssrc);
if (stream_it != receive_streams_.end()) {
call_->DestroyAudioReceiveStream(stream_it->second);
@ -2869,7 +2838,7 @@ void WebRtcVoiceMediaChannel::RemoveAudioReceiveStream(uint32_t ssrc) {
bool WebRtcVoiceMediaChannel::SetRecvCodecsInternal(
const std::vector<AudioCodec>& new_codecs) {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
for (const AudioCodec& codec : new_codecs) {
webrtc::CodecInst voe_codec;
if (engine()->FindWebRtcCodec(codec, &voe_codec)) {

View File

@ -37,6 +37,7 @@
#include "talk/media/webrtc/webrtccommon.h"
#include "talk/media/webrtc/webrtcvoe.h"
#include "talk/session/media/channel.h"
#include "webrtc/audio_state.h"
#include "webrtc/base/buffer.h"
#include "webrtc/base/byteorder.h"
#include "webrtc/base/logging.h"
@ -57,9 +58,7 @@ class WebRtcVoiceMediaChannel;
// WebRtcVoiceEngine is a class to be used with CompositeMediaEngine.
// It uses the WebRtc VoiceEngine library for audio handling.
class WebRtcVoiceEngine
: public webrtc::VoiceEngineObserver,
public webrtc::TraceCallback {
class WebRtcVoiceEngine final : public webrtc::TraceCallback {
friend class WebRtcVoiceMediaChannel;
public:
@ -70,7 +69,7 @@ class WebRtcVoiceEngine
bool Init(rtc::Thread* worker_thread);
void Terminate();
webrtc::VoiceEngine* GetVoE() { return voe()->engine(); }
rtc::scoped_refptr<webrtc::AudioState> GetAudioState() const;
VoiceMediaChannel* CreateChannel(webrtc::Call* call,
const AudioOptions& options);
@ -133,9 +132,6 @@ class WebRtcVoiceEngine
// webrtc::TraceCallback:
void Print(webrtc::TraceLevel level, const char* trace, int length) override;
// webrtc::VoiceEngineObserver:
void CallbackOnError(int channel_id, int errCode) override;
// Given the device type, name, and id, find device id. Return true and
// set the output parameter rtc_id if successful.
bool FindWebRtcAudioDeviceId(
@ -146,25 +142,26 @@ class WebRtcVoiceEngine
static const int kDefaultLogSeverity = rtc::LS_WARNING;
rtc::ThreadChecker signal_thread_checker_;
rtc::ThreadChecker worker_thread_checker_;
// The primary instance of WebRtc VoiceEngine.
rtc::scoped_ptr<VoEWrapper> voe_wrapper_;
rtc::scoped_ptr<VoETraceWrapper> tracing_;
rtc::scoped_refptr<webrtc::AudioState> audio_state_;
// The external audio device manager
webrtc::AudioDeviceModule* adm_;
webrtc::AudioDeviceModule* adm_ = nullptr;
int log_filter_;
std::string log_options_;
bool is_dumping_aec_;
bool is_dumping_aec_ = false;
std::vector<AudioCodec> codecs_;
std::vector<RtpHeaderExtension> rtp_header_extensions_;
std::vector<WebRtcVoiceMediaChannel*> channels_;
// channels_ can be read from WebRtc callback thread. We need a lock on that
// callback as well as the RegisterChannel/UnregisterChannel.
rtc::CriticalSection channels_cs_;
webrtc::AgcConfig default_agc_config_;
webrtc::Config voe_config_;
bool initialized_;
bool initialized_ = false;
AudioOptions options_;
// Cache received extended_filter_aec, delay_agnostic_aec and experimental_ns
@ -180,8 +177,8 @@ class WebRtcVoiceEngine
// WebRtcVoiceMediaChannel is an implementation of VoiceMediaChannel that uses
// WebRtc Voice Engine.
class WebRtcVoiceMediaChannel : public VoiceMediaChannel,
public webrtc::Transport {
class WebRtcVoiceMediaChannel final : public VoiceMediaChannel,
public webrtc::Transport {
public:
WebRtcVoiceMediaChannel(WebRtcVoiceEngine* engine,
const AudioOptions& options,
@ -243,8 +240,6 @@ class WebRtcVoiceMediaChannel : public VoiceMediaChannel,
return VoiceMediaChannel::SendRtcp(&packet, rtc::PacketOptions());
}
void OnError(int error);
int GetReceiveChannelId(uint32_t ssrc) const;
int GetSendChannelId(uint32_t ssrc) const;
@ -267,7 +262,6 @@ class WebRtcVoiceMediaChannel : public VoiceMediaChannel,
const std::vector<AudioCodec>& all_codecs,
webrtc::CodecInst* send_codec);
bool SetPlayout(int channel, bool playout);
static Error WebRtcErrorToChannelError(int err_code);
typedef int (webrtc::VoERTP_RTCP::* ExtensionSetterFunction)(int, bool,
unsigned char);
@ -300,23 +294,22 @@ class WebRtcVoiceMediaChannel : public VoiceMediaChannel,
int channel_id,
const std::vector<RtpHeaderExtension>& extensions);
rtc::ThreadChecker thread_checker_;
rtc::ThreadChecker worker_thread_checker_;
WebRtcVoiceEngine* const engine_;
WebRtcVoiceEngine* const engine_ = nullptr;
std::vector<AudioCodec> recv_codecs_;
std::vector<AudioCodec> send_codecs_;
rtc::scoped_ptr<webrtc::CodecInst> send_codec_;
bool send_bitrate_setting_;
int send_bitrate_bps_;
bool send_bitrate_setting_ = false;
int send_bitrate_bps_ = 0;
AudioOptions options_;
bool dtmf_allowed_;
bool desired_playout_;
bool nack_enabled_;
bool playout_;
bool typing_noise_detected_;
SendFlags desired_send_;
SendFlags send_;
webrtc::Call* const call_;
bool dtmf_allowed_ = false;
bool desired_playout_ = false;
bool nack_enabled_ = false;
bool playout_ = false;
SendFlags desired_send_ = SEND_NOTHING;
SendFlags send_ = SEND_NOTHING;
webrtc::Call* const call_ = nullptr;
// SSRC of unsignalled receive stream, or -1 if there isn't one.
int64_t default_recv_ssrc_ = -1;
@ -342,7 +335,6 @@ class WebRtcVoiceMediaChannel : public VoiceMediaChannel,
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcVoiceMediaChannel);
};
} // namespace cricket
#endif // TALK_MEDIA_WEBRTCVOICEENGINE_H_

View File

@ -313,7 +313,8 @@ class WebRtcVoiceEngineTestFake : public testing::Test {
s->SetStats(GetAudioSendStreamStats());
}
}
void VerifyVoiceSenderInfo(const cricket::VoiceSenderInfo& info) {
void VerifyVoiceSenderInfo(const cricket::VoiceSenderInfo& info,
bool is_sending) {
const auto stats = GetAudioSendStreamStats();
EXPECT_EQ(info.ssrc(), stats.local_ssrc);
EXPECT_EQ(info.bytes_sent, stats.bytes_sent);
@ -331,8 +332,8 @@ class WebRtcVoiceEngineTestFake : public testing::Test {
EXPECT_EQ(info.echo_return_loss, stats.echo_return_loss);
EXPECT_EQ(info.echo_return_loss_enhancement,
stats.echo_return_loss_enhancement);
// TODO(solenberg): Move typing noise detection into AudioSendStream.
// EXPECT_EQ(info.typing_noise_detected, stats.typing_noise_detected);
EXPECT_EQ(info.typing_noise_detected,
stats.typing_noise_detected && is_sending);
}
webrtc::AudioReceiveStream::Stats GetAudioReceiveStreamStats() const {
@ -2089,7 +2090,7 @@ TEST_F(WebRtcVoiceEngineTestFake, GetStatsWithMultipleSendStreams) {
// We have added 4 send streams. We should see empty stats for all.
EXPECT_EQ(static_cast<size_t>(ARRAY_SIZE(kSsrcs4)), info.senders.size());
for (const auto& sender : info.senders) {
VerifyVoiceSenderInfo(sender);
VerifyVoiceSenderInfo(sender, false);
}
// We have added one receive stream. We should see empty stats.
@ -2359,12 +2360,20 @@ TEST_F(WebRtcVoiceEngineTestFake, GetStats) {
// We have added one send stream. We should see the stats we've set.
EXPECT_EQ(1u, info.senders.size());
VerifyVoiceSenderInfo(info.senders[0]);
VerifyVoiceSenderInfo(info.senders[0], false);
// We have added one receive stream. We should see empty stats.
EXPECT_EQ(info.receivers.size(), 1u);
EXPECT_EQ(info.receivers[0].ssrc(), 0);
}
// Start sending - this affects some reported stats.
{
cricket::VoiceMediaInfo info;
EXPECT_TRUE(channel_->SetSend(cricket::SEND_MICROPHONE));
EXPECT_EQ(true, channel_->GetStats(&info));
VerifyVoiceSenderInfo(info.senders[0], true);
}
// Remove the kSsrc2 stream. No receiver stats.
{
cricket::VoiceMediaInfo info;

View File

@ -14,6 +14,8 @@ source_set("audio") {
"audio_receive_stream.h",
"audio_send_stream.cc",
"audio_send_stream.h",
"audio_state.cc",
"audio_state.h",
"conversion.h",
"scoped_voe_interface.h",
]

View File

@ -12,6 +12,7 @@
#include <string>
#include "webrtc/audio/audio_state.h"
#include "webrtc/audio/conversion.h"
#include "webrtc/base/checks.h"
#include "webrtc/base/logging.h"
@ -60,19 +61,18 @@ std::string AudioReceiveStream::Config::ToString() const {
namespace internal {
AudioReceiveStream::AudioReceiveStream(
RemoteBitrateEstimator* remote_bitrate_estimator,
const webrtc::AudioReceiveStream::Config& config,
VoiceEngine* voice_engine)
RemoteBitrateEstimator* remote_bitrate_estimator,
const webrtc::AudioReceiveStream::Config& config,
const rtc::scoped_refptr<webrtc::AudioState>& audio_state)
: remote_bitrate_estimator_(remote_bitrate_estimator),
config_(config),
voice_engine_(voice_engine),
voe_base_(voice_engine),
audio_state_(audio_state),
rtp_header_parser_(RtpHeaderParser::Create()) {
LOG(LS_INFO) << "AudioReceiveStream: " << config_.ToString();
RTC_DCHECK(config.voe_channel_id != -1);
RTC_DCHECK(remote_bitrate_estimator_ != nullptr);
RTC_DCHECK(voice_engine_ != nullptr);
RTC_DCHECK(rtp_header_parser_ != nullptr);
RTC_DCHECK_NE(config_.voe_channel_id, -1);
RTC_DCHECK(remote_bitrate_estimator_);
RTC_DCHECK(audio_state_.get());
RTC_DCHECK(rtp_header_parser_);
for (const auto& ext : config.rtp.extensions) {
// One-byte-extension local identifiers are in the range 1-14 inclusive.
RTC_DCHECK_GE(ext.id, 1);
@ -101,11 +101,14 @@ webrtc::AudioReceiveStream::Stats AudioReceiveStream::GetStats() const {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
webrtc::AudioReceiveStream::Stats stats;
stats.remote_ssrc = config_.rtp.remote_ssrc;
ScopedVoEInterface<VoECodec> codec(voice_engine_);
ScopedVoEInterface<VoENetEqStats> neteq(voice_engine_);
ScopedVoEInterface<VoERTP_RTCP> rtp(voice_engine_);
ScopedVoEInterface<VoEVideoSync> sync(voice_engine_);
ScopedVoEInterface<VoEVolumeControl> volume(voice_engine_);
internal::AudioState* audio_state =
static_cast<internal::AudioState*>(audio_state_.get());
VoiceEngine* voice_engine = audio_state->voice_engine();
ScopedVoEInterface<VoECodec> codec(voice_engine);
ScopedVoEInterface<VoENetEqStats> neteq(voice_engine);
ScopedVoEInterface<VoERTP_RTCP> rtp(voice_engine);
ScopedVoEInterface<VoEVideoSync> sync(voice_engine);
ScopedVoEInterface<VoEVolumeControl> volume(voice_engine);
unsigned int ssrc = 0;
webrtc::CallStatistics call_stats = {0};
webrtc::CodecInst codec_inst = {0};
@ -132,13 +135,12 @@ webrtc::AudioReceiveStream::Stats AudioReceiveStream::GetStats() const {
int playout_buffer_delay_ms = 0;
sync->GetDelayEstimate(config_.voe_channel_id, &jitter_buffer_delay_ms,
&playout_buffer_delay_ms);
stats.delay_estimate_ms =
jitter_buffer_delay_ms + playout_buffer_delay_ms;
stats.delay_estimate_ms = jitter_buffer_delay_ms + playout_buffer_delay_ms;
}
{
unsigned int level = 0;
if (volume->GetSpeechOutputLevelFullRange(config_.voe_channel_id, level)
!= -1) {
if (volume->GetSpeechOutputLevelFullRange(config_.voe_channel_id, level) !=
-1) {
stats.audio_level = static_cast<int32_t>(level);
}
}
@ -157,8 +159,7 @@ webrtc::AudioReceiveStream::Stats AudioReceiveStream::GetStats() const {
webrtc::AudioDecodingCallStats ds;
if (neteq->GetDecodingCallStatistics(config_.voe_channel_id, &ds) != -1) {
stats.decoding_calls_to_silence_generator =
ds.calls_to_silence_generator;
stats.decoding_calls_to_silence_generator = ds.calls_to_silence_generator;
stats.decoding_calls_to_neteq = ds.calls_to_neteq;
stats.decoding_normal = ds.decoded_normal;
stats.decoding_plc = ds.decoded_plc;

View File

@ -12,15 +12,13 @@
#define WEBRTC_AUDIO_AUDIO_RECEIVE_STREAM_H_
#include "webrtc/audio_receive_stream.h"
#include "webrtc/audio/scoped_voe_interface.h"
#include "webrtc/audio_state.h"
#include "webrtc/base/thread_checker.h"
#include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h"
#include "webrtc/voice_engine/include/voe_base.h"
namespace webrtc {
class RemoteBitrateEstimator;
class VoiceEngine;
namespace internal {
@ -28,7 +26,7 @@ class AudioReceiveStream final : public webrtc::AudioReceiveStream {
public:
AudioReceiveStream(RemoteBitrateEstimator* remote_bitrate_estimator,
const webrtc::AudioReceiveStream::Config& config,
VoiceEngine* voice_engine);
const rtc::scoped_refptr<webrtc::AudioState>& audio_state);
~AudioReceiveStream() override;
// webrtc::ReceiveStream implementation.
@ -49,9 +47,7 @@ class AudioReceiveStream final : public webrtc::AudioReceiveStream {
rtc::ThreadChecker thread_checker_;
RemoteBitrateEstimator* const remote_bitrate_estimator_;
const webrtc::AudioReceiveStream::Config config_;
VoiceEngine* voice_engine_;
// We hold one interface pointer to the VoE to make sure it is kept alive.
ScopedVoEInterface<VoEBase> voe_base_;
rtc::scoped_refptr<webrtc::AudioState> audio_state_;
rtc::scoped_ptr<RtpHeaderParser> rtp_header_parser_;
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(AudioReceiveStream);

View File

@ -20,10 +20,84 @@ namespace webrtc {
namespace test {
namespace {
AudioDecodingCallStats MakeAudioDecodeStatsForTest() {
AudioDecodingCallStats audio_decode_stats;
audio_decode_stats.calls_to_silence_generator = 234;
audio_decode_stats.calls_to_neteq = 567;
audio_decode_stats.decoded_normal = 890;
audio_decode_stats.decoded_plc = 123;
audio_decode_stats.decoded_cng = 456;
audio_decode_stats.decoded_plc_cng = 789;
return audio_decode_stats;
}
const int kChannelId = 2;
const uint32_t kRemoteSsrc = 1234;
const uint32_t kLocalSsrc = 5678;
const size_t kAbsoluteSendTimeLength = 4;
const int kAbsSendTimeId = 3;
const int kJitterBufferDelay = -7;
const int kPlayoutBufferDelay = 302;
const unsigned int kSpeechOutputLevel = 99;
const CallStatistics kCallStats = {
345, 678, 901, 234, -12, 3456, 7890, 567, 890, 123};
const CodecInst kCodecInst = {
123, "codec_name_recv", 96000, -187, -198, -103};
const NetworkStatistics kNetworkStats = {
123, 456, false, 0, 0, 789, 12, 345, 678, 901, -1, -1, -1, -1, -1, 0};
const AudioDecodingCallStats kAudioDecodeStats = MakeAudioDecodeStatsForTest();
struct ConfigHelper {
ConfigHelper() {
EXPECT_CALL(voice_engine_,
RegisterVoiceEngineObserver(testing::_)).WillOnce(testing::Return(0));
EXPECT_CALL(voice_engine_,
DeRegisterVoiceEngineObserver()).WillOnce(testing::Return(0));
AudioState::Config config;
config.voice_engine = &voice_engine_;
audio_state_ = AudioState::Create(config);
stream_config_.voe_channel_id = kChannelId;
stream_config_.rtp.local_ssrc = kLocalSsrc;
stream_config_.rtp.remote_ssrc = kRemoteSsrc;
}
MockRemoteBitrateEstimator* remote_bitrate_estimator() {
return &remote_bitrate_estimator_;
}
AudioReceiveStream::Config& config() { return stream_config_; }
rtc::scoped_refptr<AudioState> audio_state() { return audio_state_; }
MockVoiceEngine& voice_engine() { return voice_engine_; }
void SetupMockForGetStats() {
using testing::_;
using testing::DoAll;
using testing::Return;
using testing::SetArgPointee;
using testing::SetArgReferee;
EXPECT_CALL(voice_engine_, GetRemoteSSRC(kChannelId, _))
.WillOnce(DoAll(SetArgReferee<1>(0), Return(0)));
EXPECT_CALL(voice_engine_, GetRTCPStatistics(kChannelId, _))
.WillOnce(DoAll(SetArgReferee<1>(kCallStats), Return(0)));
EXPECT_CALL(voice_engine_, GetRecCodec(kChannelId, _))
.WillOnce(DoAll(SetArgReferee<1>(kCodecInst), Return(0)));
EXPECT_CALL(voice_engine_, GetDelayEstimate(kChannelId, _, _))
.WillOnce(DoAll(SetArgPointee<1>(kJitterBufferDelay),
SetArgPointee<2>(kPlayoutBufferDelay), Return(0)));
EXPECT_CALL(voice_engine_,
GetSpeechOutputLevelFullRange(kChannelId, _)).WillOnce(
DoAll(SetArgReferee<1>(kSpeechOutputLevel), Return(0)));
EXPECT_CALL(voice_engine_, GetNetworkStatistics(kChannelId, _))
.WillOnce(DoAll(SetArgReferee<1>(kNetworkStats), Return(0)));
EXPECT_CALL(voice_engine_, GetDecodingCallStatistics(kChannelId, _))
.WillOnce(DoAll(SetArgPointee<1>(kAudioDecodeStats), Return(0)));
}
private:
MockRemoteBitrateEstimator remote_bitrate_estimator_;
MockVoiceEngine voice_engine_;
rtc::scoped_refptr<AudioState> audio_state_;
AudioReceiveStream::Config stream_config_;
};
void BuildAbsoluteSendTimeExtension(uint8_t* buffer,
int id,
@ -62,7 +136,6 @@ size_t CreateRtpHeaderWithAbsSendTime(uint8_t* header,
} // namespace
TEST(AudioReceiveStreamTest, ConfigToString) {
const int kAbsSendTimeId = 3;
AudioReceiveStream::Config config;
config.rtp.remote_ssrc = kRemoteSsrc;
config.rtp.local_ssrc = kLocalSsrc;
@ -79,31 +152,24 @@ TEST(AudioReceiveStreamTest, ConfigToString) {
}
TEST(AudioReceiveStreamTest, ConstructDestruct) {
MockRemoteBitrateEstimator remote_bitrate_estimator;
MockVoiceEngine voice_engine;
AudioReceiveStream::Config config;
config.voe_channel_id = kChannelId;
internal::AudioReceiveStream recv_stream(&remote_bitrate_estimator, config,
&voice_engine);
ConfigHelper helper;
internal::AudioReceiveStream recv_stream(
helper.remote_bitrate_estimator(), helper.config(), helper.audio_state());
}
TEST(AudioReceiveStreamTest, AudioPacketUpdatesBweWithTimestamp) {
MockRemoteBitrateEstimator remote_bitrate_estimator;
MockVoiceEngine voice_engine;
AudioReceiveStream::Config config;
config.combined_audio_video_bwe = true;
config.voe_channel_id = kChannelId;
const int kAbsSendTimeId = 3;
config.rtp.extensions.push_back(
ConfigHelper helper;
helper.config().combined_audio_video_bwe = true;
helper.config().rtp.extensions.push_back(
RtpExtension(RtpExtension::kAbsSendTime, kAbsSendTimeId));
internal::AudioReceiveStream recv_stream(&remote_bitrate_estimator, config,
&voice_engine);
internal::AudioReceiveStream recv_stream(
helper.remote_bitrate_estimator(), helper.config(), helper.audio_state());
uint8_t rtp_packet[30];
const int kAbsSendTimeValue = 1234;
CreateRtpHeaderWithAbsSendTime(rtp_packet, kAbsSendTimeId, kAbsSendTimeValue);
PacketTime packet_time(5678000, 0);
const size_t kExpectedHeaderLength = 20;
EXPECT_CALL(remote_bitrate_estimator,
EXPECT_CALL(*helper.remote_bitrate_estimator(),
IncomingPacket(packet_time.timestamp / 1000,
sizeof(rtp_packet) - kExpectedHeaderLength,
testing::_, false))
@ -113,57 +179,10 @@ TEST(AudioReceiveStreamTest, AudioPacketUpdatesBweWithTimestamp) {
}
TEST(AudioReceiveStreamTest, GetStats) {
const int kJitterBufferDelay = -7;
const int kPlayoutBufferDelay = 302;
const unsigned int kSpeechOutputLevel = 99;
const CallStatistics kCallStats = {345, 678, 901, 234, -12,
3456, 7890, 567, 890, 123};
const CodecInst kCodecInst = {123, "codec_name_recv", 96000, -187, -198,
-103};
const NetworkStatistics kNetworkStats = {
123, 456, false, 0, 0, 789, 12, 345, 678, 901, -1, -1, -1, -1, -1, 0};
webrtc::AudioDecodingCallStats audio_decode_stats;
{
audio_decode_stats.calls_to_silence_generator = 234;
audio_decode_stats.calls_to_neteq = 567;
audio_decode_stats.decoded_normal = 890;
audio_decode_stats.decoded_plc = 123;
audio_decode_stats.decoded_cng = 456;
audio_decode_stats.decoded_plc_cng = 789;
}
MockRemoteBitrateEstimator remote_bitrate_estimator;
MockVoiceEngine voice_engine;
AudioReceiveStream::Config config;
config.rtp.remote_ssrc = kRemoteSsrc;
config.voe_channel_id = kChannelId;
internal::AudioReceiveStream recv_stream(&remote_bitrate_estimator, config,
&voice_engine);
using testing::_;
using testing::DoAll;
using testing::Return;
using testing::SetArgPointee;
using testing::SetArgReferee;
EXPECT_CALL(voice_engine, GetRemoteSSRC(kChannelId, _))
.WillOnce(DoAll(SetArgReferee<1>(0), Return(0)));
EXPECT_CALL(voice_engine, GetRTCPStatistics(kChannelId, _))
.WillOnce(DoAll(SetArgReferee<1>(kCallStats), Return(0)));
EXPECT_CALL(voice_engine, GetRecCodec(kChannelId, _))
.WillOnce(DoAll(SetArgReferee<1>(kCodecInst), Return(0)));
EXPECT_CALL(voice_engine, GetDelayEstimate(kChannelId, _, _))
.WillOnce(DoAll(SetArgPointee<1>(kJitterBufferDelay),
SetArgPointee<2>(kPlayoutBufferDelay), Return(0)));
EXPECT_CALL(voice_engine, GetSpeechOutputLevelFullRange(kChannelId, _))
.WillOnce(DoAll(SetArgReferee<1>(kSpeechOutputLevel), Return(0)));
EXPECT_CALL(voice_engine, GetNetworkStatistics(kChannelId, _))
.WillOnce(DoAll(SetArgReferee<1>(kNetworkStats), Return(0)));
EXPECT_CALL(voice_engine, GetDecodingCallStatistics(kChannelId, _))
.WillOnce(DoAll(SetArgPointee<1>(audio_decode_stats), Return(0)));
ConfigHelper helper;
internal::AudioReceiveStream recv_stream(
helper.remote_bitrate_estimator(), helper.config(), helper.audio_state());
helper.SetupMockForGetStats();
AudioReceiveStream::Stats stats = recv_stream.GetStats();
EXPECT_EQ(kRemoteSsrc, stats.remote_ssrc);
EXPECT_EQ(static_cast<int64_t>(kCallStats.bytesReceived), stats.bytes_rcvd);
@ -190,13 +209,13 @@ TEST(AudioReceiveStreamTest, GetStats) {
stats.accelerate_rate);
EXPECT_EQ(Q14ToFloat(kNetworkStats.currentPreemptiveRate),
stats.preemptive_expand_rate);
EXPECT_EQ(audio_decode_stats.calls_to_silence_generator,
EXPECT_EQ(kAudioDecodeStats.calls_to_silence_generator,
stats.decoding_calls_to_silence_generator);
EXPECT_EQ(audio_decode_stats.calls_to_neteq, stats.decoding_calls_to_neteq);
EXPECT_EQ(audio_decode_stats.decoded_normal, stats.decoding_normal);
EXPECT_EQ(audio_decode_stats.decoded_plc, stats.decoding_plc);
EXPECT_EQ(audio_decode_stats.decoded_cng, stats.decoding_cng);
EXPECT_EQ(audio_decode_stats.decoded_plc_cng, stats.decoding_plc_cng);
EXPECT_EQ(kAudioDecodeStats.calls_to_neteq, stats.decoding_calls_to_neteq);
EXPECT_EQ(kAudioDecodeStats.decoded_normal, stats.decoding_normal);
EXPECT_EQ(kAudioDecodeStats.decoded_plc, stats.decoding_plc);
EXPECT_EQ(kAudioDecodeStats.decoded_cng, stats.decoding_cng);
EXPECT_EQ(kAudioDecodeStats.decoded_plc_cng, stats.decoding_plc_cng);
EXPECT_EQ(kCallStats.capture_start_ntp_time_ms_,
stats.capture_start_ntp_time_ms);
}

View File

@ -12,7 +12,9 @@
#include <string>
#include "webrtc/audio/audio_state.h"
#include "webrtc/audio/conversion.h"
#include "webrtc/audio/scoped_voe_interface.h"
#include "webrtc/base/checks.h"
#include "webrtc/base/logging.h"
#include "webrtc/voice_engine/include/voe_audio_processing.h"
@ -48,14 +50,14 @@ std::string AudioSendStream::Config::ToString() const {
}
namespace internal {
AudioSendStream::AudioSendStream(const webrtc::AudioSendStream::Config& config,
VoiceEngine* voice_engine)
: config_(config),
voice_engine_(voice_engine),
voe_base_(voice_engine) {
AudioSendStream::AudioSendStream(
const webrtc::AudioSendStream::Config& config,
const rtc::scoped_refptr<webrtc::AudioState>& audio_state)
: config_(config), audio_state_(audio_state) {
LOG(LS_INFO) << "AudioSendStream: " << config_.ToString();
RTC_DCHECK_NE(config.voe_channel_id, -1);
RTC_DCHECK(voice_engine_);
RTC_DCHECK_NE(config_.voe_channel_id, -1);
RTC_DCHECK(audio_state_.get());
}
AudioSendStream::~AudioSendStream() {
@ -67,10 +69,13 @@ webrtc::AudioSendStream::Stats AudioSendStream::GetStats() const {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
webrtc::AudioSendStream::Stats stats;
stats.local_ssrc = config_.rtp.ssrc;
ScopedVoEInterface<VoEAudioProcessing> processing(voice_engine_);
ScopedVoEInterface<VoECodec> codec(voice_engine_);
ScopedVoEInterface<VoERTP_RTCP> rtp(voice_engine_);
ScopedVoEInterface<VoEVolumeControl> volume(voice_engine_);
internal::AudioState* audio_state =
static_cast<internal::AudioState*>(audio_state_.get());
VoiceEngine* voice_engine = audio_state->voice_engine();
ScopedVoEInterface<VoEAudioProcessing> processing(voice_engine);
ScopedVoEInterface<VoECodec> codec(voice_engine);
ScopedVoEInterface<VoERTP_RTCP> rtp(voice_engine);
ScopedVoEInterface<VoEVolumeControl> volume(voice_engine);
unsigned int ssrc = 0;
webrtc::CallStatistics call_stats = {0};
if (rtp->GetLocalSSRC(config_.voe_channel_id, ssrc) == -1 ||
@ -148,8 +153,7 @@ webrtc::AudioSendStream::Stats AudioSendStream::GetStats() const {
}
}
// TODO(solenberg): Collect typing noise warnings here too!
// bool typing_noise_detected = typing_noise_detected_;
stats.typing_noise_detected = audio_state->typing_noise_detected();
return stats;
}

View File

@ -12,20 +12,16 @@
#define WEBRTC_AUDIO_AUDIO_SEND_STREAM_H_
#include "webrtc/audio_send_stream.h"
#include "webrtc/audio/scoped_voe_interface.h"
#include "webrtc/audio_state.h"
#include "webrtc/base/thread_checker.h"
#include "webrtc/voice_engine/include/voe_base.h"
namespace webrtc {
class VoiceEngine;
namespace internal {
class AudioSendStream final : public webrtc::AudioSendStream {
public:
AudioSendStream(const webrtc::AudioSendStream::Config& config,
VoiceEngine* voice_engine);
const rtc::scoped_refptr<webrtc::AudioState>& audio_state);
~AudioSendStream() override;
// webrtc::SendStream implementation.
@ -42,9 +38,7 @@ class AudioSendStream final : public webrtc::AudioSendStream {
private:
rtc::ThreadChecker thread_checker_;
const webrtc::AudioSendStream::Config config_;
VoiceEngine* voice_engine_;
// We hold one interface pointer to the VoE to make sure it is kept alive.
ScopedVoEInterface<VoEBase> voe_base_;
rtc::scoped_refptr<webrtc::AudioState> audio_state_;
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(AudioSendStream);
};

View File

@ -11,6 +11,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/audio/audio_send_stream.h"
#include "webrtc/audio/audio_state.h"
#include "webrtc/audio/conversion.h"
#include "webrtc/test/mock_voice_engine.h"
@ -20,6 +21,72 @@ namespace {
const int kChannelId = 1;
const uint32_t kSsrc = 1234;
const int kEchoDelayMedian = 254;
const int kEchoDelayStdDev = -3;
const int kEchoReturnLoss = -65;
const int kEchoReturnLossEnhancement = 101;
const unsigned int kSpeechInputLevel = 96;
const CallStatistics kCallStats = {
1345, 1678, 1901, 1234, 112, 13456, 17890, 1567, -1890, -1123};
const CodecInst kCodecInst = {-121, "codec_name_send", 48000, -231, -451, -671};
const ReportBlock kReportBlock = {456, 780, 123, 567, 890, 132, 143, 13354};
struct ConfigHelper {
ConfigHelper() : stream_config_(nullptr) {
EXPECT_CALL(voice_engine_,
RegisterVoiceEngineObserver(testing::_)).WillOnce(testing::Return(0));
EXPECT_CALL(voice_engine_,
DeRegisterVoiceEngineObserver()).WillOnce(testing::Return(0));
AudioState::Config config;
config.voice_engine = &voice_engine_;
audio_state_ = AudioState::Create(config);
stream_config_.voe_channel_id = kChannelId;
stream_config_.rtp.ssrc = kSsrc;
}
AudioSendStream::Config& config() { return stream_config_; }
rtc::scoped_refptr<AudioState> audio_state() { return audio_state_; }
void SetupMockForGetStats() {
std::vector<ReportBlock> report_blocks;
webrtc::ReportBlock block = kReportBlock;
report_blocks.push_back(block); // Has wrong SSRC.
block.source_SSRC = kSsrc;
report_blocks.push_back(block); // Correct block.
block.fraction_lost = 0;
report_blocks.push_back(block); // Duplicate SSRC, bad fraction_lost.
using testing::_;
using testing::DoAll;
using testing::Return;
using testing::SetArgPointee;
using testing::SetArgReferee;
EXPECT_CALL(voice_engine_, GetLocalSSRC(kChannelId, _))
.WillRepeatedly(DoAll(SetArgReferee<1>(0), Return(0)));
EXPECT_CALL(voice_engine_, GetRTCPStatistics(kChannelId, _))
.WillRepeatedly(DoAll(SetArgReferee<1>(kCallStats), Return(0)));
EXPECT_CALL(voice_engine_, GetSendCodec(kChannelId, _))
.WillRepeatedly(DoAll(SetArgReferee<1>(kCodecInst), Return(0)));
EXPECT_CALL(voice_engine_, GetRemoteRTCPReportBlocks(kChannelId, _))
.WillRepeatedly(DoAll(SetArgPointee<1>(report_blocks), Return(0)));
EXPECT_CALL(voice_engine_, GetSpeechInputLevelFullRange(_))
.WillRepeatedly(DoAll(SetArgReferee<0>(kSpeechInputLevel), Return(0)));
EXPECT_CALL(voice_engine_, GetEcMetricsStatus(_))
.WillRepeatedly(DoAll(SetArgReferee<0>(true), Return(0)));
EXPECT_CALL(voice_engine_, GetEchoMetrics(_, _, _, _))
.WillRepeatedly(DoAll(SetArgReferee<0>(kEchoReturnLoss),
SetArgReferee<1>(kEchoReturnLossEnhancement),
Return(0)));
EXPECT_CALL(voice_engine_, GetEcDelayMetrics(_, _, _))
.WillRepeatedly(DoAll(SetArgReferee<0>(kEchoDelayMedian),
SetArgReferee<1>(kEchoDelayStdDev), Return(0)));
}
private:
MockVoiceEngine voice_engine_;
rtc::scoped_refptr<AudioState> audio_state_;
AudioSendStream::Config stream_config_;
};
} // namespace
TEST(AudioSendStreamTest, ConfigToString) {
@ -39,67 +106,14 @@ TEST(AudioSendStreamTest, ConfigToString) {
}
TEST(AudioSendStreamTest, ConstructDestruct) {
MockVoiceEngine voice_engine;
AudioSendStream::Config config(nullptr);
config.voe_channel_id = kChannelId;
internal::AudioSendStream send_stream(config, &voice_engine);
ConfigHelper helper;
internal::AudioSendStream send_stream(helper.config(), helper.audio_state());
}
TEST(AudioSendStreamTest, GetStats) {
const int kEchoDelayMedian = 254;
const int kEchoDelayStdDev = -3;
const int kEchoReturnLoss = -65;
const int kEchoReturnLossEnhancement = 101;
const unsigned int kSpeechInputLevel = 96;
const CallStatistics kCallStats = {1345, 1678, 1901, 1234, 112,
13456, 17890, 1567, -1890, -1123};
const CodecInst kCodecInst = {-121, "codec_name_send", 48000, -231, -451,
-671};
const ReportBlock kReportBlock = {456, 780, 123, 567, 890, 132, 143, 13354};
std::vector<ReportBlock> report_blocks;
{
webrtc::ReportBlock block = kReportBlock;
report_blocks.push_back(block); // Has wrong SSRC.
block.source_SSRC = kSsrc;
report_blocks.push_back(block); // Correct block.
block.fraction_lost = 0;
report_blocks.push_back(block); // Duplicate SSRC, bad fraction_lost.
}
MockVoiceEngine voice_engine;
AudioSendStream::Config config(nullptr);
config.rtp.ssrc = kSsrc;
config.voe_channel_id = kChannelId;
internal::AudioSendStream send_stream(config, &voice_engine);
using testing::_;
using testing::DoAll;
using testing::Return;
using testing::SetArgPointee;
using testing::SetArgReferee;
EXPECT_CALL(voice_engine, GetLocalSSRC(kChannelId, _))
.WillOnce(DoAll(SetArgReferee<1>(0), Return(0)));
EXPECT_CALL(voice_engine, GetRTCPStatistics(kChannelId, _))
.WillOnce(DoAll(SetArgReferee<1>(kCallStats), Return(0)));
EXPECT_CALL(voice_engine, GetSendCodec(kChannelId, _))
.WillOnce(DoAll(SetArgReferee<1>(kCodecInst), Return(0)));
EXPECT_CALL(voice_engine, GetRemoteRTCPReportBlocks(kChannelId, _))
.WillOnce(DoAll(SetArgPointee<1>(report_blocks), Return(0)));
EXPECT_CALL(voice_engine, GetSpeechInputLevelFullRange(_))
.WillOnce(DoAll(SetArgReferee<0>(kSpeechInputLevel), Return(0)));
EXPECT_CALL(voice_engine, GetEcMetricsStatus(_))
.WillOnce(DoAll(SetArgReferee<0>(true), Return(0)));
EXPECT_CALL(voice_engine, GetEchoMetrics(_, _, _, _))
.WillOnce(DoAll(SetArgReferee<0>(kEchoReturnLoss),
SetArgReferee<1>(kEchoReturnLossEnhancement), Return(0)));
EXPECT_CALL(voice_engine, GetEcDelayMetrics(_, _, _))
.WillOnce(DoAll(SetArgReferee<0>(kEchoDelayMedian),
SetArgReferee<1>(kEchoDelayStdDev), Return(0)));
ConfigHelper helper;
internal::AudioSendStream send_stream(helper.config(), helper.audio_state());
helper.SetupMockForGetStats();
AudioSendStream::Stats stats = send_stream.GetStats();
EXPECT_EQ(kSsrc, stats.local_ssrc);
EXPECT_EQ(static_cast<int64_t>(kCallStats.bytesSent), stats.bytes_sent);
@ -122,5 +136,21 @@ TEST(AudioSendStreamTest, GetStats) {
EXPECT_EQ(kEchoReturnLossEnhancement, stats.echo_return_loss_enhancement);
EXPECT_FALSE(stats.typing_noise_detected);
}
TEST(AudioSendStreamTest, GetStatsTypingNoiseDetected) {
ConfigHelper helper;
internal::AudioSendStream send_stream(helper.config(), helper.audio_state());
helper.SetupMockForGetStats();
EXPECT_FALSE(send_stream.GetStats().typing_noise_detected);
internal::AudioState* internal_audio_state =
static_cast<internal::AudioState*>(helper.audio_state().get());
VoiceEngineObserver* voe_observer =
static_cast<VoiceEngineObserver*>(internal_audio_state);
voe_observer->CallbackOnError(-1, VE_TYPING_NOISE_WARNING);
EXPECT_TRUE(send_stream.GetStats().typing_noise_detected);
voe_observer->CallbackOnError(-1, VE_TYPING_NOISE_OFF_WARNING);
EXPECT_FALSE(send_stream.GetStats().typing_noise_detected);
}
} // namespace test
} // namespace webrtc

View File

@ -0,0 +1,79 @@
/*
* Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/audio/audio_state.h"
#include "webrtc/base/atomicops.h"
#include "webrtc/base/checks.h"
#include "webrtc/base/logging.h"
#include "webrtc/voice_engine/include/voe_errors.h"
namespace webrtc {
namespace internal {
AudioState::AudioState(const AudioState::Config& config)
: config_(config), voe_base_(config.voice_engine) {
process_thread_checker_.DetachFromThread();
// Only one AudioState should be created per VoiceEngine.
RTC_CHECK(voe_base_->RegisterVoiceEngineObserver(*this) != -1);
}
AudioState::~AudioState() {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
voe_base_->DeRegisterVoiceEngineObserver();
}
VoiceEngine* AudioState::voice_engine() {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
return config_.voice_engine;
}
bool AudioState::typing_noise_detected() const {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
rtc::CritScope lock(&crit_sect_);
return typing_noise_detected_;
}
// Reference count; implementation copied from rtc::RefCountedObject.
int AudioState::AddRef() const {
return rtc::AtomicOps::Increment(&ref_count_);
}
// Reference count; implementation copied from rtc::RefCountedObject.
int AudioState::Release() const {
int count = rtc::AtomicOps::Decrement(&ref_count_);
if (!count) {
delete this;
}
return count;
}
void AudioState::CallbackOnError(int channel_id, int err_code) {
RTC_DCHECK(process_thread_checker_.CalledOnValidThread());
// All call sites in VoE, as of this writing, specify -1 as channel_id.
RTC_DCHECK(channel_id == -1);
LOG(LS_INFO) << "VoiceEngine error " << err_code << " reported on channel "
<< channel_id << ".";
if (err_code == VE_TYPING_NOISE_WARNING) {
rtc::CritScope lock(&crit_sect_);
typing_noise_detected_ = true;
} else if (err_code == VE_TYPING_NOISE_OFF_WARNING) {
rtc::CritScope lock(&crit_sect_);
typing_noise_detected_ = false;
}
}
} // namespace internal
rtc::scoped_refptr<AudioState> AudioState::Create(
const AudioState::Config& config) {
return rtc::scoped_refptr<AudioState>(new internal::AudioState(config));
}
} // namespace webrtc

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_AUDIO_AUDIO_STATE_H_
#define WEBRTC_AUDIO_AUDIO_STATE_H_
#include "webrtc/audio_state.h"
#include "webrtc/audio/scoped_voe_interface.h"
#include "webrtc/base/constructormagic.h"
#include "webrtc/base/criticalsection.h"
#include "webrtc/base/thread_checker.h"
#include "webrtc/voice_engine/include/voe_base.h"
namespace webrtc {
namespace internal {
class AudioState final : public webrtc::AudioState,
public webrtc::VoiceEngineObserver {
public:
explicit AudioState(const AudioState::Config& config);
~AudioState() override;
VoiceEngine* voice_engine();
bool typing_noise_detected() const;
private:
// rtc::RefCountInterface implementation.
int AddRef() const override;
int Release() const override;
// webrtc::VoiceEngineObserver implementation.
void CallbackOnError(int channel_id, int err_code) override;
rtc::ThreadChecker thread_checker_;
rtc::ThreadChecker process_thread_checker_;
const webrtc::AudioState::Config config_;
// We hold one interface pointer to the VoE to make sure it is kept alive.
ScopedVoEInterface<VoEBase> voe_base_;
// The critical section isn't strictly needed in this case, but xSAN bots may
// trigger on unprotected cross-thread access.
mutable rtc::CriticalSection crit_sect_;
bool typing_noise_detected_ GUARDED_BY(crit_sect_) = false;
// Reference count; implementation copied from rtc::RefCountedObject.
mutable volatile int ref_count_ = 0;
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(AudioState);
};
} // namespace internal
} // namespace webrtc
#endif // WEBRTC_AUDIO_AUDIO_STATE_H_

View File

@ -0,0 +1,80 @@
/*
* Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/audio/audio_state.h"
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/test/mock_voice_engine.h"
namespace webrtc {
namespace test {
namespace {
struct ConfigHelper {
ConfigHelper() {
EXPECT_CALL(voice_engine_,
RegisterVoiceEngineObserver(testing::_)).WillOnce(testing::Return(0));
EXPECT_CALL(voice_engine_,
DeRegisterVoiceEngineObserver()).WillOnce(testing::Return(0));
config_.voice_engine = &voice_engine_;
}
AudioState::Config& config() { return config_; }
MockVoiceEngine& voice_engine() { return voice_engine_; }
private:
MockVoiceEngine voice_engine_;
AudioState::Config config_;
};
} // namespace
TEST(AudioStateTest, Create) {
ConfigHelper helper;
rtc::scoped_refptr<AudioState> audio_state =
AudioState::Create(helper.config());
EXPECT_TRUE(audio_state.get());
}
TEST(AudioStateTest, ConstructDestruct) {
ConfigHelper helper;
rtc::scoped_ptr<internal::AudioState> audio_state(
new internal::AudioState(helper.config()));
}
TEST(AudioStateTest, GetVoiceEngine) {
ConfigHelper helper;
rtc::scoped_ptr<internal::AudioState> audio_state(
new internal::AudioState(helper.config()));
EXPECT_EQ(audio_state->voice_engine(), &helper.voice_engine());
}
TEST(AudioStateTest, TypingNoiseDetected) {
ConfigHelper helper;
rtc::scoped_ptr<internal::AudioState> audio_state(
new internal::AudioState(helper.config()));
VoiceEngineObserver* voe_observer =
static_cast<VoiceEngineObserver*>(audio_state.get());
EXPECT_FALSE(audio_state->typing_noise_detected());
voe_observer->CallbackOnError(-1, VE_NOT_INITED);
EXPECT_FALSE(audio_state->typing_noise_detected());
voe_observer->CallbackOnError(-1, VE_TYPING_NOISE_WARNING);
EXPECT_TRUE(audio_state->typing_noise_detected());
voe_observer->CallbackOnError(-1, VE_NOT_INITED);
EXPECT_TRUE(audio_state->typing_noise_detected());
voe_observer->CallbackOnError(-1, VE_TYPING_NOISE_OFF_WARNING);
EXPECT_FALSE(audio_state->typing_noise_detected());
voe_observer->CallbackOnError(-1, VE_NOT_INITED);
EXPECT_FALSE(audio_state->typing_noise_detected());
}
} // namespace test
} // namespace webrtc

View File

@ -18,6 +18,8 @@
'audio/audio_receive_stream.h',
'audio/audio_send_stream.cc',
'audio/audio_send_stream.h',
'audio/audio_state.cc',
'audio/audio_state.h',
'audio/conversion.h',
'audio/scoped_voe_interface.h',
],

43
webrtc/audio_state.h Normal file
View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_AUDIO_STATE_H_
#define WEBRTC_AUDIO_STATE_H_
#include "webrtc/base/refcount.h"
#include "webrtc/base/scoped_ref_ptr.h"
namespace webrtc {
class AudioDeviceModule;
class VoiceEngine;
// AudioState holds the state which must be shared between multiple instances of
// webrtc::Call for audio processing purposes.
class AudioState : public rtc::RefCountInterface {
public:
struct Config {
// VoiceEngine used for audio streams and audio/video synchronization.
// AudioState will tickle the VoE refcount to keep it alive for as long as
// the AudioState itself.
VoiceEngine* voice_engine = nullptr;
// The AudioDeviceModule associated with the Calls.
AudioDeviceModule* audio_device_module = nullptr;
};
// TODO(solenberg): Replace scoped_refptr with shared_ptr once we can use it.
static rtc::scoped_refptr<AudioState> Create(
const AudioState::Config& config);
virtual ~AudioState() {}
};
} // namespace webrtc
#endif // WEBRTC_AUDIO_STATE_H_

View File

@ -16,16 +16,14 @@
#include "webrtc/common_types.h"
#include "webrtc/audio_receive_stream.h"
#include "webrtc/audio_send_stream.h"
#include "webrtc/audio_state.h"
#include "webrtc/base/socket.h"
#include "webrtc/video_receive_stream.h"
#include "webrtc/video_send_stream.h"
namespace webrtc {
class AudioDeviceModule;
class AudioProcessing;
class VoiceEngine;
class VoiceEngineObserver;
const char* Version();
@ -74,9 +72,6 @@ class Call {
struct Config {
static const int kDefaultStartBitrateBps;
// VoiceEngine used for audio/video synchronization for this Call.
VoiceEngine* voice_engine = nullptr;
// Bitrate config used until valid bitrate estimates are calculated. Also
// used to cap total bitrate used.
struct BitrateConfig {
@ -85,11 +80,13 @@ class Call {
int max_bitrate_bps = -1;
} bitrate_config;
struct AudioConfig {
AudioDeviceModule* audio_device_module = nullptr;
AudioProcessing* audio_processing = nullptr;
VoiceEngineObserver* voice_engine_observer = nullptr;
} audio_config;
// AudioState which is possibly shared between multiple calls.
// TODO(solenberg): Change this to a shared_ptr once we can use C++11.
rtc::scoped_refptr<AudioState> audio_state;
// Audio Processing Module to be used in this call.
// TODO(solenberg): Change this to a shared_ptr once we can use C++11.
AudioProcessing* audio_processing = nullptr;
};
struct Stats {

View File

@ -13,6 +13,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/audio_state.h"
#include "webrtc/base/checks.h"
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/base/thread_annotations.h"
@ -117,11 +118,17 @@ class BitrateEstimatorTest : public test::CallTest {
virtual ~BitrateEstimatorTest() { EXPECT_TRUE(streams_.empty()); }
virtual void SetUp() {
EXPECT_CALL(mock_voice_engine_,
RegisterVoiceEngineObserver(testing::_)).WillOnce(testing::Return(0));
EXPECT_CALL(mock_voice_engine_,
DeRegisterVoiceEngineObserver()).WillOnce(testing::Return(0));
EXPECT_CALL(mock_voice_engine_, GetEventLog())
.WillRepeatedly(testing::Return(nullptr));
AudioState::Config audio_state_config;
audio_state_config.voice_engine = &mock_voice_engine_;
Call::Config config;
config.voice_engine = &mock_voice_engine_;
config.audio_state = AudioState::Create(audio_state_config);
receiver_call_.reset(Call::Create(config));
sender_call_.reset(Call::Create(config));
@ -162,6 +169,7 @@ class BitrateEstimatorTest : public test::CallTest {
}
receiver_call_.reset();
sender_call_.reset();
}
protected:

View File

@ -15,6 +15,8 @@
#include "webrtc/audio/audio_receive_stream.h"
#include "webrtc/audio/audio_send_stream.h"
#include "webrtc/audio/audio_state.h"
#include "webrtc/audio/scoped_voe_interface.h"
#include "webrtc/base/checks.h"
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/base/thread_annotations.h"
@ -94,6 +96,15 @@ class Call : public webrtc::Call, public PacketReceiver {
void ConfigureSync(const std::string& sync_group)
EXCLUSIVE_LOCKS_REQUIRED(receive_crit_);
VoiceEngine* voice_engine() {
internal::AudioState* audio_state =
static_cast<internal::AudioState*>(config_.audio_state.get());
if (audio_state)
return audio_state->voice_engine();
else
return nullptr;
}
const int num_cpu_cores_;
const rtc::scoped_ptr<ProcessThread> module_process_thread_;
const rtc::scoped_ptr<CallStats> call_stats_;
@ -123,7 +134,6 @@ class Call : public webrtc::Call, public PacketReceiver {
VideoSendStream::RtpStateMap suspended_video_send_ssrcs_;
RtcEventLog* event_log_ = nullptr;
VoECodec* voe_codec_ = nullptr;
RTC_DISALLOW_COPY_AND_ASSIGN(Call);
};
@ -152,12 +162,9 @@ Call::Call(const Call::Config& config)
RTC_DCHECK_GE(config.bitrate_config.max_bitrate_bps,
config.bitrate_config.start_bitrate_bps);
}
if (config.voice_engine) {
// Keep a reference to VoECodec, so we're sure the VoiceEngine lives for the
// duration of the call.
voe_codec_ = VoECodec::GetInterface(config.voice_engine);
if (voe_codec_)
event_log_ = voe_codec_->GetEventLog();
if (config.audio_state.get()) {
ScopedVoEInterface<VoECodec> voe_codec(voice_engine());
event_log_ = voe_codec->GetEventLog();
}
Trace::CreateTrace();
@ -184,9 +191,6 @@ Call::~Call() {
module_process_thread_->DeRegisterModule(call_stats_.get());
module_process_thread_->Stop();
Trace::ReturnTrace();
if (voe_codec_)
voe_codec_->Release();
}
PacketReceiver* Call::Receiver() {
@ -201,7 +205,7 @@ webrtc::AudioSendStream* Call::CreateAudioSendStream(
TRACE_EVENT0("webrtc", "Call::CreateAudioSendStream");
RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
AudioSendStream* send_stream =
new AudioSendStream(config, config_.voice_engine);
new AudioSendStream(config, config_.audio_state);
if (!network_enabled_)
send_stream->SignalNetworkState(kNetworkDown);
{
@ -237,7 +241,7 @@ webrtc::AudioReceiveStream* Call::CreateAudioReceiveStream(
RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
AudioReceiveStream* receive_stream = new AudioReceiveStream(
congestion_controller_->GetRemoteBitrateEstimator(false), config,
config_.voice_engine);
config_.audio_state);
{
WriteLockScoped write_lock(*receive_crit_);
RTC_DCHECK(audio_receive_ssrcs_.find(config.rtp.remote_ssrc) ==
@ -340,7 +344,7 @@ webrtc::VideoReceiveStream* Call::CreateVideoReceiveStream(
RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
VideoReceiveStream* receive_stream = new VideoReceiveStream(
num_cpu_cores_, congestion_controller_.get(), config,
config_.voice_engine, module_process_thread_.get(), call_stats_.get());
voice_engine(), module_process_thread_.get(), call_stats_.get());
WriteLockScoped write_lock(*receive_crit_);
RTC_DCHECK(video_receive_ssrcs_.find(config.rtp.remote_ssrc) ==
@ -470,7 +474,7 @@ void Call::OnSentPacket(const rtc::SentPacket& sent_packet) {
void Call::ConfigureSync(const std::string& sync_group) {
// Set sync only if there was no previous one.
if (config_.voice_engine == nullptr || sync_group.empty())
if (voice_engine() == nullptr || sync_group.empty())
return;
AudioReceiveStream* sync_audio_stream = nullptr;
@ -508,10 +512,10 @@ void Call::ConfigureSync(const std::string& sync_group) {
}
// Only sync the first A/V pair within this sync group.
if (sync_audio_stream != nullptr && num_synced_streams == 1) {
video_stream->SetSyncChannel(config_.voice_engine,
video_stream->SetSyncChannel(voice_engine(),
sync_audio_stream->config().voe_channel_id);
} else {
video_stream->SetSyncChannel(config_.voice_engine, -1);
video_stream->SetSyncChannel(voice_engine(), -1);
}
}
}

View File

@ -232,8 +232,10 @@ void CallPerfTest::TestAudioVideoSync(bool fec, bool create_audio_first) {
SyncRtcpObserver audio_observer;
AudioState::Config audio_state_config;
audio_state_config.voice_engine = voice_engine;
Call::Config receiver_config;
receiver_config.voice_engine = voice_engine;
receiver_config.audio_state = AudioState::Create(audio_state_config);
CreateCalls(Call::Config(), receiver_config);
CodecInst isac = {103, "ISAC", 16000, 480, 1, 32000};

View File

@ -12,22 +12,31 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/audio_state.h"
#include "webrtc/call.h"
#include "webrtc/test/mock_voice_engine.h"
namespace {
struct CallHelper {
CallHelper() : voice_engine_(new webrtc::test::MockVoiceEngine()) {
CallHelper() {
EXPECT_CALL(voice_engine_,
RegisterVoiceEngineObserver(testing::_)).WillOnce(testing::Return(0));
EXPECT_CALL(voice_engine_,
DeRegisterVoiceEngineObserver()).WillOnce(testing::Return(0));
EXPECT_CALL(voice_engine_,
GetEventLog()).WillOnce(testing::Return(nullptr));
webrtc::AudioState::Config audio_state_config;
audio_state_config.voice_engine = &voice_engine_;
webrtc::Call::Config config;
config.voice_engine = voice_engine_.get();
config.audio_state = webrtc::AudioState::Create(audio_state_config);
call_.reset(webrtc::Call::Create(config));
}
webrtc::Call* operator->() { return call_.get(); }
private:
rtc::scoped_ptr<webrtc::test::MockVoiceEngine> voice_engine_;
webrtc::test::MockVoiceEngine voice_engine_;
rtc::scoped_ptr<webrtc::Call> call_;
};
} // namespace

View File

@ -97,7 +97,7 @@ std::string VideoSendStream::Config::ToString() const {
ss << ", post_encode_callback: " << (post_encode_callback != nullptr
? "(EncodedFrameObserver)"
: "nullptr");
ss << "local_renderer: " << (local_renderer != nullptr ? "(VideoRenderer)"
ss << ", local_renderer: " << (local_renderer != nullptr ? "(VideoRenderer)"
: "nullptr");
ss << ", render_delay_ms: " << render_delay_ms;
ss << ", target_delay_ms: " << target_delay_ms;

View File

@ -98,6 +98,7 @@
'sources': [
'audio_receive_stream.h',
'audio_send_stream.h',
'audio_state.h',
'call.h',
'config.h',
'frame_callback.h',

View File

@ -153,6 +153,7 @@
'sources': [
'audio/audio_receive_stream_unittest.cc',
'audio/audio_send_stream_unittest.cc',
'audio/audio_state_unittest.cc',
'call/bitrate_estimator_tests.cc',
'call/call_unittest.cc',
'call/packet_injection_tests.cc',