diff --git a/talk/libjingle_tests.gyp b/talk/libjingle_tests.gyp index 265c37b5c2..be64c5ece8 100755 --- a/talk/libjingle_tests.gyp +++ b/talk/libjingle_tests.gyp @@ -91,15 +91,15 @@ 'media/base/videocapturer_unittest.cc', 'media/base/videocommon_unittest.cc', 'media/base/videoengine_unittest.h', + 'media/base/videoframe_unittest.h', 'media/devices/dummydevicemanager_unittest.cc', 'media/devices/filevideocapturer_unittest.cc', 'media/sctp/sctpdataengine_unittest.cc', 'media/webrtc/simulcast_unittest.cc', + 'media/webrtc/webrtcmediaengine_unittest.cc', 'media/webrtc/webrtcvideocapturer_unittest.cc', - 'media/base/videoframe_unittest.h', 'media/webrtc/webrtcvideoframe_unittest.cc', 'media/webrtc/webrtcvideoframefactory_unittest.cc', - # Disabled because some tests fail. # TODO(ronghuawu): Reenable these tests. # 'media/devices/devicemanager_unittest.cc', diff --git a/talk/media/base/mediachannel.h b/talk/media/base/mediachannel.h index 3f777b3bbc..f9ffffa8b9 100644 --- a/talk/media/base/mediachannel.h +++ b/talk/media/base/mediachannel.h @@ -413,8 +413,8 @@ struct RtpHeaderExtension { std::string ToString() const { std::ostringstream ost; ost << "{"; - ost << "id: , " << id; ost << "uri: " << uri; + ost << ", id: " << id; ost << "}"; return ost.str(); } @@ -936,7 +936,7 @@ struct DataMediaInfo { template struct RtpParameters { - virtual std::string ToString() { + virtual std::string ToString() const { std::ostringstream ost; ost << "{"; ost << "codecs: " << VectorToString(codecs) << ", "; @@ -952,7 +952,7 @@ struct RtpParameters { template struct RtpSendParameters : RtpParameters { - std::string ToString() override { + std::string ToString() const override { std::ostringstream ost; ost << "{"; ost << "codecs: " << VectorToString(this->codecs) << ", "; @@ -1160,13 +1160,13 @@ struct SendDataParams { enum SendDataResult { SDR_SUCCESS, SDR_ERROR, SDR_BLOCK }; struct DataOptions { - std::string ToString() { + std::string ToString() const { return "{}"; } }; struct DataSendParameters : RtpSendParameters { - std::string ToString() { + std::string ToString() const { std::ostringstream ost; // Options and extensions aren't used. ost << "{"; diff --git a/talk/media/webrtc/webrtcmediaengine.cc b/talk/media/webrtc/webrtcmediaengine.cc index e1d4ac2653..31e5025a55 100644 --- a/talk/media/webrtc/webrtcmediaengine.cc +++ b/talk/media/webrtc/webrtcmediaengine.cc @@ -26,9 +26,11 @@ */ #include "talk/media/webrtc/webrtcmediaengine.h" + +#include + #include "talk/media/webrtc/webrtcvideoengine2.h" #include "talk/media/webrtc/webrtcvoiceengine.h" -#include "webrtc/base/arraysize.h" namespace cricket { @@ -69,43 +71,85 @@ MediaEngineInterface* WebRtcMediaEngineFactory::Create( return CreateWebRtcMediaEngine(adm, encoder_factory, decoder_factory); } -const char* kBweExtensionPriorities[] = { - kRtpTransportSequenceNumberHeaderExtension, - kRtpAbsoluteSenderTimeHeaderExtension, kRtpTimestampOffsetHeaderExtension}; - -const size_t kBweExtensionPrioritiesLength = arraysize(kBweExtensionPriorities); - -int GetPriority(const RtpHeaderExtension& extension, - const char* extension_prios[], - size_t extension_prios_length) { - for (size_t i = 0; i < extension_prios_length; ++i) { - if (extension.uri == extension_prios[i]) - return static_cast(i); - } - return -1; -} - -std::vector FilterRedundantRtpExtensions( - const std::vector& extensions, - const char* extension_prios[], - size_t extension_prios_length) { - if (extensions.empty()) - return std::vector(); - std::vector filtered; - std::map sorted; - for (auto& extension : extensions) { - int priority = - GetPriority(extension, extension_prios, extension_prios_length); - if (priority == -1) { - filtered.push_back(extension); - continue; - } else { - sorted[priority] = &extension; +namespace { +// Remove mutually exclusive extensions with lower priority. +void DiscardRedundantExtensions( + std::vector* extensions, + rtc::ArrayView extensions_decreasing_prio) { + RTC_DCHECK(extensions); + bool found = false; + for (const char* name : extensions_decreasing_prio) { + auto it = std::find_if(extensions->begin(), extensions->end(), + [name](const webrtc::RtpExtension& rhs) { + return rhs.name == name; + }); + if (it != extensions->end()) { + if (found) { + extensions->erase(it); + } + found = true; } } - if (!sorted.empty()) - filtered.push_back(*sorted.begin()->second); - return filtered; +} +} // namespace + +bool ValidateRtpExtensions(const std::vector& extensions) { + bool id_used[14] = {false}; + for (const auto& extension : extensions) { + if (extension.id <= 0 || extension.id >= 15) { + LOG(LS_ERROR) << "Bad RTP extension ID: " << extension.ToString(); + return false; + } + if (id_used[extension.id - 1]) { + LOG(LS_ERROR) << "Duplicate RTP extension ID: " << extension.ToString(); + return false; + } + id_used[extension.id - 1] = true; + } + return true; } +std::vector FilterRtpExtensions( + const std::vector& extensions, + bool (*supported)(const std::string&), + bool filter_redundant_extensions) { + RTC_DCHECK(ValidateRtpExtensions(extensions)); + RTC_DCHECK(supported); + std::vector result; + + // Ignore any extensions that we don't recognize. + for (const auto& extension : extensions) { + if (supported(extension.uri)) { + result.push_back({extension.uri, extension.id}); + } else { + LOG(LS_WARNING) << "Unsupported RTP extension: " << extension.ToString(); + } + } + + // Sort by name, ascending, so that we don't reset extensions if they were + // specified in a different order (also allows us to use std::unique below). + std::sort(result.begin(), result.end(), + [](const webrtc::RtpExtension& rhs, const webrtc::RtpExtension& lhs) { + return rhs.name < lhs.name; + }); + + // Remove unnecessary extensions (used on send side). + if (filter_redundant_extensions) { + auto it = std::unique(result.begin(), result.end(), + [](const webrtc::RtpExtension& rhs, const webrtc::RtpExtension& lhs) { + return rhs.name == lhs.name; + }); + result.erase(it, result.end()); + + // Keep just the highest priority extension of any in the following list. + static const char* kBweExtensionPriorities[] = { + kRtpTransportSequenceNumberHeaderExtension, + kRtpAbsoluteSenderTimeHeaderExtension, + kRtpTimestampOffsetHeaderExtension + }; + DiscardRedundantExtensions(&result, kBweExtensionPriorities); + } + + return result; +} } // namespace cricket diff --git a/talk/media/webrtc/webrtcmediaengine.h b/talk/media/webrtc/webrtcmediaengine.h index 8d7540404d..831d0725e8 100644 --- a/talk/media/webrtc/webrtcmediaengine.h +++ b/talk/media/webrtc/webrtcmediaengine.h @@ -28,7 +28,11 @@ #ifndef TALK_MEDIA_WEBRTCMEDIAENGINE_H_ #define TALK_MEDIA_WEBRTCMEDIAENGINE_H_ +#include +#include + #include "talk/media/base/mediaengine.h" +#include "webrtc/config.h" namespace webrtc { class AudioDeviceModule; @@ -48,13 +52,18 @@ class WebRtcMediaEngineFactory { WebRtcVideoDecoderFactory* decoder_factory); }; -extern const char* kBweExtensionPriorities[]; -extern const size_t kBweExtensionPrioritiesLength; +// Verify that extension IDs are within 1-byte extension range and are not +// overlapping. +bool ValidateRtpExtensions(const std::vector& extensions); -std::vector FilterRedundantRtpExtensions( +// Convert cricket::RtpHeaderExtension:s to webrtc::RtpExtension:s, discarding +// any extensions not validated by the 'supported' predicate. Duplicate +// extensions are removed if 'filter_redundant_extensions' is set, and also any +// mutually exclusive extensions (see implementation for details). +std::vector FilterRtpExtensions( const std::vector& extensions, - const char* extension_prios[], - size_t extension_prios_length); + bool (*supported)(const std::string&), + bool filter_redundant_extensions); } // namespace cricket diff --git a/talk/media/webrtc/webrtcmediaengine_unittest.cc b/talk/media/webrtc/webrtcmediaengine_unittest.cc new file mode 100644 index 0000000000..7c80e77301 --- /dev/null +++ b/talk/media/webrtc/webrtcmediaengine_unittest.cc @@ -0,0 +1,205 @@ +/* + * libjingle + * Copyright 2015 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "testing/gtest/include/gtest/gtest.h" + +#include "talk/media/webrtc/webrtcmediaengine.h" + +namespace cricket { +namespace { + +std::vector MakeUniqueExtensions() { + std::vector result; + char name[] = "a"; + for (int i = 0; i < 7; ++i) { + result.push_back(RtpHeaderExtension(name, 1 + i)); + name[0]++; + result.push_back(RtpHeaderExtension(name, 14 - i)); + name[0]++; + } + return result; +} + +std::vector MakeRedundantExtensions() { + std::vector result; + char name[] = "a"; + for (int i = 0; i < 7; ++i) { + result.push_back(RtpHeaderExtension(name, 1 + i)); + result.push_back(RtpHeaderExtension(name, 14 - i)); + name[0]++; + } + return result; +} + +bool SupportedExtensions1(const std::string& name) { + return name == "c" || name == "i"; +} + +bool SupportedExtensions2(const std::string& name) { + return name != "a" && name != "n"; +} + +bool IsSorted(const std::vector& extensions) { + const std::string* last = nullptr; + for (const auto& extension : extensions) { + if (last && *last > extension.name) { + return false; + } + last = &extension.name; + } + return true; +} +} // namespace + +TEST(WebRtcMediaEngineTest, ValidateRtpExtensions_EmptyList) { + std::vector extensions; + EXPECT_TRUE(ValidateRtpExtensions(extensions)); +} + +TEST(WebRtcMediaEngineTest, ValidateRtpExtensions_AllGood) { + std::vector extensions = MakeUniqueExtensions(); + EXPECT_TRUE(ValidateRtpExtensions(extensions)); +} + +TEST(WebRtcMediaEngineTest, ValidateRtpExtensions_OutOfRangeId_Low) { + std::vector extensions = MakeUniqueExtensions(); + extensions.push_back(RtpHeaderExtension("foo", 0)); + EXPECT_FALSE(ValidateRtpExtensions(extensions)); +} + +TEST(WebRtcMediaEngineTest, ValidateRtpExtensions_OutOfRangeId_High) { + std::vector extensions = MakeUniqueExtensions(); + extensions.push_back(RtpHeaderExtension("foo", 15)); + EXPECT_FALSE(ValidateRtpExtensions(extensions)); +} + +TEST(WebRtcMediaEngineTest, ValidateRtpExtensions_OverlappingIds_StartOfSet) { + std::vector extensions = MakeUniqueExtensions(); + extensions.push_back(RtpHeaderExtension("foo", 1)); + EXPECT_FALSE(ValidateRtpExtensions(extensions)); +} + +TEST(WebRtcMediaEngineTest, ValidateRtpExtensions_OverlappingIds_EndOfSet) { + std::vector extensions = MakeUniqueExtensions(); + extensions.push_back(RtpHeaderExtension("foo", 14)); + EXPECT_FALSE(ValidateRtpExtensions(extensions)); +} + +TEST(WebRtcMediaEngineTest, FilterRtpExtensions_EmptyList) { + std::vector extensions; + std::vector filtered = + FilterRtpExtensions(extensions, SupportedExtensions1, true); + EXPECT_EQ(0, filtered.size()); +} + +TEST(WebRtcMediaEngineTest, FilterRtpExtensions_IncludeOnlySupported) { + std::vector extensions = MakeUniqueExtensions(); + std::vector filtered = + FilterRtpExtensions(extensions, SupportedExtensions1, false); + EXPECT_EQ(2, filtered.size()); + EXPECT_EQ("c", filtered[0].name); + EXPECT_EQ("i", filtered[1].name); +} + +TEST(WebRtcMediaEngineTest, FilterRtpExtensions_SortedByName_1) { + std::vector extensions = MakeUniqueExtensions(); + std::vector filtered = + FilterRtpExtensions(extensions, SupportedExtensions2, false); + EXPECT_EQ(12, filtered.size()); + EXPECT_TRUE(IsSorted(filtered)); +} + +TEST(WebRtcMediaEngineTest, FilterRtpExtensions_SortedByName_2) { + std::vector extensions = MakeUniqueExtensions(); + std::vector filtered = + FilterRtpExtensions(extensions, SupportedExtensions2, true); + EXPECT_EQ(12, filtered.size()); + EXPECT_TRUE(IsSorted(filtered)); +} + +TEST(WebRtcMediaEngineTest, FilterRtpExtensions_DontRemoveRedundant) { + std::vector extensions = MakeRedundantExtensions(); + std::vector filtered = + FilterRtpExtensions(extensions, SupportedExtensions2, false); + EXPECT_EQ(12, filtered.size()); + EXPECT_TRUE(IsSorted(filtered)); + EXPECT_EQ(filtered[0].name, filtered[1].name); +} + +TEST(WebRtcMediaEngineTest, FilterRtpExtensions_RemoveRedundant) { + std::vector extensions = MakeRedundantExtensions(); + std::vector filtered = + FilterRtpExtensions(extensions, SupportedExtensions2, true); + EXPECT_EQ(6, filtered.size()); + EXPECT_TRUE(IsSorted(filtered)); + EXPECT_NE(filtered[0].name, filtered[1].name); +} + +TEST(WebRtcMediaEngineTest, FilterRtpExtensions_RemoveRedundantBwe_1) { + std::vector extensions; + extensions.push_back( + RtpHeaderExtension(kRtpTransportSequenceNumberHeaderExtension, 3)); + extensions.push_back( + RtpHeaderExtension(kRtpTimestampOffsetHeaderExtension, 9)); + extensions.push_back( + RtpHeaderExtension(kRtpAbsoluteSenderTimeHeaderExtension, 6)); + extensions.push_back( + RtpHeaderExtension(kRtpTransportSequenceNumberHeaderExtension, 1)); + extensions.push_back( + RtpHeaderExtension(kRtpTimestampOffsetHeaderExtension, 14)); + std::vector filtered = + FilterRtpExtensions(extensions, SupportedExtensions2, true); + EXPECT_EQ(1, filtered.size()); + EXPECT_EQ(kRtpTransportSequenceNumberHeaderExtension, filtered[0].name); +} + +TEST(WebRtcMediaEngineTest, FilterRtpExtensions_RemoveRedundantBwe_2) { + std::vector extensions; + extensions.push_back( + RtpHeaderExtension(kRtpTimestampOffsetHeaderExtension, 1)); + extensions.push_back( + RtpHeaderExtension(kRtpAbsoluteSenderTimeHeaderExtension, 14)); + extensions.push_back( + RtpHeaderExtension(kRtpTimestampOffsetHeaderExtension, 7)); + std::vector filtered = + FilterRtpExtensions(extensions, SupportedExtensions2, true); + EXPECT_EQ(1, filtered.size()); + EXPECT_EQ(kRtpAbsoluteSenderTimeHeaderExtension, filtered[0].name); +} + +TEST(WebRtcMediaEngineTest, FilterRtpExtensions_RemoveRedundantBwe_3) { + std::vector extensions; + extensions.push_back( + RtpHeaderExtension(kRtpTimestampOffsetHeaderExtension, 2)); + extensions.push_back( + RtpHeaderExtension(kRtpTimestampOffsetHeaderExtension, 14)); + std::vector filtered = + FilterRtpExtensions(extensions, SupportedExtensions2, true); + EXPECT_EQ(1, filtered.size()); + EXPECT_EQ(kRtpTimestampOffsetHeaderExtension, filtered[0].name); +} +} // namespace cricket diff --git a/talk/media/webrtc/webrtcvideoengine2.cc b/talk/media/webrtc/webrtcvideoengine2.cc index 2f07687711..308b68b457 100644 --- a/talk/media/webrtc/webrtcvideoengine2.cc +++ b/talk/media/webrtc/webrtcvideoengine2.cc @@ -243,20 +243,6 @@ static bool ValidateStreamParams(const StreamParams& sp) { return true; } -static std::string RtpExtensionsToString( - const std::vector& extensions) { - std::stringstream out; - out << '{'; - for (size_t i = 0; i < extensions.size(); ++i) { - out << "{" << extensions[i].uri << ": " << extensions[i].id << "}"; - if (i != extensions.size() - 1) { - out << ", "; - } - } - out << '}'; - return out.str(); -} - inline const webrtc::RtpExtension* FindHeaderExtension( const std::vector& extensions, const std::string& name) { @@ -370,60 +356,6 @@ static bool FindFirstMatchingCodec(const std::vector& codecs, return false; } -static bool ValidateRtpHeaderExtensionIds( - const std::vector& extensions) { - std::set extensions_used; - for (size_t i = 0; i < extensions.size(); ++i) { - if (extensions[i].id <= 0 || extensions[i].id >= 15 || - !extensions_used.insert(extensions[i].id).second) { - LOG(LS_ERROR) << "RTP extensions are with incorrect or duplicate ids."; - return false; - } - } - return true; -} - -static bool CompareRtpHeaderExtensionIds( - const webrtc::RtpExtension& extension1, - const webrtc::RtpExtension& extension2) { - // Sorting on ID is sufficient, more than one extension per ID is unsupported. - return extension1.id > extension2.id; -} - -static std::vector FilterRtpExtensions( - const std::vector& extensions) { - std::vector webrtc_extensions; - for (size_t i = 0; i < extensions.size(); ++i) { - // Unsupported extensions will be ignored. - if (webrtc::RtpExtension::IsSupportedForVideo(extensions[i].uri)) { - webrtc_extensions.push_back(webrtc::RtpExtension( - extensions[i].uri, extensions[i].id)); - } else { - LOG(LS_WARNING) << "Unsupported RTP extension: " << extensions[i].uri; - } - } - - // Sort filtered headers to make sure that they can later be compared - // regardless of in which order they were entered. - std::sort(webrtc_extensions.begin(), webrtc_extensions.end(), - CompareRtpHeaderExtensionIds); - return webrtc_extensions; -} - -static bool RtpExtensionsHaveChanged( - const std::vector& before, - const std::vector& after) { - if (before.size() != after.size()) - return true; - for (size_t i = 0; i < before.size(); ++i) { - if (before[i].id != after[i].id) - return true; - if (before[i].name != after[i].name) - return true; - } - return false; -} - std::vector WebRtcVideoChannel2::WebRtcVideoSendStream::CreateSimulcastVideoStreams( const VideoCodec& codec, @@ -856,6 +788,7 @@ bool WebRtcVideoChannel2::ReceiveCodecsHaveChanged( } bool WebRtcVideoChannel2::SetSendParameters(const VideoSendParameters& params) { + LOG(LS_INFO) << "SetSendParameters: " << params.ToString(); // TODO(pbos): Refactor this to only recreate the send streams once // instead of 4 times. return (SetSendCodecs(params.codecs) && @@ -865,6 +798,7 @@ bool WebRtcVideoChannel2::SetSendParameters(const VideoSendParameters& params) { } bool WebRtcVideoChannel2::SetRecvParameters(const VideoRecvParameters& params) { + LOG(LS_INFO) << "SetRecvParameters: " << params.ToString(); // TODO(pbos): Refactor this to only recreate the recv streams once // instead of twice. return (SetRecvCodecs(params.codecs) && @@ -1507,20 +1441,17 @@ bool WebRtcVideoChannel2::MuteStream(uint32_t ssrc, bool mute) { bool WebRtcVideoChannel2::SetRecvRtpHeaderExtensions( const std::vector& extensions) { TRACE_EVENT0("webrtc", "WebRtcVideoChannel2::SetRecvRtpHeaderExtensions"); - LOG(LS_INFO) << "SetRecvRtpHeaderExtensions: " - << RtpExtensionsToString(extensions); - if (!ValidateRtpHeaderExtensionIds(extensions)) + if (!ValidateRtpExtensions(extensions)) { return false; - - std::vector filtered_extensions = - FilterRtpExtensions(extensions); - if (!RtpExtensionsHaveChanged(recv_rtp_extensions_, filtered_extensions)) { + } + std::vector filtered_extensions = FilterRtpExtensions( + extensions, webrtc::RtpExtension::IsSupportedForVideo, false); + if (recv_rtp_extensions_ == filtered_extensions) { LOG(LS_INFO) << "Ignoring call to SetRecvRtpHeaderExtensions because " "header extensions haven't changed."; return true; } - - recv_rtp_extensions_ = filtered_extensions; + recv_rtp_extensions_.swap(filtered_extensions); rtc::CritScope stream_lock(&stream_crit_); for (std::map::iterator it = @@ -1534,21 +1465,17 @@ bool WebRtcVideoChannel2::SetRecvRtpHeaderExtensions( bool WebRtcVideoChannel2::SetSendRtpHeaderExtensions( const std::vector& extensions) { TRACE_EVENT0("webrtc", "WebRtcVideoChannel2::SetSendRtpHeaderExtensions"); - LOG(LS_INFO) << "SetSendRtpHeaderExtensions: " - << RtpExtensionsToString(extensions); - if (!ValidateRtpHeaderExtensionIds(extensions)) + if (!ValidateRtpExtensions(extensions)) { return false; - - std::vector filtered_extensions = - FilterRtpExtensions(FilterRedundantRtpExtensions( - extensions, kBweExtensionPriorities, kBweExtensionPrioritiesLength)); - if (!RtpExtensionsHaveChanged(send_rtp_extensions_, filtered_extensions)) { - LOG(LS_INFO) << "Ignoring call to SetSendRtpHeaderExtensions because " + } + std::vector filtered_extensions = FilterRtpExtensions( + extensions, webrtc::RtpExtension::IsSupportedForVideo, true); + if (send_rtp_extensions_ == filtered_extensions) { + LOG(LS_INFO) << "Ignoring call to SetRecvRtpHeaderExtensions because " "header extensions haven't changed."; return true; } - - send_rtp_extensions_ = filtered_extensions; + send_rtp_extensions_.swap(filtered_extensions); const webrtc::RtpExtension* cvo_extension = FindHeaderExtension( send_rtp_extensions_, kRtpVideoRotationHeaderExtension); diff --git a/talk/media/webrtc/webrtcvoiceengine.cc b/talk/media/webrtc/webrtcvoiceengine.cc index 8869a98cc4..76c0c0106b 100644 --- a/talk/media/webrtc/webrtcvoiceengine.cc +++ b/talk/media/webrtc/webrtcvoiceengine.cc @@ -42,6 +42,7 @@ #include "talk/media/base/audiorenderer.h" #include "talk/media/base/constants.h" #include "talk/media/base/streamparams.h" +#include "talk/media/webrtc/webrtcmediaengine.h" #include "talk/media/webrtc/webrtcvoe.h" #include "webrtc/base/arraysize.h" #include "webrtc/base/base64.h" @@ -296,20 +297,6 @@ webrtc::AudioState::Config MakeAudioStateConfig(VoEWrapper* voe_wrapper) { return config; } -std::vector FindAudioRtpHeaderExtensions( - const std::vector& extensions) { - std::vector result; - for (const auto& extension : extensions) { - if (extension.uri == kRtpAbsoluteSenderTimeHeaderExtension || - extension.uri == kRtpAudioLevelHeaderExtension) { - result.push_back({extension.uri, extension.id}); - } else { - LOG(LS_WARNING) << "Unsupported RTP extension: " << extension.ToString(); - } - } - return result; -} - class WebRtcVoiceCodecs final { public: // TODO(solenberg): Do this filtering once off-line, add a simple AudioCodec @@ -1450,6 +1437,8 @@ WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel() { bool WebRtcVoiceMediaChannel::SetSendParameters( const AudioSendParameters& params) { RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); + LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetSendParameters: " + << params.ToString(); // TODO(pthatcher): Refactor this to be more clean now that we have // all the information at once. @@ -1457,10 +1446,14 @@ bool WebRtcVoiceMediaChannel::SetSendParameters( return false; } - std::vector send_rtp_extensions = - FindAudioRtpHeaderExtensions(params.extensions); - if (send_rtp_extensions_ != send_rtp_extensions) { - send_rtp_extensions_.swap(send_rtp_extensions); + if (!ValidateRtpExtensions(params.extensions)) { + return false; + } + std::vector filtered_extensions = + FilterRtpExtensions(params.extensions, + webrtc::RtpExtension::IsSupportedForAudio, true); + if (send_rtp_extensions_ != filtered_extensions) { + send_rtp_extensions_.swap(filtered_extensions); for (auto& it : send_streams_) { it.second->RecreateAudioSendStream(send_rtp_extensions_); } @@ -1475,6 +1468,8 @@ bool WebRtcVoiceMediaChannel::SetSendParameters( bool WebRtcVoiceMediaChannel::SetRecvParameters( const AudioRecvParameters& params) { RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); + LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetRecvParameters: " + << params.ToString(); // TODO(pthatcher): Refactor this to be more clean now that we have // all the information at once. @@ -1482,10 +1477,14 @@ bool WebRtcVoiceMediaChannel::SetRecvParameters( return false; } - std::vector recv_rtp_extensions = - FindAudioRtpHeaderExtensions(params.extensions); - if (recv_rtp_extensions_ != recv_rtp_extensions) { - recv_rtp_extensions_.swap(recv_rtp_extensions); + if (!ValidateRtpExtensions(params.extensions)) { + return false; + } + std::vector filtered_extensions = + FilterRtpExtensions(params.extensions, + webrtc::RtpExtension::IsSupportedForAudio, false); + if (recv_rtp_extensions_ != filtered_extensions) { + recv_rtp_extensions_.swap(filtered_extensions); for (auto& it : recv_streams_) { it.second->RecreateAudioReceiveStream(recv_rtp_extensions_); }