- Introduce internal classes WebRtcAudio[Send|Receive]Stream in WebRtcVoiceMediaChannel.

- Remove WebRtcVoiceMediaChannel::WebRtcVoiceChannelRenderer
- Create webrtc::AudioSendStreams.

BUG=webrtc:4690

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

Cr-Commit-Position: refs/heads/master@{#10361}
This commit is contained in:
solenberg 2015-10-21 13:01:53 -07:00 committed by Commit bot
parent f4d23b2254
commit c96df779b0
5 changed files with 192 additions and 98 deletions

View File

@ -34,6 +34,20 @@
#include "webrtc/base/gunit.h" #include "webrtc/base/gunit.h"
namespace cricket { namespace cricket {
FakeAudioSendStream::FakeAudioSendStream(
const webrtc::AudioSendStream::Config& config) : config_(config) {
RTC_DCHECK(config.voe_channel_id != -1);
}
webrtc::AudioSendStream::Stats FakeAudioSendStream::GetStats() const {
return webrtc::AudioSendStream::Stats();
}
const webrtc::AudioSendStream::Config&
FakeAudioSendStream::GetConfig() const {
return config_;
}
FakeAudioReceiveStream::FakeAudioReceiveStream( FakeAudioReceiveStream::FakeAudioReceiveStream(
const webrtc::AudioReceiveStream::Config& config) const webrtc::AudioReceiveStream::Config& config)
: config_(config), received_packets_(0) { : config_(config), received_packets_(0) {
@ -206,6 +220,7 @@ FakeCall::FakeCall(const webrtc::Call::Config& config)
FakeCall::~FakeCall() { FakeCall::~FakeCall() {
EXPECT_EQ(0u, video_send_streams_.size()); EXPECT_EQ(0u, video_send_streams_.size());
EXPECT_EQ(0u, audio_send_streams_.size());
EXPECT_EQ(0u, video_receive_streams_.size()); EXPECT_EQ(0u, video_receive_streams_.size());
EXPECT_EQ(0u, audio_receive_streams_.size()); EXPECT_EQ(0u, audio_receive_streams_.size());
} }
@ -222,12 +237,25 @@ const std::vector<FakeVideoReceiveStream*>& FakeCall::GetVideoReceiveStreams() {
return video_receive_streams_; return video_receive_streams_;
} }
const std::vector<FakeAudioSendStream*>& FakeCall::GetAudioSendStreams() {
return audio_send_streams_;
}
const FakeAudioSendStream* FakeCall::GetAudioSendStream(uint32_t ssrc) {
for (const auto* p : GetAudioSendStreams()) {
if (p->GetConfig().rtp.ssrc == ssrc) {
return p;
}
}
return nullptr;
}
const std::vector<FakeAudioReceiveStream*>& FakeCall::GetAudioReceiveStreams() { const std::vector<FakeAudioReceiveStream*>& FakeCall::GetAudioReceiveStreams() {
return audio_receive_streams_; return audio_receive_streams_;
} }
const FakeAudioReceiveStream* FakeCall::GetAudioReceiveStream(uint32_t ssrc) { const FakeAudioReceiveStream* FakeCall::GetAudioReceiveStream(uint32_t ssrc) {
for (const auto p : GetAudioReceiveStreams()) { for (const auto* p : GetAudioReceiveStreams()) {
if (p->GetConfig().rtp.remote_ssrc == ssrc) { if (p->GetConfig().rtp.remote_ssrc == ssrc) {
return p; return p;
} }
@ -241,10 +269,22 @@ webrtc::NetworkState FakeCall::GetNetworkState() const {
webrtc::AudioSendStream* FakeCall::CreateAudioSendStream( webrtc::AudioSendStream* FakeCall::CreateAudioSendStream(
const webrtc::AudioSendStream::Config& config) { const webrtc::AudioSendStream::Config& config) {
return nullptr; FakeAudioSendStream* fake_stream = new FakeAudioSendStream(config);
audio_send_streams_.push_back(fake_stream);
++num_created_send_streams_;
return fake_stream;
} }
void FakeCall::DestroyAudioSendStream(webrtc::AudioSendStream* send_stream) { void FakeCall::DestroyAudioSendStream(webrtc::AudioSendStream* send_stream) {
auto it = std::find(audio_send_streams_.begin(),
audio_send_streams_.end(),
static_cast<FakeAudioSendStream*>(send_stream));
if (it == audio_send_streams_.end()) {
ADD_FAILURE() << "DestroyAudioSendStream called with unknown paramter.";
} else {
delete *it;
audio_send_streams_.erase(it);
}
} }
webrtc::AudioReceiveStream* FakeCall::CreateAudioReceiveStream( webrtc::AudioReceiveStream* FakeCall::CreateAudioReceiveStream(

View File

@ -25,6 +25,15 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
// This file contains fake implementations, for use in unit tests, of the
// following classes:
//
// webrtc::Call
// webrtc::AudioSendStream
// webrtc::AudioReceiveStream
// webrtc::VideoSendStream
// webrtc::VideoReceiveStream
#ifndef TALK_MEDIA_WEBRTC_FAKEWEBRTCCALL_H_ #ifndef TALK_MEDIA_WEBRTC_FAKEWEBRTCCALL_H_
#define TALK_MEDIA_WEBRTC_FAKEWEBRTCCALL_H_ #define TALK_MEDIA_WEBRTC_FAKEWEBRTCCALL_H_
@ -32,11 +41,35 @@
#include "webrtc/call.h" #include "webrtc/call.h"
#include "webrtc/audio_receive_stream.h" #include "webrtc/audio_receive_stream.h"
#include "webrtc/audio_send_stream.h"
#include "webrtc/video_frame.h" #include "webrtc/video_frame.h"
#include "webrtc/video_receive_stream.h" #include "webrtc/video_receive_stream.h"
#include "webrtc/video_send_stream.h" #include "webrtc/video_send_stream.h"
namespace cricket { namespace cricket {
class FakeAudioSendStream : public webrtc::AudioSendStream {
public:
explicit FakeAudioSendStream(
const webrtc::AudioSendStream::Config& config);
// webrtc::AudioSendStream implementation.
webrtc::AudioSendStream::Stats GetStats() const override;
const webrtc::AudioSendStream::Config& GetConfig() const;
private:
// webrtc::SendStream implementation.
void Start() override {}
void Stop() override {}
void SignalNetworkState(webrtc::NetworkState state) override {}
bool DeliverRtcp(const uint8_t* packet, size_t length) override {
return true;
}
webrtc::AudioSendStream::Config config_;
};
class FakeAudioReceiveStream : public webrtc::AudioReceiveStream { class FakeAudioReceiveStream : public webrtc::AudioReceiveStream {
public: public:
explicit FakeAudioReceiveStream( explicit FakeAudioReceiveStream(
@ -161,6 +194,8 @@ class FakeCall : public webrtc::Call, public webrtc::PacketReceiver {
const std::vector<FakeVideoSendStream*>& GetVideoSendStreams(); const std::vector<FakeVideoSendStream*>& GetVideoSendStreams();
const std::vector<FakeVideoReceiveStream*>& GetVideoReceiveStreams(); const std::vector<FakeVideoReceiveStream*>& GetVideoReceiveStreams();
const std::vector<FakeAudioSendStream*>& GetAudioSendStreams();
const FakeAudioSendStream* GetAudioSendStream(uint32_t ssrc);
const std::vector<FakeAudioReceiveStream*>& GetAudioReceiveStreams(); const std::vector<FakeAudioReceiveStream*>& GetAudioReceiveStreams();
const FakeAudioReceiveStream* GetAudioReceiveStream(uint32_t ssrc); const FakeAudioReceiveStream* GetAudioReceiveStream(uint32_t ssrc);
@ -208,6 +243,7 @@ class FakeCall : public webrtc::Call, public webrtc::PacketReceiver {
rtc::SentPacket last_sent_packet_; rtc::SentPacket last_sent_packet_;
webrtc::Call::Stats stats_; webrtc::Call::Stats stats_;
std::vector<FakeVideoSendStream*> video_send_streams_; std::vector<FakeVideoSendStream*> video_send_streams_;
std::vector<FakeAudioSendStream*> audio_send_streams_;
std::vector<FakeVideoReceiveStream*> video_receive_streams_; std::vector<FakeVideoReceiveStream*> video_receive_streams_;
std::vector<FakeAudioReceiveStream*> audio_receive_streams_; std::vector<FakeAudioReceiveStream*> audio_receive_streams_;

View File

@ -1313,15 +1313,25 @@ int WebRtcVoiceEngine::CreateVoEChannel() {
return voe_wrapper_->base()->CreateChannel(voe_config_); return voe_wrapper_->base()->CreateChannel(voe_config_);
} }
class WebRtcVoiceMediaChannel::WebRtcVoiceChannelRenderer class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
: public AudioRenderer::Sink { : public AudioRenderer::Sink {
public: public:
WebRtcVoiceChannelRenderer(int ch, WebRtcAudioSendStream(int ch, webrtc::AudioTransport* voe_audio_transport,
webrtc::AudioTransport* voe_audio_transport) uint32_t ssrc, webrtc::Call* call)
: channel_(ch), : channel_(ch),
voe_audio_transport_(voe_audio_transport), voe_audio_transport_(voe_audio_transport),
renderer_(NULL) {} call_(call) {
~WebRtcVoiceChannelRenderer() override { Stop(); } RTC_DCHECK(call);
webrtc::AudioSendStream::Config config(nullptr);
config.voe_channel_id = channel_;
config.rtp.ssrc = ssrc;
stream_ = call_->CreateAudioSendStream(config);
RTC_DCHECK(stream_);
}
~WebRtcAudioSendStream() override {
Stop();
call_->DestroyAudioSendStream(stream_);
}
// Starts the rendering by setting a sink to the renderer to get data // Starts the rendering by setting a sink to the renderer to get data
// callback. // callback.
@ -1329,8 +1339,8 @@ class WebRtcVoiceMediaChannel::WebRtcVoiceChannelRenderer
// TODO(xians): Make sure Start() is called only once. // TODO(xians): Make sure Start() is called only once.
void Start(AudioRenderer* renderer) { void Start(AudioRenderer* renderer) {
rtc::CritScope lock(&lock_); rtc::CritScope lock(&lock_);
RTC_DCHECK(renderer != NULL); RTC_DCHECK(renderer);
if (renderer_ != NULL) { if (renderer_) {
RTC_DCHECK(renderer_ == renderer); RTC_DCHECK(renderer_ == renderer);
return; return;
} }
@ -1338,14 +1348,14 @@ class WebRtcVoiceMediaChannel::WebRtcVoiceChannelRenderer
renderer_ = renderer; renderer_ = renderer;
} }
// Stops rendering by setting the sink of the renderer to NULL. No data // Stops rendering by setting the sink of the renderer to nullptr. No data
// callback will be received after this method. // callback will be received after this method.
// This method is called on the libjingle worker thread. // This method is called on the libjingle worker thread.
void Stop() { void Stop() {
rtc::CritScope lock(&lock_); rtc::CritScope lock(&lock_);
if (renderer_ != NULL) { if (renderer_) {
renderer_->SetSink(NULL); renderer_->SetSink(nullptr);
renderer_ = NULL; renderer_ = nullptr;
} }
} }
@ -1356,6 +1366,7 @@ class WebRtcVoiceMediaChannel::WebRtcVoiceChannelRenderer
int sample_rate, int sample_rate,
int number_of_channels, int number_of_channels,
size_t number_of_frames) override { size_t number_of_frames) override {
RTC_DCHECK(voe_audio_transport_);
voe_audio_transport_->OnData(channel_, voe_audio_transport_->OnData(channel_,
audio_data, audio_data,
bits_per_sample, bits_per_sample,
@ -1368,25 +1379,42 @@ class WebRtcVoiceMediaChannel::WebRtcVoiceChannelRenderer
// never been called, this callback won't be triggered. // never been called, this callback won't be triggered.
void OnClose() override { void OnClose() override {
rtc::CritScope lock(&lock_); rtc::CritScope lock(&lock_);
// Set |renderer_| to NULL to make sure no more callback will get into // Set |renderer_| to nullptr to make sure no more callback will get into
// the renderer. // the renderer.
renderer_ = NULL; renderer_ = nullptr;
} }
// Accessor to the VoE channel ID. // Accessor to the VoE channel ID.
int channel() const { return channel_; } int channel() const { return channel_; }
private: private:
const int channel_; const int channel_ = -1;
webrtc::AudioTransport* const voe_audio_transport_; webrtc::AudioTransport* const voe_audio_transport_ = nullptr;
webrtc::Call* call_ = nullptr;
webrtc::AudioSendStream* stream_ = nullptr;
// Raw pointer to AudioRenderer owned by LocalAudioTrackHandler. // Raw pointer to AudioRenderer owned by LocalAudioTrackHandler.
// PeerConnection will make sure invalidating the pointer before the object // PeerConnection will make sure invalidating the pointer before the object
// goes away. // goes away.
AudioRenderer* renderer_; AudioRenderer* renderer_ = nullptr;
// Protects |renderer_| in Start(), Stop() and OnClose(). // Protects |renderer_| in Start(), Stop() and OnClose().
rtc::CriticalSection lock_; rtc::CriticalSection lock_;
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioSendStream);
};
class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream {
public:
explicit WebRtcAudioReceiveStream(int voe_channel_id)
: channel_(voe_channel_id) {}
int channel() { return channel_; }
private:
int channel_;
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioReceiveStream);
}; };
// WebRtcVoiceMediaChannel // WebRtcVoiceMediaChannel
@ -1417,8 +1445,8 @@ WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel() {
LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel"; LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel";
// Remove any remaining send streams. // Remove any remaining send streams.
while (!send_channels_.empty()) { while (!send_streams_.empty()) {
RemoveSendStream(send_channels_.begin()->first); RemoveSendStream(send_streams_.begin()->first);
} }
// Remove any remaining receive streams. // Remove any remaining receive streams.
@ -1481,6 +1509,7 @@ bool WebRtcVoiceMediaChannel::SetOptions(const AudioOptions& options) {
} }
} }
// TODO(solenberg): Don't recreate unless options changed.
RecreateAudioReceiveStreams(); RecreateAudioReceiveStreams();
LOG(LS_INFO) << "Set voice channel options. Current options: " LOG(LS_INFO) << "Set voice channel options. Current options: "
@ -1760,7 +1789,7 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs(
// Cache the codecs in order to configure the channel created later. // Cache the codecs in order to configure the channel created later.
send_codecs_ = codecs; send_codecs_ = codecs;
for (const auto& ch : send_channels_) { for (const auto& ch : send_streams_) {
if (!SetSendCodecs(ch.second->channel(), codecs)) { if (!SetSendCodecs(ch.second->channel(), codecs)) {
return false; return false;
} }
@ -1871,7 +1900,7 @@ bool WebRtcVoiceMediaChannel::SetSendRtpHeaderExtensions(
return true; return true;
} }
for (const auto& ch : send_channels_) { for (const auto& ch : send_streams_) {
if (!SetChannelSendRtpHeaderExtensions(ch.second->channel(), extensions)) { if (!SetChannelSendRtpHeaderExtensions(ch.second->channel(), extensions)) {
return false; return false;
} }
@ -1935,8 +1964,9 @@ bool WebRtcVoiceMediaChannel::ChangePlayout(bool playout) {
bool WebRtcVoiceMediaChannel::SetSend(SendFlags send) { bool WebRtcVoiceMediaChannel::SetSend(SendFlags send) {
desired_send_ = send; desired_send_ = send;
if (!send_channels_.empty()) if (!send_streams_.empty()) {
return ChangeSend(desired_send_); return ChangeSend(desired_send_);
}
return true; return true;
} }
@ -1959,7 +1989,7 @@ bool WebRtcVoiceMediaChannel::ChangeSend(SendFlags send) {
} }
// Change the settings on each send channel. // Change the settings on each send channel.
for (const auto& ch : send_channels_) { for (const auto& ch : send_streams_) {
if (!ChangeSend(ch.second->channel(), send)) { if (!ChangeSend(ch.second->channel(), send)) {
return false; return false;
} }
@ -2075,13 +2105,13 @@ bool WebRtcVoiceMediaChannel::AddSendStream(const StreamParams& sp) {
return false; return false;
} }
// Save the channel to send_channels_, so that RemoveSendStream() can still // Save the channel to send_streams_, so that RemoveSendStream() can still
// delete the channel in case failure happens below. // delete the channel in case failure happens below.
webrtc::AudioTransport* audio_transport = webrtc::AudioTransport* audio_transport =
engine()->voe()->base()->audio_transport(); engine()->voe()->base()->audio_transport();
send_channels_.insert( send_streams_.insert(
std::make_pair(ssrc, std::make_pair(ssrc,
new WebRtcVoiceChannelRenderer(channel, audio_transport))); new WebRtcAudioSendStream(channel, audio_transport, ssrc, call_)));
// Set the current codecs to be used for the new channel. We need to do this // Set the current codecs to be used for the new channel. We need to do this
// after adding the channel to send_channels_, because of how max bitrate is // after adding the channel to send_channels_, because of how max bitrate is
@ -2094,7 +2124,7 @@ bool WebRtcVoiceMediaChannel::AddSendStream(const StreamParams& sp) {
// At this point the channel's local SSRC has been updated. If the channel is // At this point the channel's local SSRC has been updated. If the channel is
// the first send channel make sure that all the receive channels are updated // the first send channel make sure that all the receive channels are updated
// with the same SSRC in order to send receiver reports. // with the same SSRC in order to send receiver reports.
if (send_channels_.size() == 1) { if (send_streams_.size() == 1) {
receiver_reports_ssrc_ = ssrc; receiver_reports_ssrc_ = ssrc;
for (const auto& ch : receive_channels_) { for (const auto& ch : receive_channels_) {
int recv_channel = ch.second->channel(); int recv_channel = ch.second->channel();
@ -2113,8 +2143,8 @@ bool WebRtcVoiceMediaChannel::AddSendStream(const StreamParams& sp) {
bool WebRtcVoiceMediaChannel::RemoveSendStream(uint32_t ssrc) { bool WebRtcVoiceMediaChannel::RemoveSendStream(uint32_t ssrc) {
RTC_DCHECK(thread_checker_.CalledOnValidThread()); RTC_DCHECK(thread_checker_.CalledOnValidThread());
ChannelMap::iterator it = send_channels_.find(ssrc); auto it = send_streams_.find(ssrc);
if (it == send_channels_.end()) { if (it == send_streams_.end()) {
LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc
<< " which doesn't exist."; << " which doesn't exist.";
return false; return false;
@ -2126,7 +2156,7 @@ bool WebRtcVoiceMediaChannel::RemoveSendStream(uint32_t ssrc) {
// Delete the WebRtcVoiceChannelRenderer object connected to the channel, // Delete the WebRtcVoiceChannelRenderer object connected to the channel,
// this will disconnect the audio renderer with the send channel. // this will disconnect the audio renderer with the send channel.
delete it->second; delete it->second;
send_channels_.erase(it); send_streams_.erase(it);
// Clean up and delete the send channel. // Clean up and delete the send channel.
LOG(LS_INFO) << "Removing audio send stream " << ssrc LOG(LS_INFO) << "Removing audio send stream " << ssrc
@ -2134,7 +2164,7 @@ bool WebRtcVoiceMediaChannel::RemoveSendStream(uint32_t ssrc) {
if (!DeleteChannel(channel)) { if (!DeleteChannel(channel)) {
return false; return false;
} }
if (send_channels_.empty()) { if (send_streams_.empty()) {
ChangeSend(SEND_NOTHING); ChangeSend(SEND_NOTHING);
} }
return true; return true;
@ -2176,11 +2206,8 @@ bool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) {
return false; return false;
} }
webrtc::AudioTransport* audio_transport = WebRtcAudioReceiveStream* stream = new WebRtcAudioReceiveStream(channel);
engine()->voe()->base()->audio_transport(); receive_channels_.insert(std::make_pair(ssrc, stream));
WebRtcVoiceChannelRenderer* channel_renderer =
new WebRtcVoiceChannelRenderer(channel, audio_transport);
receive_channels_.insert(std::make_pair(ssrc, channel_renderer));
receive_stream_params_[ssrc] = sp; receive_stream_params_[ssrc] = sp;
AddAudioReceiveStream(ssrc); AddAudioReceiveStream(ssrc);
@ -2249,7 +2276,7 @@ bool WebRtcVoiceMediaChannel::RemoveRecvStream(uint32_t ssrc) {
RTC_DCHECK(thread_checker_.CalledOnValidThread()); RTC_DCHECK(thread_checker_.CalledOnValidThread());
LOG(LS_INFO) << "RemoveRecvStream: " << ssrc; LOG(LS_INFO) << "RemoveRecvStream: " << ssrc;
ChannelMap::iterator it = receive_channels_.find(ssrc); auto it = receive_channels_.find(ssrc);
if (it == receive_channels_.end()) { if (it == receive_channels_.end()) {
LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc
<< " which doesn't exist."; << " which doesn't exist.";
@ -2259,9 +2286,6 @@ bool WebRtcVoiceMediaChannel::RemoveRecvStream(uint32_t ssrc) {
RemoveAudioReceiveStream(ssrc); RemoveAudioReceiveStream(ssrc);
receive_stream_params_.erase(ssrc); receive_stream_params_.erase(ssrc);
// Delete the WebRtcVoiceChannelRenderer object connected to the channel, this
// will disconnect the audio renderer with the receive channel.
// Cache the channel before the deletion.
const int channel = it->second->channel(); const int channel = it->second->channel();
delete it->second; delete it->second;
receive_channels_.erase(it); receive_channels_.erase(it);
@ -2278,8 +2302,8 @@ bool WebRtcVoiceMediaChannel::RemoveRecvStream(uint32_t ssrc) {
bool WebRtcVoiceMediaChannel::SetLocalRenderer(uint32_t ssrc, bool WebRtcVoiceMediaChannel::SetLocalRenderer(uint32_t ssrc,
AudioRenderer* renderer) { AudioRenderer* renderer) {
ChannelMap::iterator it = send_channels_.find(ssrc); auto it = send_streams_.find(ssrc);
if (it == send_channels_.end()) { if (it == send_streams_.end()) {
if (renderer) { if (renderer) {
// Return an error if trying to set a valid renderer with an invalid ssrc. // Return an error if trying to set a valid renderer with an invalid ssrc.
LOG(LS_ERROR) << "SetLocalRenderer failed with ssrc "<< ssrc; LOG(LS_ERROR) << "SetLocalRenderer failed with ssrc "<< ssrc;
@ -2388,8 +2412,8 @@ bool WebRtcVoiceMediaChannel::InsertDtmf(uint32_t ssrc,
if (flags & cricket::DF_SEND) { if (flags & cricket::DF_SEND) {
int channel = -1; int channel = -1;
if (ssrc == 0) { if (ssrc == 0) {
if (send_channels_.size() > 0) { if (send_streams_.size() > 0) {
channel = send_channels_.begin()->second->channel(); channel = send_streams_.begin()->second->channel();
} }
} else { } else {
channel = GetSendChannelId(ssrc); channel = GetSendChannelId(ssrc);
@ -2499,7 +2523,7 @@ void WebRtcVoiceMediaChannel::OnRtcpReceived(
// SR may continue RR and any RR entry may correspond to any one of the send // SR may continue RR and any RR entry may correspond to any one of the send
// channels. So all RTCP packets must be forwarded all send channels. VoE // channels. So all RTCP packets must be forwarded all send channels. VoE
// will filter out RR internally. // will filter out RR internally.
for (const auto& ch : send_channels_) { for (const auto& ch : send_streams_) {
engine()->voe()->network()->ReceivedRTCPPacket( engine()->voe()->network()->ReceivedRTCPPacket(
ch.second->channel(), packet->data(), packet->size()); ch.second->channel(), packet->data(), packet->size());
} }
@ -2521,7 +2545,7 @@ bool WebRtcVoiceMediaChannel::MuteStream(uint32_t ssrc, bool muted) {
// the mic channel is muted/unmuted. We can't do it today because there // the mic channel is muted/unmuted. We can't do it today because there
// is no good way to know which stream is mapping to the mic channel. // is no good way to know which stream is mapping to the mic channel.
bool all_muted = muted; bool all_muted = muted;
for (const auto& ch : send_channels_) { for (const auto& ch : send_streams_) {
if (!all_muted) { if (!all_muted) {
break; break;
} }
@ -2570,7 +2594,7 @@ bool WebRtcVoiceMediaChannel::SetSendBitrateInternal(int bps) {
if (is_multi_rate) { if (is_multi_rate) {
// If codec is multi-rate then just set the bitrate. // If codec is multi-rate then just set the bitrate.
codec.rate = bps; codec.rate = bps;
for (const auto& ch : send_channels_) { for (const auto& ch : send_streams_) {
if (!SetSendCodec(ch.second->channel(), codec)) { if (!SetSendCodec(ch.second->channel(), codec)) {
LOG(LS_INFO) << "Failed to set codec " << codec.plname LOG(LS_INFO) << "Failed to set codec " << codec.plname
<< " to bitrate " << bps << " bps."; << " to bitrate " << bps << " bps.";
@ -2630,7 +2654,7 @@ bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) {
webrtc::CodecInst codec; webrtc::CodecInst codec;
unsigned int level; unsigned int level;
for (const auto& ch : send_channels_) { for (const auto& ch : send_streams_) {
const int channel = ch.second->channel(); const int channel = ch.second->channel();
// Fill in the sender info, based on what we know, and what the // Fill in the sender info, based on what we know, and what the
@ -2791,7 +2815,7 @@ int WebRtcVoiceMediaChannel::GetOutputLevel(int channel) {
int WebRtcVoiceMediaChannel::GetReceiveChannelId(uint32_t ssrc) const { int WebRtcVoiceMediaChannel::GetReceiveChannelId(uint32_t ssrc) const {
RTC_DCHECK(thread_checker_.CalledOnValidThread()); RTC_DCHECK(thread_checker_.CalledOnValidThread());
ChannelMap::const_iterator it = receive_channels_.find(ssrc); const auto it = receive_channels_.find(ssrc);
if (it != receive_channels_.end()) { if (it != receive_channels_.end()) {
return it->second->channel(); return it->second->channel();
} }
@ -2800,8 +2824,8 @@ int WebRtcVoiceMediaChannel::GetReceiveChannelId(uint32_t ssrc) const {
int WebRtcVoiceMediaChannel::GetSendChannelId(uint32_t ssrc) const { int WebRtcVoiceMediaChannel::GetSendChannelId(uint32_t ssrc) const {
RTC_DCHECK(thread_checker_.CalledOnValidThread()); RTC_DCHECK(thread_checker_.CalledOnValidThread());
ChannelMap::const_iterator it = send_channels_.find(ssrc); const auto it = send_streams_.find(ssrc);
if (it != send_channels_.end()) { if (it != send_streams_.end()) {
return it->second->channel(); return it->second->channel();
} }
return -1; return -1;
@ -2927,8 +2951,8 @@ void WebRtcVoiceMediaChannel::RecreateAudioReceiveStreams() {
void WebRtcVoiceMediaChannel::AddAudioReceiveStream(uint32_t ssrc) { void WebRtcVoiceMediaChannel::AddAudioReceiveStream(uint32_t ssrc) {
RTC_DCHECK(thread_checker_.CalledOnValidThread()); RTC_DCHECK(thread_checker_.CalledOnValidThread());
WebRtcVoiceChannelRenderer* channel = receive_channels_[ssrc]; WebRtcAudioReceiveStream* stream = receive_channels_[ssrc];
RTC_DCHECK(channel != nullptr); RTC_DCHECK(stream != nullptr);
RTC_DCHECK(receive_streams_.find(ssrc) == receive_streams_.end()); RTC_DCHECK(receive_streams_.find(ssrc) == receive_streams_.end());
webrtc::AudioReceiveStream::Config config; webrtc::AudioReceiveStream::Config config;
config.rtp.remote_ssrc = ssrc; config.rtp.remote_ssrc = ssrc;
@ -2936,7 +2960,7 @@ void WebRtcVoiceMediaChannel::AddAudioReceiveStream(uint32_t ssrc) {
config.rtp.extensions = recv_rtp_extensions_; config.rtp.extensions = recv_rtp_extensions_;
config.combined_audio_video_bwe = config.combined_audio_video_bwe =
options_.combined_audio_video_bwe.GetWithDefaultIfUnset(false); options_.combined_audio_video_bwe.GetWithDefaultIfUnset(false);
config.voe_channel_id = channel->channel(); config.voe_channel_id = stream->channel();
config.sync_group = receive_stream_params_[ssrc].sync_label; config.sync_group = receive_stream_params_[ssrc].sync_label;
webrtc::AudioReceiveStream* s = call_->CreateAudioReceiveStream(config); webrtc::AudioReceiveStream* s = call_->CreateAudioReceiveStream(config);
receive_streams_.insert(std::make_pair(ssrc, s)); receive_streams_.insert(std::make_pair(ssrc, s));

View File

@ -172,6 +172,8 @@ class WebRtcVoiceEngine
Settable<bool> extended_filter_aec_; Settable<bool> extended_filter_aec_;
Settable<bool> delay_agnostic_aec_; Settable<bool> delay_agnostic_aec_;
Settable<bool> experimental_ns_; Settable<bool> experimental_ns_;
RTC_DISALLOW_COPY_AND_ASSIGN(WebRtcVoiceEngine);
}; };
// WebRtcVoiceMediaChannel is an implementation of VoiceMediaChannel that uses // WebRtcVoiceMediaChannel is an implementation of VoiceMediaChannel that uses
@ -265,11 +267,6 @@ class WebRtcVoiceMediaChannel : public VoiceMediaChannel,
bool SetPlayout(int channel, bool playout); bool SetPlayout(int channel, bool playout);
static Error WebRtcErrorToChannelError(int err_code); static Error WebRtcErrorToChannelError(int err_code);
class WebRtcVoiceChannelRenderer;
// Map of ssrc to WebRtcVoiceChannelRenderer object. A new object of
// WebRtcVoiceChannelRenderer will be created for every new stream and
// will be destroyed when the stream goes away.
typedef std::map<uint32_t, WebRtcVoiceChannelRenderer*> ChannelMap;
typedef int (webrtc::VoERTP_RTCP::* ExtensionSetterFunction)(int, bool, typedef int (webrtc::VoERTP_RTCP::* ExtensionSetterFunction)(int, bool,
unsigned char); unsigned char);
@ -327,12 +324,12 @@ class WebRtcVoiceMediaChannel : public VoiceMediaChannel,
// send streams. See: https://code.google.com/p/webrtc/issues/detail?id=4740 // send streams. See: https://code.google.com/p/webrtc/issues/detail?id=4740
uint32_t receiver_reports_ssrc_ = 1; uint32_t receiver_reports_ssrc_ = 1;
// send_channels_ contains the channels which are being used for sending. class WebRtcAudioSendStream;
// When the default channel (default_send_channel_id) is used for sending, it std::map<uint32_t, WebRtcAudioSendStream*> send_streams_;
// is contained in send_channels_, otherwise not.
ChannelMap send_channels_;
std::vector<RtpHeaderExtension> send_extensions_; std::vector<RtpHeaderExtension> send_extensions_;
ChannelMap receive_channels_;
class WebRtcAudioReceiveStream;
std::map<uint32_t, WebRtcAudioReceiveStream*> receive_channels_;
std::map<uint32_t, webrtc::AudioReceiveStream*> receive_streams_; std::map<uint32_t, webrtc::AudioReceiveStream*> receive_streams_;
std::map<uint32_t, StreamParams> receive_stream_params_; std::map<uint32_t, StreamParams> receive_stream_params_;
// receive_channels_ can be read from WebRtc callback thread. Access from // receive_channels_ can be read from WebRtc callback thread. Access from
@ -340,6 +337,8 @@ class WebRtcVoiceMediaChannel : public VoiceMediaChannel,
// Reads on the worker thread are ok. // Reads on the worker thread are ok.
std::vector<RtpHeaderExtension> receive_extensions_; std::vector<RtpHeaderExtension> receive_extensions_;
std::vector<webrtc::RtpExtension> recv_rtp_extensions_; std::vector<webrtc::RtpExtension> recv_rtp_extensions_;
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcVoiceMediaChannel);
}; };
} // namespace cricket } // namespace cricket

View File

@ -59,6 +59,7 @@ static const cricket::AudioCodec* const kAudioCodecs[] = {
}; };
static uint32_t kSsrc1 = 0x99; static uint32_t kSsrc1 = 0x99;
static uint32_t kSsrc2 = 0x98; static uint32_t kSsrc2 = 0x98;
static const uint32_t kSsrcs4[] = {1, 2, 3, 4};
class FakeVoEWrapper : public cricket::VoEWrapper { class FakeVoEWrapper : public cricket::VoEWrapper {
public: public:
@ -1862,44 +1863,39 @@ TEST_F(WebRtcVoiceEngineTestFake, Playout) {
TEST_F(WebRtcVoiceEngineTestFake, CreateAndDeleteMultipleSendStreams) { TEST_F(WebRtcVoiceEngineTestFake, CreateAndDeleteMultipleSendStreams) {
SetupForMultiSendStream(); SetupForMultiSendStream();
static const uint32_t kSsrcs4[] = {1, 2, 3, 4};
// Set the global state for sending. // Set the global state for sending.
EXPECT_TRUE(channel_->SetSend(cricket::SEND_MICROPHONE)); EXPECT_TRUE(channel_->SetSend(cricket::SEND_MICROPHONE));
for (unsigned int i = 0; i < ARRAY_SIZE(kSsrcs4); ++i) { for (uint32_t ssrc : kSsrcs4) {
EXPECT_TRUE(channel_->AddSendStream( EXPECT_TRUE(channel_->AddSendStream(
cricket::StreamParams::CreateLegacy(kSsrcs4[i]))); cricket::StreamParams::CreateLegacy(ssrc)));
EXPECT_NE(nullptr, call_.GetAudioSendStream(ssrc));
// Verify that we are in a sending state for all the created streams. // Verify that we are in a sending state for all the created streams.
int channel_num = voe_.GetChannelFromLocalSsrc(kSsrcs4[i]); int channel_num = voe_.GetChannelFromLocalSsrc(ssrc);
EXPECT_TRUE(voe_.GetSend(channel_num)); EXPECT_TRUE(voe_.GetSend(channel_num));
} }
EXPECT_EQ(ARRAY_SIZE(kSsrcs4), call_.GetAudioSendStreams().size());
// Remove the first send channel, which is the default channel. It will only // Delete the send streams.
// recycle the default channel but not delete it. for (uint32_t ssrc : kSsrcs4) {
EXPECT_TRUE(channel_->RemoveSendStream(kSsrcs4[0])); EXPECT_TRUE(channel_->RemoveSendStream(ssrc));
// Stream should already be Removed from the send stream list. EXPECT_EQ(nullptr, call_.GetAudioSendStream(ssrc));
EXPECT_FALSE(channel_->RemoveSendStream(kSsrcs4[0]));
// Delete the rest of send channel streams.
for (unsigned int i = 1; i < ARRAY_SIZE(kSsrcs4); ++i) {
EXPECT_TRUE(channel_->RemoveSendStream(kSsrcs4[i]));
// Stream should already be deleted. // Stream should already be deleted.
EXPECT_FALSE(channel_->RemoveSendStream(kSsrcs4[i])); EXPECT_FALSE(channel_->RemoveSendStream(ssrc));
EXPECT_EQ(-1, voe_.GetChannelFromLocalSsrc(kSsrcs4[i])); EXPECT_EQ(-1, voe_.GetChannelFromLocalSsrc(ssrc));
} }
EXPECT_EQ(0u, call_.GetAudioSendStreams().size());
} }
// Test SetSendCodecs correctly configure the codecs in all send streams. // Test SetSendCodecs correctly configure the codecs in all send streams.
TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsWithMultipleSendStreams) { TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsWithMultipleSendStreams) {
SetupForMultiSendStream(); SetupForMultiSendStream();
static const uint32_t kSsrcs4[] = {1, 2, 3, 4};
// Create send streams. // Create send streams.
for (unsigned int i = 0; i < ARRAY_SIZE(kSsrcs4); ++i) { for (uint32_t ssrc : kSsrcs4) {
EXPECT_TRUE(channel_->AddSendStream( EXPECT_TRUE(channel_->AddSendStream(
cricket::StreamParams::CreateLegacy(kSsrcs4[i]))); cricket::StreamParams::CreateLegacy(ssrc)));
} }
cricket::AudioSendParameters parameters; cricket::AudioSendParameters parameters;
@ -1911,8 +1907,8 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsWithMultipleSendStreams) {
// Verify ISAC and VAD are corrected configured on all send channels. // Verify ISAC and VAD are corrected configured on all send channels.
webrtc::CodecInst gcodec; webrtc::CodecInst gcodec;
for (unsigned int i = 0; i < ARRAY_SIZE(kSsrcs4); ++i) { for (uint32_t ssrc : kSsrcs4) {
int channel_num = voe_.GetChannelFromLocalSsrc(kSsrcs4[i]); int channel_num = voe_.GetChannelFromLocalSsrc(ssrc);
EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
EXPECT_STREQ("ISAC", gcodec.plname); EXPECT_STREQ("ISAC", gcodec.plname);
EXPECT_TRUE(voe_.GetVAD(channel_num)); EXPECT_TRUE(voe_.GetVAD(channel_num));
@ -1922,8 +1918,8 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsWithMultipleSendStreams) {
// Change to PCMU(8K) and CN(16K). VAD should not be activated. // Change to PCMU(8K) and CN(16K). VAD should not be activated.
parameters.codecs[0] = kPcmuCodec; parameters.codecs[0] = kPcmuCodec;
EXPECT_TRUE(channel_->SetSendParameters(parameters)); EXPECT_TRUE(channel_->SetSendParameters(parameters));
for (unsigned int i = 0; i < ARRAY_SIZE(kSsrcs4); ++i) { for (uint32_t ssrc : kSsrcs4) {
int channel_num = voe_.GetChannelFromLocalSsrc(kSsrcs4[i]); int channel_num = voe_.GetChannelFromLocalSsrc(ssrc);
EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
EXPECT_STREQ("PCMU", gcodec.plname); EXPECT_STREQ("PCMU", gcodec.plname);
EXPECT_FALSE(voe_.GetVAD(channel_num)); EXPECT_FALSE(voe_.GetVAD(channel_num));
@ -1934,28 +1930,27 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsWithMultipleSendStreams) {
TEST_F(WebRtcVoiceEngineTestFake, SetSendWithMultipleSendStreams) { TEST_F(WebRtcVoiceEngineTestFake, SetSendWithMultipleSendStreams) {
SetupForMultiSendStream(); SetupForMultiSendStream();
static const uint32_t kSsrcs4[] = {1, 2, 3, 4};
// Create the send channels and they should be a SEND_NOTHING date. // Create the send channels and they should be a SEND_NOTHING date.
for (unsigned int i = 0; i < ARRAY_SIZE(kSsrcs4); ++i) { for (uint32_t ssrc : kSsrcs4) {
EXPECT_TRUE(channel_->AddSendStream( EXPECT_TRUE(channel_->AddSendStream(
cricket::StreamParams::CreateLegacy(kSsrcs4[i]))); cricket::StreamParams::CreateLegacy(ssrc)));
int channel_num = voe_.GetLastChannel(); int channel_num = voe_.GetLastChannel();
EXPECT_FALSE(voe_.GetSend(channel_num)); EXPECT_FALSE(voe_.GetSend(channel_num));
} }
// Set the global state for starting sending. // Set the global state for starting sending.
EXPECT_TRUE(channel_->SetSend(cricket::SEND_MICROPHONE)); EXPECT_TRUE(channel_->SetSend(cricket::SEND_MICROPHONE));
for (unsigned int i = 0; i < ARRAY_SIZE(kSsrcs4); ++i) { for (uint32_t ssrc : kSsrcs4) {
// Verify that we are in a sending state for all the send streams. // Verify that we are in a sending state for all the send streams.
int channel_num = voe_.GetChannelFromLocalSsrc(kSsrcs4[i]); int channel_num = voe_.GetChannelFromLocalSsrc(ssrc);
EXPECT_TRUE(voe_.GetSend(channel_num)); EXPECT_TRUE(voe_.GetSend(channel_num));
} }
// Set the global state for stopping sending. // Set the global state for stopping sending.
EXPECT_TRUE(channel_->SetSend(cricket::SEND_NOTHING)); EXPECT_TRUE(channel_->SetSend(cricket::SEND_NOTHING));
for (unsigned int i = 1; i < ARRAY_SIZE(kSsrcs4); ++i) { for (uint32_t ssrc : kSsrcs4) {
// Verify that we are in a stop state for all the send streams. // Verify that we are in a stop state for all the send streams.
int channel_num = voe_.GetChannelFromLocalSsrc(kSsrcs4[i]); int channel_num = voe_.GetChannelFromLocalSsrc(ssrc);
EXPECT_FALSE(voe_.GetSend(channel_num)); EXPECT_FALSE(voe_.GetSend(channel_num));
} }
} }
@ -1964,11 +1959,10 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendWithMultipleSendStreams) {
TEST_F(WebRtcVoiceEngineTestFake, GetStatsWithMultipleSendStreams) { TEST_F(WebRtcVoiceEngineTestFake, GetStatsWithMultipleSendStreams) {
SetupForMultiSendStream(); SetupForMultiSendStream();
static const uint32_t kSsrcs4[] = {1, 2, 3, 4};
// Create send streams. // Create send streams.
for (unsigned int i = 0; i < ARRAY_SIZE(kSsrcs4); ++i) { for (uint32_t ssrc : kSsrcs4) {
EXPECT_TRUE(channel_->AddSendStream( EXPECT_TRUE(channel_->AddSendStream(
cricket::StreamParams::CreateLegacy(kSsrcs4[i]))); cricket::StreamParams::CreateLegacy(ssrc)));
} }
// Create a receive stream to check that none of the send streams end up in // Create a receive stream to check that none of the send streams end up in
// the receive stream stats. // the receive stream stats.
@ -1983,6 +1977,7 @@ TEST_F(WebRtcVoiceEngineTestFake, GetStatsWithMultipleSendStreams) {
EXPECT_EQ(static_cast<size_t>(ARRAY_SIZE(kSsrcs4)), info.senders.size()); EXPECT_EQ(static_cast<size_t>(ARRAY_SIZE(kSsrcs4)), info.senders.size());
// Verify the statistic information is correct. // Verify the statistic information is correct.
// TODO(solenberg): Make this loop ordering independent.
for (unsigned int i = 0; i < ARRAY_SIZE(kSsrcs4); ++i) { for (unsigned int i = 0; i < ARRAY_SIZE(kSsrcs4); ++i) {
EXPECT_EQ(kSsrcs4[i], info.senders[i].ssrc()); EXPECT_EQ(kSsrcs4[i], info.senders[i].ssrc());
EXPECT_EQ(kPcmuCodec.name, info.senders[i].codec_name); EXPECT_EQ(kPcmuCodec.name, info.senders[i].codec_name);