Filter overlapping RTP header extensions.

This removes unnecessary RTP header extension overhead since only one of
these extensions is used at a time.

BUG=webrtc:4254
R=pbos@webrtc.org

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

Cr-Commit-Position: refs/heads/master@{#10455}
This commit is contained in:
Stefan Holmer 2015-10-29 18:53:23 +01:00
parent 4f5db11e45
commit bbaf3633c5
4 changed files with 94 additions and 7 deletions

View File

@ -68,4 +68,44 @@ MediaEngineInterface* WebRtcMediaEngineFactory::Create(
return CreateWebRtcMediaEngine(adm, encoder_factory, decoder_factory);
}
const char* kBweExtensionPriorities[] = {
kRtpTransportSequenceNumberHeaderExtension,
kRtpAbsoluteSenderTimeHeaderExtension, kRtpTimestampOffsetHeaderExtension};
const size_t kBweExtensionPrioritiesLength =
ARRAY_SIZE(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;
}
}
if (!sorted.empty())
filtered.push_back(*sorted.begin()->second);
return filtered;
}
} // namespace cricket

View File

@ -48,6 +48,14 @@ class WebRtcMediaEngineFactory {
WebRtcVideoDecoderFactory* decoder_factory);
};
extern const char* kBweExtensionPriorities[];
extern const size_t kBweExtensionPrioritiesLength;
std::vector<RtpHeaderExtension> FilterRedundantRtpExtensions(
const std::vector<RtpHeaderExtension>& extensions,
const char* extension_prios[],
size_t extension_prios_length);
} // namespace cricket
#endif // TALK_MEDIA_WEBRTCMEDIAENGINE_H_

View File

@ -36,6 +36,7 @@
#include "talk/media/base/videorenderer.h"
#include "talk/media/webrtc/constants.h"
#include "talk/media/webrtc/simulcast.h"
#include "talk/media/webrtc/webrtcmediaengine.h"
#include "talk/media/webrtc/webrtcvideoencoderfactory.h"
#include "talk/media/webrtc/webrtcvideoframe.h"
#include "talk/media/webrtc/webrtcvoiceengine.h"
@ -1544,7 +1545,8 @@ bool WebRtcVideoChannel2::SetSendRtpHeaderExtensions(
return false;
std::vector<webrtc::RtpExtension> filtered_extensions =
FilterRtpExtensions(extensions);
FilterRtpExtensions(FilterRedundantRtpExtensions(
extensions, kBweExtensionPriorities, kBweExtensionPrioritiesLength));
if (!RtpExtensionsHaveChanged(send_rtp_extensions_, filtered_extensions)) {
LOG(LS_INFO) << "Ignoring call to SetSendRtpHeaderExtensions because "
"header extensions haven't changed.";

View File

@ -1066,6 +1066,29 @@ class WebRtcVideoChannel2Test : public WebRtcVideoEngine2Test {
EXPECT_EQ(webrtc_ext, recv_stream->GetConfig().rtp.extensions[0].name);
}
void TestExtensionFilter(const std::vector<std::string>& extensions,
const std::string& expected_extension) {
cricket::VideoSendParameters parameters = send_parameters_;
int expected_id = -1;
int id = 1;
for (const std::string& extension : extensions) {
if (extension == expected_extension)
expected_id = id;
parameters.extensions.push_back(
cricket::RtpHeaderExtension(extension, id++));
}
EXPECT_TRUE(channel_->SetSendParameters(parameters));
FakeVideoSendStream* send_stream =
AddSendStream(cricket::StreamParams::CreateLegacy(123));
// Verify that only one of them has been set, and that it is the one with
// highest priority (transport sequence number).
ASSERT_EQ(1u, send_stream->GetConfig().rtp.extensions.size());
EXPECT_EQ(expected_id, send_stream->GetConfig().rtp.extensions[0].id);
EXPECT_EQ(expected_extension,
send_stream->GetConfig().rtp.extensions[0].name);
}
void TestCpuAdaptation(bool enable_overuse, bool is_screenshare);
void TestReceiverLocalSsrcConfiguration(bool receiver_first);
void TestReceiveUnsignalledSsrcPacket(uint8_t payload_type,
@ -1199,6 +1222,23 @@ TEST_F(WebRtcVideoChannel2Test, RecvAbsoluteSendTimeHeaderExtensions) {
webrtc::RtpExtension::kAbsSendTime);
}
TEST_F(WebRtcVideoChannel2Test, FiltersExtensionsPicksTransportSeqNum) {
// Enable three redundant extensions.
std::vector<std::string> extensions;
extensions.push_back(kRtpAbsoluteSenderTimeHeaderExtension);
extensions.push_back(kRtpTimestampOffsetHeaderExtension);
extensions.push_back(kRtpTransportSequenceNumberHeaderExtension);
TestExtensionFilter(extensions, kRtpTransportSequenceNumberHeaderExtension);
}
TEST_F(WebRtcVideoChannel2Test, FiltersExtensionsPicksAbsSendTime) {
// Enable two redundant extensions.
std::vector<std::string> extensions;
extensions.push_back(kRtpAbsoluteSenderTimeHeaderExtension);
extensions.push_back(kRtpTimestampOffsetHeaderExtension);
TestExtensionFilter(extensions, kRtpAbsoluteSenderTimeHeaderExtension);
}
class WebRtcVideoChannel2WithSendSideBweTest : public WebRtcVideoChannel2Test {
public:
WebRtcVideoChannel2WithSendSideBweTest()
@ -1230,13 +1270,10 @@ TEST_F(WebRtcVideoChannel2Test, RecvVideoRotationHeaderExtensions) {
}
TEST_F(WebRtcVideoChannel2Test, IdenticalSendExtensionsDoesntRecreateStream) {
const int kTOffsetId = 1;
const int kAbsSendTimeId = 2;
const int kVideoRotationId = 3;
const int kAbsSendTimeId = 1;
const int kVideoRotationId = 2;
send_parameters_.extensions.push_back(cricket::RtpHeaderExtension(
kRtpAbsoluteSenderTimeHeaderExtension, kAbsSendTimeId));
send_parameters_.extensions.push_back(cricket::RtpHeaderExtension(
kRtpTimestampOffsetHeaderExtension, kTOffsetId));
send_parameters_.extensions.push_back(cricket::RtpHeaderExtension(
kRtpVideoRotationHeaderExtension, kVideoRotationId));
@ -1245,7 +1282,7 @@ TEST_F(WebRtcVideoChannel2Test, IdenticalSendExtensionsDoesntRecreateStream) {
AddSendStream(cricket::StreamParams::CreateLegacy(123));
EXPECT_EQ(1, fake_call_->GetNumCreatedSendStreams());
ASSERT_EQ(3u, send_stream->GetConfig().rtp.extensions.size());
ASSERT_EQ(2u, send_stream->GetConfig().rtp.extensions.size());
// Setting the same extensions (even if in different order) shouldn't
// reallocate the stream.