diff --git a/talk/media/webrtc/fakewebrtccall.cc b/talk/media/webrtc/fakewebrtccall.cc index a0386b011e..6e2a88fce2 100644 --- a/talk/media/webrtc/fakewebrtccall.cc +++ b/talk/media/webrtc/fakewebrtccall.cc @@ -34,6 +34,20 @@ #include "webrtc/base/gunit.h" 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( const webrtc::AudioReceiveStream::Config& config) : config_(config), received_packets_(0) { @@ -206,6 +220,7 @@ FakeCall::FakeCall(const webrtc::Call::Config& config) FakeCall::~FakeCall() { EXPECT_EQ(0u, video_send_streams_.size()); + EXPECT_EQ(0u, audio_send_streams_.size()); EXPECT_EQ(0u, video_receive_streams_.size()); EXPECT_EQ(0u, audio_receive_streams_.size()); } @@ -222,12 +237,25 @@ const std::vector& FakeCall::GetVideoReceiveStreams() { return video_receive_streams_; } +const std::vector& 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& FakeCall::GetAudioReceiveStreams() { return audio_receive_streams_; } const FakeAudioReceiveStream* FakeCall::GetAudioReceiveStream(uint32_t ssrc) { - for (const auto p : GetAudioReceiveStreams()) { + for (const auto* p : GetAudioReceiveStreams()) { if (p->GetConfig().rtp.remote_ssrc == ssrc) { return p; } @@ -241,10 +269,22 @@ webrtc::NetworkState FakeCall::GetNetworkState() const { webrtc::AudioSendStream* FakeCall::CreateAudioSendStream( 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) { + auto it = std::find(audio_send_streams_.begin(), + audio_send_streams_.end(), + static_cast(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( diff --git a/talk/media/webrtc/fakewebrtccall.h b/talk/media/webrtc/fakewebrtccall.h index fb271f2215..de56a033bc 100644 --- a/talk/media/webrtc/fakewebrtccall.h +++ b/talk/media/webrtc/fakewebrtccall.h @@ -25,6 +25,15 @@ * 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_ #define TALK_MEDIA_WEBRTC_FAKEWEBRTCCALL_H_ @@ -32,11 +41,35 @@ #include "webrtc/call.h" #include "webrtc/audio_receive_stream.h" +#include "webrtc/audio_send_stream.h" #include "webrtc/video_frame.h" #include "webrtc/video_receive_stream.h" #include "webrtc/video_send_stream.h" 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 { public: explicit FakeAudioReceiveStream( @@ -161,6 +194,8 @@ class FakeCall : public webrtc::Call, public webrtc::PacketReceiver { const std::vector& GetVideoSendStreams(); const std::vector& GetVideoReceiveStreams(); + const std::vector& GetAudioSendStreams(); + const FakeAudioSendStream* GetAudioSendStream(uint32_t ssrc); const std::vector& GetAudioReceiveStreams(); const FakeAudioReceiveStream* GetAudioReceiveStream(uint32_t ssrc); @@ -208,6 +243,7 @@ class FakeCall : public webrtc::Call, public webrtc::PacketReceiver { rtc::SentPacket last_sent_packet_; webrtc::Call::Stats stats_; std::vector video_send_streams_; + std::vector audio_send_streams_; std::vector video_receive_streams_; std::vector audio_receive_streams_; diff --git a/talk/media/webrtc/webrtcvoiceengine.cc b/talk/media/webrtc/webrtcvoiceengine.cc index 5375358e0f..eed1195975 100644 --- a/talk/media/webrtc/webrtcvoiceengine.cc +++ b/talk/media/webrtc/webrtcvoiceengine.cc @@ -1313,15 +1313,25 @@ int WebRtcVoiceEngine::CreateVoEChannel() { return voe_wrapper_->base()->CreateChannel(voe_config_); } -class WebRtcVoiceMediaChannel::WebRtcVoiceChannelRenderer +class WebRtcVoiceMediaChannel::WebRtcAudioSendStream : public AudioRenderer::Sink { public: - WebRtcVoiceChannelRenderer(int ch, - webrtc::AudioTransport* voe_audio_transport) + WebRtcAudioSendStream(int ch, webrtc::AudioTransport* voe_audio_transport, + uint32_t ssrc, webrtc::Call* call) : channel_(ch), voe_audio_transport_(voe_audio_transport), - renderer_(NULL) {} - ~WebRtcVoiceChannelRenderer() override { Stop(); } + call_(call) { + 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 // callback. @@ -1329,8 +1339,8 @@ class WebRtcVoiceMediaChannel::WebRtcVoiceChannelRenderer // TODO(xians): Make sure Start() is called only once. void Start(AudioRenderer* renderer) { rtc::CritScope lock(&lock_); - RTC_DCHECK(renderer != NULL); - if (renderer_ != NULL) { + RTC_DCHECK(renderer); + if (renderer_) { RTC_DCHECK(renderer_ == renderer); return; } @@ -1338,14 +1348,14 @@ class WebRtcVoiceMediaChannel::WebRtcVoiceChannelRenderer 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. // This method is called on the libjingle worker thread. void Stop() { rtc::CritScope lock(&lock_); - if (renderer_ != NULL) { - renderer_->SetSink(NULL); - renderer_ = NULL; + if (renderer_) { + renderer_->SetSink(nullptr); + renderer_ = nullptr; } } @@ -1356,6 +1366,7 @@ class WebRtcVoiceMediaChannel::WebRtcVoiceChannelRenderer int sample_rate, int number_of_channels, size_t number_of_frames) override { + RTC_DCHECK(voe_audio_transport_); voe_audio_transport_->OnData(channel_, audio_data, bits_per_sample, @@ -1368,25 +1379,42 @@ class WebRtcVoiceMediaChannel::WebRtcVoiceChannelRenderer // never been called, this callback won't be triggered. void OnClose() override { 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. - renderer_ = NULL; + renderer_ = nullptr; } // Accessor to the VoE channel ID. int channel() const { return channel_; } private: - const int channel_; - webrtc::AudioTransport* const voe_audio_transport_; + const int channel_ = -1; + webrtc::AudioTransport* const voe_audio_transport_ = nullptr; + webrtc::Call* call_ = nullptr; + webrtc::AudioSendStream* stream_ = nullptr; // Raw pointer to AudioRenderer owned by LocalAudioTrackHandler. // PeerConnection will make sure invalidating the pointer before the object // goes away. - AudioRenderer* renderer_; + AudioRenderer* renderer_ = nullptr; // Protects |renderer_| in Start(), Stop() and OnClose(). 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 @@ -1417,8 +1445,8 @@ WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel() { LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel"; // Remove any remaining send streams. - while (!send_channels_.empty()) { - RemoveSendStream(send_channels_.begin()->first); + while (!send_streams_.empty()) { + RemoveSendStream(send_streams_.begin()->first); } // Remove any remaining receive streams. @@ -1481,6 +1509,7 @@ bool WebRtcVoiceMediaChannel::SetOptions(const AudioOptions& options) { } } + // TODO(solenberg): Don't recreate unless options changed. RecreateAudioReceiveStreams(); 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. send_codecs_ = codecs; - for (const auto& ch : send_channels_) { + for (const auto& ch : send_streams_) { if (!SetSendCodecs(ch.second->channel(), codecs)) { return false; } @@ -1871,7 +1900,7 @@ bool WebRtcVoiceMediaChannel::SetSendRtpHeaderExtensions( return true; } - for (const auto& ch : send_channels_) { + for (const auto& ch : send_streams_) { if (!SetChannelSendRtpHeaderExtensions(ch.second->channel(), extensions)) { return false; } @@ -1935,8 +1964,9 @@ bool WebRtcVoiceMediaChannel::ChangePlayout(bool playout) { bool WebRtcVoiceMediaChannel::SetSend(SendFlags send) { desired_send_ = send; - if (!send_channels_.empty()) + if (!send_streams_.empty()) { return ChangeSend(desired_send_); + } return true; } @@ -1959,7 +1989,7 @@ bool WebRtcVoiceMediaChannel::ChangeSend(SendFlags send) { } // 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)) { return false; } @@ -2075,13 +2105,13 @@ bool WebRtcVoiceMediaChannel::AddSendStream(const StreamParams& sp) { 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. webrtc::AudioTransport* audio_transport = engine()->voe()->base()->audio_transport(); - send_channels_.insert( + send_streams_.insert( 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 // 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 // the first send channel make sure that all the receive channels are updated // with the same SSRC in order to send receiver reports. - if (send_channels_.size() == 1) { + if (send_streams_.size() == 1) { receiver_reports_ssrc_ = ssrc; for (const auto& ch : receive_channels_) { int recv_channel = ch.second->channel(); @@ -2113,8 +2143,8 @@ bool WebRtcVoiceMediaChannel::AddSendStream(const StreamParams& sp) { bool WebRtcVoiceMediaChannel::RemoveSendStream(uint32_t ssrc) { RTC_DCHECK(thread_checker_.CalledOnValidThread()); - ChannelMap::iterator it = send_channels_.find(ssrc); - if (it == send_channels_.end()) { + auto it = send_streams_.find(ssrc); + if (it == send_streams_.end()) { LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc << " which doesn't exist."; return false; @@ -2126,7 +2156,7 @@ bool WebRtcVoiceMediaChannel::RemoveSendStream(uint32_t ssrc) { // Delete the WebRtcVoiceChannelRenderer object connected to the channel, // this will disconnect the audio renderer with the send channel. delete it->second; - send_channels_.erase(it); + send_streams_.erase(it); // Clean up and delete the send channel. LOG(LS_INFO) << "Removing audio send stream " << ssrc @@ -2134,7 +2164,7 @@ bool WebRtcVoiceMediaChannel::RemoveSendStream(uint32_t ssrc) { if (!DeleteChannel(channel)) { return false; } - if (send_channels_.empty()) { + if (send_streams_.empty()) { ChangeSend(SEND_NOTHING); } return true; @@ -2176,11 +2206,8 @@ bool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) { return false; } - webrtc::AudioTransport* audio_transport = - engine()->voe()->base()->audio_transport(); - WebRtcVoiceChannelRenderer* channel_renderer = - new WebRtcVoiceChannelRenderer(channel, audio_transport); - receive_channels_.insert(std::make_pair(ssrc, channel_renderer)); + WebRtcAudioReceiveStream* stream = new WebRtcAudioReceiveStream(channel); + receive_channels_.insert(std::make_pair(ssrc, stream)); receive_stream_params_[ssrc] = sp; AddAudioReceiveStream(ssrc); @@ -2249,7 +2276,7 @@ bool WebRtcVoiceMediaChannel::RemoveRecvStream(uint32_t ssrc) { RTC_DCHECK(thread_checker_.CalledOnValidThread()); LOG(LS_INFO) << "RemoveRecvStream: " << ssrc; - ChannelMap::iterator it = receive_channels_.find(ssrc); + auto it = receive_channels_.find(ssrc); if (it == receive_channels_.end()) { LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc << " which doesn't exist."; @@ -2259,9 +2286,6 @@ bool WebRtcVoiceMediaChannel::RemoveRecvStream(uint32_t ssrc) { RemoveAudioReceiveStream(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(); delete it->second; receive_channels_.erase(it); @@ -2278,8 +2302,8 @@ bool WebRtcVoiceMediaChannel::RemoveRecvStream(uint32_t ssrc) { bool WebRtcVoiceMediaChannel::SetLocalRenderer(uint32_t ssrc, AudioRenderer* renderer) { - ChannelMap::iterator it = send_channels_.find(ssrc); - if (it == send_channels_.end()) { + auto it = send_streams_.find(ssrc); + if (it == send_streams_.end()) { if (renderer) { // Return an error if trying to set a valid renderer with an invalid ssrc. LOG(LS_ERROR) << "SetLocalRenderer failed with ssrc "<< ssrc; @@ -2388,8 +2412,8 @@ bool WebRtcVoiceMediaChannel::InsertDtmf(uint32_t ssrc, if (flags & cricket::DF_SEND) { int channel = -1; if (ssrc == 0) { - if (send_channels_.size() > 0) { - channel = send_channels_.begin()->second->channel(); + if (send_streams_.size() > 0) { + channel = send_streams_.begin()->second->channel(); } } else { 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 // channels. So all RTCP packets must be forwarded all send channels. VoE // will filter out RR internally. - for (const auto& ch : send_channels_) { + for (const auto& ch : send_streams_) { engine()->voe()->network()->ReceivedRTCPPacket( 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 // is no good way to know which stream is mapping to the mic channel. bool all_muted = muted; - for (const auto& ch : send_channels_) { + for (const auto& ch : send_streams_) { if (!all_muted) { break; } @@ -2570,7 +2594,7 @@ bool WebRtcVoiceMediaChannel::SetSendBitrateInternal(int bps) { if (is_multi_rate) { // If codec is multi-rate then just set the bitrate. codec.rate = bps; - for (const auto& ch : send_channels_) { + for (const auto& ch : send_streams_) { if (!SetSendCodec(ch.second->channel(), codec)) { LOG(LS_INFO) << "Failed to set codec " << codec.plname << " to bitrate " << bps << " bps."; @@ -2630,7 +2654,7 @@ bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) { webrtc::CodecInst codec; unsigned int level; - for (const auto& ch : send_channels_) { + for (const auto& ch : send_streams_) { const int channel = ch.second->channel(); // 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 { 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()) { return it->second->channel(); } @@ -2800,8 +2824,8 @@ int WebRtcVoiceMediaChannel::GetReceiveChannelId(uint32_t ssrc) const { int WebRtcVoiceMediaChannel::GetSendChannelId(uint32_t ssrc) const { RTC_DCHECK(thread_checker_.CalledOnValidThread()); - ChannelMap::const_iterator it = send_channels_.find(ssrc); - if (it != send_channels_.end()) { + const auto it = send_streams_.find(ssrc); + if (it != send_streams_.end()) { return it->second->channel(); } return -1; @@ -2927,8 +2951,8 @@ void WebRtcVoiceMediaChannel::RecreateAudioReceiveStreams() { void WebRtcVoiceMediaChannel::AddAudioReceiveStream(uint32_t ssrc) { RTC_DCHECK(thread_checker_.CalledOnValidThread()); - WebRtcVoiceChannelRenderer* channel = receive_channels_[ssrc]; - RTC_DCHECK(channel != nullptr); + WebRtcAudioReceiveStream* stream = receive_channels_[ssrc]; + RTC_DCHECK(stream != nullptr); RTC_DCHECK(receive_streams_.find(ssrc) == receive_streams_.end()); webrtc::AudioReceiveStream::Config config; config.rtp.remote_ssrc = ssrc; @@ -2936,7 +2960,7 @@ void WebRtcVoiceMediaChannel::AddAudioReceiveStream(uint32_t ssrc) { config.rtp.extensions = recv_rtp_extensions_; config.combined_audio_video_bwe = 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; webrtc::AudioReceiveStream* s = call_->CreateAudioReceiveStream(config); receive_streams_.insert(std::make_pair(ssrc, s)); diff --git a/talk/media/webrtc/webrtcvoiceengine.h b/talk/media/webrtc/webrtcvoiceengine.h index a8f3ec8511..a70840565b 100644 --- a/talk/media/webrtc/webrtcvoiceengine.h +++ b/talk/media/webrtc/webrtcvoiceengine.h @@ -172,6 +172,8 @@ class WebRtcVoiceEngine Settable extended_filter_aec_; Settable delay_agnostic_aec_; Settable experimental_ns_; + + RTC_DISALLOW_COPY_AND_ASSIGN(WebRtcVoiceEngine); }; // WebRtcVoiceMediaChannel is an implementation of VoiceMediaChannel that uses @@ -265,11 +267,6 @@ class WebRtcVoiceMediaChannel : public VoiceMediaChannel, bool SetPlayout(int channel, bool playout); 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 ChannelMap; typedef int (webrtc::VoERTP_RTCP::* ExtensionSetterFunction)(int, bool, unsigned char); @@ -327,12 +324,12 @@ class WebRtcVoiceMediaChannel : public VoiceMediaChannel, // send streams. See: https://code.google.com/p/webrtc/issues/detail?id=4740 uint32_t receiver_reports_ssrc_ = 1; - // send_channels_ contains the channels which are being used for sending. - // When the default channel (default_send_channel_id) is used for sending, it - // is contained in send_channels_, otherwise not. - ChannelMap send_channels_; + class WebRtcAudioSendStream; + std::map send_streams_; std::vector send_extensions_; - ChannelMap receive_channels_; + + class WebRtcAudioReceiveStream; + std::map receive_channels_; std::map receive_streams_; std::map receive_stream_params_; // 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. std::vector receive_extensions_; std::vector recv_rtp_extensions_; + + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcVoiceMediaChannel); }; } // namespace cricket diff --git a/talk/media/webrtc/webrtcvoiceengine_unittest.cc b/talk/media/webrtc/webrtcvoiceengine_unittest.cc index 85094f8de8..477369e182 100644 --- a/talk/media/webrtc/webrtcvoiceengine_unittest.cc +++ b/talk/media/webrtc/webrtcvoiceengine_unittest.cc @@ -59,6 +59,7 @@ static const cricket::AudioCodec* const kAudioCodecs[] = { }; static uint32_t kSsrc1 = 0x99; static uint32_t kSsrc2 = 0x98; +static const uint32_t kSsrcs4[] = {1, 2, 3, 4}; class FakeVoEWrapper : public cricket::VoEWrapper { public: @@ -1862,44 +1863,39 @@ TEST_F(WebRtcVoiceEngineTestFake, Playout) { TEST_F(WebRtcVoiceEngineTestFake, CreateAndDeleteMultipleSendStreams) { SetupForMultiSendStream(); - static const uint32_t kSsrcs4[] = {1, 2, 3, 4}; - // Set the global state for sending. 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( - 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. - int channel_num = voe_.GetChannelFromLocalSsrc(kSsrcs4[i]); + int channel_num = voe_.GetChannelFromLocalSsrc(ssrc); 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 - // recycle the default channel but not delete it. - EXPECT_TRUE(channel_->RemoveSendStream(kSsrcs4[0])); - // Stream should already be Removed from the send stream list. - 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])); + // Delete the send streams. + for (uint32_t ssrc : kSsrcs4) { + EXPECT_TRUE(channel_->RemoveSendStream(ssrc)); + EXPECT_EQ(nullptr, call_.GetAudioSendStream(ssrc)); // Stream should already be deleted. - EXPECT_FALSE(channel_->RemoveSendStream(kSsrcs4[i])); - EXPECT_EQ(-1, voe_.GetChannelFromLocalSsrc(kSsrcs4[i])); + EXPECT_FALSE(channel_->RemoveSendStream(ssrc)); + EXPECT_EQ(-1, voe_.GetChannelFromLocalSsrc(ssrc)); } + EXPECT_EQ(0u, call_.GetAudioSendStreams().size()); } // Test SetSendCodecs correctly configure the codecs in all send streams. TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsWithMultipleSendStreams) { SetupForMultiSendStream(); - static const uint32_t kSsrcs4[] = {1, 2, 3, 4}; // Create send streams. - for (unsigned int i = 0; i < ARRAY_SIZE(kSsrcs4); ++i) { + for (uint32_t ssrc : kSsrcs4) { EXPECT_TRUE(channel_->AddSendStream( - cricket::StreamParams::CreateLegacy(kSsrcs4[i]))); + cricket::StreamParams::CreateLegacy(ssrc))); } cricket::AudioSendParameters parameters; @@ -1911,8 +1907,8 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsWithMultipleSendStreams) { // Verify ISAC and VAD are corrected configured on all send channels. webrtc::CodecInst gcodec; - for (unsigned int i = 0; i < ARRAY_SIZE(kSsrcs4); ++i) { - int channel_num = voe_.GetChannelFromLocalSsrc(kSsrcs4[i]); + for (uint32_t ssrc : kSsrcs4) { + int channel_num = voe_.GetChannelFromLocalSsrc(ssrc); EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); EXPECT_STREQ("ISAC", gcodec.plname); 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. parameters.codecs[0] = kPcmuCodec; EXPECT_TRUE(channel_->SetSendParameters(parameters)); - for (unsigned int i = 0; i < ARRAY_SIZE(kSsrcs4); ++i) { - int channel_num = voe_.GetChannelFromLocalSsrc(kSsrcs4[i]); + for (uint32_t ssrc : kSsrcs4) { + int channel_num = voe_.GetChannelFromLocalSsrc(ssrc); EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); EXPECT_STREQ("PCMU", gcodec.plname); EXPECT_FALSE(voe_.GetVAD(channel_num)); @@ -1934,28 +1930,27 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsWithMultipleSendStreams) { TEST_F(WebRtcVoiceEngineTestFake, SetSendWithMultipleSendStreams) { SetupForMultiSendStream(); - static const uint32_t kSsrcs4[] = {1, 2, 3, 4}; // 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( - cricket::StreamParams::CreateLegacy(kSsrcs4[i]))); + cricket::StreamParams::CreateLegacy(ssrc))); int channel_num = voe_.GetLastChannel(); EXPECT_FALSE(voe_.GetSend(channel_num)); } // Set the global state for starting sending. 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. - int channel_num = voe_.GetChannelFromLocalSsrc(kSsrcs4[i]); + int channel_num = voe_.GetChannelFromLocalSsrc(ssrc); EXPECT_TRUE(voe_.GetSend(channel_num)); } // Set the global state for stopping sending. 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. - int channel_num = voe_.GetChannelFromLocalSsrc(kSsrcs4[i]); + int channel_num = voe_.GetChannelFromLocalSsrc(ssrc); EXPECT_FALSE(voe_.GetSend(channel_num)); } } @@ -1964,11 +1959,10 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendWithMultipleSendStreams) { TEST_F(WebRtcVoiceEngineTestFake, GetStatsWithMultipleSendStreams) { SetupForMultiSendStream(); - static const uint32_t kSsrcs4[] = {1, 2, 3, 4}; // Create send streams. - for (unsigned int i = 0; i < ARRAY_SIZE(kSsrcs4); ++i) { + for (uint32_t ssrc : kSsrcs4) { 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 // the receive stream stats. @@ -1983,6 +1977,7 @@ TEST_F(WebRtcVoiceEngineTestFake, GetStatsWithMultipleSendStreams) { EXPECT_EQ(static_cast(ARRAY_SIZE(kSsrcs4)), info.senders.size()); // Verify the statistic information is correct. + // TODO(solenberg): Make this loop ordering independent. for (unsigned int i = 0; i < ARRAY_SIZE(kSsrcs4); ++i) { EXPECT_EQ(kSsrcs4[i], info.senders[i].ssrc()); EXPECT_EQ(kPcmuCodec.name, info.senders[i].codec_name);