RtpTransceiverInterface: add header_extensions_to_offer()

This change adds exposure of a new transceiver method for getting
the total set of supported extensions stored as an attribute,
and their direction. If the direction is kStopped, the extension
is not signalled in Unified Plan SDP negotiation.

Note: SDP negotiation is not modified by this change.

Changes:
- RtpHeaderExtensionCapability gets a new RtpTransceiverDirection,
  indicating either kStopped (extension available but not signalled),
  or other (extension signalled).
- RtpTransceiver gets the new method as described above. The
  default value of the attribute comes from the voice and video
  engines as before.

https://chromestatus.com/feature/5680189201711104.
go/rtp-header-extension-ip
Intent to prototype: https://groups.google.com/a/chromium.org/g/blink-dev/c/65YdUi02yZk

Bug: chromium:1051821
Change-Id: I440443b474db5b1cfe8c6b25b6c10a3ff9c21a8c
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/170235
Commit-Queue: Markus Handell <handellm@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#30800}
This commit is contained in:
Markus Handell 2020-03-16 13:40:51 +01:00 committed by Commit Bot
parent 645f24cb86
commit 0357b3e7b6
29 changed files with 486 additions and 122 deletions

View file

@ -171,6 +171,7 @@ rtc_library("libjingle_peerconnection_api") {
":rtc_stats_api", ":rtc_stats_api",
":rtp_packet_info", ":rtp_packet_info",
":rtp_parameters", ":rtp_parameters",
":rtp_transceiver_direction",
":scoped_refptr", ":scoped_refptr",
"audio:audio_mixer_api", "audio:audio_mixer_api",
"audio_codecs:audio_codecs_api", "audio_codecs:audio_codecs_api",
@ -297,6 +298,11 @@ rtc_source_set("track_id_stream_label_map") {
sources = [ "test/track_id_stream_label_map.h" ] sources = [ "test/track_id_stream_label_map.h" ]
} }
rtc_source_set("rtp_transceiver_direction") {
visibility = [ "*" ]
sources = [ "rtp_transceiver_direction.h" ]
}
rtc_library("rtp_parameters") { rtc_library("rtp_parameters") {
visibility = [ "*" ] visibility = [ "*" ]
sources = [ sources = [
@ -307,6 +313,7 @@ rtc_library("rtp_parameters") {
] ]
deps = [ deps = [
":array_view", ":array_view",
":rtp_transceiver_direction",
"../rtc_base:checks", "../rtc_base:checks",
"../rtc_base:stringutils", "../rtc_base:stringutils",
"../rtc_base/system:rtc_export", "../rtc_base/system:rtc_export",

View file

@ -38,6 +38,11 @@ RtpHeaderExtensionCapability::RtpHeaderExtensionCapability(
const std::string& uri, const std::string& uri,
int preferred_id) int preferred_id)
: uri(uri), preferred_id(preferred_id) {} : uri(uri), preferred_id(preferred_id) {}
RtpHeaderExtensionCapability::RtpHeaderExtensionCapability(
const std::string& uri,
int preferred_id,
RtpTransceiverDirection direction)
: uri(uri), preferred_id(preferred_id), direction(direction) {}
RtpHeaderExtensionCapability::~RtpHeaderExtensionCapability() = default; RtpHeaderExtensionCapability::~RtpHeaderExtensionCapability() = default;
RtpExtension::RtpExtension() = default; RtpExtension::RtpExtension() = default;

View file

@ -19,6 +19,7 @@
#include "absl/types/optional.h" #include "absl/types/optional.h"
#include "api/media_types.h" #include "api/media_types.h"
#include "api/rtp_transceiver_direction.h"
#include "rtc_base/system/rtc_export.h" #include "rtc_base/system/rtc_export.h"
namespace webrtc { namespace webrtc {
@ -200,7 +201,8 @@ struct RTC_EXPORT RtpCodecCapability {
bool operator!=(const RtpCodecCapability& o) const { return !(*this == o); } bool operator!=(const RtpCodecCapability& o) const { return !(*this == o); }
}; };
// Used in RtpCapabilities; represents the capabilities/preferences of an // Used in RtpCapabilities and RtpTransceiverInterface's header extensions query
// and setup methods; represents the capabilities/preferences of an
// implementation for a header extension. // implementation for a header extension.
// //
// Just called "RtpHeaderExtension" in ORTC, but the "Capability" suffix was // Just called "RtpHeaderExtension" in ORTC, but the "Capability" suffix was
@ -210,7 +212,7 @@ struct RTC_EXPORT RtpCodecCapability {
// Note that ORTC includes a "kind" field, but we omit this because it's // Note that ORTC includes a "kind" field, but we omit this because it's
// redundant; if you call "RtpReceiver::GetCapabilities(MEDIA_TYPE_AUDIO)", // redundant; if you call "RtpReceiver::GetCapabilities(MEDIA_TYPE_AUDIO)",
// you know you're getting audio capabilities. // you know you're getting audio capabilities.
struct RtpHeaderExtensionCapability { struct RTC_EXPORT RtpHeaderExtensionCapability {
// URI of this extension, as defined in RFC8285. // URI of this extension, as defined in RFC8285.
std::string uri; std::string uri;
@ -221,15 +223,23 @@ struct RtpHeaderExtensionCapability {
// TODO(deadbeef): Not implemented. // TODO(deadbeef): Not implemented.
bool preferred_encrypt = false; bool preferred_encrypt = false;
// The direction of the extension. The kStopped value is only used with
// RtpTransceiverInterface::header_extensions_offered() and
// SetOfferedRtpHeaderExtensions().
RtpTransceiverDirection direction = RtpTransceiverDirection::kSendRecv;
// Constructors for convenience. // Constructors for convenience.
RtpHeaderExtensionCapability(); RtpHeaderExtensionCapability();
explicit RtpHeaderExtensionCapability(const std::string& uri); explicit RtpHeaderExtensionCapability(const std::string& uri);
RtpHeaderExtensionCapability(const std::string& uri, int preferred_id); RtpHeaderExtensionCapability(const std::string& uri, int preferred_id);
RtpHeaderExtensionCapability(const std::string& uri,
int preferred_id,
RtpTransceiverDirection direction);
~RtpHeaderExtensionCapability(); ~RtpHeaderExtensionCapability();
bool operator==(const RtpHeaderExtensionCapability& o) const { bool operator==(const RtpHeaderExtensionCapability& o) const {
return uri == o.uri && preferred_id == o.preferred_id && return uri == o.uri && preferred_id == o.preferred_id &&
preferred_encrypt == o.preferred_encrypt; preferred_encrypt == o.preferred_encrypt && direction == o.direction;
} }
bool operator!=(const RtpHeaderExtensionCapability& o) const { bool operator!=(const RtpHeaderExtensionCapability& o) const {
return !(*this == o); return !(*this == o);

View file

@ -0,0 +1,27 @@
/*
* Copyright 2020 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef API_RTP_TRANSCEIVER_DIRECTION_H_
#define API_RTP_TRANSCEIVER_DIRECTION_H_
namespace webrtc {
// https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiverdirection
enum class RtpTransceiverDirection {
kSendRecv,
kSendOnly,
kRecvOnly,
kInactive,
kStopped,
};
} // namespace webrtc
#endif // API_RTP_TRANSCEIVER_DIRECTION_H_

View file

@ -36,4 +36,9 @@ std::vector<RtpCodecCapability> RtpTransceiverInterface::codec_preferences()
return {}; return {};
} }
std::vector<RtpHeaderExtensionCapability>
RtpTransceiverInterface::HeaderExtensionsToOffer() const {
return {};
}
} // namespace webrtc } // namespace webrtc

View file

@ -20,21 +20,13 @@
#include "api/rtp_parameters.h" #include "api/rtp_parameters.h"
#include "api/rtp_receiver_interface.h" #include "api/rtp_receiver_interface.h"
#include "api/rtp_sender_interface.h" #include "api/rtp_sender_interface.h"
#include "api/rtp_transceiver_direction.h"
#include "api/scoped_refptr.h" #include "api/scoped_refptr.h"
#include "rtc_base/ref_count.h" #include "rtc_base/ref_count.h"
#include "rtc_base/system/rtc_export.h" #include "rtc_base/system/rtc_export.h"
namespace webrtc { namespace webrtc {
// https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiverdirection
enum class RtpTransceiverDirection {
kSendRecv,
kSendOnly,
kRecvOnly,
kInactive,
kStopped,
};
// Structure for initializing an RtpTransceiver in a call to // Structure for initializing an RtpTransceiver in a call to
// PeerConnectionInterface::AddTransceiver. // PeerConnectionInterface::AddTransceiver.
// https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiverinit // https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiverinit
@ -134,6 +126,13 @@ class RTC_EXPORT RtpTransceiverInterface : public rtc::RefCountInterface {
rtc::ArrayView<RtpCodecCapability> codecs); rtc::ArrayView<RtpCodecCapability> codecs);
virtual std::vector<RtpCodecCapability> codec_preferences() const; virtual std::vector<RtpCodecCapability> codec_preferences() const;
// Readonly attribute which contains the set of header extensions that was set
// with SetOfferedRtpHeaderExtensions, or a default set if it has not been
// called.
// https://w3c.github.io/webrtc-extensions/#rtcrtptransceiver-interface
virtual std::vector<RtpHeaderExtensionCapability> HeaderExtensionsToOffer()
const;
protected: protected:
~RtpTransceiverInterface() override = default; ~RtpTransceiverInterface() override = default;
}; };

View file

@ -599,6 +599,7 @@ if (rtc_include_tests) {
] ]
sources = [ sources = [
"base/codec_unittest.cc", "base/codec_unittest.cc",
"base/media_engine_unittest.cc",
"base/rtp_data_engine_unittest.cc", "base/rtp_data_engine_unittest.cc",
"base/rtp_utils_unittest.cc", "base/rtp_utils_unittest.cc",
"base/sdp_fmtp_utils_unittest.cc", "base/sdp_fmtp_utils_unittest.cc",

View file

@ -513,9 +513,6 @@ FakeVoiceEngine::FakeVoiceEngine() : fail_create_channel_(false) {
// sanity checks against that. // sanity checks against that.
SetCodecs({AudioCodec(101, "fake_audio_codec", 0, 0, 1)}); SetCodecs({AudioCodec(101, "fake_audio_codec", 0, 0, 1)});
} }
RtpCapabilities FakeVoiceEngine::GetCapabilities() const {
return RtpCapabilities();
}
void FakeVoiceEngine::Init() {} void FakeVoiceEngine::Init() {}
rtc::scoped_refptr<webrtc::AudioState> FakeVoiceEngine::GetAudioState() const { rtc::scoped_refptr<webrtc::AudioState> FakeVoiceEngine::GetAudioState() const {
return rtc::scoped_refptr<webrtc::AudioState>(); return rtc::scoped_refptr<webrtc::AudioState>();
@ -564,15 +561,22 @@ bool FakeVoiceEngine::StartAecDump(webrtc::FileWrapper file,
} }
void FakeVoiceEngine::StopAecDump() {} void FakeVoiceEngine::StopAecDump() {}
std::vector<webrtc::RtpHeaderExtensionCapability>
FakeVoiceEngine::GetRtpHeaderExtensions() const {
return header_extensions_;
}
void FakeVoiceEngine::SetRtpHeaderExtensions(
std::vector<webrtc::RtpHeaderExtensionCapability> header_extensions) {
header_extensions_ = std::move(header_extensions);
}
FakeVideoEngine::FakeVideoEngine() FakeVideoEngine::FakeVideoEngine()
: capture_(false), fail_create_channel_(false) { : capture_(false), fail_create_channel_(false) {
// Add a fake video codec. Note that the name must not be "" as there are // Add a fake video codec. Note that the name must not be "" as there are
// sanity checks against that. // sanity checks against that.
codecs_.push_back(VideoCodec(0, "fake_video_codec")); codecs_.push_back(VideoCodec(0, "fake_video_codec"));
} }
RtpCapabilities FakeVideoEngine::GetCapabilities() const {
return RtpCapabilities();
}
bool FakeVideoEngine::SetOptions(const VideoOptions& options) { bool FakeVideoEngine::SetOptions(const VideoOptions& options) {
options_ = options; options_ = options;
return true; return true;
@ -609,6 +613,14 @@ bool FakeVideoEngine::SetCapture(bool capture) {
capture_ = capture; capture_ = capture;
return true; return true;
} }
std::vector<webrtc::RtpHeaderExtensionCapability>
FakeVideoEngine::GetRtpHeaderExtensions() const {
return header_extensions_;
}
void FakeVideoEngine::SetRtpHeaderExtensions(
std::vector<webrtc::RtpHeaderExtensionCapability> header_extensions) {
header_extensions_ = std::move(header_extensions);
}
FakeMediaEngine::FakeMediaEngine() FakeMediaEngine::FakeMediaEngine()
: CompositeMediaEngine(std::make_unique<FakeVoiceEngine>(), : CompositeMediaEngine(std::make_unique<FakeVoiceEngine>(),

View file

@ -514,7 +514,6 @@ class FakeDataMediaChannel : public RtpHelper<DataMediaChannel> {
class FakeVoiceEngine : public VoiceEngineInterface { class FakeVoiceEngine : public VoiceEngineInterface {
public: public:
FakeVoiceEngine(); FakeVoiceEngine();
RtpCapabilities GetCapabilities() const override;
void Init() override; void Init() override;
rtc::scoped_refptr<webrtc::AudioState> GetAudioState() const override; rtc::scoped_refptr<webrtc::AudioState> GetAudioState() const override;
@ -536,12 +535,17 @@ class FakeVoiceEngine : public VoiceEngineInterface {
int GetInputLevel(); int GetInputLevel();
bool StartAecDump(webrtc::FileWrapper file, int64_t max_size_bytes) override; bool StartAecDump(webrtc::FileWrapper file, int64_t max_size_bytes) override;
void StopAecDump() override; void StopAecDump() override;
std::vector<webrtc::RtpHeaderExtensionCapability> GetRtpHeaderExtensions()
const override;
void SetRtpHeaderExtensions(
std::vector<webrtc::RtpHeaderExtensionCapability> header_extensions);
private: private:
std::vector<FakeVoiceMediaChannel*> channels_; std::vector<FakeVoiceMediaChannel*> channels_;
std::vector<AudioCodec> recv_codecs_; std::vector<AudioCodec> recv_codecs_;
std::vector<AudioCodec> send_codecs_; std::vector<AudioCodec> send_codecs_;
bool fail_create_channel_; bool fail_create_channel_;
std::vector<webrtc::RtpHeaderExtensionCapability> header_extensions_;
friend class FakeMediaEngine; friend class FakeMediaEngine;
}; };
@ -549,7 +553,6 @@ class FakeVoiceEngine : public VoiceEngineInterface {
class FakeVideoEngine : public VideoEngineInterface { class FakeVideoEngine : public VideoEngineInterface {
public: public:
FakeVideoEngine(); FakeVideoEngine();
RtpCapabilities GetCapabilities() const override;
bool SetOptions(const VideoOptions& options); bool SetOptions(const VideoOptions& options);
VideoMediaChannel* CreateMediaChannel( VideoMediaChannel* CreateMediaChannel(
webrtc::Call* call, webrtc::Call* call,
@ -563,6 +566,10 @@ class FakeVideoEngine : public VideoEngineInterface {
std::vector<VideoCodec> codecs() const override; std::vector<VideoCodec> codecs() const override;
void SetCodecs(const std::vector<VideoCodec> codecs); void SetCodecs(const std::vector<VideoCodec> codecs);
bool SetCapture(bool capture); bool SetCapture(bool capture);
std::vector<webrtc::RtpHeaderExtensionCapability> GetRtpHeaderExtensions()
const override;
void SetRtpHeaderExtensions(
std::vector<webrtc::RtpHeaderExtensionCapability> header_extensions);
private: private:
std::vector<FakeVideoMediaChannel*> channels_; std::vector<FakeVideoMediaChannel*> channels_;
@ -570,6 +577,7 @@ class FakeVideoEngine : public VideoEngineInterface {
bool capture_; bool capture_;
VideoOptions options_; VideoOptions options_;
bool fail_create_channel_; bool fail_create_channel_;
std::vector<webrtc::RtpHeaderExtensionCapability> header_extensions_;
friend class FakeMediaEngine; friend class FakeMediaEngine;
}; };

View file

@ -55,6 +55,16 @@ webrtc::RtpParameters CreateRtpParametersWithEncodings(StreamParams sp) {
return parameters; return parameters;
} }
std::vector<webrtc::RtpExtension> GetDefaultEnabledRtpHeaderExtensions(
const RtpHeaderExtensionQueryInterface& query_interface) {
std::vector<webrtc::RtpExtension> extensions;
for (const auto& entry : query_interface.GetRtpHeaderExtensions()) {
if (entry.direction != webrtc::RtpTransceiverDirection::kStopped)
extensions.emplace_back(entry.uri, *entry.preferred_id);
}
return extensions;
}
webrtc::RTCError CheckRtpParametersValues( webrtc::RTCError CheckRtpParametersValues(
const webrtc::RtpParameters& rtp_parameters) { const webrtc::RtpParameters& rtp_parameters) {
using webrtc::RTCErrorType; using webrtc::RTCErrorType;

View file

@ -48,7 +48,17 @@ struct RtpCapabilities {
std::vector<webrtc::RtpExtension> header_extensions; std::vector<webrtc::RtpExtension> header_extensions;
}; };
class VoiceEngineInterface { class RtpHeaderExtensionQueryInterface {
public:
virtual ~RtpHeaderExtensionQueryInterface() = default;
// Returns a vector of RtpHeaderExtensionCapability, whose direction is
// kStopped if the extension is stopped (not used) by default.
virtual std::vector<webrtc::RtpHeaderExtensionCapability>
GetRtpHeaderExtensions() const = 0;
};
class VoiceEngineInterface : public RtpHeaderExtensionQueryInterface {
public: public:
VoiceEngineInterface() = default; VoiceEngineInterface() = default;
virtual ~VoiceEngineInterface() = default; virtual ~VoiceEngineInterface() = default;
@ -71,7 +81,6 @@ class VoiceEngineInterface {
virtual const std::vector<AudioCodec>& send_codecs() const = 0; virtual const std::vector<AudioCodec>& send_codecs() const = 0;
virtual const std::vector<AudioCodec>& recv_codecs() const = 0; virtual const std::vector<AudioCodec>& recv_codecs() const = 0;
virtual RtpCapabilities GetCapabilities() const = 0;
// Starts AEC dump using existing file, a maximum file size in bytes can be // Starts AEC dump using existing file, a maximum file size in bytes can be
// specified. Logging is stopped just before the size limit is exceeded. // specified. Logging is stopped just before the size limit is exceeded.
@ -83,7 +92,7 @@ class VoiceEngineInterface {
virtual void StopAecDump() = 0; virtual void StopAecDump() = 0;
}; };
class VideoEngineInterface { class VideoEngineInterface : public RtpHeaderExtensionQueryInterface {
public: public:
VideoEngineInterface() = default; VideoEngineInterface() = default;
virtual ~VideoEngineInterface() = default; virtual ~VideoEngineInterface() = default;
@ -100,7 +109,6 @@ class VideoEngineInterface {
video_bitrate_allocator_factory) = 0; video_bitrate_allocator_factory) = 0;
virtual std::vector<VideoCodec> codecs() const = 0; virtual std::vector<VideoCodec> codecs() const = 0;
virtual RtpCapabilities GetCapabilities() const = 0;
}; };
// MediaEngineInterface is an abstraction of a media engine which can be // MediaEngineInterface is an abstraction of a media engine which can be
@ -167,6 +175,13 @@ class DataEngineInterface {
webrtc::RtpParameters CreateRtpParametersWithOneEncoding(); webrtc::RtpParameters CreateRtpParametersWithOneEncoding();
webrtc::RtpParameters CreateRtpParametersWithEncodings(StreamParams sp); webrtc::RtpParameters CreateRtpParametersWithEncodings(StreamParams sp);
// Returns a vector of RTP extensions as visible from RtpSender/Receiver
// GetCapabilities(). The returned vector only shows what will definitely be
// offered by default, i.e. the list of extensions returned from
// GetRtpHeaderExtensions() that are not kStopped.
std::vector<webrtc::RtpExtension> GetDefaultEnabledRtpHeaderExtensions(
const RtpHeaderExtensionQueryInterface& query_interface);
} // namespace cricket } // namespace cricket
#endif // MEDIA_BASE_MEDIA_ENGINE_H_ #endif // MEDIA_BASE_MEDIA_ENGINE_H_

View file

@ -0,0 +1,56 @@
/*
* Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "media/base/media_engine.h"
#include "test/gmock.h"
using ::testing::ElementsAre;
using ::testing::Field;
using ::testing::Return;
using ::testing::StrEq;
using ::webrtc::RtpExtension;
using ::webrtc::RtpHeaderExtensionCapability;
using ::webrtc::RtpTransceiverDirection;
namespace cricket {
namespace {
class MockRtpHeaderExtensionQueryInterface
: public RtpHeaderExtensionQueryInterface {
public:
MOCK_CONST_METHOD0(GetRtpHeaderExtensions,
std::vector<RtpHeaderExtensionCapability>());
};
} // namespace
TEST(MediaEngineTest, ReturnsNotStoppedHeaderExtensions) {
MockRtpHeaderExtensionQueryInterface mock;
std::vector<RtpHeaderExtensionCapability> extensions(
{RtpHeaderExtensionCapability("uri1", 1,
RtpTransceiverDirection::kInactive),
RtpHeaderExtensionCapability("uri2", 2,
RtpTransceiverDirection::kSendRecv),
RtpHeaderExtensionCapability("uri3", 3,
RtpTransceiverDirection::kStopped),
RtpHeaderExtensionCapability("uri4", 4,
RtpTransceiverDirection::kSendOnly),
RtpHeaderExtensionCapability("uri5", 5,
RtpTransceiverDirection::kRecvOnly)});
EXPECT_CALL(mock, GetRtpHeaderExtensions).WillOnce(Return(extensions));
EXPECT_THAT(GetDefaultEnabledRtpHeaderExtensions(mock),
ElementsAre(Field(&RtpExtension::uri, StrEq("uri1")),
Field(&RtpExtension::uri, StrEq("uri2")),
Field(&RtpExtension::uri, StrEq("uri4")),
Field(&RtpExtension::uri, StrEq("uri5"))));
}
} // namespace cricket

View file

@ -34,7 +34,10 @@ class NullWebRtcVideoEngine : public VideoEngineInterface {
return std::vector<VideoCodec>(); return std::vector<VideoCodec>();
} }
RtpCapabilities GetCapabilities() const override { return RtpCapabilities(); } std::vector<webrtc::RtpHeaderExtensionCapability> GetRtpHeaderExtensions()
const override {
return {};
}
VideoMediaChannel* CreateMediaChannel( VideoMediaChannel* CreateMediaChannel(
webrtc::Call* call, webrtc::Call* call,

View file

@ -503,39 +503,29 @@ std::vector<VideoCodec> WebRtcVideoEngine::codecs() const {
return AssignPayloadTypesAndDefaultCodecs(encoder_factory_.get()); return AssignPayloadTypesAndDefaultCodecs(encoder_factory_.get());
} }
RtpCapabilities WebRtcVideoEngine::GetCapabilities() const { std::vector<webrtc::RtpHeaderExtensionCapability>
RtpCapabilities capabilities; WebRtcVideoEngine::GetRtpHeaderExtensions() const {
std::vector<webrtc::RtpHeaderExtensionCapability> result;
int id = 1; int id = 1;
capabilities.header_extensions.push_back( for (const auto& uri :
webrtc::RtpExtension(webrtc::RtpExtension::kTimestampOffsetUri, id++)); {webrtc::RtpExtension::kTimestampOffsetUri,
capabilities.header_extensions.push_back( webrtc::RtpExtension::kAbsSendTimeUri,
webrtc::RtpExtension(webrtc::RtpExtension::kAbsSendTimeUri, id++)); webrtc::RtpExtension::kVideoRotationUri,
capabilities.header_extensions.push_back( webrtc::RtpExtension::kTransportSequenceNumberUri,
webrtc::RtpExtension(webrtc::RtpExtension::kVideoRotationUri, id++)); webrtc::RtpExtension::kPlayoutDelayUri,
capabilities.header_extensions.push_back(webrtc::RtpExtension( webrtc::RtpExtension::kVideoContentTypeUri,
webrtc::RtpExtension::kTransportSequenceNumberUri, id++)); webrtc::RtpExtension::kVideoTimingUri,
capabilities.header_extensions.push_back( webrtc::RtpExtension::kFrameMarkingUri,
webrtc::RtpExtension(webrtc::RtpExtension::kPlayoutDelayUri, id++)); webrtc::RtpExtension::kColorSpaceUri, webrtc::RtpExtension::kMidUri,
capabilities.header_extensions.push_back( webrtc::RtpExtension::kRidUri, webrtc::RtpExtension::kRepairedRidUri}) {
webrtc::RtpExtension(webrtc::RtpExtension::kVideoContentTypeUri, id++)); result.emplace_back(uri, id++, webrtc::RtpTransceiverDirection::kSendRecv);
capabilities.header_extensions.push_back(
webrtc::RtpExtension(webrtc::RtpExtension::kVideoTimingUri, id++));
capabilities.header_extensions.push_back(
webrtc::RtpExtension(webrtc::RtpExtension::kFrameMarkingUri, id++));
capabilities.header_extensions.push_back(
webrtc::RtpExtension(webrtc::RtpExtension::kColorSpaceUri, id++));
capabilities.header_extensions.push_back(
webrtc::RtpExtension(webrtc::RtpExtension::kMidUri, id++));
capabilities.header_extensions.push_back(
webrtc::RtpExtension(webrtc::RtpExtension::kRidUri, id++));
capabilities.header_extensions.push_back(
webrtc::RtpExtension(webrtc::RtpExtension::kRepairedRidUri, id++));
if (webrtc::field_trial::IsEnabled("WebRTC-GenericDescriptorAdvertised")) {
capabilities.header_extensions.push_back(webrtc::RtpExtension(
webrtc::RtpExtension::kGenericFrameDescriptorUri00, id++));
} }
result.emplace_back(
return capabilities; webrtc::RtpExtension::kGenericFrameDescriptorUri00, id,
webrtc::field_trial::IsEnabled("WebRTC-GenericDescriptorAdvertised")
? webrtc::RtpTransceiverDirection::kSendRecv
: webrtc::RtpTransceiverDirection::kStopped);
return result;
} }
WebRtcVideoChannel::WebRtcVideoChannel( WebRtcVideoChannel::WebRtcVideoChannel(

View file

@ -98,7 +98,8 @@ class WebRtcVideoEngine : public VideoEngineInterface {
override; override;
std::vector<VideoCodec> codecs() const override; std::vector<VideoCodec> codecs() const override;
RtpCapabilities GetCapabilities() const override; std::vector<webrtc::RtpHeaderExtensionCapability> GetRtpHeaderExtensions()
const override;
private: private:
const std::unique_ptr<webrtc::VideoDecoderFactory> decoder_factory_; const std::unique_ptr<webrtc::VideoDecoderFactory> decoder_factory_;

View file

@ -733,12 +733,13 @@ VideoMediaChannel* WebRtcVideoEngineTest::SetRecvParamsWithSupportedCodecs(
void WebRtcVideoEngineTest::ExpectRtpCapabilitySupport(const char* uri, void WebRtcVideoEngineTest::ExpectRtpCapabilitySupport(const char* uri,
bool supported) const { bool supported) const {
const RtpCapabilities capabilities = engine_.GetCapabilities(); const std::vector<webrtc::RtpExtension> header_extensions =
GetDefaultEnabledRtpHeaderExtensions(engine_);
if (supported) { if (supported) {
EXPECT_THAT(capabilities.header_extensions, EXPECT_THAT(header_extensions,
::testing::Contains(::testing::Field(&RtpExtension::uri, uri))); ::testing::Contains(::testing::Field(&RtpExtension::uri, uri)));
} else { } else {
EXPECT_THAT(capabilities.header_extensions, EXPECT_THAT(header_extensions,
::testing::Each(::testing::Field(&RtpExtension::uri, ::testing::Each(::testing::Field(&RtpExtension::uri,
::testing::StrNe(uri)))); ::testing::StrNe(uri))));
} }

View file

@ -539,23 +539,20 @@ const std::vector<AudioCodec>& WebRtcVoiceEngine::recv_codecs() const {
return recv_codecs_; return recv_codecs_;
} }
RtpCapabilities WebRtcVoiceEngine::GetCapabilities() const { std::vector<webrtc::RtpHeaderExtensionCapability>
WebRtcVoiceEngine::GetRtpHeaderExtensions() const {
RTC_DCHECK(signal_thread_checker_.IsCurrent()); RTC_DCHECK(signal_thread_checker_.IsCurrent());
RtpCapabilities capabilities; std::vector<webrtc::RtpHeaderExtensionCapability> result;
int id = 1; int id = 1;
capabilities.header_extensions.push_back( for (const auto& uri :
webrtc::RtpExtension(webrtc::RtpExtension::kAudioLevelUri, id++)); {webrtc::RtpExtension::kAudioLevelUri,
capabilities.header_extensions.push_back( webrtc::RtpExtension::kAbsSendTimeUri,
webrtc::RtpExtension(webrtc::RtpExtension::kAbsSendTimeUri, id++)); webrtc::RtpExtension::kTransportSequenceNumberUri,
capabilities.header_extensions.push_back(webrtc::RtpExtension( webrtc::RtpExtension::kMidUri, webrtc::RtpExtension::kRidUri,
webrtc::RtpExtension::kTransportSequenceNumberUri, id++)); webrtc::RtpExtension::kRepairedRidUri}) {
capabilities.header_extensions.push_back( result.emplace_back(uri, id++, webrtc::RtpTransceiverDirection::kSendRecv);
webrtc::RtpExtension(webrtc::RtpExtension::kMidUri, id++)); }
capabilities.header_extensions.push_back( return result;
webrtc::RtpExtension(webrtc::RtpExtension::kRidUri, id++));
capabilities.header_extensions.push_back(
webrtc::RtpExtension(webrtc::RtpExtension::kRepairedRidUri, id++));
return capabilities;
} }
void WebRtcVoiceEngine::RegisterChannel(WebRtcVoiceMediaChannel* channel) { void WebRtcVoiceEngine::RegisterChannel(WebRtcVoiceMediaChannel* channel) {

View file

@ -64,7 +64,8 @@ class WebRtcVoiceEngine final : public VoiceEngineInterface {
const std::vector<AudioCodec>& send_codecs() const override; const std::vector<AudioCodec>& send_codecs() const override;
const std::vector<AudioCodec>& recv_codecs() const override; const std::vector<AudioCodec>& recv_codecs() const override;
RtpCapabilities GetCapabilities() const override; std::vector<webrtc::RtpHeaderExtensionCapability> GetRtpHeaderExtensions()
const override;
// For tracking WebRtc channels. Needed because we have to pause them // For tracking WebRtc channels. Needed because we have to pause them
// all when switching devices. // all when switching devices.

View file

@ -2016,8 +2016,9 @@ class WebRtcVoiceEngineWithSendSideBweTest : public WebRtcVoiceEngineTestFake {
TEST_F(WebRtcVoiceEngineWithSendSideBweTest, TEST_F(WebRtcVoiceEngineWithSendSideBweTest,
SupportsTransportSequenceNumberHeaderExtension) { SupportsTransportSequenceNumberHeaderExtension) {
const cricket::RtpCapabilities capabilities = engine_->GetCapabilities(); const std::vector<webrtc::RtpExtension> header_extensions =
EXPECT_THAT(capabilities.header_extensions, GetDefaultEnabledRtpHeaderExtensions(*engine_);
EXPECT_THAT(header_extensions,
Contains(::testing::Field( Contains(::testing::Field(
"uri", &RtpExtension::uri, "uri", &RtpExtension::uri,
webrtc::RtpExtension::kTransportSequenceNumberUri))); webrtc::RtpExtension::kTransportSequenceNumberUri)));
@ -3204,17 +3205,18 @@ TEST_F(WebRtcVoiceEngineTestFake, ConfiguresAudioReceiveStreamRtpExtensions) {
} }
// Set up receive extensions. // Set up receive extensions.
cricket::RtpCapabilities capabilities = engine_->GetCapabilities(); const std::vector<webrtc::RtpExtension> header_extensions =
GetDefaultEnabledRtpHeaderExtensions(*engine_);
cricket::AudioRecvParameters recv_parameters; cricket::AudioRecvParameters recv_parameters;
recv_parameters.extensions = capabilities.header_extensions; recv_parameters.extensions = header_extensions;
channel_->SetRecvParameters(recv_parameters); channel_->SetRecvParameters(recv_parameters);
EXPECT_EQ(2u, call_.GetAudioReceiveStreams().size()); EXPECT_EQ(2u, call_.GetAudioReceiveStreams().size());
for (uint32_t ssrc : ssrcs) { for (uint32_t ssrc : ssrcs) {
const auto* s = call_.GetAudioReceiveStream(ssrc); const auto* s = call_.GetAudioReceiveStream(ssrc);
EXPECT_NE(nullptr, s); EXPECT_NE(nullptr, s);
const auto& s_exts = s->GetConfig().rtp.extensions; const auto& s_exts = s->GetConfig().rtp.extensions;
EXPECT_EQ(capabilities.header_extensions.size(), s_exts.size()); EXPECT_EQ(header_extensions.size(), s_exts.size());
for (const auto& e_ext : capabilities.header_extensions) { for (const auto& e_ext : header_extensions) {
for (const auto& s_ext : s_exts) { for (const auto& s_ext : s_exts) {
if (e_ext.id == s_ext.id) { if (e_ext.id == s_ext.id) {
EXPECT_EQ(e_ext.uri, s_ext.uri); EXPECT_EQ(e_ext.uri, s_ext.uri);

View file

@ -519,6 +519,7 @@ if (rtc_include_tests) {
"peer_connection_data_channel_unittest.cc", "peer_connection_data_channel_unittest.cc",
"peer_connection_end_to_end_unittest.cc", "peer_connection_end_to_end_unittest.cc",
"peer_connection_factory_unittest.cc", "peer_connection_factory_unittest.cc",
"peer_connection_header_extension_unittest.cc",
"peer_connection_histogram_unittest.cc", "peer_connection_histogram_unittest.cc",
"peer_connection_ice_unittest.cc", "peer_connection_ice_unittest.cc",
"peer_connection_integrationtest.cc", "peer_connection_integrationtest.cc",

View file

@ -79,14 +79,6 @@ void ChannelManager::GetSupportedAudioReceiveCodecs(
*codecs = media_engine_->voice().recv_codecs(); *codecs = media_engine_->voice().recv_codecs();
} }
void ChannelManager::GetSupportedAudioRtpHeaderExtensions(
RtpHeaderExtensions* ext) const {
if (!media_engine_) {
return;
}
*ext = media_engine_->voice().GetCapabilities().header_extensions;
}
void ChannelManager::GetSupportedVideoCodecs( void ChannelManager::GetSupportedVideoCodecs(
std::vector<VideoCodec>* codecs) const { std::vector<VideoCodec>* codecs) const {
if (!media_engine_) { if (!media_engine_) {
@ -104,14 +96,6 @@ void ChannelManager::GetSupportedVideoCodecs(
} }
} }
void ChannelManager::GetSupportedVideoRtpHeaderExtensions(
RtpHeaderExtensions* ext) const {
if (!media_engine_) {
return;
}
*ext = media_engine_->video().GetCapabilities().header_extensions;
}
void ChannelManager::GetSupportedDataCodecs( void ChannelManager::GetSupportedDataCodecs(
std::vector<DataCodec>* codecs) const { std::vector<DataCodec>* codecs) const {
*codecs = data_engine_->data_codecs(); *codecs = data_engine_->data_codecs();
@ -140,6 +124,34 @@ bool ChannelManager::Init() {
return initialized_; return initialized_;
} }
RtpHeaderExtensions ChannelManager::GetDefaultEnabledAudioRtpHeaderExtensions()
const {
if (!media_engine_)
return {};
return GetDefaultEnabledRtpHeaderExtensions(media_engine_->voice());
}
std::vector<webrtc::RtpHeaderExtensionCapability>
ChannelManager::GetSupportedAudioRtpHeaderExtensions() const {
if (!media_engine_)
return {};
return media_engine_->voice().GetRtpHeaderExtensions();
}
RtpHeaderExtensions ChannelManager::GetDefaultEnabledVideoRtpHeaderExtensions()
const {
if (!media_engine_)
return {};
return GetDefaultEnabledRtpHeaderExtensions(media_engine_->video());
}
std::vector<webrtc::RtpHeaderExtensionCapability>
ChannelManager::GetSupportedVideoRtpHeaderExtensions() const {
if (!media_engine_)
return {};
return media_engine_->video().GetRtpHeaderExtensions();
}
void ChannelManager::Terminate() { void ChannelManager::Terminate() {
RTC_DCHECK(initialized_); RTC_DCHECK(initialized_);
if (!initialized_) { if (!initialized_) {

View file

@ -75,10 +75,14 @@ class ChannelManager final {
// Can be called before starting the media engine. // Can be called before starting the media engine.
void GetSupportedAudioSendCodecs(std::vector<AudioCodec>* codecs) const; void GetSupportedAudioSendCodecs(std::vector<AudioCodec>* codecs) const;
void GetSupportedAudioReceiveCodecs(std::vector<AudioCodec>* codecs) const; void GetSupportedAudioReceiveCodecs(std::vector<AudioCodec>* codecs) const;
void GetSupportedAudioRtpHeaderExtensions(RtpHeaderExtensions* ext) const;
void GetSupportedVideoCodecs(std::vector<VideoCodec>* codecs) const; void GetSupportedVideoCodecs(std::vector<VideoCodec>* codecs) const;
void GetSupportedVideoRtpHeaderExtensions(RtpHeaderExtensions* ext) const;
void GetSupportedDataCodecs(std::vector<DataCodec>* codecs) const; void GetSupportedDataCodecs(std::vector<DataCodec>* codecs) const;
RtpHeaderExtensions GetDefaultEnabledAudioRtpHeaderExtensions() const;
std::vector<webrtc::RtpHeaderExtensionCapability>
GetSupportedAudioRtpHeaderExtensions() const;
RtpHeaderExtensions GetDefaultEnabledVideoRtpHeaderExtensions() const;
std::vector<webrtc::RtpHeaderExtensionCapability>
GetSupportedVideoRtpHeaderExtensions() const;
// Indicates whether the media engine is started. // Indicates whether the media engine is started.
bool initialized() const { return initialized_; } bool initialized() const { return initialized_; }

View file

@ -1365,9 +1365,11 @@ MediaSessionDescriptionFactory::MediaSessionDescriptionFactory(
: MediaSessionDescriptionFactory(transport_desc_factory, ssrc_generator) { : MediaSessionDescriptionFactory(transport_desc_factory, ssrc_generator) {
channel_manager->GetSupportedAudioSendCodecs(&audio_send_codecs_); channel_manager->GetSupportedAudioSendCodecs(&audio_send_codecs_);
channel_manager->GetSupportedAudioReceiveCodecs(&audio_recv_codecs_); channel_manager->GetSupportedAudioReceiveCodecs(&audio_recv_codecs_);
channel_manager->GetSupportedAudioRtpHeaderExtensions(&audio_rtp_extensions_); audio_rtp_extensions_ =
channel_manager->GetDefaultEnabledAudioRtpHeaderExtensions();
channel_manager->GetSupportedVideoCodecs(&video_codecs_); channel_manager->GetSupportedVideoCodecs(&video_codecs_);
channel_manager->GetSupportedVideoRtpHeaderExtensions(&video_rtp_extensions_); video_rtp_extensions_ =
channel_manager->GetDefaultEnabledVideoRtpHeaderExtensions();
channel_manager->GetSupportedDataCodecs(&rtp_data_codecs_); channel_manager->GetSupportedDataCodecs(&rtp_data_codecs_);
ComputeAudioCodecsIntersectionAndUnion(); ComputeAudioCodecsIntersectionAndUnion();
} }

View file

@ -1907,7 +1907,11 @@ PeerConnection::CreateAndAddTransceiver(
RTC_DCHECK(!FindSenderById(sender->id())); RTC_DCHECK(!FindSenderById(sender->id()));
auto transceiver = RtpTransceiverProxyWithInternal<RtpTransceiver>::Create( auto transceiver = RtpTransceiverProxyWithInternal<RtpTransceiver>::Create(
signaling_thread(), signaling_thread(),
new RtpTransceiver(sender, receiver, channel_manager())); new RtpTransceiver(
sender, receiver, channel_manager(),
sender->media_type() == cricket::MEDIA_TYPE_AUDIO
? channel_manager()->GetSupportedAudioRtpHeaderExtensions()
: channel_manager()->GetSupportedVideoRtpHeaderExtensions()));
transceivers_.push_back(transceiver); transceivers_.push_back(transceiver);
transceiver->internal()->SignalNegotiationNeeded.connect( transceiver->internal()->SignalNegotiationNeeded.connect(
this, &PeerConnection::OnNegotiationNeeded); this, &PeerConnection::OnNegotiationNeeded);
@ -4983,6 +4987,7 @@ void PeerConnection::GetOptionsForPlanBOffer(
cricket::MEDIA_TYPE_AUDIO, cricket::CN_AUDIO, cricket::MEDIA_TYPE_AUDIO, cricket::CN_AUDIO,
RtpTransceiverDirectionFromSendRecv(send_audio, recv_audio), RtpTransceiverDirectionFromSendRecv(send_audio, recv_audio),
false)); false));
audio_index = session_options->media_description_options.size() - 1; audio_index = session_options->media_description_options.size() - 1;
} }
if (!video_index && offer_new_video_description) { if (!video_index && offer_new_video_description) {
@ -4991,6 +4996,7 @@ void PeerConnection::GetOptionsForPlanBOffer(
cricket::MEDIA_TYPE_VIDEO, cricket::CN_VIDEO, cricket::MEDIA_TYPE_VIDEO, cricket::CN_VIDEO,
RtpTransceiverDirectionFromSendRecv(send_video, recv_video), RtpTransceiverDirectionFromSendRecv(send_video, recv_video),
false)); false));
video_index = session_options->media_description_options.size() - 1; video_index = session_options->media_description_options.size() - 1;
} }
if (!data_index && offer_new_data_description) { if (!data_index && offer_new_data_description) {

View file

@ -160,19 +160,17 @@ RtpCapabilities PeerConnectionFactory::GetRtpSenderCapabilities(
switch (kind) { switch (kind) {
case cricket::MEDIA_TYPE_AUDIO: { case cricket::MEDIA_TYPE_AUDIO: {
cricket::AudioCodecs cricket_codecs; cricket::AudioCodecs cricket_codecs;
cricket::RtpHeaderExtensions cricket_extensions;
channel_manager_->GetSupportedAudioSendCodecs(&cricket_codecs); channel_manager_->GetSupportedAudioSendCodecs(&cricket_codecs);
channel_manager_->GetSupportedAudioRtpHeaderExtensions( return ToRtpCapabilities(
&cricket_extensions); cricket_codecs,
return ToRtpCapabilities(cricket_codecs, cricket_extensions); channel_manager_->GetDefaultEnabledAudioRtpHeaderExtensions());
} }
case cricket::MEDIA_TYPE_VIDEO: { case cricket::MEDIA_TYPE_VIDEO: {
cricket::VideoCodecs cricket_codecs; cricket::VideoCodecs cricket_codecs;
cricket::RtpHeaderExtensions cricket_extensions;
channel_manager_->GetSupportedVideoCodecs(&cricket_codecs); channel_manager_->GetSupportedVideoCodecs(&cricket_codecs);
channel_manager_->GetSupportedVideoRtpHeaderExtensions( return ToRtpCapabilities(
&cricket_extensions); cricket_codecs,
return ToRtpCapabilities(cricket_codecs, cricket_extensions); channel_manager_->GetDefaultEnabledVideoRtpHeaderExtensions());
} }
case cricket::MEDIA_TYPE_DATA: case cricket::MEDIA_TYPE_DATA:
return RtpCapabilities(); return RtpCapabilities();
@ -187,19 +185,17 @@ RtpCapabilities PeerConnectionFactory::GetRtpReceiverCapabilities(
switch (kind) { switch (kind) {
case cricket::MEDIA_TYPE_AUDIO: { case cricket::MEDIA_TYPE_AUDIO: {
cricket::AudioCodecs cricket_codecs; cricket::AudioCodecs cricket_codecs;
cricket::RtpHeaderExtensions cricket_extensions;
channel_manager_->GetSupportedAudioReceiveCodecs(&cricket_codecs); channel_manager_->GetSupportedAudioReceiveCodecs(&cricket_codecs);
channel_manager_->GetSupportedAudioRtpHeaderExtensions( return ToRtpCapabilities(
&cricket_extensions); cricket_codecs,
return ToRtpCapabilities(cricket_codecs, cricket_extensions); channel_manager_->GetDefaultEnabledAudioRtpHeaderExtensions());
} }
case cricket::MEDIA_TYPE_VIDEO: { case cricket::MEDIA_TYPE_VIDEO: {
cricket::VideoCodecs cricket_codecs; cricket::VideoCodecs cricket_codecs;
cricket::RtpHeaderExtensions cricket_extensions;
channel_manager_->GetSupportedVideoCodecs(&cricket_codecs); channel_manager_->GetSupportedVideoCodecs(&cricket_codecs);
channel_manager_->GetSupportedVideoRtpHeaderExtensions( return ToRtpCapabilities(
&cricket_extensions); cricket_codecs,
return ToRtpCapabilities(cricket_codecs, cricket_extensions); channel_manager_->GetDefaultEnabledVideoRtpHeaderExtensions());
} }
case cricket::MEDIA_TYPE_DATA: case cricket::MEDIA_TYPE_DATA:
return RtpCapabilities(); return RtpCapabilities();

View file

@ -0,0 +1,144 @@
/*
* Copyright 2020 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <memory>
#include <tuple>
#include "api/rtc_event_log/rtc_event_log_factory.h"
#include "api/task_queue/default_task_queue_factory.h"
#include "media/base/fake_media_engine.h"
#include "p2p/base/fake_port_allocator.h"
#include "pc/media_session.h"
#include "pc/peer_connection_wrapper.h"
#include "rtc_base/gunit.h"
#include "rtc_base/strings/string_builder.h"
#include "test/gmock.h"
namespace webrtc {
using ::testing::Combine;
using ::testing::ElementsAre;
using ::testing::Field;
using ::testing::Return;
using ::testing::Values;
class PeerConnectionHeaderExtensionTest
: public ::testing::TestWithParam<
std::tuple<cricket::MediaType, SdpSemantics>> {
protected:
std::unique_ptr<PeerConnectionWrapper> CreatePeerConnection(
cricket::MediaType media_type,
absl::optional<SdpSemantics> semantics,
std::vector<RtpHeaderExtensionCapability> extensions) {
auto voice = std::make_unique<cricket::FakeVoiceEngine>();
auto video = std::make_unique<cricket::FakeVideoEngine>();
if (media_type == cricket::MediaType::MEDIA_TYPE_AUDIO)
voice->SetRtpHeaderExtensions(extensions);
else
video->SetRtpHeaderExtensions(extensions);
auto media_engine = std::make_unique<cricket::CompositeMediaEngine>(
std::move(voice), std::move(video));
PeerConnectionFactoryDependencies factory_dependencies;
factory_dependencies.network_thread = rtc::Thread::Current();
factory_dependencies.worker_thread = rtc::Thread::Current();
factory_dependencies.signaling_thread = rtc::Thread::Current();
factory_dependencies.task_queue_factory = CreateDefaultTaskQueueFactory();
factory_dependencies.media_engine = std::move(media_engine);
factory_dependencies.call_factory = CreateCallFactory();
factory_dependencies.event_log_factory =
std::make_unique<RtcEventLogFactory>(
factory_dependencies.task_queue_factory.get());
auto pc_factory =
CreateModularPeerConnectionFactory(std::move(factory_dependencies));
auto fake_port_allocator = std::make_unique<cricket::FakePortAllocator>(
rtc::Thread::Current(), nullptr);
auto observer = std::make_unique<MockPeerConnectionObserver>();
PeerConnectionInterface::RTCConfiguration config;
if (semantics)
config.sdp_semantics = *semantics;
auto pc = pc_factory->CreatePeerConnection(
config, std::move(fake_port_allocator), nullptr, observer.get());
observer->SetPeerConnectionInterface(pc.get());
return std::make_unique<PeerConnectionWrapper>(pc_factory, pc,
std::move(observer));
}
};
TEST_P(PeerConnectionHeaderExtensionTest, TransceiverOffersHeaderExtensions) {
cricket::MediaType media_type;
SdpSemantics semantics;
std::tie(media_type, semantics) = GetParam();
if (semantics != SdpSemantics::kUnifiedPlan)
return;
std::vector<RtpHeaderExtensionCapability> extensions(
{RtpHeaderExtensionCapability("uri1", 1,
RtpTransceiverDirection::kStopped),
RtpHeaderExtensionCapability("uri2", 2,
RtpTransceiverDirection::kSendOnly),
RtpHeaderExtensionCapability("uri3", 3,
RtpTransceiverDirection::kRecvOnly),
RtpHeaderExtensionCapability("uri4", 4,
RtpTransceiverDirection::kSendRecv)});
std::unique_ptr<PeerConnectionWrapper> wrapper =
CreatePeerConnection(media_type, semantics, extensions);
auto transceiver = wrapper->AddTransceiver(media_type);
EXPECT_EQ(transceiver->HeaderExtensionsToOffer(), extensions);
}
TEST_P(PeerConnectionHeaderExtensionTest,
SenderReceiverCapabilitiesReturnNotStoppedExtensions) {
cricket::MediaType media_type;
SdpSemantics semantics;
std::tie(media_type, semantics) = GetParam();
std::unique_ptr<PeerConnectionWrapper> wrapper = CreatePeerConnection(
media_type, semantics,
std::vector<RtpHeaderExtensionCapability>(
{RtpHeaderExtensionCapability("uri1", 1,
RtpTransceiverDirection::kSendRecv),
RtpHeaderExtensionCapability("uri2", 2,
RtpTransceiverDirection::kStopped),
RtpHeaderExtensionCapability("uri3", 3,
RtpTransceiverDirection::kRecvOnly)}));
EXPECT_THAT(wrapper->pc_factory()
->GetRtpSenderCapabilities(media_type)
.header_extensions,
ElementsAre(Field(&RtpHeaderExtensionCapability::uri, "uri1"),
Field(&RtpHeaderExtensionCapability::uri, "uri3")));
EXPECT_EQ(wrapper->pc_factory()
->GetRtpReceiverCapabilities(media_type)
.header_extensions,
wrapper->pc_factory()
->GetRtpSenderCapabilities(media_type)
.header_extensions);
}
INSTANTIATE_TEST_SUITE_P(
,
PeerConnectionHeaderExtensionTest,
Combine(Values(SdpSemantics::kPlanB, SdpSemantics::kUnifiedPlan),
Values(cricket::MediaType::MEDIA_TYPE_AUDIO,
cricket::MediaType::MEDIA_TYPE_VIDEO)),
[](const testing::TestParamInfo<
PeerConnectionHeaderExtensionTest::ParamType>& info) {
cricket::MediaType media_type;
SdpSemantics semantics;
std::tie(media_type, semantics) = info.param;
return (rtc::StringBuilder("With")
<< (semantics == SdpSemantics::kPlanB ? "PlanB" : "UnifiedPlan")
<< "And"
<< (media_type == cricket::MediaType::MEDIA_TYPE_AUDIO ? "Voice"
: "Video")
<< "Engine")
.str();
});
} // namespace webrtc

View file

@ -11,8 +11,10 @@
#include "pc/rtp_transceiver.h" #include "pc/rtp_transceiver.h"
#include <string> #include <string>
#include <utility>
#include "absl/algorithm/container.h" #include "absl/algorithm/container.h"
#include "api/rtp_parameters.h"
#include "pc/channel_manager.h" #include "pc/channel_manager.h"
#include "pc/rtp_media_utils.h" #include "pc/rtp_media_utils.h"
#include "pc/rtp_parameters_conversion.h" #include "pc/rtp_parameters_conversion.h"
@ -31,10 +33,12 @@ RtpTransceiver::RtpTransceiver(
rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> sender, rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> sender,
rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>> rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
receiver, receiver,
cricket::ChannelManager* channel_manager) cricket::ChannelManager* channel_manager,
std::vector<RtpHeaderExtensionCapability> header_extensions_offered)
: unified_plan_(true), : unified_plan_(true),
media_type_(sender->media_type()), media_type_(sender->media_type()),
channel_manager_(channel_manager) { channel_manager_(channel_manager),
HeaderExtensionsToOffer_(std::move(header_extensions_offered)) {
RTC_DCHECK(media_type_ == cricket::MEDIA_TYPE_AUDIO || RTC_DCHECK(media_type_ == cricket::MEDIA_TYPE_AUDIO ||
media_type_ == cricket::MEDIA_TYPE_VIDEO); media_type_ == cricket::MEDIA_TYPE_VIDEO);
RTC_DCHECK_EQ(sender->media_type(), receiver->media_type()); RTC_DCHECK_EQ(sender->media_type(), receiver->media_type());
@ -358,4 +362,9 @@ RTCError RtpTransceiver::SetCodecPreferences(
return RTCError::OK(); return RTCError::OK();
} }
std::vector<RtpHeaderExtensionCapability>
RtpTransceiver::HeaderExtensionsToOffer() const {
return HeaderExtensionsToOffer_;
}
} // namespace webrtc } // namespace webrtc

View file

@ -64,11 +64,14 @@ class RtpTransceiver final
// Construct a Unified Plan-style RtpTransceiver with the given sender and // Construct a Unified Plan-style RtpTransceiver with the given sender and
// receiver. The media type will be derived from the media types of the sender // receiver. The media type will be derived from the media types of the sender
// and receiver. The sender and receiver should have the same media type. // and receiver. The sender and receiver should have the same media type.
// |HeaderExtensionsToOffer| is used for initializing the return value of
// HeaderExtensionsToOffer().
RtpTransceiver( RtpTransceiver(
rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> sender, rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> sender,
rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>> rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
receiver, receiver,
cricket::ChannelManager* channel_manager); cricket::ChannelManager* channel_manager,
std::vector<RtpHeaderExtensionCapability> HeaderExtensionsToOffer);
~RtpTransceiver() override; ~RtpTransceiver() override;
// Returns the Voice/VideoChannel set for this transceiver. May be null if // Returns the Voice/VideoChannel set for this transceiver. May be null if
@ -190,6 +193,8 @@ class RtpTransceiver final
std::vector<RtpCodecCapability> codec_preferences() const override { std::vector<RtpCodecCapability> codec_preferences() const override {
return codec_preferences_; return codec_preferences_;
} }
std::vector<RtpHeaderExtensionCapability> HeaderExtensionsToOffer()
const override;
private: private:
void OnFirstPacketReceived(cricket::ChannelInterface* channel); void OnFirstPacketReceived(cricket::ChannelInterface* channel);
@ -215,6 +220,7 @@ class RtpTransceiver final
cricket::ChannelInterface* channel_ = nullptr; cricket::ChannelInterface* channel_ = nullptr;
cricket::ChannelManager* channel_manager_ = nullptr; cricket::ChannelManager* channel_manager_ = nullptr;
std::vector<RtpCodecCapability> codec_preferences_; std::vector<RtpCodecCapability> codec_preferences_;
std::vector<RtpHeaderExtensionCapability> HeaderExtensionsToOffer_;
}; };
BEGIN_SIGNALING_PROXY_MAP(RtpTransceiver) BEGIN_SIGNALING_PROXY_MAP(RtpTransceiver)
@ -233,6 +239,8 @@ PROXY_METHOD1(webrtc::RTCError,
SetCodecPreferences, SetCodecPreferences,
rtc::ArrayView<RtpCodecCapability>) rtc::ArrayView<RtpCodecCapability>)
PROXY_CONSTMETHOD0(std::vector<RtpCodecCapability>, codec_preferences) PROXY_CONSTMETHOD0(std::vector<RtpCodecCapability>, codec_preferences)
PROXY_CONSTMETHOD0(std::vector<RtpHeaderExtensionCapability>,
HeaderExtensionsToOffer)
END_PROXY_MAP() END_PROXY_MAP()
} // namespace webrtc } // namespace webrtc

View file

@ -12,10 +12,19 @@
#include "pc/rtp_transceiver.h" #include "pc/rtp_transceiver.h"
#include <memory>
#include "media/base/fake_media_engine.h"
#include "pc/test/mock_channel_interface.h" #include "pc/test/mock_channel_interface.h"
#include "pc/test/mock_rtp_receiver_internal.h"
#include "pc/test/mock_rtp_sender_internal.h"
#include "test/gmock.h" #include "test/gmock.h"
#include "test/gtest.h" #include "test/gtest.h"
using ::testing::ElementsAre;
using ::testing::Eq;
using ::testing::Field;
using ::testing::Not;
using ::testing::Return; using ::testing::Return;
using ::testing::ReturnRef; using ::testing::ReturnRef;
@ -69,4 +78,27 @@ TEST(RtpTransceiverTest, CanUnsetChannelOnStoppedTransceiver) {
EXPECT_EQ(nullptr, transceiver.channel()); EXPECT_EQ(nullptr, transceiver.channel());
} }
TEST(RtpTransceiverTest,
InitsWithChannelManagerRtpHeaderExtensionCapabilities) {
cricket::ChannelManager channel_manager(
std::make_unique<cricket::FakeMediaEngine>(),
std::make_unique<cricket::FakeDataEngine>(), rtc::Thread::Current(),
rtc::Thread::Current());
std::vector<RtpHeaderExtensionCapability> extensions({
RtpHeaderExtensionCapability("uri1", 1,
RtpTransceiverDirection::kSendRecv),
RtpHeaderExtensionCapability("uri2", 2,
RtpTransceiverDirection::kRecvOnly),
});
RtpTransceiver transceiver(
RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
rtc::Thread::Current(),
new rtc::RefCountedObject<MockRtpSenderInternal>()),
RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
rtc::Thread::Current(),
new rtc::RefCountedObject<MockRtpReceiverInternal>()),
&channel_manager, extensions);
EXPECT_EQ(transceiver.HeaderExtensionsToOffer(), extensions);
}
} // namespace webrtc } // namespace webrtc