From 4e8c1159608ef44460edfa8fabb8e705f4490fc7 Mon Sep 17 00:00:00 2001 From: Philipp Hancke Date: Tue, 13 Oct 2020 12:43:15 +0200 Subject: [PATCH] Reland "introduce an unsupported content description type" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a reland of 239f92ecf7fc8ca27e0376dd192b33ce33377b3c Original change's description: > introduce an unsupported content description type > > This carries around unsupported content descriptions > (i.e. things where webrtc does not understand the media type > or protocol) in a special data type so that a rejected content or > mediasection is added to the answer SDP. > > BUG=webrtc:3513 > > Change-Id: Ifc4168eae11e899f2504649de5e1eecb6801a9fb > Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/179082 > Reviewed-by: Kári Helgason > Reviewed-by: Harald Alvestrand > Commit-Queue: Philipp Hancke > Cr-Commit-Position: refs/heads/master@{#32410} Bug: webrtc:3513 Change-Id: I48e338100f829f1df5b8165217c89b5ef860fe79 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/188820 Reviewed-by: Harald Alvestrand Reviewed-by: Kári Helgason Commit-Queue: Harald Alvestrand Cr-Commit-Position: refs/heads/master@{#32457} --- api/media_types.cc | 4 + api/media_types.h | 7 +- pc/media_session.cc | 80 +++++++++++++++++++ pc/media_session.h | 20 +++++ pc/peer_connection_factory.cc | 4 + pc/peer_connection_signaling_unittest.cc | 60 ++++++++++++++ pc/rtc_stats_collector_unittest.cc | 2 + pc/sdp_offer_answer.cc | 22 +++++ pc/session_description.h | 38 ++++++++- pc/webrtc_sdp.cc | 43 ++++++---- pc/webrtc_sdp_unittest.cc | 30 ++++--- .../peerconnection/RTCRtpCodecParameters.mm | 3 + sdk/objc/api/peerconnection/RTCRtpReceiver.h | 1 + sdk/objc/api/peerconnection/RTCRtpReceiver.mm | 6 ++ 14 files changed, 291 insertions(+), 29 deletions(-) diff --git a/api/media_types.cc b/api/media_types.cc index 6bc693860d..c7635b52de 100644 --- a/api/media_types.cc +++ b/api/media_types.cc @@ -26,6 +26,10 @@ std::string MediaTypeToString(MediaType type) { return kMediaTypeVideo; case MEDIA_TYPE_DATA: return kMediaTypeData; + case MEDIA_TYPE_UNSUPPORTED: + // Unsupported media stores the m= differently. + RTC_NOTREACHED(); + return ""; } FATAL(); // Not reachable; avoids compile warning. diff --git a/api/media_types.h b/api/media_types.h index 8c6ba3d1ed..b2ff08c0c3 100644 --- a/api/media_types.h +++ b/api/media_types.h @@ -20,7 +20,12 @@ namespace cricket { -enum MediaType { MEDIA_TYPE_AUDIO, MEDIA_TYPE_VIDEO, MEDIA_TYPE_DATA }; +enum MediaType { + MEDIA_TYPE_AUDIO, + MEDIA_TYPE_VIDEO, + MEDIA_TYPE_DATA, + MEDIA_TYPE_UNSUPPORTED +}; extern const char kMediaTypeAudio[]; extern const char kMediaTypeVideo[]; diff --git a/pc/media_session.cc b/pc/media_session.cc index 0cff84d79b..8c757cd722 100644 --- a/pc/media_session.cc +++ b/pc/media_session.cc @@ -1559,6 +1559,13 @@ std::unique_ptr MediaSessionDescriptionFactory::CreateOffer( return nullptr; } break; + case MEDIA_TYPE_UNSUPPORTED: + if (!AddUnsupportedContentForOffer( + media_description_options, session_options, current_content, + current_description, offer.get(), &ice_credentials)) { + return nullptr; + } + break; default: RTC_NOTREACHED(); } @@ -1713,6 +1720,14 @@ MediaSessionDescriptionFactory::CreateAnswer( return nullptr; } break; + case MEDIA_TYPE_UNSUPPORTED: + if (!AddUnsupportedContentForAnswer( + media_description_options, session_options, offer_content, + offer, current_content, current_description, + bundle_transport.get(), answer.get(), &ice_credentials)) { + return nullptr; + } + break; default: RTC_NOTREACHED(); } @@ -2403,6 +2418,31 @@ bool MediaSessionDescriptionFactory::AddDataContentForOffer( } } +bool MediaSessionDescriptionFactory::AddUnsupportedContentForOffer( + const MediaDescriptionOptions& media_description_options, + const MediaSessionOptions& session_options, + const ContentInfo* current_content, + const SessionDescription* current_description, + SessionDescription* desc, + IceCredentialsIterator* ice_credentials) const { + RTC_CHECK(IsMediaContentOfType(current_content, MEDIA_TYPE_UNSUPPORTED)); + + const UnsupportedContentDescription* current_unsupported_description = + current_content->media_description()->as_unsupported(); + auto unsupported = std::make_unique( + current_unsupported_description->media_type()); + unsupported->set_protocol(current_content->media_description()->protocol()); + desc->AddContent(media_description_options.mid, MediaProtocolType::kOther, + /*rejected=*/true, std::move(unsupported)); + + if (!AddTransportOffer(media_description_options.mid, + media_description_options.transport_options, + current_description, desc, ice_credentials)) { + return false; + } + return true; +} + // |audio_codecs| = set of all possible codecs that can be used, with correct // payload type mappings // @@ -2745,6 +2785,42 @@ bool MediaSessionDescriptionFactory::AddDataContentForAnswer( return true; } +bool MediaSessionDescriptionFactory::AddUnsupportedContentForAnswer( + const MediaDescriptionOptions& media_description_options, + const MediaSessionOptions& session_options, + const ContentInfo* offer_content, + const SessionDescription* offer_description, + const ContentInfo* current_content, + const SessionDescription* current_description, + const TransportInfo* bundle_transport, + SessionDescription* answer, + IceCredentialsIterator* ice_credentials) const { + std::unique_ptr unsupported_transport = + CreateTransportAnswer(media_description_options.mid, offer_description, + media_description_options.transport_options, + current_description, bundle_transport != nullptr, + ice_credentials); + if (!unsupported_transport) { + return false; + } + RTC_CHECK(IsMediaContentOfType(offer_content, MEDIA_TYPE_UNSUPPORTED)); + + const UnsupportedContentDescription* offer_unsupported_description = + offer_content->media_description()->as_unsupported(); + std::unique_ptr unsupported_answer = + std::make_unique( + offer_unsupported_description->media_type()); + unsupported_answer->set_protocol(offer_unsupported_description->protocol()); + + if (!AddTransportAnswer(media_description_options.mid, + *(unsupported_transport.get()), answer)) { + return false; + } + answer->AddContent(media_description_options.mid, offer_content->type, + /*rejected=*/true, std::move(unsupported_answer)); + return true; +} + void MediaSessionDescriptionFactory::ComputeAudioCodecsIntersectionAndUnion() { audio_sendrecv_codecs_.clear(); all_audio_codecs_.clear(); @@ -2822,6 +2898,10 @@ bool IsDataContent(const ContentInfo* content) { return IsMediaContentOfType(content, MEDIA_TYPE_DATA); } +bool IsUnsupportedContent(const ContentInfo* content) { + return IsMediaContentOfType(content, MEDIA_TYPE_UNSUPPORTED); +} + const ContentInfo* GetFirstMediaContent(const ContentInfos& contents, MediaType media_type) { for (const ContentInfo& content : contents) { diff --git a/pc/media_session.h b/pc/media_session.h index f305a6214c..58a31a2ab2 100644 --- a/pc/media_session.h +++ b/pc/media_session.h @@ -283,6 +283,14 @@ class MediaSessionDescriptionFactory { SessionDescription* desc, IceCredentialsIterator* ice_credentials) const; + bool AddUnsupportedContentForOffer( + const MediaDescriptionOptions& media_description_options, + const MediaSessionOptions& session_options, + const ContentInfo* current_content, + const SessionDescription* current_description, + SessionDescription* desc, + IceCredentialsIterator* ice_credentials) const; + bool AddAudioContentForAnswer( const MediaDescriptionOptions& media_description_options, const MediaSessionOptions& session_options, @@ -324,6 +332,17 @@ class MediaSessionDescriptionFactory { SessionDescription* answer, IceCredentialsIterator* ice_credentials) const; + bool AddUnsupportedContentForAnswer( + const MediaDescriptionOptions& media_description_options, + const MediaSessionOptions& session_options, + const ContentInfo* offer_content, + const SessionDescription* offer_description, + const ContentInfo* current_content, + const SessionDescription* current_description, + const TransportInfo* bundle_transport, + SessionDescription* answer, + IceCredentialsIterator* ice_credentials) const; + void ComputeAudioCodecsIntersectionAndUnion(); void ComputeVideoCodecsIntersectionAndUnion(); @@ -356,6 +375,7 @@ bool IsMediaContent(const ContentInfo* content); bool IsAudioContent(const ContentInfo* content); bool IsVideoContent(const ContentInfo* content); bool IsDataContent(const ContentInfo* content); +bool IsUnsupportedContent(const ContentInfo* content); const ContentInfo* GetFirstMediaContent(const ContentInfos& contents, MediaType media_type); const ContentInfo* GetFirstAudioContent(const ContentInfos& contents); diff --git a/pc/peer_connection_factory.cc b/pc/peer_connection_factory.cc index ba81c29901..8a998481c1 100644 --- a/pc/peer_connection_factory.cc +++ b/pc/peer_connection_factory.cc @@ -137,6 +137,8 @@ RtpCapabilities PeerConnectionFactory::GetRtpSenderCapabilities( } case cricket::MEDIA_TYPE_DATA: return RtpCapabilities(); + case cricket::MEDIA_TYPE_UNSUPPORTED: + return RtpCapabilities(); } // Not reached; avoids compile warning. FATAL(); @@ -162,6 +164,8 @@ RtpCapabilities PeerConnectionFactory::GetRtpReceiverCapabilities( } case cricket::MEDIA_TYPE_DATA: return RtpCapabilities(); + case cricket::MEDIA_TYPE_UNSUPPORTED: + return RtpCapabilities(); } // Not reached; avoids compile warning. FATAL(); diff --git a/pc/peer_connection_signaling_unittest.cc b/pc/peer_connection_signaling_unittest.cc index 9a89fceab2..605a1338c6 100644 --- a/pc/peer_connection_signaling_unittest.cc +++ b/pc/peer_connection_signaling_unittest.cc @@ -17,12 +17,14 @@ #include "api/audio_codecs/builtin_audio_decoder_factory.h" #include "api/audio_codecs/builtin_audio_encoder_factory.h" #include "api/create_peerconnection_factory.h" +#include "api/jsep_session_description.h" #include "api/peer_connection_proxy.h" #include "api/video_codecs/builtin_video_decoder_factory.h" #include "api/video_codecs/builtin_video_encoder_factory.h" #include "pc/peer_connection.h" #include "pc/peer_connection_wrapper.h" #include "pc/sdp_utils.h" +#include "pc/webrtc_sdp.h" #ifdef WEBRTC_ANDROID #include "pc/test/android_test_initializer.h" #endif @@ -841,6 +843,64 @@ TEST_P(PeerConnectionSignalingTest, observer->error()); } +TEST_P(PeerConnectionSignalingTest, UnsupportedContentType) { + auto caller = CreatePeerConnection(); + + // Call setRemoteDescription with a m= line we don't understand. + std::string sdp = + "v=0\r\n" + "o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1\r\n" + "s=-\r\n" + "t=0 0\r\n" + "m=bogus 9 FOO 0 8\r\n" + "c=IN IP4 0.0.0.0\r\n" + "a=mid:bogusmid\r\n"; + std::unique_ptr remote_description = + webrtc::CreateSessionDescription(SdpType::kOffer, sdp, nullptr); + + EXPECT_TRUE(caller->SetRemoteDescription(std::move(remote_description))); + + // Assert we respond back with something meaningful. + auto answer = caller->CreateAnswer(); + ASSERT_EQ(answer->description()->contents().size(), 1u); + EXPECT_NE(answer->description() + ->contents()[0] + .media_description() + ->as_unsupported(), + nullptr); + EXPECT_EQ(answer->description() + ->contents()[0] + .media_description() + ->as_unsupported() + ->media_type(), + "bogus"); + EXPECT_TRUE(answer->description()->contents()[0].rejected); + EXPECT_EQ(answer->description()->contents()[0].mid(), "bogusmid"); + EXPECT_EQ( + answer->description()->contents()[0].media_description()->protocol(), + "FOO"); + EXPECT_FALSE( + answer->description()->contents()[0].media_description()->has_codecs()); + + EXPECT_TRUE(caller->SetLocalDescription(std::move(answer))); + + // Assert we keep this in susequent offers. + auto offer = caller->CreateOffer(); + EXPECT_EQ(offer->description() + ->contents()[0] + .media_description() + ->as_unsupported() + ->media_type(), + "bogus"); + EXPECT_TRUE(offer->description()->contents()[0].rejected); + EXPECT_EQ(offer->description()->contents()[0].media_description()->protocol(), + "FOO"); + EXPECT_EQ(offer->description()->contents()[0].mid(), "bogusmid"); + EXPECT_FALSE( + offer->description()->contents()[0].media_description()->has_codecs()); + EXPECT_TRUE(caller->SetLocalDescription(std::move(offer))); +} + INSTANTIATE_TEST_SUITE_P(PeerConnectionSignalingTest, PeerConnectionSignalingTest, Values(SdpSemantics::kPlanB, diff --git a/pc/rtc_stats_collector_unittest.cc b/pc/rtc_stats_collector_unittest.cc index 6d71e2acd1..b0b7254e9c 100644 --- a/pc/rtc_stats_collector_unittest.cc +++ b/pc/rtc_stats_collector_unittest.cc @@ -2597,6 +2597,7 @@ class RTCStatsCollectorTestWithParamKind case cricket::MEDIA_TYPE_VIDEO: return "Video"; case cricket::MEDIA_TYPE_DATA: + case cricket::MEDIA_TYPE_UNSUPPORTED: RTC_NOTREACHED(); return ""; } @@ -2655,6 +2656,7 @@ class RTCStatsCollectorTestWithParamKind return; } case cricket::MEDIA_TYPE_DATA: + case cricket::MEDIA_TYPE_UNSUPPORTED: RTC_NOTREACHED(); } } diff --git a/pc/sdp_offer_answer.cc b/pc/sdp_offer_answer.cc index 5197a69025..b40d00c72a 100644 --- a/pc/sdp_offer_answer.cc +++ b/pc/sdp_offer_answer.cc @@ -562,6 +562,8 @@ static absl::string_view GetDefaultMidForPlanB(cricket::MediaType media_type) { return cricket::CN_VIDEO; case cricket::MEDIA_TYPE_DATA: return cricket::CN_DATA; + case cricket::MEDIA_TYPE_UNSUPPORTED: + return "not supported"; } RTC_NOTREACHED(); return ""; @@ -3050,6 +3052,8 @@ RTCError SdpOfferAnswerHandler::UpdateTransceiversAndDataChannels( if (!error.ok()) { return error; } + } else if (media_type == cricket::MEDIA_TYPE_UNSUPPORTED) { + RTC_LOG(LS_INFO) << "Ignoring unsupported media type"; } else { LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR, "Unknown section type."); @@ -3592,6 +3596,12 @@ void SdpOfferAnswerHandler::GetOptionsForUnifiedPlanOffer( transceiver->internal()->set_mline_index(i); } } + } else if (media_type == cricket::MEDIA_TYPE_UNSUPPORTED) { + RTC_DCHECK(local_content->rejected); + session_options->media_description_options.push_back( + cricket::MediaDescriptionOptions(media_type, mid, + RtpTransceiverDirection::kInactive, + /*stopped=*/true)); } else { RTC_CHECK_EQ(cricket::MEDIA_TYPE_DATA, media_type); if (had_been_rejected) { @@ -3757,6 +3767,12 @@ void SdpOfferAnswerHandler::GetOptionsForUnifiedPlanAnswer( RtpTransceiverDirection::kInactive, /*stopped=*/true)); } + } else if (media_type == cricket::MEDIA_TYPE_UNSUPPORTED) { + RTC_DCHECK(content.rejected); + session_options->media_description_options.push_back( + cricket::MediaDescriptionOptions(media_type, content.name, + RtpTransceiverDirection::kInactive, + /*stopped=*/true)); } else { RTC_CHECK_EQ(cricket::MEDIA_TYPE_DATA, media_type); // Reject all data sections if data channels are disabled. @@ -4705,6 +4721,12 @@ void SdpOfferAnswerHandler::GenerateMediaDescriptionOptions( } session_options->media_description_options.back().header_extensions = channel_manager()->GetSupportedVideoRtpHeaderExtensions(); + } else if (IsUnsupportedContent(&content)) { + session_options->media_description_options.push_back( + cricket::MediaDescriptionOptions(cricket::MEDIA_TYPE_UNSUPPORTED, + content.name, + RtpTransceiverDirection::kInactive, + /*stopped=*/true)); } else { RTC_DCHECK(IsDataContent(&content)); // If we already have an data m= section, reject this extra one. diff --git a/pc/session_description.h b/pc/session_description.h index 53c981a346..52a3a1fe04 100644 --- a/pc/session_description.h +++ b/pc/session_description.h @@ -58,6 +58,7 @@ class AudioContentDescription; class VideoContentDescription; class RtpDataContentDescription; class SctpDataContentDescription; +class UnsupportedContentDescription; // Describes a session description media section. There are subclasses for each // media type (audio, video, data) that will have additional information. @@ -86,6 +87,11 @@ class MediaContentDescription { virtual SctpDataContentDescription* as_sctp() { return nullptr; } virtual const SctpDataContentDescription* as_sctp() const { return nullptr; } + virtual UnsupportedContentDescription* as_unsupported() { return nullptr; } + virtual const UnsupportedContentDescription* as_unsupported() const { + return nullptr; + } + virtual bool has_codecs() const = 0; // Copy operator that returns an unique_ptr. @@ -406,13 +412,37 @@ class SctpDataContentDescription : public MediaContentDescription { int max_message_size_ = 64 * 1024; }; +class UnsupportedContentDescription : public MediaContentDescription { + public: + explicit UnsupportedContentDescription(const std::string& media_type) + : media_type_(media_type) {} + MediaType type() const override { return MEDIA_TYPE_UNSUPPORTED; } + + UnsupportedContentDescription* as_unsupported() override { return this; } + const UnsupportedContentDescription* as_unsupported() const override { + return this; + } + + bool has_codecs() const override { return false; } + const std::string& media_type() const { return media_type_; } + + private: + UnsupportedContentDescription* CloneInternal() const override { + return new UnsupportedContentDescription(*this); + } + + std::string media_type_; +}; + // Protocol used for encoding media. This is the "top level" protocol that may // be wrapped by zero or many transport protocols (UDP, ICE, etc.). enum class MediaProtocolType { - kRtp, // Section will use the RTP protocol (e.g., for audio or video). - // https://tools.ietf.org/html/rfc3550 - kSctp // Section will use the SCTP protocol (e.g., for a data channel). - // https://tools.ietf.org/html/rfc4960 + kRtp, // Section will use the RTP protocol (e.g., for audio or video). + // https://tools.ietf.org/html/rfc3550 + kSctp, // Section will use the SCTP protocol (e.g., for a data channel). + // https://tools.ietf.org/html/rfc4960 + kOther // Section will use another top protocol which is not + // explicitly supported. }; // Represents a session description section. Most information about the section diff --git a/pc/webrtc_sdp.cc b/pc/webrtc_sdp.cc index 4af121ddc3..2f9b63175f 100644 --- a/pc/webrtc_sdp.cc +++ b/pc/webrtc_sdp.cc @@ -75,6 +75,7 @@ using cricket::StreamParams; using cricket::StreamParamsVec; using cricket::TransportDescription; using cricket::TransportInfo; +using cricket::UnsupportedContentDescription; using cricket::VideoContentDescription; using rtc::SocketAddress; @@ -276,9 +277,6 @@ static bool ParseSessionDescription(const std::string& message, rtc::SocketAddress* connection_addr, cricket::SessionDescription* desc, SdpParseError* error); -static bool ParseGroupAttribute(const std::string& line, - cricket::SessionDescription* desc, - SdpParseError* error); static bool ParseMediaDescription( const std::string& message, const TransportDescription& session_td, @@ -302,6 +300,9 @@ static bool ParseContent( TransportDescription* transport, std::vector>* candidates, SdpParseError* error); +static bool ParseGroupAttribute(const std::string& line, + cricket::SessionDescription* desc, + SdpParseError* error); static bool ParseSsrcAttribute(const std::string& line, SsrcInfoVec* ssrc_infos, int* msid_signaling, @@ -1346,30 +1347,24 @@ void BuildMediaDescription(const ContentInfo* content_info, // RFC 4566 // m= // fmt is a list of payload type numbers that MAY be used in the session. - const char* type = NULL; - if (media_type == cricket::MEDIA_TYPE_AUDIO) - type = kMediaTypeAudio; - else if (media_type == cricket::MEDIA_TYPE_VIDEO) - type = kMediaTypeVideo; - else if (media_type == cricket::MEDIA_TYPE_DATA) - type = kMediaTypeData; - else - RTC_NOTREACHED(); - + std::string type; std::string fmt; if (media_type == cricket::MEDIA_TYPE_VIDEO) { + type = kMediaTypeVideo; const VideoContentDescription* video_desc = media_desc->as_video(); for (const cricket::VideoCodec& codec : video_desc->codecs()) { fmt.append(" "); fmt.append(rtc::ToString(codec.id)); } } else if (media_type == cricket::MEDIA_TYPE_AUDIO) { + type = kMediaTypeAudio; const AudioContentDescription* audio_desc = media_desc->as_audio(); for (const cricket::AudioCodec& codec : audio_desc->codecs()) { fmt.append(" "); fmt.append(rtc::ToString(codec.id)); } } else if (media_type == cricket::MEDIA_TYPE_DATA) { + type = kMediaTypeData; const cricket::SctpDataContentDescription* sctp_data_desc = media_desc->as_sctp(); if (sctp_data_desc) { @@ -1388,6 +1383,12 @@ void BuildMediaDescription(const ContentInfo* content_info, fmt.append(rtc::ToString(codec.id)); } } + } else if (media_type == cricket::MEDIA_TYPE_UNSUPPORTED) { + const UnsupportedContentDescription* unsupported_desc = + media_desc->as_unsupported(); + type = unsupported_desc->media_type(); + } else { + RTC_NOTREACHED(); } // The fmt must never be empty. If no codecs are found, set the fmt attribute // to 0. @@ -2711,7 +2712,17 @@ bool ParseMediaDescription( } } else { RTC_LOG(LS_WARNING) << "Unsupported media type: " << line; - continue; + auto unsupported_desc = + std::make_unique(media_type); + if (!ParseContent(message, cricket::MEDIA_TYPE_UNSUPPORTED, mline_index, + protocol, payload_types, pos, &content_name, + &bundle_only, §ion_msid_signaling, + unsupported_desc.get(), &transport, candidates, + error)) { + return false; + } + unsupported_desc->set_protocol(protocol); + content = std::move(unsupported_desc); } if (!content.get()) { // ParseContentDescription returns NULL if failed. @@ -2739,7 +2750,9 @@ bool ParseMediaDescription( content_rejected = port_rejected; } - if (cricket::IsRtpProtocol(protocol) && !content->as_sctp()) { + if (content->as_unsupported()) { + content_rejected = true; + } else if (cricket::IsRtpProtocol(protocol) && !content->as_sctp()) { content->set_protocol(protocol); // Set the extmap. if (!session_extmaps.empty() && diff --git a/pc/webrtc_sdp_unittest.cc b/pc/webrtc_sdp_unittest.cc index 9f81129663..cf5384725b 100644 --- a/pc/webrtc_sdp_unittest.cc +++ b/pc/webrtc_sdp_unittest.cc @@ -2991,7 +2991,8 @@ TEST_F(WebRtcSdpTest, DeserializeSdpWithSctpDataChannelsButWrongMediaType) { JsepSessionDescription jdesc_output(kDummyType); EXPECT_TRUE(SdpDeserialize(sdp, &jdesc_output)); - EXPECT_EQ(0u, jdesc_output.description()->contents().size()); + EXPECT_EQ(1u, jdesc_output.description()->contents().size()); + EXPECT_TRUE(jdesc_output.description()->contents()[0].rejected); } // Helper function to set the max-message-size parameter in the @@ -4725,21 +4726,32 @@ TEST_F(WebRtcSdpTest, DeserializeSessionDescriptionWithoutCname) { } TEST_F(WebRtcSdpTest, DeserializeSdpWithUnsupportedMediaType) { - bool use_sctpmap = true; - AddSctpDataChannel(use_sctpmap); - JsepSessionDescription jdesc(kDummyType); - ASSERT_TRUE(jdesc.Initialize(desc_.Clone(), kSessionId, kSessionVersion)); - std::string sdp = kSdpSessionString; sdp += "m=bogus 9 RTP/SAVPF 0 8\r\n" - "c=IN IP4 0.0.0.0\r\n"; + "c=IN IP4 0.0.0.0\r\n" + "a=mid:bogusmid\r\n"; sdp += "m=audio/something 9 RTP/SAVPF 0 8\r\n" - "c=IN IP4 0.0.0.0\r\n"; + "c=IN IP4 0.0.0.0\r\n" + "a=mid:somethingmid\r\n"; JsepSessionDescription jdesc_output(kDummyType); EXPECT_TRUE(SdpDeserialize(sdp, &jdesc_output)); - EXPECT_EQ(0u, jdesc_output.description()->contents().size()); + ASSERT_EQ(2u, jdesc_output.description()->contents().size()); + ASSERT_NE(nullptr, jdesc_output.description() + ->contents()[0] + .media_description() + ->as_unsupported()); + ASSERT_NE(nullptr, jdesc_output.description() + ->contents()[1] + .media_description() + ->as_unsupported()); + + EXPECT_TRUE(jdesc_output.description()->contents()[0].rejected); + EXPECT_TRUE(jdesc_output.description()->contents()[1].rejected); + + EXPECT_EQ(jdesc_output.description()->contents()[0].name, "bogusmid"); + EXPECT_EQ(jdesc_output.description()->contents()[1].name, "somethingmid"); } diff --git a/sdk/objc/api/peerconnection/RTCRtpCodecParameters.mm b/sdk/objc/api/peerconnection/RTCRtpCodecParameters.mm index f61b93cce2..1dbd683e24 100644 --- a/sdk/objc/api/peerconnection/RTCRtpCodecParameters.mm +++ b/sdk/objc/api/peerconnection/RTCRtpCodecParameters.mm @@ -62,6 +62,9 @@ const NSString * const kRTCH264CodecName = @(cricket::kH264CodecName); case cricket::MEDIA_TYPE_DATA: RTC_NOTREACHED(); break; + case cricket::MEDIA_TYPE_UNSUPPORTED: + RTC_NOTREACHED(); + break; } if (nativeParameters.clock_rate) { _clockRate = [NSNumber numberWithInt:*nativeParameters.clock_rate]; diff --git a/sdk/objc/api/peerconnection/RTCRtpReceiver.h b/sdk/objc/api/peerconnection/RTCRtpReceiver.h index 7ab2cfae72..1e407fd71b 100644 --- a/sdk/objc/api/peerconnection/RTCRtpReceiver.h +++ b/sdk/objc/api/peerconnection/RTCRtpReceiver.h @@ -21,6 +21,7 @@ typedef NS_ENUM(NSInteger, RTCRtpMediaType) { RTCRtpMediaTypeAudio, RTCRtpMediaTypeVideo, RTCRtpMediaTypeData, + RTCRtpMediaTypeUnsupported, }; @class RTC_OBJC_TYPE(RTCRtpReceiver); diff --git a/sdk/objc/api/peerconnection/RTCRtpReceiver.mm b/sdk/objc/api/peerconnection/RTCRtpReceiver.mm index 3e00935694..60af86ac1b 100644 --- a/sdk/objc/api/peerconnection/RTCRtpReceiver.mm +++ b/sdk/objc/api/peerconnection/RTCRtpReceiver.mm @@ -125,6 +125,8 @@ void RtpReceiverDelegateAdapter::OnFirstPacketReceived( return RTCRtpMediaTypeVideo; case cricket::MEDIA_TYPE_DATA: return RTCRtpMediaTypeData; + case cricket::MEDIA_TYPE_UNSUPPORTED: + return RTCRtpMediaTypeUnsupported; } } @@ -136,6 +138,8 @@ void RtpReceiverDelegateAdapter::OnFirstPacketReceived( return cricket::MEDIA_TYPE_VIDEO; case RTCRtpMediaTypeData: return cricket::MEDIA_TYPE_DATA; + case RTCRtpMediaTypeUnsupported: + return cricket::MEDIA_TYPE_UNSUPPORTED; } } @@ -147,6 +151,8 @@ void RtpReceiverDelegateAdapter::OnFirstPacketReceived( return @"VIDEO"; case RTCRtpMediaTypeData: return @"DATA"; + case RTCRtpMediaTypeUnsupported: + return @"UNSUPPORTED"; } }