Add header extension filtering for WebRtcVoiceEngine/MediaChannel.

Rework filtering functionality to be reused for both Audio+Video.

BUG=webrtc:4690

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

Cr-Commit-Position: refs/heads/master@{#10869}
This commit is contained in:
solenberg
2015-12-02 08:05:01 -08:00
committed by Commit bot
parent 2515af28e9
commit 7e4e01a441
7 changed files with 342 additions and 158 deletions

View File

@ -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',

View File

@ -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 <class Codec>
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 <class Codec, class Options>
struct RtpSendParameters : RtpParameters<Codec> {
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<DataCodec, DataOptions> {
std::string ToString() {
std::string ToString() const {
std::ostringstream ost;
// Options and extensions aren't used.
ost << "{";

View File

@ -26,9 +26,11 @@
*/
#include "talk/media/webrtc/webrtcmediaengine.h"
#include <algorithm>
#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<int>(i);
}
return -1;
}
std::vector<RtpHeaderExtension> FilterRedundantRtpExtensions(
const std::vector<RtpHeaderExtension>& extensions,
const char* extension_prios[],
size_t extension_prios_length) {
if (extensions.empty())
return std::vector<RtpHeaderExtension>();
std::vector<RtpHeaderExtension> filtered;
std::map<int, const RtpHeaderExtension*> 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<webrtc::RtpExtension>* extensions,
rtc::ArrayView<const char*> 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<RtpHeaderExtension>& 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<webrtc::RtpExtension> FilterRtpExtensions(
const std::vector<RtpHeaderExtension>& extensions,
bool (*supported)(const std::string&),
bool filter_redundant_extensions) {
RTC_DCHECK(ValidateRtpExtensions(extensions));
RTC_DCHECK(supported);
std::vector<webrtc::RtpExtension> 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

View File

@ -28,7 +28,11 @@
#ifndef TALK_MEDIA_WEBRTCMEDIAENGINE_H_
#define TALK_MEDIA_WEBRTCMEDIAENGINE_H_
#include <string>
#include <vector>
#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<RtpHeaderExtension>& extensions);
std::vector<RtpHeaderExtension> 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<webrtc::RtpExtension> FilterRtpExtensions(
const std::vector<RtpHeaderExtension>& extensions,
const char* extension_prios[],
size_t extension_prios_length);
bool (*supported)(const std::string&),
bool filter_redundant_extensions);
} // namespace cricket

View File

@ -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<RtpHeaderExtension> MakeUniqueExtensions() {
std::vector<RtpHeaderExtension> 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<RtpHeaderExtension> MakeRedundantExtensions() {
std::vector<RtpHeaderExtension> 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<webrtc::RtpExtension>& 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<RtpHeaderExtension> extensions;
EXPECT_TRUE(ValidateRtpExtensions(extensions));
}
TEST(WebRtcMediaEngineTest, ValidateRtpExtensions_AllGood) {
std::vector<RtpHeaderExtension> extensions = MakeUniqueExtensions();
EXPECT_TRUE(ValidateRtpExtensions(extensions));
}
TEST(WebRtcMediaEngineTest, ValidateRtpExtensions_OutOfRangeId_Low) {
std::vector<RtpHeaderExtension> extensions = MakeUniqueExtensions();
extensions.push_back(RtpHeaderExtension("foo", 0));
EXPECT_FALSE(ValidateRtpExtensions(extensions));
}
TEST(WebRtcMediaEngineTest, ValidateRtpExtensions_OutOfRangeId_High) {
std::vector<RtpHeaderExtension> extensions = MakeUniqueExtensions();
extensions.push_back(RtpHeaderExtension("foo", 15));
EXPECT_FALSE(ValidateRtpExtensions(extensions));
}
TEST(WebRtcMediaEngineTest, ValidateRtpExtensions_OverlappingIds_StartOfSet) {
std::vector<RtpHeaderExtension> extensions = MakeUniqueExtensions();
extensions.push_back(RtpHeaderExtension("foo", 1));
EXPECT_FALSE(ValidateRtpExtensions(extensions));
}
TEST(WebRtcMediaEngineTest, ValidateRtpExtensions_OverlappingIds_EndOfSet) {
std::vector<RtpHeaderExtension> extensions = MakeUniqueExtensions();
extensions.push_back(RtpHeaderExtension("foo", 14));
EXPECT_FALSE(ValidateRtpExtensions(extensions));
}
TEST(WebRtcMediaEngineTest, FilterRtpExtensions_EmptyList) {
std::vector<RtpHeaderExtension> extensions;
std::vector<webrtc::RtpExtension> filtered =
FilterRtpExtensions(extensions, SupportedExtensions1, true);
EXPECT_EQ(0, filtered.size());
}
TEST(WebRtcMediaEngineTest, FilterRtpExtensions_IncludeOnlySupported) {
std::vector<RtpHeaderExtension> extensions = MakeUniqueExtensions();
std::vector<webrtc::RtpExtension> 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<RtpHeaderExtension> extensions = MakeUniqueExtensions();
std::vector<webrtc::RtpExtension> filtered =
FilterRtpExtensions(extensions, SupportedExtensions2, false);
EXPECT_EQ(12, filtered.size());
EXPECT_TRUE(IsSorted(filtered));
}
TEST(WebRtcMediaEngineTest, FilterRtpExtensions_SortedByName_2) {
std::vector<RtpHeaderExtension> extensions = MakeUniqueExtensions();
std::vector<webrtc::RtpExtension> filtered =
FilterRtpExtensions(extensions, SupportedExtensions2, true);
EXPECT_EQ(12, filtered.size());
EXPECT_TRUE(IsSorted(filtered));
}
TEST(WebRtcMediaEngineTest, FilterRtpExtensions_DontRemoveRedundant) {
std::vector<RtpHeaderExtension> extensions = MakeRedundantExtensions();
std::vector<webrtc::RtpExtension> 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<RtpHeaderExtension> extensions = MakeRedundantExtensions();
std::vector<webrtc::RtpExtension> 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<RtpHeaderExtension> 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<webrtc::RtpExtension> filtered =
FilterRtpExtensions(extensions, SupportedExtensions2, true);
EXPECT_EQ(1, filtered.size());
EXPECT_EQ(kRtpTransportSequenceNumberHeaderExtension, filtered[0].name);
}
TEST(WebRtcMediaEngineTest, FilterRtpExtensions_RemoveRedundantBwe_2) {
std::vector<RtpHeaderExtension> extensions;
extensions.push_back(
RtpHeaderExtension(kRtpTimestampOffsetHeaderExtension, 1));
extensions.push_back(
RtpHeaderExtension(kRtpAbsoluteSenderTimeHeaderExtension, 14));
extensions.push_back(
RtpHeaderExtension(kRtpTimestampOffsetHeaderExtension, 7));
std::vector<webrtc::RtpExtension> filtered =
FilterRtpExtensions(extensions, SupportedExtensions2, true);
EXPECT_EQ(1, filtered.size());
EXPECT_EQ(kRtpAbsoluteSenderTimeHeaderExtension, filtered[0].name);
}
TEST(WebRtcMediaEngineTest, FilterRtpExtensions_RemoveRedundantBwe_3) {
std::vector<RtpHeaderExtension> extensions;
extensions.push_back(
RtpHeaderExtension(kRtpTimestampOffsetHeaderExtension, 2));
extensions.push_back(
RtpHeaderExtension(kRtpTimestampOffsetHeaderExtension, 14));
std::vector<webrtc::RtpExtension> filtered =
FilterRtpExtensions(extensions, SupportedExtensions2, true);
EXPECT_EQ(1, filtered.size());
EXPECT_EQ(kRtpTimestampOffsetHeaderExtension, filtered[0].name);
}
} // namespace cricket

View File

@ -243,20 +243,6 @@ static bool ValidateStreamParams(const StreamParams& sp) {
return true;
}
static std::string RtpExtensionsToString(
const std::vector<RtpHeaderExtension>& 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<webrtc::RtpExtension>& extensions,
const std::string& name) {
@ -370,60 +356,6 @@ static bool FindFirstMatchingCodec(const std::vector<VideoCodec>& codecs,
return false;
}
static bool ValidateRtpHeaderExtensionIds(
const std::vector<RtpHeaderExtension>& extensions) {
std::set<int> 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<webrtc::RtpExtension> FilterRtpExtensions(
const std::vector<RtpHeaderExtension>& extensions) {
std::vector<webrtc::RtpExtension> 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<webrtc::RtpExtension>& before,
const std::vector<webrtc::RtpExtension>& 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<webrtc::VideoStream>
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<RtpHeaderExtension>& extensions) {
TRACE_EVENT0("webrtc", "WebRtcVideoChannel2::SetRecvRtpHeaderExtensions");
LOG(LS_INFO) << "SetRecvRtpHeaderExtensions: "
<< RtpExtensionsToString(extensions);
if (!ValidateRtpHeaderExtensionIds(extensions))
if (!ValidateRtpExtensions(extensions)) {
return false;
std::vector<webrtc::RtpExtension> filtered_extensions =
FilterRtpExtensions(extensions);
if (!RtpExtensionsHaveChanged(recv_rtp_extensions_, filtered_extensions)) {
}
std::vector<webrtc::RtpExtension> 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<uint32_t, WebRtcVideoReceiveStream*>::iterator it =
@ -1534,21 +1465,17 @@ bool WebRtcVideoChannel2::SetRecvRtpHeaderExtensions(
bool WebRtcVideoChannel2::SetSendRtpHeaderExtensions(
const std::vector<RtpHeaderExtension>& extensions) {
TRACE_EVENT0("webrtc", "WebRtcVideoChannel2::SetSendRtpHeaderExtensions");
LOG(LS_INFO) << "SetSendRtpHeaderExtensions: "
<< RtpExtensionsToString(extensions);
if (!ValidateRtpHeaderExtensionIds(extensions))
if (!ValidateRtpExtensions(extensions)) {
return false;
std::vector<webrtc::RtpExtension> filtered_extensions =
FilterRtpExtensions(FilterRedundantRtpExtensions(
extensions, kBweExtensionPriorities, kBweExtensionPrioritiesLength));
if (!RtpExtensionsHaveChanged(send_rtp_extensions_, filtered_extensions)) {
LOG(LS_INFO) << "Ignoring call to SetSendRtpHeaderExtensions because "
}
std::vector<webrtc::RtpExtension> 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);

View File

@ -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<webrtc::RtpExtension> FindAudioRtpHeaderExtensions(
const std::vector<RtpHeaderExtension>& extensions) {
std::vector<webrtc::RtpExtension> 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<webrtc::RtpExtension> 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<webrtc::RtpExtension> 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<webrtc::RtpExtension> 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<webrtc::RtpExtension> 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_);
}