Revert "RtpTransceiverInterface: introduce SetOfferedRtpHeaderExtensions."

This reverts commit 71db9acc40.

Reason for revert: breaks downstream project.
Reason for force push: win bot broken.

Original change's description:
> RtpTransceiverInterface: introduce SetOfferedRtpHeaderExtensions.
>
> This change adds exposure of a new transceiver method for
> modifying the extensions offered in the next SDP negotiation,
> following spec details in https://w3c.github.io/webrtc-extensions/#rtcrtptransceiver-interface.
>
> Features:
> - The interface allows to control the negotiated direction as
>   per https://tools.ietf.org/html/rfc5285#page-7.
> - The interface allows to remove an extension from SDP
>   negotiation by modifying the direction to
>   RtpTransceiverDirection::kStopped.
>
> Note: support for signalling directionality of header extensions
> in the SDP isn't implemented yet.
>
> https://chromestatus.com/feature/5680189201711104.
> Intent to prototype: https://groups.google.com/a/chromium.org/g/blink-dev/c/65YdUi02yZk
>
> Bug: chromium:1051821
> Change-Id: Iaabc34446f038c46d93c442e90c2a77f77d542d4
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/176408
> Reviewed-by: Harald Alvestrand <hta@webrtc.org>
> Commit-Queue: Markus Handell <handellm@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#31487}

TBR=hta@webrtc.org,handellm@webrtc.org

# Not skipping CQ checks because original CL landed > 1 day ago.

No-Try: true
Bug: chromium:1051821
Change-Id: I70e1a07225d7eeec7480fa5577d8ff647eba6902
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/177103
Commit-Queue: Markus Handell <handellm@webrtc.org>
Reviewed-by: Markus Handell <handellm@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#31516}
This commit is contained in:
Markus Handell 2020-06-12 15:24:54 +00:00 committed by Commit Bot
parent 4d11c02ad3
commit 6f727da62b
11 changed files with 208 additions and 558 deletions

View file

@ -222,7 +222,7 @@ struct RTC_EXPORT RtpHeaderExtensionCapability {
bool preferred_encrypt = false; bool preferred_encrypt = false;
// The direction of the extension. The kStopped value is only used with // The direction of the extension. The kStopped value is only used with
// RtpTransceiverInterface::HeaderExtensionsToOffer() and // RtpTransceiverInterface::header_extensions_offered() and
// SetOfferedRtpHeaderExtensions(). // SetOfferedRtpHeaderExtensions().
RtpTransceiverDirection direction = RtpTransceiverDirection::kSendRecv; RtpTransceiverDirection direction = RtpTransceiverDirection::kSendRecv;

View file

@ -41,10 +41,4 @@ RtpTransceiverInterface::HeaderExtensionsToOffer() const {
return {}; return {};
} }
webrtc::RTCError RtpTransceiverInterface::SetOfferedRtpHeaderExtensions(
rtc::ArrayView<const RtpHeaderExtensionCapability>
header_extensions_to_offer) {
return webrtc::RTCError(webrtc::RTCErrorType::UNSUPPORTED_OPERATION);
}
} // namespace webrtc } // namespace webrtc

View file

@ -133,13 +133,6 @@ class RTC_EXPORT RtpTransceiverInterface : public rtc::RefCountInterface {
virtual std::vector<RtpHeaderExtensionCapability> HeaderExtensionsToOffer() virtual std::vector<RtpHeaderExtensionCapability> HeaderExtensionsToOffer()
const; const;
// The SetOfferedRtpHeaderExtensions 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
virtual webrtc::RTCError SetOfferedRtpHeaderExtensions(
rtc::ArrayView<const RtpHeaderExtensionCapability>
header_extensions_to_offer);
protected: protected:
~RtpTransceiverInterface() override = default; ~RtpTransceiverInterface() override = default;
}; };

View file

@ -55,29 +55,6 @@ void GetSupportedSdesCryptoSuiteNames(
} }
} }
cricket::RtpHeaderExtensions RtpHeaderExtensionsFromCapabilities(
const std::vector<webrtc::RtpHeaderExtensionCapability>& capabilities) {
cricket::RtpHeaderExtensions exts;
for (const auto& extension_with_direction : capabilities) {
exts.emplace_back(extension_with_direction.uri,
extension_with_direction.preferred_id.value_or(1));
}
return exts;
}
std::vector<webrtc::RtpHeaderExtensionCapability>
UnstoppedRtpHeaderExtensionCapabilities(
std::vector<webrtc::RtpHeaderExtensionCapability> capabilities) {
capabilities.erase(
std::remove_if(
capabilities.begin(), capabilities.end(),
[](const webrtc::RtpHeaderExtensionCapability& capability) {
return capability.direction == RtpTransceiverDirection::kStopped;
}),
capabilities.end());
return capabilities;
}
} // namespace } // namespace
namespace cricket { namespace cricket {
@ -656,22 +633,7 @@ static bool CreateContentOffer(
if (offer->type() == cricket::MEDIA_TYPE_VIDEO) { if (offer->type() == cricket::MEDIA_TYPE_VIDEO) {
offer->set_rtcp_reduced_size(true); offer->set_rtcp_reduced_size(true);
} }
offer->set_rtp_header_extensions(rtp_extensions);
// Build the vector of header extensions with directions for this
// media_description's options.
RtpHeaderExtensions extensions;
for (auto extension_with_id : rtp_extensions) {
for (const auto& extension : UnstoppedRtpHeaderExtensionCapabilities(
media_description_options.header_extensions)) {
if (extension_with_id.uri == extension.uri) {
// TODO(crbug.com/1051821): Configure the extension direction from
// the information in the media_description_options extension
// capability.
extensions.push_back(extension_with_id);
}
}
}
offer->set_rtp_header_extensions(extensions);
AddSimulcastToMediaDescription(media_description_options, offer); AddSimulcastToMediaDescription(media_description_options, offer);
@ -1203,7 +1165,7 @@ static bool CreateMediaContentAnswer(
const MediaSessionOptions& session_options, const MediaSessionOptions& session_options,
const SecurePolicy& sdes_policy, const SecurePolicy& sdes_policy,
const CryptoParamsVec* current_cryptos, const CryptoParamsVec* current_cryptos,
const RtpHeaderExtensions& local_rtp_extensions, const RtpHeaderExtensions& local_rtp_extenstions,
UniqueRandomIdGenerator* ssrc_generator, UniqueRandomIdGenerator* ssrc_generator,
bool enable_encrypted_rtp_header_extensions, bool enable_encrypted_rtp_header_extensions,
StreamParamsVec* current_streams, StreamParamsVec* current_streams,
@ -1212,7 +1174,7 @@ static bool CreateMediaContentAnswer(
answer->set_extmap_allow_mixed_enum(offer->extmap_allow_mixed_enum()); answer->set_extmap_allow_mixed_enum(offer->extmap_allow_mixed_enum());
RtpHeaderExtensions negotiated_rtp_extensions; RtpHeaderExtensions negotiated_rtp_extensions;
NegotiateRtpHeaderExtensions( NegotiateRtpHeaderExtensions(
local_rtp_extensions, offer->rtp_header_extensions(), local_rtp_extenstions, offer->rtp_header_extensions(),
enable_encrypted_rtp_header_extensions, &negotiated_rtp_extensions); enable_encrypted_rtp_header_extensions, &negotiated_rtp_extensions);
answer->set_rtp_header_extensions(negotiated_rtp_extensions); answer->set_rtp_header_extensions(negotiated_rtp_extensions);
@ -1390,8 +1352,12 @@ 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_);
audio_rtp_extensions_ =
channel_manager->GetDefaultEnabledAudioRtpHeaderExtensions();
channel_manager->GetSupportedVideoSendCodecs(&video_send_codecs_); channel_manager->GetSupportedVideoSendCodecs(&video_send_codecs_);
channel_manager->GetSupportedVideoReceiveCodecs(&video_recv_codecs_); channel_manager->GetSupportedVideoReceiveCodecs(&video_recv_codecs_);
video_rtp_extensions_ =
channel_manager->GetDefaultEnabledVideoRtpHeaderExtensions();
channel_manager->GetSupportedDataCodecs(&rtp_data_codecs_); channel_manager->GetSupportedDataCodecs(&rtp_data_codecs_);
ComputeAudioCodecsIntersectionAndUnion(); ComputeAudioCodecsIntersectionAndUnion();
ComputeVideoCodecsIntersectionAndUnion(); ComputeVideoCodecsIntersectionAndUnion();
@ -1454,11 +1420,22 @@ static void RemoveUnifiedPlanExtensions(RtpHeaderExtensions* extensions) {
} }
RtpHeaderExtensions RtpHeaderExtensions
MediaSessionDescriptionFactory::filtered_rtp_header_extensions( MediaSessionDescriptionFactory::audio_rtp_header_extensions() const {
RtpHeaderExtensions extensions) const { RtpHeaderExtensions extensions = audio_rtp_extensions_;
if (!is_unified_plan_) { if (!is_unified_plan_) {
RemoveUnifiedPlanExtensions(&extensions); RemoveUnifiedPlanExtensions(&extensions);
} }
return extensions;
}
RtpHeaderExtensions
MediaSessionDescriptionFactory::video_rtp_header_extensions() const {
RtpHeaderExtensions extensions = video_rtp_extensions_;
if (!is_unified_plan_) {
RemoveUnifiedPlanExtensions(&extensions);
}
return extensions; return extensions;
} }
@ -1494,10 +1471,11 @@ std::unique_ptr<SessionDescription> MediaSessionDescriptionFactory::CreateOffer(
StripCNCodecs(&offer_audio_codecs); StripCNCodecs(&offer_audio_codecs);
} }
AudioVideoRtpHeaderExtensions extensions_with_ids = RtpHeaderExtensions audio_rtp_extensions;
GetOfferedRtpHeaderExtensionsWithIds( RtpHeaderExtensions video_rtp_extensions;
current_active_contents, session_options.offer_extmap_allow_mixed, GetRtpHdrExtsToOffer(current_active_contents,
session_options.media_description_options); session_options.offer_extmap_allow_mixed,
&audio_rtp_extensions, &video_rtp_extensions);
auto offer = std::make_unique<SessionDescription>(); auto offer = std::make_unique<SessionDescription>();
@ -1517,20 +1495,18 @@ std::unique_ptr<SessionDescription> MediaSessionDescriptionFactory::CreateOffer(
} }
switch (media_description_options.type) { switch (media_description_options.type) {
case MEDIA_TYPE_AUDIO: case MEDIA_TYPE_AUDIO:
if (!AddAudioContentForOffer(media_description_options, session_options, if (!AddAudioContentForOffer(
current_content, current_description, media_description_options, session_options, current_content,
extensions_with_ids.audio, current_description, audio_rtp_extensions, offer_audio_codecs,
offer_audio_codecs, &current_streams, &current_streams, offer.get(), &ice_credentials)) {
offer.get(), &ice_credentials)) {
return nullptr; return nullptr;
} }
break; break;
case MEDIA_TYPE_VIDEO: case MEDIA_TYPE_VIDEO:
if (!AddVideoContentForOffer(media_description_options, session_options, if (!AddVideoContentForOffer(
current_content, current_description, media_description_options, session_options, current_content,
extensions_with_ids.video, current_description, video_rtp_extensions, offer_video_codecs,
offer_video_codecs, &current_streams, &current_streams, offer.get(), &ice_credentials)) {
offer.get(), &ice_credentials)) {
return nullptr; return nullptr;
} }
break; break;
@ -1665,16 +1641,13 @@ MediaSessionDescriptionFactory::CreateAnswer(
msection_index < current_description->contents().size()) { msection_index < current_description->contents().size()) {
current_content = &current_description->contents()[msection_index]; current_content = &current_description->contents()[msection_index];
} }
RtpHeaderExtensions header_extensions = RtpHeaderExtensionsFromCapabilities(
UnstoppedRtpHeaderExtensionCapabilities(
media_description_options.header_extensions));
switch (media_description_options.type) { switch (media_description_options.type) {
case MEDIA_TYPE_AUDIO: case MEDIA_TYPE_AUDIO:
if (!AddAudioContentForAnswer( if (!AddAudioContentForAnswer(
media_description_options, session_options, offer_content, media_description_options, session_options, offer_content,
offer, current_content, current_description, offer, current_content, current_description,
bundle_transport.get(), answer_audio_codecs, header_extensions, bundle_transport.get(), answer_audio_codecs, &current_streams,
&current_streams, answer.get(), &ice_credentials)) { answer.get(), &ice_credentials)) {
return nullptr; return nullptr;
} }
break; break;
@ -1682,8 +1655,8 @@ MediaSessionDescriptionFactory::CreateAnswer(
if (!AddVideoContentForAnswer( if (!AddVideoContentForAnswer(
media_description_options, session_options, offer_content, media_description_options, session_options, offer_content,
offer, current_content, current_description, offer, current_content, current_description,
bundle_transport.get(), answer_video_codecs, header_extensions, bundle_transport.get(), answer_video_codecs, &current_streams,
&current_streams, answer.get(), &ice_credentials)) { answer.get(), &ice_credentials)) {
return nullptr; return nullptr;
} }
break; break;
@ -1976,12 +1949,11 @@ void MediaSessionDescriptionFactory::GetCodecsForAnswer(
&used_pltypes); &used_pltypes);
} }
MediaSessionDescriptionFactory::AudioVideoRtpHeaderExtensions void MediaSessionDescriptionFactory::GetRtpHdrExtsToOffer(
MediaSessionDescriptionFactory::GetOfferedRtpHeaderExtensionsWithIds(
const std::vector<const ContentInfo*>& current_active_contents, const std::vector<const ContentInfo*>& current_active_contents,
bool extmap_allow_mixed, bool extmap_allow_mixed,
const std::vector<MediaDescriptionOptions>& media_description_options) RtpHeaderExtensions* offer_audio_extensions,
const { RtpHeaderExtensions* offer_video_extensions) const {
// All header extensions allocated from the same range to avoid potential // All header extensions allocated from the same range to avoid potential
// issues when using BUNDLE. // issues when using BUNDLE.
@ -1995,7 +1967,6 @@ MediaSessionDescriptionFactory::GetOfferedRtpHeaderExtensionsWithIds(
RtpHeaderExtensions all_regular_extensions; RtpHeaderExtensions all_regular_extensions;
RtpHeaderExtensions all_encrypted_extensions; RtpHeaderExtensions all_encrypted_extensions;
AudioVideoRtpHeaderExtensions offered_extensions;
// First - get all extensions from the current description if the media type // First - get all extensions from the current description if the media type
// is used. // is used.
// Add them to |used_ids| so the local ids are not reused if a new media // Add them to |used_ids| so the local ids are not reused if a new media
@ -2004,42 +1975,36 @@ MediaSessionDescriptionFactory::GetOfferedRtpHeaderExtensionsWithIds(
if (IsMediaContentOfType(content, MEDIA_TYPE_AUDIO)) { if (IsMediaContentOfType(content, MEDIA_TYPE_AUDIO)) {
const AudioContentDescription* audio = const AudioContentDescription* audio =
content->media_description()->as_audio(); content->media_description()->as_audio();
MergeRtpHdrExts(audio->rtp_header_extensions(), &offered_extensions.audio, MergeRtpHdrExts(audio->rtp_header_extensions(), offer_audio_extensions,
&all_regular_extensions, &all_encrypted_extensions, &all_regular_extensions, &all_encrypted_extensions,
&used_ids); &used_ids);
} else if (IsMediaContentOfType(content, MEDIA_TYPE_VIDEO)) { } else if (IsMediaContentOfType(content, MEDIA_TYPE_VIDEO)) {
const VideoContentDescription* video = const VideoContentDescription* video =
content->media_description()->as_video(); content->media_description()->as_video();
MergeRtpHdrExts(video->rtp_header_extensions(), &offered_extensions.video, MergeRtpHdrExts(video->rtp_header_extensions(), offer_video_extensions,
&all_regular_extensions, &all_encrypted_extensions, &all_regular_extensions, &all_encrypted_extensions,
&used_ids); &used_ids);
} }
} }
// Add all encountered header extensions in the media description options that // Add our default RTP header extensions that are not in the current
// are not in the current description. // description.
for (const auto& entry : media_description_options) { MergeRtpHdrExts(audio_rtp_header_extensions(), offer_audio_extensions,
RtpHeaderExtensions filtered_extensions = filtered_rtp_header_extensions( &all_regular_extensions, &all_encrypted_extensions,
RtpHeaderExtensionsFromCapabilities(entry.header_extensions)); &used_ids);
if (entry.type == MEDIA_TYPE_AUDIO) MergeRtpHdrExts(video_rtp_header_extensions(), offer_video_extensions,
MergeRtpHdrExts(filtered_extensions, &offered_extensions.audio, &all_regular_extensions, &all_encrypted_extensions,
&all_regular_extensions, &all_encrypted_extensions, &used_ids);
&used_ids);
else if (entry.type == MEDIA_TYPE_VIDEO)
MergeRtpHdrExts(filtered_extensions, &offered_extensions.video,
&all_regular_extensions, &all_encrypted_extensions,
&used_ids);
}
// TODO(jbauch): Support adding encrypted header extensions to existing // TODO(jbauch): Support adding encrypted header extensions to existing
// sessions. // sessions.
if (enable_encrypted_rtp_header_extensions_ && if (enable_encrypted_rtp_header_extensions_ &&
current_active_contents.empty()) { current_active_contents.empty()) {
AddEncryptedVersionsOfHdrExts(&offered_extensions.audio, AddEncryptedVersionsOfHdrExts(offer_audio_extensions,
&all_encrypted_extensions, &used_ids); &all_encrypted_extensions, &used_ids);
AddEncryptedVersionsOfHdrExts(&offered_extensions.video, AddEncryptedVersionsOfHdrExts(offer_video_extensions,
&all_encrypted_extensions, &used_ids); &all_encrypted_extensions, &used_ids);
} }
return offered_extensions;
} }
bool MediaSessionDescriptionFactory::AddTransportOffer( bool MediaSessionDescriptionFactory::AddTransportOffer(
@ -2414,7 +2379,6 @@ bool MediaSessionDescriptionFactory::AddAudioContentForAnswer(
const SessionDescription* current_description, const SessionDescription* current_description,
const TransportInfo* bundle_transport, const TransportInfo* bundle_transport,
const AudioCodecs& audio_codecs, const AudioCodecs& audio_codecs,
const RtpHeaderExtensions& default_audio_rtp_header_extensions,
StreamParamsVec* current_streams, StreamParamsVec* current_streams,
SessionDescription* answer, SessionDescription* answer,
IceCredentialsIterator* ice_credentials) const { IceCredentialsIterator* ice_credentials) const {
@ -2487,9 +2451,9 @@ bool MediaSessionDescriptionFactory::AddAudioContentForAnswer(
if (!CreateMediaContentAnswer( if (!CreateMediaContentAnswer(
offer_audio_description, media_description_options, session_options, offer_audio_description, media_description_options, session_options,
sdes_policy, GetCryptos(current_content), sdes_policy, GetCryptos(current_content),
filtered_rtp_header_extensions(default_audio_rtp_header_extensions), audio_rtp_header_extensions(), ssrc_generator_,
ssrc_generator_, enable_encrypted_rtp_header_extensions_, enable_encrypted_rtp_header_extensions_, current_streams,
current_streams, bundle_enabled, audio_answer.get())) { bundle_enabled, audio_answer.get())) {
return false; // Fails the session setup. return false; // Fails the session setup.
} }
@ -2525,7 +2489,6 @@ bool MediaSessionDescriptionFactory::AddVideoContentForAnswer(
const SessionDescription* current_description, const SessionDescription* current_description,
const TransportInfo* bundle_transport, const TransportInfo* bundle_transport,
const VideoCodecs& video_codecs, const VideoCodecs& video_codecs,
const RtpHeaderExtensions& default_video_rtp_header_extensions,
StreamParamsVec* current_streams, StreamParamsVec* current_streams,
SessionDescription* answer, SessionDescription* answer,
IceCredentialsIterator* ice_credentials) const { IceCredentialsIterator* ice_credentials) const {
@ -2606,9 +2569,9 @@ bool MediaSessionDescriptionFactory::AddVideoContentForAnswer(
if (!CreateMediaContentAnswer( if (!CreateMediaContentAnswer(
offer_video_description, media_description_options, session_options, offer_video_description, media_description_options, session_options,
sdes_policy, GetCryptos(current_content), sdes_policy, GetCryptos(current_content),
filtered_rtp_header_extensions(default_video_rtp_header_extensions), video_rtp_header_extensions(), ssrc_generator_,
ssrc_generator_, enable_encrypted_rtp_header_extensions_, enable_encrypted_rtp_header_extensions_, current_streams,
current_streams, bundle_enabled, video_answer.get())) { bundle_enabled, video_answer.get())) {
return false; // Failed the sessin setup. return false; // Failed the sessin setup.
} }
bool secure = bundle_transport ? bundle_transport->description.secure() bool secure = bundle_transport ? bundle_transport->description.secure()

View file

@ -79,7 +79,6 @@ struct MediaDescriptionOptions {
std::vector<SenderOptions> sender_options; std::vector<SenderOptions> sender_options;
std::vector<webrtc::RtpCodecCapability> codec_preferences; std::vector<webrtc::RtpCodecCapability> codec_preferences;
absl::optional<std::string> alt_protocol; absl::optional<std::string> alt_protocol;
std::vector<webrtc::RtpHeaderExtensionCapability> header_extensions;
private: private:
// Doesn't DCHECK on |type|. // Doesn't DCHECK on |type|.
@ -148,13 +147,19 @@ class MediaSessionDescriptionFactory {
const AudioCodecs& audio_recv_codecs() const; const AudioCodecs& audio_recv_codecs() const;
void set_audio_codecs(const AudioCodecs& send_codecs, void set_audio_codecs(const AudioCodecs& send_codecs,
const AudioCodecs& recv_codecs); const AudioCodecs& recv_codecs);
void set_audio_rtp_header_extensions(const RtpHeaderExtensions& extensions) {
audio_rtp_extensions_ = extensions;
}
RtpHeaderExtensions audio_rtp_header_extensions() const;
const VideoCodecs& video_sendrecv_codecs() const; const VideoCodecs& video_sendrecv_codecs() const;
const VideoCodecs& video_send_codecs() const; const VideoCodecs& video_send_codecs() const;
const VideoCodecs& video_recv_codecs() const; const VideoCodecs& video_recv_codecs() const;
void set_video_codecs(const VideoCodecs& send_codecs, void set_video_codecs(const VideoCodecs& send_codecs,
const VideoCodecs& recv_codecs); const VideoCodecs& recv_codecs);
RtpHeaderExtensions filtered_rtp_header_extensions( void set_video_rtp_header_extensions(const RtpHeaderExtensions& extensions) {
RtpHeaderExtensions extensions) const; video_rtp_extensions_ = extensions;
}
RtpHeaderExtensions video_rtp_header_extensions() const;
const RtpDataCodecs& rtp_data_codecs() const { return rtp_data_codecs_; } const RtpDataCodecs& rtp_data_codecs() const { return rtp_data_codecs_; }
void set_rtp_data_codecs(const RtpDataCodecs& codecs) { void set_rtp_data_codecs(const RtpDataCodecs& codecs) {
rtp_data_codecs_ = codecs; rtp_data_codecs_ = codecs;
@ -179,11 +184,6 @@ class MediaSessionDescriptionFactory {
const SessionDescription* current_description) const; const SessionDescription* current_description) const;
private: private:
struct AudioVideoRtpHeaderExtensions {
RtpHeaderExtensions audio;
RtpHeaderExtensions video;
};
const AudioCodecs& GetAudioCodecsForOffer( const AudioCodecs& GetAudioCodecsForOffer(
const webrtc::RtpTransceiverDirection& direction) const; const webrtc::RtpTransceiverDirection& direction) const;
const AudioCodecs& GetAudioCodecsForAnswer( const AudioCodecs& GetAudioCodecsForAnswer(
@ -205,11 +205,11 @@ class MediaSessionDescriptionFactory {
AudioCodecs* audio_codecs, AudioCodecs* audio_codecs,
VideoCodecs* video_codecs, VideoCodecs* video_codecs,
RtpDataCodecs* rtp_data_codecs) const; RtpDataCodecs* rtp_data_codecs) const;
AudioVideoRtpHeaderExtensions GetOfferedRtpHeaderExtensionsWithIds( void GetRtpHdrExtsToOffer(
const std::vector<const ContentInfo*>& current_active_contents, const std::vector<const ContentInfo*>& current_active_contents,
bool extmap_allow_mixed, bool extmap_allow_mixed,
const std::vector<MediaDescriptionOptions>& media_description_options) RtpHeaderExtensions* audio_extensions,
const; RtpHeaderExtensions* video_extensions) const;
bool AddTransportOffer(const std::string& content_name, bool AddTransportOffer(const std::string& content_name,
const TransportOptions& transport_options, const TransportOptions& transport_options,
const SessionDescription* current_desc, const SessionDescription* current_desc,
@ -293,7 +293,6 @@ class MediaSessionDescriptionFactory {
const SessionDescription* current_description, const SessionDescription* current_description,
const TransportInfo* bundle_transport, const TransportInfo* bundle_transport,
const AudioCodecs& audio_codecs, const AudioCodecs& audio_codecs,
const RtpHeaderExtensions& default_audio_rtp_header_extensions,
StreamParamsVec* current_streams, StreamParamsVec* current_streams,
SessionDescription* answer, SessionDescription* answer,
IceCredentialsIterator* ice_credentials) const; IceCredentialsIterator* ice_credentials) const;
@ -307,7 +306,6 @@ class MediaSessionDescriptionFactory {
const SessionDescription* current_description, const SessionDescription* current_description,
const TransportInfo* bundle_transport, const TransportInfo* bundle_transport,
const VideoCodecs& video_codecs, const VideoCodecs& video_codecs,
const RtpHeaderExtensions& default_video_rtp_header_extensions,
StreamParamsVec* current_streams, StreamParamsVec* current_streams,
SessionDescription* answer, SessionDescription* answer,
IceCredentialsIterator* ice_credentials) const; IceCredentialsIterator* ice_credentials) const;
@ -336,12 +334,14 @@ class MediaSessionDescriptionFactory {
AudioCodecs audio_sendrecv_codecs_; AudioCodecs audio_sendrecv_codecs_;
// Union of send and recv. // Union of send and recv.
AudioCodecs all_audio_codecs_; AudioCodecs all_audio_codecs_;
RtpHeaderExtensions audio_rtp_extensions_;
VideoCodecs video_send_codecs_; VideoCodecs video_send_codecs_;
VideoCodecs video_recv_codecs_; VideoCodecs video_recv_codecs_;
// Intersection of send and recv. // Intersection of send and recv.
VideoCodecs video_sendrecv_codecs_; VideoCodecs video_sendrecv_codecs_;
// Union of send and recv. // Union of send and recv.
VideoCodecs all_video_codecs_; VideoCodecs all_video_codecs_;
RtpHeaderExtensions video_rtp_extensions_;
RtpDataCodecs rtp_data_codecs_; RtpDataCodecs rtp_data_codecs_;
// This object is not owned by the channel so it must outlive it. // This object is not owned by the channel so it must outlive it.
rtc::UniqueRandomIdGenerator* const ssrc_generator_; rtc::UniqueRandomIdGenerator* const ssrc_generator_;

View file

@ -754,10 +754,13 @@ class MediaSessionDescriptionFactoryTest : public ::testing::Test {
const cricket::RtpHeaderExtensions& expectedAnswer) { const cricket::RtpHeaderExtensions& expectedAnswer) {
MediaSessionOptions opts; MediaSessionOptions opts;
AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts); AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
SetAudioVideoRtpHeaderExtensions(offered, offered, &opts); f1_.set_audio_rtp_header_extensions(offered);
f1_.set_video_rtp_header_extensions(offered);
f2_.set_audio_rtp_header_extensions(local);
f2_.set_video_rtp_header_extensions(local);
std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL); std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
ASSERT_TRUE(offer.get() != NULL); ASSERT_TRUE(offer.get() != NULL);
SetAudioVideoRtpHeaderExtensions(local, local, &opts);
std::unique_ptr<SessionDescription> answer = std::unique_ptr<SessionDescription> answer =
f2_.CreateAnswer(offer.get(), opts, NULL); f2_.CreateAnswer(offer.get(), opts, NULL);
@ -769,38 +772,6 @@ class MediaSessionDescriptionFactoryTest : public ::testing::Test {
GetFirstVideoContentDescription(answer.get())->rtp_header_extensions()); GetFirstVideoContentDescription(answer.get())->rtp_header_extensions());
} }
std::vector<webrtc::RtpHeaderExtensionCapability>
HeaderExtensionCapabilitiesFromRtpExtensions(
cricket::RtpHeaderExtensions extensions) {
std::vector<webrtc::RtpHeaderExtensionCapability> capabilities;
for (const auto& extension : extensions) {
webrtc::RtpHeaderExtensionCapability capability(
extension.uri, extension.id,
webrtc::RtpTransceiverDirection::kSendRecv);
capabilities.push_back(capability);
}
return capabilities;
}
void SetAudioVideoRtpHeaderExtensions(cricket::RtpHeaderExtensions audio_exts,
cricket::RtpHeaderExtensions video_exts,
MediaSessionOptions* opts) {
auto audio_caps = HeaderExtensionCapabilitiesFromRtpExtensions(audio_exts);
auto video_caps = HeaderExtensionCapabilitiesFromRtpExtensions(video_exts);
for (auto& entry : opts->media_description_options) {
switch (entry.type) {
case MEDIA_TYPE_AUDIO:
entry.header_extensions = audio_caps;
break;
case MEDIA_TYPE_VIDEO:
entry.header_extensions = video_caps;
break;
default:
break;
}
}
}
protected: protected:
UniqueRandomIdGenerator ssrc_generator1; UniqueRandomIdGenerator ssrc_generator1;
UniqueRandomIdGenerator ssrc_generator2; UniqueRandomIdGenerator ssrc_generator2;
@ -1688,13 +1659,13 @@ TEST_F(MediaSessionDescriptionFactoryTest, AudioOfferAnswerWithCryptoDisabled) {
TEST_F(MediaSessionDescriptionFactoryTest, TestOfferAnswerWithRtpExtensions) { TEST_F(MediaSessionDescriptionFactoryTest, TestOfferAnswerWithRtpExtensions) {
MediaSessionOptions opts; MediaSessionOptions opts;
AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts); AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
SetAudioVideoRtpHeaderExtensions(MAKE_VECTOR(kAudioRtpExtension1), f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
MAKE_VECTOR(kVideoRtpExtension1), &opts); f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL); std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
ASSERT_TRUE(offer.get() != NULL); ASSERT_TRUE(offer.get() != NULL);
SetAudioVideoRtpHeaderExtensions(MAKE_VECTOR(kAudioRtpExtension2),
MAKE_VECTOR(kVideoRtpExtension2), &opts);
std::unique_ptr<SessionDescription> answer = std::unique_ptr<SessionDescription> answer =
f2_.CreateAnswer(offer.get(), opts, NULL); f2_.CreateAnswer(offer.get(), opts, NULL);
@ -1743,21 +1714,21 @@ TEST_F(MediaSessionDescriptionFactoryTest,
MediaSessionOptions opts; MediaSessionOptions opts;
AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts); AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
SetAudioVideoRtpHeaderExtensions( const auto offered = MAKE_VECTOR(kRtpExtensionGenericFrameDescriptorUri00);
MAKE_VECTOR(kRtpExtensionGenericFrameDescriptorUri00), f1_.set_audio_rtp_header_extensions(offered);
MAKE_VECTOR(kRtpExtensionGenericFrameDescriptorUri00), &opts); f1_.set_video_rtp_header_extensions(offered);
const auto local = MAKE_VECTOR(kRtpExtensionTransportSequenceNumber01);
f2_.set_audio_rtp_header_extensions(local);
f2_.set_video_rtp_header_extensions(local);
std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr); std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
SetAudioVideoRtpHeaderExtensions(
MAKE_VECTOR(kRtpExtensionTransportSequenceNumber01),
MAKE_VECTOR(kRtpExtensionTransportSequenceNumber01), &opts);
std::unique_ptr<SessionDescription> answer = std::unique_ptr<SessionDescription> answer =
f2_.CreateAnswer(offer.get(), opts, nullptr); f2_.CreateAnswer(offer.get(), opts, nullptr);
EXPECT_THAT( EXPECT_THAT(
GetFirstAudioContentDescription(answer.get())->rtp_header_extensions(), GetFirstAudioContentDescription(answer.get())->rtp_header_extensions(),
ElementsAreArray(kRtpExtensionGenericFrameDescriptorUri00)); ElementsAreArray(offered));
EXPECT_THAT( EXPECT_THAT(
GetFirstVideoContentDescription(answer.get())->rtp_header_extensions(), GetFirstVideoContentDescription(answer.get())->rtp_header_extensions(),
ElementsAreArray(kRtpExtensionGenericFrameDescriptorUri00)); ElementsAreArray(offered));
} }
TEST_F(MediaSessionDescriptionFactoryTest, TEST_F(MediaSessionDescriptionFactoryTest,
@ -1765,18 +1736,21 @@ TEST_F(MediaSessionDescriptionFactoryTest,
MediaSessionOptions opts; MediaSessionOptions opts;
AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts); AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
SetAudioVideoRtpHeaderExtensions( const auto offered = MAKE_VECTOR(kRtpExtensionGenericFrameDescriptorUri00);
MAKE_VECTOR(kRtpExtensionGenericFrameDescriptorUri00), f1_.set_audio_rtp_header_extensions(offered);
MAKE_VECTOR(kRtpExtensionGenericFrameDescriptorUri00), &opts); f1_.set_video_rtp_header_extensions(offered);
const auto local = MAKE_VECTOR(kRtpExtensionGenericFrameDescriptorUri00);
f2_.set_audio_rtp_header_extensions(local);
f2_.set_video_rtp_header_extensions(local);
std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr); std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
std::unique_ptr<SessionDescription> answer = std::unique_ptr<SessionDescription> answer =
f2_.CreateAnswer(offer.get(), opts, nullptr); f2_.CreateAnswer(offer.get(), opts, nullptr);
EXPECT_THAT( EXPECT_THAT(
GetFirstAudioContentDescription(answer.get())->rtp_header_extensions(), GetFirstAudioContentDescription(answer.get())->rtp_header_extensions(),
ElementsAreArray(kRtpExtensionGenericFrameDescriptorUri00)); ElementsAreArray(offered));
EXPECT_THAT( EXPECT_THAT(
GetFirstVideoContentDescription(answer.get())->rtp_header_extensions(), GetFirstVideoContentDescription(answer.get())->rtp_header_extensions(),
ElementsAreArray(kRtpExtensionGenericFrameDescriptorUri00)); ElementsAreArray(offered));
} }
TEST_F(MediaSessionDescriptionFactoryTest, TEST_F(MediaSessionDescriptionFactoryTest,
@ -1785,10 +1759,10 @@ TEST_F(MediaSessionDescriptionFactoryTest,
AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts); AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
RtpExtension offer_dd(RtpExtension::kDependencyDescriptorUri, 7); RtpExtension offer_dd(RtpExtension::kDependencyDescriptorUri, 7);
SetAudioVideoRtpHeaderExtensions({}, {offer_dd}, &opts);
std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
RtpExtension local_tsn(RtpExtension::kTransportSequenceNumberUri, 5); RtpExtension local_tsn(RtpExtension::kTransportSequenceNumberUri, 5);
SetAudioVideoRtpHeaderExtensions({}, {local_tsn}, &opts); f1_.set_video_rtp_header_extensions({offer_dd});
f2_.set_video_rtp_header_extensions({local_tsn});
std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
std::unique_ptr<SessionDescription> answer = std::unique_ptr<SessionDescription> answer =
f2_.CreateAnswer(offer.get(), opts, nullptr); f2_.CreateAnswer(offer.get(), opts, nullptr);
EXPECT_THAT( EXPECT_THAT(
@ -1803,9 +1777,9 @@ TEST_F(MediaSessionDescriptionFactoryTest,
RtpExtension offer_dd(RtpExtension::kDependencyDescriptorUri, 7); RtpExtension offer_dd(RtpExtension::kDependencyDescriptorUri, 7);
RtpExtension local_dd(RtpExtension::kDependencyDescriptorUri, 5); RtpExtension local_dd(RtpExtension::kDependencyDescriptorUri, 5);
SetAudioVideoRtpHeaderExtensions({}, {offer_dd}, &opts); f1_.set_video_rtp_header_extensions({offer_dd});
f2_.set_video_rtp_header_extensions({local_dd});
std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr); std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
SetAudioVideoRtpHeaderExtensions({}, {local_dd}, &opts);
std::unique_ptr<SessionDescription> answer = std::unique_ptr<SessionDescription> answer =
f2_.CreateAnswer(offer.get(), opts, nullptr); f2_.CreateAnswer(offer.get(), opts, nullptr);
EXPECT_THAT( EXPECT_THAT(
@ -1822,10 +1796,12 @@ TEST_F(MediaSessionDescriptionFactoryTest,
RtpExtension(RtpExtension::kAbsoluteCaptureTimeUri, 7)}; RtpExtension(RtpExtension::kAbsoluteCaptureTimeUri, 7)};
const cricket::RtpHeaderExtensions local_extensions = { const cricket::RtpHeaderExtensions local_extensions = {
RtpExtension(RtpExtension::kTransportSequenceNumberUri, 5)}; RtpExtension(RtpExtension::kTransportSequenceNumberUri, 5)};
SetAudioVideoRtpHeaderExtensions(offered_extensions, offered_extensions, f1_.set_video_rtp_header_extensions(offered_extensions);
&opts); f1_.set_audio_rtp_header_extensions(offered_extensions);
f2_.set_video_rtp_header_extensions(local_extensions);
f2_.set_audio_rtp_header_extensions(local_extensions);
std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr); std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
SetAudioVideoRtpHeaderExtensions(local_extensions, local_extensions, &opts);
std::unique_ptr<SessionDescription> answer = std::unique_ptr<SessionDescription> answer =
f2_.CreateAnswer(offer.get(), opts, nullptr); f2_.CreateAnswer(offer.get(), opts, nullptr);
EXPECT_THAT( EXPECT_THAT(
@ -1845,10 +1821,12 @@ TEST_F(MediaSessionDescriptionFactoryTest,
RtpExtension(RtpExtension::kAbsoluteCaptureTimeUri, 7)}; RtpExtension(RtpExtension::kAbsoluteCaptureTimeUri, 7)};
const cricket::RtpHeaderExtensions local_extensions = { const cricket::RtpHeaderExtensions local_extensions = {
RtpExtension(RtpExtension::kAbsoluteCaptureTimeUri, 5)}; RtpExtension(RtpExtension::kAbsoluteCaptureTimeUri, 5)};
SetAudioVideoRtpHeaderExtensions(offered_extensions, offered_extensions, f1_.set_video_rtp_header_extensions(offered_extensions);
&opts); f1_.set_audio_rtp_header_extensions(offered_extensions);
f2_.set_video_rtp_header_extensions(local_extensions);
f2_.set_audio_rtp_header_extensions(local_extensions);
std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr); std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
SetAudioVideoRtpHeaderExtensions(local_extensions, local_extensions, &opts);
std::unique_ptr<SessionDescription> answer = std::unique_ptr<SessionDescription> answer =
f2_.CreateAnswer(offer.get(), opts, nullptr); f2_.CreateAnswer(offer.get(), opts, nullptr);
EXPECT_THAT( EXPECT_THAT(
@ -1868,10 +1846,12 @@ TEST_F(MediaSessionDescriptionFactoryTest,
RtpExtension(RtpExtension::kTransportSequenceNumberUri, 7)}; RtpExtension(RtpExtension::kTransportSequenceNumberUri, 7)};
const cricket::RtpHeaderExtensions local_extensions = { const cricket::RtpHeaderExtensions local_extensions = {
RtpExtension(RtpExtension::kAbsoluteCaptureTimeUri, 5)}; RtpExtension(RtpExtension::kAbsoluteCaptureTimeUri, 5)};
SetAudioVideoRtpHeaderExtensions(offered_extensions, offered_extensions, f1_.set_video_rtp_header_extensions(offered_extensions);
&opts); f1_.set_audio_rtp_header_extensions(offered_extensions);
f2_.set_video_rtp_header_extensions(local_extensions);
f2_.set_audio_rtp_header_extensions(local_extensions);
std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr); std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
SetAudioVideoRtpHeaderExtensions(local_extensions, local_extensions, &opts);
std::unique_ptr<SessionDescription> answer = std::unique_ptr<SessionDescription> answer =
f2_.CreateAnswer(offer.get(), opts, nullptr); f2_.CreateAnswer(offer.get(), opts, nullptr);
EXPECT_THAT( EXPECT_THAT(
@ -1882,123 +1862,6 @@ TEST_F(MediaSessionDescriptionFactoryTest,
IsEmpty()); IsEmpty());
} }
TEST_F(MediaSessionDescriptionFactoryTest, OffersUnstoppedExtensions) {
MediaSessionOptions opts;
AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio",
RtpTransceiverDirection::kSendRecv, kActive,
&opts);
opts.media_description_options.back().header_extensions = {
webrtc::RtpHeaderExtensionCapability("uri1", 1,
RtpTransceiverDirection::kStopped),
webrtc::RtpHeaderExtensionCapability("uri2", 3,
RtpTransceiverDirection::kSendOnly),
webrtc::RtpHeaderExtensionCapability("uri3", 5,
RtpTransceiverDirection::kRecvOnly)};
AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video1",
RtpTransceiverDirection::kSendRecv, kActive,
&opts);
opts.media_description_options.back().header_extensions = {
webrtc::RtpHeaderExtensionCapability("uri1", 1,
RtpTransceiverDirection::kSendRecv),
webrtc::RtpHeaderExtensionCapability("uri2", 3,
RtpTransceiverDirection::kStopped),
webrtc::RtpHeaderExtensionCapability("uri3", 5,
RtpTransceiverDirection::kRecvOnly)};
AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video2",
RtpTransceiverDirection::kSendRecv, kActive,
&opts);
opts.media_description_options.back().header_extensions = {
webrtc::RtpHeaderExtensionCapability("uri1", 1,
RtpTransceiverDirection::kSendRecv),
webrtc::RtpHeaderExtensionCapability("uri2", 3,
RtpTransceiverDirection::kRecvOnly),
webrtc::RtpHeaderExtensionCapability("uri3", 5,
RtpTransceiverDirection::kStopped)};
auto offer = f1_.CreateOffer(opts, nullptr);
EXPECT_THAT(
offer->contents(),
ElementsAre(
Property(&ContentInfo::media_description,
Pointee(Property(
&MediaContentDescription::rtp_header_extensions,
ElementsAre(Field(&RtpExtension::uri, "uri2"),
Field(&RtpExtension::uri, "uri3"))))),
Property(&ContentInfo::media_description,
Pointee(Property(
&MediaContentDescription::rtp_header_extensions,
ElementsAre(Field(&RtpExtension::uri, "uri1"),
Field(&RtpExtension::uri, "uri3"))))),
Property(&ContentInfo::media_description,
Pointee(Property(
&MediaContentDescription::rtp_header_extensions,
ElementsAre(Field(&RtpExtension::uri, "uri1"),
Field(&RtpExtension::uri, "uri2")))))));
}
TEST_F(MediaSessionDescriptionFactoryTest, AnswersUnstoppedExtensions) {
MediaSessionOptions opts;
AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio",
RtpTransceiverDirection::kSendRecv, kActive,
&opts);
opts.media_description_options.back().header_extensions = {
webrtc::RtpHeaderExtensionCapability("uri1", 4,
RtpTransceiverDirection::kStopped),
webrtc::RtpHeaderExtensionCapability("uri2", 3,
RtpTransceiverDirection::kSendOnly),
webrtc::RtpHeaderExtensionCapability("uri3", 2,
RtpTransceiverDirection::kRecvOnly),
webrtc::RtpHeaderExtensionCapability("uri4", 1,
RtpTransceiverDirection::kSendRecv)};
auto offer = f1_.CreateOffer(opts, nullptr);
opts.media_description_options.back().header_extensions = {
webrtc::RtpHeaderExtensionCapability("uri1", 4,
RtpTransceiverDirection::kSendOnly),
webrtc::RtpHeaderExtensionCapability("uri2", 3,
RtpTransceiverDirection::kRecvOnly),
webrtc::RtpHeaderExtensionCapability("uri3", 2,
RtpTransceiverDirection::kStopped),
webrtc::RtpHeaderExtensionCapability("uri4", 1,
RtpTransceiverDirection::kSendRecv)};
auto answer = f2_.CreateAnswer(offer.get(), opts, nullptr);
EXPECT_THAT(
answer->contents(),
ElementsAre(Property(
&ContentInfo::media_description,
Pointee(Property(&MediaContentDescription::rtp_header_extensions,
ElementsAre(Field(&RtpExtension::uri, "uri2"),
Field(&RtpExtension::uri, "uri4")))))));
}
TEST_F(MediaSessionDescriptionFactoryTest,
AppendsUnstoppedExtensionsToCurrentDescription) {
MediaSessionOptions opts;
AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio",
RtpTransceiverDirection::kSendRecv, kActive,
&opts);
opts.media_description_options.back().header_extensions = {
webrtc::RtpHeaderExtensionCapability("uri1", 1,
RtpTransceiverDirection::kSendRecv)};
auto offer = f1_.CreateOffer(opts, nullptr);
opts.media_description_options.back().header_extensions = {
webrtc::RtpHeaderExtensionCapability("uri1", 2,
RtpTransceiverDirection::kSendRecv),
webrtc::RtpHeaderExtensionCapability("uri2", 3,
RtpTransceiverDirection::kRecvOnly),
webrtc::RtpHeaderExtensionCapability("uri3", 5,
RtpTransceiverDirection::kStopped),
webrtc::RtpHeaderExtensionCapability("uri4", 6,
RtpTransceiverDirection::kSendRecv)};
auto offer2 = f1_.CreateOffer(opts, offer.get());
EXPECT_THAT(
offer2->contents(),
ElementsAre(Property(
&ContentInfo::media_description,
Pointee(Property(&MediaContentDescription::rtp_header_extensions,
ElementsAre(Field(&RtpExtension::uri, "uri1"),
Field(&RtpExtension::uri, "uri2"),
Field(&RtpExtension::uri, "uri4")))))));
}
TEST_F(MediaSessionDescriptionFactoryTest, TEST_F(MediaSessionDescriptionFactoryTest,
TestOfferAnswerWithEncryptedRtpExtensionsBoth) { TestOfferAnswerWithEncryptedRtpExtensionsBoth) {
MediaSessionOptions opts; MediaSessionOptions opts;
@ -2007,12 +1870,13 @@ TEST_F(MediaSessionDescriptionFactoryTest,
f1_.set_enable_encrypted_rtp_header_extensions(true); f1_.set_enable_encrypted_rtp_header_extensions(true);
f2_.set_enable_encrypted_rtp_header_extensions(true); f2_.set_enable_encrypted_rtp_header_extensions(true);
SetAudioVideoRtpHeaderExtensions(MAKE_VECTOR(kAudioRtpExtension1), f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
MAKE_VECTOR(kVideoRtpExtension1), &opts); f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL); std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
ASSERT_TRUE(offer.get() != NULL); ASSERT_TRUE(offer.get() != NULL);
SetAudioVideoRtpHeaderExtensions(MAKE_VECTOR(kAudioRtpExtension2),
MAKE_VECTOR(kVideoRtpExtension2), &opts);
std::unique_ptr<SessionDescription> answer = std::unique_ptr<SessionDescription> answer =
f2_.CreateAnswer(offer.get(), opts, NULL); f2_.CreateAnswer(offer.get(), opts, NULL);
@ -2037,12 +1901,13 @@ TEST_F(MediaSessionDescriptionFactoryTest,
f1_.set_enable_encrypted_rtp_header_extensions(true); f1_.set_enable_encrypted_rtp_header_extensions(true);
SetAudioVideoRtpHeaderExtensions(MAKE_VECTOR(kAudioRtpExtension1), f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
MAKE_VECTOR(kVideoRtpExtension1), &opts); f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL); std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
ASSERT_TRUE(offer.get() != NULL); ASSERT_TRUE(offer.get() != NULL);
SetAudioVideoRtpHeaderExtensions(MAKE_VECTOR(kAudioRtpExtension2),
MAKE_VECTOR(kVideoRtpExtension2), &opts);
std::unique_ptr<SessionDescription> answer = std::unique_ptr<SessionDescription> answer =
f2_.CreateAnswer(offer.get(), opts, NULL); f2_.CreateAnswer(offer.get(), opts, NULL);
@ -2067,12 +1932,13 @@ TEST_F(MediaSessionDescriptionFactoryTest,
f2_.set_enable_encrypted_rtp_header_extensions(true); f2_.set_enable_encrypted_rtp_header_extensions(true);
SetAudioVideoRtpHeaderExtensions(MAKE_VECTOR(kAudioRtpExtension1), f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
MAKE_VECTOR(kVideoRtpExtension1), &opts); f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL); std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
ASSERT_TRUE(offer.get() != NULL); ASSERT_TRUE(offer.get() != NULL);
SetAudioVideoRtpHeaderExtensions(MAKE_VECTOR(kAudioRtpExtension2),
MAKE_VECTOR(kVideoRtpExtension2), &opts);
std::unique_ptr<SessionDescription> answer = std::unique_ptr<SessionDescription> answer =
f2_.CreateAnswer(offer.get(), opts, NULL); f2_.CreateAnswer(offer.get(), opts, NULL);
@ -3474,11 +3340,12 @@ TEST_F(MediaSessionDescriptionFactoryTest,
MediaSessionOptions opts; MediaSessionOptions opts;
AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts); AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
SetAudioVideoRtpHeaderExtensions(MAKE_VECTOR(kAudioRtpExtension1), f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
MAKE_VECTOR(kVideoRtpExtension1), &opts); f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL); std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
SetAudioVideoRtpHeaderExtensions(MAKE_VECTOR(kAudioRtpExtension2),
MAKE_VECTOR(kVideoRtpExtension2), &opts);
std::unique_ptr<SessionDescription> answer = std::unique_ptr<SessionDescription> answer =
f2_.CreateAnswer(offer.get(), opts, NULL); f2_.CreateAnswer(offer.get(), opts, NULL);
@ -3529,8 +3396,9 @@ TEST_F(MediaSessionDescriptionFactoryTest, RtpExtensionIdReused) {
MediaSessionOptions opts; MediaSessionOptions opts;
AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts); AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
SetAudioVideoRtpHeaderExtensions(MAKE_VECTOR(kAudioRtpExtension3), f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension3));
MAKE_VECTOR(kVideoRtpExtension3), &opts); f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension3));
std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL); std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
// Since the audio extensions used ID 3 for "both_audio_and_video", so should // Since the audio extensions used ID 3 for "both_audio_and_video", so should
@ -3567,9 +3435,11 @@ TEST_F(MediaSessionDescriptionFactoryTest, RtpExtensionIdReusedEncrypted) {
f1_.set_enable_encrypted_rtp_header_extensions(true); f1_.set_enable_encrypted_rtp_header_extensions(true);
f2_.set_enable_encrypted_rtp_header_extensions(true); f2_.set_enable_encrypted_rtp_header_extensions(true);
SetAudioVideoRtpHeaderExtensions( f1_.set_audio_rtp_header_extensions(
MAKE_VECTOR(kAudioRtpExtension3ForEncryption), MAKE_VECTOR(kAudioRtpExtension3ForEncryption));
MAKE_VECTOR(kVideoRtpExtension3ForEncryption), &opts); f1_.set_video_rtp_header_extensions(
MAKE_VECTOR(kVideoRtpExtension3ForEncryption));
std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL); std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
// The extensions that are shared between audio and video should use the same // The extensions that are shared between audio and video should use the same

View file

@ -5020,21 +5020,21 @@ void PeerConnection::GetOptionsForPlanBOffer(
// Add audio/video/data m= sections to the end if needed. // Add audio/video/data m= sections to the end if needed.
if (!audio_index && offer_new_audio_description) { if (!audio_index && offer_new_audio_description) {
cricket::MediaDescriptionOptions options( session_options->media_description_options.push_back(
cricket::MEDIA_TYPE_AUDIO, cricket::CN_AUDIO, cricket::MediaDescriptionOptions(
RtpTransceiverDirectionFromSendRecv(send_audio, recv_audio), false); cricket::MEDIA_TYPE_AUDIO, cricket::CN_AUDIO,
options.header_extensions = RtpTransceiverDirectionFromSendRecv(send_audio, recv_audio),
channel_manager()->GetSupportedAudioRtpHeaderExtensions(); false));
session_options->media_description_options.push_back(options);
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) {
cricket::MediaDescriptionOptions options( session_options->media_description_options.push_back(
cricket::MEDIA_TYPE_VIDEO, cricket::CN_VIDEO, cricket::MediaDescriptionOptions(
RtpTransceiverDirectionFromSendRecv(send_video, recv_video), false); cricket::MEDIA_TYPE_VIDEO, cricket::CN_VIDEO,
options.header_extensions = RtpTransceiverDirectionFromSendRecv(send_video, recv_video),
channel_manager()->GetSupportedVideoRtpHeaderExtensions(); false));
session_options->media_description_options.push_back(options);
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) {
@ -5066,8 +5066,6 @@ GetMediaDescriptionOptionsForTransceiver(
transceiver->stopped()); transceiver->stopped());
media_description_options.codec_preferences = media_description_options.codec_preferences =
transceiver->codec_preferences(); transceiver->codec_preferences();
media_description_options.header_extensions =
transceiver->HeaderExtensionsToOffer();
// This behavior is specified in JSEP. The gist is that: // This behavior is specified in JSEP. The gist is that:
// 1. The MSID is included if the RtpTransceiver's direction is sendonly or // 1. The MSID is included if the RtpTransceiver's direction is sendonly or
// sendrecv. // sendrecv.
@ -5399,8 +5397,6 @@ void PeerConnection::GenerateMediaDescriptionOptions(
stopped)); stopped));
*audio_index = session_options->media_description_options.size() - 1; *audio_index = session_options->media_description_options.size() - 1;
} }
session_options->media_description_options.back().header_extensions =
channel_manager()->GetSupportedAudioRtpHeaderExtensions();
} else if (IsVideoContent(&content)) { } else if (IsVideoContent(&content)) {
// If we already have an video m= section, reject this extra one. // If we already have an video m= section, reject this extra one.
if (*video_index) { if (*video_index) {
@ -5416,8 +5412,6 @@ void PeerConnection::GenerateMediaDescriptionOptions(
stopped)); stopped));
*video_index = session_options->media_description_options.size() - 1; *video_index = session_options->media_description_options.size() - 1;
} }
session_options->media_description_options.back().header_extensions =
channel_manager()->GetSupportedVideoRtpHeaderExtensions();
} else { } else {
RTC_DCHECK(IsDataContent(&content)); RTC_DCHECK(IsDataContent(&content));
// If we already have an data m= section, reject this extra one. // If we already have an data m= section, reject this extra one.

View file

@ -33,31 +33,16 @@ class PeerConnectionHeaderExtensionTest
: public ::testing::TestWithParam< : public ::testing::TestWithParam<
std::tuple<cricket::MediaType, SdpSemantics>> { std::tuple<cricket::MediaType, SdpSemantics>> {
protected: protected:
PeerConnectionHeaderExtensionTest()
: 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> CreatePeerConnection( std::unique_ptr<PeerConnectionWrapper> CreatePeerConnection(
cricket::MediaType media_type, cricket::MediaType media_type,
absl::optional<SdpSemantics> semantics) { absl::optional<SdpSemantics> semantics,
std::vector<RtpHeaderExtensionCapability> extensions) {
auto voice = std::make_unique<cricket::FakeVoiceEngine>(); auto voice = std::make_unique<cricket::FakeVoiceEngine>();
auto video = std::make_unique<cricket::FakeVideoEngine>(); auto video = std::make_unique<cricket::FakeVideoEngine>();
if (media_type == cricket::MediaType::MEDIA_TYPE_AUDIO) if (media_type == cricket::MediaType::MEDIA_TYPE_AUDIO)
voice->SetRtpHeaderExtensions(extensions_); voice->SetRtpHeaderExtensions(extensions);
else else
video->SetRtpHeaderExtensions(extensions_); video->SetRtpHeaderExtensions(extensions);
auto media_engine = std::make_unique<cricket::CompositeMediaEngine>( auto media_engine = std::make_unique<cricket::CompositeMediaEngine>(
std::move(voice), std::move(video)); std::move(voice), std::move(video));
PeerConnectionFactoryDependencies factory_dependencies; PeerConnectionFactoryDependencies factory_dependencies;
@ -86,8 +71,6 @@ class PeerConnectionHeaderExtensionTest
return std::make_unique<PeerConnectionWrapper>(pc_factory, pc, return std::make_unique<PeerConnectionWrapper>(pc_factory, pc,
std::move(observer)); std::move(observer));
} }
std::vector<RtpHeaderExtensionCapability> extensions_;
}; };
TEST_P(PeerConnectionHeaderExtensionTest, TransceiverOffersHeaderExtensions) { TEST_P(PeerConnectionHeaderExtensionTest, TransceiverOffersHeaderExtensions) {
@ -96,10 +79,19 @@ TEST_P(PeerConnectionHeaderExtensionTest, TransceiverOffersHeaderExtensions) {
std::tie(media_type, semantics) = GetParam(); std::tie(media_type, semantics) = GetParam();
if (semantics != SdpSemantics::kUnifiedPlan) if (semantics != SdpSemantics::kUnifiedPlan)
return; 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 = std::unique_ptr<PeerConnectionWrapper> wrapper =
CreatePeerConnection(media_type, semantics); CreatePeerConnection(media_type, semantics, extensions);
auto transceiver = wrapper->AddTransceiver(media_type); auto transceiver = wrapper->AddTransceiver(media_type);
EXPECT_EQ(transceiver->HeaderExtensionsToOffer(), extensions_); EXPECT_EQ(transceiver->HeaderExtensionsToOffer(), extensions);
} }
TEST_P(PeerConnectionHeaderExtensionTest, TEST_P(PeerConnectionHeaderExtensionTest,
@ -107,14 +99,20 @@ TEST_P(PeerConnectionHeaderExtensionTest,
cricket::MediaType media_type; cricket::MediaType media_type;
SdpSemantics semantics; SdpSemantics semantics;
std::tie(media_type, semantics) = GetParam(); std::tie(media_type, semantics) = GetParam();
std::unique_ptr<PeerConnectionWrapper> wrapper = std::unique_ptr<PeerConnectionWrapper> wrapper = CreatePeerConnection(
CreatePeerConnection(media_type, semantics); 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() EXPECT_THAT(wrapper->pc_factory()
->GetRtpSenderCapabilities(media_type) ->GetRtpSenderCapabilities(media_type)
.header_extensions, .header_extensions,
ElementsAre(Field(&RtpHeaderExtensionCapability::uri, "uri2"), ElementsAre(Field(&RtpHeaderExtensionCapability::uri, "uri1"),
Field(&RtpHeaderExtensionCapability::uri, "uri3"), Field(&RtpHeaderExtensionCapability::uri, "uri3")));
Field(&RtpHeaderExtensionCapability::uri, "uri4")));
EXPECT_EQ(wrapper->pc_factory() EXPECT_EQ(wrapper->pc_factory()
->GetRtpReceiverCapabilities(media_type) ->GetRtpReceiverCapabilities(media_type)
.header_extensions, .header_extensions,
@ -123,49 +121,6 @@ TEST_P(PeerConnectionHeaderExtensionTest,
.header_extensions); .header_extensions);
} }
TEST_P(PeerConnectionHeaderExtensionTest, OffersUnstoppedDefaultExtensions) {
cricket::MediaType media_type;
SdpSemantics semantics;
std::tie(media_type, semantics) = GetParam();
if (semantics != SdpSemantics::kUnifiedPlan)
return;
std::unique_ptr<PeerConnectionWrapper> wrapper =
CreatePeerConnection(media_type, semantics);
auto transceiver = wrapper->AddTransceiver(media_type);
auto session_description = wrapper->CreateOffer();
EXPECT_THAT(session_description->description()
->contents()[0]
.media_description()
->rtp_header_extensions(),
ElementsAre(Field(&RtpExtension::uri, "uri2"),
Field(&RtpExtension::uri, "uri3"),
Field(&RtpExtension::uri, "uri4")));
}
TEST_P(PeerConnectionHeaderExtensionTest, OffersUnstoppedModifiedExtensions) {
cricket::MediaType media_type;
SdpSemantics semantics;
std::tie(media_type, semantics) = GetParam();
if (semantics != SdpSemantics::kUnifiedPlan)
return;
std::unique_ptr<PeerConnectionWrapper> wrapper =
CreatePeerConnection(media_type, semantics);
auto transceiver = wrapper->AddTransceiver(media_type);
auto modified_extensions = transceiver->HeaderExtensionsToOffer();
modified_extensions[0].direction = RtpTransceiverDirection::kSendRecv;
modified_extensions[3].direction = RtpTransceiverDirection::kStopped;
EXPECT_TRUE(
transceiver->SetOfferedRtpHeaderExtensions(modified_extensions).ok());
auto session_description = wrapper->CreateOffer();
EXPECT_THAT(session_description->description()
->contents()[0]
.media_description()
->rtp_header_extensions(),
ElementsAre(Field(&RtpExtension::uri, "uri1"),
Field(&RtpExtension::uri, "uri2"),
Field(&RtpExtension::uri, "uri3")));
}
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(
, ,
PeerConnectionHeaderExtensionTest, PeerConnectionHeaderExtensionTest,

View file

@ -114,7 +114,7 @@ RtpTransceiver::RtpTransceiver(
: unified_plan_(true), : unified_plan_(true),
media_type_(sender->media_type()), media_type_(sender->media_type()),
channel_manager_(channel_manager), channel_manager_(channel_manager),
header_extensions_to_offer_(std::move(header_extensions_offered)) { 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());
@ -356,51 +356,7 @@ RTCError RtpTransceiver::SetCodecPreferences(
std::vector<RtpHeaderExtensionCapability> std::vector<RtpHeaderExtensionCapability>
RtpTransceiver::HeaderExtensionsToOffer() const { RtpTransceiver::HeaderExtensionsToOffer() const {
return header_extensions_to_offer_; return HeaderExtensionsToOffer_;
}
RTCError RtpTransceiver::SetOfferedRtpHeaderExtensions(
rtc::ArrayView<const RtpHeaderExtensionCapability>
header_extensions_to_offer) {
for (const auto& entry : header_extensions_to_offer) {
// Handle unsupported requests for mandatory extensions as per
// https://w3c.github.io/webrtc-extensions/#rtcrtptransceiver-interface.
// Note:
// - We do not handle setOfferedRtpHeaderExtensions algorithm step 2.1,
// this has to be checked on a higher level. We naturally error out
// in the handling of Step 2.2 if an unset URI is encountered.
// Step 2.2.
// Handle unknown extensions.
auto it = std::find_if(
header_extensions_to_offer_.begin(), header_extensions_to_offer_.end(),
[&entry](const auto& offered) { return entry.uri == offered.uri; });
if (it == header_extensions_to_offer_.end()) {
return RTCError(RTCErrorType::INVALID_PARAMETER,
"Attempted to modify an unoffered extension.");
}
// Step 2.4-2.5.
// - Use of the transceiver interface indicates unified plan is in effect,
// hence the MID extension needs to be enabled.
// - Also handle the mandatory video orientation extensions.
if ((entry.uri == RtpExtension::kMidUri ||
entry.uri == RtpExtension::kVideoRotationUri) &&
entry.direction != RtpTransceiverDirection::kSendRecv) {
return RTCError(RTCErrorType::INVALID_MODIFICATION,
"Attempted to stop a mandatory extension.");
}
}
// Apply mutation after error checking.
for (const auto& entry : header_extensions_to_offer) {
auto it = std::find_if(
header_extensions_to_offer_.begin(), header_extensions_to_offer_.end(),
[&entry](const auto& offered) { return entry.uri == offered.uri; });
it->direction = entry.direction;
}
return RTCError::OK();
} }
} // namespace webrtc } // namespace webrtc

View file

@ -195,9 +195,6 @@ class RtpTransceiver final
} }
std::vector<RtpHeaderExtensionCapability> HeaderExtensionsToOffer() std::vector<RtpHeaderExtensionCapability> HeaderExtensionsToOffer()
const override; const override;
RTCError SetOfferedRtpHeaderExtensions(
rtc::ArrayView<const RtpHeaderExtensionCapability>
header_extensions_to_offer) override;
private: private:
void OnFirstPacketReceived(cricket::ChannelInterface* channel); void OnFirstPacketReceived(cricket::ChannelInterface* channel);
@ -223,7 +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> header_extensions_to_offer_; std::vector<RtpHeaderExtensionCapability> HeaderExtensionsToOffer_;
}; };
BEGIN_SIGNALING_PROXY_MAP(RtpTransceiver) BEGIN_SIGNALING_PROXY_MAP(RtpTransceiver)
@ -244,9 +241,6 @@ PROXY_METHOD1(webrtc::RTCError,
PROXY_CONSTMETHOD0(std::vector<RtpCodecCapability>, codec_preferences) PROXY_CONSTMETHOD0(std::vector<RtpCodecCapability>, codec_preferences)
PROXY_CONSTMETHOD0(std::vector<RtpHeaderExtensionCapability>, PROXY_CONSTMETHOD0(std::vector<RtpHeaderExtensionCapability>,
HeaderExtensionsToOffer) HeaderExtensionsToOffer)
PROXY_METHOD1(webrtc::RTCError,
SetOfferedRtpHeaderExtensions,
rtc::ArrayView<const RtpHeaderExtensionCapability>)
END_PROXY_MAP() END_PROXY_MAP()
} // namespace webrtc } // namespace webrtc

View file

@ -25,7 +25,6 @@ using ::testing::ElementsAre;
using ::testing::Eq; using ::testing::Eq;
using ::testing::Field; using ::testing::Field;
using ::testing::Not; using ::testing::Not;
using ::testing::Property;
using ::testing::Return; using ::testing::Return;
using ::testing::ReturnRef; using ::testing::ReturnRef;
@ -79,95 +78,27 @@ TEST(RtpTransceiverTest, CanUnsetChannelOnStoppedTransceiver) {
EXPECT_EQ(nullptr, transceiver.channel()); EXPECT_EQ(nullptr, transceiver.channel());
} }
class RtpTransceiverTestForHeaderExtensions : public ::testing::Test { TEST(RtpTransceiverTest,
public: InitsWithChannelManagerRtpHeaderExtensionCapabilities) {
RtpTransceiverTestForHeaderExtensions() cricket::ChannelManager channel_manager(
: channel_manager_(std::make_unique<cricket::FakeMediaEngine>(), std::make_unique<cricket::FakeMediaEngine>(),
std::make_unique<cricket::FakeDataEngine>(), std::make_unique<cricket::FakeDataEngine>(), rtc::Thread::Current(),
rtc::Thread::Current(), rtc::Thread::Current());
rtc::Thread::Current()), std::vector<RtpHeaderExtensionCapability> extensions({
extensions_( RtpHeaderExtensionCapability("uri1", 1,
{RtpHeaderExtensionCapability("uri1", RtpTransceiverDirection::kSendRecv),
1, RtpHeaderExtensionCapability("uri2", 2,
RtpTransceiverDirection::kSendOnly), RtpTransceiverDirection::kRecvOnly),
RtpHeaderExtensionCapability("uri2", });
2, RtpTransceiver transceiver(
RtpTransceiverDirection::kRecvOnly), RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
RtpHeaderExtensionCapability(RtpExtension::kMidUri, rtc::Thread::Current(),
3, new rtc::RefCountedObject<MockRtpSenderInternal>()),
RtpTransceiverDirection::kSendRecv), RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
RtpHeaderExtensionCapability(RtpExtension::kVideoRotationUri, rtc::Thread::Current(),
4, new rtc::RefCountedObject<MockRtpReceiverInternal>()),
RtpTransceiverDirection::kSendRecv)}), &channel_manager, extensions);
transceiver_(RtpSenderProxyWithInternal<RtpSenderInternal>::Create( EXPECT_EQ(transceiver.HeaderExtensionsToOffer(), extensions);
rtc::Thread::Current(),
new rtc::RefCountedObject<MockRtpSenderInternal>()),
RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
rtc::Thread::Current(),
new rtc::RefCountedObject<MockRtpReceiverInternal>()),
&channel_manager_,
extensions_) {}
cricket::ChannelManager channel_manager_;
std::vector<RtpHeaderExtensionCapability> extensions_;
RtpTransceiver transceiver_;
};
TEST_F(RtpTransceiverTestForHeaderExtensions, OffersChannelManagerList) {
EXPECT_EQ(transceiver_.HeaderExtensionsToOffer(), extensions_);
}
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);
modified_extensions[0].direction = RtpTransceiverDirection::kRecvOnly;
EXPECT_TRUE(
transceiver_.SetOfferedRtpHeaderExtensions(modified_extensions).ok());
EXPECT_EQ(transceiver_.HeaderExtensionsToOffer(), modified_extensions);
modified_extensions[0].direction = RtpTransceiverDirection::kSendRecv;
EXPECT_TRUE(
transceiver_.SetOfferedRtpHeaderExtensions(modified_extensions).ok());
EXPECT_EQ(transceiver_.HeaderExtensionsToOffer(), modified_extensions);
modified_extensions[0].direction = RtpTransceiverDirection::kInactive;
EXPECT_TRUE(
transceiver_.SetOfferedRtpHeaderExtensions(modified_extensions).ok());
EXPECT_EQ(transceiver_.HeaderExtensionsToOffer(), modified_extensions);
}
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);
}
TEST_F(RtpTransceiverTestForHeaderExtensions, RejectsUnsupportedExtension) {
std::vector<RtpHeaderExtensionCapability> modified_extensions(
{RtpHeaderExtensionCapability("uri3", 1,
RtpTransceiverDirection::kSendRecv)});
EXPECT_THAT(transceiver_.SetOfferedRtpHeaderExtensions(modified_extensions),
Property(&RTCError::type, RTCErrorType::INVALID_PARAMETER));
EXPECT_EQ(transceiver_.HeaderExtensionsToOffer(), extensions_);
}
TEST_F(RtpTransceiverTestForHeaderExtensions,
RejectsStoppedMandatoryExtensions) {
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),
Property(&RTCError::type, RTCErrorType::INVALID_MODIFICATION));
EXPECT_EQ(transceiver_.HeaderExtensionsToOffer(), extensions_);
modified_extensions = extensions_;
// Attempting to stop the mandatory video orientation extension.
modified_extensions[3].direction = RtpTransceiverDirection::kStopped;
EXPECT_THAT(transceiver_.SetOfferedRtpHeaderExtensions(modified_extensions),
Property(&RTCError::type, RTCErrorType::INVALID_MODIFICATION));
EXPECT_EQ(transceiver_.HeaderExtensionsToOffer(), extensions_);
} }
} // namespace webrtc } // namespace webrtc