Changeset 239136 in webkit
- Timestamp:
- Dec 12, 2018 5:13:29 PM (5 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r239135 r239136 1 2018-12-12 Youenn Fablet <youenn@apple.com> 2 3 Recycling the m section should work if it was rejected remotely 4 https://bugs.webkit.org/show_bug.cgi?id=192636 5 6 Reviewed by Eric Carlson. 7 8 * webrtc/msection-recycling-expected.txt: Added. 9 * webrtc/msection-recycling.html: Added. 10 1 11 2018-12-12 Tim Horton <timothy_horton@apple.com> 2 12 -
trunk/Source/ThirdParty/libwebrtc/ChangeLog
r238996 r239136 1 2018-12-12 Youenn Fablet <youenn@apple.com> 2 3 Recycling the m section should work if it was rejected remotely 4 https://bugs.webkit.org/show_bug.cgi?id=192636 5 6 Reviewed by Eric Carlson. 7 8 Changes merged from https://webrtc.googlesource.com/src.git/+/5c72e71e14cfa76a2d1b0979d6b918abe187c208 9 10 * Source/webrtc/pc/mediasession.cc: 11 * Source/webrtc/pc/mediasession.h: 12 * Source/webrtc/pc/mediasession_unittest.cc: 13 * Source/webrtc/pc/peerconnection.cc: 14 * Source/webrtc/pc/peerconnection_jsep_unittest.cc: 15 1 16 2018-12-07 Youenn Fablet <youenn@apple.com> 2 17 -
trunk/Source/ThirdParty/libwebrtc/Source/webrtc/pc/mediasession.cc
r238967 r239136 19 19 #include <utility> 20 20 21 #include "absl/memory/memory.h" 21 22 #include "absl/strings/match.h" 22 23 #include "absl/types/optional.h" … … 290 291 291 292 // Finds all StreamParams of all media types and attach them to stream_params. 292 static void GetCurrentStreamParams(const SessionDescription* sdesc, 293 StreamParamsVec* stream_params) { 294 RTC_DCHECK(stream_params); 295 if (!sdesc) { 296 return; 297 } 298 for (const ContentInfo& content : sdesc->contents()) { 299 if (!content.media_description()) { 300 continue; 301 } 302 for (const StreamParams& params : content.media_description()->streams()) { 303 stream_params->push_back(params); 304 } 305 } 293 static StreamParamsVec GetCurrentStreamParams( 294 const std::vector<const ContentInfo*>& active_local_contents) { 295 StreamParamsVec stream_params; 296 for (const ContentInfo* content : active_local_contents) { 297 for (const StreamParams& params : content->media_description()->streams()) { 298 stream_params.push_back(params); 299 } 300 } 301 return stream_params; 306 302 } 307 303 … … 643 639 } 644 640 641 static std::vector<const ContentInfo*> GetActiveContents( 642 const SessionDescription& description, 643 const MediaSessionOptions& session_options) { 644 std::vector<const ContentInfo*> active_contents; 645 for (size_t i = 0; i < description.contents().size(); ++i) { 646 RTC_DCHECK_LT(i, session_options.media_description_options.size()); 647 const ContentInfo& content = description.contents()[i]; 648 const MediaDescriptionOptions& media_options = 649 session_options.media_description_options[i]; 650 if (!content.rejected && !media_options.stopped && 651 content.name == media_options.mid) { 652 active_contents.push_back(&content); 653 } 654 } 655 return active_contents; 656 } 657 645 658 template <class C> 646 659 static bool ContainsRtxCodec(const std::vector<C>& codecs) { … … 1266 1279 const MediaSessionOptions& session_options, 1267 1280 const SessionDescription* current_description) const { 1268 std::unique_ptr<SessionDescription> offer(new SessionDescription()); 1281 // Must have options for each existing section. 1282 if (current_description) { 1283 RTC_DCHECK_LE(current_description->contents().size(), 1284 session_options.media_description_options.size()); 1285 } 1269 1286 1270 1287 IceCredentialsIterator ice_credentials( 1271 1288 session_options.pooled_ice_credentials); 1272 StreamParamsVec current_streams; 1273 GetCurrentStreamParams(current_description, ¤t_streams); 1289 1290 std::vector<const ContentInfo*> current_active_contents; 1291 if (current_description) { 1292 current_active_contents = 1293 GetActiveContents(*current_description, session_options); 1294 } 1295 1296 StreamParamsVec current_streams = 1297 GetCurrentStreamParams(current_active_contents); 1274 1298 1275 1299 AudioCodecs offer_audio_codecs; 1276 1300 VideoCodecs offer_video_codecs; 1277 1301 DataCodecs offer_data_codecs; 1278 GetCodecsForOffer(current_ description, &offer_audio_codecs,1302 GetCodecsForOffer(current_active_contents, &offer_audio_codecs, 1279 1303 &offer_video_codecs, &offer_data_codecs); 1280 1304 … … 1288 1312 RtpHeaderExtensions audio_rtp_extensions; 1289 1313 RtpHeaderExtensions video_rtp_extensions; 1290 GetRtpHdrExtsToOffer( session_options, current_description,1314 GetRtpHdrExtsToOffer(current_active_contents, session_options.is_unified_plan, 1291 1315 &audio_rtp_extensions, &video_rtp_extensions); 1292 1316 1293 // Must have options for each existing section. 1294 if (current_description) { 1295 RTC_DCHECK(current_description->contents().size() <= 1296 session_options.media_description_options.size()); 1297 } 1317 auto offer = absl::make_unique<SessionDescription>(); 1298 1318 1299 1319 // Iterate through the media description options, matching with existing media … … 1307 1327 current_content = ¤t_description->contents()[msection_index]; 1308 1328 // Media type must match unless this media section is being recycled. 1309 RTC_DCHECK(current_content-> rejected ||1329 RTC_DCHECK(current_content->name != media_description_options.mid || 1310 1330 IsMediaContentOfType(current_content, 1311 1331 media_description_options.type)); … … 1392 1412 } 1393 1413 1414 // Must have options for exactly as many sections as in the offer. 1415 RTC_DCHECK_EQ(offer->contents().size(), 1416 session_options.media_description_options.size()); 1417 1394 1418 IceCredentialsIterator ice_credentials( 1395 1419 session_options.pooled_ice_credentials); 1396 1420 1397 // The answer contains the intersection of the codecs in the offer with the 1398 // codecs we support. As indicated by XEP-0167, we retain the same payload ids 1399 // from the offer in the answer. 1400 std::unique_ptr<SessionDescription> answer(new SessionDescription()); 1401 1402 StreamParamsVec current_streams; 1403 GetCurrentStreamParams(current_description, ¤t_streams); 1404 1405 // If the offer supports BUNDLE, and we want to use it too, create a BUNDLE 1406 // group in the answer with the appropriate content names. 1407 const ContentGroup* offer_bundle = offer->GetGroupByName(GROUP_TYPE_BUNDLE); 1408 ContentGroup answer_bundle(GROUP_TYPE_BUNDLE); 1409 // Transport info shared by the bundle group. 1410 std::unique_ptr<TransportInfo> bundle_transport; 1411 1412 answer->set_extmap_allow_mixed(offer->extmap_allow_mixed()); 1421 std::vector<const ContentInfo*> current_active_contents; 1422 if (current_description) { 1423 current_active_contents = 1424 GetActiveContents(*current_description, session_options); 1425 } 1426 1427 StreamParamsVec current_streams = 1428 GetCurrentStreamParams(current_active_contents); 1413 1429 1414 1430 // Get list of all possible codecs that respects existing payload type … … 1421 1437 VideoCodecs answer_video_codecs; 1422 1438 DataCodecs answer_data_codecs; 1423 GetCodecsForAnswer(current_ description,offer, &answer_audio_codecs,1439 GetCodecsForAnswer(current_active_contents, *offer, &answer_audio_codecs, 1424 1440 &answer_video_codecs, &answer_data_codecs); 1425 1441 … … 1431 1447 session_options.data_channel_type == DCT_SCTP); 1432 1448 1433 // Must have options for exactly as many sections as in the offer. 1434 RTC_DCHECK(offer->contents().size() == 1435 session_options.media_description_options.size()); 1449 auto answer = absl::make_unique<SessionDescription>(); 1450 1451 // If the offer supports BUNDLE, and we want to use it too, create a BUNDLE 1452 // group in the answer with the appropriate content names. 1453 const ContentGroup* offer_bundle = offer->GetGroupByName(GROUP_TYPE_BUNDLE); 1454 ContentGroup answer_bundle(GROUP_TYPE_BUNDLE); 1455 // Transport info shared by the bundle group. 1456 std::unique_ptr<TransportInfo> bundle_transport; 1457 1458 answer->set_extmap_allow_mixed(offer->extmap_allow_mixed()); 1459 1436 1460 // Iterate through the media description options, matching with existing 1437 1461 // media descriptions in |current_description|. … … 1590 1614 } 1591 1615 1592 void MergeCodecsFromDescription( const SessionDescription* description,1593 AudioCodecs* audio_codecs,1594 VideoCodecs* video_codecs,1595 DataCodecs* data_codecs,1596 UsedPayloadTypes* used_pltypes) {1597 RTC_DCHECK(description);1598 for (const ContentInfo & content : description->contents()) {1599 if (IsMediaContentOfType( &content, MEDIA_TYPE_AUDIO)) {1616 void MergeCodecsFromDescription( 1617 const std::vector<const ContentInfo*>& current_active_contents, 1618 AudioCodecs* audio_codecs, 1619 VideoCodecs* video_codecs, 1620 DataCodecs* data_codecs, 1621 UsedPayloadTypes* used_pltypes) { 1622 for (const ContentInfo* content : current_active_contents) { 1623 if (IsMediaContentOfType(content, MEDIA_TYPE_AUDIO)) { 1600 1624 const AudioContentDescription* audio = 1601 content .media_description()->as_audio();1625 content->media_description()->as_audio(); 1602 1626 MergeCodecs<AudioCodec>(audio->codecs(), audio_codecs, used_pltypes); 1603 } else if (IsMediaContentOfType( &content, MEDIA_TYPE_VIDEO)) {1627 } else if (IsMediaContentOfType(content, MEDIA_TYPE_VIDEO)) { 1604 1628 const VideoContentDescription* video = 1605 content .media_description()->as_video();1629 content->media_description()->as_video(); 1606 1630 MergeCodecs<VideoCodec>(video->codecs(), video_codecs, used_pltypes); 1607 } else if (IsMediaContentOfType( &content, MEDIA_TYPE_DATA)) {1631 } else if (IsMediaContentOfType(content, MEDIA_TYPE_DATA)) { 1608 1632 const DataContentDescription* data = 1609 content .media_description()->as_data();1633 content->media_description()->as_data(); 1610 1634 MergeCodecs<DataCodec>(data->codecs(), data_codecs, used_pltypes); 1611 1635 } … … 1620 1644 // on the directional attribute (happens in another method). 1621 1645 void MediaSessionDescriptionFactory::GetCodecsForOffer( 1622 const SessionDescription* current_description,1646 const std::vector<const ContentInfo*>& current_active_contents, 1623 1647 AudioCodecs* audio_codecs, 1624 1648 VideoCodecs* video_codecs, 1625 1649 DataCodecs* data_codecs) const { 1626 UsedPayloadTypes used_pltypes;1627 audio_codecs->clear();1628 video_codecs->clear();1629 data_codecs->clear();1630 1631 1650 // First - get all codecs from the current description if the media type 1632 1651 // is used. Add them to |used_pltypes| so the payload type is not reused if a 1633 1652 // new media type is added. 1634 if (current_description) { 1635 MergeCodecsFromDescription(current_description, audio_codecs, video_codecs, 1636 data_codecs, &used_pltypes); 1637 } 1638 1639 // Add our codecs that are not in |current_description|. 1653 UsedPayloadTypes used_pltypes; 1654 MergeCodecsFromDescription(current_active_contents, audio_codecs, 1655 video_codecs, data_codecs, &used_pltypes); 1656 1657 // Add our codecs that are not in the current description. 1640 1658 MergeCodecs<AudioCodec>(all_audio_codecs_, audio_codecs, &used_pltypes); 1641 1659 MergeCodecs<VideoCodec>(video_codecs_, video_codecs, &used_pltypes); … … 1651 1669 // on the directional attribute (happens in another method). 1652 1670 void MediaSessionDescriptionFactory::GetCodecsForAnswer( 1653 const SessionDescription* current_description,1654 const SessionDescription *remote_offer,1671 const std::vector<const ContentInfo*>& current_active_contents, 1672 const SessionDescription& remote_offer, 1655 1673 AudioCodecs* audio_codecs, 1656 1674 VideoCodecs* video_codecs, 1657 1675 DataCodecs* data_codecs) const { 1658 UsedPayloadTypes used_pltypes;1659 audio_codecs->clear();1660 video_codecs->clear();1661 data_codecs->clear();1662 1663 1676 // First - get all codecs from the current description if the media type 1664 1677 // is used. Add them to |used_pltypes| so the payload type is not reused if a 1665 1678 // new media type is added. 1666 if (current_description) { 1667 MergeCodecsFromDescription(current_description, audio_codecs, video_codecs, 1668 data_codecs, &used_pltypes); 1669 } 1679 UsedPayloadTypes used_pltypes; 1680 MergeCodecsFromDescription(current_active_contents, audio_codecs, 1681 video_codecs, data_codecs, &used_pltypes); 1670 1682 1671 1683 // Second - filter out codecs that we don't support at all and should ignore. … … 1673 1685 VideoCodecs filtered_offered_video_codecs; 1674 1686 DataCodecs filtered_offered_data_codecs; 1675 for (const ContentInfo& content : remote_offer ->contents()) {1687 for (const ContentInfo& content : remote_offer.contents()) { 1676 1688 if (IsMediaContentOfType(&content, MEDIA_TYPE_AUDIO)) { 1677 1689 const AudioContentDescription* audio = … … 1713 1725 } 1714 1726 1715 // Add codecs that are not in |current_description|but were in1727 // Add codecs that are not in the current description but were in 1716 1728 // |remote_offer|. 1717 1729 MergeCodecs<AudioCodec>(filtered_offered_audio_codecs, audio_codecs, … … 1723 1735 } 1724 1736 1737 // TODO(steveanton): Replace |is_unified_plan| flag with a member variable. 1725 1738 void MediaSessionDescriptionFactory::GetRtpHdrExtsToOffer( 1726 const MediaSessionOptions& session_options,1727 const SessionDescription* current_description,1739 const std::vector<const ContentInfo*>& current_active_contents, 1740 bool is_unified_plan, 1728 1741 RtpHeaderExtensions* offer_audio_extensions, 1729 1742 RtpHeaderExtensions* offer_video_extensions) const { … … 1733 1746 RtpHeaderExtensions all_regular_extensions; 1734 1747 RtpHeaderExtensions all_encrypted_extensions; 1735 offer_audio_extensions->clear();1736 offer_video_extensions->clear();1737 1748 1738 1749 // First - get all extensions from the current description if the media type … … 1740 1751 // Add them to |used_ids| so the local ids are not reused if a new media 1741 1752 // type is added. 1742 if (current_description) { 1743 for (const ContentInfo& content : current_description->contents()) { 1744 if (IsMediaContentOfType(&content, MEDIA_TYPE_AUDIO)) { 1745 const AudioContentDescription* audio = 1746 content.media_description()->as_audio(); 1747 MergeRtpHdrExts(audio->rtp_header_extensions(), offer_audio_extensions, 1748 &all_regular_extensions, &all_encrypted_extensions, 1749 &used_ids); 1750 } else if (IsMediaContentOfType(&content, MEDIA_TYPE_VIDEO)) { 1751 const VideoContentDescription* video = 1752 content.media_description()->as_video(); 1753 MergeRtpHdrExts(video->rtp_header_extensions(), offer_video_extensions, 1754 &all_regular_extensions, &all_encrypted_extensions, 1755 &used_ids); 1756 } 1757 } 1758 } 1759 1760 // Add our default RTP header extensions that are not in 1761 // |current_description|. 1762 MergeRtpHdrExts(audio_rtp_header_extensions(session_options.is_unified_plan), 1753 for (const ContentInfo* content : current_active_contents) { 1754 if (IsMediaContentOfType(content, MEDIA_TYPE_AUDIO)) { 1755 const AudioContentDescription* audio = 1756 content->media_description()->as_audio(); 1757 MergeRtpHdrExts(audio->rtp_header_extensions(), offer_audio_extensions, 1758 &all_regular_extensions, &all_encrypted_extensions, 1759 &used_ids); 1760 } else if (IsMediaContentOfType(content, MEDIA_TYPE_VIDEO)) { 1761 const VideoContentDescription* video = 1762 content->media_description()->as_video(); 1763 MergeRtpHdrExts(video->rtp_header_extensions(), offer_video_extensions, 1764 &all_regular_extensions, &all_encrypted_extensions, 1765 &used_ids); 1766 } 1767 } 1768 1769 // Add our default RTP header extensions that are not in the current 1770 // description. 1771 MergeRtpHdrExts(audio_rtp_header_extensions(is_unified_plan), 1763 1772 offer_audio_extensions, &all_regular_extensions, 1764 1773 &all_encrypted_extensions, &used_ids); 1765 MergeRtpHdrExts(video_rtp_header_extensions( session_options.is_unified_plan),1774 MergeRtpHdrExts(video_rtp_header_extensions(is_unified_plan), 1766 1775 offer_video_extensions, &all_regular_extensions, 1767 1776 &all_encrypted_extensions, &used_ids); … … 1769 1778 // TODO(jbauch): Support adding encrypted header extensions to existing 1770 1779 // sessions. 1771 if (enable_encrypted_rtp_header_extensions_ && !current_description) { 1780 if (enable_encrypted_rtp_header_extensions_ && 1781 current_active_contents.empty()) { 1772 1782 AddEncryptedVersionsOfHdrExts(offer_audio_extensions, 1773 1783 &all_encrypted_extensions, &used_ids); … … 1859 1869 1860 1870 AudioCodecs filtered_codecs; 1861 // Add the codecs from current content if it exists and is not being recycled. 1862 if (current_content && !current_content->rejected) { 1871 // Add the codecs from current content if it exists and is not rejected nor 1872 // recycled. 1873 if (current_content && !current_content->rejected && 1874 current_content->name == media_description_options.mid) { 1863 1875 RTC_CHECK(IsMediaContentOfType(current_content, MEDIA_TYPE_AUDIO)); 1864 1876 const AudioContentDescription* acd = … … 1935 1947 1936 1948 VideoCodecs filtered_codecs; 1937 // Add the codecs from current content if it exists and is not being recycled. 1938 if (current_content && !current_content->rejected) { 1949 // Add the codecs from current content if it exists and is not rejected nor 1950 // recycled. 1951 if (current_content && !current_content->rejected && 1952 current_content->name == media_description_options.mid) { 1939 1953 RTC_CHECK(IsMediaContentOfType(current_content, MEDIA_TYPE_VIDEO)); 1940 1954 const VideoContentDescription* vcd = … … 2098 2112 2099 2113 AudioCodecs filtered_codecs; 2100 // Add the codecs from current content if it exists and is not being recycled. 2101 if (current_content && !current_content->rejected) { 2114 // Add the codecs from current content if it exists and is not rejected nor 2115 // recycled. 2116 if (current_content && !current_content->rejected && 2117 current_content->name == media_description_options.mid) { 2102 2118 RTC_CHECK(IsMediaContentOfType(current_content, MEDIA_TYPE_AUDIO)); 2103 2119 const AudioContentDescription* acd = … … 2184 2200 2185 2201 VideoCodecs filtered_codecs; 2186 // Add the codecs from current content if it exists and is not being recycled. 2187 if (current_content && !current_content->rejected) { 2202 // Add the codecs from current content if it exists and is not rejected nor 2203 // recycled. 2204 if (current_content && !current_content->rejected && 2205 current_content->name == media_description_options.mid) { 2188 2206 RTC_CHECK(IsMediaContentOfType(current_content, MEDIA_TYPE_VIDEO)); 2189 2207 const VideoContentDescription* vcd = -
trunk/Source/ThirdParty/libwebrtc/Source/webrtc/pc/mediasession.h
r238967 r239136 174 174 const webrtc::RtpTransceiverDirection& offer, 175 175 const webrtc::RtpTransceiverDirection& answer) const; 176 void GetCodecsForOffer(const SessionDescription* current_description, 177 AudioCodecs* audio_codecs, 178 VideoCodecs* video_codecs, 179 DataCodecs* data_codecs) const; 180 void GetCodecsForAnswer(const SessionDescription* current_description, 181 const SessionDescription* remote_offer, 182 AudioCodecs* audio_codecs, 183 VideoCodecs* video_codecs, 184 DataCodecs* data_codecs) const; 185 void GetRtpHdrExtsToOffer(const MediaSessionOptions& session_options, 186 const SessionDescription* current_description, 187 RtpHeaderExtensions* audio_extensions, 188 RtpHeaderExtensions* video_extensions) const; 176 void GetCodecsForOffer( 177 const std::vector<const ContentInfo*>& current_active_contents, 178 AudioCodecs* audio_codecs, 179 VideoCodecs* video_codecs, 180 DataCodecs* data_codecs) const; 181 void GetCodecsForAnswer( 182 const std::vector<const ContentInfo*>& current_active_contents, 183 const SessionDescription& remote_offer, 184 AudioCodecs* audio_codecs, 185 VideoCodecs* video_codecs, 186 DataCodecs* data_codecs) const; 187 void GetRtpHdrExtsToOffer( 188 const std::vector<const ContentInfo*>& current_active_contents, 189 bool is_unified_plan, 190 RtpHeaderExtensions* audio_extensions, 191 RtpHeaderExtensions* video_extensions) const; 189 192 bool AddTransportOffer(const std::string& content_name, 190 193 const TransportOptions& transport_options, -
trunk/Source/ThirdParty/libwebrtc/Source/webrtc/pc/mediasession_unittest.cc
r238967 r239136 2021 2021 } 2022 2022 2023 // Test that a reoffer does not reuse audio codecs from a previous media section 2024 // that is being recycled. 2025 TEST_F(MediaSessionDescriptionFactoryTest, 2026 ReOfferDoesNotReUseRecycledAudioCodecs) { 2027 f1_.set_video_codecs({}); 2028 f2_.set_video_codecs({}); 2029 2030 MediaSessionOptions opts; 2031 AddMediaSection(MEDIA_TYPE_AUDIO, "a0", RtpTransceiverDirection::kSendRecv, 2032 kActive, &opts); 2033 auto offer = absl::WrapUnique(f1_.CreateOffer(opts, nullptr)); 2034 auto answer = absl::WrapUnique(f2_.CreateAnswer(offer.get(), opts, nullptr)); 2035 2036 // Recycle the media section by changing its mid. 2037 opts.media_description_options[0].mid = "a1"; 2038 auto reoffer = absl::WrapUnique(f2_.CreateOffer(opts, answer.get())); 2039 2040 // Expect that the results of the first negotiation are ignored. If the m= 2041 // section was not recycled the payload types would match the initial offerer. 2042 const AudioContentDescription* acd = 2043 GetFirstAudioContentDescription(reoffer.get()); 2044 EXPECT_THAT(acd->codecs(), ElementsAreArray(kAudioCodecs2)); 2045 } 2046 2047 // Test that a reoffer does not reuse video codecs from a previous media section 2048 // that is being recycled. 2049 TEST_F(MediaSessionDescriptionFactoryTest, 2050 ReOfferDoesNotReUseRecycledVideoCodecs) { 2051 f1_.set_audio_codecs({}, {}); 2052 f2_.set_audio_codecs({}, {}); 2053 2054 MediaSessionOptions opts; 2055 AddMediaSection(MEDIA_TYPE_VIDEO, "v0", RtpTransceiverDirection::kSendRecv, 2056 kActive, &opts); 2057 auto offer = absl::WrapUnique(f1_.CreateOffer(opts, nullptr)); 2058 auto answer = absl::WrapUnique(f2_.CreateAnswer(offer.get(), opts, nullptr)); 2059 2060 // Recycle the media section by changing its mid. 2061 opts.media_description_options[0].mid = "v1"; 2062 auto reoffer = absl::WrapUnique(f2_.CreateOffer(opts, answer.get())); 2063 2064 // Expect that the results of the first negotiation are ignored. If the m= 2065 // section was not recycled the payload types would match the initial offerer. 2066 const VideoContentDescription* vcd = 2067 GetFirstVideoContentDescription(reoffer.get()); 2068 EXPECT_THAT(vcd->codecs(), ElementsAreArray(kVideoCodecs2)); 2069 } 2070 2071 // Test that a reanswer does not reuse audio codecs from a previous media 2072 // section that is being recycled. 2073 TEST_F(MediaSessionDescriptionFactoryTest, 2074 ReAnswerDoesNotReUseRecycledAudioCodecs) { 2075 f1_.set_video_codecs({}); 2076 f2_.set_video_codecs({}); 2077 2078 // Perform initial offer/answer in reverse (|f2_| as offerer) so that the 2079 // second offer/answer is forward (|f1_| as offerer). 2080 MediaSessionOptions opts; 2081 AddMediaSection(MEDIA_TYPE_AUDIO, "a0", RtpTransceiverDirection::kSendRecv, 2082 kActive, &opts); 2083 auto offer = absl::WrapUnique(f2_.CreateOffer(opts, nullptr)); 2084 auto answer = absl::WrapUnique(f1_.CreateAnswer(offer.get(), opts, nullptr)); 2085 2086 // Recycle the media section by changing its mid. 2087 opts.media_description_options[0].mid = "a1"; 2088 auto reoffer = absl::WrapUnique(f1_.CreateOffer(opts, answer.get())); 2089 auto reanswer = 2090 absl::WrapUnique(f2_.CreateAnswer(reoffer.get(), opts, offer.get())); 2091 2092 // Expect that the results of the first negotiation are ignored. If the m= 2093 // section was not recycled the payload types would match the initial offerer. 2094 const AudioContentDescription* acd = 2095 GetFirstAudioContentDescription(reanswer.get()); 2096 EXPECT_THAT(acd->codecs(), ElementsAreArray(kAudioCodecsAnswer)); 2097 } 2098 2099 // Test that a reanswer does not reuse video codecs from a previous media 2100 // section that is being recycled. 2101 TEST_F(MediaSessionDescriptionFactoryTest, 2102 ReAnswerDoesNotReUseRecycledVideoCodecs) { 2103 f1_.set_audio_codecs({}, {}); 2104 f2_.set_audio_codecs({}, {}); 2105 2106 // Perform initial offer/answer in reverse (|f2_| as offerer) so that the 2107 // second offer/answer is forward (|f1_| as offerer). 2108 MediaSessionOptions opts; 2109 AddMediaSection(MEDIA_TYPE_VIDEO, "v0", RtpTransceiverDirection::kSendRecv, 2110 kActive, &opts); 2111 auto offer = absl::WrapUnique(f2_.CreateOffer(opts, nullptr)); 2112 auto answer = absl::WrapUnique(f1_.CreateAnswer(offer.get(), opts, nullptr)); 2113 2114 // Recycle the media section by changing its mid. 2115 opts.media_description_options[0].mid = "v1"; 2116 auto reoffer = absl::WrapUnique(f1_.CreateOffer(opts, answer.get())); 2117 auto reanswer = 2118 absl::WrapUnique(f2_.CreateAnswer(reoffer.get(), opts, offer.get())); 2119 2120 // Expect that the results of the first negotiation are ignored. If the m= 2121 // section was not recycled the payload types would match the initial offerer. 2122 const VideoContentDescription* vcd = 2123 GetFirstVideoContentDescription(reanswer.get()); 2124 EXPECT_THAT(vcd->codecs(), ElementsAreArray(kVideoCodecsAnswer)); 2125 } 2126 2023 2127 // Create an updated offer after creating an answer to the original offer and 2024 2128 // verify that the codecs that were part of the original answer are not changed -
trunk/Source/ThirdParty/libwebrtc/Source/webrtc/pc/peerconnection.cc
r238996 r239136 3955 3955 } 3956 3956 3957 // Returns the ContentInfo at mline index |i|, or null if none exists. 3958 static const ContentInfo* GetContentByIndex( 3959 const SessionDescriptionInterface* sdesc, 3960 size_t i) { 3961 if (!sdesc) { 3962 return nullptr; 3963 } 3964 const ContentInfos& contents = sdesc->description()->contents(); 3965 return (i < contents.size() ? &contents[i] : nullptr); 3966 } 3967 3957 3968 void PeerConnection::GetOptionsForUnifiedPlanOffer( 3958 3969 const RTCOfferAnswerOptions& offer_answer_options, … … 3982 3993 const ContentInfo* local_content = 3983 3994 (i < local_contents.size() ? &local_contents[i] : nullptr); 3995 const ContentInfo* current_local_content = 3996 GetContentByIndex(current_local_description(), i); 3984 3997 const ContentInfo* remote_content = 3985 3998 (i < remote_contents.size() ? &remote_contents[i] : nullptr); 3986 bool had_been_rejected = (local_content && local_content->rejected) || 3987 (remote_content && remote_content->rejected); 3999 const ContentInfo* current_remote_content = 4000 GetContentByIndex(current_remote_description(), i); 4001 bool had_been_rejected = 4002 (current_local_content && current_local_content->rejected) || 4003 (current_remote_content && current_remote_content->rejected); 3988 4004 const std::string& mid = 3989 4005 (local_content ? local_content->name : remote_content->name); … … 3996 4012 RTC_CHECK(transceiver); 3997 4013 // A media section is considered eligible for recycling if it is marked as 3998 // rejected in either the local orremote description.4014 // rejected in either the current local or current remote description. 3999 4015 if (had_been_rejected && transceiver->stopped()) { 4000 4016 session_options->media_description_options.push_back( … … 4188 4204 cricket::MediaDescriptionOptions( 4189 4205 cricket::MEDIA_TYPE_AUDIO, content.name, 4190 RtpTransceiverDirection::kInactive, true));4206 RtpTransceiverDirection::kInactive, /*stopped=*/true)); 4191 4207 } else { 4208 bool stopped = (audio_direction == RtpTransceiverDirection::kInactive); 4192 4209 session_options->media_description_options.push_back( 4193 cricket::MediaDescriptionOptions( 4194 cricket::MEDIA_TYPE_AUDIO,content.name, audio_direction,4195 audio_direction == RtpTransceiverDirection::kInactive));4210 cricket::MediaDescriptionOptions(cricket::MEDIA_TYPE_AUDIO, 4211 content.name, audio_direction, 4212 stopped)); 4196 4213 *audio_index = session_options->media_description_options.size() - 1; 4197 4214 } … … 4202 4219 cricket::MediaDescriptionOptions( 4203 4220 cricket::MEDIA_TYPE_VIDEO, content.name, 4204 RtpTransceiverDirection::kInactive, true));4221 RtpTransceiverDirection::kInactive, /*stopped=*/true)); 4205 4222 } else { 4223 bool stopped = (video_direction == RtpTransceiverDirection::kInactive); 4206 4224 session_options->media_description_options.push_back( 4207 cricket::MediaDescriptionOptions( 4208 cricket::MEDIA_TYPE_VIDEO,content.name, video_direction,4209 video_direction == RtpTransceiverDirection::kInactive));4225 cricket::MediaDescriptionOptions(cricket::MEDIA_TYPE_VIDEO, 4226 content.name, video_direction, 4227 stopped)); 4210 4228 *video_index = session_options->media_description_options.size() - 1; 4211 4229 } -
trunk/Source/ThirdParty/libwebrtc/Source/webrtc/pc/peerconnection_jsep_unittest.cc
r238967 r239136 701 701 // side are generated/updated correctly when recycling an audio/video media 702 702 // section as a media section of either the same or opposite type. 703 // Correct recycling works as follows: 704 // - The m= section is re-offered with a new MID value and the new media type. 705 // - The previously-associated transceiver is dissociated when the new offer is 706 // set as a local description on the offerer or as a remote description on 707 // the answerer. 708 // - The new transceiver is associated with the new MID value. 703 709 class RecycleMediaSectionTest 704 710 : public PeerConnectionJsepTest, … … 715 721 }; 716 722 717 TEST_P(RecycleMediaSectionTest, VerifyOfferAnswerAndTransceivers) { 723 // Test that recycling works properly when a new transceiver recycles an m= 724 // section that was rejected in both the current local and remote descriptions. 725 TEST_P(RecycleMediaSectionTest, CurrentLocalAndCurrentRemoteRejected) { 718 726 auto caller = CreatePeerConnection(); 719 727 auto first_transceiver = caller->AddTransceiver(first_type_); … … 773 781 ASSERT_EQ(2u, caller->pc()->GetTransceivers().size()); 774 782 ASSERT_EQ(2u, callee->pc()->GetTransceivers().size()); 783 } 784 785 // Test that recycling works properly when a new transceiver recycles an m= 786 // section that was rejected in only the current remote description. 787 TEST_P(RecycleMediaSectionTest, CurrentRemoteOnlyRejected) { 788 auto caller = CreatePeerConnection(); 789 auto caller_first_transceiver = caller->AddTransceiver(first_type_); 790 auto callee = CreatePeerConnection(); 791 792 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal())); 793 794 std::string first_mid = *caller_first_transceiver->mid(); 795 ASSERT_EQ(1u, callee->pc()->GetTransceivers().size()); 796 auto callee_first_transceiver = callee->pc()->GetTransceivers()[0]; 797 callee_first_transceiver->Stop(); 798 799 // The answer will have a rejected m= section. 800 ASSERT_TRUE( 801 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal())); 802 803 // The offer should reuse the previous media section but allocate a new MID 804 // and change the media type. 805 auto caller_second_transceiver = caller->AddTransceiver(second_type_); 806 auto offer = caller->CreateOffer(); 807 const auto& offer_contents = offer->description()->contents(); 808 ASSERT_EQ(1u, offer_contents.size()); 809 EXPECT_FALSE(offer_contents[0].rejected); 810 EXPECT_EQ(second_type_, offer_contents[0].media_description()->type()); 811 std::string second_mid = offer_contents[0].name; 812 EXPECT_NE(first_mid, second_mid); 813 814 // Setting the local offer will dissociate the previous transceiver and set 815 // the MID for the new transceiver. 816 ASSERT_TRUE( 817 caller->SetLocalDescription(CloneSessionDescription(offer.get()))); 818 EXPECT_EQ(absl::nullopt, caller_first_transceiver->mid()); 819 EXPECT_EQ(second_mid, caller_second_transceiver->mid()); 820 821 // Setting the remote offer will dissociate the previous transceiver and 822 // create a new transceiver for the media section. 823 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer))); 824 auto callee_transceivers = callee->pc()->GetTransceivers(); 825 ASSERT_EQ(2u, callee_transceivers.size()); 826 EXPECT_EQ(absl::nullopt, callee_transceivers[0]->mid()); 827 EXPECT_EQ(first_type_, callee_transceivers[0]->media_type()); 828 EXPECT_EQ(second_mid, callee_transceivers[1]->mid()); 829 EXPECT_EQ(second_type_, callee_transceivers[1]->media_type()); 830 831 // The answer should have only one media section for the new transceiver. 832 auto answer = callee->CreateAnswer(); 833 auto answer_contents = answer->description()->contents(); 834 ASSERT_EQ(1u, answer_contents.size()); 835 EXPECT_FALSE(answer_contents[0].rejected); 836 EXPECT_EQ(second_mid, answer_contents[0].name); 837 EXPECT_EQ(second_type_, answer_contents[0].media_description()->type()); 838 839 // Setting the local answer should succeed. 840 ASSERT_TRUE( 841 callee->SetLocalDescription(CloneSessionDescription(answer.get()))); 842 843 // Setting the remote answer should succeed and not create any new 844 // transceivers. 845 ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer))); 846 ASSERT_EQ(2u, caller->pc()->GetTransceivers().size()); 847 ASSERT_EQ(2u, callee->pc()->GetTransceivers().size()); 848 } 849 850 // Test that recycling works properly when a new transceiver recycles an m= 851 // section that was rejected only in the current local description. 852 TEST_P(RecycleMediaSectionTest, CurrentLocalOnlyRejected) { 853 auto caller = CreatePeerConnection(); 854 auto caller_first_transceiver = caller->AddTransceiver(first_type_); 855 auto callee = CreatePeerConnection(); 856 857 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal())); 858 859 std::string first_mid = *caller_first_transceiver->mid(); 860 ASSERT_EQ(1u, callee->pc()->GetTransceivers().size()); 861 auto callee_first_transceiver = callee->pc()->GetTransceivers()[0]; 862 callee_first_transceiver->Stop(); 863 864 // The answer will have a rejected m= section. 865 ASSERT_TRUE( 866 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal())); 867 868 // The offer should reuse the previous media section but allocate a new MID 869 // and change the media type. 870 auto callee_second_transceiver = callee->AddTransceiver(second_type_); 871 auto offer = callee->CreateOffer(); 872 const auto& offer_contents = offer->description()->contents(); 873 ASSERT_EQ(1u, offer_contents.size()); 874 EXPECT_FALSE(offer_contents[0].rejected); 875 EXPECT_EQ(second_type_, offer_contents[0].media_description()->type()); 876 std::string second_mid = offer_contents[0].name; 877 EXPECT_NE(first_mid, second_mid); 878 879 // Setting the local offer will dissociate the previous transceiver and set 880 // the MID for the new transceiver. 881 ASSERT_TRUE( 882 callee->SetLocalDescription(CloneSessionDescription(offer.get()))); 883 EXPECT_EQ(absl::nullopt, callee_first_transceiver->mid()); 884 EXPECT_EQ(second_mid, callee_second_transceiver->mid()); 885 886 // Setting the remote offer will dissociate the previous transceiver and 887 // create a new transceiver for the media section. 888 ASSERT_TRUE(caller->SetRemoteDescription(std::move(offer))); 889 auto caller_transceivers = caller->pc()->GetTransceivers(); 890 ASSERT_EQ(2u, caller_transceivers.size()); 891 EXPECT_EQ(absl::nullopt, caller_transceivers[0]->mid()); 892 EXPECT_EQ(first_type_, caller_transceivers[0]->media_type()); 893 EXPECT_EQ(second_mid, caller_transceivers[1]->mid()); 894 EXPECT_EQ(second_type_, caller_transceivers[1]->media_type()); 895 896 // The answer should have only one media section for the new transceiver. 897 auto answer = caller->CreateAnswer(); 898 auto answer_contents = answer->description()->contents(); 899 ASSERT_EQ(1u, answer_contents.size()); 900 EXPECT_FALSE(answer_contents[0].rejected); 901 EXPECT_EQ(second_mid, answer_contents[0].name); 902 EXPECT_EQ(second_type_, answer_contents[0].media_description()->type()); 903 904 // Setting the local answer should succeed. 905 ASSERT_TRUE( 906 caller->SetLocalDescription(CloneSessionDescription(answer.get()))); 907 908 // Setting the remote answer should succeed and not create any new 909 // transceivers. 910 ASSERT_TRUE(callee->SetRemoteDescription(std::move(answer))); 911 ASSERT_EQ(2u, callee->pc()->GetTransceivers().size()); 912 ASSERT_EQ(2u, caller->pc()->GetTransceivers().size()); 913 } 914 915 // Test that a m= section is *not* recycled if the media section is only 916 // rejected in the pending local description and there is no current remote 917 // description. 918 TEST_P(RecycleMediaSectionTest, PendingLocalRejectedAndNoRemote) { 919 auto caller = CreatePeerConnection(); 920 auto caller_first_transceiver = caller->AddTransceiver(first_type_); 921 922 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer())); 923 924 std::string first_mid = *caller_first_transceiver->mid(); 925 caller_first_transceiver->Stop(); 926 927 // The reoffer will have a rejected m= section. 928 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer())); 929 930 auto caller_second_transceiver = caller->AddTransceiver(second_type_); 931 932 // The reoffer should not recycle the existing m= section since it is not 933 // rejected in either the *current* local or *current* remote description. 934 auto reoffer = caller->CreateOffer(); 935 auto reoffer_contents = reoffer->description()->contents(); 936 ASSERT_EQ(2u, reoffer_contents.size()); 937 EXPECT_TRUE(reoffer_contents[0].rejected); 938 EXPECT_EQ(first_type_, reoffer_contents[0].media_description()->type()); 939 EXPECT_EQ(first_mid, reoffer_contents[0].name); 940 EXPECT_FALSE(reoffer_contents[1].rejected); 941 EXPECT_EQ(second_type_, reoffer_contents[1].media_description()->type()); 942 std::string second_mid = reoffer_contents[1].name; 943 EXPECT_NE(first_mid, second_mid); 944 945 ASSERT_TRUE(caller->SetLocalDescription(std::move(reoffer))); 946 947 // Both RtpTransceivers are associated. 948 EXPECT_EQ(first_mid, caller_first_transceiver->mid()); 949 EXPECT_EQ(second_mid, caller_second_transceiver->mid()); 950 } 951 952 // Test that a m= section is *not* recycled if the media section is only 953 // rejected in the pending local description and not rejected in the current 954 // remote description. 955 TEST_P(RecycleMediaSectionTest, PendingLocalRejectedAndNotRejectedRemote) { 956 auto caller = CreatePeerConnection(); 957 auto caller_first_transceiver = caller->AddTransceiver(first_type_); 958 auto callee = CreatePeerConnection(); 959 960 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get())); 961 962 std::string first_mid = *caller_first_transceiver->mid(); 963 caller_first_transceiver->Stop(); 964 965 // The reoffer will have a rejected m= section. 966 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer())); 967 968 auto caller_second_transceiver = caller->AddTransceiver(second_type_); 969 970 // The reoffer should not recycle the existing m= section since it is not 971 // rejected in either the *current* local or *current* remote description. 972 auto reoffer = caller->CreateOffer(); 973 auto reoffer_contents = reoffer->description()->contents(); 974 ASSERT_EQ(2u, reoffer_contents.size()); 975 EXPECT_TRUE(reoffer_contents[0].rejected); 976 EXPECT_EQ(first_type_, reoffer_contents[0].media_description()->type()); 977 EXPECT_EQ(first_mid, reoffer_contents[0].name); 978 EXPECT_FALSE(reoffer_contents[1].rejected); 979 EXPECT_EQ(second_type_, reoffer_contents[1].media_description()->type()); 980 std::string second_mid = reoffer_contents[1].name; 981 EXPECT_NE(first_mid, second_mid); 982 983 ASSERT_TRUE(caller->SetLocalDescription(std::move(reoffer))); 984 985 // Both RtpTransceivers are associated. 986 EXPECT_EQ(first_mid, caller_first_transceiver->mid()); 987 EXPECT_EQ(second_mid, caller_second_transceiver->mid()); 988 } 989 990 // Test that an m= section is *not* recycled if the media section is only 991 // rejected in the pending remote description and there is no current local 992 // description. 993 TEST_P(RecycleMediaSectionTest, PendingRemoteRejectedAndNoLocal) { 994 auto caller = CreatePeerConnection(); 995 auto caller_first_transceiver = caller->AddTransceiver(first_type_); 996 auto callee = CreatePeerConnection(); 997 998 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal())); 999 1000 ASSERT_EQ(1u, callee->pc()->GetTransceivers().size()); 1001 auto callee_first_transceiver = callee->pc()->GetTransceivers()[0]; 1002 std::string first_mid = *callee_first_transceiver->mid(); 1003 caller_first_transceiver->Stop(); 1004 1005 // The reoffer will have a rejected m= section. 1006 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal())); 1007 1008 auto callee_second_transceiver = callee->AddTransceiver(second_type_); 1009 1010 // The reoffer should not recycle the existing m= section since it is not 1011 // rejected in either the *current* local or *current* remote description. 1012 auto reoffer = callee->CreateOffer(); 1013 auto reoffer_contents = reoffer->description()->contents(); 1014 ASSERT_EQ(2u, reoffer_contents.size()); 1015 EXPECT_TRUE(reoffer_contents[0].rejected); 1016 EXPECT_EQ(first_type_, reoffer_contents[0].media_description()->type()); 1017 EXPECT_EQ(first_mid, reoffer_contents[0].name); 1018 EXPECT_FALSE(reoffer_contents[1].rejected); 1019 EXPECT_EQ(second_type_, reoffer_contents[1].media_description()->type()); 1020 std::string second_mid = reoffer_contents[1].name; 1021 EXPECT_NE(first_mid, second_mid); 1022 1023 // Note: Cannot actually set the reoffer since the callee is in the signaling 1024 // state 'have-remote-offer'. 1025 } 1026 1027 // Test that an m= section is *not* recycled if the media section is only 1028 // rejected in the pending remote description and not rejected in the current 1029 // local description. 1030 TEST_P(RecycleMediaSectionTest, PendingRemoteRejectedAndNotRejectedLocal) { 1031 auto caller = CreatePeerConnection(); 1032 auto caller_first_transceiver = caller->AddTransceiver(first_type_); 1033 auto callee = CreatePeerConnection(); 1034 1035 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get())); 1036 1037 ASSERT_EQ(1u, callee->pc()->GetTransceivers().size()); 1038 auto callee_first_transceiver = callee->pc()->GetTransceivers()[0]; 1039 std::string first_mid = *callee_first_transceiver->mid(); 1040 caller_first_transceiver->Stop(); 1041 1042 // The reoffer will have a rejected m= section. 1043 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal())); 1044 1045 auto callee_second_transceiver = callee->AddTransceiver(second_type_); 1046 1047 // The reoffer should not recycle the existing m= section since it is not 1048 // rejected in either the *current* local or *current* remote description. 1049 auto reoffer = callee->CreateOffer(); 1050 auto reoffer_contents = reoffer->description()->contents(); 1051 ASSERT_EQ(2u, reoffer_contents.size()); 1052 EXPECT_TRUE(reoffer_contents[0].rejected); 1053 EXPECT_EQ(first_type_, reoffer_contents[0].media_description()->type()); 1054 EXPECT_EQ(first_mid, reoffer_contents[0].name); 1055 EXPECT_FALSE(reoffer_contents[1].rejected); 1056 EXPECT_EQ(second_type_, reoffer_contents[1].media_description()->type()); 1057 std::string second_mid = reoffer_contents[1].name; 1058 EXPECT_NE(first_mid, second_mid); 1059 1060 // Note: Cannot actually set the reoffer since the callee is in the signaling 1061 // state 'have-remote-offer'. 775 1062 } 776 1063
Note: See TracChangeset
for help on using the changeset viewer.