diff --git a/talk/media/webrtc/fakewebrtcvideoengine.h b/talk/media/webrtc/fakewebrtcvideoengine.h index 7e9e437e95..5e15aa8e33 100644 --- a/talk/media/webrtc/fakewebrtcvideoengine.h +++ b/talk/media/webrtc/fakewebrtcvideoengine.h @@ -276,10 +276,10 @@ class FakeWebRtcVideoEngine tmmbr_(false), remb_contribute_(false), remb_bw_partition_(false), - rtp_offset_send_id_(0), - rtp_offset_receive_id_(0), - rtp_absolute_send_time_send_id_(0), - rtp_absolute_send_time_receive_id_(0), + rtp_offset_send_id_(-1), + rtp_offset_receive_id_(-1), + rtp_absolute_send_time_send_id_(-1), + rtp_absolute_send_time_receive_id_(-1), sender_target_delay_(0), receiver_target_delay_(0), transmission_smoothing_(false), @@ -483,21 +483,24 @@ class FakeWebRtcVideoEngine WEBRTC_ASSERT_CHANNEL(channel); return channels_.find(channel)->second->remb_contribute_; } - int GetSendRtpTimestampOffsetExtensionId(int channel) { + int GetSendRtpExtensionId(int channel, const std::string& extension) { WEBRTC_ASSERT_CHANNEL(channel); - return channels_.find(channel)->second->rtp_offset_send_id_; + if (extension == kRtpTimestampOffsetHeaderExtension) { + return channels_.find(channel)->second->rtp_offset_send_id_; + } else if (extension == kRtpAbsoluteSenderTimeHeaderExtension) { + return channels_.find(channel)->second->rtp_absolute_send_time_send_id_; + } + return -1; } - int GetReceiveRtpTimestampOffsetExtensionId(int channel) { + int GetReceiveRtpExtensionId(int channel, const std::string& extension) { WEBRTC_ASSERT_CHANNEL(channel); - return channels_.find(channel)->second->rtp_offset_receive_id_; - } - int GetSendAbsoluteSendTimeExtensionId(int channel) { - WEBRTC_ASSERT_CHANNEL(channel); - return channels_.find(channel)->second->rtp_absolute_send_time_send_id_; - } - int GetReceiveAbsoluteSendTimeExtensionId(int channel) { - WEBRTC_ASSERT_CHANNEL(channel); - return channels_.find(channel)->second->rtp_absolute_send_time_receive_id_; + if (extension == kRtpTimestampOffsetHeaderExtension) { + return channels_.find(channel)->second->rtp_offset_receive_id_; + } else if (extension == kRtpAbsoluteSenderTimeHeaderExtension) { + return + channels_.find(channel)->second->rtp_absolute_send_time_receive_id_; + } + return -1; } bool GetTransmissionSmoothingStatus(int channel) { WEBRTC_ASSERT_CHANNEL(channel); @@ -1046,25 +1049,25 @@ class FakeWebRtcVideoEngine WEBRTC_FUNC(SetSendTimestampOffsetStatus, (int channel, bool enable, int id)) { WEBRTC_CHECK_CHANNEL(channel); - channels_[channel]->rtp_offset_send_id_ = (enable) ? id : 0; + channels_[channel]->rtp_offset_send_id_ = (enable) ? id : -1; return 0; } WEBRTC_FUNC(SetReceiveTimestampOffsetStatus, (int channel, bool enable, int id)) { WEBRTC_CHECK_CHANNEL(channel); - channels_[channel]->rtp_offset_receive_id_ = (enable) ? id : 0; + channels_[channel]->rtp_offset_receive_id_ = (enable) ? id : -1; return 0; } WEBRTC_FUNC(SetSendAbsoluteSendTimeStatus, (int channel, bool enable, int id)) { WEBRTC_CHECK_CHANNEL(channel); - channels_[channel]->rtp_absolute_send_time_send_id_ = (enable) ? id : 0; + channels_[channel]->rtp_absolute_send_time_send_id_ = (enable) ? id : -1; return 0; } WEBRTC_FUNC(SetReceiveAbsoluteSendTimeStatus, (int channel, bool enable, int id)) { WEBRTC_CHECK_CHANNEL(channel); - channels_[channel]->rtp_absolute_send_time_receive_id_ = (enable) ? id : 0; + channels_[channel]->rtp_absolute_send_time_receive_id_ = (enable) ? id : -1; return 0; } WEBRTC_STUB(SetRtcpXrRrtrStatus, (int, bool)); diff --git a/talk/media/webrtc/fakewebrtcvoiceengine.h b/talk/media/webrtc/fakewebrtcvoiceengine.h index 9314e4d013..1df2195b43 100644 --- a/talk/media/webrtc/fakewebrtcvoiceengine.h +++ b/talk/media/webrtc/fakewebrtcvoiceengine.h @@ -110,6 +110,7 @@ class FakeWebRtcVoiceEngine video_channel(-1), send_ssrc(0), send_audio_level_ext_(-1), + receive_audio_level_ext_(-1), send_absolute_sender_time_ext_(-1), receive_absolute_sender_time_ext_(-1) { memset(&send_codec, 0, sizeof(send_codec)); @@ -138,6 +139,7 @@ class FakeWebRtcVoiceEngine int video_channel; uint32 send_ssrc; int send_audio_level_ext_; + int receive_audio_level_ext_; int send_absolute_sender_time_ext_; int receive_absolute_sender_time_ext_; DtmfInfo dtmf_info; @@ -299,14 +301,23 @@ class FakeWebRtcVoiceEngine channels_[++last_channel_] = ch; return last_channel_; } - int GetSendAudioLevelId(int channel) { - return channels_[channel]->send_audio_level_ext_; + int GetSendRtpExtensionId(int channel, const std::string& extension) { + WEBRTC_ASSERT_CHANNEL(channel); + if (extension == kRtpAudioLevelHeaderExtension) { + return channels_[channel]->send_audio_level_ext_; + } else if (extension == kRtpAbsoluteSenderTimeHeaderExtension) { + return channels_[channel]->send_absolute_sender_time_ext_; + } + return -1; } - int GetSendAbsoluteSenderTimeId(int channel) { - return channels_[channel]->send_absolute_sender_time_ext_; - } - int GetReceiveAbsoluteSenderTimeId(int channel) { - return channels_[channel]->receive_absolute_sender_time_ext_; + int GetReceiveRtpExtensionId(int channel, const std::string& extension) { + WEBRTC_ASSERT_CHANNEL(channel); + if (extension == kRtpAudioLevelHeaderExtension) { + return channels_[channel]->receive_audio_level_ext_; + } else if (extension == kRtpAbsoluteSenderTimeHeaderExtension) { + return channels_[channel]->receive_absolute_sender_time_ext_; + } + return -1; } int GetNumSetSendCodecs() const { return num_set_send_codecs_; } @@ -736,6 +747,15 @@ class FakeWebRtcVoiceEngine channels_[channel]->send_audio_level_ext_ = (enable) ? id : -1; return 0; } +#ifdef USE_WEBRTC_DEV_BRANCH + WEBRTC_FUNC(SetReceiveAudioLevelIndicationStatus, (int channel, bool enable, + unsigned char id)) { + WEBRTC_CHECK_CHANNEL(channel); + WEBRTC_CHECK_HEADER_EXTENSION_ID(enable, id); + channels_[channel]->receive_audio_level_ext_ = (enable) ? id : -1; + return 0; + } +#endif // USE_WEBRTC_DEV_BRANCH WEBRTC_FUNC(SetSendAbsoluteSenderTimeStatus, (int channel, bool enable, unsigned char id)) { WEBRTC_CHECK_CHANNEL(channel); diff --git a/talk/media/webrtc/webrtcvideoengine.cc b/talk/media/webrtc/webrtcvideoengine.cc index d987c7c91c..7c057e0e9a 100644 --- a/talk/media/webrtc/webrtcvideoengine.cc +++ b/talk/media/webrtc/webrtcvideoengine.cc @@ -2728,7 +2728,6 @@ bool WebRtcVideoMediaChannel::SetRecvRtpHeaderExtensions( if (receive_extensions_ == extensions) { return true; } - receive_extensions_ = extensions; const RtpHeaderExtension* offset_extension = FindHeaderExtension(extensions, kRtpTimestampOffsetHeaderExtension); @@ -2750,12 +2749,16 @@ bool WebRtcVideoMediaChannel::SetRecvRtpHeaderExtensions( return false; } } + + receive_extensions_ = extensions; return true; } bool WebRtcVideoMediaChannel::SetSendRtpHeaderExtensions( const std::vector& extensions) { - send_extensions_ = extensions; + if (send_extensions_ == extensions) { + return true; + } const RtpHeaderExtension* offset_extension = FindHeaderExtension(extensions, kRtpTimestampOffsetHeaderExtension); @@ -2786,6 +2789,8 @@ bool WebRtcVideoMediaChannel::SetSendRtpHeaderExtensions( talk_base::Socket::OPT_RTP_SENDTIME_EXTN_ID, send_time_extension->id); } + + send_extensions_ = extensions; return true; } diff --git a/talk/media/webrtc/webrtcvideoengine_unittest.cc b/talk/media/webrtc/webrtcvideoengine_unittest.cc index b2123f9b9f..4d88579540 100644 --- a/talk/media/webrtc/webrtcvideoengine_unittest.cc +++ b/talk/media/webrtc/webrtcvideoengine_unittest.cc @@ -50,6 +50,9 @@ // Tests for the WebRtcVideoEngine/VideoChannel code. +using cricket::kRtpTimestampOffsetHeaderExtension; +using cricket::kRtpAbsoluteSenderTimeHeaderExtension; + static const cricket::VideoCodec kVP8Codec720p(100, "VP8", 1280, 720, 30, 0); static const cricket::VideoCodec kVP8Codec360p(100, "VP8", 640, 360, 30, 0); static const cricket::VideoCodec kVP8Codec270p(100, "VP8", 480, 270, 30, 0); @@ -148,6 +151,76 @@ class WebRtcVideoEngineTestFake : public testing::Test, channel_->SendFrame(&capturer, &frame); return true; } + void TestSetSendRtpHeaderExtensions(const std::string& ext) { + EXPECT_TRUE(SetupEngine()); + int channel_num = vie_.GetLastChannel(); + + // Verify extensions are off by default. + EXPECT_EQ(-1, vie_.GetSendRtpExtensionId(channel_num, ext)); + + // Enable extension. + const int id = 1; + std::vector extensions; + extensions.push_back(cricket::RtpHeaderExtension(ext, id)); + + // Verify the send extension id. + EXPECT_TRUE(channel_->SetSendRtpHeaderExtensions(extensions)); + EXPECT_EQ(id, vie_.GetSendRtpExtensionId(channel_num, ext)); + // Verify call with same set of extensions returns true. + EXPECT_TRUE(channel_->SetSendRtpHeaderExtensions(extensions)); + EXPECT_EQ(id, vie_.GetSendRtpExtensionId(channel_num, ext)); + + // Add a new send stream and verify the extension is set. + // The first send stream to occupy the default channel. + EXPECT_TRUE( + channel_->AddSendStream(cricket::StreamParams::CreateLegacy(123))); + EXPECT_TRUE( + channel_->AddSendStream(cricket::StreamParams::CreateLegacy(234))); + int new_send_channel_num = vie_.GetLastChannel(); + EXPECT_NE(channel_num, new_send_channel_num); + EXPECT_EQ(id, vie_.GetSendRtpExtensionId(new_send_channel_num, ext)); + + // Remove the extension id. + std::vector empty_extensions; + EXPECT_TRUE(channel_->SetSendRtpHeaderExtensions(empty_extensions)); + EXPECT_EQ(-1, vie_.GetSendRtpExtensionId(channel_num, ext)); + EXPECT_EQ(-1, vie_.GetSendRtpExtensionId(new_send_channel_num, ext)); + } + void TestSetRecvRtpHeaderExtensions(const std::string& ext) { + EXPECT_TRUE(SetupEngine()); + int channel_num = vie_.GetLastChannel(); + + // Verify extensions are off by default. + EXPECT_EQ(-1, vie_.GetReceiveRtpExtensionId(channel_num, ext)); + + // Enable extension. + const int id = 2; + std::vector extensions; + extensions.push_back(cricket::RtpHeaderExtension(ext, id)); + + // Verify receive extension id. + EXPECT_TRUE(channel_->SetRecvRtpHeaderExtensions(extensions)); + EXPECT_EQ(id, vie_.GetReceiveRtpExtensionId(channel_num, ext)); + // Verify call with same set of extensions returns true. + EXPECT_TRUE(channel_->SetRecvRtpHeaderExtensions(extensions)); + EXPECT_EQ(id, vie_.GetReceiveRtpExtensionId(channel_num, ext)); + + // Add a new receive stream and verify the extension is set. + // The first send stream to occupy the default channel. + EXPECT_TRUE( + channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(345))); + EXPECT_TRUE( + channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(456))); + int new_recv_channel_num = vie_.GetLastChannel(); + EXPECT_NE(channel_num, new_recv_channel_num); + EXPECT_EQ(id, vie_.GetReceiveRtpExtensionId(new_recv_channel_num, ext)); + + // Remove the extension id. + std::vector empty_extensions; + EXPECT_TRUE(channel_->SetRecvRtpHeaderExtensions(empty_extensions)); + EXPECT_EQ(-1, vie_.GetReceiveRtpExtensionId(channel_num, ext)); + EXPECT_EQ(-1, vie_.GetReceiveRtpExtensionId(new_recv_channel_num, ext)); + } void VerifyCodecFeedbackParams(const cricket::VideoCodec& codec) { EXPECT_TRUE(codec.HasFeedbackParam( cricket::FeedbackParam(cricket::kRtcpFbParamNack, @@ -730,89 +803,19 @@ TEST_F(WebRtcVideoEngineTestFake, RecvStreamNoRtx) { } // Test support for RTP timestamp offset header extension. -TEST_F(WebRtcVideoEngineTestFake, RtpTimestampOffsetHeaderExtensions) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - cricket::VideoOptions options; - options.conference_mode.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - - // Verify extensions are off by default. - EXPECT_EQ(0, vie_.GetSendRtpTimestampOffsetExtensionId(channel_num)); - EXPECT_EQ(0, vie_.GetReceiveRtpTimestampOffsetExtensionId(channel_num)); - - // Enable RTP timestamp extension. - const int id = 14; - std::vector extensions; - extensions.push_back(cricket::RtpHeaderExtension( - "urn:ietf:params:rtp-hdrext:toffset", id)); - - // Verify the send extension id. - EXPECT_TRUE(channel_->SetSendRtpHeaderExtensions(extensions)); - EXPECT_EQ(id, vie_.GetSendRtpTimestampOffsetExtensionId(channel_num)); - - // Remove the extension id. - std::vector empty_extensions; - EXPECT_TRUE(channel_->SetSendRtpHeaderExtensions(empty_extensions)); - EXPECT_EQ(0, vie_.GetSendRtpTimestampOffsetExtensionId(channel_num)); - - // Verify receive extension id. - EXPECT_TRUE(channel_->SetRecvRtpHeaderExtensions(extensions)); - EXPECT_EQ(id, vie_.GetReceiveRtpTimestampOffsetExtensionId(channel_num)); - - // Add a new receive stream and verify the extension is set. - EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2))); - int new_channel_num = vie_.GetLastChannel(); - EXPECT_NE(channel_num, new_channel_num); - EXPECT_EQ(id, vie_.GetReceiveRtpTimestampOffsetExtensionId(new_channel_num)); - - // Remove the extension id. - EXPECT_TRUE(channel_->SetRecvRtpHeaderExtensions(empty_extensions)); - EXPECT_EQ(0, vie_.GetReceiveRtpTimestampOffsetExtensionId(channel_num)); - EXPECT_EQ(0, vie_.GetReceiveRtpTimestampOffsetExtensionId(new_channel_num)); +TEST_F(WebRtcVideoEngineTestFake, SendRtpTimestampOffsetHeaderExtensions) { + TestSetSendRtpHeaderExtensions(kRtpTimestampOffsetHeaderExtension); +} +TEST_F(WebRtcVideoEngineTestFake, RecvRtpTimestampOffsetHeaderExtensions) { + TestSetRecvRtpHeaderExtensions(kRtpTimestampOffsetHeaderExtension); } // Test support for absolute send time header extension. -TEST_F(WebRtcVideoEngineTestFake, AbsoluteSendTimeHeaderExtensions) { - EXPECT_TRUE(SetupEngine()); - int channel_num = vie_.GetLastChannel(); - cricket::VideoOptions options; - options.conference_mode.Set(true); - EXPECT_TRUE(channel_->SetOptions(options)); - - // Verify extensions are off by default. - EXPECT_EQ(0, vie_.GetSendAbsoluteSendTimeExtensionId(channel_num)); - EXPECT_EQ(0, vie_.GetReceiveAbsoluteSendTimeExtensionId(channel_num)); - - // Enable RTP timestamp extension. - const int id = 12; - std::vector extensions; - extensions.push_back(cricket::RtpHeaderExtension( - "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time", id)); - - // Verify the send extension id. - EXPECT_TRUE(channel_->SetSendRtpHeaderExtensions(extensions)); - EXPECT_EQ(id, vie_.GetSendAbsoluteSendTimeExtensionId(channel_num)); - - // Remove the extension id. - std::vector empty_extensions; - EXPECT_TRUE(channel_->SetSendRtpHeaderExtensions(empty_extensions)); - EXPECT_EQ(0, vie_.GetSendAbsoluteSendTimeExtensionId(channel_num)); - - // Verify receive extension id. - EXPECT_TRUE(channel_->SetRecvRtpHeaderExtensions(extensions)); - EXPECT_EQ(id, vie_.GetReceiveAbsoluteSendTimeExtensionId(channel_num)); - - // Add a new receive stream and verify the extension is set. - EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2))); - int new_channel_num = vie_.GetLastChannel(); - EXPECT_NE(channel_num, new_channel_num); - EXPECT_EQ(id, vie_.GetReceiveAbsoluteSendTimeExtensionId(new_channel_num)); - - // Remove the extension id. - EXPECT_TRUE(channel_->SetRecvRtpHeaderExtensions(empty_extensions)); - EXPECT_EQ(0, vie_.GetReceiveAbsoluteSendTimeExtensionId(channel_num)); - EXPECT_EQ(0, vie_.GetReceiveAbsoluteSendTimeExtensionId(new_channel_num)); +TEST_F(WebRtcVideoEngineTestFake, SendAbsoluteSendTimeHeaderExtensions) { + TestSetSendRtpHeaderExtensions(kRtpAbsoluteSenderTimeHeaderExtension); +} +TEST_F(WebRtcVideoEngineTestFake, RecvAbsoluteSendTimeHeaderExtensions) { + TestSetRecvRtpHeaderExtensions(kRtpAbsoluteSenderTimeHeaderExtension); } TEST_F(WebRtcVideoEngineTestFake, LeakyBucketTest) { diff --git a/talk/media/webrtc/webrtcvoiceengine.cc b/talk/media/webrtc/webrtcvoiceengine.cc index ed0c28ce32..b26f14aa52 100644 --- a/talk/media/webrtc/webrtcvoiceengine.cc +++ b/talk/media/webrtc/webrtcvoiceengine.cc @@ -2202,53 +2202,96 @@ bool WebRtcVoiceMediaChannel::SetSendCodec( bool WebRtcVoiceMediaChannel::SetRecvRtpHeaderExtensions( const std::vector& extensions) { - const RtpHeaderExtension* send_time_extension = - FindHeaderExtension(extensions, kRtpAbsoluteSenderTimeHeaderExtension); + if (receive_extensions_ == extensions) { + return true; + } + + // The default channel may or may not be in |receive_channels_|. Set the rtp + // header extensions for default channel regardless. + if (!SetChannelRecvRtpHeaderExtensions(voe_channel(), extensions)) { + return false; + } // Loop through all receive channels and enable/disable the extensions. for (ChannelMap::const_iterator channel_it = receive_channels_.begin(); channel_it != receive_channels_.end(); ++channel_it) { - int channel_id = channel_it->second->channel(); - if (!SetHeaderExtension( - &webrtc::VoERTP_RTCP::SetReceiveAbsoluteSenderTimeStatus, channel_id, - send_time_extension)) { + if (!SetChannelRecvRtpHeaderExtensions(channel_it->second->channel(), + extensions)) { return false; } } + + receive_extensions_ = extensions; + return true; +} + +bool WebRtcVoiceMediaChannel::SetChannelRecvRtpHeaderExtensions( + int channel_id, const std::vector& extensions) { +#ifdef USE_WEBRTC_DEV_BRANCH + const RtpHeaderExtension* audio_level_extension = + FindHeaderExtension(extensions, kRtpAudioLevelHeaderExtension); + if (!SetHeaderExtension( + &webrtc::VoERTP_RTCP::SetReceiveAudioLevelIndicationStatus, channel_id, + audio_level_extension)) { + return false; + } +#endif // USE_WEBRTC_DEV_BRANCH + + const RtpHeaderExtension* send_time_extension = + FindHeaderExtension(extensions, kRtpAbsoluteSenderTimeHeaderExtension); + if (!SetHeaderExtension( + &webrtc::VoERTP_RTCP::SetReceiveAbsoluteSenderTimeStatus, channel_id, + send_time_extension)) { + return false; + } return true; } bool WebRtcVoiceMediaChannel::SetSendRtpHeaderExtensions( const std::vector& extensions) { + if (send_extensions_ == extensions) { + return true; + } + + // The default channel may or may not be in |send_channels_|. Set the rtp + // header extensions for default channel regardless. + + if (!SetChannelSendRtpHeaderExtensions(voe_channel(), extensions)) { + return false; + } + + // Loop through all send channels and enable/disable the extensions. + for (ChannelMap::const_iterator channel_it = send_channels_.begin(); + channel_it != send_channels_.end(); ++channel_it) { + if (!SetChannelSendRtpHeaderExtensions(channel_it->second->channel(), + extensions)) { + return false; + } + } + + send_extensions_ = extensions; + return true; +} + +bool WebRtcVoiceMediaChannel::SetChannelSendRtpHeaderExtensions( + int channel_id, const std::vector& extensions) { const RtpHeaderExtension* audio_level_extension = FindHeaderExtension(extensions, kRtpAudioLevelHeaderExtension); - const RtpHeaderExtension* send_time_extension = - FindHeaderExtension(extensions, kRtpAbsoluteSenderTimeHeaderExtension); + if (!SetHeaderExtension( - &webrtc::VoERTP_RTCP::SetSendAudioLevelIndicationStatus, voe_channel(), + &webrtc::VoERTP_RTCP::SetSendAudioLevelIndicationStatus, channel_id, audio_level_extension)) { return false; } + + const RtpHeaderExtension* send_time_extension = + FindHeaderExtension(extensions, kRtpAbsoluteSenderTimeHeaderExtension); if (!SetHeaderExtension( - &webrtc::VoERTP_RTCP::SetSendAbsoluteSenderTimeStatus, voe_channel(), + &webrtc::VoERTP_RTCP::SetSendAbsoluteSenderTimeStatus, channel_id, send_time_extension)) { return false; } - for (ChannelMap::const_iterator channel_it = send_channels_.begin(); - channel_it != send_channels_.end(); ++channel_it) { - int channel_id = channel_it->second->channel(); - if (!SetHeaderExtension( - &webrtc::VoERTP_RTCP::SetSendAudioLevelIndicationStatus, channel_id, - audio_level_extension)) { - return false; - } - if (!SetHeaderExtension( - &webrtc::VoERTP_RTCP::SetSendAbsoluteSenderTimeStatus, channel_id, - send_time_extension)) { - return false; - } - } return true; } @@ -2352,6 +2395,7 @@ bool WebRtcVoiceMediaChannel::ChangeSend(int channel, SendFlags send) { return true; } +// TODO(ronghuawu): Change this method to return bool. void WebRtcVoiceMediaChannel::ConfigureSendChannel(int channel) { if (engine()->voe()->network()->RegisterExternalTransport( channel, *this) == -1) { @@ -2363,6 +2407,9 @@ void WebRtcVoiceMediaChannel::ConfigureSendChannel(int channel) { // Reset all recv codecs; they will be enabled via SetRecvCodecs. ResetRecvCodecs(channel); + + // Set RTP header extension for the new channel. + SetChannelSendRtpHeaderExtensions(channel, send_extensions_); } bool WebRtcVoiceMediaChannel::DeleteChannel(int channel) { @@ -2599,6 +2646,11 @@ bool WebRtcVoiceMediaChannel::ConfigureRecvChannel(int channel) { } SetNack(channel, nack_enabled_); + // Set RTP header extension for the new channel. + if (!SetChannelRecvRtpHeaderExtensions(channel, receive_extensions_)) { + return false; + } + return SetPlayout(channel, playout_); } @@ -3474,13 +3526,15 @@ VoiceMediaChannel::Error bool WebRtcVoiceMediaChannel::SetHeaderExtension(ExtensionSetterFunction setter, int channel_id, const RtpHeaderExtension* extension) { bool enable = false; - unsigned char id = 0; + int id = 0; + std::string uri; if (extension) { enable = true; id = extension->id; + uri = extension->uri; } if ((engine()->voe()->rtp()->*setter)(channel_id, enable, id) != 0) { - LOG_RTCERR4(*setter, extension->uri, channel_id, enable, id); + LOG_RTCERR4(*setter, uri, channel_id, enable, id); return false; } return true; diff --git a/talk/media/webrtc/webrtcvoiceengine.h b/talk/media/webrtc/webrtcvoiceengine.h index a15e0540b0..efc388fc33 100644 --- a/talk/media/webrtc/webrtcvoiceengine.h +++ b/talk/media/webrtc/webrtcvoiceengine.h @@ -416,6 +416,13 @@ class WebRtcVoiceMediaChannel bool SetHeaderExtension(ExtensionSetterFunction setter, int channel_id, const RtpHeaderExtension* extension); + bool SetChannelRecvRtpHeaderExtensions( + int channel_id, + const std::vector& extensions); + bool SetChannelSendRtpHeaderExtensions( + int channel_id, + const std::vector& extensions); + talk_base::scoped_ptr ringback_tone_; std::set ringback_channels_; // channels playing ringback std::vector recv_codecs_; @@ -436,6 +443,7 @@ class WebRtcVoiceMediaChannel // When the default channel (voe_channel) is used for sending, it is // contained in send_channels_, otherwise not. ChannelMap send_channels_; + std::vector send_extensions_; uint32 default_receive_ssrc_; // Note the default channel (voe_channel()) can reside in both // receive_channels_ and send_channels_ in non-conference mode and in that @@ -445,6 +453,7 @@ class WebRtcVoiceMediaChannel // the WebRtc thread must be synchronized with edits on the worker thread. // Reads on the worker thread are ok. // + std::vector receive_extensions_; // Do not lock this on the VoE media processor thread; potential for deadlock // exists. mutable talk_base::CriticalSection receive_channels_cs_; diff --git a/talk/media/webrtc/webrtcvoiceengine_unittest.cc b/talk/media/webrtc/webrtcvoiceengine_unittest.cc index 4e0f339fba..cbc0007193 100644 --- a/talk/media/webrtc/webrtcvoiceengine_unittest.cc +++ b/talk/media/webrtc/webrtcvoiceengine_unittest.cc @@ -44,6 +44,9 @@ // Tests for the WebRtcVoiceEngine/VoiceChannel code. +using cricket::kRtpAudioLevelHeaderExtension; +using cricket::kRtpAbsoluteSenderTimeHeaderExtension; + static const cricket::AudioCodec kPcmuCodec(0, "PCMU", 8000, 64000, 1, 0); static const cricket::AudioCodec kIsacCodec(103, "ISAC", 16000, 32000, 1, 0); static const cricket::AudioCodec kCeltCodec(110, "CELT", 32000, 64000, 2, 0); @@ -136,17 +139,19 @@ class WebRtcVoiceEngineTestFake : public testing::Test { options_conference_.conference_mode.Set(true); options_adjust_agc_.adjust_agc_delta.Set(-10); } + bool SetupEngineWithoutStream() { + if (!engine_.Init(talk_base::Thread::Current())) { + return false; + } + channel_ = engine_.CreateChannel(); + return (channel_ != NULL); + } bool SetupEngine() { - bool result = engine_.Init(talk_base::Thread::Current()); - if (result) { - channel_ = engine_.CreateChannel(); - result = (channel_ != NULL); + if (!SetupEngineWithoutStream()) { + return false; } - if (result) { - result = channel_->AddSendStream( - cricket::StreamParams::CreateLegacy(kSsrc1)); - } - return result; + return channel_->AddSendStream( + cricket::StreamParams::CreateLegacy(kSsrc1)); } void SetupForMultiSendStream() { EXPECT_TRUE(SetupEngine()); @@ -246,75 +251,88 @@ class WebRtcVoiceEngineTestFake : public testing::Test { EXPECT_EQ(expected_bitrate, temp_codec.rate); } - void TestSetSendRtpHeaderExtensions(int channel_id) { - std::vector extensions; + void TestSetSendRtpHeaderExtensions(const std::string& ext) { + EXPECT_TRUE(SetupEngineWithoutStream()); + int channel_num = voe_.GetLastChannel(); // Ensure extensions are off by default. - EXPECT_EQ(-1, voe_.GetSendAudioLevelId(channel_id)); - EXPECT_EQ(-1, voe_.GetSendAbsoluteSenderTimeId(channel_id)); + EXPECT_EQ(-1, voe_.GetSendRtpExtensionId(channel_num, ext)); + std::vector extensions; // Ensure unknown extensions won't cause an error. extensions.push_back(cricket::RtpHeaderExtension( "urn:ietf:params:unknownextention", 1)); EXPECT_TRUE(channel_->SetSendRtpHeaderExtensions(extensions)); - EXPECT_EQ(-1, voe_.GetSendAudioLevelId(channel_id)); - EXPECT_EQ(-1, voe_.GetSendAbsoluteSenderTimeId(channel_id)); + EXPECT_EQ(-1, voe_.GetSendRtpExtensionId(channel_num, ext)); // Ensure extensions stay off with an empty list of headers. extensions.clear(); EXPECT_TRUE(channel_->SetSendRtpHeaderExtensions(extensions)); - EXPECT_EQ(-1, voe_.GetSendAudioLevelId(channel_id)); - EXPECT_EQ(-1, voe_.GetSendAbsoluteSenderTimeId(channel_id)); + EXPECT_EQ(-1, voe_.GetSendRtpExtensionId(channel_num, ext)); - // Ensure audio levels are enabled if the audio-level header is specified - // (but AST is still off). - extensions.push_back(cricket::RtpHeaderExtension( - "urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8)); + // Ensure extension is set properly. + const int id = 1; + extensions.push_back(cricket::RtpHeaderExtension(ext, id)); EXPECT_TRUE(channel_->SetSendRtpHeaderExtensions(extensions)); - EXPECT_EQ(8, voe_.GetSendAudioLevelId(channel_id)); - EXPECT_EQ(-1, voe_.GetSendAbsoluteSenderTimeId(channel_id)); + EXPECT_EQ(id, voe_.GetSendRtpExtensionId(channel_num, ext)); - // Ensure audio level and AST are enabled if the extensions are specified. - extensions.push_back(cricket::RtpHeaderExtension( - "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time", 12)); - EXPECT_TRUE(channel_->SetSendRtpHeaderExtensions(extensions)); - EXPECT_EQ(8, voe_.GetSendAudioLevelId(channel_id)); - EXPECT_EQ(12, voe_.GetSendAbsoluteSenderTimeId(channel_id)); + // Ensure extension is set properly on new channel. + // The first stream to occupy the default channel. + EXPECT_TRUE(channel_->AddSendStream( + cricket::StreamParams::CreateLegacy(123))); + EXPECT_TRUE(channel_->AddSendStream( + cricket::StreamParams::CreateLegacy(234))); + int new_channel_num = voe_.GetLastChannel(); + EXPECT_NE(channel_num, new_channel_num); + EXPECT_EQ(id, voe_.GetSendRtpExtensionId(new_channel_num, ext)); // Ensure all extensions go back off with an empty list. extensions.clear(); EXPECT_TRUE(channel_->SetSendRtpHeaderExtensions(extensions)); - EXPECT_EQ(-1, voe_.GetSendAudioLevelId(channel_id)); - EXPECT_EQ(-1, voe_.GetSendAbsoluteSenderTimeId(channel_id)); + EXPECT_EQ(-1, voe_.GetSendRtpExtensionId(channel_num, ext)); + EXPECT_EQ(-1, voe_.GetSendRtpExtensionId(new_channel_num, ext)); } - void TestSetRecvRtpHeaderExtensions(int channel_id) { - std::vector extensions; + void TestSetRecvRtpHeaderExtensions(const std::string& ext) { + EXPECT_TRUE(SetupEngineWithoutStream()); + int channel_num = voe_.GetLastChannel(); // Ensure extensions are off by default. - EXPECT_EQ(-1, voe_.GetReceiveAbsoluteSenderTimeId(channel_id)); + EXPECT_EQ(-1, voe_.GetReceiveRtpExtensionId(channel_num, ext)); + std::vector extensions; // Ensure unknown extensions won't cause an error. extensions.push_back(cricket::RtpHeaderExtension( "urn:ietf:params:unknownextention", 1)); EXPECT_TRUE(channel_->SetRecvRtpHeaderExtensions(extensions)); - EXPECT_EQ(-1, voe_.GetReceiveAbsoluteSenderTimeId(channel_id)); + EXPECT_EQ(-1, voe_.GetReceiveRtpExtensionId(channel_num, ext)); - // An empty list shouldn't cause any headers to be enabled. + // Ensure extensions stay off with an empty list of headers. extensions.clear(); EXPECT_TRUE(channel_->SetRecvRtpHeaderExtensions(extensions)); - EXPECT_EQ(-1, voe_.GetReceiveAbsoluteSenderTimeId(channel_id)); + EXPECT_EQ(-1, voe_.GetReceiveRtpExtensionId(channel_num, ext)); - // Nor should indicating we can receive the absolute sender time header. - extensions.push_back(cricket::RtpHeaderExtension( - "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time", 11)); + // Ensure extension is set properly. + const int id = 2; + extensions.push_back(cricket::RtpHeaderExtension(ext, id)); EXPECT_TRUE(channel_->SetRecvRtpHeaderExtensions(extensions)); - EXPECT_EQ(11, voe_.GetReceiveAbsoluteSenderTimeId(channel_id)); + EXPECT_EQ(id, voe_.GetReceiveRtpExtensionId(channel_num, ext)); - // Resetting to an empty list shouldn't cause any headers to be enabled. + // Ensure extension is set properly on new channel. + // The first stream to occupy the default channel. + EXPECT_TRUE(channel_->AddRecvStream( + cricket::StreamParams::CreateLegacy(345))); + EXPECT_TRUE(channel_->AddRecvStream( + cricket::StreamParams::CreateLegacy(456))); + int new_channel_num = voe_.GetLastChannel(); + EXPECT_NE(channel_num, new_channel_num); + EXPECT_EQ(id, voe_.GetReceiveRtpExtensionId(new_channel_num, ext)); + + // Ensure all extensions go back off with an empty list. extensions.clear(); EXPECT_TRUE(channel_->SetRecvRtpHeaderExtensions(extensions)); - EXPECT_EQ(-1, voe_.GetReceiveAbsoluteSenderTimeId(channel_id)); + EXPECT_EQ(-1, voe_.GetReceiveRtpExtensionId(channel_num, ext)); + EXPECT_EQ(-1, voe_.GetReceiveRtpExtensionId(new_channel_num, ext)); } protected: @@ -1559,17 +1577,22 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsBadRED5) { EXPECT_FALSE(voe_.GetFEC(channel_num)); } -// Test that we support setting certain send header extensions. -TEST_F(WebRtcVoiceEngineTestFake, SetSendRtpHeaderExtensions) { - EXPECT_TRUE(SetupEngine()); - TestSetSendRtpHeaderExtensions(voe_.GetLastChannel()); +// Test support for audio level header extension. +TEST_F(WebRtcVoiceEngineTestFake, SendAudioLevelHeaderExtensions) { + TestSetSendRtpHeaderExtensions(kRtpAudioLevelHeaderExtension); } +#ifdef USE_WEBRTC_DEV_BRANCH +TEST_F(WebRtcVoiceEngineTestFake, RecvAudioLevelHeaderExtensions) { + TestSetRecvRtpHeaderExtensions(kRtpAudioLevelHeaderExtension); +} +#endif // USE_WEBRTC_DEV_BRANCH -// Test that we support setting recv header extensions. -TEST_F(WebRtcVoiceEngineTestFake, SetRecvRtpHeaderExtensions) { - EXPECT_TRUE(SetupEngine()); - EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2))); - TestSetRecvRtpHeaderExtensions(voe_.GetLastChannel()); +// Test support for absolute send time header extension. +TEST_F(WebRtcVoiceEngineTestFake, SendAbsoluteSendTimeHeaderExtensions) { + TestSetSendRtpHeaderExtensions(kRtpAbsoluteSenderTimeHeaderExtension); +} +TEST_F(WebRtcVoiceEngineTestFake, RecvAbsoluteSendTimeHeaderExtensions) { + TestSetRecvRtpHeaderExtensions(kRtpAbsoluteSenderTimeHeaderExtension); } // Test that we can create a channel and start sending/playing out on it. @@ -1729,41 +1752,6 @@ TEST_F(WebRtcVoiceEngineTestFake, GetStatsWithMultipleSendStreams) { EXPECT_EQ(1u, info.receivers.size()); } -// Test that we support setting header extensions on multiple send streams. -TEST_F(WebRtcVoiceEngineTestFake, - SetSendRtpHeaderExtensionsWithMultipleSendStreams) { - SetupForMultiSendStream(); - - static const uint32 kSsrcs[] = {1, 2, 3, 4}; - for (unsigned int i = 0; i < ARRAY_SIZE(kSsrcs); ++i) { - EXPECT_TRUE(channel_->AddSendStream( - cricket::StreamParams::CreateLegacy(kSsrcs[i]))); - } - - for (unsigned int i = 0; i < ARRAY_SIZE(kSsrcs); ++i) { - int channel_num = voe_.GetChannelFromLocalSsrc(kSsrcs[i]); - TestSetSendRtpHeaderExtensions(channel_num); - } -} - -// Test that we support setting header extensions on multiple receive streams. -TEST_F(WebRtcVoiceEngineTestFake, - SetRecvRtpHeaderExtensionsWithMultipleRecvStreams) { - EXPECT_TRUE(SetupEngine()); - - static const uint32 kSsrcs[] = {1, 2, 3, 4}; - int channel_ids[ARRAY_SIZE(kSsrcs)] = {0}; - for (unsigned int i = 0; i < ARRAY_SIZE(kSsrcs); ++i) { - EXPECT_TRUE(channel_->AddRecvStream( - cricket::StreamParams::CreateLegacy(kSsrcs[i]))); - channel_ids[i] = voe_.GetLastChannel(); - } - - for (unsigned int i = 0; i < ARRAY_SIZE(kSsrcs); ++i) { - TestSetRecvRtpHeaderExtensions(channel_ids[i]); - } -} - // Test that we can add and remove receive streams, and do proper send/playout. // We can receive on multiple streams while sending one stream. TEST_F(WebRtcVoiceEngineTestFake, PlayoutWithMultipleStreams) {