Rename header extension API methods

following spec updates from
  https://github.com/w3c/webrtc-extensions/pull/142

BUG=chromium:1051821

Change-Id: I1fd991a5024d38ac59ebe510ea1a48fd6f42d23b
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/296321
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Commit-Queue: Philipp Hancke <phancke@microsoft.com>
Cr-Commit-Position: refs/heads/main@{#39491}
This commit is contained in:
Philipp Hancke 2023-03-06 18:08:31 +01:00 committed by WebRTC LUCI CQ
parent 1c1382be0f
commit 9f6ae375e3
8 changed files with 104 additions and 73 deletions

View file

@ -229,8 +229,8 @@ struct RTC_EXPORT RtpHeaderExtensionCapability {
bool preferred_encrypt = false;
// The direction of the extension. The kStopped value is only used with
// RtpTransceiverInterface::HeaderExtensionsToOffer() and
// SetOfferedRtpHeaderExtensions().
// RtpTransceiverInterface::SetHeaderExtensionsToNegotiate() and
// SetHeaderExtensionsToNegotiate().
RtpTransceiverDirection direction = RtpTransceiverDirection::kSendRecv;
// Constructors for convenience.

View file

@ -149,25 +149,49 @@ class RTC_EXPORT RtpTransceiverInterface : public rtc::RefCountInterface {
rtc::ArrayView<RtpCodecCapability> codecs) = 0;
virtual std::vector<RtpCodecCapability> codec_preferences() const = 0;
// Readonly attribute which contains the set of header extensions that was set
// with SetOfferedRtpHeaderExtensions, or a default set if it has not been
// Returns the set of header extensions that was set
// with SetHeaderExtensionsToNegotiate, or a default set if it has not been
// called.
// https://w3c.github.io/webrtc-extensions/#rtcrtptransceiver-interface
// TODO(crbug.com/1051821): remove old name after Chromium roll, make pure
// virtual again.
virtual std::vector<RtpHeaderExtensionCapability>
GetHeaderExtensionsToNegotiate() const {
return {};
}
virtual std::vector<RtpHeaderExtensionCapability> HeaderExtensionsToOffer()
const = 0;
const {
return GetHeaderExtensionsToNegotiate();
}
// Readonly attribute which is either empty if negotation has not yet
// Returns either the empty set if negotation has not yet
// happened, or a vector of the negotiated header extensions.
// https://w3c.github.io/webrtc-extensions/#rtcrtptransceiver-interface
// TODO(crbug.com/1051821): remove old name after Chromium roll, make pure
// virtual again.
virtual std::vector<RtpHeaderExtensionCapability>
GetNegotiatedHeaderExtensions() const {
return {};
}
virtual std::vector<RtpHeaderExtensionCapability> HeaderExtensionsNegotiated()
const = 0;
const {
return GetNegotiatedHeaderExtensions();
}
// The SetOfferedRtpHeaderExtensions method modifies the next SDP negotiation
// The SetHeaderExtensionsToNegotiate method modifies the next SDP negotiation
// so that it negotiates use of header extensions which are not kStopped.
// https://w3c.github.io/webrtc-extensions/#rtcrtptransceiver-interface
// TODO(crbug.com/1051821): remove old name after Chromium roll, make pure
// virtual again.
virtual webrtc::RTCError SetHeaderExtensionsToNegotiate(
rtc::ArrayView<const RtpHeaderExtensionCapability> header_extensions) {
return RTCError::OK();
}
virtual webrtc::RTCError SetOfferedRtpHeaderExtensions(
rtc::ArrayView<const RtpHeaderExtensionCapability>
header_extensions_to_offer) = 0;
header_extensions_to_offer) {
return SetHeaderExtensionsToNegotiate(header_extensions_to_offer);
}
protected:
~RtpTransceiverInterface() override = default;

View file

@ -68,17 +68,17 @@ class MockRtpTransceiver : public RtpTransceiverInterface {
(),
(const, override));
MOCK_METHOD(std::vector<RtpHeaderExtensionCapability>,
HeaderExtensionsToOffer,
GetHeaderExtensionsToNegotiate,
(),
(const, override));
MOCK_METHOD(std::vector<RtpHeaderExtensionCapability>,
HeaderExtensionsNegotiated,
GetNegotiatedHeaderExtensions,
(),
(const, override));
MOCK_METHOD(webrtc::RTCError,
SetOfferedRtpHeaderExtensions,
(rtc::ArrayView<const RtpHeaderExtensionCapability>
header_extensions_to_offer),
MOCK_METHOD(
webrtc::RTCError,
SetHeaderExtensionsToNegotiate,
(rtc::ArrayView<const RtpHeaderExtensionCapability> header_extensions),
(override));
};

View file

@ -132,7 +132,7 @@ TEST_P(PeerConnectionHeaderExtensionTest, TransceiverOffersHeaderExtensions) {
std::unique_ptr<PeerConnectionWrapper> wrapper =
CreatePeerConnection(media_type, semantics);
auto transceiver = wrapper->AddTransceiver(media_type);
EXPECT_EQ(transceiver->HeaderExtensionsToOffer(), extensions_);
EXPECT_EQ(transceiver->GetHeaderExtensionsToNegotiate(), extensions_);
}
TEST_P(PeerConnectionHeaderExtensionTest,
@ -184,11 +184,11 @@ TEST_P(PeerConnectionHeaderExtensionTest, OffersUnstoppedModifiedExtensions) {
std::unique_ptr<PeerConnectionWrapper> wrapper =
CreatePeerConnection(media_type, semantics);
auto transceiver = wrapper->AddTransceiver(media_type);
auto modified_extensions = transceiver->HeaderExtensionsToOffer();
auto modified_extensions = transceiver->GetHeaderExtensionsToNegotiate();
modified_extensions[0].direction = RtpTransceiverDirection::kSendRecv;
modified_extensions[3].direction = RtpTransceiverDirection::kStopped;
EXPECT_TRUE(
transceiver->SetOfferedRtpHeaderExtensions(modified_extensions).ok());
transceiver->SetHeaderExtensionsToNegotiate(modified_extensions).ok());
auto session_description = wrapper->CreateOffer();
EXPECT_THAT(session_description->description()
->contents()[0]
@ -208,9 +208,9 @@ TEST_P(PeerConnectionHeaderExtensionTest, NegotiatedExtensionsAreAccessible) {
std::unique_ptr<PeerConnectionWrapper> pc1 =
CreatePeerConnection(media_type, semantics);
auto transceiver1 = pc1->AddTransceiver(media_type);
auto modified_extensions = transceiver1->HeaderExtensionsToOffer();
auto modified_extensions = transceiver1->GetHeaderExtensionsToNegotiate();
modified_extensions[3].direction = RtpTransceiverDirection::kStopped;
transceiver1->SetOfferedRtpHeaderExtensions(modified_extensions);
transceiver1->SetHeaderExtensionsToNegotiate(modified_extensions);
auto offer = pc1->CreateOfferAndSetAsLocal(
PeerConnectionInterface::RTCOfferAnswerOptions());
@ -224,7 +224,7 @@ TEST_P(PeerConnectionHeaderExtensionTest, NegotiatedExtensionsAreAccessible) {
// PC1 has exts 2-4 unstopped and PC2 has exts 1-3 unstopped -> ext 2, 3
// survives.
EXPECT_THAT(transceiver1->HeaderExtensionsNegotiated(),
EXPECT_THAT(transceiver1->GetNegotiatedHeaderExtensions(),
ElementsAre(Field(&RtpHeaderExtensionCapability::uri, "uri2"),
Field(&RtpHeaderExtensionCapability::uri, "uri3")));
}
@ -238,9 +238,9 @@ TEST_P(PeerConnectionHeaderExtensionTest, OfferedExtensionsArePerTransceiver) {
std::unique_ptr<PeerConnectionWrapper> pc1 =
CreatePeerConnection(media_type, semantics);
auto transceiver1 = pc1->AddTransceiver(media_type);
auto modified_extensions = transceiver1->HeaderExtensionsToOffer();
auto modified_extensions = transceiver1->GetHeaderExtensionsToNegotiate();
modified_extensions[3].direction = RtpTransceiverDirection::kStopped;
transceiver1->SetOfferedRtpHeaderExtensions(modified_extensions);
transceiver1->SetHeaderExtensionsToNegotiate(modified_extensions);
auto transceiver2 = pc1->AddTransceiver(media_type);
auto session_description = pc1->CreateOffer();
@ -278,10 +278,10 @@ TEST_P(PeerConnectionHeaderExtensionTest, RemovalAfterRenegotiation) {
PeerConnectionInterface::RTCOfferAnswerOptions());
pc1->SetRemoteDescription(std::move(answer));
auto modified_extensions = transceiver1->HeaderExtensionsToOffer();
auto modified_extensions = transceiver1->GetHeaderExtensionsToNegotiate();
modified_extensions[3].direction = RtpTransceiverDirection::kStopped;
modified_extensions[3].direction = RtpTransceiverDirection::kStopped;
transceiver1->SetOfferedRtpHeaderExtensions(modified_extensions);
transceiver1->SetHeaderExtensionsToNegotiate(modified_extensions);
auto session_description = pc1->CreateOffer();
EXPECT_THAT(session_description->description()
->contents()[0]

View file

@ -150,13 +150,14 @@ RtpTransceiver::RtpTransceiver(
rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
receiver,
ConnectionContext* context,
std::vector<RtpHeaderExtensionCapability> header_extensions_offered,
std::vector<RtpHeaderExtensionCapability> header_extensions_to_negotiate,
std::function<void()> on_negotiation_needed)
: thread_(GetCurrentTaskQueueOrThread()),
unified_plan_(true),
media_type_(sender->media_type()),
context_(context),
header_extensions_to_offer_(std::move(header_extensions_offered)),
header_extensions_to_negotiate_(
std::move(header_extensions_to_negotiate)),
on_negotiation_needed_(std::move(on_negotiation_needed)) {
RTC_DCHECK(media_type_ == cricket::MEDIA_TYPE_AUDIO ||
media_type_ == cricket::MEDIA_TYPE_VIDEO);
@ -664,12 +665,12 @@ RTCError RtpTransceiver::SetCodecPreferences(
}
std::vector<RtpHeaderExtensionCapability>
RtpTransceiver::HeaderExtensionsToOffer() const {
return header_extensions_to_offer_;
RtpTransceiver::GetHeaderExtensionsToNegotiate() const {
return header_extensions_to_negotiate_;
}
std::vector<RtpHeaderExtensionCapability>
RtpTransceiver::HeaderExtensionsNegotiated() const {
RtpTransceiver::GetNegotiatedHeaderExtensions() const {
RTC_DCHECK_RUN_ON(thread_);
std::vector<RtpHeaderExtensionCapability> result;
for (const auto& ext : negotiated_header_extensions_) {
@ -687,10 +688,9 @@ bool IsMandatoryHeaderExtension(const std::string& uri) {
return uri == RtpExtension::kMidUri;
}
RTCError RtpTransceiver::SetOfferedRtpHeaderExtensions(
rtc::ArrayView<const RtpHeaderExtensionCapability>
header_extensions_to_offer) {
for (const auto& entry : header_extensions_to_offer) {
RTCError RtpTransceiver::SetHeaderExtensionsToNegotiate(
rtc::ArrayView<const RtpHeaderExtensionCapability> header_extensions) {
for (const auto& entry : header_extensions) {
// Handle unsupported requests for mandatory extensions as per
// https://w3c.github.io/webrtc-extensions/#rtcrtptransceiver-interface.
// Note:
@ -701,9 +701,10 @@ RTCError RtpTransceiver::SetOfferedRtpHeaderExtensions(
// Step 2.2.
// Handle unknown extensions.
auto it = std::find_if(
header_extensions_to_offer_.begin(), header_extensions_to_offer_.end(),
header_extensions_to_negotiate_.begin(),
header_extensions_to_negotiate_.end(),
[&entry](const auto& offered) { return entry.uri == offered.uri; });
if (it == header_extensions_to_offer_.end()) {
if (it == header_extensions_to_negotiate_.end()) {
return RTCError(RTCErrorType::UNSUPPORTED_PARAMETER,
"Attempted to modify an unoffered extension.");
}
@ -718,15 +719,16 @@ RTCError RtpTransceiver::SetOfferedRtpHeaderExtensions(
// Set all current extensions but the mandatory ones to stopped.
// This means that anything filtered from the input will not show up.
for (auto& entry : header_extensions_to_offer_) {
for (auto& entry : header_extensions_to_negotiate_) {
if (!IsMandatoryHeaderExtension(entry.uri)) {
entry.direction = RtpTransceiverDirection::kStopped;
}
}
// Apply mutation after error checking.
for (const auto& entry : header_extensions_to_offer) {
for (const auto& entry : header_extensions) {
auto it = std::find_if(
header_extensions_to_offer_.begin(), header_extensions_to_offer_.end(),
header_extensions_to_negotiate_.begin(),
header_extensions_to_negotiate_.end(),
[&entry](const auto& offered) { return entry.uri == offered.uri; });
it->direction = entry.direction;
}

View file

@ -91,14 +91,14 @@ class RtpTransceiver : public RtpTransceiverInterface {
// 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
// and receiver. The sender and receiver should have the same media type.
// `HeaderExtensionsToOffer` is used for initializing the return value of
// HeaderExtensionsToOffer().
// `HeaderExtensionsToNegotiate` is used for initializing the return value of
// HeaderExtensionsToNegotiate().
RtpTransceiver(
rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> sender,
rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
receiver,
ConnectionContext* context,
std::vector<RtpHeaderExtensionCapability> HeaderExtensionsToOffer,
std::vector<RtpHeaderExtensionCapability> HeaderExtensionsToNegotiate,
std::function<void()> on_negotiation_needed);
~RtpTransceiver() override;
@ -274,13 +274,13 @@ class RtpTransceiver : public RtpTransceiverInterface {
std::vector<RtpCodecCapability> codec_preferences() const override {
return codec_preferences_;
}
std::vector<RtpHeaderExtensionCapability> HeaderExtensionsToOffer()
std::vector<RtpHeaderExtensionCapability> GetHeaderExtensionsToNegotiate()
const override;
std::vector<RtpHeaderExtensionCapability> HeaderExtensionsNegotiated()
std::vector<RtpHeaderExtensionCapability> GetNegotiatedHeaderExtensions()
const override;
RTCError SetOfferedRtpHeaderExtensions(
rtc::ArrayView<const RtpHeaderExtensionCapability>
header_extensions_to_offer) override;
RTCError SetHeaderExtensionsToNegotiate(
rtc::ArrayView<const RtpHeaderExtensionCapability> header_extensions)
override;
// Called on the signaling thread when the local or remote content description
// is updated. Used to update the negotiated header extensions.
@ -333,7 +333,7 @@ class RtpTransceiver : public RtpTransceiverInterface {
std::unique_ptr<cricket::ChannelInterface> channel_ = nullptr;
ConnectionContext* const context_;
std::vector<RtpCodecCapability> codec_preferences_;
std::vector<RtpHeaderExtensionCapability> header_extensions_to_offer_;
std::vector<RtpHeaderExtensionCapability> header_extensions_to_negotiate_;
// `negotiated_header_extensions_` is read and written to on the signaling
// thread from the SdpOfferAnswerHandler class (e.g.
@ -364,11 +364,11 @@ PROXY_METHOD1(webrtc::RTCError,
rtc::ArrayView<RtpCodecCapability>)
PROXY_CONSTMETHOD0(std::vector<RtpCodecCapability>, codec_preferences)
PROXY_CONSTMETHOD0(std::vector<RtpHeaderExtensionCapability>,
HeaderExtensionsToOffer)
GetHeaderExtensionsToNegotiate)
PROXY_CONSTMETHOD0(std::vector<RtpHeaderExtensionCapability>,
HeaderExtensionsNegotiated)
GetNegotiatedHeaderExtensions)
PROXY_METHOD1(webrtc::RTCError,
SetOfferedRtpHeaderExtensions,
SetHeaderExtensionsToNegotiate,
rtc::ArrayView<const RtpHeaderExtensionCapability>)
END_PROXY_MAP(RtpTransceiver)

View file

@ -246,7 +246,7 @@ TEST_F(RtpTransceiverTestForHeaderExtensions, OffersChannelManagerList) {
EXPECT_CALL(*sender_.get(), SetTransceiverAsStopped());
EXPECT_CALL(*sender_.get(), Stop());
EXPECT_EQ(transceiver_->HeaderExtensionsToOffer(), extensions_);
EXPECT_EQ(transceiver_->GetHeaderExtensionsToNegotiate(), extensions_);
}
TEST_F(RtpTransceiverTestForHeaderExtensions, ModifiesDirection) {
@ -258,20 +258,24 @@ TEST_F(RtpTransceiverTestForHeaderExtensions, ModifiesDirection) {
auto modified_extensions = extensions_;
modified_extensions[0].direction = RtpTransceiverDirection::kSendOnly;
EXPECT_TRUE(
transceiver_->SetOfferedRtpHeaderExtensions(modified_extensions).ok());
EXPECT_EQ(transceiver_->HeaderExtensionsToOffer(), modified_extensions);
transceiver_->SetHeaderExtensionsToNegotiate(modified_extensions).ok());
EXPECT_EQ(transceiver_->GetHeaderExtensionsToNegotiate(),
modified_extensions);
modified_extensions[0].direction = RtpTransceiverDirection::kRecvOnly;
EXPECT_TRUE(
transceiver_->SetOfferedRtpHeaderExtensions(modified_extensions).ok());
EXPECT_EQ(transceiver_->HeaderExtensionsToOffer(), modified_extensions);
transceiver_->SetHeaderExtensionsToNegotiate(modified_extensions).ok());
EXPECT_EQ(transceiver_->GetHeaderExtensionsToNegotiate(),
modified_extensions);
modified_extensions[0].direction = RtpTransceiverDirection::kSendRecv;
EXPECT_TRUE(
transceiver_->SetOfferedRtpHeaderExtensions(modified_extensions).ok());
EXPECT_EQ(transceiver_->HeaderExtensionsToOffer(), modified_extensions);
transceiver_->SetHeaderExtensionsToNegotiate(modified_extensions).ok());
EXPECT_EQ(transceiver_->GetHeaderExtensionsToNegotiate(),
modified_extensions);
modified_extensions[0].direction = RtpTransceiverDirection::kInactive;
EXPECT_TRUE(
transceiver_->SetOfferedRtpHeaderExtensions(modified_extensions).ok());
EXPECT_EQ(transceiver_->HeaderExtensionsToOffer(), modified_extensions);
transceiver_->SetHeaderExtensionsToNegotiate(modified_extensions).ok());
EXPECT_EQ(transceiver_->GetHeaderExtensionsToNegotiate(),
modified_extensions);
}
TEST_F(RtpTransceiverTestForHeaderExtensions, AcceptsStoppedExtension) {
@ -283,8 +287,9 @@ TEST_F(RtpTransceiverTestForHeaderExtensions, AcceptsStoppedExtension) {
auto modified_extensions = extensions_;
modified_extensions[0].direction = RtpTransceiverDirection::kStopped;
EXPECT_TRUE(
transceiver_->SetOfferedRtpHeaderExtensions(modified_extensions).ok());
EXPECT_EQ(transceiver_->HeaderExtensionsToOffer(), modified_extensions);
transceiver_->SetHeaderExtensionsToNegotiate(modified_extensions).ok());
EXPECT_EQ(transceiver_->GetHeaderExtensionsToNegotiate(),
modified_extensions);
}
TEST_F(RtpTransceiverTestForHeaderExtensions, RejectsUnsupportedExtension) {
@ -296,9 +301,9 @@ TEST_F(RtpTransceiverTestForHeaderExtensions, RejectsUnsupportedExtension) {
std::vector<RtpHeaderExtensionCapability> modified_extensions(
{RtpHeaderExtensionCapability("uri3", 1,
RtpTransceiverDirection::kSendRecv)});
EXPECT_THAT(transceiver_->SetOfferedRtpHeaderExtensions(modified_extensions),
EXPECT_THAT(transceiver_->SetHeaderExtensionsToNegotiate(modified_extensions),
Property(&RTCError::type, RTCErrorType::UNSUPPORTED_PARAMETER));
EXPECT_EQ(transceiver_->HeaderExtensionsToOffer(), extensions_);
EXPECT_EQ(transceiver_->GetHeaderExtensionsToNegotiate(), extensions_);
}
TEST_F(RtpTransceiverTestForHeaderExtensions,
@ -311,9 +316,9 @@ TEST_F(RtpTransceiverTestForHeaderExtensions,
std::vector<RtpHeaderExtensionCapability> modified_extensions = extensions_;
// Attempting to stop the mandatory MID extension.
modified_extensions[2].direction = RtpTransceiverDirection::kStopped;
EXPECT_THAT(transceiver_->SetOfferedRtpHeaderExtensions(modified_extensions),
EXPECT_THAT(transceiver_->SetHeaderExtensionsToNegotiate(modified_extensions),
Property(&RTCError::type, RTCErrorType::INVALID_MODIFICATION));
EXPECT_EQ(transceiver_->HeaderExtensionsToOffer(), extensions_);
EXPECT_EQ(transceiver_->GetHeaderExtensionsToNegotiate(), extensions_);
}
TEST_F(RtpTransceiverTestForHeaderExtensions,
@ -322,7 +327,7 @@ TEST_F(RtpTransceiverTestForHeaderExtensions,
EXPECT_CALL(*receiver_.get(), SetMediaChannel(_));
EXPECT_CALL(*sender_.get(), SetTransceiverAsStopped());
EXPECT_CALL(*sender_.get(), Stop());
EXPECT_THAT(transceiver_->HeaderExtensionsNegotiated(), ElementsAre());
EXPECT_THAT(transceiver_->GetNegotiatedHeaderExtensions(), ElementsAre());
}
TEST_F(RtpTransceiverTestForHeaderExtensions,
@ -344,7 +349,7 @@ TEST_F(RtpTransceiverTestForHeaderExtensions,
EXPECT_CALL(*mock_channel, SetRtpTransport(_)).WillRepeatedly(Return(true));
transceiver_->SetChannel(std::move(mock_channel),
[](const std::string&) { return nullptr; });
EXPECT_THAT(transceiver_->HeaderExtensionsNegotiated(), ElementsAre());
EXPECT_THAT(transceiver_->GetNegotiatedHeaderExtensions(), ElementsAre());
EXPECT_CALL(*mock_channel_ptr, SetFirstPacketReceivedCallback(_));
ClearChannel();
@ -376,7 +381,7 @@ TEST_F(RtpTransceiverTestForHeaderExtensions, ReturnsNegotiatedHdrExts) {
transceiver_->SetChannel(std::move(mock_channel),
[](const std::string&) { return nullptr; });
EXPECT_THAT(transceiver_->HeaderExtensionsNegotiated(),
EXPECT_THAT(transceiver_->GetNegotiatedHeaderExtensions(),
ElementsAre(RtpHeaderExtensionCapability(
"uri1", 1, RtpTransceiverDirection::kSendRecv),
RtpHeaderExtensionCapability(
@ -399,7 +404,7 @@ TEST_F(RtpTransceiverTestForHeaderExtensions,
description.set_rtp_header_extensions(extensions);
transceiver_->OnNegotiationUpdate(SdpType::kAnswer, &description);
EXPECT_THAT(transceiver_->HeaderExtensionsNegotiated(),
EXPECT_THAT(transceiver_->GetNegotiatedHeaderExtensions(),
ElementsAre(RtpHeaderExtensionCapability(
"uri1", 1, RtpTransceiverDirection::kSendRecv),
RtpHeaderExtensionCapability(
@ -410,7 +415,7 @@ TEST_F(RtpTransceiverTestForHeaderExtensions,
description.set_rtp_header_extensions(extensions);
transceiver_->OnNegotiationUpdate(SdpType::kAnswer, &description);
EXPECT_THAT(transceiver_->HeaderExtensionsNegotiated(),
EXPECT_THAT(transceiver_->GetNegotiatedHeaderExtensions(),
ElementsAre(RtpHeaderExtensionCapability(
"uri3", 4, RtpTransceiverDirection::kSendRecv),
RtpHeaderExtensionCapability(

View file

@ -694,7 +694,7 @@ cricket::MediaDescriptionOptions GetMediaDescriptionOptionsForTransceiver(
media_description_options.codec_preferences =
transceiver->codec_preferences();
media_description_options.header_extensions =
transceiver->HeaderExtensionsToOffer();
transceiver->GetHeaderExtensionsToNegotiate();
// This behavior is specified in JSEP. The gist is that:
// 1. The MSID is included if the RtpTransceiver's direction is sendonly or
// sendrecv.