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:
@ -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',
|
||||
|
@ -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 << "{";
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
205
talk/media/webrtc/webrtcmediaengine_unittest.cc
Normal file
205
talk/media/webrtc/webrtcmediaengine_unittest.cc
Normal 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
|
@ -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);
|
||||
|
@ -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_);
|
||||
}
|
||||
|
Reference in New Issue
Block a user