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 <kthelgason@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Commit-Queue: Philipp Hancke <philipp.hancke@googlemail.com>
Cr-Commit-Position: refs/heads/master@{#32410}
diff --git a/api/media_types.cc b/api/media_types.cc
index 6bc6938..c7635b5 100644
--- a/api/media_types.cc
+++ b/api/media_types.cc
@@ -26,6 +26,10 @@
return kMediaTypeVideo;
case MEDIA_TYPE_DATA:
return kMediaTypeData;
+ case MEDIA_TYPE_UNSUPPORTED:
+ // Unsupported media stores the m=<mediatype> differently.
+ RTC_NOTREACHED();
+ return "";
}
FATAL();
// Not reachable; avoids compile warning.
diff --git a/api/media_types.h b/api/media_types.h
index 8c6ba3d..b2ff08c 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 0cff84d..8c757cd 100644
--- a/pc/media_session.cc
+++ b/pc/media_session.cc
@@ -1559,6 +1559,13 @@
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 @@
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::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<UnsupportedContentDescription>(
+ 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 @@
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<TransportDescription> 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<MediaContentDescription> unsupported_answer =
+ std::make_unique<UnsupportedContentDescription>(
+ 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 @@
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 f305a62..58a31a2 100644
--- a/pc/media_session.h
+++ b/pc/media_session.h
@@ -283,6 +283,14 @@
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 @@
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 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 3565c52..926bb91 100644
--- a/pc/peer_connection_factory.cc
+++ b/pc/peer_connection_factory.cc
@@ -190,6 +190,8 @@
}
case cricket::MEDIA_TYPE_DATA:
return RtpCapabilities();
+ case cricket::MEDIA_TYPE_UNSUPPORTED:
+ return RtpCapabilities();
}
// Not reached; avoids compile warning.
FATAL();
@@ -215,6 +217,8 @@
}
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 9a89fce..605a133 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 @@
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<webrtc::SessionDescriptionInterface> 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 6d71e2ac..b0b7254 100644
--- a/pc/rtc_stats_collector_unittest.cc
+++ b/pc/rtc_stats_collector_unittest.cc
@@ -2597,6 +2597,7 @@
case cricket::MEDIA_TYPE_VIDEO:
return "Video";
case cricket::MEDIA_TYPE_DATA:
+ case cricket::MEDIA_TYPE_UNSUPPORTED:
RTC_NOTREACHED();
return "";
}
@@ -2655,6 +2656,7 @@
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 022e5e5..75ce1a0 100644
--- a/pc/sdp_offer_answer.cc
+++ b/pc/sdp_offer_answer.cc
@@ -523,6 +523,8 @@
return cricket::CN_VIDEO;
case cricket::MEDIA_TYPE_DATA:
return cricket::CN_DATA;
+ case cricket::MEDIA_TYPE_UNSUPPORTED:
+ return "not supported";
}
RTC_NOTREACHED();
return "";
@@ -2999,6 +3001,8 @@
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.");
@@ -3538,6 +3542,12 @@
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) {
@@ -3701,6 +3711,12 @@
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.
@@ -4642,6 +4658,12 @@
}
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 53c981a..52a3a1f 100644
--- a/pc/session_description.h
+++ b/pc/session_description.h
@@ -58,6 +58,7 @@
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 @@
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 @@
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 4af121d..2f9b631 100644
--- a/pc/webrtc_sdp.cc
+++ b/pc/webrtc_sdp.cc
@@ -75,6 +75,7 @@
using cricket::StreamParamsVec;
using cricket::TransportDescription;
using cricket::TransportInfo;
+using cricket::UnsupportedContentDescription;
using cricket::VideoContentDescription;
using rtc::SocketAddress;
@@ -276,9 +277,6 @@
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 @@
TransportDescription* transport,
std::vector<std::unique_ptr<JsepIceCandidate>>* 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 @@
// RFC 4566
// m=<media> <port> <proto> <fmt>
// 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 @@
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 @@
}
} else {
RTC_LOG(LS_WARNING) << "Unsupported media type: " << line;
- continue;
+ auto unsupported_desc =
+ std::make_unique<UnsupportedContentDescription>(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 @@
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 9f81129..cf53847 100644
--- a/pc/webrtc_sdp_unittest.cc
+++ b/pc/webrtc_sdp_unittest.cc
@@ -2991,7 +2991,8 @@
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, 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 f61b93c..1dbd683 100644
--- a/sdk/objc/api/peerconnection/RTCRtpCodecParameters.mm
+++ b/sdk/objc/api/peerconnection/RTCRtpCodecParameters.mm
@@ -62,6 +62,9 @@
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 7ab2cfa..1e407fd 100644
--- a/sdk/objc/api/peerconnection/RTCRtpReceiver.h
+++ b/sdk/objc/api/peerconnection/RTCRtpReceiver.h
@@ -21,6 +21,7 @@
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 3e00935..60af86a 100644
--- a/sdk/objc/api/peerconnection/RTCRtpReceiver.mm
+++ b/sdk/objc/api/peerconnection/RTCRtpReceiver.mm
@@ -125,6 +125,8 @@
return RTCRtpMediaTypeVideo;
case cricket::MEDIA_TYPE_DATA:
return RTCRtpMediaTypeData;
+ case cricket::MEDIA_TYPE_UNSUPPORTED:
+ return RTCRtpMediaTypeUnsupported;
}
}
@@ -136,6 +138,8 @@
return cricket::MEDIA_TYPE_VIDEO;
case RTCRtpMediaTypeData:
return cricket::MEDIA_TYPE_DATA;
+ case RTCRtpMediaTypeUnsupported:
+ return cricket::MEDIA_TYPE_UNSUPPORTED;
}
}
@@ -147,6 +151,8 @@
return @"VIDEO";
case RTCRtpMediaTypeData:
return @"DATA";
+ case RTCRtpMediaTypeUnsupported:
+ return @"UNSUPPORTED";
}
}